Changes in uspace/drv/bus/usb/usbhid/usbhid.c [9d58539:93d2684] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/usbhid/usbhid.c
r9d58539 r93d2684 51 51 #include "subdrivers.h" 52 52 53 /*----------------------------------------------------------------------------*/ 54 53 55 /* Array of endpoints expected on the device, NULL terminated. */ 54 56 const usb_endpoint_description_t *usb_hid_endpoints[] = { … … 58 60 NULL 59 61 }; 60 /*----------------------------------------------------------------------------*/ 62 63 /*----------------------------------------------------------------------------*/ 64 61 65 static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev) 62 66 { … … 74 78 return EOK; 75 79 } 76 /*----------------------------------------------------------------------------*/ 80 81 /*----------------------------------------------------------------------------*/ 82 77 83 static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev) 78 84 { … … 86 92 hid_dev->subdriver_count = 1; 87 93 // TODO 2 should be mouse, but find a better way 88 hid_dev->subdrivers[ 0] = usb_hid_subdrivers[2].subdriver;94 hid_dev->subdrivers[2] = usb_hid_subdrivers[0].subdriver; 89 95 90 96 return EOK; 91 97 } 92 /*----------------------------------------------------------------------------*/ 98 99 /*----------------------------------------------------------------------------*/ 100 93 101 static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev) 94 102 { 95 assert(hid_dev != NULL); 96 assert(hid_dev->subdriver_count == 0); 103 assert(hid_dev != NULL && hid_dev->subdriver_count == 0); 97 104 98 105 hid_dev->subdrivers = malloc(sizeof(usb_hid_subdriver_t)); … … 110 117 return EOK; 111 118 } 112 /*----------------------------------------------------------------------------*/ 119 120 /*----------------------------------------------------------------------------*/ 121 113 122 static bool usb_hid_ids_match(const usb_hid_dev_t *hid_dev, 114 123 const usb_hid_subdriver_mapping_t *mapping) … … 119 128 return (hid_dev->usb_dev->descriptors.device.vendor_id 120 129 == mapping->vendor_id 121 && hid_dev->usb_dev->descriptors.device.product_id 130 && hid_dev->usb_dev->descriptors.device.product_id 122 131 == mapping->product_id); 123 132 } 124 /*----------------------------------------------------------------------------*/ 133 134 /*----------------------------------------------------------------------------*/ 135 125 136 static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev, 126 137 const usb_hid_subdriver_mapping_t *mapping) … … 134 145 return false; 135 146 } 136 137 for (int i = 0;mapping->usage_path[i].usage != 0138 || mapping->usage_path[i].usage_page != 0 ; ++i) {147 int i = 0; 148 while (mapping->usage_path[i].usage != 0 149 || mapping->usage_path[i].usage_page != 0) { 139 150 if (usb_hid_report_path_append_item(usage_path, 140 151 mapping->usage_path[i].usage_page, … … 144 155 return false; 145 156 } 157 ++i; 146 158 } 147 159 … … 153 165 do { 154 166 usb_log_debug("Trying report id %u\n", report_id); 167 155 168 if (report_id != 0) { 156 169 usb_hid_report_path_set_report_id(usage_path, … … 158 171 } 159 172 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); 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); 164 176 165 177 usb_log_debug("Field: %p\n", field); … … 178 190 return matches; 179 191 } 180 /*----------------------------------------------------------------------------*/ 192 193 /*----------------------------------------------------------------------------*/ 194 181 195 static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev, 182 const usb_hid_subdriver_t **subdrivers, unsigned count) 183 { 184 assert(hid_dev); 185 assert(subdrivers); 186 187 if (count == 0) { 196 const usb_hid_subdriver_t **subdrivers, int count) 197 { 198 int i; 199 200 if (count <= 0) { 188 201 hid_dev->subdriver_count = 0; 189 202 hid_dev->subdrivers = NULL; … … 197 210 } 198 211 199 for (unsigned i = 0; i < count; ++i) { 200 hid_dev->subdrivers[i] = *subdrivers[i]; 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; 201 217 } 202 218 … … 211 227 return EOK; 212 228 } 213 /*----------------------------------------------------------------------------*/ 229 230 /*----------------------------------------------------------------------------*/ 231 214 232 static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev) 215 233 { … … 217 235 218 236 const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS]; 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. */ 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 225 248 if (mapping->vendor_id >= 0 && mapping->product_id < 0) { 226 usb_log_warning("Mapping[%d]: Missing Product ID for " 227 "Vendor ID %d\n", i, mapping->vendor_id); 249 usb_log_warning("Missing Product ID for Vendor ID %d\n", 250 mapping->vendor_id); 251 return EINVAL; 228 252 } 229 253 if (mapping->product_id >= 0 && mapping->vendor_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) { 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); 238 264 usb_log_debug("Comparing device against vendor ID %u" 239 265 " and product ID %u.\n", mapping->vendor_id, … … 241 267 if (usb_hid_ids_match(hid_dev, mapping)) { 242 268 usb_log_debug("IDs matched.\n"); 243 matched = true;269 ids_matched = true; 244 270 } 245 271 } 246 272 247 /* Check usage match. */248 273 if (mapping->usage_path != NULL) { 249 274 usb_log_debug("Comparing device against usage path.\n"); 250 275 if (usb_hid_path_matches(hid_dev, mapping)) { 251 / * Does not matter if IDs were matched. */276 // does not matter if IDs were matched 252 277 matched = true; 253 278 } 279 } else { 280 // matched only if IDs were matched and there is no path 281 matched = ids_matched; 254 282 } 255 283 … … 258 286 subdrivers[count++] = &mapping->subdriver; 259 287 } 288 289 mapping = &usb_hid_subdrivers[++i]; 260 290 } 261 291 262 292 /* We have all subdrivers determined, save them into the hid device */ 293 // TODO Dowe really need this complicated stuff if there is 294 // max_subdrivers limitation? 263 295 return usb_hid_save_subdrivers(hid_dev, subdrivers, count); 264 296 } 265 /*----------------------------------------------------------------------------*/ 297 298 /*----------------------------------------------------------------------------*/ 299 266 300 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, const usb_device_t *dev) 267 301 { … … 269 303 assert(dev); 270 304 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 /*----------------------------------------------------------------------------*/ 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 293 328 static int usb_hid_init_report(usb_hid_dev_t *hid_dev) 294 329 { … … 322 357 return EOK; 323 358 } 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 */ 359 360 /*----------------------------------------------------------------------------*/ 361 342 362 int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev) 343 363 { 344 assert(hid_dev); 345 assert(dev); 364 int rc, i; 346 365 347 366 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 } 348 379 349 380 usb_hid_report_init(&hid_dev->report); … … 353 384 hid_dev->poll_pipe_index = -1; 354 385 355 intrc = usb_hid_check_pipes(hid_dev, dev);386 rc = usb_hid_check_pipes(hid_dev, dev); 356 387 if (rc != EOK) { 357 388 return rc; … … 359 390 360 391 /* Get the report descriptor and parse it. */ 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. */ 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 366 397 if (rc == EOK) { 367 usb_hid_find_subdrivers(hid_dev); 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 } 368 408 } else { 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 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 383 416 switch (hid_dev->poll_pipe_index) { 384 417 case USB_HID_KBD_POLL_EP_NO: … … 386 419 rc = usb_kbd_set_boot_protocol(hid_dev); 387 420 if (rc == EOK) { 388 usb_hid_set_boot_kbd_subdriver(hid_dev);421 rc = usb_hid_set_boot_kbd_subdriver(hid_dev); 389 422 } 390 423 break; … … 393 426 rc = usb_mouse_set_boot_protocol(hid_dev); 394 427 if (rc == EOK) { 395 usb_hid_set_boot_mouse_subdriver(hid_dev);428 rc = usb_hid_set_boot_mouse_subdriver(hid_dev); 396 429 } 397 430 break; … … 399 432 assert(hid_dev->poll_pipe_index 400 433 == USB_HID_GENERIC_POLL_EP_NO); 434 401 435 usb_log_info("Falling back to generic HID driver.\n"); 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; 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 } 438 463 } else { 439 /* At least one subdriver initialized. */440 464 ok = true; 441 465 } 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 */ 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 451 474 rc = usb_hid_init_report(hid_dev); 452 475 if (rc != EOK) { … … 458 481 return rc; 459 482 } 460 /*----------------------------------------------------------------------------*/ 483 484 /*----------------------------------------------------------------------------*/ 485 461 486 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer, 462 487 size_t buffer_size, void *arg) … … 491 516 bool cont = false; 492 517 /* Continue if at least one of the subdrivers want to continue */ 493 for ( unsignedi = 0; i < hid_dev->subdriver_count; ++i) {518 for (int i = 0; i < hid_dev->subdriver_count; ++i) { 494 519 if (hid_dev->subdrivers[i].poll != NULL) { 495 520 cont = cont || hid_dev->subdrivers[i].poll( … … 500 525 return cont; 501 526 } 502 /*----------------------------------------------------------------------------*/ 527 528 /*----------------------------------------------------------------------------*/ 529 503 530 void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, void *arg) 504 531 { … … 508 535 usb_hid_dev_t *hid_dev = arg; 509 536 510 for ( unsignedi = 0; i < hid_dev->subdriver_count; ++i) {537 for (int i = 0; i < hid_dev->subdriver_count; ++i) { 511 538 if (hid_dev->subdrivers[i].poll_end != NULL) { 512 539 hid_dev->subdrivers[i].poll_end( … … 517 544 hid_dev->running = false; 518 545 } 519 /*----------------------------------------------------------------------------*/ 546 547 /*----------------------------------------------------------------------------*/ 548 520 549 void usb_hid_new_report(usb_hid_dev_t *hid_dev) 521 550 { 522 551 ++hid_dev->report_nr; 523 552 } 524 /*----------------------------------------------------------------------------*/ 553 554 /*----------------------------------------------------------------------------*/ 555 525 556 int usb_hid_report_number(const usb_hid_dev_t *hid_dev) 526 557 { 527 558 return hid_dev->report_nr; 528 559 } 529 /*----------------------------------------------------------------------------*/ 560 561 /*----------------------------------------------------------------------------*/ 562 530 563 void usb_hid_deinit(usb_hid_dev_t *hid_dev) 531 564 { … … 537 570 hid_dev->subdrivers, hid_dev->subdriver_count); 538 571 539 for ( unsignedi = 0; i < hid_dev->subdriver_count; ++i) {572 for (int i = 0; i < hid_dev->subdriver_count; ++i) { 540 573 if (hid_dev->subdrivers[i].deinit != NULL) { 541 574 hid_dev->subdrivers[i].deinit(hid_dev,
Note:
See TracChangeset
for help on using the changeset viewer.