source: mainline/uspace/drv/bus/usb/usbhid/usbhid.c@ 408d3c9

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 408d3c9 was 5203e256, checked in by Martin Decky <martin@…>, 14 years ago

keep the drivers source tree tidy by using logical subdirectories

  • Property mode set to 100644
File size: 18.2 KB
RevLine 
[966acede]1/*
2 * Copyright (c) 2011 Lubos Slovak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup drvusbhid
30 * @{
31 */
32/**
33 * @file
34 * USB HID driver API.
35 */
36
37#include <usb/debug.h>
38#include <usb/classes/classes.h>
[faa44e58]39#include <usb/hid/hid.h>
40#include <usb/hid/hidparser.h>
41#include <usb/hid/hidreport.h>
42#include <usb/hid/request.h>
[61257f4]43#include <errno.h>
[f76153ce]44#include <str_error.h>
[966acede]45
46#include "usbhid.h"
47
[61257f4]48#include "kbd/kbddev.h"
[dd10e07]49#include "generic/hiddev.h"
[e9f0348]50#include "mouse/mousedev.h"
[62bd8d3]51#include "subdrivers.h"
[61257f4]52
[966acede]53/*----------------------------------------------------------------------------*/
54
55/* Array of endpoints expected on the device, NULL terminated. */
[fec47d4]56usb_endpoint_description_t *usb_hid_endpoints[USB_HID_POLL_EP_COUNT + 1] = {
57 &usb_hid_kbd_poll_endpoint_description,
58 &usb_hid_mouse_poll_endpoint_description,
[61257f4]59 &usb_hid_generic_poll_endpoint_description,
[966acede]60 NULL
61};
62
[f76153ce]63static const int USB_HID_MAX_SUBDRIVERS = 10;
64
[966acede]65/*----------------------------------------------------------------------------*/
66
[60c0573]67static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
[61257f4]68{
[e7df6cd]69 assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
[61257f4]70
[60c0573]71 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
72 sizeof(usb_hid_subdriver_t));
73 if (hid_dev->subdrivers == NULL) {
74 return ENOMEM;
[61257f4]75 }
76
[2002595]77 assert(hid_dev->subdriver_count >= 0);
78
[60c0573]79 // set the init callback
[2002595]80 hid_dev->subdrivers[hid_dev->subdriver_count].init = usb_kbd_init;
[60c0573]81
82 // set the polling callback
[2002595]83 hid_dev->subdrivers[hid_dev->subdriver_count].poll =
84 usb_kbd_polling_callback;
[60c0573]85
86 // set the polling ended callback
[2002595]87 hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
[60c0573]88
89 // set the deinit callback
[2002595]90 hid_dev->subdrivers[hid_dev->subdriver_count].deinit = usb_kbd_deinit;
[60c0573]91
92 // set subdriver count
[2002595]93 ++hid_dev->subdriver_count;
[60c0573]94
95 return EOK;
96}
97
98/*----------------------------------------------------------------------------*/
99
100static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
101{
[e7df6cd]102 assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
[60c0573]103
104 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
105 sizeof(usb_hid_subdriver_t));
106 if (hid_dev->subdrivers == NULL) {
107 return ENOMEM;
[61257f4]108 }
109
[2002595]110 assert(hid_dev->subdriver_count >= 0);
111
[60c0573]112 // set the init callback
[2002595]113 hid_dev->subdrivers[hid_dev->subdriver_count].init = usb_mouse_init;
[60c0573]114
115 // set the polling callback
[2002595]116 hid_dev->subdrivers[hid_dev->subdriver_count].poll =
117 usb_mouse_polling_callback;
[60c0573]118
119 // set the polling ended callback
[2002595]120 hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
[60c0573]121
122 // set the deinit callback
[2002595]123 hid_dev->subdrivers[hid_dev->subdriver_count].deinit = usb_mouse_deinit;
[60c0573]124
125 // set subdriver count
[2002595]126 ++hid_dev->subdriver_count;
[60c0573]127
128 return EOK;
129}
130
131/*----------------------------------------------------------------------------*/
132
133static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
134{
[e7df6cd]135 assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
[60c0573]136
137 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
138 sizeof(usb_hid_subdriver_t));
139 if (hid_dev->subdrivers == NULL) {
140 return ENOMEM;
141 }
142
[2002595]143 assert(hid_dev->subdriver_count >= 0);
144
[60c0573]145 // set the init callback
[2002595]146 hid_dev->subdrivers[hid_dev->subdriver_count].init =
147 usb_generic_hid_init;
[60c0573]148
149 // set the polling callback
[2002595]150 hid_dev->subdrivers[hid_dev->subdriver_count].poll =
151 usb_generic_hid_polling_callback;
[60c0573]152
153 // set the polling ended callback
[2002595]154 hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
[60c0573]155
156 // set the deinit callback
[2002595]157 hid_dev->subdrivers[hid_dev->subdriver_count].deinit = NULL;
[60c0573]158
[f76153ce]159 // set subdriver count
[2002595]160 ++hid_dev->subdriver_count;
[f76153ce]161
[60c0573]162 return EOK;
163}
164
165/*----------------------------------------------------------------------------*/
166
[f76153ce]167static bool usb_hid_ids_match(usb_hid_dev_t *hid_dev,
168 const usb_hid_subdriver_mapping_t *mapping)
169{
[36f737a]170 assert(hid_dev != NULL);
171 assert(hid_dev->usb_dev != NULL);
172
173 return (hid_dev->usb_dev->descriptors.device.vendor_id
174 == mapping->vendor_id
175 && hid_dev->usb_dev->descriptors.device.product_id
176 == mapping->product_id);
[f76153ce]177}
178
179/*----------------------------------------------------------------------------*/
180
181static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev,
[e3b5129]182 const usb_hid_subdriver_mapping_t *mapping)
[f76153ce]183{
184 assert(hid_dev != NULL);
[e3b5129]185 assert(mapping != NULL);
[f76153ce]186
187 usb_hid_report_path_t *usage_path = usb_hid_report_path();
188 if (usage_path == NULL) {
[1cbb4b7]189 usb_log_debug("Failed to create usage path.\n");
[f76153ce]190 return false;
191 }
[777e336]192 int i = 0;
[e3b5129]193 while (mapping->usage_path[i].usage != 0
194 || mapping->usage_path[i].usage_page != 0) {
[f76153ce]195 if (usb_hid_report_path_append_item(usage_path,
[e3b5129]196 mapping->usage_path[i].usage_page,
197 mapping->usage_path[i].usage) != EOK) {
[1cbb4b7]198 usb_log_debug("Failed to append to usage path.\n");
[f76153ce]199 usb_hid_report_path_free(usage_path);
200 return false;
201 }
[777e336]202 ++i;
[f76153ce]203 }
204
[e60436b]205 assert(hid_dev->report != NULL);
[1cbb4b7]206
[e3b5129]207 usb_log_debug("Compare flags: %d\n", mapping->compare);
[f3f9733]208
209 bool matches = false;
210 uint8_t report_id = mapping->report_id;
[dcb7d7cd]211
[19e0560e]212 do {
[f3f9733]213 usb_log_debug("Trying report id %u\n", report_id);
214
215 if (report_id != 0) {
[dcb7d7cd]216 usb_hid_report_path_set_report_id(usage_path,
[f3f9733]217 report_id);
[dcb7d7cd]218 }
219
[f3f9733]220 usb_hid_report_field_t *field = usb_hid_report_get_sibling(
221 hid_dev->report,
222 NULL, usage_path, mapping->compare,
223 USB_HID_REPORT_TYPE_INPUT);
224
225 usb_log_debug("Field: %p\n", field);
[dcb7d7cd]226
[f3f9733]227 if (field != NULL) {
228 matches = true;
229 break;
[dcb7d7cd]230 }
[f3f9733]231
232 report_id = usb_hid_get_next_report_id(
233 hid_dev->report, report_id,
234 USB_HID_REPORT_TYPE_INPUT);
235 } while (!matches && report_id != 0);
236
[f76153ce]237 usb_hid_report_path_free(usage_path);
238
[f3f9733]239 return matches;
[f76153ce]240}
241
242/*----------------------------------------------------------------------------*/
243
244static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev,
245 const usb_hid_subdriver_t **subdrivers, int count)
[60c0573]246{
[f76153ce]247 int i;
248
249 if (count <= 0) {
250 hid_dev->subdriver_count = 0;
251 hid_dev->subdrivers = NULL;
252 return EOK;
253 }
254
[78bfae9]255 // add one generic HID subdriver per device
256
257 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc((count + 1) *
[f76153ce]258 sizeof(usb_hid_subdriver_t));
259 if (hid_dev->subdrivers == NULL) {
260 return ENOMEM;
261 }
262
263 for (i = 0; i < count; ++i) {
264 hid_dev->subdrivers[i].init = subdrivers[i]->init;
265 hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit;
266 hid_dev->subdrivers[i].poll = subdrivers[i]->poll;
267 hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end;
268 }
269
[78bfae9]270 hid_dev->subdrivers[count].init = usb_generic_hid_init;
271 hid_dev->subdrivers[count].poll = usb_generic_hid_polling_callback;
272 hid_dev->subdrivers[count].deinit = NULL;
273 hid_dev->subdrivers[count].poll_end = NULL;
274
275 hid_dev->subdriver_count = count + 1;
[f76153ce]276
[60c0573]277 return EOK;
[61257f4]278}
[966acede]279
280/*----------------------------------------------------------------------------*/
281
[f76153ce]282static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
283{
[e7df6cd]284 assert(hid_dev != NULL);
285
[f76153ce]286 const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
287
288 int i = 0, count = 0;
289 const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i];
[4bb9fd2]290
291 bool ids_matched;
292 bool matched;
[f76153ce]293
294 while (count < USB_HID_MAX_SUBDRIVERS &&
295 (mapping->usage_path != NULL
[d0a6e54]296 || mapping->vendor_id >= 0 || mapping->product_id >= 0)) {
[f76153ce]297 // check the vendor & product ID
[d0a6e54]298 if (mapping->vendor_id >= 0 && mapping->product_id < 0) {
299 usb_log_warning("Missing Product ID for Vendor ID %d\n",
[f76153ce]300 mapping->vendor_id);
301 return EINVAL;
302 }
[d0a6e54]303 if (mapping->product_id >= 0 && mapping->vendor_id < 0) {
304 usb_log_warning("Missing Vendor ID for Product ID %d\n",
[f76153ce]305 mapping->product_id);
306 return EINVAL;
307 }
308
[4bb9fd2]309 ids_matched = false;
310 matched = false;
311
[d0a6e54]312 if (mapping->vendor_id >= 0) {
313 assert(mapping->product_id >= 0);
[777e336]314 usb_log_debug("Comparing device against vendor ID %u"
315 " and product ID %u.\n", mapping->vendor_id,
[f76153ce]316 mapping->product_id);
317 if (usb_hid_ids_match(hid_dev, mapping)) {
[4bb9fd2]318 usb_log_debug("IDs matched.\n");
319 ids_matched = true;
[f76153ce]320 }
321 }
322
323 if (mapping->usage_path != NULL) {
[1cbb4b7]324 usb_log_debug("Comparing device against usage path.\n");
[e3b5129]325 if (usb_hid_path_matches(hid_dev, mapping)) {
[4bb9fd2]326 // does not matter if IDs were matched
327 matched = true;
[f76153ce]328 }
[4bb9fd2]329 } else {
330 // matched only if IDs were matched and there is no path
331 matched = ids_matched;
[f76153ce]332 }
[4bb9fd2]333
334 if (matched) {
[d1fb591]335 usb_log_debug("Subdriver matched.\n");
[4bb9fd2]336 subdrivers[count++] = &mapping->subdriver;
[f76153ce]337 }
[4bb9fd2]338
[f76153ce]339 mapping = &usb_hid_subdrivers[++i];
340 }
341
342 // we have all subdrivers determined, save them into the hid device
343 return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
344}
345
346/*----------------------------------------------------------------------------*/
347
[61257f4]348static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
[966acede]349{
[e7df6cd]350 assert(hid_dev != NULL && dev != NULL);
351
[f76153ce]352 int rc = EOK;
[60c0573]353
[61257f4]354 if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
355 usb_log_debug("Found keyboard endpoint.\n");
[60c0573]356 // save the pipe index
[61257f4]357 hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
358 } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
359 usb_log_debug("Found mouse endpoint.\n");
[60c0573]360 // save the pipe index
[61257f4]361 hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
362 } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
363 usb_log_debug("Found generic HID endpoint.\n");
[60c0573]364 // save the pipe index
[61257f4]365 hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
366 } else {
[60c0573]367 usb_log_error("None of supported endpoints found - probably"
[61257f4]368 " not a supported device.\n");
[60c0573]369 rc = ENOTSUP;
[61257f4]370 }
371
[60c0573]372 return rc;
[61257f4]373}
374
375/*----------------------------------------------------------------------------*/
376
[d1fb591]377static int usb_hid_init_report(usb_hid_dev_t *hid_dev)
378{
379 assert(hid_dev != NULL && hid_dev->report != NULL);
380
381 uint8_t report_id = 0;
[19e0560e]382 size_t size;
[d1fb591]383
384 size_t max_size = 0;
385
[a9cdca0]386 do {
[2002595]387 usb_log_debug("Getting size of the report.\n");
[a9cdca0]388 size = usb_hid_report_byte_size(hid_dev->report, report_id,
[d1fb591]389 USB_HID_REPORT_TYPE_INPUT);
[8fb45e08]390 usb_log_debug("Report ID: %u, size: %zu\n", report_id, size);
391 max_size = (size > max_size) ? size : max_size;
[2002595]392 usb_log_debug("Getting next report ID\n");
[a9cdca0]393 report_id = usb_hid_get_next_report_id(hid_dev->report,
394 report_id, USB_HID_REPORT_TYPE_INPUT);
395 } while (report_id != 0);
[d1fb591]396
397 usb_log_debug("Max size of input report: %zu\n", max_size);
398
399 hid_dev->max_input_report_size = max_size;
400 assert(hid_dev->input_report == NULL);
401
402 hid_dev->input_report = malloc(max_size);
403 if (hid_dev->input_report == NULL) {
404 return ENOMEM;
405 }
406 memset(hid_dev->input_report, 0, max_size);
407
408 return EOK;
409}
410
411/*----------------------------------------------------------------------------*/
412
[60c0573]413usb_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
[e60436b]423 hid_dev->report = (usb_hid_report_t *)(malloc(sizeof(
[e50cd7f]424 usb_hid_report_t)));
[e60436b]425 if (hid_dev->report == NULL) {
[60c0573]426 usb_log_fatal("No memory!\n");
427 free(hid_dev);
428 return NULL;
429 }
430
[f76153ce]431 hid_dev->poll_pipe_index = -1;
432
[60c0573]433 return hid_dev;
434}
435
436/*----------------------------------------------------------------------------*/
437
[61257f4]438int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
439{
[60c0573]440 int rc, i;
[61257f4]441
442 usb_log_debug("Initializing HID structure...\n");
443
444 if (hid_dev == NULL) {
445 usb_log_error("Failed to init HID structure: no structure given"
446 ".\n");
447 return EINVAL;
448 }
449
450 if (dev == NULL) {
451 usb_log_error("Failed to init HID structure: no USB device"
452 " given.\n");
453 return EINVAL;
454 }
455
456 /* The USB device should already be initialized, save it in structure */
457 hid_dev->usb_dev = dev;
458
459 rc = usb_hid_check_pipes(hid_dev, dev);
460 if (rc != EOK) {
461 return rc;
462 }
[e50cd7f]463
[f76153ce]464 /* Get the report descriptor and parse it. */
465 rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
[fa8d346]466 hid_dev->report, &hid_dev->report_desc, &hid_dev->report_desc_size);
[f76153ce]467
468 bool fallback = false;
469
470 if (rc == EOK) {
471 // try to find subdrivers that may want to handle this device
472 rc = usb_hid_find_subdrivers(hid_dev);
473 if (rc != EOK || hid_dev->subdriver_count == 0) {
474 // try to fall back to the boot protocol if available
475 usb_log_info("No subdrivers found to handle this"
476 " device.\n");
477 fallback = true;
[aaf6155]478 assert(hid_dev->subdrivers == NULL);
479 assert(hid_dev->subdriver_count == 0);
[f76153ce]480 }
481 } else {
482 usb_log_error("Failed to parse Report descriptor.\n");
483 // try to fall back to the boot protocol if available
484 fallback = true;
485 }
486
[7bb8036]487 if (fallback) {
[f76153ce]488 // fall back to boot protocol
489 switch (hid_dev->poll_pipe_index) {
490 case USB_HID_KBD_POLL_EP_NO:
491 usb_log_info("Falling back to kbd boot protocol.\n");
492 rc = usb_kbd_set_boot_protocol(hid_dev);
493 if (rc == EOK) {
494 rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
[60c0573]495 }
[f76153ce]496 break;
497 case USB_HID_MOUSE_POLL_EP_NO:
498 usb_log_info("Falling back to mouse boot protocol.\n");
499 rc = usb_mouse_set_boot_protocol(hid_dev);
500 if (rc == EOK) {
501 rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
502 }
503 break;
504 default:
505 assert(hid_dev->poll_pipe_index
506 == USB_HID_GENERIC_POLL_EP_NO);
507
508 usb_log_info("Falling back to generic HID driver.\n");
509 rc = usb_hid_set_generic_hid_subdriver(hid_dev);
[e9f0348]510 }
[61257f4]511 }
512
[f76153ce]513 if (rc != EOK) {
514 usb_log_error("No subdriver for handling this device could be"
515 " initialized: %s.\n", str_error(rc));
[aaf6155]516 usb_log_debug("Subdriver count: %d\n",
517 hid_dev->subdriver_count);
[2002595]518
[f76153ce]519 } else {
520 bool ok = false;
521
522 usb_log_debug("Subdriver count: %d\n",
523 hid_dev->subdriver_count);
524
525 for (i = 0; i < hid_dev->subdriver_count; ++i) {
526 if (hid_dev->subdrivers[i].init != NULL) {
527 usb_log_debug("Initializing subdriver %d.\n",i);
[65b458c4]528 rc = hid_dev->subdrivers[i].init(hid_dev,
529 &hid_dev->subdrivers[i].data);
[f76153ce]530 if (rc != EOK) {
531 usb_log_warning("Failed to initialize"
532 " HID subdriver structure.\n");
533 } else {
534 // at least one subdriver initialized
535 ok = true;
536 }
537 } else {
538 ok = true;
539 }
540 }
541
542 rc = (ok) ? EOK : -1; // what error to report
543 }
544
[2002595]545
546 if (rc == EOK) {
547 // save max input report size and allocate space for the report
548 rc = usb_hid_init_report(hid_dev);
549 if (rc != EOK) {
550 usb_log_error("Failed to initialize input report buffer"
551 ".\n");
552 }
[d1fb591]553 }
554
[2002595]555
[61257f4]556 return rc;
557}
558
559/*----------------------------------------------------------------------------*/
560
[60c0573]561bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
562 size_t buffer_size, void *arg)
563{
564 int i;
565
566 if (dev == NULL || arg == NULL || buffer == NULL) {
567 usb_log_error("Missing arguments to polling callback.\n");
568 return false;
569 }
570
571 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
572
[d1fb591]573 assert(hid_dev->input_report != NULL);
[ae5f77d5]574 usb_log_debug("New data [%zu/%zu]: %s\n", buffer_size,
575 hid_dev->max_input_report_size,
576 usb_debug_str_buffer(buffer, buffer_size, 0));
[19e0560e]577
[2002595]578 if (hid_dev->max_input_report_size >= buffer_size) {
579 /*! @todo This should probably be atomic. */
580 memcpy(hid_dev->input_report, buffer, buffer_size);
581 hid_dev->input_report_size = buffer_size;
582 usb_hid_new_report(hid_dev);
583 }
[31cfee16]584
[65c3794]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
590 if (rc != EOK) {
591 usb_log_warning("Error in usb_hid_parse_report():"
592 "%s\n", str_error(rc));
593 }
594
[60c0573]595 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
[65b458c4]600 && hid_dev->subdrivers[i].poll(hid_dev,
[4d3c13e]601 hid_dev->subdrivers[i].data)) {
[60c0573]602 cont = true;
603 }
604 }
605
606 return cont;
607}
608
609/*----------------------------------------------------------------------------*/
610
[61257f4]611void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason,
612 void *arg)
613{
[60c0573]614 int i;
615
[61257f4]616 if (dev == NULL || arg == NULL) {
617 return;
618 }
619
620 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
621
[60c0573]622 for (i = 0; i < hid_dev->subdriver_count; ++i) {
623 if (hid_dev->subdrivers[i].poll_end != NULL) {
[65b458c4]624 hid_dev->subdrivers[i].poll_end(hid_dev,
625 hid_dev->subdrivers[i].data, reason);
[60c0573]626 }
627 }
628
[61257f4]629 usb_hid_free(&hid_dev);
630}
631
632/*----------------------------------------------------------------------------*/
633
[8fb45e08]634void usb_hid_new_report(usb_hid_dev_t *hid_dev)
[dd3eda2]635{
[8fb45e08]636 ++hid_dev->report_nr;
[dd3eda2]637}
638
639/*----------------------------------------------------------------------------*/
640
[8fb45e08]641int usb_hid_report_number(usb_hid_dev_t *hid_dev)
[dd3eda2]642{
[8fb45e08]643 return hid_dev->report_nr;
[dd3eda2]644}
645
646/*----------------------------------------------------------------------------*/
647
[61257f4]648void usb_hid_free(usb_hid_dev_t **hid_dev)
649{
[60c0573]650 int i;
651
[61257f4]652 if (hid_dev == NULL || *hid_dev == NULL) {
653 return;
654 }
655
[aaf6155]656 usb_log_debug("Subdrivers: %p, subdriver count: %d\n",
657 (*hid_dev)->subdrivers, (*hid_dev)->subdriver_count);
658
[f76153ce]659 assert((*hid_dev)->subdrivers != NULL
660 || (*hid_dev)->subdriver_count == 0);
661
[60c0573]662 for (i = 0; i < (*hid_dev)->subdriver_count; ++i) {
663 if ((*hid_dev)->subdrivers[i].deinit != NULL) {
[65b458c4]664 (*hid_dev)->subdrivers[i].deinit(*hid_dev,
665 (*hid_dev)->subdrivers[i].data);
[60c0573]666 }
[61257f4]667 }
[f76153ce]668
669 // free the subdrivers info
670 if ((*hid_dev)->subdrivers != NULL) {
[1cbb4b7]671 free((*hid_dev)->subdrivers);
[f76153ce]672 }
[61257f4]673
674 // destroy the parser
[e60436b]675 if ((*hid_dev)->report != NULL) {
676 usb_hid_free_report((*hid_dev)->report);
[61257f4]677 }
678
679 if ((*hid_dev)->report_desc != NULL) {
680 free((*hid_dev)->report_desc);
681 }
682
683 free(*hid_dev);
684 *hid_dev = NULL;
[966acede]685}
686
687/**
688 * @}
689 */
Note: See TracBrowser for help on using the repository browser.