source: mainline/uspace/drv/usbhid/usbhid.c@ dcb7d7cd

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since dcb7d7cd was dcb7d7cd, checked in by Matej Klonfar <maklf@…>, 15 years ago

subdrivers matching without specified report_id

  • Property mode set to 100644
File size: 20.3 KB
Line 
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>
39#include <usb/hid/hid.h>
40#include <usb/hid/hidparser.h>
41#include <usb/hid/hidreport.h>
42#include <usb/hid/request.h>
43#include <errno.h>
44#include <str_error.h>
45
46#include "usbhid.h"
47
48#include "kbd/kbddev.h"
49#include "generic/hiddev.h"
50#include "mouse/mousedev.h"
51#include "subdrivers.h"
52
53/*----------------------------------------------------------------------------*/
54
55/* Array of endpoints expected on the device, NULL terminated. */
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,
59 &usb_hid_generic_poll_endpoint_description,
60 NULL
61};
62
63static const int USB_HID_MAX_SUBDRIVERS = 10;
64
65/** @todo What happens if this is not fibril local? */
66//static fibril_local bool report_number;
67
68/*----------------------------------------------------------------------------*/
69
70static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
71{
72 assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
73
74 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
75 sizeof(usb_hid_subdriver_t));
76 if (hid_dev->subdrivers == NULL) {
77 return ENOMEM;
78 }
79
80 // set the init callback
81 hid_dev->subdrivers[0].init = usb_kbd_init;
82
83 // set the polling callback
84 hid_dev->subdrivers[0].poll = usb_kbd_polling_callback;
85
86 // set the polling ended callback
87 hid_dev->subdrivers[0].poll_end = NULL;
88
89 // set the deinit callback
90 hid_dev->subdrivers[0].deinit = usb_kbd_deinit;
91
92 // set subdriver count
93 hid_dev->subdriver_count = 1;
94
95 return EOK;
96}
97
98/*----------------------------------------------------------------------------*/
99
100static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
101{
102 assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
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;
108 }
109
110 // set the init callback
111 hid_dev->subdrivers[0].init = usb_mouse_init;
112
113 // set the polling callback
114 hid_dev->subdrivers[0].poll = usb_mouse_polling_callback;
115
116 // set the polling ended callback
117 hid_dev->subdrivers[0].poll_end = NULL;
118
119 // set the deinit callback
120 hid_dev->subdrivers[0].deinit = usb_mouse_deinit;
121
122 // set subdriver count
123 hid_dev->subdriver_count = 1;
124
125 return EOK;
126}
127
128/*----------------------------------------------------------------------------*/
129
130static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
131{
132 assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
133
134 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
135 sizeof(usb_hid_subdriver_t));
136 if (hid_dev->subdrivers == NULL) {
137 return ENOMEM;
138 }
139
140 // set the init callback
141 hid_dev->subdrivers[0].init = usb_generic_hid_init;
142
143 // set the polling callback
144 hid_dev->subdrivers[0].poll = usb_generic_hid_polling_callback;
145
146 // set the polling ended callback
147 hid_dev->subdrivers[0].poll_end = NULL;
148
149 // set the deinit callback
150 hid_dev->subdrivers[0].deinit = NULL;
151
152 // set subdriver count
153 hid_dev->subdriver_count = 1;
154
155 return EOK;
156}
157
158/*----------------------------------------------------------------------------*/
159
160static bool usb_hid_ids_match(usb_hid_dev_t *hid_dev,
161 const usb_hid_subdriver_mapping_t *mapping)
162{
163 assert(hid_dev != NULL);
164 assert(hid_dev->usb_dev != NULL);
165
166 return (hid_dev->usb_dev->descriptors.device.vendor_id
167 == mapping->vendor_id
168 && hid_dev->usb_dev->descriptors.device.product_id
169 == mapping->product_id);
170}
171
172/*----------------------------------------------------------------------------*/
173
174static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev,
175 const usb_hid_subdriver_mapping_t *mapping)
176{
177 assert(hid_dev != NULL);
178 assert(mapping != NULL);
179
180 usb_hid_report_path_t *usage_path = usb_hid_report_path();
181 if (usage_path == NULL) {
182 usb_log_debug("Failed to create usage path.\n");
183 return false;
184 }
185 int i = 0;
186 while (mapping->usage_path[i].usage != 0
187 || mapping->usage_path[i].usage_page != 0) {
188 if (usb_hid_report_path_append_item(usage_path,
189 mapping->usage_path[i].usage_page,
190 mapping->usage_path[i].usage) != EOK) {
191 usb_log_debug("Failed to append to usage path.\n");
192 usb_hid_report_path_free(usage_path);
193 return false;
194 }
195 ++i;
196 }
197
198 if (mapping->report_id >= 0) {
199 usb_hid_report_path_set_report_id(usage_path,
200 mapping->report_id);
201 }
202
203 assert(hid_dev->report != NULL);
204
205 usb_log_debug("Compare flags: %d\n", mapping->compare);
206// size_t size = usb_hid_report_size(hid_dev->report, 0,
207// USB_HID_REPORT_TYPE_INPUT);
208 size_t size = 0;
209
210 usb_hid_report_description_t *report_des =
211 usb_hid_report_find_description(hid_dev->report,
212 mapping->report_id, USB_HID_REPORT_TYPE_INPUT);
213
214 while(report_des != NULL) {
215
216 if((mapping->report_id) == 0 && (report_des->report_id != 0)) {
217 usb_hid_report_path_set_report_id(usage_path,
218 report_des->report_id);
219 }
220
221 usb_hid_report_field_t *field = usb_hid_report_get_sibling (
222 hid_dev->report,
223 NULL, usage_path, mapping->compare,
224 USB_HID_REPORT_TYPE_INPUT);
225
226 while(field != NULL) {
227 size++;
228 field = usb_hid_report_get_sibling (hid_dev->report,
229 field, usage_path, mapping->compare,
230 USB_HID_REPORT_TYPE_INPUT);
231 }
232
233 if((mapping->report_id == 0) && (report_des->report_id != 0)) {
234 uint8_t report_id = usb_hid_get_next_report_id(
235 hid_dev->report, report_des->report_id,
236 USB_HID_REPORT_TYPE_INPUT);
237
238 if(report_id == 0) {
239 break;
240 }
241
242 report_des = usb_hid_report_find_description(
243 hid_dev->report, report_id,
244 USB_HID_REPORT_TYPE_INPUT);
245 }
246 else {
247 break;
248 }
249 }
250
251 usb_log_debug("Size of the input report: %zuB\n", size);
252 usb_hid_report_path_free(usage_path);
253
254 return (size > 0);
255}
256
257/*----------------------------------------------------------------------------*/
258
259static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev,
260 const usb_hid_subdriver_t **subdrivers, int count)
261{
262 int i;
263
264 if (count <= 0) {
265 hid_dev->subdriver_count = 0;
266 hid_dev->subdrivers = NULL;
267 return EOK;
268 }
269
270 // add one generic HID subdriver per device
271
272 hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc((count + 1) *
273 sizeof(usb_hid_subdriver_t));
274 if (hid_dev->subdrivers == NULL) {
275 return ENOMEM;
276 }
277
278 for (i = 0; i < count; ++i) {
279 hid_dev->subdrivers[i].init = subdrivers[i]->init;
280 hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit;
281 hid_dev->subdrivers[i].poll = subdrivers[i]->poll;
282 hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end;
283 }
284
285 hid_dev->subdrivers[count].init = usb_generic_hid_init;
286 hid_dev->subdrivers[count].poll = usb_generic_hid_polling_callback;
287 hid_dev->subdrivers[count].deinit = NULL;
288 hid_dev->subdrivers[count].poll_end = NULL;
289
290 hid_dev->subdriver_count = count + 1;
291
292 return EOK;
293}
294
295/*----------------------------------------------------------------------------*/
296
297static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
298{
299 assert(hid_dev != NULL);
300
301 const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
302
303 int i = 0, count = 0;
304 const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i];
305
306 bool ids_matched;
307 bool matched;
308
309 while (count < USB_HID_MAX_SUBDRIVERS &&
310 (mapping->usage_path != NULL
311 || mapping->vendor_id >= 0 || mapping->product_id >= 0)) {
312 // check the vendor & product ID
313 if (mapping->vendor_id >= 0 && mapping->product_id < 0) {
314 usb_log_warning("Missing Product ID for Vendor ID %d\n",
315 mapping->vendor_id);
316 return EINVAL;
317 }
318 if (mapping->product_id >= 0 && mapping->vendor_id < 0) {
319 usb_log_warning("Missing Vendor ID for Product ID %d\n",
320 mapping->product_id);
321 return EINVAL;
322 }
323
324 ids_matched = false;
325 matched = false;
326
327 if (mapping->vendor_id >= 0) {
328 assert(mapping->product_id >= 0);
329 usb_log_debug("Comparing device against vendor ID %u"
330 " and product ID %u.\n", mapping->vendor_id,
331 mapping->product_id);
332 if (usb_hid_ids_match(hid_dev, mapping)) {
333 usb_log_debug("IDs matched.\n");
334 ids_matched = true;
335 }
336 }
337
338 if (mapping->usage_path != NULL) {
339 usb_log_debug("Comparing device against usage path.\n");
340 if (usb_hid_path_matches(hid_dev, mapping)) {
341 // does not matter if IDs were matched
342 matched = true;
343 }
344 } else {
345 // matched only if IDs were matched and there is no path
346 matched = ids_matched;
347 }
348
349 if (matched) {
350 usb_log_debug("Subdriver matched.\n");
351 subdrivers[count++] = &mapping->subdriver;
352 }
353
354 mapping = &usb_hid_subdrivers[++i];
355 }
356
357 // we have all subdrivers determined, save them into the hid device
358 return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
359}
360
361/*----------------------------------------------------------------------------*/
362
363static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
364{
365 assert(hid_dev != NULL && dev != NULL);
366
367 int rc = EOK;
368
369 if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
370 usb_log_debug("Found keyboard endpoint.\n");
371 // save the pipe index
372 hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
373 } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
374 usb_log_debug("Found mouse endpoint.\n");
375 // save the pipe index
376 hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
377 } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
378 usb_log_debug("Found generic HID endpoint.\n");
379 // save the pipe index
380 hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
381 } else {
382 usb_log_error("None of supported endpoints found - probably"
383 " not a supported device.\n");
384 rc = ENOTSUP;
385 }
386
387 return rc;
388}
389
390/*----------------------------------------------------------------------------*/
391
392static int usb_hid_init_report(usb_hid_dev_t *hid_dev)
393{
394 assert(hid_dev != NULL && hid_dev->report != NULL);
395
396 uint8_t report_id = 0;
397 size_t size;/* = usb_hid_report_byte_size(hid_dev->report, report_id,
398 USB_HID_REPORT_TYPE_INPUT);*/
399
400 size_t max_size = 0;
401
402 do {
403 size = usb_hid_report_byte_size(hid_dev->report, report_id,
404 USB_HID_REPORT_TYPE_INPUT);
405 usb_log_debug("Report ID: %u, size: %zu\n", report_id, size);
406 max_size = (size > max_size) ? size : max_size;
407 report_id = usb_hid_get_next_report_id(hid_dev->report,
408 report_id, USB_HID_REPORT_TYPE_INPUT);
409 } while (report_id != 0);
410
411 usb_log_debug("Max size of input report: %zu\n", max_size);
412
413 hid_dev->max_input_report_size = max_size;
414 assert(hid_dev->input_report == NULL);
415
416 hid_dev->input_report = malloc(max_size);
417 if (hid_dev->input_report == NULL) {
418 return ENOMEM;
419 }
420 memset(hid_dev->input_report, 0, max_size);
421
422 return EOK;
423}
424
425/*----------------------------------------------------------------------------*/
426
427usb_hid_dev_t *usb_hid_new(void)
428{
429 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)calloc(1,
430 sizeof(usb_hid_dev_t));
431
432 if (hid_dev == NULL) {
433 usb_log_fatal("No memory!\n");
434 return NULL;
435 }
436
437 hid_dev->report = (usb_hid_report_t *)(malloc(sizeof(
438 usb_hid_report_t)));
439 if (hid_dev->report == NULL) {
440 usb_log_fatal("No memory!\n");
441 free(hid_dev);
442 return NULL;
443 }
444
445 hid_dev->poll_pipe_index = -1;
446
447 return hid_dev;
448}
449
450/*----------------------------------------------------------------------------*/
451
452int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
453{
454 int rc, i;
455
456 usb_log_debug("Initializing HID structure...\n");
457
458 if (hid_dev == NULL) {
459 usb_log_error("Failed to init HID structure: no structure given"
460 ".\n");
461 return EINVAL;
462 }
463
464 if (dev == NULL) {
465 usb_log_error("Failed to init HID structure: no USB device"
466 " given.\n");
467 return EINVAL;
468 }
469
470 /* The USB device should already be initialized, save it in structure */
471 hid_dev->usb_dev = dev;
472
473 rc = usb_hid_check_pipes(hid_dev, dev);
474 if (rc != EOK) {
475 //usb_hid_free(&hid_dev);
476 return rc;
477 }
478
479 /* Get the report descriptor and parse it. */
480 rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
481 hid_dev->report, &hid_dev->report_desc, &hid_dev->report_desc_size);
482
483 bool fallback = false;
484
485 if (rc == EOK) {
486 // try to find subdrivers that may want to handle this device
487 rc = usb_hid_find_subdrivers(hid_dev);
488 if (rc != EOK || hid_dev->subdriver_count == 0) {
489 // try to fall back to the boot protocol if available
490 usb_log_info("No subdrivers found to handle this"
491 " device.\n");
492 fallback = true;
493 assert(hid_dev->subdrivers == NULL);
494 assert(hid_dev->subdriver_count == 0);
495 }
496 } else {
497 usb_log_error("Failed to parse Report descriptor.\n");
498 // try to fall back to the boot protocol if available
499 fallback = true;
500 }
501
502 if (fallback) {
503 // fall back to boot protocol
504 switch (hid_dev->poll_pipe_index) {
505 case USB_HID_KBD_POLL_EP_NO:
506 usb_log_info("Falling back to kbd boot protocol.\n");
507 rc = usb_kbd_set_boot_protocol(hid_dev);
508 if (rc == EOK) {
509 rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
510 }
511 break;
512 case USB_HID_MOUSE_POLL_EP_NO:
513 usb_log_info("Falling back to mouse boot protocol.\n");
514 rc = usb_mouse_set_boot_protocol(hid_dev);
515 if (rc == EOK) {
516 rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
517 }
518 break;
519 default:
520 assert(hid_dev->poll_pipe_index
521 == USB_HID_GENERIC_POLL_EP_NO);
522
523 /* TODO: this has no meaning if the report descriptor
524 is not parsed */
525 usb_log_info("Falling back to generic HID driver.\n");
526 rc = usb_hid_set_generic_hid_subdriver(hid_dev);
527 }
528 }
529
530 if (rc != EOK) {
531 usb_log_error("No subdriver for handling this device could be"
532 " initialized: %s.\n", str_error(rc));
533 usb_log_debug("Subdriver count: %d\n",
534 hid_dev->subdriver_count);
535 //usb_hid_free(&hid_dev);
536 } else {
537 bool ok = false;
538
539 usb_log_debug("Subdriver count: %d\n",
540 hid_dev->subdriver_count);
541
542 for (i = 0; i < hid_dev->subdriver_count; ++i) {
543 if (hid_dev->subdrivers[i].init != NULL) {
544 usb_log_debug("Initializing subdriver %d.\n",i);
545 rc = hid_dev->subdrivers[i].init(hid_dev,
546 &hid_dev->subdrivers[i].data);
547 if (rc != EOK) {
548 usb_log_warning("Failed to initialize"
549 " HID subdriver structure.\n");
550 } else {
551 // at least one subdriver initialized
552 ok = true;
553 }
554 } else {
555 ok = true;
556 }
557 }
558
559 rc = (ok) ? EOK : -1; // what error to report
560 }
561
562 // save max input report size and allocate space for the report
563 rc = usb_hid_init_report(hid_dev);
564 if (rc != EOK) {
565 usb_log_error("Failed to initialize input report buffer.\n");
566 }
567
568 return rc;
569}
570
571/*----------------------------------------------------------------------------*/
572
573bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
574 size_t buffer_size, void *arg)
575{
576 int i;
577
578 if (dev == NULL || arg == NULL || buffer == NULL) {
579 usb_log_error("Missing arguments to polling callback.\n");
580 return false;
581 }
582
583 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
584
585// int allocated = (hid_dev->input_report != NULL);
586 assert(hid_dev->input_report != NULL);
587 usb_log_debug("Max input report size: %zu, buffer size: %zu\n",
588 hid_dev->max_input_report_size, buffer_size);
589 assert(hid_dev->max_input_report_size >= buffer_size);
590
591// if (/*!allocated*/
592// /*|| *//*hid_dev->input_report_size < buffer_size*/) {
593// uint8_t *input_old = hid_dev->input_report;
594// uint8_t *input_new = (uint8_t *)malloc(buffer_size);
595
596// if (input_new == NULL) {
597// usb_log_error("Failed to allocate space for input "
598// "buffer. This event may not be reported\n");
599// memset(hid_dev->input_report, 0,
600// hid_dev->input_report_size);
601// } else {
602// memcpy(input_new, input_old,
603// hid_dev->input_report_size);
604// hid_dev->input_report = input_new;
605// if (allocated) {
606// free(input_old);
607// }
608// usb_hid_new_report();
609// }
610// }
611
612 /*! @todo This should probably be atomic. */
613 memcpy(hid_dev->input_report, buffer, buffer_size);
614 hid_dev->input_report_size = buffer_size;
615 usb_hid_new_report(hid_dev);
616
617 bool cont = false;
618
619 // continue if at least one of the subdrivers want to continue
620 for (i = 0; i < hid_dev->subdriver_count; ++i) {
621 if (hid_dev->subdrivers[i].poll != NULL
622 && hid_dev->subdrivers[i].poll(hid_dev,
623 hid_dev->subdrivers[i].data, buffer, buffer_size)) {
624 cont = true;
625 }
626 }
627
628 return cont;
629}
630
631/*----------------------------------------------------------------------------*/
632
633void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason,
634 void *arg)
635{
636 int i;
637
638 if (dev == NULL || arg == NULL) {
639 return;
640 }
641
642 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
643
644 for (i = 0; i < hid_dev->subdriver_count; ++i) {
645 if (hid_dev->subdrivers[i].poll_end != NULL) {
646 hid_dev->subdrivers[i].poll_end(hid_dev,
647 hid_dev->subdrivers[i].data, reason);
648 }
649 }
650
651 usb_hid_free(&hid_dev);
652}
653
654/*----------------------------------------------------------------------------*/
655
656//const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev)
657//{
658// switch (hid_dev->poll_pipe_index) {
659// case USB_HID_KBD_POLL_EP_NO:
660// return HID_KBD_FUN_NAME;
661// break;
662// case USB_HID_MOUSE_POLL_EP_NO:
663// return HID_MOUSE_FUN_NAME;
664// break;
665// default:
666// return HID_GENERIC_FUN_NAME;
667// }
668//}
669
670/*----------------------------------------------------------------------------*/
671
672//const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev)
673//{
674// // this means that only boot protocol keyboards will be connected
675// // to the console; there is probably no better way to do this
676
677// switch (hid_dev->poll_pipe_index) {
678// case USB_HID_KBD_POLL_EP_NO:
679// return HID_KBD_CLASS_NAME;
680// break;
681// case USB_HID_MOUSE_POLL_EP_NO:
682// return HID_MOUSE_CLASS_NAME;
683// break;
684// default:
685// return HID_GENERIC_CLASS_NAME;
686// }
687//}
688
689/*----------------------------------------------------------------------------*/
690
691void usb_hid_new_report(usb_hid_dev_t *hid_dev)
692{
693 ++hid_dev->report_nr;
694}
695
696/*----------------------------------------------------------------------------*/
697
698int usb_hid_report_number(usb_hid_dev_t *hid_dev)
699{
700 return hid_dev->report_nr;
701}
702
703/*----------------------------------------------------------------------------*/
704
705//void usb_hid_report_received(void)
706//{
707// ++report_number;
708//}
709
710/*----------------------------------------------------------------------------*/
711
712//bool usb_hid_report_ready(void)
713//{
714// return !report_received;
715//}
716
717/*----------------------------------------------------------------------------*/
718
719void usb_hid_free(usb_hid_dev_t **hid_dev)
720{
721 int i;
722
723 if (hid_dev == NULL || *hid_dev == NULL) {
724 return;
725 }
726
727 usb_log_debug("Subdrivers: %p, subdriver count: %d\n",
728 (*hid_dev)->subdrivers, (*hid_dev)->subdriver_count);
729
730 assert((*hid_dev)->subdrivers != NULL
731 || (*hid_dev)->subdriver_count == 0);
732
733 for (i = 0; i < (*hid_dev)->subdriver_count; ++i) {
734 if ((*hid_dev)->subdrivers[i].deinit != NULL) {
735 (*hid_dev)->subdrivers[i].deinit(*hid_dev,
736 (*hid_dev)->subdrivers[i].data);
737 }
738 }
739
740 // free the subdrivers info
741 if ((*hid_dev)->subdrivers != NULL) {
742 free((*hid_dev)->subdrivers);
743 }
744
745 // destroy the parser
746 if ((*hid_dev)->report != NULL) {
747 usb_hid_free_report((*hid_dev)->report);
748 }
749
750 if ((*hid_dev)->report_desc != NULL) {
751 free((*hid_dev)->report_desc);
752 }
753
754 free(*hid_dev);
755 *hid_dev = NULL;
756}
757
758/**
759 * @}
760 */
Note: See TracBrowser for help on using the repository browser.