4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Copyright (c) 2018, Joyent, Inc.
30 #include <sys/usb/usba/usbai_version.h>
31 #include <sys/usb/usba.h>
32 #include <sys/usb/clients/hid/hid.h>
33 #include <sys/usb/clients/hidparser/hidparser.h>
34 #include <sys/usb/clients/hidparser/hid_parser_driver.h>
35 #include <sys/usb/clients/hidparser/hidparser_impl.h>
38 * hidparser: Parser to generate parse tree for Report Descriptors
42 uint_t hparser_errmask
= (uint_t
)PRINT_MASK_ALL
;
43 uint_t hparser_errlevel
= (uint_t
)USB_LOG_L1
;
44 static usb_log_handle_t hparser_log_handle
;
47 * Array used to store corresponding strings for the
48 * different item types for debugging.
50 char *items
[500]; /* Print items */
55 extern struct mod_ops mod_miscops
;
57 static struct modlmisc modlmisc
= {
58 &mod_miscops
, /* Type of module */
62 static struct modlinkage modlinkage
= {
63 MODREV_1
, (void *)&modlmisc
, NULL
69 int rval
= mod_install(&modlinkage
);
72 hparser_log_handle
= usb_alloc_log_hdl(NULL
, "hidparser",
73 &hparser_errlevel
, &hparser_errmask
, NULL
, 0);
82 int rval
= mod_remove(&modlinkage
);
85 usb_free_log_hdl(hparser_log_handle
);
92 _info(struct modinfo
*modinfop
)
95 return (mod_info(&modlinkage
, modinfop
));
99 * These functions are used internally in the parser.
102 static void hidparser_scan(hidparser_tok_t
*);
103 static int hidparser_Items(hidparser_tok_t
*);
104 static int hidparser_LocalItem(hidparser_tok_t
*);
105 static int hidparser_GlobalItem(hidparser_tok_t
*);
106 static int hidparser_ItemList(entity_item_t
**,
108 static int hidparser_ReportDescriptor(entity_item_t
**,
110 static int hidparser_ReportDescriptorDash(entity_item_t
**,
112 static int hidparser_MainItem(entity_item_t
**,
114 static void hidparser_free_attribute_list(
115 entity_attribute_t
*);
116 static entity_item_t
*hidparser_allocate_entity(hidparser_tok_t
*);
117 static void hidparser_add_attribute(hidparser_tok_t
*);
118 static entity_attribute_t
*hidparser_cp_attribute_list(
119 entity_attribute_t
*);
120 static entity_attribute_t
*hidparser_find_attribute_end(
121 entity_attribute_t
*);
122 static entity_attribute_t
*hidparser_alloc_attrib_list(int);
123 static void hidparser_report_err(int, int,
125 static int hidparser_isvalid_item(int);
126 static entity_attribute_t
*hidparser_lookup_attribute(entity_item_t
*,
128 static void hidparser_global_err_check(entity_item_t
*);
129 static void hidparser_local_err_check(entity_item_t
*);
130 static void hidparser_mainitem_err_check(entity_item_t
*);
131 static unsigned int hidparser_find_unsigned_val(
132 entity_attribute_t
*);
133 static int hidparser_find_signed_val(
134 entity_attribute_t
*);
135 static void hidparser_check_correspondence(
136 entity_item_t
*, int, int, int,
137 int, char *, char *);
138 static void hidparser_check_minmax_val(entity_item_t
*,
140 static void hidparser_check_minmax_val_signed(
143 static void hidparser_error_delim(entity_item_t
*, int);
144 static int hidparser_get_usage_attribute_report_des(
146 uint32_t, uint32_t, uint32_t,
147 uint32_t, uint32_t, int32_t *);
148 static int hidparser_get_packet_size_report_des(
149 entity_item_t
*, uint32_t, uint32_t,
151 static int hidparser_get_main_item_data_descr_main(
152 entity_item_t
*, uint32_t,
153 uint32_t, uint32_t, uint32_t,
155 static void hidparser_print_entity(
156 entity_item_t
*entity
,
158 static void hidparser_print_this_attribute(
159 entity_attribute_t
*attribute
,
161 static int hidparser_main(unsigned char *, size_t,
163 static void hidparser_initialize_items();
164 static void hidparser_free_report_descr_handle(
166 static int hidparser_print_report_descr_handle(
167 entity_item_t
*handle
,
169 static int hidparser_get_usage_list_in_order_internal(
170 entity_item_t
*parse_handle
,
171 uint_t collection_usage
,
173 uint_t main_item_type
,
174 hidparser_rpt_t
*rpt
);
175 static void hidparser_fill_usage_info(
176 hidparser_usage_info_t
*ui
,
177 entity_attribute_t
*attribute
);
178 static int hidparser_get_report_id_list_internal(
179 entity_item_t
*parser_handle
,
180 uint_t main_item_type
,
181 hidparser_report_id_list_t
*id_lst
);
184 * The hidparser_lookup_first(N) of a non-terminal N is stored as an array of
185 * integer tokens, terminated by 0. Right now there is only one element.
187 static hidparser_terminal_t first_Items
[] = {
188 R_ITEM_USAGE_PAGE
, R_ITEM_LOGICAL_MINIMUM
, R_ITEM_LOGICAL_MAXIMUM
, \
189 R_ITEM_PHYSICAL_MINIMUM
, R_ITEM_PHYSICAL_MAXIMUM
, R_ITEM_UNIT
, \
190 R_ITEM_EXPONENT
, R_ITEM_REPORT_SIZE
, R_ITEM_REPORT_COUNT
, \
192 R_ITEM_USAGE
, R_ITEM_USAGE_MIN
, R_ITEM_USAGE_MAX
, \
193 R_ITEM_DESIGNATOR_INDEX
, \
194 R_ITEM_DESIGNATOR_MIN
, R_ITEM_STRING_INDEX
, R_ITEM_STRING_MIN
, \
196 R_ITEM_SET_DELIMITER
, \
202 * Each non-terminal is represented by a function. In a top-down parser,
203 * whenever a non-terminal is encountered on the state diagram, the
204 * corresponding function is called. Because of the grammar, there is NO
205 * backtracking. If there is an error in the middle, the parser returns
208 static hidparser_terminal_t
*hid_first_list
[] = {
214 * hidparser_parse_report_descriptor:
215 * Calls the main parser routine
218 hidparser_parse_report_descriptor(
219 unsigned char *descriptor
,
221 usb_hid_descr_t
*hid_descriptor
,
222 hidparser_handle_t
*parse_handle
)
227 hidparser_initialize_items();
229 error
= hidparser_main(descriptor
, size
, &root
);
231 if (error
!= HIDPARSER_SUCCESS
) {
233 return (HIDPARSER_FAILURE
);
235 *parse_handle
= kmem_zalloc(
236 sizeof (hidparser_handle
), KM_SLEEP
);
237 (*parse_handle
)->hidparser_handle_hid_descr
= hid_descriptor
;
238 (*parse_handle
)->hidparser_handle_parse_tree
= root
;
240 return (HIDPARSER_SUCCESS
);
246 * hidparser_free_report_descriptor_handle:
247 * Frees the parse_handle which consists of a pointer to the parse
248 * tree and a pointer to the Hid descriptor structure
251 hidparser_free_report_descriptor_handle(hidparser_handle_t parse_handle
)
253 if (parse_handle
!= NULL
) {
254 hidparser_free_report_descr_handle(
255 parse_handle
->hidparser_handle_parse_tree
);
256 if (parse_handle
!= NULL
) {
257 kmem_free(parse_handle
, sizeof (hidparser_handle
));
261 return (HIDPARSER_SUCCESS
);
266 * hidparser_get_country_code:
267 * Return the bCountryCode from the Hid Descriptor
271 hidparser_get_country_code(hidparser_handle_t parser_handle
,
272 uint16_t *country_code
)
274 if ((parser_handle
== NULL
) ||
275 (parser_handle
->hidparser_handle_hid_descr
== NULL
)) {
277 return (HIDPARSER_FAILURE
);
281 parser_handle
->hidparser_handle_hid_descr
->bCountryCode
;
283 return (HIDPARSER_SUCCESS
);
288 * hidparser_get_packet_size:
289 * Get the packet size(sum of REPORT_SIZE * REPORT_COUNT)
290 * corresponding to a report id and an item type
293 hidparser_get_packet_size(hidparser_handle_t parser_handle
,
295 uint_t main_item_type
,
298 if ((parser_handle
== NULL
) || (parser_handle
->
299 hidparser_handle_parse_tree
== NULL
)) {
301 return (HIDPARSER_FAILURE
);
306 return (hidparser_get_packet_size_report_des(
307 parser_handle
->hidparser_handle_parse_tree
,
308 report_id
, main_item_type
, size
));
313 * hidparser_get_packet_size_report_des:
314 * Get the packet size(sum of REPORT_SIZE * REPORT_COUNT)
315 * corresponding to a report id and an item type
318 hidparser_get_packet_size_report_des(entity_item_t
*parser_handle
,
320 uint32_t main_item_type
,
323 entity_item_t
*current
= parser_handle
;
324 entity_attribute_t
*attribute
;
326 uchar_t foundsize
, foundcount
, foundreportid
, right_report_id
;
333 if (current
->entity_item_type
== R_ITEM_COLLECTION
) {
334 (void) hidparser_get_packet_size_report_des(
335 current
->info
.child
, report_id
, main_item_type
,
337 } else if (current
->entity_item_type
== main_item_type
) {
343 attribute
= current
->entity_item_attributes
;
344 while (attribute
!= NULL
) {
345 if (attribute
->entity_attribute_tag
==
349 entity_attribute_value
[0]) ==
353 } else if (attribute
->entity_attribute_tag
==
354 R_ITEM_REPORT_SIZE
) {
356 temp
*= hidparser_find_unsigned_val(
358 if (foundcount
== 1) {
364 } else if (attribute
->entity_attribute_tag
==
365 R_ITEM_REPORT_COUNT
) {
367 temp
*= hidparser_find_unsigned_val(
369 if (foundsize
== 1) {
376 attribute
= attribute
->entity_attribute_next
;
380 if (right_report_id
) {
381 *size
= *size
+ temp
;
383 } else if (report_id
== HID_REPORT_ID_UNDEFINED
) {
384 /* Just sanity checking */
385 *size
= *size
+ temp
;
390 current
= current
->entity_item_right_sibling
;
391 } /* end while current */
394 return (HIDPARSER_SUCCESS
);
399 * hidparser_get_usage_attribute:
400 * Get the attribute value corresponding to a particular
401 * report id, main item and usage
404 hidparser_get_usage_attribute(hidparser_handle_t parser_handle
,
406 uint_t main_item_type
,
409 uint_t usage_attribute
,
410 int *usage_attribute_value
)
413 return (hidparser_get_usage_attribute_report_des(
414 parser_handle
->hidparser_handle_parse_tree
,
415 report_id
, main_item_type
, usage_page
,
416 usage_id
, usage_attribute
, usage_attribute_value
));
421 * hidparser_get_usage_attribute_report_des:
422 * Called by the wrapper function hidparser_get_usage_attribute()
425 hidparser_get_usage_attribute_report_des(entity_item_t
*parser_handle
,
427 uint_t main_item_type
,
430 uint_t usage_attribute
,
431 int *usage_attribute_value
)
433 entity_item_t
*current
= parser_handle
;
434 entity_attribute_t
*attribute
;
435 uchar_t found_page
, found_ret_value
, found_usage_id
;
436 uchar_t foundreportid
, right_report_id
;
447 if (usage_id
== HID_USAGE_UNDEFINED
) {
450 if (current
->entity_item_type
== R_ITEM_COLLECTION
) {
452 if (hidparser_get_usage_attribute_report_des(
453 current
->info
.child
, report_id
, main_item_type
,
454 usage_page
, usage_id
, usage_attribute
,
455 usage_attribute_value
) ==
458 return (HIDPARSER_SUCCESS
);
461 } else if (current
->entity_item_type
== main_item_type
) {
462 /* Match Item Type */
463 attribute
= current
->entity_item_attributes
;
465 while (attribute
!= NULL
) {
466 if (attribute
->entity_attribute_tag
==
468 usage
= hidparser_find_unsigned_val(
470 if (usage_id
== HID_USAGE_ID(usage
)) {
475 * If we are trying to find out
476 * say, report size of usage =
477 * 0, a m.i with a valid usage
478 * will not contain that
481 HID_USAGE_UNDEFINED
) {
486 if (found_usage_id
&& attribute
->
487 entity_attribute_length
== 3) {
489 * This is an extended usage ie.
490 * usage page in upper 16 bits
491 * or-ed with usage in the lower
494 if (HID_USAGE_PAGE(usage
) &&
495 HID_USAGE_PAGE(usage
) ==
504 } else if (attribute
->entity_attribute_tag
==
507 entity_attribute_value
[0] ==
509 /* Match Usage Page */
512 } else if (attribute
->entity_attribute_tag
==
516 entity_attribute_value
[0] ==
521 if (attribute
->entity_attribute_tag
==
523 /* Match attribute */
525 *usage_attribute_value
= attribute
->
526 entity_attribute_value
[0];
528 entity_attribute_length
== 2) {
531 entity_attribute_value
[0] &
534 entity_attribute_value
[1] <<
536 *usage_attribute_value
=
540 attribute
= attribute
->entity_attribute_next
;
543 if (found_usage_id
&& found_page
&& found_ret_value
) {
546 if (right_report_id
) {
548 return (HIDPARSER_SUCCESS
);
549 } else if (report_id
==
550 HID_REPORT_ID_UNDEFINED
) {
552 return (HIDPARSER_SUCCESS
);
556 return (HIDPARSER_SUCCESS
);
562 * search the next main item, right sibling of this one
564 if (current
->entity_item_right_sibling
!= NULL
) {
566 current
= current
->entity_item_right_sibling
;
567 found_usage_id
= found_page
= found_ret_value
= 0;
568 /* Don't change foundreportid */
575 /* Don't give junk result */
576 *usage_attribute_value
= 0;
578 return (HIDPARSER_NOT_FOUND
);
583 * hidparser_get_main_item_data_descr:
584 * Get the data value corresponding to a particular
585 * Main Item (Input, Output, Feature)
588 hidparser_get_main_item_data_descr(hidparser_handle_t parser_handle
,
590 uint_t main_item_type
,
593 uint_t
*main_item_descr_value
)
596 return hidparser_get_main_item_data_descr_main(
597 parser_handle
->hidparser_handle_parse_tree
,
598 report_id
, main_item_type
, usage_page
, usage_id
,
599 main_item_descr_value
);
604 * hidparser_get_main_item_data_descr_main:
605 * Called by the wrapper function hidparser_get_main_item_data_descr()
608 hidparser_get_main_item_data_descr_main(entity_item_t
*parser_handle
,
610 uint_t main_item_type
,
613 uint_t
*main_item_descr_value
)
615 entity_item_t
*current
= parser_handle
;
616 entity_attribute_t
*attribute
;
618 uchar_t found_page
, found_usage_id
;
619 uchar_t foundreportid
, right_report_id
;
628 if (usage_id
== HID_USAGE_UNDEFINED
) {
631 if (current
->entity_item_type
== R_ITEM_COLLECTION
) {
633 if (hidparser_get_main_item_data_descr_main(
634 current
->info
.child
, report_id
, main_item_type
,
635 usage_page
, usage_id
, main_item_descr_value
) ==
638 return (HIDPARSER_SUCCESS
);
640 } else if (current
->entity_item_type
== main_item_type
) {
641 /* Match Item Type */
642 attribute
= current
->entity_item_attributes
;
644 if (report_id
== HID_REPORT_ID_UNDEFINED
) {
645 foundreportid
= right_report_id
= 1;
648 while (attribute
!= NULL
) {
649 if (attribute
->entity_attribute_tag
==
651 usage
= hidparser_find_unsigned_val(
653 if (usage_id
== HID_USAGE_ID(usage
)) {
656 entity_attribute_length
==
671 if (found_usage_id
&&
675 *main_item_descr_value
=
677 entity_item_params
[0];
681 } else if ((attribute
->entity_attribute_tag
==
682 R_ITEM_USAGE_PAGE
) &&
683 (attribute
->entity_attribute_value
[0] ==
686 /* Match Usage Page */
688 if (found_usage_id
&& foundreportid
&&
690 *main_item_descr_value
=
692 entity_item_params
[0];
695 } else if (attribute
->entity_attribute_tag
==
699 entity_attribute_value
[0] ==
707 attribute
= attribute
->entity_attribute_next
;
711 if (right_report_id
) {
712 if (found_usage_id
&& found_page
) {
714 return (HIDPARSER_SUCCESS
);
721 * search the next main item, right sibling of this one
723 if (current
->entity_item_right_sibling
!= NULL
) {
725 current
= current
->entity_item_right_sibling
;
726 found_page
= found_usage_id
= right_report_id
= 0;
733 *main_item_descr_value
= 0;
735 return (HIDPARSER_NOT_FOUND
);
739 * hidparser_lookup_usage_collection:
740 * Look up the collection specified by the usage page and usage id
743 hidparser_lookup_usage_collection(hidparser_handle_t parse_handle
,
747 entity_item_t
*current
;
748 entity_attribute_t
*attribute
;
749 int found_usage_id
= 0;
755 if ((parse_handle
== NULL
) ||
756 (parse_handle
->hidparser_handle_parse_tree
== NULL
))
757 return (HIDPARSER_FAILURE
);
759 current
= parse_handle
->hidparser_handle_parse_tree
;
760 while (current
!= NULL
) {
762 if (current
->entity_item_type
!= R_ITEM_COLLECTION
) {
763 current
= current
->entity_item_right_sibling
;
767 attribute
= current
->entity_item_attributes
;
771 while (attribute
!= NULL
) {
772 if (attribute
->entity_attribute_tag
== R_ITEM_USAGE
) {
774 usage
= hidparser_find_unsigned_val(attribute
);
775 usage_id
= HID_USAGE_ID(usage
);
776 if (attribute
->entity_attribute_length
== 3) {
777 if (HID_USAGE_PAGE(usage
)) {
780 HID_USAGE_PAGE(usage
);
786 } else if (attribute
->entity_attribute_tag
==
790 attribute
->entity_attribute_value
[0];
791 if (found_usage_id
) {
795 attribute
= attribute
->entity_attribute_next
;
798 if ((usage_page
== lusage_page
) && (usage_id
== lusage_id
))
799 return (HIDPARSER_SUCCESS
);
801 current
= current
->entity_item_right_sibling
;
804 return (HIDPARSER_FAILURE
);
809 * hidparser_get_top_level_collection_usage:
810 * Get the usage page and usage for the top level collection item
813 hidparser_get_top_level_collection_usage(hidparser_handle_t parse_handle
,
817 entity_item_t
*current
;
818 entity_attribute_t
*attribute
;
819 int found_usage_id
= 0;
823 if ((parse_handle
== NULL
) ||
824 (parse_handle
->hidparser_handle_parse_tree
== NULL
))
826 return (HIDPARSER_FAILURE
);
828 current
= parse_handle
->hidparser_handle_parse_tree
;
830 if (current
->entity_item_type
!= R_ITEM_COLLECTION
) {
832 return (HIDPARSER_FAILURE
);
834 attribute
= current
->entity_item_attributes
;
835 while (attribute
!= NULL
) {
836 if (attribute
->entity_attribute_tag
== R_ITEM_USAGE
) {
838 usage
= hidparser_find_unsigned_val(attribute
);
839 *usage_id
= HID_USAGE_ID(usage
);
840 if (attribute
->entity_attribute_length
== 3) {
841 if (HID_USAGE_PAGE(usage
)) {
843 *usage_page
= HID_USAGE_PAGE(usage
);
846 if (found_usage_id
&& found_page
) {
848 return (HIDPARSER_SUCCESS
);
850 } else if (attribute
->entity_attribute_tag
==
853 *usage_page
= attribute
->entity_attribute_value
[0];
854 if (found_usage_id
&& found_page
) {
856 return (HIDPARSER_SUCCESS
);
859 attribute
= attribute
->entity_attribute_next
;
862 return (HIDPARSER_FAILURE
);
867 * hidparser_get_usage_list_in_order:
868 * Find all the usages corresponding to a main item and report id.
869 * Note that only short items are supported.
875 * report id of the particular report where the usages belong to
877 * type of report, either Input, Output, or Feature
879 * Filled in with the pointer to the first element of the
883 * HIDPARSER_SUCCESS - returned success
884 * HIDPARSER_NOT_FOUND - usage specified by the parameters was not found
885 * HIDPARSER_FAILURE - unspecified failure
888 hidparser_get_usage_list_in_order(hidparser_handle_t parser_handle
,
890 uint_t main_item_type
,
891 hidparser_rpt_t
*rpt
)
894 if ((parser_handle
== NULL
) ||
895 (parser_handle
->hidparser_handle_parse_tree
== NULL
)) {
897 return (HIDPARSER_FAILURE
);
900 rpt
->no_of_usages
= 0;
902 return (hidparser_get_usage_list_in_order_internal(
903 parser_handle
->hidparser_handle_parse_tree
, HID_USAGE_UNDEFINED
,
904 report_id
, main_item_type
, rpt
));
909 hidparser_get_usage_list_in_order_internal(entity_item_t
*parser_handle
,
910 uint_t collection_usage
,
912 uint_t main_item_type
,
913 hidparser_rpt_t
*rpt
)
916 /* setup wrapper function */
917 entity_item_t
*current
= parser_handle
;
918 entity_attribute_t
*attribute
;
919 uchar_t foundreportid
, right_report_id
, valid_usage
;
920 uchar_t found_usage_min
, found_usage_max
, found_usage
;
923 uint32_t usage
, usage_min
, usage_max
, usage_id
[USAGE_MAX
];
924 hidparser_usage_info_t
*ui
;
933 if (current
->entity_item_type
== R_ITEM_COLLECTION
) {
936 * find collection usage information for this
941 attribute
= current
->entity_item_attributes
;
943 while (attribute
!= NULL
) {
944 if (attribute
->entity_attribute_tag
==
946 usage
= hidparser_find_unsigned_val(
950 attribute
= attribute
->entity_attribute_next
;
954 usage
= HID_USAGE_UNDEFINED
;
957 rval
= hidparser_get_usage_list_in_order_internal(
958 current
->info
.child
, usage
,
959 report_id
, main_item_type
, rpt
);
960 if (rval
!= HIDPARSER_SUCCESS
) {
965 } else if (current
->entity_item_type
== main_item_type
) {
966 /* Match Item Type */
975 attribute
= current
->entity_item_attributes
;
977 while (attribute
!= NULL
) {
978 switch (attribute
->entity_attribute_tag
) {
979 case R_ITEM_REPORT_ID
:
983 entity_attribute_value
[0] ==
987 /* different report id */
993 if (found_usage
>= USAGE_MAX
) {
995 return (HIDPARSER_FAILURE
);
997 usage
= hidparser_find_unsigned_val(
1000 usage_id
[found_usage
] = usage
;
1005 case R_ITEM_USAGE_MIN
:
1006 found_usage_min
= 1;
1007 usage_min
= hidparser_find_unsigned_val(
1011 case R_ITEM_USAGE_MAX
:
1012 found_usage_max
= 1;
1013 usage_max
= hidparser_find_unsigned_val(
1017 case R_ITEM_SET_DELIMITER
:
1018 /* skip over alternate usages */
1020 attribute
= attribute
->
1021 entity_attribute_next
;
1022 } while (attribute
->
1023 entity_attribute_tag
!=
1024 R_ITEM_SET_DELIMITER
);
1029 attribute
= attribute
->entity_attribute_next
;
1033 * If we have a report id match (or report ids
1034 * are not present), and have a usage item or
1035 * usage min&max, put the usage item into the
1036 * list. Don't put undefined usage items
1037 * (HID_USAGE_UNDEFINED, 0) into the list;
1038 * a 0 usage item is used to match padding
1039 * fields that don't have an attached usage.
1041 if (!foundreportid
||
1042 (foundreportid
&& right_report_id
)) {
1044 for (j
= 0; j
< found_usage
; j
++) {
1046 /* Put in usage list */
1047 if (rpt
->no_of_usages
>= USAGE_MAX
) {
1049 return (HIDPARSER_FAILURE
);
1052 i
= rpt
->no_of_usages
++;
1053 ui
= &(rpt
->usage_descr
[i
]);
1055 hidparser_fill_usage_info(ui
,
1056 current
->entity_item_attributes
);
1058 ui
->rptcnt
/= found_usage
;
1059 ui
->collection_usage
= collection_usage
;
1060 ui
->usage_id
= HID_USAGE_ID(
1064 * This is an extended usage ie.
1065 * usage page in upper 16 bits
1066 * or-ed with usage in the lower
1069 if (usage_id
[j
] >> 16) {
1071 HID_USAGE_PAGE(usage_id
[j
]);
1074 rpt
->report_id
= report_id
;
1078 if (found_usage_min
&& found_usage_max
) {
1080 /* Put in usage list */
1081 if (rpt
->no_of_usages
>= USAGE_MAX
) {
1083 return (HIDPARSER_FAILURE
);
1088 /* handle duplication */
1089 ui
->usage_min
= HID_USAGE_ID(
1091 ui
->usage_max
= HID_USAGE_ID(
1094 i
= rpt
->no_of_usages
++;
1095 ui
= &(rpt
->usage_descr
[i
]);
1097 hidparser_fill_usage_info(ui
,
1099 entity_item_attributes
);
1101 ui
->collection_usage
=
1103 ui
->usage_min
= HID_USAGE_ID(
1105 ui
->usage_max
= HID_USAGE_ID(
1108 rpt
->report_id
= report_id
;
1113 * This is an extended usage ie.
1114 * usage page in upper 16 bits
1115 * or-ed with usage_max in the lower
1118 if (usage_max
>> 16) {
1120 HID_USAGE_PAGE(usage_max
);
1126 * This main item contains no usage
1127 * Fill in with usage "UNDEFINED".
1128 * If report id is valid, only the
1129 * main item with matched report id
1134 if (rpt
->no_of_usages
>= USAGE_MAX
) {
1136 return (HIDPARSER_FAILURE
);
1139 i
= rpt
->no_of_usages
++;
1140 ui
= &(rpt
->usage_descr
[i
]);
1142 hidparser_fill_usage_info(ui
,
1143 current
->entity_item_attributes
);
1145 ui
->collection_usage
= collection_usage
;
1146 ui
->usage_id
= HID_USAGE_UNDEFINED
;
1148 rpt
->report_id
= report_id
;
1153 current
= current
->entity_item_right_sibling
;
1155 } /* end while current */
1157 return (HIDPARSER_SUCCESS
);
1162 * hidparser_fill_usage_info():
1163 * Fill in the mandatory item information for a main item.
1167 hidparser_fill_usage_info(hidparser_usage_info_t
*ui
,
1168 entity_attribute_t
*attribute
)
1170 bzero(ui
, sizeof (*ui
));
1173 switch (attribute
->entity_attribute_tag
) {
1174 case R_ITEM_LOGICAL_MINIMUM
:
1175 ui
->lmin
= hidparser_find_signed_val(attribute
);
1178 case R_ITEM_LOGICAL_MAXIMUM
:
1179 ui
->lmax
= hidparser_find_signed_val(attribute
);
1182 case R_ITEM_REPORT_COUNT
:
1183 ui
->rptcnt
= hidparser_find_unsigned_val(attribute
);
1186 case R_ITEM_REPORT_SIZE
:
1187 ui
->rptsz
= hidparser_find_unsigned_val(attribute
);
1190 case R_ITEM_USAGE_PAGE
:
1191 ui
->usage_page
= hidparser_find_unsigned_val(attribute
)
1197 attribute
= attribute
->entity_attribute_next
;
1203 * hidparser_get_report_id_list:
1204 * Return a list of all report ids used for descriptor items
1205 * corresponding to a main item.
1211 * type of report, either Input, Output, or Feature
1213 * Filled in with a list of report ids found in the descriptor
1216 * HIDPARSER_SUCCESS - returned success
1217 * HIDPARSER_FAILURE - unspecified failure
1220 hidparser_get_report_id_list(hidparser_handle_t parser_handle
,
1221 uint_t main_item_type
,
1222 hidparser_report_id_list_t
*report_id_list
)
1225 if ((parser_handle
== NULL
) ||
1226 (parser_handle
->hidparser_handle_parse_tree
== NULL
)) {
1228 return (HIDPARSER_FAILURE
);
1231 report_id_list
->no_of_report_ids
= 0;
1233 return (hidparser_get_report_id_list_internal(
1234 parser_handle
->hidparser_handle_parse_tree
,
1235 main_item_type
, report_id_list
));
1240 * hidparser_get_report_id_list_internal:
1241 * internal function that generates list of all report ids
1244 hidparser_get_report_id_list_internal(
1245 entity_item_t
*parser_handle
,
1246 uint_t main_item_type
,
1247 hidparser_report_id_list_t
*id_lst
)
1249 /* setup wrapper function */
1250 entity_item_t
*current
= parser_handle
;
1251 entity_attribute_t
*attribute
;
1252 uint_t report_id
= 0;
1258 if (current
->entity_item_type
== R_ITEM_COLLECTION
) {
1260 rval
= hidparser_get_report_id_list_internal(
1261 current
->info
.child
, main_item_type
, id_lst
);
1262 if (rval
!= HIDPARSER_SUCCESS
) {
1267 } else if (current
->entity_item_type
== main_item_type
) {
1268 /* Match Item Type */
1269 attribute
= current
->entity_item_attributes
;
1271 while (attribute
!= NULL
) {
1273 if (attribute
->entity_attribute_tag
==
1276 /* Found a Report ID */
1277 report_id
= attribute
->
1278 entity_attribute_value
[0];
1280 /* Report ID already in list? */
1282 i
< id_lst
->no_of_report_ids
;
1284 if (report_id
== id_lst
->
1291 if (i
>= id_lst
->no_of_report_ids
) {
1293 * New Report ID found, put
1296 if (i
>= REPORT_ID_MAX
) {
1299 (HIDPARSER_FAILURE
);
1302 id_lst
->report_id
[i
] =
1304 id_lst
->no_of_report_ids
++;
1308 attribute
= attribute
->entity_attribute_next
;
1312 current
= current
->entity_item_right_sibling
;
1314 } /* end while current */
1316 return (HIDPARSER_SUCCESS
);
1321 * hidparser_print_report_descr_handle:
1322 * Functions to print the parse tree. Currently not
1326 hidparser_print_report_descr_handle(entity_item_t
*handle
,
1329 entity_item_t
*current
= handle
;
1332 if (current
->info
.child
) {
1333 hidparser_print_entity(current
, indent_level
);
1335 (void) hidparser_print_report_descr_handle(
1336 current
->info
.child
, indent_level
+1);
1337 } else /* just a regular entity */ {
1338 hidparser_print_entity(current
, indent_level
);
1340 current
= current
->entity_item_right_sibling
;
1343 return (HIDPARSER_SUCCESS
);
1347 #define SPACE_PER_LEVEL 5
1350 * hidparser_print_entity ;
1351 * Prints the entity items recursively
1354 hidparser_print_entity(entity_item_t
*entity
, int indent_level
)
1356 char indent_space
[256];
1358 entity_attribute_t
*attr
;
1360 indent_level
*= SPACE_PER_LEVEL
;
1362 for (count
= 0; indent_level
--; count
++)
1363 indent_space
[count
] = ' ';
1365 indent_space
[count
] = 0;
1367 attr
= entity
->entity_item_attributes
;
1369 hidparser_print_this_attribute(attr
, indent_space
);
1370 attr
= attr
->entity_attribute_next
;
1373 USB_DPRINTF_L3(PRINT_MASK_ALL
, hparser_log_handle
, "%s%s(0x%x)",
1374 indent_space
, items
[entity
->entity_item_type
],
1375 (entity
->entity_item_params_leng
?
1376 entity
->entity_item_params
[0] & 0xFF : 0x00));
1381 * hidparser_print_this_attribute:
1382 * Prints the attribute passed in the argument
1385 hidparser_print_this_attribute(entity_attribute_t
*attribute
,
1388 if (ident_space
== NULL
) {
1390 USB_DPRINTF_L3(PRINT_MASK_ALL
, hparser_log_handle
,
1392 items
[attribute
->entity_attribute_tag
],
1393 hidparser_find_unsigned_val(attribute
));
1395 USB_DPRINTF_L3(PRINT_MASK_ALL
, hparser_log_handle
,
1396 "%s%s(0x%X)", ident_space
,
1397 items
[attribute
->entity_attribute_tag
],
1398 hidparser_find_unsigned_val(attribute
));
1405 * The next few functions will be used for parsing using the
1408 * Start -> ReportDescriptor <EOF>
1410 * ReportDescriptor -> ItemList
1412 * ItemList -> Items MainItem ItemList
1415 * MainItem -> BeginCollection ItemList EndCollection
1420 * Items -> GlobalItem Items
1422 * | SetDelimiterOpen LocalItemList
1423 * SetDelimiterClose Items
1426 * LocalItemList -> LocalItem Temp2
1428 * Temp2 -> LocalItem Temp2
1431 * GlobalItem -> UsagePage
1442 * LocalItem -> Usage
1446 * | DesignatorMinimum
1455 * hidparser_lookup_first:
1456 * Looks up if token belongs to the FIRST of the function tag
1457 * that is passed through the first argument
1460 hidparser_lookup_first(int func_index
,
1465 itemp
= hid_first_list
[func_index
];
1466 while (*itemp
!= 0) {
1467 /* get the next terminal on the list */
1468 if (*itemp
== token
) {
1470 return (HIDPARSER_SUCCESS
);
1475 /* token is not on the FIRST list */
1477 return (HIDPARSER_FAILURE
);
1483 * Function called from hidparser_parse_report_descriptor()
1484 * to parse the Report Descriptor
1487 hidparser_main(unsigned char *descriptor
,
1489 entity_item_t
**item_ptr
)
1491 hidparser_tok_t
*scan_ifp
;
1494 scan_ifp
= kmem_zalloc(sizeof (hidparser_tok_t
), KM_SLEEP
);
1495 scan_ifp
->hidparser_tok_text
=
1496 kmem_zalloc(HIDPARSER_TEXT_LENGTH
, KM_SLEEP
);
1497 scan_ifp
->hidparser_tok_max_bsize
= size
;
1498 scan_ifp
->hidparser_tok_entity_descriptor
= descriptor
;
1501 retval
= hidparser_ReportDescriptorDash(item_ptr
, scan_ifp
);
1504 * Free the Local & Global item list
1505 * It maybe the case that no tree has been built
1506 * up but there have been allocation in the attribute
1509 if (scan_ifp
->hidparser_tok_gitem_head
) {
1510 hidparser_free_attribute_list(
1511 scan_ifp
->hidparser_tok_gitem_head
);
1514 if (scan_ifp
->hidparser_tok_litem_head
) {
1515 hidparser_free_attribute_list(
1516 scan_ifp
->hidparser_tok_litem_head
);
1518 kmem_free(scan_ifp
->hidparser_tok_text
, HIDPARSER_TEXT_LENGTH
);
1519 kmem_free(scan_ifp
, sizeof (hidparser_tok_t
));
1526 * hidparser_ReportDescriptorDash:
1527 * Synthetic start symbol, implements
1528 * hidparser_ReportDescriptor <EOF>
1531 hidparser_ReportDescriptorDash(entity_item_t
** item_ptr
,
1532 hidparser_tok_t
*scan_ifp
)
1535 if ((hidparser_ReportDescriptor(item_ptr
, scan_ifp
) ==
1536 HIDPARSER_SUCCESS
) && (scan_ifp
->hidparser_tok_token
== 0)) {
1538 return (HIDPARSER_SUCCESS
);
1542 * In case of failure, free the kernel memory
1543 * allocated for partial building of the tree,
1546 if (*item_ptr
!= NULL
) {
1547 (void) hidparser_free_report_descr_handle(*item_ptr
);
1552 return (HIDPARSER_FAILURE
);
1557 * hidparser_ReportDescriptor:
1558 * Implements the Rule:
1559 * ReportDescriptor -> ItemList
1562 hidparser_ReportDescriptor(entity_item_t
** item_ptr
,
1563 hidparser_tok_t
*scan_ifp
)
1565 hidparser_scan(scan_ifp
);
1568 * We do not search for the token in FIRST(ReportDescriptor)
1571 * FIRST(ReportDescriptor) == FIRST(ItemList)
1572 * ReportDescriptor ----> ItemList
1574 if (hidparser_ItemList(item_ptr
, scan_ifp
) == HIDPARSER_SUCCESS
) {
1576 return (HIDPARSER_SUCCESS
);
1579 return (HIDPARSER_FAILURE
);
1584 * hidparser_ItemList:
1585 * Implements the Rule:
1586 * ItemList -> Items MainItem ItemList | epsilon
1588 * This function constructs the tree on which depends the "hidparser"
1589 * consumer functions. Basically the structure of the tree is
1591 * C--[RS]->EC--[RS]->C--[RS]->EC..(and so on)
1593 * [CH] <== This relationship is true for other "C's"
1596 * C/-------------/I/O/F <== [ Any of these ]
1601 * C/I/O/F | EC I/O/F
1606 * where C = Collection
1607 * EC = EndCollection
1610 * F = Feature "Main" Items.
1612 * and the relationships are [RS] for right sibling and [CH] for
1613 * child. [CH | RS ] stands for "child or right sibling" with the
1614 * possible values below it.
1617 hidparser_ItemList(entity_item_t
** item_ptr
, hidparser_tok_t
*scan_ifp
)
1619 entity_item_t
*curr_ei
, *cache_ei
, *prev_ei
, *tmp_ei
;
1620 boolean_t root_coll
= B_FALSE
;
1622 curr_ei
= cache_ei
= prev_ei
= tmp_ei
= NULL
;
1624 while (scan_ifp
->hidparser_tok_token
!= 0) {
1625 if (hidparser_Items(scan_ifp
) == HIDPARSER_FAILURE
) {
1627 return (HIDPARSER_FAILURE
);
1630 if (hidparser_MainItem(&curr_ei
, scan_ifp
) ==
1631 HIDPARSER_FAILURE
) {
1632 USB_DPRINTF_L2(PRINT_MASK_ALL
,
1634 "Invalid MAIN item 0x%x in input stream",
1635 scan_ifp
->hidparser_tok_token
);
1637 return (HIDPARSER_FAILURE
);
1639 if (curr_ei
->entity_item_type
== R_ITEM_COLLECTION
) {
1640 if (root_coll
== B_FALSE
) {
1641 *item_ptr
= curr_ei
;
1644 curr_ei
->prev_coll
= cache_ei
;
1647 USB_DPRINTF_L3(PRINT_MASK_ALL
,
1649 "Start Collection:cache_ei = 0x%p,"
1651 (void *)cache_ei
, (void *)curr_ei
);
1653 if (prev_ei
== NULL
) {
1658 if (prev_ei
->entity_item_type
==
1659 R_ITEM_COLLECTION
) {
1660 prev_ei
->info
.child
= curr_ei
;
1662 prev_ei
->entity_item_right_sibling
=
1665 } else if (curr_ei
->entity_item_type
==
1666 R_ITEM_END_COLLECTION
) {
1667 tmp_ei
= cache_ei
->prev_coll
;
1668 cache_ei
->entity_item_right_sibling
= curr_ei
;
1669 USB_DPRINTF_L3(PRINT_MASK_ALL
,
1671 "End Collection: cache_ei = 0x%p, "
1673 (void *)cache_ei
, (void *)curr_ei
);
1674 if (tmp_ei
!= NULL
) {
1676 * As will be the case for final end
1683 if (prev_ei
== NULL
) {
1684 USB_DPRINTF_L2(PRINT_MASK_ALL
,
1686 "Invalid First MAIN item 0x%x",
1687 scan_ifp
->hidparser_tok_token
);
1689 return (HIDPARSER_FAILURE
);
1691 if (prev_ei
->entity_item_type
==
1692 R_ITEM_COLLECTION
) {
1693 USB_DPRINTF_L3(PRINT_MASK_ALL
,
1695 "Main Item: token = 0x%x, "
1697 "will be the child of prev_ei "
1699 "cache_ei being 0x%p",
1700 curr_ei
->entity_item_type
,
1701 (void *)curr_ei
, (void *)prev_ei
,
1703 prev_ei
->info
.child
= curr_ei
;
1705 USB_DPRINTF_L3(PRINT_MASK_ALL
,
1707 "Main Item: token = 0x%x, "
1709 "will be the right sibling of "
1711 "cache_ei being 0x%p",
1712 curr_ei
->entity_item_type
,
1713 (void *)curr_ei
, (void *)prev_ei
,
1715 prev_ei
->entity_item_right_sibling
=
1721 if (*item_ptr
!= cache_ei
) {
1722 /* Something wrong happened */
1723 USB_DPRINTF_L2(PRINT_MASK_ALL
, hparser_log_handle
,
1724 "Failed to parse report descriptor");
1726 return (HIDPARSER_FAILURE
);
1728 (void) hidparser_print_report_descr_handle(cache_ei
, 0);
1730 return (HIDPARSER_SUCCESS
);
1735 * hidparser_MainItem:
1736 * Implements the Rule:
1737 * MainItem -> BeginCollection ItemList EndCollection
1743 hidparser_MainItem(entity_item_t
** item_ptr
,
1744 hidparser_tok_t
*scan_ifp
)
1746 switch (scan_ifp
->hidparser_tok_token
) {
1751 case R_ITEM_FEATURE
:
1752 case R_ITEM_COLLECTION
:
1753 case R_ITEM_END_COLLECTION
:
1754 *item_ptr
= hidparser_allocate_entity(scan_ifp
);
1755 USB_DPRINTF_L4(PRINT_MASK_ALL
, hparser_log_handle
,
1756 "hidparser_MainItem:index = 0x%lx token = 0x%x",
1757 scan_ifp
->hidparser_tok_index
-
1758 (*item_ptr
)->entity_item_params_leng
- 1,
1759 scan_ifp
->hidparser_tok_token
);
1760 hidparser_scan(scan_ifp
);
1761 hidparser_global_err_check(*item_ptr
);
1762 hidparser_local_err_check(*item_ptr
);
1763 hidparser_mainitem_err_check(*item_ptr
);
1765 return (HIDPARSER_SUCCESS
);
1773 return (HIDPARSER_FAILURE
);
1779 * Implements the Rule:
1780 * Items -> GlobalItem Items
1782 * | SetDelimiterOpen LocalItemList
1783 * SetDelimiterClose Items
1787 hidparser_Items(hidparser_tok_t
*scan_ifp
)
1789 boolean_t delim_pre
= B_FALSE
;
1791 int token
= scan_ifp
->hidparser_tok_token
;
1793 while (hidparser_lookup_first(HIDPARSER_ITEMS
, token
) ==
1794 HIDPARSER_SUCCESS
) {
1795 if (token
== R_ITEM_SET_DELIMITER
) {
1796 if (delim_pre
== B_FALSE
) {
1797 if (scan_ifp
->hidparser_tok_text
[0] != 1) {
1798 hidparser_error_delim(NULL
,
1799 HIDPARSER_DELIM_ERR1
);
1804 if (scan_ifp
->hidparser_tok_text
[0] !=
1806 hidparser_error_delim(NULL
,
1807 HIDPARSER_DELIM_ERR2
);
1809 delim_pre
= B_FALSE
;
1812 (void) hidparser_LocalItem(scan_ifp
);
1813 token
= scan_ifp
->hidparser_tok_token
;
1814 } else if (hidparser_GlobalItem(scan_ifp
) ==
1815 HIDPARSER_SUCCESS
) {
1816 token
= scan_ifp
->hidparser_tok_token
;
1817 } else if (hidparser_LocalItem(scan_ifp
) == HIDPARSER_SUCCESS
) {
1818 token
= scan_ifp
->hidparser_tok_token
;
1822 return (HIDPARSER_SUCCESS
); /* epsilon */
1827 * hidparser_GlobalItem:
1828 * Implements the Rule:
1829 * GlobalItem -> UsagePage
1841 hidparser_GlobalItem(hidparser_tok_t
*scan_ifp
)
1845 entity_attribute_stack_t
*elem
;
1847 switch (scan_ifp
->hidparser_tok_token
) {
1848 case R_ITEM_USAGE_PAGE
:
1850 for (i
= 0; i
< scan_ifp
->hidparser_tok_leng
; i
++) {
1851 /* Undefined data value: 0 */
1852 if (scan_ifp
->hidparser_tok_text
[i
] == 0) {
1853 hidparser_report_err(
1855 HIDPARSER_ERR_STANDARD
,
1858 "Data field should be non-Zero");
1860 /* Reserved values 0x0A-0xFE */
1861 else if ((scan_ifp
->hidparser_tok_text
[i
] >=
1863 (scan_ifp
->hidparser_tok_text
[i
] <=
1865 hidparser_report_err(
1867 HIDPARSER_ERR_STANDARD
,
1870 "Data field should not use "
1877 case R_ITEM_EXPONENT
:
1880 * Nibble 7 should be zero
1882 if (scan_ifp
->hidparser_tok_leng
== 4) {
1883 if ((scan_ifp
->hidparser_tok_text
[3] &
1885 hidparser_report_err(
1887 HIDPARSER_ERR_STANDARD
,
1888 scan_ifp
->hidparser_tok_token
,
1890 "Data field reserved bits should "
1895 case R_ITEM_REPORT_COUNT
:
1898 * Report Count should be nonzero
1900 for (i
= 0; i
< scan_ifp
->hidparser_tok_leng
; i
++) {
1901 if (scan_ifp
->hidparser_tok_text
[i
])
1904 if (i
== scan_ifp
->hidparser_tok_leng
) {
1905 hidparser_report_err(
1906 HIDPARSER_ERR_ERROR
,
1907 HIDPARSER_ERR_STANDARD
,
1908 R_ITEM_REPORT_COUNT
,
1910 "Report Count = 0");
1913 case R_ITEM_REPORT_ID
:
1916 * Report Id should be nonzero & <= 255
1918 if (scan_ifp
->hidparser_tok_leng
!= 1) {
1919 hidparser_report_err(
1920 HIDPARSER_ERR_ERROR
,
1921 HIDPARSER_ERR_STANDARD
,
1924 "Must be contained in a byte");
1926 if (!scan_ifp
->hidparser_tok_text
[0]) {
1927 hidparser_report_err(
1928 HIDPARSER_ERR_ERROR
,
1929 HIDPARSER_ERR_STANDARD
,
1932 "Report Id must be non-zero");
1935 case R_ITEM_LOGICAL_MINIMUM
:
1937 case R_ITEM_LOGICAL_MAXIMUM
:
1939 case R_ITEM_PHYSICAL_MINIMUM
:
1941 case R_ITEM_PHYSICAL_MAXIMUM
:
1943 case R_ITEM_REPORT_SIZE
:
1946 if (scan_ifp
->hidparser_tok_leng
!= 0) {
1947 hidparser_report_err(
1948 HIDPARSER_ERR_ERROR
,
1949 HIDPARSER_ERR_STANDARD
,
1950 scan_ifp
->hidparser_tok_token
,
1952 "Data Field size should be zero");
1954 elem
= (entity_attribute_stack_t
*)kmem_zalloc(
1955 sizeof (entity_attribute_stack_t
),
1958 elem
->list
= hidparser_cp_attribute_list(
1959 scan_ifp
->hidparser_tok_gitem_head
);
1960 if (scan_ifp
->hidparser_head
) {
1961 elem
->next
= scan_ifp
->hidparser_head
;
1963 scan_ifp
->hidparser_head
= elem
;
1968 if (scan_ifp
->hidparser_tok_leng
!= 0) {
1969 hidparser_report_err(
1970 HIDPARSER_ERR_ERROR
,
1971 HIDPARSER_ERR_STANDARD
,
1972 scan_ifp
->hidparser_tok_token
,
1974 "Data Field size should be zero");
1976 /* Free the current global list */
1977 hidparser_free_attribute_list(scan_ifp
->
1978 hidparser_tok_gitem_head
);
1979 scan_ifp
->hidparser_tok_gitem_head
=
1980 scan_ifp
->hidparser_head
->list
;
1981 scan_ifp
->hidparser_head
->list
= NULL
;
1982 elem
= scan_ifp
->hidparser_head
;
1983 scan_ifp
->hidparser_head
= elem
->next
;
1985 sizeof (entity_attribute_stack_t
));
1991 return (HIDPARSER_FAILURE
);
1996 hidparser_add_attribute(scan_ifp
);
1997 USB_DPRINTF_L4(PRINT_MASK_ALL
, hparser_log_handle
,
1998 "hidparser_GlobalItem:index = 0x%lx token = 0x%x",
1999 scan_ifp
->hidparser_tok_index
-
2000 scan_ifp
->hidparser_tok_leng
- 1,
2001 scan_ifp
->hidparser_tok_token
);
2002 hidparser_scan(scan_ifp
);
2004 return (HIDPARSER_SUCCESS
);
2009 * hidparser_LocalItem:
2010 * Implements the Rule:
2011 * LocalItem -> Usage
2015 * | DesignatorMinimum
2021 hidparser_LocalItem(hidparser_tok_t
*scan_ifp
)
2025 switch (scan_ifp
->hidparser_tok_token
) {
2029 * Data Field should be nonzero
2031 for (i
= 0; i
< scan_ifp
->hidparser_tok_leng
; i
++) {
2032 if (scan_ifp
->hidparser_tok_text
[i
])
2035 if (i
== scan_ifp
->hidparser_tok_leng
) {
2036 hidparser_report_err(
2038 HIDPARSER_ERR_STANDARD
,
2041 "Data Field should be non-zero");
2044 case R_ITEM_USAGE_MIN
:
2046 case R_ITEM_USAGE_MAX
:
2048 case R_ITEM_DESIGNATOR_INDEX
:
2050 case R_ITEM_DESIGNATOR_MIN
:
2052 case R_ITEM_STRING_INDEX
:
2054 case R_ITEM_STRING_MIN
:
2056 case R_ITEM_STRING_MAX
:
2058 case R_ITEM_SET_DELIMITER
:
2059 hidparser_add_attribute(scan_ifp
);
2060 USB_DPRINTF_L4(PRINT_MASK_ALL
, hparser_log_handle
,
2061 "hidparser_LocalItem:index = 0x%lx token = 0x%x",
2062 scan_ifp
->hidparser_tok_index
-
2063 scan_ifp
->hidparser_tok_leng
- 1,
2064 scan_ifp
->hidparser_tok_token
);
2065 hidparser_scan(scan_ifp
);
2067 return (HIDPARSER_SUCCESS
);
2074 return (HIDPARSER_FAILURE
);
2079 * hidparser_allocate_entity:
2080 * Allocate Item of type 'type', length 'leng' and
2081 * params 'text'. Fill in the attributes allocated
2082 * so far from both the local and global item lists.
2083 * Make the child and sibling of the item NULL.
2085 static entity_item_t
*
2086 hidparser_allocate_entity(hidparser_tok_t
*scan_ifp
)
2088 entity_item_t
*entity
;
2089 entity_attribute_t
*aend
;
2091 int entity_type
= scan_ifp
->hidparser_tok_token
;
2092 unsigned char *text
= scan_ifp
->hidparser_tok_text
;
2093 int len
= scan_ifp
->hidparser_tok_leng
;
2095 entity
= kmem_zalloc(sizeof (entity_item_t
), KM_SLEEP
);
2096 entity
->entity_item_type
= entity_type
;
2097 entity
->entity_item_params_leng
= len
;
2100 entity
->entity_item_params
= kmem_zalloc(len
, KM_SLEEP
);
2101 (void) bcopy(text
, entity
->entity_item_params
, len
);
2105 * Copy attributes from entity attribute state table if not
2108 if (entity_type
!= R_ITEM_END_COLLECTION
) {
2109 entity
->entity_item_attributes
= hidparser_cp_attribute_list(
2110 scan_ifp
->hidparser_tok_gitem_head
);
2113 * append the control attributes, then clear out the control
2114 * attribute state table list
2116 if (entity
->entity_item_attributes
) {
2117 aend
= hidparser_find_attribute_end(
2118 entity
->entity_item_attributes
);
2119 aend
->entity_attribute_next
=
2120 scan_ifp
->hidparser_tok_litem_head
;
2121 scan_ifp
->hidparser_tok_litem_head
= NULL
;
2123 entity
->entity_item_attributes
=
2124 scan_ifp
->hidparser_tok_litem_head
;
2125 scan_ifp
->hidparser_tok_litem_head
= NULL
;
2129 entity
->info
.child
= entity
->entity_item_right_sibling
= 0;
2136 * hidparser_add_attribute:
2137 * Add an attribute to the global or local item list
2138 * If the last 4th bit from right is 1, add to the local item list
2139 * Else add to the global item list
2142 hidparser_add_attribute(hidparser_tok_t
*scan_ifp
)
2144 entity_attribute_t
*newattrib
, **previous
, *elem
;
2145 int entity
= scan_ifp
->hidparser_tok_token
;
2146 unsigned char *text
= scan_ifp
->hidparser_tok_text
;
2147 int len
= scan_ifp
->hidparser_tok_leng
;
2150 USB_DPRINTF_L2(PRINT_MASK_ALL
, hparser_log_handle
,
2151 "hidparser_add_attribute: len = 0 for item = 0x%x",
2157 if (entity
& HIDPARSER_ISLOCAL_MASK
) {
2158 previous
= &scan_ifp
->hidparser_tok_litem_head
;
2160 previous
= &scan_ifp
->hidparser_tok_gitem_head
;
2166 * remove attribute if it is already on list, except
2167 * for control attributes(local items), as we could have
2168 * multiple usages...
2169 * unless we want to hassle with checking for unique parameters.
2172 if (elem
->entity_attribute_tag
== entity
&&
2173 !(entity
& HIDPARSER_ISLOCAL_MASK
)) {
2174 *previous
= elem
->entity_attribute_next
;
2175 kmem_free(elem
->entity_attribute_value
,
2176 elem
->entity_attribute_length
);
2177 kmem_free(elem
, sizeof (entity_attribute_t
));
2180 previous
= &elem
->entity_attribute_next
;
2181 elem
= elem
->entity_attribute_next
;
2185 /* create new attribute for this entry */
2186 newattrib
= hidparser_alloc_attrib_list(1);
2187 newattrib
->entity_attribute_tag
= entity
;
2188 newattrib
->entity_attribute_value
= kmem_zalloc(len
, KM_SLEEP
);
2189 (void) bcopy(text
, newattrib
->entity_attribute_value
, len
);
2190 newattrib
->entity_attribute_length
= len
;
2192 /* attach to end of list */
2193 *previous
= newattrib
;
2198 * hidparser_alloc_attrib_list:
2199 * Allocate space for n attributes , create a linked list and
2202 static entity_attribute_t
*
2203 hidparser_alloc_attrib_list(int count
)
2205 entity_attribute_t
*head
, *current
;
2212 head
= kmem_zalloc(sizeof (entity_attribute_t
), KM_SLEEP
);
2216 current
->entity_attribute_next
= kmem_zalloc(
2217 sizeof (entity_attribute_t
), KM_SLEEP
);
2218 current
= current
->entity_attribute_next
;
2220 current
->entity_attribute_next
= NULL
;
2227 * hidparser_cp_attribute_list:
2228 * Copies the Global item list pointed to by head
2229 * We create a clone of the global item list here
2230 * because we want to retain the Global items to
2231 * the next Main Item.
2233 static entity_attribute_t
*
2234 hidparser_cp_attribute_list(entity_attribute_t
*head
)
2236 entity_attribute_t
*return_value
, *current_src
, *current_dst
;
2244 current_dst
= return_value
= hidparser_alloc_attrib_list(1);
2246 while (current_src
) {
2247 current_dst
->entity_attribute_tag
=
2248 current_src
->entity_attribute_tag
;
2249 current_dst
->entity_attribute_length
=
2250 current_src
->entity_attribute_length
;
2251 current_dst
->entity_attribute_value
= kmem_zalloc(
2252 current_dst
->entity_attribute_length
, KM_SLEEP
);
2253 (void) bcopy(current_src
->entity_attribute_value
,
2254 current_dst
->entity_attribute_value
,
2255 current_src
->entity_attribute_length
);
2256 if (current_src
->entity_attribute_next
) {
2257 current_dst
->entity_attribute_next
=
2258 hidparser_alloc_attrib_list(1);
2260 current_dst
->entity_attribute_next
= NULL
;
2262 current_src
= current_src
->entity_attribute_next
;
2263 current_dst
= current_dst
->entity_attribute_next
;
2266 return (return_value
);
2271 * hidparser_find_attribute_end:
2272 * Find the last item in the attribute list pointed to by head
2274 static entity_attribute_t
*
2275 hidparser_find_attribute_end(entity_attribute_t
*head
)
2281 while (head
->entity_attribute_next
!= NULL
) {
2282 head
= head
->entity_attribute_next
;
2290 * hidparser_free_report_descr_handle:
2291 * Free the parse tree pointed to by handle
2294 hidparser_free_report_descr_handle(entity_item_t
*handle
)
2296 entity_item_t
*next
, *current
, *child
;
2301 child
= current
->info
.child
;
2302 next
= current
->entity_item_right_sibling
;
2303 if (current
->entity_item_type
== R_ITEM_COLLECTION
) {
2304 if (current
->entity_item_params
!= NULL
)
2305 kmem_free(current
->entity_item_params
,
2306 current
->entity_item_params_leng
);
2307 if (current
->entity_item_attributes
!= NULL
)
2308 hidparser_free_attribute_list(
2309 current
->entity_item_attributes
);
2310 USB_DPRINTF_L4(PRINT_MASK_ALL
, hparser_log_handle
,
2312 items
[current
->entity_item_type
]);
2313 kmem_free(current
, sizeof (entity_item_t
));
2314 (void) hidparser_free_report_descr_handle(child
);
2316 if (current
->entity_item_params
!= NULL
) {
2317 kmem_free(current
->entity_item_params
,
2318 current
->entity_item_params_leng
);
2320 if (current
->entity_item_attributes
!= NULL
) {
2321 hidparser_free_attribute_list(
2322 current
->entity_item_attributes
);
2324 USB_DPRINTF_L4(PRINT_MASK_ALL
,
2325 hparser_log_handle
, "FREE 2: %s",
2326 items
[current
->entity_item_type
]);
2327 kmem_free(current
, sizeof (entity_item_t
));
2336 * hidparser_free_attribute_list:
2337 * Free the attribute list pointed to by head
2340 hidparser_free_attribute_list(entity_attribute_t
*head
)
2342 entity_attribute_t
*next
, *current
;
2347 next
= current
->entity_attribute_next
;
2348 USB_DPRINTF_L4(PRINT_MASK_ALL
,
2349 hparser_log_handle
, "FREE: %s value_length = %d",
2350 items
[current
->entity_attribute_tag
],
2351 current
->entity_attribute_length
);
2353 if (current
->entity_attribute_value
!= NULL
) {
2354 USB_DPRINTF_L4(PRINT_MASK_ALL
,
2357 current
->entity_attribute_value
[0]);
2358 kmem_free(current
->entity_attribute_value
,
2359 current
->entity_attribute_length
);
2362 kmem_free(current
, sizeof (entity_attribute_t
));
2369 * hidparser_initialize_items:
2370 * Initialize items array before start scanning and parsing.
2371 * This array of strings are used for printing purpose.
2374 hidparser_initialize_items(void)
2376 items
[R_ITEM_USAGE
] = "Usage";
2377 items
[R_ITEM_USAGE_MIN
] = "Usage Minimum";
2378 items
[R_ITEM_USAGE_MAX
] = "Usage Maximum";
2379 items
[R_ITEM_DESIGNATOR_INDEX
] = "Designator Index";
2380 items
[R_ITEM_DESIGNATOR_MIN
] = "Designator Minimum";
2381 items
[R_ITEM_DESIGNATOR_MAX
] = "Designator Maximum";
2382 items
[R_ITEM_STRING_INDEX
] = "String Index";
2383 items
[R_ITEM_STRING_MIN
] = "String Minimum";
2384 items
[R_ITEM_STRING_MAX
] = "String Maximum";
2387 items
[R_ITEM_USAGE_PAGE
] = "Usage Page";
2388 items
[R_ITEM_LOGICAL_MINIMUM
] = "Logical Minimum";
2389 items
[R_ITEM_LOGICAL_MAXIMUM
] = "Logical Maximum";
2390 items
[R_ITEM_PHYSICAL_MINIMUM
] = "Physical Minimum";
2391 items
[R_ITEM_PHYSICAL_MAXIMUM
] = "Physical Maximum";
2392 items
[R_ITEM_EXPONENT
] = "Exponent";
2393 items
[R_ITEM_UNIT
] = "Unit";
2394 items
[R_ITEM_REPORT_SIZE
] = "Report Size";
2395 items
[R_ITEM_REPORT_ID
] = "Report Id";
2396 items
[R_ITEM_REPORT_COUNT
] = "Report Count";
2397 items
[R_ITEM_PUSH
] = "Push";
2398 items
[R_ITEM_POP
] = "Pop";
2401 items
[R_ITEM_INPUT
] = "Input";
2402 items
[R_ITEM_OUTPUT
] = "Output";
2403 items
[R_ITEM_COLLECTION
] = "Collection";
2404 items
[R_ITEM_FEATURE
] = "Feature";
2405 items
[R_ITEM_END_COLLECTION
] = "End Collection";
2407 items
[R_ITEM_SET_DELIMITER
] = "Delimiter";
2413 * This function scans the input entity descriptor, sees the data
2414 * length, returns the next token, data bytes and length in the
2415 * scan_ifp structure.
2418 hidparser_scan(hidparser_tok_t
*scan_ifp
)
2423 unsigned char *parsed_text
;
2424 unsigned char *entity_descriptor
;
2426 size_t entity_buffer_size
, index
;
2428 index
= scan_ifp
->hidparser_tok_index
;
2429 entity_buffer_size
= scan_ifp
->hidparser_tok_max_bsize
;
2431 parsed_text
= scan_ifp
->hidparser_tok_text
;
2432 entity_descriptor
= scan_ifp
->hidparser_tok_entity_descriptor
;
2435 if (index
<= entity_buffer_size
-1) {
2437 ch
= 0xFF & entity_descriptor
[index
];
2438 USB_DPRINTF_L4(PRINT_MASK_ALL
,
2439 hparser_log_handle
, "scanner: index = 0x%lx ch = 0x%x",
2446 * Unrecognized items should be passed over
2450 if (!(hidparser_isvalid_item(ch
))) {
2451 (void) sprintf(err_str
, "%s: 0x%2x",
2452 "Unknown or reserved item", ch
);
2453 hidparser_report_err(HIDPARSER_ERR_ERROR
,
2454 HIDPARSER_ERR_STANDARD
, 0, 0x3F, err_str
);
2458 if (ch
== EXTENDED_ITEM
) {
2459 parsed_length
= entity_descriptor
[index
++];
2460 ch
= entity_descriptor
[index
++];
2461 hidparser_report_err(HIDPARSER_ERR_WARN
,
2462 HIDPARSER_ERR_STANDARD
,
2465 "Long item defined");
2467 parsed_length
= ch
& 0x03;
2468 USB_DPRINTF_L4(PRINT_MASK_ALL
,
2470 "scanner: parsed_length = %x", parsed_length
);
2471 /* 3 really means 4.. see p.21 HID */
2472 if (parsed_length
== 3)
2475 for (count
= 0; count
< parsed_length
; count
++) {
2476 parsed_text
[count
] = entity_descriptor
[index
];
2477 USB_DPRINTF_L4(PRINT_MASK_ALL
, hparser_log_handle
,
2478 "scanner: parsed_text[%d] = 0x%x,"
2480 count
, parsed_text
[count
], index
);
2484 USB_DPRINTF_L4(PRINT_MASK_ALL
,
2485 hparser_log_handle
, "scanner: lexical analyzer found 0x%x "
2486 "before translation", ch
);
2488 scan_ifp
->hidparser_tok_index
= index
;
2489 scan_ifp
->hidparser_tok_leng
= parsed_length
;
2490 scan_ifp
->hidparser_tok_token
= ch
& 0xFC;
2491 USB_DPRINTF_L4(PRINT_MASK_ALL
,
2492 hparser_log_handle
, "scanner: aindex = 0x%lx", index
);
2494 USB_DPRINTF_L4(PRINT_MASK_ALL
,
2495 hparser_log_handle
, "scanner: eindex = 0x%lx", index
);
2496 scan_ifp
->hidparser_tok_leng
= 0;
2497 scan_ifp
->hidparser_tok_token
= 0; /* EOF */
2503 * hidparser_report_err:
2504 * Construct and print the error code
2505 * Ref: Hidview error check list
2508 hidparser_report_err(int err_level
,
2514 unsigned int BmParserErrorCode
= 0;
2517 BmParserErrorCode
|= HIDPARSER_ERR_ERROR
;
2520 BmParserErrorCode
|= HIDPARSER_ERR_STANDARD
;
2522 BmParserErrorCode
|= (tag
<< 8) & HIDPARSER_ERR_TAG_MASK
;
2523 BmParserErrorCode
|= subcode
& HIDPARSER_ERR_SUBCODE_MASK
;
2526 USB_DPRINTF_L2(PRINT_MASK_ALL
, hparser_log_handle
,
2527 "err code = 0x%4x, err str = %s",
2528 BmParserErrorCode
, msg
);
2531 USB_DPRINTF_L2(PRINT_MASK_ALL
, hparser_log_handle
,
2532 "wrn code = 0x%4x, wrn str = %s",
2533 BmParserErrorCode
, msg
);
2539 * hidparser_isvalid_item:
2540 * Find if the item tag is a valid one
2543 hidparser_isvalid_item(int tag
)
2545 if (tag
== EXTENDED_ITEM
) {
2551 if ((tag
== R_ITEM_INPUT
) ||
2552 (tag
== R_ITEM_OUTPUT
) ||
2553 (tag
== R_ITEM_COLLECTION
) ||
2554 (tag
== R_ITEM_FEATURE
) ||
2555 (tag
== R_ITEM_END_COLLECTION
) ||
2556 (tag
== R_ITEM_USAGE_PAGE
) ||
2557 (tag
== R_ITEM_LOGICAL_MINIMUM
) ||
2558 (tag
== R_ITEM_LOGICAL_MAXIMUM
) ||
2559 (tag
== R_ITEM_PHYSICAL_MINIMUM
) ||
2560 (tag
== R_ITEM_PHYSICAL_MAXIMUM
) ||
2561 (tag
== R_ITEM_EXPONENT
) ||
2562 (tag
== R_ITEM_UNIT
) ||
2563 (tag
== R_ITEM_REPORT_SIZE
) ||
2564 (tag
== R_ITEM_REPORT_ID
) ||
2565 (tag
== R_ITEM_REPORT_COUNT
) ||
2566 (tag
== R_ITEM_PUSH
) ||
2567 (tag
== R_ITEM_POP
) ||
2568 (tag
== R_ITEM_USAGE
) ||
2569 (tag
== R_ITEM_USAGE_MIN
) ||
2570 (tag
== R_ITEM_USAGE_MAX
) ||
2571 (tag
== R_ITEM_DESIGNATOR_INDEX
) ||
2572 (tag
== R_ITEM_DESIGNATOR_MIN
) ||
2573 (tag
== R_ITEM_DESIGNATOR_MAX
) ||
2574 (tag
== R_ITEM_STRING_INDEX
) ||
2575 (tag
== R_ITEM_STRING_MIN
) ||
2576 (tag
== R_ITEM_STRING_MAX
) ||
2577 (tag
== R_ITEM_SET_DELIMITER
)) {
2588 * hidparser_lookup_attribute:
2589 * Takes an item pointer(report structure) and a tag(e.g Logical
2590 * Min) as input. Returns the corresponding attribute structure.
2591 * Presently used for error checking only.
2593 static entity_attribute_t
*
2594 hidparser_lookup_attribute(entity_item_t
*item
, int attr_tag
)
2596 entity_attribute_t
*temp
;
2603 temp
= item
->entity_item_attributes
;
2604 while (temp
!= NULL
) {
2605 if (temp
->entity_attribute_tag
== attr_tag
) {
2610 temp
= temp
->entity_attribute_next
;
2618 * hidparser_global_err_check:
2619 * Error checking for Global Items that need to be
2620 * performed in MainItem
2623 hidparser_global_err_check(entity_item_t
*mainitem
)
2625 hidparser_check_minmax_val_signed(mainitem
, R_ITEM_LOGICAL_MINIMUM
,
2626 R_ITEM_LOGICAL_MAXIMUM
, 0, 0);
2627 hidparser_check_minmax_val_signed(mainitem
, R_ITEM_PHYSICAL_MINIMUM
,
2628 R_ITEM_PHYSICAL_MAXIMUM
, 0, 0);
2629 hidparser_check_correspondence(mainitem
, R_ITEM_PHYSICAL_MINIMUM
,
2630 R_ITEM_PHYSICAL_MAXIMUM
, 0, 0,
2631 "Must have a corresponding Physical min",
2632 "Must have a corresponding Physical max");
2633 hidparser_check_correspondence(mainitem
, R_ITEM_PUSH
, R_ITEM_POP
,
2634 1, 0, "Should have a corresponding Pop",
2635 "Must have a corresponding Push");
2641 * hidparser_mainitem_err_check:
2642 * Error checking for Main Items
2645 hidparser_mainitem_err_check(entity_item_t
*mainitem
)
2648 entity_attribute_t
*attr
;
2650 attr
= mainitem
->entity_item_attributes
;
2654 switch (attr
->entity_attribute_tag
) {
2655 case R_ITEM_LOGICAL_MINIMUM
:
2658 case R_ITEM_LOGICAL_MAXIMUM
:
2661 case R_ITEM_REPORT_SIZE
:
2664 case R_ITEM_REPORT_COUNT
:
2667 case R_ITEM_USAGE_PAGE
:
2673 attr
= attr
->entity_attribute_next
;
2677 if ((mainitem
->entity_item_type
== R_ITEM_COLLECTION
) ||
2678 (mainitem
->entity_item_type
== R_ITEM_END_COLLECTION
)) {
2682 if (itemmask
!= 0x1f) {
2683 hidparser_report_err(
2684 HIDPARSER_ERR_ERROR
,
2685 HIDPARSER_ERR_STANDARD
,
2686 mainitem
->entity_item_type
,
2688 "Required Global/Local items must be defined");
2694 * hidparser_local_err_check:
2695 * Error checking for Local items that is done when a MainItem
2699 hidparser_local_err_check(entity_item_t
*mainitem
)
2701 hidparser_check_correspondence(mainitem
, R_ITEM_USAGE_MIN
,
2702 R_ITEM_USAGE_MAX
, 0, 0,
2703 "Must have a corresponding Usage Min",
2704 "Must have a corresponding Usage Max");
2705 hidparser_check_minmax_val(mainitem
, R_ITEM_USAGE_MIN
,
2706 R_ITEM_USAGE_MAX
, 1, 1);
2707 hidparser_check_correspondence(mainitem
, R_ITEM_DESIGNATOR_MIN
,
2708 R_ITEM_DESIGNATOR_MAX
, 0, 0,
2709 "Must have a corresponding Designator min",
2710 "Must have a corresponding Designator Max");
2711 hidparser_check_minmax_val(mainitem
, R_ITEM_DESIGNATOR_MIN
,
2712 R_ITEM_DESIGNATOR_MAX
, 1, 1);
2713 hidparser_check_correspondence(mainitem
, R_ITEM_STRING_MIN
,
2714 R_ITEM_STRING_MAX
, 0, 0,
2715 "Must have a corresponding String min",
2716 "Must have a corresponding String Max");
2717 hidparser_check_minmax_val(mainitem
, R_ITEM_STRING_MIN
,
2718 R_ITEM_STRING_MAX
, 1, 1);
2723 * hidparser_find_unsigned_val:
2724 * Find the value for multibyte data
2725 * Ref: Section 5.8 of HID Spec 1.0
2728 hidparser_find_unsigned_val(entity_attribute_t
*attr
)
2732 unsigned int ret
= 0;
2734 text
= attr
->entity_attribute_value
;
2735 len
= attr
->entity_attribute_length
;
2736 for (i
= 0; i
< len
; i
++) {
2737 ret
|= ((text
[i
] & 0xff) << (8*i
));
2745 * hidparser_find_signed_val:
2746 * Find the value for signed multibyte data
2747 * Ref: Section 5.8 of HID Spec 1.0
2750 hidparser_find_signed_val(entity_attribute_t
*attr
)
2756 text
= attr
->entity_attribute_value
;
2757 len
= attr
->entity_attribute_length
;
2759 for (i
= 0; i
< len
- 1; i
++) {
2760 ret
|= ((text
[i
] & 0xff) << (8 * i
));
2764 ret
|= (text
[i
] << (8 * i
));
2772 * hidparser_check_correspondence:
2773 * Check if the item item2 corresponding to item1 exists and vice versa
2774 * If not report the appropriate error
2777 hidparser_check_correspondence(entity_item_t
*mainitem
,
2785 entity_attribute_t
*temp1
, *temp2
;
2787 temp1
= hidparser_lookup_attribute(mainitem
, item_tag1
);
2788 temp2
= hidparser_lookup_attribute(mainitem
, item_tag2
);
2789 if ((temp1
!= NULL
) && (temp2
== NULL
)) {
2790 hidparser_report_err(
2791 HIDPARSER_ERR_ERROR
,
2792 HIDPARSER_ERR_STANDARD
,
2797 if ((temp2
!= NULL
) && (temp1
== NULL
)) {
2798 hidparser_report_err(
2799 HIDPARSER_ERR_ERROR
,
2800 HIDPARSER_ERR_STANDARD
,
2809 * hidparser_check_minmax_val:
2810 * Check if the Min value <= Max and vice versa
2811 * Print for warnings and errors have been taken care separately.
2814 hidparser_check_minmax_val(entity_item_t
*mainitem
,
2820 entity_attribute_t
*temp1
, *temp2
;
2822 temp1
= hidparser_lookup_attribute(mainitem
, item_tag1
);
2823 temp2
= hidparser_lookup_attribute(mainitem
, item_tag2
);
2824 if ((temp1
!= NULL
) && (temp2
!= NULL
)) {
2825 if (hidparser_find_unsigned_val(temp1
) >
2826 hidparser_find_unsigned_val(temp2
)) {
2827 if ((item_tag1
== R_ITEM_LOGICAL_MINIMUM
) ||
2828 (item_tag1
== R_ITEM_PHYSICAL_MINIMUM
)) {
2829 hidparser_report_err(
2831 HIDPARSER_ERR_STANDARD
,
2834 "unsigned: Min should be <= to Max");
2836 hidparser_report_err(
2837 HIDPARSER_ERR_ERROR
,
2838 HIDPARSER_ERR_STANDARD
,
2841 "Min must be <= to Max");
2844 if (hidparser_find_unsigned_val(temp2
) <
2845 hidparser_find_unsigned_val(temp1
)) {
2846 if ((item_tag2
== R_ITEM_LOGICAL_MAXIMUM
) ||
2847 (item_tag2
== R_ITEM_PHYSICAL_MAXIMUM
)) {
2848 hidparser_report_err(
2849 HIDPARSER_ERR_ERROR
,
2850 HIDPARSER_ERR_STANDARD
,
2853 "unsigned: Max should be >= to Min");
2855 hidparser_report_err(
2856 HIDPARSER_ERR_ERROR
,
2857 HIDPARSER_ERR_STANDARD
,
2860 "Max must be >= to Min");
2863 } /* if (temp1 != NULL) && (temp2 != NULL) */
2868 * hidparser_check_minmax_val_signed:
2869 * Check if the Min value <= Max and vice versa
2870 * Print for warnings and errors have been taken care separately.
2873 hidparser_check_minmax_val_signed(entity_item_t
*mainitem
,
2879 entity_attribute_t
*temp1
, *temp2
;
2881 temp1
= hidparser_lookup_attribute(mainitem
, item_tag1
);
2882 temp2
= hidparser_lookup_attribute(mainitem
, item_tag2
);
2883 if ((temp1
!= NULL
) && (temp2
!= NULL
)) {
2884 if (hidparser_find_signed_val(temp1
) >
2885 hidparser_find_signed_val(temp2
)) {
2886 if ((item_tag1
== R_ITEM_LOGICAL_MINIMUM
) ||
2887 (item_tag1
== R_ITEM_PHYSICAL_MINIMUM
)) {
2888 hidparser_report_err(
2890 HIDPARSER_ERR_STANDARD
,
2893 "signed: Min should be <= to Max");
2895 hidparser_report_err(
2896 HIDPARSER_ERR_ERROR
,
2897 HIDPARSER_ERR_STANDARD
,
2900 "Min must be <= to Max");
2903 if (hidparser_find_signed_val(temp2
) <
2904 hidparser_find_signed_val(temp1
)) {
2905 if ((item_tag2
== R_ITEM_LOGICAL_MAXIMUM
) ||
2906 (item_tag2
== R_ITEM_PHYSICAL_MAXIMUM
)) {
2907 hidparser_report_err(
2908 HIDPARSER_ERR_ERROR
,
2909 HIDPARSER_ERR_STANDARD
,
2912 "signed: Max should be >= to Min");
2914 hidparser_report_err(
2915 HIDPARSER_ERR_ERROR
,
2916 HIDPARSER_ERR_STANDARD
,
2919 "Max must be >= to Min");
2922 } /* if (temp1 != NULL) && (temp2 != NULL) */
2927 * hidparser_error_delim:
2928 * Error check for Delimiter Sets
2931 hidparser_error_delim(entity_item_t
*item
, int err
)
2933 entity_attribute_t
*attr
;
2935 case HIDPARSER_DELIM_ERR1
:
2936 hidparser_report_err(
2937 HIDPARSER_ERR_ERROR
,
2938 HIDPARSER_ERR_STANDARD
,
2939 R_ITEM_SET_DELIMITER
,
2941 "Must be Delimiter Open");
2944 case HIDPARSER_DELIM_ERR2
:
2945 hidparser_report_err(
2946 HIDPARSER_ERR_ERROR
,
2947 HIDPARSER_ERR_STANDARD
,
2948 R_ITEM_SET_DELIMITER
,
2950 "Must be Delimiter Close");
2953 case HIDPARSER_DELIM_ERR3
:
2954 attr
= item
->entity_item_attributes
;
2955 while (attr
!= NULL
) {
2956 if ((attr
->entity_attribute_tag
!=
2958 (attr
->entity_attribute_tag
!=
2959 R_ITEM_USAGE_MIN
) &&
2960 (attr
->entity_attribute_tag
!=
2961 R_ITEM_USAGE_MAX
)) {
2962 hidparser_report_err(
2963 HIDPARSER_ERR_ERROR
,
2964 HIDPARSER_ERR_STANDARD
,
2965 R_ITEM_SET_DELIMITER
,
2967 "May only contain Usage, "
2968 "Usage Min and Usage Max");
2970 attr
= attr
->entity_attribute_next
;
2982 * hidparser_find_max_packet_size_from_report_descriptor:
2983 * find packet size of the largest report in the report descriptor
2986 hidparser_find_max_packet_size_from_report_descriptor(
2987 hidparser_handle_t hparser_handle
,
2988 hidparser_packet_info_t
*hpack
)
2993 uint_t max_packet_size
;
2994 uint_t max_report_id
;
2995 hidparser_report_id_list_t report_id_list
;
2997 USB_DPRINTF_L4(PRINT_MASK_ALL
, hparser_log_handle
,
2998 "hidparser_find_max_packet_size_from_report_descriptor");
3000 /* get a list of input reports */
3001 rval
= hidparser_get_report_id_list(hparser_handle
,
3002 R_ITEM_INPUT
, &report_id_list
);
3003 if (rval
!= HIDPARSER_SUCCESS
) {
3004 USB_DPRINTF_L2(PRINT_MASK_ALL
, hparser_log_handle
,
3005 "No report id used");
3007 USB_DPRINTF_L3(PRINT_MASK_ALL
, hparser_log_handle
,
3008 "%d unique report IDs found in hid report descriptor",
3009 report_id_list
.no_of_report_ids
);
3011 for (i
= 0; i
< (report_id_list
.no_of_report_ids
); i
++) {
3012 USB_DPRINTF_L3(PRINT_MASK_ALL
, hparser_log_handle
,
3013 "report_id: %d", report_id_list
.report_id
[i
]);
3017 if ((rval
!= HIDPARSER_SUCCESS
) ||
3018 (report_id_list
.no_of_report_ids
== 0)) {
3020 * since no report id is used, get the packet size
3021 * for the only report available
3023 (void) hidparser_get_packet_size(hparser_handle
,
3024 0, R_ITEM_INPUT
, &packet_size
);
3025 USB_DPRINTF_L2(PRINT_MASK_ALL
, hparser_log_handle
,
3026 "Not using report id prefix. HID packet size = %d",
3029 hpack
->max_packet_size
= packet_size
;
3030 hpack
->report_id
= HID_REPORT_ID_UNDEFINED
;
3033 * hid device uses multiple reports with report id prefix byte.
3034 * Find the longest input report.
3037 max_packet_size
= 0;
3040 for (i
= 0; i
< (report_id_list
.no_of_report_ids
); i
++) {
3041 (void) hidparser_get_packet_size(hparser_handle
,
3042 report_id_list
.report_id
[i
], R_ITEM_INPUT
,
3044 if (packet_size
> max_packet_size
) {
3045 max_packet_size
= packet_size
;
3046 max_report_id
= report_id_list
.report_id
[i
];
3048 USB_DPRINTF_L2(PRINT_MASK_ALL
, hparser_log_handle
,
3049 "Report ID %d has a packet size of %d",
3050 report_id_list
.report_id
[i
], packet_size
);
3053 hpack
->max_packet_size
= max_packet_size
;
3054 hpack
->report_id
= max_report_id
;
3056 USB_DPRINTF_L2(PRINT_MASK_ALL
, hparser_log_handle
,
3057 "Report ID %d has the maximum packet size of %d",
3058 max_report_id
, max_packet_size
);