Changeset 20a3465 in mainline for uspace/drv/bus/usb/usbhid/usbhid.c
- Timestamp:
- 2011-10-30T19:50:54Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 3ce78580, 48902fa
- Parents:
- 4c3ad56 (diff), 45bf63c (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
r4c3ad56 r20a3465 54 54 55 55 /* Array of endpoints expected on the device, NULL terminated. */ 56 usb_endpoint_description_t *usb_hid_endpoints[USB_HID_POLL_EP_COUNT + 1] = {56 const usb_endpoint_description_t *usb_hid_endpoints[] = { 57 57 &usb_hid_kbd_poll_endpoint_description, 58 58 &usb_hid_mouse_poll_endpoint_description, … … 61 61 }; 62 62 63 static const int USB_HID_MAX_SUBDRIVERS = 10;64 65 63 /*----------------------------------------------------------------------------*/ 66 64 67 65 static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev) 68 66 { 69 assert(hid_dev != NULL && hid_dev->subdriver_count == 0);70 71 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc( 72 67 assert(hid_dev != NULL); 68 assert(hid_dev->subdriver_count == 0); 69 70 hid_dev->subdrivers = malloc(sizeof(usb_hid_subdriver_t)); 73 71 if (hid_dev->subdrivers == NULL) { 74 72 return ENOMEM; 75 73 } 76 77 assert(hid_dev->subdriver_count >= 0); 78 79 // set the init callback 80 hid_dev->subdrivers[hid_dev->subdriver_count].init = usb_kbd_init; 81 82 // set the polling callback 83 hid_dev->subdrivers[hid_dev->subdriver_count].poll = 84 usb_kbd_polling_callback; 85 86 // set the polling ended callback 87 hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL; 88 89 // set the deinit callback 90 hid_dev->subdrivers[hid_dev->subdriver_count].deinit = usb_kbd_deinit; 91 92 // set subdriver count 93 ++hid_dev->subdriver_count; 94 74 hid_dev->subdriver_count = 1; 75 // TODO 0 should be keyboard, but find a better way 76 hid_dev->subdrivers[0] = usb_hid_subdrivers[0].subdriver; 77 95 78 return EOK; 96 79 } … … 100 83 static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev) 101 84 { 102 assert(hid_dev != NULL && hid_dev->subdriver_count == 0);103 104 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc( 105 85 assert(hid_dev != NULL); 86 assert(hid_dev->subdriver_count == 0); 87 88 hid_dev->subdrivers = malloc(sizeof(usb_hid_subdriver_t)); 106 89 if (hid_dev->subdrivers == NULL) { 107 90 return ENOMEM; 108 91 } 109 110 assert(hid_dev->subdriver_count >= 0); 111 112 // set the init callback 113 hid_dev->subdrivers[hid_dev->subdriver_count].init = usb_mouse_init; 114 115 // set the polling callback 116 hid_dev->subdrivers[hid_dev->subdriver_count].poll = 117 usb_mouse_polling_callback; 118 119 // set the polling ended callback 120 hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL; 121 122 // set the deinit callback 123 hid_dev->subdrivers[hid_dev->subdriver_count].deinit = usb_mouse_deinit; 124 125 // set subdriver count 126 ++hid_dev->subdriver_count; 127 92 hid_dev->subdriver_count = 1; 93 // TODO 2 should be mouse, but find a better way 94 hid_dev->subdrivers[2] = usb_hid_subdrivers[0].subdriver; 95 128 96 return EOK; 129 97 } … … 134 102 { 135 103 assert(hid_dev != NULL && hid_dev->subdriver_count == 0); 136 137 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc( 138 sizeof(usb_hid_subdriver_t)); 104 105 hid_dev->subdrivers = malloc(sizeof(usb_hid_subdriver_t)); 139 106 if (hid_dev->subdrivers == NULL) { 140 107 return ENOMEM; 141 108 } 142 143 assert(hid_dev->subdriver_count >= 0); 144 145 // set the init callback 146 hid_dev->subdrivers[hid_dev->subdriver_count].init = 147 usb_generic_hid_init; 148 149 // set the polling callback 150 hid_dev->subdrivers[hid_dev->subdriver_count].poll = 151 usb_generic_hid_polling_callback; 152 153 // set the polling ended callback 154 hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL; 155 156 // set the deinit callback 157 hid_dev->subdrivers[hid_dev->subdriver_count].deinit = NULL; 158 159 // set subdriver count 160 ++hid_dev->subdriver_count; 161 109 hid_dev->subdriver_count = 1; 110 111 /* Set generic hid subdriver routines */ 112 hid_dev->subdrivers[0].init = usb_generic_hid_init; 113 hid_dev->subdrivers[0].poll = usb_generic_hid_polling_callback; 114 hid_dev->subdrivers[0].poll_end = NULL; 115 hid_dev->subdrivers[0].deinit = usb_generic_hid_deinit; 116 162 117 return EOK; 163 118 } … … 165 120 /*----------------------------------------------------------------------------*/ 166 121 167 static bool usb_hid_ids_match( usb_hid_dev_t *hid_dev,122 static bool usb_hid_ids_match(const usb_hid_dev_t *hid_dev, 168 123 const usb_hid_subdriver_mapping_t *mapping) 169 124 { 170 125 assert(hid_dev != NULL); 171 126 assert(hid_dev->usb_dev != NULL); 172 173 return (hid_dev->usb_dev->descriptors.device.vendor_id 127 128 return (hid_dev->usb_dev->descriptors.device.vendor_id 174 129 == mapping->vendor_id 175 130 && hid_dev->usb_dev->descriptors.device.product_id … … 179 134 /*----------------------------------------------------------------------------*/ 180 135 181 static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev, 136 static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev, 182 137 const usb_hid_subdriver_mapping_t *mapping) 183 138 { 184 139 assert(hid_dev != NULL); 185 140 assert(mapping != NULL); 186 141 187 142 usb_hid_report_path_t *usage_path = usb_hid_report_path(); 188 143 if (usage_path == NULL) { … … 191 146 } 192 147 int i = 0; 193 while (mapping->usage_path[i].usage != 0 148 while (mapping->usage_path[i].usage != 0 194 149 || mapping->usage_path[i].usage_page != 0) { 195 if (usb_hid_report_path_append_item(usage_path, 196 mapping->usage_path[i].usage_page, 150 if (usb_hid_report_path_append_item(usage_path, 151 mapping->usage_path[i].usage_page, 197 152 mapping->usage_path[i].usage) != EOK) { 198 153 usb_log_debug("Failed to append to usage path.\n"); … … 202 157 ++i; 203 158 } 204 205 assert(hid_dev->report != NULL); 206 159 207 160 usb_log_debug("Compare flags: %d\n", mapping->compare); 208 161 209 162 bool matches = false; 210 163 uint8_t report_id = mapping->report_id; … … 212 165 do { 213 166 usb_log_debug("Trying report id %u\n", report_id); 214 167 215 168 if (report_id != 0) { 216 169 usb_hid_report_path_set_report_id(usage_path, … … 219 172 220 173 usb_hid_report_field_t *field = usb_hid_report_get_sibling( 221 hid_dev->report, 222 NULL, usage_path, mapping->compare, 174 &hid_dev->report, NULL, usage_path, mapping->compare, 223 175 USB_HID_REPORT_TYPE_INPUT); 224 176 225 177 usb_log_debug("Field: %p\n", field); 226 178 … … 229 181 break; 230 182 } 231 183 232 184 report_id = usb_hid_get_next_report_id( 233 hid_dev->report, report_id, 234 USB_HID_REPORT_TYPE_INPUT); 185 &hid_dev->report, report_id, USB_HID_REPORT_TYPE_INPUT); 235 186 } while (!matches && report_id != 0); 236 187 237 188 usb_hid_report_path_free(usage_path); 238 189 239 190 return matches; 240 191 } … … 242 193 /*----------------------------------------------------------------------------*/ 243 194 244 static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev, 195 static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev, 245 196 const usb_hid_subdriver_t **subdrivers, int count) 246 197 { 247 198 int i; 248 199 249 200 if (count <= 0) { 250 201 hid_dev->subdriver_count = 0; … … 252 203 return EOK; 253 204 } 254 255 // add one generic HID subdriver per device 256 257 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc((count + 1) * 258 sizeof(usb_hid_subdriver_t)); 205 206 /* +1 for generic hid subdriver */ 207 hid_dev->subdrivers = calloc((count + 1), sizeof(usb_hid_subdriver_t)); 259 208 if (hid_dev->subdrivers == NULL) { 260 209 return ENOMEM; 261 210 } 262 211 263 212 for (i = 0; i < count; ++i) { 264 213 hid_dev->subdrivers[i].init = subdrivers[i]->init; … … 267 216 hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end; 268 217 } 269 218 219 /* Add one generic HID subdriver per device */ 270 220 hid_dev->subdrivers[count].init = usb_generic_hid_init; 271 221 hid_dev->subdrivers[count].poll = usb_generic_hid_polling_callback; 272 hid_dev->subdrivers[count].deinit = NULL;222 hid_dev->subdrivers[count].deinit = usb_generic_hid_deinit; 273 223 hid_dev->subdrivers[count].poll_end = NULL; 274 224 275 225 hid_dev->subdriver_count = count + 1; 276 226 277 227 return EOK; 278 228 } … … 283 233 { 284 234 assert(hid_dev != NULL); 285 235 286 236 const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS]; 287 237 288 238 int i = 0, count = 0; 289 239 const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i]; … … 291 241 bool ids_matched; 292 242 bool matched; 293 243 294 244 while (count < USB_HID_MAX_SUBDRIVERS && 295 245 (mapping->usage_path != NULL … … 306 256 return EINVAL; 307 257 } 308 258 309 259 ids_matched = false; 310 260 matched = false; 311 261 312 262 if (mapping->vendor_id >= 0) { 313 263 assert(mapping->product_id >= 0); … … 320 270 } 321 271 } 322 272 323 273 if (mapping->usage_path != NULL) { 324 274 usb_log_debug("Comparing device against usage path.\n"); … … 331 281 matched = ids_matched; 332 282 } 333 283 334 284 if (matched) { 335 285 usb_log_debug("Subdriver matched.\n"); 336 286 subdrivers[count++] = &mapping->subdriver; 337 287 } 338 288 339 289 mapping = &usb_hid_subdrivers[++i]; 340 290 } 341 342 // we have all subdrivers determined, save them into the hid device 291 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? 343 295 return usb_hid_save_subdrivers(hid_dev, subdrivers, count); 344 296 } … … 346 298 /*----------------------------------------------------------------------------*/ 347 299 348 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev) 349 { 350 assert(hid_dev != NULL && dev != NULL); 351 352 int rc = EOK; 353 300 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, const usb_device_t *dev) 301 { 302 assert(hid_dev); 303 assert(dev); 304 354 305 if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) { 355 306 usb_log_debug("Found keyboard endpoint.\n"); … … 367 318 usb_log_error("None of supported endpoints found - probably" 368 319 " not a supported device.\n"); 369 r c =ENOTSUP;370 } 371 372 return rc;320 return ENOTSUP; 321 } 322 323 return EOK; 373 324 } 374 325 … … 377 328 static int usb_hid_init_report(usb_hid_dev_t *hid_dev) 378 329 { 379 assert(hid_dev != NULL && hid_dev->report != NULL);380 330 assert(hid_dev != NULL); 331 381 332 uint8_t report_id = 0; 382 size_t size;383 384 333 size_t max_size = 0; 385 334 386 335 do { 387 336 usb_log_debug("Getting size of the report.\n"); 388 size = usb_hid_report_byte_size(hid_dev->report, report_id, 389 USB_HID_REPORT_TYPE_INPUT); 337 const size_t size = 338 usb_hid_report_byte_size(&hid_dev->report, report_id, 339 USB_HID_REPORT_TYPE_INPUT); 390 340 usb_log_debug("Report ID: %u, size: %zu\n", report_id, size); 391 341 max_size = (size > max_size) ? size : max_size; 392 342 usb_log_debug("Getting next report ID\n"); 393 report_id = usb_hid_get_next_report_id( hid_dev->report,343 report_id = usb_hid_get_next_report_id(&hid_dev->report, 394 344 report_id, USB_HID_REPORT_TYPE_INPUT); 395 345 } while (report_id != 0); 396 346 397 347 usb_log_debug("Max size of input report: %zu\n", max_size); 398 399 hid_dev->max_input_report_size = max_size; 348 400 349 assert(hid_dev->input_report == NULL); 401 402 hid_dev->input_report = malloc(max_size);350 351 hid_dev->input_report = calloc(1, max_size); 403 352 if (hid_dev->input_report == NULL) { 404 353 return ENOMEM; 405 354 } 406 memset(hid_dev->input_report, 0, max_size);407 355 hid_dev->max_input_report_size = max_size; 356 408 357 return EOK; 409 358 } … … 411 360 /*----------------------------------------------------------------------------*/ 412 361 413 usb_hid_dev_t *usb_hid_new(void)414 {415 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)calloc(1,416 sizeof(usb_hid_dev_t));417 418 if (hid_dev == NULL) {419 usb_log_fatal("No memory!\n");420 return NULL;421 }422 423 hid_dev->report = (usb_hid_report_t *)(malloc(sizeof(424 usb_hid_report_t)));425 if (hid_dev->report == NULL) {426 usb_log_fatal("No memory!\n");427 free(hid_dev);428 return NULL;429 }430 431 hid_dev->poll_pipe_index = -1;432 433 return hid_dev;434 }435 436 /*----------------------------------------------------------------------------*/437 438 362 int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev) 439 363 { 440 364 int rc, i; 441 365 442 366 usb_log_debug("Initializing HID structure...\n"); 443 367 444 368 if (hid_dev == NULL) { 445 369 usb_log_error("Failed to init HID structure: no structure given" … … 447 371 return EINVAL; 448 372 } 449 373 450 374 if (dev == NULL) { 451 375 usb_log_error("Failed to init HID structure: no USB device" … … 453 377 return EINVAL; 454 378 } 455 379 380 usb_hid_report_init(&hid_dev->report); 381 456 382 /* The USB device should already be initialized, save it in structure */ 457 383 hid_dev->usb_dev = dev; 458 384 hid_dev->poll_pipe_index = -1; 385 459 386 rc = usb_hid_check_pipes(hid_dev, dev); 460 387 if (rc != EOK) { 461 388 return rc; 462 389 } 463 390 464 391 /* Get the report descriptor and parse it. */ 465 rc = usb_hid_process_report_descriptor(hid_dev->usb_dev, 466 hid_dev->report, &hid_dev->report_desc, &hid_dev->report_desc_size);467 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 468 395 bool fallback = false; 469 396 470 397 if (rc == EOK) { 471 398 // try to find subdrivers that may want to handle this device … … 484 411 fallback = true; 485 412 } 486 413 487 414 if (fallback) { 488 415 // fall back to boot protocol … … 503 430 break; 504 431 default: 505 assert(hid_dev->poll_pipe_index 432 assert(hid_dev->poll_pipe_index 506 433 == USB_HID_GENERIC_POLL_EP_NO); 507 434 508 435 usb_log_info("Falling back to generic HID driver.\n"); 509 436 rc = usb_hid_set_generic_hid_subdriver(hid_dev); 510 437 } 511 438 } 512 439 513 440 if (rc != EOK) { 514 441 usb_log_error("No subdriver for handling this device could be" 515 442 " initialized: %s.\n", str_error(rc)); 516 usb_log_debug("Subdriver count: %d\n", 443 usb_log_debug("Subdriver count: %d\n", 517 444 hid_dev->subdriver_count); 518 519 445 } else { 520 446 bool ok = false; 521 522 usb_log_debug("Subdriver count: %d\n", 447 448 usb_log_debug("Subdriver count: %d\n", 523 449 hid_dev->subdriver_count); 524 450 525 451 for (i = 0; i < hid_dev->subdriver_count; ++i) { 526 452 if (hid_dev->subdrivers[i].init != NULL) { … … 539 465 } 540 466 } 541 467 542 468 rc = (ok) ? EOK : -1; // what error to report 543 469 } 544 545 470 471 546 472 if (rc == EOK) { 547 473 // save max input report size and allocate space for the report … … 552 478 } 553 479 } 554 555 480 556 481 return rc; 557 482 } … … 559 484 /*----------------------------------------------------------------------------*/ 560 485 561 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer, 486 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer, 562 487 size_t buffer_size, void *arg) 563 488 { 564 int i;565 566 489 if (dev == NULL || arg == NULL || buffer == NULL) { 567 490 usb_log_error("Missing arguments to polling callback.\n"); 568 491 return false; 569 492 } 570 571 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg; 572 493 usb_hid_dev_t *hid_dev = arg; 494 573 495 assert(hid_dev->input_report != NULL); 496 574 497 usb_log_debug("New data [%zu/%zu]: %s\n", buffer_size, 575 498 hid_dev->max_input_report_size, … … 582 505 usb_hid_new_report(hid_dev); 583 506 } 584 585 // parse the input report 586 587 int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size, 588 &hid_dev->report_id); 589 507 508 /* Parse the input report */ 509 const int rc = usb_hid_parse_report( 510 &hid_dev->report, buffer, buffer_size, &hid_dev->report_id); 590 511 if (rc != EOK) { 591 512 usb_log_warning("Error in usb_hid_parse_report():" 592 513 "%s\n", str_error(rc)); 593 } 594 514 } 515 595 516 bool cont = false; 596 597 // continue if at least one of the subdrivers want to continue 598 for (i = 0; i < hid_dev->subdriver_count; ++i) { 599 if (hid_dev->subdrivers[i].poll != NULL 600 && hid_dev->subdrivers[i].poll(hid_dev, 601 hid_dev->subdrivers[i].data)) { 602 cont = true; 603 } 604 } 605 517 /* Continue if at least one of the subdrivers want to continue */ 518 for (int i = 0; i < hid_dev->subdriver_count; ++i) { 519 if (hid_dev->subdrivers[i].poll != NULL) { 520 cont = cont || hid_dev->subdrivers[i].poll( 521 hid_dev, hid_dev->subdrivers[i].data); 522 } 523 } 524 606 525 return cont; 607 526 } … … 609 528 /*----------------------------------------------------------------------------*/ 610 529 611 void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, 612 void *arg) 613 { 614 int i; 615 616 if (dev == NULL || arg == NULL) { 617 return; 618 } 619 620 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg; 621 622 for (i = 0; i < hid_dev->subdriver_count; ++i) { 530 void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, void *arg) 531 { 532 assert(dev); 533 assert(arg); 534 535 usb_hid_dev_t *hid_dev = arg; 536 537 for (int i = 0; i < hid_dev->subdriver_count; ++i) { 623 538 if (hid_dev->subdrivers[i].poll_end != NULL) { 624 hid_dev->subdrivers[i].poll_end( hid_dev,625 hid_dev ->subdrivers[i].data, reason);626 } 627 } 628 629 usb_hid_destroy(hid_dev);539 hid_dev->subdrivers[i].poll_end( 540 hid_dev, hid_dev->subdrivers[i].data, reason); 541 } 542 } 543 544 hid_dev->running = false; 630 545 } 631 546 … … 639 554 /*----------------------------------------------------------------------------*/ 640 555 641 int usb_hid_report_number( usb_hid_dev_t *hid_dev)556 int usb_hid_report_number(const usb_hid_dev_t *hid_dev) 642 557 { 643 558 return hid_dev->report_nr; … … 646 561 /*----------------------------------------------------------------------------*/ 647 562 648 void usb_hid_destroy(usb_hid_dev_t *hid_dev) 649 { 650 int i; 651 652 if (hid_dev == NULL) { 653 return; 654 } 655 563 void usb_hid_deinit(usb_hid_dev_t *hid_dev) 564 { 565 assert(hid_dev); 566 assert(hid_dev->subdrivers != NULL || hid_dev->subdriver_count == 0); 567 568 656 569 usb_log_debug("Subdrivers: %p, subdriver count: %d\n", 657 570 hid_dev->subdrivers, hid_dev->subdriver_count); 658 659 assert(hid_dev->subdrivers != NULL 660 || hid_dev->subdriver_count == 0); 661 662 for (i = 0; i < hid_dev->subdriver_count; ++i) { 571 572 for (int i = 0; i < hid_dev->subdriver_count; ++i) { 663 573 if (hid_dev->subdrivers[i].deinit != NULL) { 664 574 hid_dev->subdrivers[i].deinit(hid_dev, … … 666 576 } 667 577 } 668 669 // free the subdrivers info 670 if (hid_dev->subdrivers != NULL) { 671 free(hid_dev->subdrivers); 672 } 673 674 // destroy the parser 675 if (hid_dev->report != NULL) { 676 usb_hid_free_report(hid_dev->report); 677 } 678 679 if (hid_dev->report_desc != NULL) { 680 free(hid_dev->report_desc); 681 } 578 579 /* Free allocated structures */ 580 free(hid_dev->subdrivers); 581 free(hid_dev->report_desc); 582 583 /* Destroy the parser */ 584 usb_hid_report_deinit(&hid_dev->report); 585 682 586 } 683 587
Note:
See TracChangeset
for help on using the changeset viewer.