Changes in uspace/drv/usbhid/usbhid.c [fec47d4:36f737a] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbhid/usbhid.c
rfec47d4 r36f737a 42 42 #include <usb/classes/hidreq.h> 43 43 #include <errno.h> 44 #include <str_error.h> 44 45 45 46 #include "usbhid.h" … … 47 48 #include "kbd/kbddev.h" 48 49 #include "generic/hiddev.h" 49 50 /*----------------------------------------------------------------------------*/ 51 52 /** Mouse polling endpoint description for boot protocol class. */ 53 static usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description = { 54 .transfer_type = USB_TRANSFER_INTERRUPT, 55 .direction = USB_DIRECTION_IN, 56 .interface_class = USB_CLASS_HID, 57 .interface_subclass = USB_HID_SUBCLASS_BOOT, 58 .interface_protocol = USB_HID_PROTOCOL_MOUSE, 59 .flags = 0 60 }; 50 #include "mouse/mousedev.h" 51 #include "subdrivers.h" 52 53 /*----------------------------------------------------------------------------*/ 61 54 62 55 /* Array of endpoints expected on the device, NULL terminated. */ … … 68 61 }; 69 62 70 static const char *HID_MOUSE_FUN_NAME = "mouse"; 71 static const char *HID_MOUSE_CLASS_NAME = "mouse"; 63 static const int USB_HID_MAX_SUBDRIVERS = 10; 64 65 /*----------------------------------------------------------------------------*/ 66 67 static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev) 68 { 69 assert(hid_dev != NULL && hid_dev->subdriver_count == 0); 70 71 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc( 72 sizeof(usb_hid_subdriver_t)); 73 if (hid_dev->subdrivers == NULL) { 74 return ENOMEM; 75 } 76 77 // set the init callback 78 hid_dev->subdrivers[0].init = usb_kbd_init; 79 80 // set the polling callback 81 hid_dev->subdrivers[0].poll = usb_kbd_polling_callback; 82 83 // set the polling ended callback 84 hid_dev->subdrivers[0].poll_end = NULL; 85 86 // set the deinit callback 87 hid_dev->subdrivers[0].deinit = usb_kbd_deinit; 88 89 // set subdriver count 90 hid_dev->subdriver_count = 1; 91 92 return EOK; 93 } 94 95 /*----------------------------------------------------------------------------*/ 96 97 static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev) 98 { 99 assert(hid_dev != NULL && hid_dev->subdriver_count == 0); 100 101 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc( 102 sizeof(usb_hid_subdriver_t)); 103 if (hid_dev->subdrivers == NULL) { 104 return ENOMEM; 105 } 106 107 // set the init callback 108 hid_dev->subdrivers[0].init = usb_mouse_init; 109 110 // set the polling callback 111 hid_dev->subdrivers[0].poll = usb_mouse_polling_callback; 112 113 // set the polling ended callback 114 hid_dev->subdrivers[0].poll_end = NULL; 115 116 // set the deinit callback 117 hid_dev->subdrivers[0].deinit = usb_mouse_deinit; 118 119 // set subdriver count 120 hid_dev->subdriver_count = 1; 121 122 return EOK; 123 } 124 125 /*----------------------------------------------------------------------------*/ 126 127 static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev) 128 { 129 assert(hid_dev != NULL && hid_dev->subdriver_count == 0); 130 131 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc( 132 sizeof(usb_hid_subdriver_t)); 133 if (hid_dev->subdrivers == NULL) { 134 return ENOMEM; 135 } 136 137 // set the init callback 138 hid_dev->subdrivers[0].init = NULL; 139 140 // set the polling callback 141 hid_dev->subdrivers[0].poll = usb_generic_hid_polling_callback; 142 143 // set the polling ended callback 144 hid_dev->subdrivers[0].poll_end = NULL; 145 146 // set the deinit callback 147 hid_dev->subdrivers[0].deinit = NULL; 148 149 // set subdriver count 150 hid_dev->subdriver_count = 1; 151 152 return EOK; 153 } 154 155 /*----------------------------------------------------------------------------*/ 156 157 static bool usb_hid_ids_match(usb_hid_dev_t *hid_dev, 158 const usb_hid_subdriver_mapping_t *mapping) 159 { 160 assert(hid_dev != NULL); 161 assert(hid_dev->usb_dev != NULL); 162 163 return (hid_dev->usb_dev->descriptors.device.vendor_id 164 == mapping->vendor_id 165 && hid_dev->usb_dev->descriptors.device.product_id 166 == mapping->product_id); 167 } 168 169 /*----------------------------------------------------------------------------*/ 170 171 static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev, 172 const usb_hid_subdriver_mapping_t *mapping) 173 { 174 assert(hid_dev != NULL); 175 assert(mapping != NULL); 176 177 usb_hid_report_path_t *usage_path = usb_hid_report_path(); 178 if (usage_path == NULL) { 179 usb_log_debug("Failed to create usage path.\n"); 180 return false; 181 } 182 int i = 0; 183 while (mapping->usage_path[i].usage != 0 184 || mapping->usage_path[i].usage_page != 0) { 185 if (usb_hid_report_path_append_item(usage_path, 186 mapping->usage_path[i].usage_page, 187 mapping->usage_path[i].usage) != EOK) { 188 usb_log_debug("Failed to append to usage path.\n"); 189 usb_hid_report_path_free(usage_path); 190 return false; 191 } 192 ++i; 193 } 194 195 if (mapping->report_id >= 0) { 196 usb_hid_report_path_set_report_id(usage_path, 197 mapping->report_id); 198 } 199 200 assert(hid_dev->report != NULL); 201 202 usb_log_debug("Compare flags: %d\n", mapping->compare); 203 size_t size = usb_hid_report_input_length(hid_dev->report, usage_path, 204 mapping->compare); 205 usb_log_debug("Size of the input report: %zuB\n", size); 206 207 usb_hid_report_path_free(usage_path); 208 209 return (size > 0); 210 } 211 212 /*----------------------------------------------------------------------------*/ 213 214 static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev, 215 const usb_hid_subdriver_t **subdrivers, int count) 216 { 217 int i; 218 219 if (count <= 0) { 220 hid_dev->subdriver_count = 0; 221 hid_dev->subdrivers = NULL; 222 return EOK; 223 } 224 225 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(count * 226 sizeof(usb_hid_subdriver_t)); 227 if (hid_dev->subdrivers == NULL) { 228 return ENOMEM; 229 } 230 231 for (i = 0; i < count; ++i) { 232 hid_dev->subdrivers[i].init = subdrivers[i]->init; 233 hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit; 234 hid_dev->subdrivers[i].poll = subdrivers[i]->poll; 235 hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end; 236 } 237 238 hid_dev->subdriver_count = count; 239 240 return EOK; 241 } 242 243 /*----------------------------------------------------------------------------*/ 244 245 static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev) 246 { 247 assert(hid_dev != NULL); 248 249 const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS]; 250 251 int i = 0, count = 0; 252 const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i]; 253 254 bool ids_matched; 255 bool matched; 256 257 while (count < USB_HID_MAX_SUBDRIVERS && 258 (mapping->usage_path != NULL 259 || mapping->vendor_id >= 0 || mapping->product_id >= 0)) { 260 // check the vendor & product ID 261 if (mapping->vendor_id >= 0 && mapping->product_id < 0) { 262 usb_log_warning("Missing Product ID for Vendor ID %d\n", 263 mapping->vendor_id); 264 return EINVAL; 265 } 266 if (mapping->product_id >= 0 && mapping->vendor_id < 0) { 267 usb_log_warning("Missing Vendor ID for Product ID %d\n", 268 mapping->product_id); 269 return EINVAL; 270 } 271 272 ids_matched = false; 273 matched = false; 274 275 if (mapping->vendor_id >= 0) { 276 assert(mapping->product_id >= 0); 277 usb_log_debug("Comparing device against vendor ID %u" 278 " and product ID %u.\n", mapping->vendor_id, 279 mapping->product_id); 280 if (usb_hid_ids_match(hid_dev, mapping)) { 281 usb_log_debug("IDs matched.\n"); 282 ids_matched = true; 283 } 284 } 285 286 if (mapping->usage_path != NULL) { 287 usb_log_debug("Comparing device against usage path.\n"); 288 if (usb_hid_path_matches(hid_dev, mapping)) { 289 // does not matter if IDs were matched 290 matched = true; 291 } 292 } else { 293 // matched only if IDs were matched and there is no path 294 matched = ids_matched; 295 } 296 297 if (matched) { 298 subdrivers[count++] = &mapping->subdriver; 299 } 300 301 mapping = &usb_hid_subdrivers[++i]; 302 } 303 304 // we have all subdrivers determined, save them into the hid device 305 return usb_hid_save_subdrivers(hid_dev, subdrivers, count); 306 } 307 308 /*----------------------------------------------------------------------------*/ 309 310 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev) 311 { 312 assert(hid_dev != NULL && dev != NULL); 313 314 int rc = EOK; 315 316 if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) { 317 usb_log_debug("Found keyboard endpoint.\n"); 318 // save the pipe index 319 hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO; 320 } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) { 321 usb_log_debug("Found mouse endpoint.\n"); 322 // save the pipe index 323 hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO; 324 } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) { 325 usb_log_debug("Found generic HID endpoint.\n"); 326 // save the pipe index 327 hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO; 328 } else { 329 usb_log_error("None of supported endpoints found - probably" 330 " not a supported device.\n"); 331 rc = ENOTSUP; 332 } 333 334 return rc; 335 } 72 336 73 337 /*----------------------------------------------------------------------------*/ … … 83 347 } 84 348 85 hid_dev-> parser = (usb_hid_report_parser_t *)(malloc(sizeof(86 usb_hid_report_ parser_t)));87 if (hid_dev-> parser== NULL) {349 hid_dev->report = (usb_hid_report_t *)(malloc(sizeof( 350 usb_hid_report_t))); 351 if (hid_dev->report == NULL) { 88 352 usb_log_fatal("No memory!\n"); 89 353 free(hid_dev); … … 91 355 } 92 356 357 hid_dev->poll_pipe_index = -1; 358 93 359 return hid_dev; 94 360 } … … 96 362 /*----------------------------------------------------------------------------*/ 97 363 98 static bool usb_dummy_polling_callback(usb_device_t *dev, uint8_t *buffer,99 size_t buffer_size, void *arg)100 {101 usb_log_debug("Dummy polling callback.\n");102 return false;103 }104 105 /*----------------------------------------------------------------------------*/106 107 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)108 {109 if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {110 usb_log_debug("Found keyboard endpoint.\n");111 112 // save the pipe index and device type113 hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;114 hid_dev->device_type = USB_HID_PROTOCOL_KEYBOARD;115 116 // set the polling callback117 hid_dev->poll_callback = usb_kbd_polling_callback;118 119 } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {120 usb_log_debug("Found mouse endpoint.\n");121 122 // save the pipe index and device type123 hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;124 hid_dev->device_type = USB_HID_PROTOCOL_MOUSE;125 126 // set the polling callback127 hid_dev->poll_callback = usb_dummy_polling_callback;128 129 } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {130 usb_log_debug("Found generic HID endpoint.\n");131 132 // save the pipe index and device type133 hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;134 hid_dev->device_type = USB_HID_PROTOCOL_NONE;135 136 // set the polling callback137 hid_dev->poll_callback = usb_hid_polling_callback;138 139 } else {140 usb_log_warning("None of supported endpoints found - probably"141 " not a supported device.\n");142 return ENOTSUP;143 }144 145 return EOK;146 }147 148 /*----------------------------------------------------------------------------*/149 150 static int usb_hid_init_parser(usb_hid_dev_t *hid_dev)151 {152 /* Initialize the report parser. */153 int rc = usb_hid_parser_init(hid_dev->parser);154 if (rc != EOK) {155 usb_log_error("Failed to initialize report parser.\n");156 return rc;157 }158 159 /* Get the report descriptor and parse it. */160 rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,161 hid_dev->parser);162 163 if (rc != EOK) {164 usb_log_warning("Could not process report descriptor.\n");165 166 if (hid_dev->device_type == USB_HID_PROTOCOL_KEYBOARD) {167 usb_log_warning("Falling back to boot protocol.\n");168 169 rc = usb_kbd_set_boot_protocol(hid_dev);170 171 } else if (hid_dev->device_type == USB_HID_PROTOCOL_MOUSE) {172 usb_log_warning("No boot protocol for mouse yet.\n");173 rc = ENOTSUP;174 }175 }176 177 return rc;178 }179 180 /*----------------------------------------------------------------------------*/181 182 364 int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev) 183 365 { 184 int rc ;366 int rc, i; 185 367 186 368 usb_log_debug("Initializing HID structure...\n"); … … 203 385 rc = usb_hid_check_pipes(hid_dev, dev); 204 386 if (rc != EOK) { 387 //usb_hid_free(&hid_dev); 205 388 return rc; 206 389 } 207 208 rc = usb_hid_init_parser(hid_dev); 390 391 /* Get the report descriptor and parse it. */ 392 rc = usb_hid_process_report_descriptor(hid_dev->usb_dev, 393 hid_dev->report); 394 395 bool fallback = false; 396 397 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 } 408 } 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 // TODO: remove the mouse hack 415 if (hid_dev->poll_pipe_index == USB_HID_MOUSE_POLL_EP_NO || 416 fallback) { 417 // fall back to boot protocol 418 switch (hid_dev->poll_pipe_index) { 419 case USB_HID_KBD_POLL_EP_NO: 420 usb_log_info("Falling back to kbd boot protocol.\n"); 421 rc = usb_kbd_set_boot_protocol(hid_dev); 422 if (rc == EOK) { 423 rc = usb_hid_set_boot_kbd_subdriver(hid_dev); 424 } 425 break; 426 case USB_HID_MOUSE_POLL_EP_NO: 427 usb_log_info("Falling back to mouse boot protocol.\n"); 428 rc = usb_mouse_set_boot_protocol(hid_dev); 429 if (rc == EOK) { 430 rc = usb_hid_set_boot_mouse_subdriver(hid_dev); 431 } 432 break; 433 default: 434 assert(hid_dev->poll_pipe_index 435 == USB_HID_GENERIC_POLL_EP_NO); 436 437 /* TODO: this has no meaning if the report descriptor 438 is not parsed */ 439 usb_log_info("Falling back to generic HID driver.\n"); 440 rc = usb_hid_set_generic_hid_subdriver(hid_dev); 441 } 442 } 443 209 444 if (rc != EOK) { 210 usb_log_error("Failed to initialize HID parser.\n"); 211 return rc; 212 } 213 214 switch (hid_dev->device_type) { 215 case USB_HID_PROTOCOL_KEYBOARD: 216 // initialize the keyboard structure 217 rc = usb_kbd_init(hid_dev); 218 if (rc != EOK) { 219 usb_log_warning("Failed to initialize KBD structure." 220 "\n"); 221 } 222 break; 223 case USB_HID_PROTOCOL_MOUSE: 224 break; 225 default: 226 // usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 227 // hid_dev->usb_dev->interface_no, 0); 228 break; 445 usb_log_error("No subdriver for handling this device could be" 446 " initialized: %s.\n", str_error(rc)); 447 usb_log_debug("Subdriver count: %d\n", 448 hid_dev->subdriver_count); 449 //usb_hid_free(&hid_dev); 450 } else { 451 bool ok = false; 452 453 usb_log_debug("Subdriver count: %d\n", 454 hid_dev->subdriver_count); 455 456 for (i = 0; i < hid_dev->subdriver_count; ++i) { 457 if (hid_dev->subdrivers[i].init != NULL) { 458 usb_log_debug("Initializing subdriver %d.\n",i); 459 rc = hid_dev->subdrivers[i].init(hid_dev); 460 if (rc != EOK) { 461 usb_log_warning("Failed to initialize" 462 " HID subdriver structure.\n"); 463 } else { 464 // at least one subdriver initialized 465 ok = true; 466 } 467 } else { 468 ok = true; 469 } 470 } 471 472 rc = (ok) ? EOK : -1; // what error to report 229 473 } 230 474 231 475 return rc; 476 } 477 478 /*----------------------------------------------------------------------------*/ 479 480 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer, 481 size_t buffer_size, void *arg) 482 { 483 int i; 484 485 if (dev == NULL || arg == NULL || buffer == NULL) { 486 usb_log_error("Missing arguments to polling callback.\n"); 487 return false; 488 } 489 490 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg; 491 492 bool cont = false; 493 494 // continue if at least one of the subdrivers want to continue 495 for (i = 0; i < hid_dev->subdriver_count; ++i) { 496 if (hid_dev->subdrivers[i].poll != NULL 497 && hid_dev->subdrivers[i].poll(hid_dev, buffer, 498 buffer_size)) { 499 cont = true; 500 } 501 } 502 503 return cont; 232 504 } 233 505 … … 237 509 void *arg) 238 510 { 511 int i; 512 239 513 if (dev == NULL || arg == NULL) { 240 514 return; … … 243 517 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg; 244 518 519 for (i = 0; i < hid_dev->subdriver_count; ++i) { 520 if (hid_dev->subdrivers[i].poll_end != NULL) { 521 hid_dev->subdrivers[i].poll_end(hid_dev, reason); 522 } 523 } 524 245 525 usb_hid_free(&hid_dev); 246 526 } … … 248 528 /*----------------------------------------------------------------------------*/ 249 529 250 const char *usb_hid_get_function_name( usb_hid_iface_protocol_t device_type)251 { 252 switch ( device_type) {253 case USB_HID_ PROTOCOL_KEYBOARD:530 const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev) 531 { 532 switch (hid_dev->poll_pipe_index) { 533 case USB_HID_KBD_POLL_EP_NO: 254 534 return HID_KBD_FUN_NAME; 255 535 break; 256 case USB_HID_ PROTOCOL_MOUSE:536 case USB_HID_MOUSE_POLL_EP_NO: 257 537 return HID_MOUSE_FUN_NAME; 258 538 break; … … 264 544 /*----------------------------------------------------------------------------*/ 265 545 266 const char *usb_hid_get_class_name(usb_hid_iface_protocol_t device_type) 267 { 268 switch (device_type) { 269 case USB_HID_PROTOCOL_KEYBOARD: 546 const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev) 547 { 548 // this means that only boot protocol keyboards will be connected 549 // to the console; there is probably no better way to do this 550 551 switch (hid_dev->poll_pipe_index) { 552 case USB_HID_KBD_POLL_EP_NO: 270 553 return HID_KBD_CLASS_NAME; 271 554 break; 272 case USB_HID_ PROTOCOL_MOUSE:555 case USB_HID_MOUSE_POLL_EP_NO: 273 556 return HID_MOUSE_CLASS_NAME; 274 557 break; … … 282 565 void usb_hid_free(usb_hid_dev_t **hid_dev) 283 566 { 567 int i; 568 284 569 if (hid_dev == NULL || *hid_dev == NULL) { 285 570 return; 286 571 } 287 572 288 switch ((*hid_dev)->device_type) { 289 case USB_HID_PROTOCOL_KEYBOARD: 290 usb_kbd_deinit(*hid_dev); 291 break; 292 case USB_HID_PROTOCOL_MOUSE: 293 break; 294 default: 295 break; 573 usb_log_debug("Subdrivers: %p, subdriver count: %d\n", 574 (*hid_dev)->subdrivers, (*hid_dev)->subdriver_count); 575 576 assert((*hid_dev)->subdrivers != NULL 577 || (*hid_dev)->subdriver_count == 0); 578 579 for (i = 0; i < (*hid_dev)->subdriver_count; ++i) { 580 if ((*hid_dev)->subdrivers[i].deinit != NULL) { 581 (*hid_dev)->subdrivers[i].deinit(*hid_dev); 582 } 583 } 584 585 // free the subdrivers info 586 if ((*hid_dev)->subdrivers != NULL) { 587 free((*hid_dev)->subdrivers); 296 588 } 297 589 298 590 // destroy the parser 299 if ((*hid_dev)-> parser!= NULL) {300 usb_hid_free_report _parser((*hid_dev)->parser);591 if ((*hid_dev)->report != NULL) { 592 usb_hid_free_report((*hid_dev)->report); 301 593 } 302 594
Note:
See TracChangeset
for help on using the changeset viewer.