Changeset 747ef72 in mainline for uspace/drv/bus/usb/usbhid/usbhid.c
- Timestamp:
- 2011-11-10T11:29:10Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 54464f6a, c2245a3, c6f189f7
- Parents:
- 2e1b9dc (diff), 2d1ba51 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/usbhid/usbhid.c
r2e1b9dc r747ef72 51 51 #include "subdrivers.h" 52 52 53 /*----------------------------------------------------------------------------*/54 55 53 /* Array of endpoints expected on the device, NULL terminated. */ 56 54 const usb_endpoint_description_t *usb_hid_endpoints[] = { … … 60 58 NULL 61 59 }; 62 63 /*----------------------------------------------------------------------------*/ 64 60 /*----------------------------------------------------------------------------*/ 65 61 static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev) 66 62 { … … 78 74 return EOK; 79 75 } 80 81 /*----------------------------------------------------------------------------*/ 82 76 /*----------------------------------------------------------------------------*/ 83 77 static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev) 84 78 { … … 92 86 hid_dev->subdriver_count = 1; 93 87 // TODO 2 should be mouse, but find a better way 94 hid_dev->subdrivers[ 2] = usb_hid_subdrivers[0].subdriver;88 hid_dev->subdrivers[0] = usb_hid_subdrivers[2].subdriver; 95 89 96 90 return EOK; 97 91 } 98 99 /*----------------------------------------------------------------------------*/ 100 92 /*----------------------------------------------------------------------------*/ 101 93 static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev) 102 94 { 103 assert(hid_dev != NULL && hid_dev->subdriver_count == 0); 95 assert(hid_dev != NULL); 96 assert(hid_dev->subdriver_count == 0); 104 97 105 98 hid_dev->subdrivers = malloc(sizeof(usb_hid_subdriver_t)); … … 117 110 return EOK; 118 111 } 119 120 /*----------------------------------------------------------------------------*/ 121 112 /*----------------------------------------------------------------------------*/ 122 113 static bool usb_hid_ids_match(const usb_hid_dev_t *hid_dev, 123 114 const usb_hid_subdriver_mapping_t *mapping) … … 128 119 return (hid_dev->usb_dev->descriptors.device.vendor_id 129 120 == mapping->vendor_id 130 && hid_dev->usb_dev->descriptors.device.product_id 121 && hid_dev->usb_dev->descriptors.device.product_id 131 122 == mapping->product_id); 132 123 } 133 134 /*----------------------------------------------------------------------------*/ 135 124 /*----------------------------------------------------------------------------*/ 136 125 static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev, 137 126 const usb_hid_subdriver_mapping_t *mapping) … … 145 134 return false; 146 135 } 147 int i = 0; 148 while (mapping->usage_path[i].usage != 0149 || mapping->usage_path[i].usage_page != 0 ) {136 137 for (int i = 0; mapping->usage_path[i].usage != 0 138 || mapping->usage_path[i].usage_page != 0; ++i) { 150 139 if (usb_hid_report_path_append_item(usage_path, 151 140 mapping->usage_path[i].usage_page, … … 155 144 return false; 156 145 } 157 ++i;158 146 } 159 147 … … 165 153 do { 166 154 usb_log_debug("Trying report id %u\n", report_id); 167 168 155 if (report_id != 0) { 169 156 usb_hid_report_path_set_report_id(usage_path, … … 171 158 } 172 159 173 usb_hid_report_field_t *field = usb_hid_report_get_sibling( 174 &hid_dev->report, NULL, usage_path, mapping->compare, 175 USB_HID_REPORT_TYPE_INPUT); 160 const usb_hid_report_field_t *field = 161 usb_hid_report_get_sibling( 162 &hid_dev->report, NULL, usage_path, mapping->compare, 163 USB_HID_REPORT_TYPE_INPUT); 176 164 177 165 usb_log_debug("Field: %p\n", field); … … 190 178 return matches; 191 179 } 192 193 /*----------------------------------------------------------------------------*/ 194 180 /*----------------------------------------------------------------------------*/ 195 181 static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev, 196 const usb_hid_subdriver_t **subdrivers, int count) 197 { 198 int i; 199 200 if (count <= 0) { 182 const usb_hid_subdriver_t **subdrivers, unsigned count) 183 { 184 assert(hid_dev); 185 assert(subdrivers); 186 187 if (count == 0) { 201 188 hid_dev->subdriver_count = 0; 202 189 hid_dev->subdrivers = NULL; … … 210 197 } 211 198 212 for (i = 0; i < count; ++i) { 213 hid_dev->subdrivers[i].init = subdrivers[i]->init; 214 hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit; 215 hid_dev->subdrivers[i].poll = subdrivers[i]->poll; 216 hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end; 199 for (unsigned i = 0; i < count; ++i) { 200 hid_dev->subdrivers[i] = *subdrivers[i]; 217 201 } 218 202 … … 227 211 return EOK; 228 212 } 229 230 /*----------------------------------------------------------------------------*/ 231 213 /*----------------------------------------------------------------------------*/ 232 214 static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev) 233 215 { … … 235 217 236 218 const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS]; 237 238 int i = 0, count = 0; 239 const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i]; 240 241 bool ids_matched; 242 bool matched; 243 244 while (count < USB_HID_MAX_SUBDRIVERS && 245 (mapping->usage_path != NULL 246 || mapping->vendor_id >= 0 || mapping->product_id >= 0)) { 247 // check the vendor & product ID 219 unsigned count = 0; 220 221 for (unsigned i = 0; i < USB_HID_MAX_SUBDRIVERS; ++i) { 222 const usb_hid_subdriver_mapping_t *mapping = 223 &usb_hid_subdrivers[i]; 224 /* Check the vendor & product ID. */ 248 225 if (mapping->vendor_id >= 0 && mapping->product_id < 0) { 249 usb_log_warning("Missing Product ID for Vendor ID %d\n", 250 mapping->vendor_id); 251 return EINVAL; 226 usb_log_warning("Mapping[%d]: Missing Product ID for " 227 "Vendor ID %d\n", i, mapping->vendor_id); 252 228 } 253 229 if (mapping->product_id >= 0 && mapping->vendor_id < 0) { 254 usb_log_warning("Missing Vendor ID for Product ID %d\n", 255 mapping->product_id); 256 return EINVAL; 257 } 258 259 ids_matched = false; 260 matched = false; 261 262 if (mapping->vendor_id >= 0) { 263 assert(mapping->product_id >= 0); 230 usb_log_warning("Mapping[%d]: Missing Vendor ID for " 231 "Product ID %d\n", i, mapping->product_id); 232 } 233 234 bool matched = false; 235 236 /* Check ID match. */ 237 if (mapping->vendor_id >= 0 && mapping->product_id >= 0) { 264 238 usb_log_debug("Comparing device against vendor ID %u" 265 239 " and product ID %u.\n", mapping->vendor_id, … … 267 241 if (usb_hid_ids_match(hid_dev, mapping)) { 268 242 usb_log_debug("IDs matched.\n"); 269 ids_matched = true;243 matched = true; 270 244 } 271 245 } 272 246 247 /* Check usage match. */ 273 248 if (mapping->usage_path != NULL) { 274 249 usb_log_debug("Comparing device against usage path.\n"); 275 250 if (usb_hid_path_matches(hid_dev, mapping)) { 276 / / does not matter if IDs were matched251 /* Does not matter if IDs were matched. */ 277 252 matched = true; 278 253 } 279 } else {280 // matched only if IDs were matched and there is no path281 matched = ids_matched;282 254 } 283 255 … … 286 258 subdrivers[count++] = &mapping->subdriver; 287 259 } 288 289 mapping = &usb_hid_subdrivers[++i];290 260 } 291 261 292 262 /* We have all subdrivers determined, save them into the hid device */ 293 // TODO Dowe really need this complicated stuff if there is294 // max_subdrivers limitation?295 263 return usb_hid_save_subdrivers(hid_dev, subdrivers, count); 296 264 } 297 298 /*----------------------------------------------------------------------------*/ 299 265 /*----------------------------------------------------------------------------*/ 300 266 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, const usb_device_t *dev) 301 267 { … … 303 269 assert(dev); 304 270 305 if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) { 306 usb_log_debug("Found keyboard endpoint.\n"); 307 // save the pipe index 308 hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO; 309 } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) { 310 usb_log_debug("Found mouse endpoint.\n"); 311 // save the pipe index 312 hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO; 313 } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) { 314 usb_log_debug("Found generic HID endpoint.\n"); 315 // save the pipe index 316 hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO; 317 } else { 318 usb_log_error("None of supported endpoints found - probably" 319 " not a supported device.\n"); 320 return ENOTSUP; 321 } 322 323 return EOK; 324 } 325 326 /*----------------------------------------------------------------------------*/ 327 271 static const struct { 272 unsigned ep_number; 273 const char* description; 274 } endpoints[] = { 275 {USB_HID_KBD_POLL_EP_NO, "Keyboard endpoint"}, 276 {USB_HID_MOUSE_POLL_EP_NO, "Mouse endpoint"}, 277 {USB_HID_GENERIC_POLL_EP_NO, "Generic HID endpoint"}, 278 }; 279 280 for (unsigned i = 0; i < sizeof(endpoints)/sizeof(endpoints[0]); ++i) { 281 if (endpoints[i].ep_number >= dev->pipes_count) { 282 return EINVAL; 283 } 284 if (dev->pipes[endpoints[i].ep_number].present) { 285 usb_log_debug("Found: %s.\n", endpoints[i].description); 286 hid_dev->poll_pipe_index = endpoints[i].ep_number; 287 return EOK; 288 } 289 } 290 return ENOTSUP; 291 } 292 /*----------------------------------------------------------------------------*/ 328 293 static int usb_hid_init_report(usb_hid_dev_t *hid_dev) 329 294 { … … 357 322 return EOK; 358 323 } 359 360 /*----------------------------------------------------------------------------*/ 361 324 /*----------------------------------------------------------------------------*/ 325 /* 326 * This functions initializes required structures from the device's descriptors 327 * and starts new fibril for polling the keyboard for events and another one for 328 * handling auto-repeat of keys. 329 * 330 * During initialization, the keyboard is switched into boot protocol, the idle 331 * rate is set to 0 (infinity), resulting in the keyboard only reporting event 332 * when a key is pressed or released. Finally, the LED lights are turned on 333 * according to the default setup of lock keys. 334 * 335 * @note By default, the keyboards is initialized with Num Lock turned on and 336 * other locks turned off. 337 * 338 * @param hid_dev Device to initialize, non-NULL. 339 * @param dev USB device, non-NULL. 340 * @return Error code. 341 */ 362 342 int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev) 363 343 { 364 int rc, i; 344 assert(hid_dev); 345 assert(dev); 365 346 366 347 usb_log_debug("Initializing HID structure...\n"); 367 368 if (hid_dev == NULL) {369 usb_log_error("Failed to init HID structure: no structure given"370 ".\n");371 return EINVAL;372 }373 374 if (dev == NULL) {375 usb_log_error("Failed to init HID structure: no USB device"376 " given.\n");377 return EINVAL;378 }379 348 380 349 usb_hid_report_init(&hid_dev->report); … … 384 353 hid_dev->poll_pipe_index = -1; 385 354 386 rc = usb_hid_check_pipes(hid_dev, dev);355 int rc = usb_hid_check_pipes(hid_dev, dev); 387 356 if (rc != EOK) { 388 357 return rc; … … 390 359 391 360 /* Get the report descriptor and parse it. */ 392 rc = usb_hid_process_report_descriptor( hid_dev->usb_dev,393 &hid_dev->report, &hid_dev->report_desc, &hid_dev->report_desc_size);394 395 bool fallback = false; 396 361 rc = usb_hid_process_report_descriptor( 362 hid_dev->usb_dev, &hid_dev->report, &hid_dev->report_desc, 363 &hid_dev->report_desc_size); 364 365 /* If report parsing went well, find subdrivers. */ 397 366 if (rc == EOK) { 398 // try to find subdrivers that may want to handle this device 399 rc = usb_hid_find_subdrivers(hid_dev); 400 if (rc != EOK || hid_dev->subdriver_count == 0) { 401 // try to fall back to the boot protocol if available 402 usb_log_info("No subdrivers found to handle this" 403 " device.\n"); 404 fallback = true; 405 assert(hid_dev->subdrivers == NULL); 406 assert(hid_dev->subdriver_count == 0); 407 } 367 usb_hid_find_subdrivers(hid_dev); 408 368 } else { 409 usb_log_error("Failed to parse Report descriptor.\n"); 410 // try to fall back to the boot protocol if available 411 fallback = true; 412 } 413 414 if (fallback) { 415 // fall back to boot protocol 369 usb_log_error("Failed to parse report descriptor: fallback.\n"); 370 hid_dev->subdrivers = NULL; 371 hid_dev->subdriver_count = 0; 372 } 373 374 usb_log_debug("Subdriver count(before trying boot protocol): %d\n", 375 hid_dev->subdriver_count); 376 377 /* No subdrivers, fall back to the boot protocol if available. */ 378 if (hid_dev->subdriver_count == 0) { 379 assert(hid_dev->subdrivers == NULL); 380 usb_log_info("No subdrivers found to handle device, trying " 381 "boot protocol.\n"); 382 416 383 switch (hid_dev->poll_pipe_index) { 417 384 case USB_HID_KBD_POLL_EP_NO: … … 419 386 rc = usb_kbd_set_boot_protocol(hid_dev); 420 387 if (rc == EOK) { 421 rc =usb_hid_set_boot_kbd_subdriver(hid_dev);388 usb_hid_set_boot_kbd_subdriver(hid_dev); 422 389 } 423 390 break; … … 426 393 rc = usb_mouse_set_boot_protocol(hid_dev); 427 394 if (rc == EOK) { 428 rc =usb_hid_set_boot_mouse_subdriver(hid_dev);395 usb_hid_set_boot_mouse_subdriver(hid_dev); 429 396 } 430 397 break; … … 432 399 assert(hid_dev->poll_pipe_index 433 400 == USB_HID_GENERIC_POLL_EP_NO); 434 435 401 usb_log_info("Falling back to generic HID driver.\n"); 436 rc = usb_hid_set_generic_hid_subdriver(hid_dev); 437 } 438 } 439 440 if (rc != EOK) { 441 usb_log_error("No subdriver for handling this device could be" 442 " initialized: %s.\n", str_error(rc)); 443 usb_log_debug("Subdriver count: %d\n", 444 hid_dev->subdriver_count); 445 } else { 446 bool ok = false; 447 448 usb_log_debug("Subdriver count: %d\n", 449 hid_dev->subdriver_count); 450 451 for (i = 0; i < hid_dev->subdriver_count; ++i) { 452 if (hid_dev->subdrivers[i].init != NULL) { 453 usb_log_debug("Initializing subdriver %d.\n",i); 454 rc = hid_dev->subdrivers[i].init(hid_dev, 455 &hid_dev->subdrivers[i].data); 456 if (rc != EOK) { 457 usb_log_warning("Failed to initialize" 458 " HID subdriver structure.\n"); 459 } else { 460 // at least one subdriver initialized 461 ok = true; 462 } 402 usb_hid_set_generic_hid_subdriver(hid_dev); 403 } 404 } 405 406 usb_log_debug("Subdriver count(after trying boot protocol): %d\n", 407 hid_dev->subdriver_count); 408 409 /* Still no subdrivers? */ 410 if (hid_dev->subdriver_count == 0) { 411 assert(hid_dev->subdrivers == NULL); 412 usb_log_error( 413 "No subdriver for handling this device could be found.\n"); 414 return ENOTSUP; 415 } 416 417 /* 418 * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da 419 * do nej. 420 * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi 421 * vyplnenu strukturu usbhid_iface_t. 422 * 3) klientska aplikacia - musi si rucne vytvorit telefon 423 * (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az 424 * k tej fcii. 425 * pouzit usb/classes/hid/iface.h - prvy int je telefon 426 */ 427 bool ok = false; 428 for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) { 429 if (hid_dev->subdrivers[i].init != NULL) { 430 usb_log_debug("Initializing subdriver %d.\n",i); 431 const int pret = hid_dev->subdrivers[i].init(hid_dev, 432 &hid_dev->subdrivers[i].data); 433 if (pret != EOK) { 434 usb_log_warning("Failed to initialize" 435 " HID subdriver structure: %s.\n", 436 str_error(pret)); 437 rc = pret; 463 438 } else { 439 /* At least one subdriver initialized. */ 464 440 ok = true; 465 441 } 466 } 467 468 rc = (ok) ? EOK : -1; // what error to report 469 } 470 471 472 if (rc == EOK) { 473 // save max input report size and allocate space for the report 442 } else { 443 /* Does not need initialization. */ 444 ok = true; 445 } 446 } 447 448 if (ok) { 449 /* Save max input report size and 450 * allocate space for the report */ 474 451 rc = usb_hid_init_report(hid_dev); 475 452 if (rc != EOK) { … … 481 458 return rc; 482 459 } 483 484 /*----------------------------------------------------------------------------*/ 485 460 /*----------------------------------------------------------------------------*/ 486 461 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer, 487 462 size_t buffer_size, void *arg) … … 516 491 bool cont = false; 517 492 /* Continue if at least one of the subdrivers want to continue */ 518 for ( inti = 0; i < hid_dev->subdriver_count; ++i) {493 for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) { 519 494 if (hid_dev->subdrivers[i].poll != NULL) { 520 495 cont = cont || hid_dev->subdrivers[i].poll( … … 525 500 return cont; 526 501 } 527 528 /*----------------------------------------------------------------------------*/ 529 502 /*----------------------------------------------------------------------------*/ 530 503 void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, void *arg) 531 504 { … … 535 508 usb_hid_dev_t *hid_dev = arg; 536 509 537 for ( inti = 0; i < hid_dev->subdriver_count; ++i) {510 for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) { 538 511 if (hid_dev->subdrivers[i].poll_end != NULL) { 539 512 hid_dev->subdrivers[i].poll_end( … … 544 517 hid_dev->running = false; 545 518 } 546 547 /*----------------------------------------------------------------------------*/ 548 519 /*----------------------------------------------------------------------------*/ 549 520 void usb_hid_new_report(usb_hid_dev_t *hid_dev) 550 521 { 551 522 ++hid_dev->report_nr; 552 523 } 553 554 /*----------------------------------------------------------------------------*/ 555 524 /*----------------------------------------------------------------------------*/ 556 525 int usb_hid_report_number(const usb_hid_dev_t *hid_dev) 557 526 { 558 527 return hid_dev->report_nr; 559 528 } 560 561 /*----------------------------------------------------------------------------*/ 562 529 /*----------------------------------------------------------------------------*/ 563 530 void usb_hid_deinit(usb_hid_dev_t *hid_dev) 564 531 { … … 570 537 hid_dev->subdrivers, hid_dev->subdriver_count); 571 538 572 for ( inti = 0; i < hid_dev->subdriver_count; ++i) {539 for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) { 573 540 if (hid_dev->subdrivers[i].deinit != NULL) { 574 541 hid_dev->subdrivers[i].deinit(hid_dev,
Note:
See TracChangeset
for help on using the changeset viewer.