00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00037 #include <usb/debug.h>
00038 #include <usb/classes/classes.h>
00039 #include <usb/hid/hid.h>
00040 #include <usb/hid/hidparser.h>
00041 #include <usb/hid/hidreport.h>
00042 #include <usb/hid/request.h>
00043 #include <errno.h>
00044 #include <str_error.h>
00045
00046 #include "usbhid.h"
00047
00048 #include "kbd/kbddev.h"
00049 #include "generic/hiddev.h"
00050 #include "mouse/mousedev.h"
00051 #include "subdrivers.h"
00052
00053
00054
00055
00056 usb_endpoint_description_t *usb_hid_endpoints[USB_HID_POLL_EP_COUNT + 1] = {
00057 &usb_hid_kbd_poll_endpoint_description,
00058 &usb_hid_mouse_poll_endpoint_description,
00059 &usb_hid_generic_poll_endpoint_description,
00060 NULL
00061 };
00062
00063 static const int USB_HID_MAX_SUBDRIVERS = 10;
00064
00065
00066
00067 static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
00068 {
00069 assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
00070
00071 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
00072 sizeof(usb_hid_subdriver_t));
00073 if (hid_dev->subdrivers == NULL) {
00074 return ENOMEM;
00075 }
00076
00077 assert(hid_dev->subdriver_count >= 0);
00078
00079
00080 hid_dev->subdrivers[hid_dev->subdriver_count].init = usb_kbd_init;
00081
00082
00083 hid_dev->subdrivers[hid_dev->subdriver_count].poll =
00084 usb_kbd_polling_callback;
00085
00086
00087 hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
00088
00089
00090 hid_dev->subdrivers[hid_dev->subdriver_count].deinit = usb_kbd_deinit;
00091
00092
00093 ++hid_dev->subdriver_count;
00094
00095 return EOK;
00096 }
00097
00098
00099
00100 static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
00101 {
00102 assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
00103
00104 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
00105 sizeof(usb_hid_subdriver_t));
00106 if (hid_dev->subdrivers == NULL) {
00107 return ENOMEM;
00108 }
00109
00110 assert(hid_dev->subdriver_count >= 0);
00111
00112
00113 hid_dev->subdrivers[hid_dev->subdriver_count].init = usb_mouse_init;
00114
00115
00116 hid_dev->subdrivers[hid_dev->subdriver_count].poll =
00117 usb_mouse_polling_callback;
00118
00119
00120 hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
00121
00122
00123 hid_dev->subdrivers[hid_dev->subdriver_count].deinit = usb_mouse_deinit;
00124
00125
00126 ++hid_dev->subdriver_count;
00127
00128 return EOK;
00129 }
00130
00131
00132
00133 static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
00134 {
00135 assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
00136
00137 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
00138 sizeof(usb_hid_subdriver_t));
00139 if (hid_dev->subdrivers == NULL) {
00140 return ENOMEM;
00141 }
00142
00143 assert(hid_dev->subdriver_count >= 0);
00144
00145
00146 hid_dev->subdrivers[hid_dev->subdriver_count].init =
00147 usb_generic_hid_init;
00148
00149
00150 hid_dev->subdrivers[hid_dev->subdriver_count].poll =
00151 usb_generic_hid_polling_callback;
00152
00153
00154 hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
00155
00156
00157 hid_dev->subdrivers[hid_dev->subdriver_count].deinit = NULL;
00158
00159
00160 ++hid_dev->subdriver_count;
00161
00162 return EOK;
00163 }
00164
00165
00166
00167 static bool usb_hid_ids_match(usb_hid_dev_t *hid_dev,
00168 const usb_hid_subdriver_mapping_t *mapping)
00169 {
00170 assert(hid_dev != NULL);
00171 assert(hid_dev->usb_dev != NULL);
00172
00173 return (hid_dev->usb_dev->descriptors.device.vendor_id
00174 == mapping->vendor_id
00175 && hid_dev->usb_dev->descriptors.device.product_id
00176 == mapping->product_id);
00177 }
00178
00179
00180
00181 static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev,
00182 const usb_hid_subdriver_mapping_t *mapping)
00183 {
00184 assert(hid_dev != NULL);
00185 assert(mapping != NULL);
00186
00187 usb_hid_report_path_t *usage_path = usb_hid_report_path();
00188 if (usage_path == NULL) {
00189 usb_log_debug("Failed to create usage path.\n");
00190 return false;
00191 }
00192 int i = 0;
00193 while (mapping->usage_path[i].usage != 0
00194 || mapping->usage_path[i].usage_page != 0) {
00195 if (usb_hid_report_path_append_item(usage_path,
00196 mapping->usage_path[i].usage_page,
00197 mapping->usage_path[i].usage) != EOK) {
00198 usb_log_debug("Failed to append to usage path.\n");
00199 usb_hid_report_path_free(usage_path);
00200 return false;
00201 }
00202 ++i;
00203 }
00204
00205 assert(hid_dev->report != NULL);
00206
00207 usb_log_debug("Compare flags: %d\n", mapping->compare);
00208
00209 bool matches = false;
00210 uint8_t report_id = mapping->report_id;
00211
00212 do {
00213 usb_log_debug("Trying report id %u\n", report_id);
00214
00215 if (report_id != 0) {
00216 usb_hid_report_path_set_report_id(usage_path,
00217 report_id);
00218 }
00219
00220 usb_hid_report_field_t *field = usb_hid_report_get_sibling(
00221 hid_dev->report,
00222 NULL, usage_path, mapping->compare,
00223 USB_HID_REPORT_TYPE_INPUT);
00224
00225 usb_log_debug("Field: %p\n", field);
00226
00227 if (field != NULL) {
00228 matches = true;
00229 break;
00230 }
00231
00232 report_id = usb_hid_get_next_report_id(
00233 hid_dev->report, report_id,
00234 USB_HID_REPORT_TYPE_INPUT);
00235 } while (!matches && report_id != 0);
00236
00237 usb_hid_report_path_free(usage_path);
00238
00239 return matches;
00240 }
00241
00242
00243
00244 static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev,
00245 const usb_hid_subdriver_t **subdrivers, int count)
00246 {
00247 int i;
00248
00249 if (count <= 0) {
00250 hid_dev->subdriver_count = 0;
00251 hid_dev->subdrivers = NULL;
00252 return EOK;
00253 }
00254
00255
00256
00257 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc((count + 1) *
00258 sizeof(usb_hid_subdriver_t));
00259 if (hid_dev->subdrivers == NULL) {
00260 return ENOMEM;
00261 }
00262
00263 for (i = 0; i < count; ++i) {
00264 hid_dev->subdrivers[i].init = subdrivers[i]->init;
00265 hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit;
00266 hid_dev->subdrivers[i].poll = subdrivers[i]->poll;
00267 hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end;
00268 }
00269
00270 hid_dev->subdrivers[count].init = usb_generic_hid_init;
00271 hid_dev->subdrivers[count].poll = usb_generic_hid_polling_callback;
00272 hid_dev->subdrivers[count].deinit = NULL;
00273 hid_dev->subdrivers[count].poll_end = NULL;
00274
00275 hid_dev->subdriver_count = count + 1;
00276
00277 return EOK;
00278 }
00279
00280
00281
00282 static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
00283 {
00284 assert(hid_dev != NULL);
00285
00286 const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
00287
00288 int i = 0, count = 0;
00289 const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i];
00290
00291 bool ids_matched;
00292 bool matched;
00293
00294 while (count < USB_HID_MAX_SUBDRIVERS &&
00295 (mapping->usage_path != NULL
00296 || mapping->vendor_id >= 0 || mapping->product_id >= 0)) {
00297
00298 if (mapping->vendor_id >= 0 && mapping->product_id < 0) {
00299 usb_log_warning("Missing Product ID for Vendor ID %d\n",
00300 mapping->vendor_id);
00301 return EINVAL;
00302 }
00303 if (mapping->product_id >= 0 && mapping->vendor_id < 0) {
00304 usb_log_warning("Missing Vendor ID for Product ID %d\n",
00305 mapping->product_id);
00306 return EINVAL;
00307 }
00308
00309 ids_matched = false;
00310 matched = false;
00311
00312 if (mapping->vendor_id >= 0) {
00313 assert(mapping->product_id >= 0);
00314 usb_log_debug("Comparing device against vendor ID %u"
00315 " and product ID %u.\n", mapping->vendor_id,
00316 mapping->product_id);
00317 if (usb_hid_ids_match(hid_dev, mapping)) {
00318 usb_log_debug("IDs matched.\n");
00319 ids_matched = true;
00320 }
00321 }
00322
00323 if (mapping->usage_path != NULL) {
00324 usb_log_debug("Comparing device against usage path.\n");
00325 if (usb_hid_path_matches(hid_dev, mapping)) {
00326
00327 matched = true;
00328 }
00329 } else {
00330
00331 matched = ids_matched;
00332 }
00333
00334 if (matched) {
00335 usb_log_debug("Subdriver matched.\n");
00336 subdrivers[count++] = &mapping->subdriver;
00337 }
00338
00339 mapping = &usb_hid_subdrivers[++i];
00340 }
00341
00342
00343 return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
00344 }
00345
00346
00347
00348 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
00349 {
00350 assert(hid_dev != NULL && dev != NULL);
00351
00352 int rc = EOK;
00353
00354 if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
00355 usb_log_debug("Found keyboard endpoint.\n");
00356
00357 hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
00358 } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
00359 usb_log_debug("Found mouse endpoint.\n");
00360
00361 hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
00362 } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
00363 usb_log_debug("Found generic HID endpoint.\n");
00364
00365 hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
00366 } else {
00367 usb_log_error("None of supported endpoints found - probably"
00368 " not a supported device.\n");
00369 rc = ENOTSUP;
00370 }
00371
00372 return rc;
00373 }
00374
00375
00376
00377 static int usb_hid_init_report(usb_hid_dev_t *hid_dev)
00378 {
00379 assert(hid_dev != NULL && hid_dev->report != NULL);
00380
00381 uint8_t report_id = 0;
00382 size_t size;
00383
00384 size_t max_size = 0;
00385
00386 do {
00387 usb_log_debug("Getting size of the report.\n");
00388 size = usb_hid_report_byte_size(hid_dev->report, report_id,
00389 USB_HID_REPORT_TYPE_INPUT);
00390 usb_log_debug("Report ID: %u, size: %zu\n", report_id, size);
00391 max_size = (size > max_size) ? size : max_size;
00392 usb_log_debug("Getting next report ID\n");
00393 report_id = usb_hid_get_next_report_id(hid_dev->report,
00394 report_id, USB_HID_REPORT_TYPE_INPUT);
00395 } while (report_id != 0);
00396
00397 usb_log_debug("Max size of input report: %zu\n", max_size);
00398
00399 hid_dev->max_input_report_size = max_size;
00400 assert(hid_dev->input_report == NULL);
00401
00402 hid_dev->input_report = malloc(max_size);
00403 if (hid_dev->input_report == NULL) {
00404 return ENOMEM;
00405 }
00406 memset(hid_dev->input_report, 0, max_size);
00407
00408 return EOK;
00409 }
00410
00411
00412
00413 usb_hid_dev_t *usb_hid_new(void)
00414 {
00415 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)calloc(1,
00416 sizeof(usb_hid_dev_t));
00417
00418 if (hid_dev == NULL) {
00419 usb_log_fatal("No memory!\n");
00420 return NULL;
00421 }
00422
00423 hid_dev->report = (usb_hid_report_t *)(malloc(sizeof(
00424 usb_hid_report_t)));
00425 if (hid_dev->report == NULL) {
00426 usb_log_fatal("No memory!\n");
00427 free(hid_dev);
00428 return NULL;
00429 }
00430
00431 hid_dev->poll_pipe_index = -1;
00432
00433 return hid_dev;
00434 }
00435
00436
00437
00438 int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
00439 {
00440 int rc, i;
00441
00442 usb_log_debug("Initializing HID structure...\n");
00443
00444 if (hid_dev == NULL) {
00445 usb_log_error("Failed to init HID structure: no structure given"
00446 ".\n");
00447 return EINVAL;
00448 }
00449
00450 if (dev == NULL) {
00451 usb_log_error("Failed to init HID structure: no USB device"
00452 " given.\n");
00453 return EINVAL;
00454 }
00455
00456
00457 hid_dev->usb_dev = dev;
00458
00459 rc = usb_hid_check_pipes(hid_dev, dev);
00460 if (rc != EOK) {
00461 return rc;
00462 }
00463
00464
00465 rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
00466 hid_dev->report, &hid_dev->report_desc, &hid_dev->report_desc_size);
00467
00468 bool fallback = false;
00469
00470 if (rc == EOK) {
00471
00472 rc = usb_hid_find_subdrivers(hid_dev);
00473 if (rc != EOK || hid_dev->subdriver_count == 0) {
00474
00475 usb_log_info("No subdrivers found to handle this"
00476 " device.\n");
00477 fallback = true;
00478 assert(hid_dev->subdrivers == NULL);
00479 assert(hid_dev->subdriver_count == 0);
00480 }
00481 } else {
00482 usb_log_error("Failed to parse Report descriptor.\n");
00483
00484 fallback = true;
00485 }
00486
00487 if (fallback) {
00488
00489 switch (hid_dev->poll_pipe_index) {
00490 case USB_HID_KBD_POLL_EP_NO:
00491 usb_log_info("Falling back to kbd boot protocol.\n");
00492 rc = usb_kbd_set_boot_protocol(hid_dev);
00493 if (rc == EOK) {
00494 rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
00495 }
00496 break;
00497 case USB_HID_MOUSE_POLL_EP_NO:
00498 usb_log_info("Falling back to mouse boot protocol.\n");
00499 rc = usb_mouse_set_boot_protocol(hid_dev);
00500 if (rc == EOK) {
00501 rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
00502 }
00503 break;
00504 default:
00505 assert(hid_dev->poll_pipe_index
00506 == USB_HID_GENERIC_POLL_EP_NO);
00507
00508 usb_log_info("Falling back to generic HID driver.\n");
00509 rc = usb_hid_set_generic_hid_subdriver(hid_dev);
00510 }
00511 }
00512
00513 if (rc != EOK) {
00514 usb_log_error("No subdriver for handling this device could be"
00515 " initialized: %s.\n", str_error(rc));
00516 usb_log_debug("Subdriver count: %d\n",
00517 hid_dev->subdriver_count);
00518
00519 } else {
00520 bool ok = false;
00521
00522 usb_log_debug("Subdriver count: %d\n",
00523 hid_dev->subdriver_count);
00524
00525 for (i = 0; i < hid_dev->subdriver_count; ++i) {
00526 if (hid_dev->subdrivers[i].init != NULL) {
00527 usb_log_debug("Initializing subdriver %d.\n",i);
00528 rc = hid_dev->subdrivers[i].init(hid_dev,
00529 &hid_dev->subdrivers[i].data);
00530 if (rc != EOK) {
00531 usb_log_warning("Failed to initialize"
00532 " HID subdriver structure.\n");
00533 } else {
00534
00535 ok = true;
00536 }
00537 } else {
00538 ok = true;
00539 }
00540 }
00541
00542 rc = (ok) ? EOK : -1;
00543 }
00544
00545
00546 if (rc == EOK) {
00547
00548 rc = usb_hid_init_report(hid_dev);
00549 if (rc != EOK) {
00550 usb_log_error("Failed to initialize input report buffer"
00551 ".\n");
00552 }
00553 }
00554
00555
00556 return rc;
00557 }
00558
00559
00560
00561 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
00562 size_t buffer_size, void *arg)
00563 {
00564 int i;
00565
00566 if (dev == NULL || arg == NULL || buffer == NULL) {
00567 usb_log_error("Missing arguments to polling callback.\n");
00568 return false;
00569 }
00570
00571 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
00572
00573 assert(hid_dev->input_report != NULL);
00574 usb_log_debug("Max input report size: %zu, buffer size: %zu\n",
00575 hid_dev->max_input_report_size, buffer_size);
00576
00577 if (hid_dev->max_input_report_size >= buffer_size) {
00579 memcpy(hid_dev->input_report, buffer, buffer_size);
00580 hid_dev->input_report_size = buffer_size;
00581 usb_hid_new_report(hid_dev);
00582 }
00583
00584
00585
00586 int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size,
00587 &hid_dev->report_id);
00588
00589 if (rc != EOK) {
00590 usb_log_warning("Error in usb_hid_parse_report():"
00591 "%s\n", str_error(rc));
00592 }
00593
00594 bool cont = false;
00595
00596
00597 for (i = 0; i < hid_dev->subdriver_count; ++i) {
00598 if (hid_dev->subdrivers[i].poll != NULL
00599 && hid_dev->subdrivers[i].poll(hid_dev,
00600 hid_dev->subdrivers[i].data)) {
00601 cont = true;
00602 }
00603 }
00604
00605 return cont;
00606 }
00607
00608
00609
00610 void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason,
00611 void *arg)
00612 {
00613 int i;
00614
00615 if (dev == NULL || arg == NULL) {
00616 return;
00617 }
00618
00619 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
00620
00621 for (i = 0; i < hid_dev->subdriver_count; ++i) {
00622 if (hid_dev->subdrivers[i].poll_end != NULL) {
00623 hid_dev->subdrivers[i].poll_end(hid_dev,
00624 hid_dev->subdrivers[i].data, reason);
00625 }
00626 }
00627
00628 usb_hid_free(&hid_dev);
00629 }
00630
00631
00632
00633 void usb_hid_new_report(usb_hid_dev_t *hid_dev)
00634 {
00635 ++hid_dev->report_nr;
00636 }
00637
00638
00639
00640 int usb_hid_report_number(usb_hid_dev_t *hid_dev)
00641 {
00642 return hid_dev->report_nr;
00643 }
00644
00645
00646
00647 void usb_hid_free(usb_hid_dev_t **hid_dev)
00648 {
00649 int i;
00650
00651 if (hid_dev == NULL || *hid_dev == NULL) {
00652 return;
00653 }
00654
00655 usb_log_debug("Subdrivers: %p, subdriver count: %d\n",
00656 (*hid_dev)->subdrivers, (*hid_dev)->subdriver_count);
00657
00658 assert((*hid_dev)->subdrivers != NULL
00659 || (*hid_dev)->subdriver_count == 0);
00660
00661 for (i = 0; i < (*hid_dev)->subdriver_count; ++i) {
00662 if ((*hid_dev)->subdrivers[i].deinit != NULL) {
00663 (*hid_dev)->subdrivers[i].deinit(*hid_dev,
00664 (*hid_dev)->subdrivers[i].data);
00665 }
00666 }
00667
00668
00669 if ((*hid_dev)->subdrivers != NULL) {
00670 free((*hid_dev)->subdrivers);
00671 }
00672
00673
00674 if ((*hid_dev)->report != NULL) {
00675 usb_hid_free_report((*hid_dev)->report);
00676 }
00677
00678 if ((*hid_dev)->report_desc != NULL) {
00679 free((*hid_dev)->report_desc);
00680 }
00681
00682 free(*hid_dev);
00683 *hid_dev = NULL;
00684 }
00685