17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5d2bde62eSgc161489 * Common Development and Distribution License (the "License"). 6d2bde62eSgc161489 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22112116d8Sfb209375 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <sys/usb/usba/usbai_version.h> 297c478bd9Sstevel@tonic-gate #include <sys/usb/usba.h> 307c478bd9Sstevel@tonic-gate #include <sys/usb/clients/hid/hid.h> 317c478bd9Sstevel@tonic-gate #include <sys/usb/clients/hidparser/hidparser.h> 327c478bd9Sstevel@tonic-gate #include <sys/usb/clients/hidparser/hid_parser_driver.h> 337c478bd9Sstevel@tonic-gate #include <sys/usb/clients/hidparser/hidparser_impl.h> 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate /* 367c478bd9Sstevel@tonic-gate * hidparser: Parser to generate parse tree for Report Descriptors 377c478bd9Sstevel@tonic-gate * in HID devices. 387c478bd9Sstevel@tonic-gate */ 397c478bd9Sstevel@tonic-gate 404610e4a0Sfrits uint_t hparser_errmask = (uint_t)PRINT_MASK_ALL; 414610e4a0Sfrits uint_t hparser_errlevel = (uint_t)USB_LOG_L1; 427c478bd9Sstevel@tonic-gate static usb_log_handle_t hparser_log_handle; 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate /* 457c478bd9Sstevel@tonic-gate * Array used to store corresponding strings for the 467c478bd9Sstevel@tonic-gate * different item types for debugging. 477c478bd9Sstevel@tonic-gate */ 487c478bd9Sstevel@tonic-gate char *items[500]; /* Print items */ 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate /* 517c478bd9Sstevel@tonic-gate * modload support 527c478bd9Sstevel@tonic-gate */ 537c478bd9Sstevel@tonic-gate extern struct mod_ops mod_miscops; 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc = { 567c478bd9Sstevel@tonic-gate &mod_miscops, /* Type of module */ 57*e7cc2e17Sbc224572 "HID Parser" 587c478bd9Sstevel@tonic-gate }; 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 617c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modlmisc, NULL 627c478bd9Sstevel@tonic-gate }; 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate int 657c478bd9Sstevel@tonic-gate _init(void) 667c478bd9Sstevel@tonic-gate { 677c478bd9Sstevel@tonic-gate int rval = mod_install(&modlinkage); 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate if (rval == 0) { 707c478bd9Sstevel@tonic-gate hparser_log_handle = usb_alloc_log_hdl(NULL, "hidparser", 717c478bd9Sstevel@tonic-gate &hparser_errlevel, &hparser_errmask, NULL, 0); 727c478bd9Sstevel@tonic-gate } 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate return (rval); 757c478bd9Sstevel@tonic-gate } 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate int 787c478bd9Sstevel@tonic-gate _fini() 797c478bd9Sstevel@tonic-gate { 807c478bd9Sstevel@tonic-gate int rval = mod_remove(&modlinkage); 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate if (rval == 0) { 837c478bd9Sstevel@tonic-gate usb_free_log_hdl(hparser_log_handle); 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate return (rval); 877c478bd9Sstevel@tonic-gate } 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate int 907c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 917c478bd9Sstevel@tonic-gate { 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate /* 977c478bd9Sstevel@tonic-gate * These functions are used internally in the parser. 987c478bd9Sstevel@tonic-gate * local declarations 997c478bd9Sstevel@tonic-gate */ 1007c478bd9Sstevel@tonic-gate static void hidparser_scan(hidparser_tok_t *); 1017c478bd9Sstevel@tonic-gate static int hidparser_Items(hidparser_tok_t *); 1027c478bd9Sstevel@tonic-gate static int hidparser_LocalItem(hidparser_tok_t *); 1037c478bd9Sstevel@tonic-gate static int hidparser_GlobalItem(hidparser_tok_t *); 1047c478bd9Sstevel@tonic-gate static int hidparser_ItemList(entity_item_t **, 1057c478bd9Sstevel@tonic-gate hidparser_tok_t *); 1067c478bd9Sstevel@tonic-gate static int hidparser_ReportDescriptor(entity_item_t **, 1077c478bd9Sstevel@tonic-gate hidparser_tok_t *); 1087c478bd9Sstevel@tonic-gate static int hidparser_ReportDescriptorDash(entity_item_t **, 1097c478bd9Sstevel@tonic-gate hidparser_tok_t *); 1107c478bd9Sstevel@tonic-gate static int hidparser_MainItem(entity_item_t **, 1117c478bd9Sstevel@tonic-gate hidparser_tok_t *); 1127c478bd9Sstevel@tonic-gate static void hidparser_free_attribute_list( 1137c478bd9Sstevel@tonic-gate entity_attribute_t *); 1147c478bd9Sstevel@tonic-gate static entity_item_t *hidparser_allocate_entity(hidparser_tok_t *); 1157c478bd9Sstevel@tonic-gate static void hidparser_add_attribute(hidparser_tok_t *); 1167c478bd9Sstevel@tonic-gate static entity_attribute_t *hidparser_cp_attribute_list( 1177c478bd9Sstevel@tonic-gate entity_attribute_t *); 1187c478bd9Sstevel@tonic-gate static entity_attribute_t *hidparser_find_attribute_end( 1197c478bd9Sstevel@tonic-gate entity_attribute_t *); 1207c478bd9Sstevel@tonic-gate static entity_attribute_t *hidparser_alloc_attrib_list(int); 1217c478bd9Sstevel@tonic-gate static entity_item_t *hidparser_find_item_end(entity_item_t *); 1227c478bd9Sstevel@tonic-gate static void hidparser_report_err(int, int, 1237c478bd9Sstevel@tonic-gate int, int, char *); 1247c478bd9Sstevel@tonic-gate static int hidparser_isvalid_item(int); 1257c478bd9Sstevel@tonic-gate static entity_attribute_t *hidparser_lookup_attribute(entity_item_t *, 1267c478bd9Sstevel@tonic-gate int); 1277c478bd9Sstevel@tonic-gate static void hidparser_global_err_check(entity_item_t *); 1287c478bd9Sstevel@tonic-gate static void hidparser_local_err_check(entity_item_t *); 1297c478bd9Sstevel@tonic-gate static void hidparser_mainitem_err_check(entity_item_t *); 1307c478bd9Sstevel@tonic-gate static unsigned int hidparser_find_unsigned_val( 1317c478bd9Sstevel@tonic-gate entity_attribute_t *); 1327c478bd9Sstevel@tonic-gate static int hidparser_find_signed_val( 1337c478bd9Sstevel@tonic-gate entity_attribute_t *); 1347c478bd9Sstevel@tonic-gate static void hidparser_check_correspondence( 1357c478bd9Sstevel@tonic-gate entity_item_t *, int, int, int, 1367c478bd9Sstevel@tonic-gate int, char *, char *); 1377c478bd9Sstevel@tonic-gate static void hidparser_check_minmax_val(entity_item_t *, 1387c478bd9Sstevel@tonic-gate int, int, int, int); 1397c478bd9Sstevel@tonic-gate static void hidparser_check_minmax_val_signed( 1407c478bd9Sstevel@tonic-gate entity_item_t *, 1417c478bd9Sstevel@tonic-gate int, int, int, int); 1427c478bd9Sstevel@tonic-gate static void hidparser_error_delim(entity_item_t *, int); 1437c478bd9Sstevel@tonic-gate static int hidparser_get_usage_attribute_report_des( 1447c478bd9Sstevel@tonic-gate entity_item_t *, 1457c478bd9Sstevel@tonic-gate uint32_t, uint32_t, uint32_t, 1467c478bd9Sstevel@tonic-gate uint32_t, uint32_t, int32_t *); 1477c478bd9Sstevel@tonic-gate static int hidparser_get_packet_size_report_des( 1487c478bd9Sstevel@tonic-gate entity_item_t *, uint32_t, uint32_t, 1497c478bd9Sstevel@tonic-gate uint32_t *); 1507c478bd9Sstevel@tonic-gate static int hidparser_get_main_item_data_descr_main( 1517c478bd9Sstevel@tonic-gate entity_item_t *, uint32_t, 1527c478bd9Sstevel@tonic-gate uint32_t, uint32_t, uint32_t, 1537c478bd9Sstevel@tonic-gate uint32_t *); 1547c478bd9Sstevel@tonic-gate static void hidparser_print_entity( 1557c478bd9Sstevel@tonic-gate entity_item_t *entity, 1567c478bd9Sstevel@tonic-gate int indent_level); 1577c478bd9Sstevel@tonic-gate static void hidparser_print_this_attribute( 1587c478bd9Sstevel@tonic-gate entity_attribute_t *attribute, 1597c478bd9Sstevel@tonic-gate char *ident_space); 1607c478bd9Sstevel@tonic-gate static int hidparser_main(unsigned char *, size_t, 1617c478bd9Sstevel@tonic-gate entity_item_t **); 1627c478bd9Sstevel@tonic-gate static void hidparser_initialize_items(); 1637c478bd9Sstevel@tonic-gate static void hidparser_free_report_descr_handle( 1647c478bd9Sstevel@tonic-gate entity_item_t *); 1657c478bd9Sstevel@tonic-gate static int hidparser_print_report_descr_handle( 1667c478bd9Sstevel@tonic-gate entity_item_t *handle, 1677c478bd9Sstevel@tonic-gate int indent_level); 1687c478bd9Sstevel@tonic-gate static int hidparser_get_usage_list_in_order_internal( 1697c478bd9Sstevel@tonic-gate entity_item_t *parse_handle, 1707c478bd9Sstevel@tonic-gate uint_t collection_usage, 1717c478bd9Sstevel@tonic-gate uint_t report_id, 1727c478bd9Sstevel@tonic-gate uint_t main_item_type, 1737c478bd9Sstevel@tonic-gate hidparser_rpt_t *rpt); 1747c478bd9Sstevel@tonic-gate static void hidparser_fill_usage_info( 1757c478bd9Sstevel@tonic-gate hidparser_usage_info_t *ui, 1767c478bd9Sstevel@tonic-gate entity_attribute_t *attribute); 1777c478bd9Sstevel@tonic-gate static int hidparser_get_report_id_list_internal( 1787c478bd9Sstevel@tonic-gate entity_item_t *parser_handle, 1797c478bd9Sstevel@tonic-gate uint_t main_item_type, 1807c478bd9Sstevel@tonic-gate hidparser_report_id_list_t *id_lst); 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* 1837c478bd9Sstevel@tonic-gate * The hidparser_lookup_first(N) of a non-terminal N is stored as an array of 1847c478bd9Sstevel@tonic-gate * integer tokens, terminated by 0. Right now there is only one element. 1857c478bd9Sstevel@tonic-gate */ 1867c478bd9Sstevel@tonic-gate static hidparser_terminal_t first_Items[] = { 1877c478bd9Sstevel@tonic-gate R_ITEM_USAGE_PAGE, R_ITEM_LOGICAL_MINIMUM, R_ITEM_LOGICAL_MAXIMUM, \ 1887c478bd9Sstevel@tonic-gate R_ITEM_PHYSICAL_MINIMUM, R_ITEM_PHYSICAL_MAXIMUM, R_ITEM_UNIT, \ 1897c478bd9Sstevel@tonic-gate R_ITEM_EXPONENT, R_ITEM_REPORT_SIZE, R_ITEM_REPORT_COUNT, \ 1907c478bd9Sstevel@tonic-gate R_ITEM_REPORT_ID, \ 1917c478bd9Sstevel@tonic-gate R_ITEM_USAGE, R_ITEM_USAGE_MIN, R_ITEM_USAGE_MAX, \ 1927c478bd9Sstevel@tonic-gate R_ITEM_DESIGNATOR_INDEX, \ 1937c478bd9Sstevel@tonic-gate R_ITEM_DESIGNATOR_MIN, R_ITEM_STRING_INDEX, R_ITEM_STRING_MIN, \ 1947c478bd9Sstevel@tonic-gate R_ITEM_STRING_MAX, \ 1957c478bd9Sstevel@tonic-gate R_ITEM_SET_DELIMITER, \ 1967c478bd9Sstevel@tonic-gate 0 1977c478bd9Sstevel@tonic-gate }; 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate /* 2017c478bd9Sstevel@tonic-gate * Each non-terminal is represented by a function. In a top-down parser, 2027c478bd9Sstevel@tonic-gate * whenever a non-terminal is encountered on the state diagram, the 2037c478bd9Sstevel@tonic-gate * corresponding function is called. Because of the grammar, there is NO 2047c478bd9Sstevel@tonic-gate * backtracking. If there is an error in the middle, the parser returns 2057c478bd9Sstevel@tonic-gate * HIDPARSER_FAILURE 2067c478bd9Sstevel@tonic-gate */ 2077c478bd9Sstevel@tonic-gate static hidparser_terminal_t *hid_first_list[] = { 2087c478bd9Sstevel@tonic-gate first_Items 2097c478bd9Sstevel@tonic-gate }; 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate /* 2137c478bd9Sstevel@tonic-gate * hidparser_parse_report_descriptor: 2147c478bd9Sstevel@tonic-gate * Calls the main parser routine 2157c478bd9Sstevel@tonic-gate */ 2167c478bd9Sstevel@tonic-gate int 2177c478bd9Sstevel@tonic-gate hidparser_parse_report_descriptor( 2187c478bd9Sstevel@tonic-gate unsigned char *descriptor, 2197c478bd9Sstevel@tonic-gate size_t size, 2207c478bd9Sstevel@tonic-gate usb_hid_descr_t *hid_descriptor, 2217c478bd9Sstevel@tonic-gate hidparser_handle_t *parse_handle) 2227c478bd9Sstevel@tonic-gate { 2237c478bd9Sstevel@tonic-gate int error = 0; 2247c478bd9Sstevel@tonic-gate entity_item_t *root; 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate hidparser_initialize_items(); 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate error = hidparser_main(descriptor, size, &root); 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate if (error != HIDPARSER_SUCCESS) { 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 2337c478bd9Sstevel@tonic-gate } else { 2347c478bd9Sstevel@tonic-gate *parse_handle = kmem_zalloc( 2357c478bd9Sstevel@tonic-gate sizeof (hidparser_handle), KM_SLEEP); 2367c478bd9Sstevel@tonic-gate (*parse_handle)->hidparser_handle_hid_descr = hid_descriptor; 2377c478bd9Sstevel@tonic-gate (*parse_handle)->hidparser_handle_parse_tree = root; 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate /* 2457c478bd9Sstevel@tonic-gate * hidparser_free_report_descriptor_handle: 2467c478bd9Sstevel@tonic-gate * Frees the parse_handle which consists of a pointer to the parse 2477c478bd9Sstevel@tonic-gate * tree and a pointer to the Hid descriptor structure 2487c478bd9Sstevel@tonic-gate */ 2497c478bd9Sstevel@tonic-gate int 2507c478bd9Sstevel@tonic-gate hidparser_free_report_descriptor_handle(hidparser_handle_t parse_handle) 2517c478bd9Sstevel@tonic-gate { 2527c478bd9Sstevel@tonic-gate if (parse_handle != NULL) { 2537c478bd9Sstevel@tonic-gate hidparser_free_report_descr_handle( 2547c478bd9Sstevel@tonic-gate parse_handle->hidparser_handle_parse_tree); 2557c478bd9Sstevel@tonic-gate if (parse_handle != NULL) { 2567c478bd9Sstevel@tonic-gate kmem_free(parse_handle, sizeof (hidparser_handle)); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate /* 2657c478bd9Sstevel@tonic-gate * hidparser_get_country_code: 2667c478bd9Sstevel@tonic-gate * Return the bCountryCode from the Hid Descriptor 2677c478bd9Sstevel@tonic-gate * to the hid module. 2687c478bd9Sstevel@tonic-gate */ 2697c478bd9Sstevel@tonic-gate int 2707c478bd9Sstevel@tonic-gate hidparser_get_country_code(hidparser_handle_t parser_handle, 2717c478bd9Sstevel@tonic-gate uint16_t *country_code) 2727c478bd9Sstevel@tonic-gate { 2737c478bd9Sstevel@tonic-gate if ((parser_handle == NULL) || 2747c478bd9Sstevel@tonic-gate (parser_handle->hidparser_handle_hid_descr == NULL)) { 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate *country_code = 2807c478bd9Sstevel@tonic-gate parser_handle->hidparser_handle_hid_descr->bCountryCode; 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate /* 2877c478bd9Sstevel@tonic-gate * hidparser_get_packet_size: 2887c478bd9Sstevel@tonic-gate * Get the packet size(sum of REPORT_SIZE * REPORT_COUNT) 2897c478bd9Sstevel@tonic-gate * corresponding to a report id and an item type 2907c478bd9Sstevel@tonic-gate */ 2917c478bd9Sstevel@tonic-gate int 2927c478bd9Sstevel@tonic-gate hidparser_get_packet_size(hidparser_handle_t parser_handle, 2937c478bd9Sstevel@tonic-gate uint_t report_id, 2947c478bd9Sstevel@tonic-gate uint_t main_item_type, 2957c478bd9Sstevel@tonic-gate uint_t *size) 2967c478bd9Sstevel@tonic-gate { 2977c478bd9Sstevel@tonic-gate if ((parser_handle == NULL) || (parser_handle-> 2987c478bd9Sstevel@tonic-gate hidparser_handle_parse_tree == NULL)) { 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate *size = 0; 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate return (hidparser_get_packet_size_report_des( 3067c478bd9Sstevel@tonic-gate parser_handle->hidparser_handle_parse_tree, 3077c478bd9Sstevel@tonic-gate report_id, main_item_type, size)); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate /* 3127c478bd9Sstevel@tonic-gate * hidparser_get_packet_size_report_des: 3137c478bd9Sstevel@tonic-gate * Get the packet size(sum of REPORT_SIZE * REPORT_COUNT) 3147c478bd9Sstevel@tonic-gate * corresponding to a report id and an item type 3157c478bd9Sstevel@tonic-gate */ 3167c478bd9Sstevel@tonic-gate int 3177c478bd9Sstevel@tonic-gate hidparser_get_packet_size_report_des(entity_item_t *parser_handle, 3187c478bd9Sstevel@tonic-gate uint32_t report_id, 3197c478bd9Sstevel@tonic-gate uint32_t main_item_type, 3207c478bd9Sstevel@tonic-gate uint32_t *size) 3217c478bd9Sstevel@tonic-gate { 3227c478bd9Sstevel@tonic-gate entity_item_t *current = parser_handle; 3237c478bd9Sstevel@tonic-gate entity_attribute_t *attribute; 3247c478bd9Sstevel@tonic-gate uint32_t temp; 3257c478bd9Sstevel@tonic-gate uchar_t foundsize, foundcount, foundreportid, right_report_id; 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate foundsize = 0; 3287c478bd9Sstevel@tonic-gate foundcount = 0; 3297c478bd9Sstevel@tonic-gate right_report_id = 0; 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate while (current) { 3327c478bd9Sstevel@tonic-gate if (current->entity_item_type == R_ITEM_COLLECTION) { 3337c478bd9Sstevel@tonic-gate (void) hidparser_get_packet_size_report_des( 3347c478bd9Sstevel@tonic-gate current->info.child, report_id, main_item_type, 3357c478bd9Sstevel@tonic-gate size); 3367c478bd9Sstevel@tonic-gate } else if (current->entity_item_type == main_item_type) { 3377c478bd9Sstevel@tonic-gate temp = 1; 3387c478bd9Sstevel@tonic-gate foundsize = 0; 3397c478bd9Sstevel@tonic-gate foundcount = 0; 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate foundreportid = 0; 3427c478bd9Sstevel@tonic-gate attribute = current->entity_item_attributes; 3437c478bd9Sstevel@tonic-gate while (attribute != NULL) { 3447c478bd9Sstevel@tonic-gate if (attribute->entity_attribute_tag == 3457c478bd9Sstevel@tonic-gate R_ITEM_REPORT_ID) { 3467c478bd9Sstevel@tonic-gate foundreportid = 1; 3477c478bd9Sstevel@tonic-gate if ((attribute-> 3487c478bd9Sstevel@tonic-gate entity_attribute_value[0]) == 3497c478bd9Sstevel@tonic-gate report_id) { 3507c478bd9Sstevel@tonic-gate right_report_id = 1; 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate } else if (attribute->entity_attribute_tag == 3537c478bd9Sstevel@tonic-gate R_ITEM_REPORT_SIZE) { 3547c478bd9Sstevel@tonic-gate foundsize = 1; 35541d01d31Sqz150045 temp *= hidparser_find_unsigned_val( 35641d01d31Sqz150045 attribute); 3577c478bd9Sstevel@tonic-gate if (foundcount == 1) { 3587c478bd9Sstevel@tonic-gate if (report_id && 3597c478bd9Sstevel@tonic-gate right_report_id) { 3607c478bd9Sstevel@tonic-gate break; 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate } else if (attribute->entity_attribute_tag == 3647c478bd9Sstevel@tonic-gate R_ITEM_REPORT_COUNT) { 3657c478bd9Sstevel@tonic-gate foundcount = 1; 36641d01d31Sqz150045 temp *= hidparser_find_unsigned_val( 36741d01d31Sqz150045 attribute); 3687c478bd9Sstevel@tonic-gate if (foundsize == 1) { 3697c478bd9Sstevel@tonic-gate if (report_id && 3707c478bd9Sstevel@tonic-gate right_report_id) { 3717c478bd9Sstevel@tonic-gate break; 3727c478bd9Sstevel@tonic-gate } 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate attribute = attribute->entity_attribute_next; 3767c478bd9Sstevel@tonic-gate } /* end while */ 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate if (foundreportid) { 3797c478bd9Sstevel@tonic-gate if (right_report_id) { 3807c478bd9Sstevel@tonic-gate *size = *size + temp; 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate } else if (report_id == HID_REPORT_ID_UNDEFINED) { 3837c478bd9Sstevel@tonic-gate /* Just sanity checking */ 3847c478bd9Sstevel@tonic-gate *size = *size + temp; 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate right_report_id = 0; 3877c478bd9Sstevel@tonic-gate } /* end else if */ 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate current = current->entity_item_right_sibling; 3907c478bd9Sstevel@tonic-gate } /* end while current */ 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate /* 3987c478bd9Sstevel@tonic-gate * hidparser_get_usage_attribute: 3997c478bd9Sstevel@tonic-gate * Get the attribute value corresponding to a particular 4007c478bd9Sstevel@tonic-gate * report id, main item and usage 4017c478bd9Sstevel@tonic-gate */ 4027c478bd9Sstevel@tonic-gate int 4037c478bd9Sstevel@tonic-gate hidparser_get_usage_attribute(hidparser_handle_t parser_handle, 4047c478bd9Sstevel@tonic-gate uint_t report_id, 4057c478bd9Sstevel@tonic-gate uint_t main_item_type, 4067c478bd9Sstevel@tonic-gate uint_t usage_page, 4077c478bd9Sstevel@tonic-gate uint_t usage_id, 4087c478bd9Sstevel@tonic-gate uint_t usage_attribute, 4097c478bd9Sstevel@tonic-gate int *usage_attribute_value) 4107c478bd9Sstevel@tonic-gate { 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate return (hidparser_get_usage_attribute_report_des( 4137c478bd9Sstevel@tonic-gate parser_handle->hidparser_handle_parse_tree, 4147c478bd9Sstevel@tonic-gate report_id, main_item_type, usage_page, 4157c478bd9Sstevel@tonic-gate usage_id, usage_attribute, usage_attribute_value)); 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate /* 4207c478bd9Sstevel@tonic-gate * hidparser_get_usage_attribute_report_des: 4217c478bd9Sstevel@tonic-gate * Called by the wrapper function hidparser_get_usage_attribute() 4227c478bd9Sstevel@tonic-gate */ 4237c478bd9Sstevel@tonic-gate static int 4247c478bd9Sstevel@tonic-gate hidparser_get_usage_attribute_report_des(entity_item_t *parser_handle, 4257c478bd9Sstevel@tonic-gate uint_t report_id, 4267c478bd9Sstevel@tonic-gate uint_t main_item_type, 4277c478bd9Sstevel@tonic-gate uint_t usage_page, 4287c478bd9Sstevel@tonic-gate uint_t usage_id, 4297c478bd9Sstevel@tonic-gate uint_t usage_attribute, 4307c478bd9Sstevel@tonic-gate int *usage_attribute_value) 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate { 4337c478bd9Sstevel@tonic-gate entity_item_t *current = parser_handle; 4347c478bd9Sstevel@tonic-gate entity_attribute_t *attribute; 4357c478bd9Sstevel@tonic-gate uchar_t found_page, found_ret_value, found_usage_id; 4367c478bd9Sstevel@tonic-gate uchar_t foundreportid, right_report_id; 4377c478bd9Sstevel@tonic-gate uint32_t usage; 4387c478bd9Sstevel@tonic-gate short attvalue; 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate found_page = 0; 4417c478bd9Sstevel@tonic-gate found_ret_value = 0; 4427c478bd9Sstevel@tonic-gate found_usage_id = 0; 4437c478bd9Sstevel@tonic-gate foundreportid = 0; 4447c478bd9Sstevel@tonic-gate right_report_id = 0; 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate while (current) { 4477c478bd9Sstevel@tonic-gate if (usage_id == HID_USAGE_UNDEFINED) { 4487c478bd9Sstevel@tonic-gate found_usage_id = 1; 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate if (current->entity_item_type == R_ITEM_COLLECTION) { 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate if (hidparser_get_usage_attribute_report_des( 4537c478bd9Sstevel@tonic-gate current->info.child, report_id, main_item_type, 4547c478bd9Sstevel@tonic-gate usage_page, usage_id, usage_attribute, 4557c478bd9Sstevel@tonic-gate usage_attribute_value) == 4567c478bd9Sstevel@tonic-gate HIDPARSER_SUCCESS) { 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate } else if (current->entity_item_type == main_item_type) { 4627c478bd9Sstevel@tonic-gate /* Match Item Type */ 4637c478bd9Sstevel@tonic-gate attribute = current->entity_item_attributes; 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate while (attribute != NULL) { 4667c478bd9Sstevel@tonic-gate if (attribute->entity_attribute_tag == 4677c478bd9Sstevel@tonic-gate R_ITEM_USAGE) { 4687c478bd9Sstevel@tonic-gate usage = hidparser_find_unsigned_val( 4697c478bd9Sstevel@tonic-gate attribute); 4707c478bd9Sstevel@tonic-gate if (usage_id == HID_USAGE_ID(usage)) { 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate found_usage_id = 1; 4737c478bd9Sstevel@tonic-gate } else { 4747c478bd9Sstevel@tonic-gate /* 4757c478bd9Sstevel@tonic-gate * If we are trying to find out 4767c478bd9Sstevel@tonic-gate * say, report size of usage = 4777c478bd9Sstevel@tonic-gate * 0, a m.i with a valid usage 4787c478bd9Sstevel@tonic-gate * will not contain that 4797c478bd9Sstevel@tonic-gate */ 4807c478bd9Sstevel@tonic-gate if (usage_id == 4817c478bd9Sstevel@tonic-gate HID_USAGE_UNDEFINED) { 4827c478bd9Sstevel@tonic-gate found_usage_id = 0; 4837c478bd9Sstevel@tonic-gate } 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate if (found_usage_id && attribute-> 4877c478bd9Sstevel@tonic-gate entity_attribute_length == 3) { 4887c478bd9Sstevel@tonic-gate /* 4897c478bd9Sstevel@tonic-gate * This is an extended usage ie. 4907c478bd9Sstevel@tonic-gate * usage page in upper 16 bits 4917c478bd9Sstevel@tonic-gate * or-ed with usage in the lower 4927c478bd9Sstevel@tonic-gate * 16 bits. 4937c478bd9Sstevel@tonic-gate */ 4947c478bd9Sstevel@tonic-gate if (HID_USAGE_PAGE(usage) && 4957c478bd9Sstevel@tonic-gate HID_USAGE_PAGE(usage) == 4967c478bd9Sstevel@tonic-gate usage_page) { 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate found_page = 1; 4997c478bd9Sstevel@tonic-gate } else { 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate found_usage_id = 0; 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate } else if (attribute->entity_attribute_tag == 5057c478bd9Sstevel@tonic-gate R_ITEM_USAGE_PAGE) { 5067c478bd9Sstevel@tonic-gate if (attribute-> 5077c478bd9Sstevel@tonic-gate entity_attribute_value[0] == 5087c478bd9Sstevel@tonic-gate usage_page) { 5097c478bd9Sstevel@tonic-gate /* Match Usage Page */ 5107c478bd9Sstevel@tonic-gate found_page = 1; 5117c478bd9Sstevel@tonic-gate } 5127c478bd9Sstevel@tonic-gate } else if (attribute->entity_attribute_tag == 5137c478bd9Sstevel@tonic-gate R_ITEM_REPORT_ID) { 5147c478bd9Sstevel@tonic-gate foundreportid = 1; 5157c478bd9Sstevel@tonic-gate if (attribute-> 5167c478bd9Sstevel@tonic-gate entity_attribute_value[0] == 5177c478bd9Sstevel@tonic-gate report_id) { 5187c478bd9Sstevel@tonic-gate right_report_id = 1; 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate } 5217c478bd9Sstevel@tonic-gate if (attribute->entity_attribute_tag == 5227c478bd9Sstevel@tonic-gate usage_attribute) { 5237c478bd9Sstevel@tonic-gate /* Match attribute */ 5247c478bd9Sstevel@tonic-gate found_ret_value = 1; 5257c478bd9Sstevel@tonic-gate *usage_attribute_value = 5267c478bd9Sstevel@tonic-gate attribute->entity_attribute_value[0]; 5277c478bd9Sstevel@tonic-gate if (attribute-> 5287c478bd9Sstevel@tonic-gate entity_attribute_length == 2) { 5297c478bd9Sstevel@tonic-gate attvalue = 5307c478bd9Sstevel@tonic-gate (attribute-> 5317c478bd9Sstevel@tonic-gate entity_attribute_value[0] & 5327c478bd9Sstevel@tonic-gate 0xff) | 5337c478bd9Sstevel@tonic-gate (attribute-> 5347c478bd9Sstevel@tonic-gate entity_attribute_value[1] << 5357c478bd9Sstevel@tonic-gate 8); 5367c478bd9Sstevel@tonic-gate *usage_attribute_value = 5377c478bd9Sstevel@tonic-gate attvalue; 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate attribute = attribute->entity_attribute_next; 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate if (found_usage_id && found_page && found_ret_value) { 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate if (foundreportid) { 5467c478bd9Sstevel@tonic-gate if (right_report_id) { 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 5497c478bd9Sstevel@tonic-gate } else if (report_id == 5507c478bd9Sstevel@tonic-gate HID_REPORT_ID_UNDEFINED) { 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate } else { 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate /* 5627c478bd9Sstevel@tonic-gate * search the next main item, right sibling of this one 5637c478bd9Sstevel@tonic-gate */ 5647c478bd9Sstevel@tonic-gate if (current->entity_item_right_sibling != NULL) { 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate current = current->entity_item_right_sibling; 5677c478bd9Sstevel@tonic-gate found_usage_id = found_page = found_ret_value = 0; 5687c478bd9Sstevel@tonic-gate /* Don't change foundreportid */ 5697c478bd9Sstevel@tonic-gate right_report_id = 0; 5707c478bd9Sstevel@tonic-gate } else { 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate break; 5737c478bd9Sstevel@tonic-gate } 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate /* Don't give junk result */ 5767c478bd9Sstevel@tonic-gate *usage_attribute_value = 0; 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate return (HIDPARSER_NOT_FOUND); 5797c478bd9Sstevel@tonic-gate } 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate 5827c478bd9Sstevel@tonic-gate /* 5837c478bd9Sstevel@tonic-gate * hidparser_get_main_item_data_descr: 5847c478bd9Sstevel@tonic-gate * Get the data value corresponding to a particular 5857c478bd9Sstevel@tonic-gate * Main Item (Input, Output, Feature) 5867c478bd9Sstevel@tonic-gate */ 5877c478bd9Sstevel@tonic-gate int 5887c478bd9Sstevel@tonic-gate hidparser_get_main_item_data_descr(hidparser_handle_t parser_handle, 5897c478bd9Sstevel@tonic-gate uint_t report_id, 5907c478bd9Sstevel@tonic-gate uint_t main_item_type, 5917c478bd9Sstevel@tonic-gate uint_t usage_page, 5927c478bd9Sstevel@tonic-gate uint_t usage_id, 5937c478bd9Sstevel@tonic-gate uint_t *main_item_descr_value) 5947c478bd9Sstevel@tonic-gate { 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate return hidparser_get_main_item_data_descr_main( 5977c478bd9Sstevel@tonic-gate parser_handle->hidparser_handle_parse_tree, 5987c478bd9Sstevel@tonic-gate report_id, main_item_type, usage_page, usage_id, 5997c478bd9Sstevel@tonic-gate main_item_descr_value); 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate /* 6047c478bd9Sstevel@tonic-gate * hidparser_get_main_item_data_descr_main: 6057c478bd9Sstevel@tonic-gate * Called by the wrapper function hidparser_get_main_item_data_descr() 6067c478bd9Sstevel@tonic-gate */ 6077c478bd9Sstevel@tonic-gate static int 6087c478bd9Sstevel@tonic-gate hidparser_get_main_item_data_descr_main(entity_item_t *parser_handle, 6097c478bd9Sstevel@tonic-gate uint_t report_id, 6107c478bd9Sstevel@tonic-gate uint_t main_item_type, 6117c478bd9Sstevel@tonic-gate uint_t usage_page, 6127c478bd9Sstevel@tonic-gate uint_t usage_id, 6137c478bd9Sstevel@tonic-gate uint_t *main_item_descr_value) 6147c478bd9Sstevel@tonic-gate { 6157c478bd9Sstevel@tonic-gate entity_item_t *current = parser_handle; 6167c478bd9Sstevel@tonic-gate entity_attribute_t *attribute; 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate uchar_t found_page, found_usage_id; 6197c478bd9Sstevel@tonic-gate uchar_t foundreportid, right_report_id; 6207c478bd9Sstevel@tonic-gate uint32_t usage; 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate found_page = 0; 6237c478bd9Sstevel@tonic-gate found_usage_id = 0; 6247c478bd9Sstevel@tonic-gate foundreportid = 0; 6257c478bd9Sstevel@tonic-gate right_report_id = 0; 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate while (current) { 6287c478bd9Sstevel@tonic-gate if (usage_id == HID_USAGE_UNDEFINED) { 6297c478bd9Sstevel@tonic-gate found_usage_id = 1; 6307c478bd9Sstevel@tonic-gate } 6317c478bd9Sstevel@tonic-gate if (current->entity_item_type == R_ITEM_COLLECTION) { 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate if (hidparser_get_main_item_data_descr_main( 6347c478bd9Sstevel@tonic-gate current->info.child, report_id, main_item_type, 6357c478bd9Sstevel@tonic-gate usage_page, usage_id, main_item_descr_value) == 6367c478bd9Sstevel@tonic-gate HIDPARSER_SUCCESS) { 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate } else if (current->entity_item_type == main_item_type) { 6417c478bd9Sstevel@tonic-gate /* Match Item Type */ 6427c478bd9Sstevel@tonic-gate attribute = current->entity_item_attributes; 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate if (report_id == HID_REPORT_ID_UNDEFINED) { 6457c478bd9Sstevel@tonic-gate foundreportid = right_report_id = 1; 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate while (attribute != NULL) { 6497c478bd9Sstevel@tonic-gate if (attribute->entity_attribute_tag == 6507c478bd9Sstevel@tonic-gate R_ITEM_USAGE) { 6517c478bd9Sstevel@tonic-gate usage = hidparser_find_unsigned_val( 6527c478bd9Sstevel@tonic-gate attribute); 6537c478bd9Sstevel@tonic-gate if (usage_id == HID_USAGE_ID(usage)) { 6547c478bd9Sstevel@tonic-gate found_usage_id = 1; 6557c478bd9Sstevel@tonic-gate if (attribute-> 6567c478bd9Sstevel@tonic-gate entity_attribute_length == 6577c478bd9Sstevel@tonic-gate 3) { 6587c478bd9Sstevel@tonic-gate if (HID_USAGE_PAGE( 6597c478bd9Sstevel@tonic-gate usage) && 6607c478bd9Sstevel@tonic-gate HID_USAGE_PAGE( 6617c478bd9Sstevel@tonic-gate usage) == 6627c478bd9Sstevel@tonic-gate usage_page) { 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate found_page = 1; 6657c478bd9Sstevel@tonic-gate } else { 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate found_usage_id = 0; 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate if (found_usage_id && 6727c478bd9Sstevel@tonic-gate found_page && 6737c478bd9Sstevel@tonic-gate foundreportid && 6747c478bd9Sstevel@tonic-gate right_report_id) { 6757c478bd9Sstevel@tonic-gate *main_item_descr_value = 6767c478bd9Sstevel@tonic-gate current-> 6777c478bd9Sstevel@tonic-gate entity_item_params[0]; 6787c478bd9Sstevel@tonic-gate break; 6797c478bd9Sstevel@tonic-gate } 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate } else if ((attribute->entity_attribute_tag == 6827c478bd9Sstevel@tonic-gate R_ITEM_USAGE_PAGE) && 6837c478bd9Sstevel@tonic-gate (attribute->entity_attribute_value[0] == 6847c478bd9Sstevel@tonic-gate usage_page)) { 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate /* Match Usage Page */ 6877c478bd9Sstevel@tonic-gate found_page = 1; 6887c478bd9Sstevel@tonic-gate if (found_usage_id && foundreportid && 6897c478bd9Sstevel@tonic-gate right_report_id) { 6907c478bd9Sstevel@tonic-gate *main_item_descr_value = 6917c478bd9Sstevel@tonic-gate current-> 6927c478bd9Sstevel@tonic-gate entity_item_params[0]; 6937c478bd9Sstevel@tonic-gate break; 6947c478bd9Sstevel@tonic-gate } 6957c478bd9Sstevel@tonic-gate } else if (attribute->entity_attribute_tag == 6967c478bd9Sstevel@tonic-gate R_ITEM_REPORT_ID) { 6977c478bd9Sstevel@tonic-gate foundreportid = 1; 6987c478bd9Sstevel@tonic-gate if (attribute-> 6997c478bd9Sstevel@tonic-gate entity_attribute_value[0] == 7007c478bd9Sstevel@tonic-gate report_id) { 7017c478bd9Sstevel@tonic-gate right_report_id = 1; 7027c478bd9Sstevel@tonic-gate } else { 7037c478bd9Sstevel@tonic-gate break; 7047c478bd9Sstevel@tonic-gate } 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate 7077c478bd9Sstevel@tonic-gate attribute = attribute->entity_attribute_next; 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate if (foundreportid) { 7117c478bd9Sstevel@tonic-gate if (right_report_id) { 7127c478bd9Sstevel@tonic-gate if (found_usage_id && found_page) { 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 7157c478bd9Sstevel@tonic-gate } 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate } 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate /* 7217c478bd9Sstevel@tonic-gate * search the next main item, right sibling of this one 7227c478bd9Sstevel@tonic-gate */ 7237c478bd9Sstevel@tonic-gate if (current->entity_item_right_sibling != NULL) { 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate current = current->entity_item_right_sibling; 7267c478bd9Sstevel@tonic-gate found_page = found_usage_id = right_report_id = 0; 7277c478bd9Sstevel@tonic-gate } else { 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate break; 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate *main_item_descr_value = (uint_t)NULL; 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate return (HIDPARSER_NOT_FOUND); 7367c478bd9Sstevel@tonic-gate } 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate 7397c478bd9Sstevel@tonic-gate /* 7407c478bd9Sstevel@tonic-gate * hidparser_get_top_level_collection_usage: 7417c478bd9Sstevel@tonic-gate * Get the usage page and usage for the top level collection item 7427c478bd9Sstevel@tonic-gate */ 7437c478bd9Sstevel@tonic-gate int 7447c478bd9Sstevel@tonic-gate hidparser_get_top_level_collection_usage(hidparser_handle_t parse_handle, 7457c478bd9Sstevel@tonic-gate uint_t *usage_page, 7467c478bd9Sstevel@tonic-gate uint_t *usage_id) 7477c478bd9Sstevel@tonic-gate { 7487c478bd9Sstevel@tonic-gate entity_item_t *current; 7497c478bd9Sstevel@tonic-gate entity_attribute_t *attribute; 7507c478bd9Sstevel@tonic-gate int found_usage_id = 0; 7517c478bd9Sstevel@tonic-gate int found_page = 0; 7527c478bd9Sstevel@tonic-gate uint32_t usage; 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate if ((parse_handle == NULL) || 7557c478bd9Sstevel@tonic-gate (parse_handle->hidparser_handle_parse_tree == NULL)) 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate current = parse_handle->hidparser_handle_parse_tree; 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate if (current->entity_item_type != R_ITEM_COLLECTION) { 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate attribute = current->entity_item_attributes; 7667c478bd9Sstevel@tonic-gate while (attribute != NULL) { 7677c478bd9Sstevel@tonic-gate if (attribute->entity_attribute_tag == R_ITEM_USAGE) { 7687c478bd9Sstevel@tonic-gate found_usage_id = 1; 7697c478bd9Sstevel@tonic-gate usage = hidparser_find_unsigned_val(attribute); 7707c478bd9Sstevel@tonic-gate *usage_id = HID_USAGE_ID(usage); 7717c478bd9Sstevel@tonic-gate if (attribute->entity_attribute_length == 3) { 7727c478bd9Sstevel@tonic-gate if (HID_USAGE_PAGE(usage)) { 7737c478bd9Sstevel@tonic-gate found_page = 1; 7747c478bd9Sstevel@tonic-gate *usage_page = HID_USAGE_PAGE(usage); 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate } 7777c478bd9Sstevel@tonic-gate if (found_usage_id && found_page) { 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate } else if (attribute->entity_attribute_tag == 7827c478bd9Sstevel@tonic-gate R_ITEM_USAGE_PAGE) { 7837c478bd9Sstevel@tonic-gate found_page = 1; 7847c478bd9Sstevel@tonic-gate *usage_page = attribute->entity_attribute_value[0]; 7857c478bd9Sstevel@tonic-gate if (found_usage_id && found_page) { 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 7887c478bd9Sstevel@tonic-gate } 7897c478bd9Sstevel@tonic-gate } 7907c478bd9Sstevel@tonic-gate attribute = attribute->entity_attribute_next; 7917c478bd9Sstevel@tonic-gate } 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 7947c478bd9Sstevel@tonic-gate } 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate /* 7987c478bd9Sstevel@tonic-gate * hidparser_get_usage_list_in_order: 7997c478bd9Sstevel@tonic-gate * Find all the usages corresponding to a main item and report id. 8007c478bd9Sstevel@tonic-gate * Note that only short items are supported. 8017c478bd9Sstevel@tonic-gate * 8027c478bd9Sstevel@tonic-gate * Arguments: 8037c478bd9Sstevel@tonic-gate * parser_handle: 8047c478bd9Sstevel@tonic-gate * hid parser handle 8057c478bd9Sstevel@tonic-gate * report id: 8067c478bd9Sstevel@tonic-gate * report id of the particular report where the usages belong to 8077c478bd9Sstevel@tonic-gate * main_item_type: 8087c478bd9Sstevel@tonic-gate * type of report, either Input, Output, or Feature 8097c478bd9Sstevel@tonic-gate * usage_list: 8107c478bd9Sstevel@tonic-gate * Filled in with the pointer to the first element of the 8117c478bd9Sstevel@tonic-gate * usage list 8127c478bd9Sstevel@tonic-gate * 8137c478bd9Sstevel@tonic-gate * Return values: 8147c478bd9Sstevel@tonic-gate * HIDPARSER_SUCCESS - returned success 8157c478bd9Sstevel@tonic-gate * HIDPARSER_NOT_FOUND - usage specified by the parameters was not found 8167c478bd9Sstevel@tonic-gate * HIDPARSER_FAILURE - unspecified failure 8177c478bd9Sstevel@tonic-gate */ 8187c478bd9Sstevel@tonic-gate int 8197c478bd9Sstevel@tonic-gate hidparser_get_usage_list_in_order(hidparser_handle_t parser_handle, 8207c478bd9Sstevel@tonic-gate uint_t report_id, 8217c478bd9Sstevel@tonic-gate uint_t main_item_type, 8227c478bd9Sstevel@tonic-gate hidparser_rpt_t *rpt) 8237c478bd9Sstevel@tonic-gate { 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate if ((parser_handle == NULL) || 8267c478bd9Sstevel@tonic-gate (parser_handle->hidparser_handle_parse_tree == NULL)) { 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 8297c478bd9Sstevel@tonic-gate } 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate rpt->no_of_usages = 0; 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate return (hidparser_get_usage_list_in_order_internal( 8347c478bd9Sstevel@tonic-gate parser_handle->hidparser_handle_parse_tree, HID_USAGE_UNDEFINED, 8357c478bd9Sstevel@tonic-gate report_id, main_item_type, rpt)); 8367c478bd9Sstevel@tonic-gate } 8377c478bd9Sstevel@tonic-gate 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate static int 8407c478bd9Sstevel@tonic-gate hidparser_get_usage_list_in_order_internal(entity_item_t *parser_handle, 8417c478bd9Sstevel@tonic-gate uint_t collection_usage, 8427c478bd9Sstevel@tonic-gate uint_t report_id, 8437c478bd9Sstevel@tonic-gate uint_t main_item_type, 8447c478bd9Sstevel@tonic-gate hidparser_rpt_t *rpt) 8457c478bd9Sstevel@tonic-gate { 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate /* setup wrapper function */ 8487c478bd9Sstevel@tonic-gate entity_item_t *current = parser_handle; 8497c478bd9Sstevel@tonic-gate entity_attribute_t *attribute; 8507c478bd9Sstevel@tonic-gate uchar_t foundreportid, right_report_id, valid_usage; 851d2bde62eSgc161489 uchar_t found_usage_min, found_usage_max, found_usage; 852d2bde62eSgc161489 int i, j; 8537c478bd9Sstevel@tonic-gate int rval; 854d2bde62eSgc161489 uint32_t usage, usage_min, usage_max, usage_id[USAGE_MAX]; 855d2bde62eSgc161489 hidparser_usage_info_t *ui; 8567c478bd9Sstevel@tonic-gate 8577c478bd9Sstevel@tonic-gate found_usage_min = 0; 8587c478bd9Sstevel@tonic-gate found_usage_max = 0; 8597c478bd9Sstevel@tonic-gate foundreportid = 0; 8607c478bd9Sstevel@tonic-gate right_report_id = 0; 8617c478bd9Sstevel@tonic-gate 8627c478bd9Sstevel@tonic-gate while (current) { 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate if (current->entity_item_type == R_ITEM_COLLECTION) { 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate /* 8677c478bd9Sstevel@tonic-gate * find collection usage information for this 8687c478bd9Sstevel@tonic-gate * collection 8697c478bd9Sstevel@tonic-gate */ 8707c478bd9Sstevel@tonic-gate valid_usage = 0; 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate attribute = current->entity_item_attributes; 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate while (attribute != NULL) { 8757c478bd9Sstevel@tonic-gate if (attribute->entity_attribute_tag == 8767c478bd9Sstevel@tonic-gate R_ITEM_USAGE) { 8777c478bd9Sstevel@tonic-gate usage = hidparser_find_unsigned_val( 8787c478bd9Sstevel@tonic-gate attribute); 8797c478bd9Sstevel@tonic-gate valid_usage = 1; 8807c478bd9Sstevel@tonic-gate } 8817c478bd9Sstevel@tonic-gate attribute = attribute->entity_attribute_next; 8827c478bd9Sstevel@tonic-gate } 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate if (!valid_usage) { 8857c478bd9Sstevel@tonic-gate usage = HID_USAGE_UNDEFINED; 8867c478bd9Sstevel@tonic-gate } 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate rval = hidparser_get_usage_list_in_order_internal( 8897c478bd9Sstevel@tonic-gate current->info.child, usage, 8907c478bd9Sstevel@tonic-gate report_id, main_item_type, rpt); 8917c478bd9Sstevel@tonic-gate if (rval != HIDPARSER_SUCCESS) { 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate return (rval); 8947c478bd9Sstevel@tonic-gate } 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate } else if (current->entity_item_type == main_item_type) { 8977c478bd9Sstevel@tonic-gate /* Match Item Type */ 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate foundreportid = 0; 9007c478bd9Sstevel@tonic-gate right_report_id = 0; 9017c478bd9Sstevel@tonic-gate found_usage_min = 0; 9027c478bd9Sstevel@tonic-gate found_usage_max = 0; 903d2bde62eSgc161489 found_usage = 0; 9047c478bd9Sstevel@tonic-gate valid_usage = 0; 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate attribute = current->entity_item_attributes; 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate while (attribute != NULL) { 9097c478bd9Sstevel@tonic-gate switch (attribute->entity_attribute_tag) { 9107c478bd9Sstevel@tonic-gate case R_ITEM_REPORT_ID: 9117c478bd9Sstevel@tonic-gate foundreportid = 1; 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate if (attribute-> 9147c478bd9Sstevel@tonic-gate entity_attribute_value[0] == 9157c478bd9Sstevel@tonic-gate report_id) { 9167c478bd9Sstevel@tonic-gate right_report_id = 1; 9177c478bd9Sstevel@tonic-gate } else { 9187c478bd9Sstevel@tonic-gate /* different report id */ 9197c478bd9Sstevel@tonic-gate valid_usage = 1; 9207c478bd9Sstevel@tonic-gate } 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate break; 923d2bde62eSgc161489 case R_ITEM_USAGE: 924d2bde62eSgc161489 if (found_usage >= USAGE_MAX) { 925d2bde62eSgc161489 926d2bde62eSgc161489 return (HIDPARSER_FAILURE); 927d2bde62eSgc161489 } 928d2bde62eSgc161489 usage = hidparser_find_unsigned_val( 929d2bde62eSgc161489 attribute); 930d2bde62eSgc161489 if (usage) { 931d2bde62eSgc161489 usage_id[found_usage] = usage; 932d2bde62eSgc161489 found_usage++; 933d2bde62eSgc161489 } 934d2bde62eSgc161489 935d2bde62eSgc161489 break; 9367c478bd9Sstevel@tonic-gate case R_ITEM_USAGE_MIN: 9377c478bd9Sstevel@tonic-gate found_usage_min = 1; 9387c478bd9Sstevel@tonic-gate usage_min = hidparser_find_unsigned_val( 9397c478bd9Sstevel@tonic-gate attribute); 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate break; 9427c478bd9Sstevel@tonic-gate case R_ITEM_USAGE_MAX: 9437c478bd9Sstevel@tonic-gate found_usage_max = 1; 9447c478bd9Sstevel@tonic-gate usage_max = hidparser_find_unsigned_val( 9457c478bd9Sstevel@tonic-gate attribute); 9467c478bd9Sstevel@tonic-gate 9477c478bd9Sstevel@tonic-gate break; 9487c478bd9Sstevel@tonic-gate case R_ITEM_SET_DELIMITER: 949d2bde62eSgc161489 /* skip over alternate usages */ 950d2bde62eSgc161489 do { 951d2bde62eSgc161489 attribute = attribute-> 952d2bde62eSgc161489 entity_attribute_next; 953d2bde62eSgc161489 } while (attribute-> 954d2bde62eSgc161489 entity_attribute_tag != 955d2bde62eSgc161489 R_ITEM_SET_DELIMITER); 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate break; 9587c478bd9Sstevel@tonic-gate } 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate attribute = attribute->entity_attribute_next; 9617c478bd9Sstevel@tonic-gate } 9627c478bd9Sstevel@tonic-gate 9637c478bd9Sstevel@tonic-gate /* 964d2bde62eSgc161489 * If we have a report id match (or report ids 965d2bde62eSgc161489 * are not present), and have a usage item or 966d2bde62eSgc161489 * usage min&max, put the usage item into the 967d2bde62eSgc161489 * list. Don't put undefined usage items 968d2bde62eSgc161489 * (HID_USAGE_UNDEFINED, 0) into the list; 969d2bde62eSgc161489 * a 0 usage item is used to match padding 970d2bde62eSgc161489 * fields that don't have an attached usage. 971d2bde62eSgc161489 */ 972d2bde62eSgc161489 if (!foundreportid || 973d2bde62eSgc161489 (foundreportid && right_report_id)) { 974d2bde62eSgc161489 975d2bde62eSgc161489 for (j = 0; j < found_usage; j++) { 976d2bde62eSgc161489 977d2bde62eSgc161489 /* Put in usage list */ 978d2bde62eSgc161489 if (rpt->no_of_usages >= USAGE_MAX) { 979d2bde62eSgc161489 980d2bde62eSgc161489 return (HIDPARSER_FAILURE); 981d2bde62eSgc161489 } 982d2bde62eSgc161489 983d2bde62eSgc161489 i = rpt->no_of_usages++; 984d2bde62eSgc161489 ui = &(rpt->usage_descr[i]); 985d2bde62eSgc161489 986d2bde62eSgc161489 hidparser_fill_usage_info(ui, 987d2bde62eSgc161489 current->entity_item_attributes); 988d2bde62eSgc161489 989d2bde62eSgc161489 ui->rptcnt /= found_usage; 990d2bde62eSgc161489 ui->collection_usage = collection_usage; 991d2bde62eSgc161489 ui->usage_id = HID_USAGE_ID( 992d2bde62eSgc161489 usage_id[j]); 993d2bde62eSgc161489 994d2bde62eSgc161489 /* 995d2bde62eSgc161489 * This is an extended usage ie. 996d2bde62eSgc161489 * usage page in upper 16 bits 997d2bde62eSgc161489 * or-ed with usage in the lower 998d2bde62eSgc161489 * 16 bits. 999d2bde62eSgc161489 */ 1000d2bde62eSgc161489 if (usage_id[j] >> 16) { 1001d2bde62eSgc161489 ui->usage_page = 1002d2bde62eSgc161489 HID_USAGE_PAGE(usage_id[j]); 1003d2bde62eSgc161489 } 1004d2bde62eSgc161489 1005d2bde62eSgc161489 rpt->report_id = report_id; 1006d2bde62eSgc161489 valid_usage = 1; 1007d2bde62eSgc161489 } 1008d2bde62eSgc161489 1009d2bde62eSgc161489 if (found_usage_min && found_usage_max) { 1010d2bde62eSgc161489 1011d2bde62eSgc161489 /* Put in usage list */ 1012d2bde62eSgc161489 if (rpt->no_of_usages >= USAGE_MAX) { 1013d2bde62eSgc161489 1014d2bde62eSgc161489 return (HIDPARSER_FAILURE); 1015d2bde62eSgc161489 } 1016d2bde62eSgc161489 1017d2bde62eSgc161489 if (found_usage) { 1018d2bde62eSgc161489 1019d2bde62eSgc161489 /* handle duplication */ 1020d2bde62eSgc161489 ui->usage_min = HID_USAGE_ID( 1021d2bde62eSgc161489 usage_min); 1022d2bde62eSgc161489 ui->usage_max = HID_USAGE_ID( 1023d2bde62eSgc161489 usage_max); 1024d2bde62eSgc161489 } else { 1025d2bde62eSgc161489 i = rpt->no_of_usages++; 1026d2bde62eSgc161489 ui = &(rpt->usage_descr[i]); 1027d2bde62eSgc161489 1028d2bde62eSgc161489 hidparser_fill_usage_info(ui, 1029d2bde62eSgc161489 current-> 1030d2bde62eSgc161489 entity_item_attributes); 1031d2bde62eSgc161489 1032d2bde62eSgc161489 ui->collection_usage = 1033d2bde62eSgc161489 collection_usage; 1034d2bde62eSgc161489 ui->usage_min = HID_USAGE_ID( 1035d2bde62eSgc161489 usage_min); 1036d2bde62eSgc161489 ui->usage_max = HID_USAGE_ID( 1037d2bde62eSgc161489 usage_max); 1038d2bde62eSgc161489 1039d2bde62eSgc161489 rpt->report_id = report_id; 1040d2bde62eSgc161489 valid_usage = 1; 1041d2bde62eSgc161489 } 1042d2bde62eSgc161489 1043d2bde62eSgc161489 /* 1044d2bde62eSgc161489 * This is an extended usage ie. 1045d2bde62eSgc161489 * usage page in upper 16 bits 1046d2bde62eSgc161489 * or-ed with usage_max in the lower 1047d2bde62eSgc161489 * 16 bits. 1048d2bde62eSgc161489 */ 1049d2bde62eSgc161489 if (usage_max >> 16) { 1050d2bde62eSgc161489 ui->usage_page = 1051d2bde62eSgc161489 HID_USAGE_PAGE(usage_max); 1052d2bde62eSgc161489 } 1053d2bde62eSgc161489 } 1054d2bde62eSgc161489 } 1055d2bde62eSgc161489 1056d2bde62eSgc161489 /* 10577c478bd9Sstevel@tonic-gate * This main item contains no usage 10587c478bd9Sstevel@tonic-gate * Fill in with usage "UNDEFINED". 10597c478bd9Sstevel@tonic-gate * If report id is valid, only the 10607c478bd9Sstevel@tonic-gate * main item with matched report id 10617c478bd9Sstevel@tonic-gate * can be filled in. 10627c478bd9Sstevel@tonic-gate */ 10637c478bd9Sstevel@tonic-gate if (!valid_usage) { 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate if (rpt->no_of_usages >= USAGE_MAX) { 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 10687c478bd9Sstevel@tonic-gate } 10697c478bd9Sstevel@tonic-gate 1070d2bde62eSgc161489 i = rpt->no_of_usages++; 1071d2bde62eSgc161489 ui = &(rpt->usage_descr[i]); 1072d2bde62eSgc161489 1073d2bde62eSgc161489 hidparser_fill_usage_info(ui, 10747c478bd9Sstevel@tonic-gate current->entity_item_attributes); 10757c478bd9Sstevel@tonic-gate 1076d2bde62eSgc161489 ui->collection_usage = collection_usage; 1077d2bde62eSgc161489 ui->usage_id = HID_USAGE_UNDEFINED; 10787c478bd9Sstevel@tonic-gate 10797c478bd9Sstevel@tonic-gate rpt->report_id = report_id; 10807c478bd9Sstevel@tonic-gate } 10817c478bd9Sstevel@tonic-gate 10827c478bd9Sstevel@tonic-gate } 10837c478bd9Sstevel@tonic-gate 10847c478bd9Sstevel@tonic-gate current = current->entity_item_right_sibling; 10857c478bd9Sstevel@tonic-gate 10867c478bd9Sstevel@tonic-gate } /* end while current */ 10877c478bd9Sstevel@tonic-gate 10887c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 10897c478bd9Sstevel@tonic-gate } 10907c478bd9Sstevel@tonic-gate 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate /* 10937c478bd9Sstevel@tonic-gate * hidparser_fill_usage_info(): 10947c478bd9Sstevel@tonic-gate * Fill in the mandatory item information for a main item. 10957c478bd9Sstevel@tonic-gate * See HID 6.2.2. 10967c478bd9Sstevel@tonic-gate */ 10977c478bd9Sstevel@tonic-gate static void 10987c478bd9Sstevel@tonic-gate hidparser_fill_usage_info(hidparser_usage_info_t *ui, 10997c478bd9Sstevel@tonic-gate entity_attribute_t *attribute) 11007c478bd9Sstevel@tonic-gate { 11017c478bd9Sstevel@tonic-gate bzero(ui, sizeof (*ui)); 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate while (attribute) { 11047c478bd9Sstevel@tonic-gate switch (attribute->entity_attribute_tag) { 11057c478bd9Sstevel@tonic-gate case R_ITEM_LOGICAL_MINIMUM: 11067c478bd9Sstevel@tonic-gate ui->lmin = hidparser_find_signed_val(attribute); 11077c478bd9Sstevel@tonic-gate 11087c478bd9Sstevel@tonic-gate break; 11097c478bd9Sstevel@tonic-gate case R_ITEM_LOGICAL_MAXIMUM: 11107c478bd9Sstevel@tonic-gate ui->lmax = hidparser_find_signed_val(attribute); 11117c478bd9Sstevel@tonic-gate 11127c478bd9Sstevel@tonic-gate break; 11137c478bd9Sstevel@tonic-gate case R_ITEM_REPORT_COUNT: 11147c478bd9Sstevel@tonic-gate ui->rptcnt = hidparser_find_unsigned_val(attribute); 11157c478bd9Sstevel@tonic-gate 11167c478bd9Sstevel@tonic-gate break; 11177c478bd9Sstevel@tonic-gate case R_ITEM_REPORT_SIZE: 11187c478bd9Sstevel@tonic-gate ui->rptsz = hidparser_find_unsigned_val(attribute); 11197c478bd9Sstevel@tonic-gate 11207c478bd9Sstevel@tonic-gate break; 11217c478bd9Sstevel@tonic-gate case R_ITEM_USAGE_PAGE: 11227c478bd9Sstevel@tonic-gate ui->usage_page = hidparser_find_unsigned_val(attribute) 11237c478bd9Sstevel@tonic-gate & 0xffff; 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate break; 11267c478bd9Sstevel@tonic-gate } 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate attribute = attribute->entity_attribute_next; 11297c478bd9Sstevel@tonic-gate } 11307c478bd9Sstevel@tonic-gate } 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate 11337c478bd9Sstevel@tonic-gate /* 11347c478bd9Sstevel@tonic-gate * hidparser_get_report_id_list: 11357c478bd9Sstevel@tonic-gate * Return a list of all report ids used for descriptor items 11367c478bd9Sstevel@tonic-gate * corresponding to a main item. 11377c478bd9Sstevel@tonic-gate * 11387c478bd9Sstevel@tonic-gate * Arguments: 11397c478bd9Sstevel@tonic-gate * parser_handle: 11407c478bd9Sstevel@tonic-gate * hid parser handle 11417c478bd9Sstevel@tonic-gate * main_item_type: 11427c478bd9Sstevel@tonic-gate * type of report, either Input, Output, or Feature 11437c478bd9Sstevel@tonic-gate * report_id_list: 11447c478bd9Sstevel@tonic-gate * Filled in with a list of report ids found in the descriptor 11457c478bd9Sstevel@tonic-gate * 11467c478bd9Sstevel@tonic-gate * Return values: 11477c478bd9Sstevel@tonic-gate * HIDPARSER_SUCCESS - returned success 11487c478bd9Sstevel@tonic-gate * HIDPARSER_FAILURE - unspecified failure 11497c478bd9Sstevel@tonic-gate */ 11507c478bd9Sstevel@tonic-gate int 11517c478bd9Sstevel@tonic-gate hidparser_get_report_id_list(hidparser_handle_t parser_handle, 11527c478bd9Sstevel@tonic-gate uint_t main_item_type, 11537c478bd9Sstevel@tonic-gate hidparser_report_id_list_t *report_id_list) 11547c478bd9Sstevel@tonic-gate { 11557c478bd9Sstevel@tonic-gate 11567c478bd9Sstevel@tonic-gate if ((parser_handle == NULL) || 11577c478bd9Sstevel@tonic-gate (parser_handle->hidparser_handle_parse_tree == NULL)) { 11587c478bd9Sstevel@tonic-gate 11597c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 11607c478bd9Sstevel@tonic-gate } 11617c478bd9Sstevel@tonic-gate 11627c478bd9Sstevel@tonic-gate report_id_list->no_of_report_ids = 0; 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate return (hidparser_get_report_id_list_internal( 11657c478bd9Sstevel@tonic-gate parser_handle->hidparser_handle_parse_tree, 11667c478bd9Sstevel@tonic-gate main_item_type, report_id_list)); 11677c478bd9Sstevel@tonic-gate } 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate 11707c478bd9Sstevel@tonic-gate /* 11717c478bd9Sstevel@tonic-gate * hidparser_get_report_id_list_internal: 11727c478bd9Sstevel@tonic-gate * internal function that generates list of all report ids 11737c478bd9Sstevel@tonic-gate */ 11747c478bd9Sstevel@tonic-gate int 11757c478bd9Sstevel@tonic-gate hidparser_get_report_id_list_internal( 11767c478bd9Sstevel@tonic-gate entity_item_t *parser_handle, 11777c478bd9Sstevel@tonic-gate uint_t main_item_type, 11787c478bd9Sstevel@tonic-gate hidparser_report_id_list_t *id_lst) 11797c478bd9Sstevel@tonic-gate { 11807c478bd9Sstevel@tonic-gate /* setup wrapper function */ 11817c478bd9Sstevel@tonic-gate entity_item_t *current = parser_handle; 11827c478bd9Sstevel@tonic-gate entity_attribute_t *attribute; 11837c478bd9Sstevel@tonic-gate uint_t report_id = 0; 11847c478bd9Sstevel@tonic-gate int i = 0; 11857c478bd9Sstevel@tonic-gate int rval; 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate while (current) { 11887c478bd9Sstevel@tonic-gate 11897c478bd9Sstevel@tonic-gate if (current->entity_item_type == R_ITEM_COLLECTION) { 11907c478bd9Sstevel@tonic-gate 11917c478bd9Sstevel@tonic-gate rval = hidparser_get_report_id_list_internal( 11927c478bd9Sstevel@tonic-gate current->info.child, main_item_type, id_lst); 11937c478bd9Sstevel@tonic-gate if (rval != HIDPARSER_SUCCESS) { 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate return (rval); 11967c478bd9Sstevel@tonic-gate } 11977c478bd9Sstevel@tonic-gate 11987c478bd9Sstevel@tonic-gate } else if (current->entity_item_type == main_item_type) { 11997c478bd9Sstevel@tonic-gate /* Match Item Type */ 12007c478bd9Sstevel@tonic-gate attribute = current->entity_item_attributes; 12017c478bd9Sstevel@tonic-gate 12027c478bd9Sstevel@tonic-gate while (attribute != NULL) { 12037c478bd9Sstevel@tonic-gate 12047c478bd9Sstevel@tonic-gate if (attribute->entity_attribute_tag == 12057c478bd9Sstevel@tonic-gate R_ITEM_REPORT_ID) { 12067c478bd9Sstevel@tonic-gate 12077c478bd9Sstevel@tonic-gate /* Found a Report ID */ 12087c478bd9Sstevel@tonic-gate report_id = attribute-> 12097c478bd9Sstevel@tonic-gate entity_attribute_value[0]; 12107c478bd9Sstevel@tonic-gate 12117c478bd9Sstevel@tonic-gate /* Report ID already in list? */ 12127c478bd9Sstevel@tonic-gate for (i = 0; 12137c478bd9Sstevel@tonic-gate i < id_lst->no_of_report_ids; 12147c478bd9Sstevel@tonic-gate i++) { 12157c478bd9Sstevel@tonic-gate if (report_id == id_lst-> 12167c478bd9Sstevel@tonic-gate report_id[i]) { 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate break; 12197c478bd9Sstevel@tonic-gate } 12207c478bd9Sstevel@tonic-gate } 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate if (i >= id_lst->no_of_report_ids) { 12237c478bd9Sstevel@tonic-gate /* 12247c478bd9Sstevel@tonic-gate * New Report ID found, put 12257c478bd9Sstevel@tonic-gate * in list 12267c478bd9Sstevel@tonic-gate */ 12277c478bd9Sstevel@tonic-gate if (i >= REPORT_ID_MAX) { 12287c478bd9Sstevel@tonic-gate 12297c478bd9Sstevel@tonic-gate return 12307c478bd9Sstevel@tonic-gate (HIDPARSER_FAILURE); 12317c478bd9Sstevel@tonic-gate } 12327c478bd9Sstevel@tonic-gate 12337c478bd9Sstevel@tonic-gate id_lst->report_id[i] = 12347c478bd9Sstevel@tonic-gate report_id; 12357c478bd9Sstevel@tonic-gate id_lst->no_of_report_ids++; 12367c478bd9Sstevel@tonic-gate } 12377c478bd9Sstevel@tonic-gate } 12387c478bd9Sstevel@tonic-gate 12397c478bd9Sstevel@tonic-gate attribute = attribute->entity_attribute_next; 12407c478bd9Sstevel@tonic-gate } 12417c478bd9Sstevel@tonic-gate } 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate current = current->entity_item_right_sibling; 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate } /* end while current */ 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 12487c478bd9Sstevel@tonic-gate } 12497c478bd9Sstevel@tonic-gate 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate /* 12527c478bd9Sstevel@tonic-gate * hidparser_print_report_descr_handle: 12537c478bd9Sstevel@tonic-gate * Functions to print the parse tree. Currently not 12547c478bd9Sstevel@tonic-gate * being called. 12557c478bd9Sstevel@tonic-gate */ 12567c478bd9Sstevel@tonic-gate static int 12577c478bd9Sstevel@tonic-gate hidparser_print_report_descr_handle(entity_item_t *handle, 12587c478bd9Sstevel@tonic-gate int indent_level) 12597c478bd9Sstevel@tonic-gate { 12607c478bd9Sstevel@tonic-gate entity_item_t *current = handle; 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate while (current) { 12637c478bd9Sstevel@tonic-gate if (current->info.child) { 12647c478bd9Sstevel@tonic-gate hidparser_print_entity(current, indent_level); 12657c478bd9Sstevel@tonic-gate /* do children */ 12667c478bd9Sstevel@tonic-gate (void) hidparser_print_report_descr_handle( 12677c478bd9Sstevel@tonic-gate current->info.child, indent_level+1); 12687c478bd9Sstevel@tonic-gate } else /* just a regular entity */ { 12697c478bd9Sstevel@tonic-gate hidparser_print_entity(current, indent_level); 12707c478bd9Sstevel@tonic-gate } 12717c478bd9Sstevel@tonic-gate current = current->entity_item_right_sibling; 12727c478bd9Sstevel@tonic-gate } 12737c478bd9Sstevel@tonic-gate 12747c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 12757c478bd9Sstevel@tonic-gate } 12767c478bd9Sstevel@tonic-gate 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate #define SPACE_PER_LEVEL 5 12797c478bd9Sstevel@tonic-gate 12807c478bd9Sstevel@tonic-gate /* 12817c478bd9Sstevel@tonic-gate * hidparser_print_entity ; 12827c478bd9Sstevel@tonic-gate * Prints the entity items recursively 12837c478bd9Sstevel@tonic-gate */ 12847c478bd9Sstevel@tonic-gate static void 12857c478bd9Sstevel@tonic-gate hidparser_print_entity(entity_item_t *entity, int indent_level) 12867c478bd9Sstevel@tonic-gate { 12877c478bd9Sstevel@tonic-gate char indent_space[256]; 12887c478bd9Sstevel@tonic-gate int count; 12897c478bd9Sstevel@tonic-gate entity_attribute_t *attr; 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate indent_level *= SPACE_PER_LEVEL; 12927c478bd9Sstevel@tonic-gate 1293112116d8Sfb209375 for (count = 0; indent_level--; count++) 1294112116d8Sfb209375 indent_space[count] = ' '; 12957c478bd9Sstevel@tonic-gate 12967c478bd9Sstevel@tonic-gate indent_space[count] = 0; 12977c478bd9Sstevel@tonic-gate 12987c478bd9Sstevel@tonic-gate attr = entity->entity_item_attributes; 12997c478bd9Sstevel@tonic-gate while (attr) { 13007c478bd9Sstevel@tonic-gate hidparser_print_this_attribute(attr, indent_space); 13017c478bd9Sstevel@tonic-gate attr = attr->entity_attribute_next; 13027c478bd9Sstevel@tonic-gate } 13037c478bd9Sstevel@tonic-gate 13047c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, hparser_log_handle, "%s%s(0x%x)", 13057c478bd9Sstevel@tonic-gate indent_space, items[entity->entity_item_type], 13067c478bd9Sstevel@tonic-gate (entity->entity_item_params_leng ? 13077c478bd9Sstevel@tonic-gate entity->entity_item_params[0] & 0xFF : 0x00)); 13087c478bd9Sstevel@tonic-gate } 13097c478bd9Sstevel@tonic-gate 13107c478bd9Sstevel@tonic-gate 13117c478bd9Sstevel@tonic-gate /* 13127c478bd9Sstevel@tonic-gate * hidparser_print_this_attribute: 13137c478bd9Sstevel@tonic-gate * Prints the attribute passed in the argument 13147c478bd9Sstevel@tonic-gate */ 13157c478bd9Sstevel@tonic-gate static void 13167c478bd9Sstevel@tonic-gate hidparser_print_this_attribute(entity_attribute_t *attribute, 13177c478bd9Sstevel@tonic-gate char *ident_space) 13187c478bd9Sstevel@tonic-gate { 13197c478bd9Sstevel@tonic-gate if (ident_space == NULL) { 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, hparser_log_handle, 13227c478bd9Sstevel@tonic-gate "%s(0x%X)", 13237c478bd9Sstevel@tonic-gate items[attribute->entity_attribute_tag], 13247c478bd9Sstevel@tonic-gate hidparser_find_unsigned_val(attribute)); 13257c478bd9Sstevel@tonic-gate } else { 13267c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, hparser_log_handle, 13277c478bd9Sstevel@tonic-gate "%s%s(0x%X)", ident_space, 13287c478bd9Sstevel@tonic-gate items[attribute->entity_attribute_tag], 13297c478bd9Sstevel@tonic-gate hidparser_find_unsigned_val(attribute)); 13307c478bd9Sstevel@tonic-gate 13317c478bd9Sstevel@tonic-gate } 13327c478bd9Sstevel@tonic-gate } 13337c478bd9Sstevel@tonic-gate 13347c478bd9Sstevel@tonic-gate 13357c478bd9Sstevel@tonic-gate /* 13367c478bd9Sstevel@tonic-gate * The next few functions will be used for parsing using the 13377c478bd9Sstevel@tonic-gate * grammar: 13387c478bd9Sstevel@tonic-gate * 13397c478bd9Sstevel@tonic-gate * Start -> ReportDescriptor <EOF> 13407c478bd9Sstevel@tonic-gate * 13417c478bd9Sstevel@tonic-gate * ReportDescriptor -> ItemList 13427c478bd9Sstevel@tonic-gate * 13437c478bd9Sstevel@tonic-gate * ItemList -> Items MainItem ItemList 13447c478bd9Sstevel@tonic-gate * | epsilon 13457c478bd9Sstevel@tonic-gate * 13467c478bd9Sstevel@tonic-gate * MainItem -> BeginCollection ItemList EndCollection 13477c478bd9Sstevel@tonic-gate * | Input 13487c478bd9Sstevel@tonic-gate * | Output 13497c478bd9Sstevel@tonic-gate * | Feature 13507c478bd9Sstevel@tonic-gate * 13517c478bd9Sstevel@tonic-gate * Items -> GlobalItem Items 13527c478bd9Sstevel@tonic-gate * | LocalItem Items 13537c478bd9Sstevel@tonic-gate * | SetDelimiterOpen LocalItemList 13547c478bd9Sstevel@tonic-gate * SetDelimiterClose Items 13557c478bd9Sstevel@tonic-gate * | epsilon 13567c478bd9Sstevel@tonic-gate * 13577c478bd9Sstevel@tonic-gate * LocalItemList -> LocalItem Temp2 13587c478bd9Sstevel@tonic-gate * 13597c478bd9Sstevel@tonic-gate * Temp2 -> LocalItem Temp2 13607c478bd9Sstevel@tonic-gate * | epsilon 13617c478bd9Sstevel@tonic-gate * 13627c478bd9Sstevel@tonic-gate * GlobalItem -> UsagePage 13637c478bd9Sstevel@tonic-gate * | LogicalMinimum 13647c478bd9Sstevel@tonic-gate * | LogicalMaximum 13657c478bd9Sstevel@tonic-gate * | PhysicalMinimum 13667c478bd9Sstevel@tonic-gate * | PhysicalMaximum 13677c478bd9Sstevel@tonic-gate * | Unit 13687c478bd9Sstevel@tonic-gate * | Exponent 13697c478bd9Sstevel@tonic-gate * | ReportSize 13707c478bd9Sstevel@tonic-gate * | ReportCount 13717c478bd9Sstevel@tonic-gate * | ReportID 13727c478bd9Sstevel@tonic-gate * 13737c478bd9Sstevel@tonic-gate * LocalItem -> Usage 13747c478bd9Sstevel@tonic-gate * | UsageMinimum 13757c478bd9Sstevel@tonic-gate * | UsageMaximum 13767c478bd9Sstevel@tonic-gate * | DesignatorIndex 13777c478bd9Sstevel@tonic-gate * | DesignatorMinimum 13787c478bd9Sstevel@tonic-gate * | StringIndex 13797c478bd9Sstevel@tonic-gate * | StringMinimum 13807c478bd9Sstevel@tonic-gate * | StringMaximum 13817c478bd9Sstevel@tonic-gate * 13827c478bd9Sstevel@tonic-gate */ 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate 13857c478bd9Sstevel@tonic-gate /* 13867c478bd9Sstevel@tonic-gate * hidparser_lookup_first: 13877c478bd9Sstevel@tonic-gate * Looks up if token belongs to the FIRST of the function tag 13887c478bd9Sstevel@tonic-gate * that is passed through the first argument 13897c478bd9Sstevel@tonic-gate */ 13907c478bd9Sstevel@tonic-gate static int 13917c478bd9Sstevel@tonic-gate hidparser_lookup_first(int func_index, 13927c478bd9Sstevel@tonic-gate int token) 13937c478bd9Sstevel@tonic-gate { 13947c478bd9Sstevel@tonic-gate int *itemp; 13957c478bd9Sstevel@tonic-gate 13967c478bd9Sstevel@tonic-gate itemp = hid_first_list[func_index]; 13977c478bd9Sstevel@tonic-gate while (*itemp != 0) { 13987c478bd9Sstevel@tonic-gate /* get the next terminal on the list */ 13997c478bd9Sstevel@tonic-gate if (*itemp == token) { 14007c478bd9Sstevel@tonic-gate 14017c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 14027c478bd9Sstevel@tonic-gate } 14037c478bd9Sstevel@tonic-gate itemp++; 14047c478bd9Sstevel@tonic-gate } 14057c478bd9Sstevel@tonic-gate 14067c478bd9Sstevel@tonic-gate /* token is not on the FIRST list */ 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 14097c478bd9Sstevel@tonic-gate } 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate /* 14137c478bd9Sstevel@tonic-gate * hidparser_main: 14147c478bd9Sstevel@tonic-gate * Function called from hidparser_parse_report_descriptor() 14157c478bd9Sstevel@tonic-gate * to parse the Report Descriptor 14167c478bd9Sstevel@tonic-gate */ 14177c478bd9Sstevel@tonic-gate static int 14187c478bd9Sstevel@tonic-gate hidparser_main(unsigned char *descriptor, 14197c478bd9Sstevel@tonic-gate size_t size, 14207c478bd9Sstevel@tonic-gate entity_item_t **item_ptr) 14217c478bd9Sstevel@tonic-gate { 14227c478bd9Sstevel@tonic-gate hidparser_tok_t *scan_ifp; 14237c478bd9Sstevel@tonic-gate int retval; 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate scan_ifp = kmem_zalloc(sizeof (hidparser_tok_t), KM_SLEEP); 14267c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_text = 14277c478bd9Sstevel@tonic-gate kmem_zalloc(HIDPARSER_TEXT_LENGTH, KM_SLEEP); 14287c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_max_bsize = size; 14297c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_entity_descriptor = descriptor; 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate *item_ptr = NULL; 14327c478bd9Sstevel@tonic-gate retval = hidparser_ReportDescriptorDash(item_ptr, scan_ifp); 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate /* 14357c478bd9Sstevel@tonic-gate * Free the Local & Global item list 14367c478bd9Sstevel@tonic-gate * It maybe the case that no tree has been built 14377c478bd9Sstevel@tonic-gate * up but there have been allocation in the attribute 14387c478bd9Sstevel@tonic-gate * & control lists 14397c478bd9Sstevel@tonic-gate */ 14407c478bd9Sstevel@tonic-gate if (scan_ifp->hidparser_tok_gitem_head) { 14417c478bd9Sstevel@tonic-gate hidparser_free_attribute_list( 14427c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_gitem_head); 14437c478bd9Sstevel@tonic-gate } 14447c478bd9Sstevel@tonic-gate 14457c478bd9Sstevel@tonic-gate if (scan_ifp->hidparser_tok_litem_head) { 14467c478bd9Sstevel@tonic-gate hidparser_free_attribute_list( 14477c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_litem_head); 14487c478bd9Sstevel@tonic-gate } 14497c478bd9Sstevel@tonic-gate kmem_free(scan_ifp->hidparser_tok_text, HIDPARSER_TEXT_LENGTH); 14507c478bd9Sstevel@tonic-gate kmem_free(scan_ifp, sizeof (hidparser_tok_t)); 14517c478bd9Sstevel@tonic-gate 14527c478bd9Sstevel@tonic-gate return (retval); 14537c478bd9Sstevel@tonic-gate } 14547c478bd9Sstevel@tonic-gate 14557c478bd9Sstevel@tonic-gate 14567c478bd9Sstevel@tonic-gate /* 14577c478bd9Sstevel@tonic-gate * hidparser_ReportDescriptorDash: 14587c478bd9Sstevel@tonic-gate * Synthetic start symbol, implements 14597c478bd9Sstevel@tonic-gate * hidparser_ReportDescriptor <EOF> 14607c478bd9Sstevel@tonic-gate */ 14617c478bd9Sstevel@tonic-gate static int 14627c478bd9Sstevel@tonic-gate hidparser_ReportDescriptorDash(entity_item_t ** item_ptr, 14637c478bd9Sstevel@tonic-gate hidparser_tok_t *scan_ifp) 14647c478bd9Sstevel@tonic-gate { 14657c478bd9Sstevel@tonic-gate 14667c478bd9Sstevel@tonic-gate if ((hidparser_ReportDescriptor(item_ptr, scan_ifp) == 14677c478bd9Sstevel@tonic-gate HIDPARSER_SUCCESS) && (scan_ifp->hidparser_tok_token == 0)) { 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 14707c478bd9Sstevel@tonic-gate } 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate /* 14737c478bd9Sstevel@tonic-gate * In case of failure, free the kernel memory 14747c478bd9Sstevel@tonic-gate * allocated for partial building of the tree, 14757c478bd9Sstevel@tonic-gate * if any 14767c478bd9Sstevel@tonic-gate */ 14777c478bd9Sstevel@tonic-gate if (*item_ptr != NULL) { 14787c478bd9Sstevel@tonic-gate (void) hidparser_free_report_descr_handle(*item_ptr); 14797c478bd9Sstevel@tonic-gate } 14807c478bd9Sstevel@tonic-gate 14817c478bd9Sstevel@tonic-gate *item_ptr = NULL; 14827c478bd9Sstevel@tonic-gate 14837c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 14847c478bd9Sstevel@tonic-gate } 14857c478bd9Sstevel@tonic-gate 14867c478bd9Sstevel@tonic-gate 14877c478bd9Sstevel@tonic-gate /* 14887c478bd9Sstevel@tonic-gate * hidparser_ReportDescriptor: 14897c478bd9Sstevel@tonic-gate * Implements the Rule: 14907c478bd9Sstevel@tonic-gate * ReportDescriptor -> ItemList 14917c478bd9Sstevel@tonic-gate */ 14927c478bd9Sstevel@tonic-gate static int 14937c478bd9Sstevel@tonic-gate hidparser_ReportDescriptor(entity_item_t ** item_ptr, 14947c478bd9Sstevel@tonic-gate hidparser_tok_t *scan_ifp) 14957c478bd9Sstevel@tonic-gate { 14967c478bd9Sstevel@tonic-gate hidparser_scan(scan_ifp); 14977c478bd9Sstevel@tonic-gate 14987c478bd9Sstevel@tonic-gate /* 14997c478bd9Sstevel@tonic-gate * We do not search for the token in FIRST(ReportDescriptor) 15007c478bd9Sstevel@tonic-gate * since - 15017c478bd9Sstevel@tonic-gate * 15027c478bd9Sstevel@tonic-gate * FIRST(ReportDescriptor) == FIRST(ItemList) 15037c478bd9Sstevel@tonic-gate * ReportDescriptor ----> ItemList 15047c478bd9Sstevel@tonic-gate */ 15057c478bd9Sstevel@tonic-gate if (hidparser_ItemList(item_ptr, scan_ifp) == HIDPARSER_SUCCESS) { 15067c478bd9Sstevel@tonic-gate 15077c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 15087c478bd9Sstevel@tonic-gate } 15097c478bd9Sstevel@tonic-gate 15107c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 15117c478bd9Sstevel@tonic-gate } 15127c478bd9Sstevel@tonic-gate 15137c478bd9Sstevel@tonic-gate 15147c478bd9Sstevel@tonic-gate /* 15157c478bd9Sstevel@tonic-gate * hidparser_ItemList: 15167c478bd9Sstevel@tonic-gate * Implements the Rule: 15177c478bd9Sstevel@tonic-gate * ItemList -> Items MainItem ItemList | epsilon 15187c478bd9Sstevel@tonic-gate * 15197c478bd9Sstevel@tonic-gate * This function constructs the tree on which depends the "hidparser" 15207c478bd9Sstevel@tonic-gate * consumer functions. Basically the structure of the tree is 15217c478bd9Sstevel@tonic-gate * 15227c478bd9Sstevel@tonic-gate * C--[RS]->EC--[RS]->C--[RS]->EC..(and so on) 15237c478bd9Sstevel@tonic-gate * | 15247c478bd9Sstevel@tonic-gate * [CH] <== This relationship is true for other "C's" 15257c478bd9Sstevel@tonic-gate * | also. 15267c478bd9Sstevel@tonic-gate * v 15277c478bd9Sstevel@tonic-gate * C/-------------/I/O/F <== [ Any of these ] 15287c478bd9Sstevel@tonic-gate * | ------ 15297c478bd9Sstevel@tonic-gate * | | 15307c478bd9Sstevel@tonic-gate * v v 15317c478bd9Sstevel@tonic-gate * [CH | RS] [ RS ] 15327c478bd9Sstevel@tonic-gate * C/I/O/F | EC I/O/F 15337c478bd9Sstevel@tonic-gate * | 15347c478bd9Sstevel@tonic-gate * | 15357c478bd9Sstevel@tonic-gate * and so on... 15367c478bd9Sstevel@tonic-gate * 15377c478bd9Sstevel@tonic-gate * where C = Collection 15387c478bd9Sstevel@tonic-gate * EC = EndCollection 15397c478bd9Sstevel@tonic-gate * I = Input 15407c478bd9Sstevel@tonic-gate * O = Output 15417c478bd9Sstevel@tonic-gate * F = Feature "Main" Items. 15427c478bd9Sstevel@tonic-gate * 15437c478bd9Sstevel@tonic-gate * and the relationships are [RS] for right sibling and [CH] for 15447c478bd9Sstevel@tonic-gate * child. [CH | RS ] stands for "child or right sibling" with the 15457c478bd9Sstevel@tonic-gate * possible values below it. 15467c478bd9Sstevel@tonic-gate */ 15477c478bd9Sstevel@tonic-gate static int 15487c478bd9Sstevel@tonic-gate hidparser_ItemList(entity_item_t ** item_ptr, hidparser_tok_t *scan_ifp) 15497c478bd9Sstevel@tonic-gate { 15507c478bd9Sstevel@tonic-gate entity_item_t *curr_ei, *cache_ei, *prev_ei, *tmp_ei; 15517c478bd9Sstevel@tonic-gate boolean_t root_coll = B_FALSE; 15527c478bd9Sstevel@tonic-gate 15537c478bd9Sstevel@tonic-gate curr_ei = cache_ei = prev_ei = tmp_ei = NULL; 15547c478bd9Sstevel@tonic-gate 15557c478bd9Sstevel@tonic-gate while (scan_ifp->hidparser_tok_token != 0) { 15567c478bd9Sstevel@tonic-gate if (hidparser_Items(scan_ifp) == HIDPARSER_FAILURE) { 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 15597c478bd9Sstevel@tonic-gate } 15607c478bd9Sstevel@tonic-gate 15617c478bd9Sstevel@tonic-gate if (hidparser_MainItem(&curr_ei, scan_ifp) == 15627c478bd9Sstevel@tonic-gate HIDPARSER_FAILURE) { 15637c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, 15647c478bd9Sstevel@tonic-gate hparser_log_handle, 15657c478bd9Sstevel@tonic-gate "Invalid MAIN item 0x%x in input stream", 15667c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_token); 15677c478bd9Sstevel@tonic-gate 15687c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 15697c478bd9Sstevel@tonic-gate } 15707c478bd9Sstevel@tonic-gate if (curr_ei->entity_item_type == R_ITEM_COLLECTION) { 15717c478bd9Sstevel@tonic-gate if (root_coll == B_FALSE) { 15727c478bd9Sstevel@tonic-gate *item_ptr = curr_ei; 15737c478bd9Sstevel@tonic-gate root_coll = B_TRUE; 15747c478bd9Sstevel@tonic-gate } 15757c478bd9Sstevel@tonic-gate curr_ei->prev_coll = cache_ei; 15767c478bd9Sstevel@tonic-gate cache_ei = curr_ei; 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, 15797c478bd9Sstevel@tonic-gate hparser_log_handle, 1580112116d8Sfb209375 "Start Collection:cache_ei = 0x%p," 1581112116d8Sfb209375 " curr_ei = 0x%p", 1582112116d8Sfb209375 (void *)cache_ei, (void *)curr_ei); 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate if (prev_ei == NULL) { 15857c478bd9Sstevel@tonic-gate prev_ei = curr_ei; 15867c478bd9Sstevel@tonic-gate 15877c478bd9Sstevel@tonic-gate continue; 15887c478bd9Sstevel@tonic-gate } 15897c478bd9Sstevel@tonic-gate if (prev_ei->entity_item_type == 15907c478bd9Sstevel@tonic-gate R_ITEM_COLLECTION) { 15917c478bd9Sstevel@tonic-gate prev_ei->info.child = curr_ei; 15927c478bd9Sstevel@tonic-gate } else { 15937c478bd9Sstevel@tonic-gate prev_ei->entity_item_right_sibling = 15947c478bd9Sstevel@tonic-gate curr_ei; 15957c478bd9Sstevel@tonic-gate } 15967c478bd9Sstevel@tonic-gate } else if (curr_ei->entity_item_type == 15977c478bd9Sstevel@tonic-gate R_ITEM_END_COLLECTION) { 15987c478bd9Sstevel@tonic-gate tmp_ei = cache_ei->prev_coll; 15997c478bd9Sstevel@tonic-gate cache_ei->entity_item_right_sibling = curr_ei; 16007c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, 16017c478bd9Sstevel@tonic-gate hparser_log_handle, 1602112116d8Sfb209375 "End Collection: cache_ei = 0x%p, " 1603112116d8Sfb209375 "curr_ei = 0x%p", 1604112116d8Sfb209375 (void *)cache_ei, (void *)curr_ei); 16057c478bd9Sstevel@tonic-gate if (tmp_ei != NULL) { 16067c478bd9Sstevel@tonic-gate /* 16077c478bd9Sstevel@tonic-gate * As will be the case for final end 16087c478bd9Sstevel@tonic-gate * collection. 16097c478bd9Sstevel@tonic-gate */ 16107c478bd9Sstevel@tonic-gate cache_ei = tmp_ei; 16117c478bd9Sstevel@tonic-gate } 16127c478bd9Sstevel@tonic-gate tmp_ei = NULL; 16137c478bd9Sstevel@tonic-gate } else { 1614*e7cc2e17Sbc224572 if (prev_ei == NULL) { 1615*e7cc2e17Sbc224572 USB_DPRINTF_L2(PRINT_MASK_ALL, 1616*e7cc2e17Sbc224572 hparser_log_handle, 1617*e7cc2e17Sbc224572 "Invalid First MAIN item 0x%x", 1618*e7cc2e17Sbc224572 scan_ifp->hidparser_tok_token); 1619*e7cc2e17Sbc224572 1620*e7cc2e17Sbc224572 return (HIDPARSER_FAILURE); 1621*e7cc2e17Sbc224572 } 16227c478bd9Sstevel@tonic-gate if (prev_ei->entity_item_type == 16237c478bd9Sstevel@tonic-gate R_ITEM_COLLECTION) { 16247c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, 16257c478bd9Sstevel@tonic-gate hparser_log_handle, 16267c478bd9Sstevel@tonic-gate "Main Item: token = 0x%x, " 1627112116d8Sfb209375 "curr_ei = 0x%p " 16287c478bd9Sstevel@tonic-gate "will be the child of prev_ei " 1629112116d8Sfb209375 "= 0x%p, " 1630112116d8Sfb209375 "cache_ei being 0x%p", 16317c478bd9Sstevel@tonic-gate curr_ei->entity_item_type, 1632112116d8Sfb209375 (void *)curr_ei, (void *)prev_ei, 1633112116d8Sfb209375 (void *)cache_ei); 16347c478bd9Sstevel@tonic-gate prev_ei->info.child = curr_ei; 16357c478bd9Sstevel@tonic-gate } else { 16367c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, 16377c478bd9Sstevel@tonic-gate hparser_log_handle, 16387c478bd9Sstevel@tonic-gate "Main Item: token = 0x%x, " 1639112116d8Sfb209375 "curr_ei = 0x%p " 16407c478bd9Sstevel@tonic-gate "will be the right sibling of " 1641112116d8Sfb209375 "prev_ei = 0x%p, " 1642112116d8Sfb209375 "cache_ei being 0x%p", 16437c478bd9Sstevel@tonic-gate curr_ei->entity_item_type, 1644112116d8Sfb209375 (void *)curr_ei, (void *)prev_ei, 1645112116d8Sfb209375 (void *)cache_ei); 16467c478bd9Sstevel@tonic-gate prev_ei->entity_item_right_sibling = 16477c478bd9Sstevel@tonic-gate curr_ei; 16487c478bd9Sstevel@tonic-gate } 16497c478bd9Sstevel@tonic-gate } 16507c478bd9Sstevel@tonic-gate prev_ei = curr_ei; 16517c478bd9Sstevel@tonic-gate } 16527c478bd9Sstevel@tonic-gate if (*item_ptr != cache_ei) { 16537c478bd9Sstevel@tonic-gate /* Something wrong happened */ 16547c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, hparser_log_handle, 16557c478bd9Sstevel@tonic-gate "Failed to parse report descriptor"); 16567c478bd9Sstevel@tonic-gate 16577c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 16587c478bd9Sstevel@tonic-gate } 16597c478bd9Sstevel@tonic-gate (void) hidparser_print_report_descr_handle(cache_ei, 0); 16607c478bd9Sstevel@tonic-gate 16617c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 16627c478bd9Sstevel@tonic-gate } 16637c478bd9Sstevel@tonic-gate 16647c478bd9Sstevel@tonic-gate 16657c478bd9Sstevel@tonic-gate /* 16667c478bd9Sstevel@tonic-gate * hidparser_MainItem: 16677c478bd9Sstevel@tonic-gate * Implements the Rule: 16687c478bd9Sstevel@tonic-gate * MainItem -> BeginCollection ItemList EndCollection 16697c478bd9Sstevel@tonic-gate * | Input 16707c478bd9Sstevel@tonic-gate * | Output 16717c478bd9Sstevel@tonic-gate * | Feature 16727c478bd9Sstevel@tonic-gate */ 16737c478bd9Sstevel@tonic-gate static int 16747c478bd9Sstevel@tonic-gate hidparser_MainItem(entity_item_t ** item_ptr, 16757c478bd9Sstevel@tonic-gate hidparser_tok_t *scan_ifp) 16767c478bd9Sstevel@tonic-gate { 16777c478bd9Sstevel@tonic-gate switch (scan_ifp->hidparser_tok_token) { 16787c478bd9Sstevel@tonic-gate case R_ITEM_INPUT: 16797c478bd9Sstevel@tonic-gate /* FALLTHRU */ 16807c478bd9Sstevel@tonic-gate case R_ITEM_OUTPUT: 16817c478bd9Sstevel@tonic-gate /* FALLTHRU */ 16827c478bd9Sstevel@tonic-gate case R_ITEM_FEATURE: 16837c478bd9Sstevel@tonic-gate case R_ITEM_COLLECTION: 16847c478bd9Sstevel@tonic-gate case R_ITEM_END_COLLECTION: 16857c478bd9Sstevel@tonic-gate *item_ptr = hidparser_allocate_entity(scan_ifp); 16867c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, hparser_log_handle, 1687112116d8Sfb209375 "hidparser_MainItem:index = 0x%lx token = 0x%x", 16887c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_index - 16897c478bd9Sstevel@tonic-gate (*item_ptr)->entity_item_params_leng - 1, 16907c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_token); 16917c478bd9Sstevel@tonic-gate hidparser_scan(scan_ifp); 16927c478bd9Sstevel@tonic-gate hidparser_global_err_check(*item_ptr); 16937c478bd9Sstevel@tonic-gate hidparser_local_err_check(*item_ptr); 16947c478bd9Sstevel@tonic-gate hidparser_mainitem_err_check(*item_ptr); 16957c478bd9Sstevel@tonic-gate 16967c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 16977c478bd9Sstevel@tonic-gate 16987c478bd9Sstevel@tonic-gate default: 16997c478bd9Sstevel@tonic-gate break; 17007c478bd9Sstevel@tonic-gate } 17017c478bd9Sstevel@tonic-gate 17027c478bd9Sstevel@tonic-gate *item_ptr = NULL; 17037c478bd9Sstevel@tonic-gate 17047c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 17057c478bd9Sstevel@tonic-gate } 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate 17087c478bd9Sstevel@tonic-gate /* 17097c478bd9Sstevel@tonic-gate * hidparser_Items: 17107c478bd9Sstevel@tonic-gate * Implements the Rule: 17117c478bd9Sstevel@tonic-gate * Items -> GlobalItem Items 17127c478bd9Sstevel@tonic-gate * | LocalItem Items 17137c478bd9Sstevel@tonic-gate * | SetDelimiterOpen LocalItemList 17147c478bd9Sstevel@tonic-gate * SetDelimiterClose Items 17157c478bd9Sstevel@tonic-gate * | epsilon 17167c478bd9Sstevel@tonic-gate */ 17177c478bd9Sstevel@tonic-gate static int 17187c478bd9Sstevel@tonic-gate hidparser_Items(hidparser_tok_t *scan_ifp) 17197c478bd9Sstevel@tonic-gate { 17207c478bd9Sstevel@tonic-gate boolean_t delim_pre = B_FALSE; 17217c478bd9Sstevel@tonic-gate 17227c478bd9Sstevel@tonic-gate int token = scan_ifp->hidparser_tok_token; 17237c478bd9Sstevel@tonic-gate 17247c478bd9Sstevel@tonic-gate while (hidparser_lookup_first(HIDPARSER_ITEMS, token) == 17257c478bd9Sstevel@tonic-gate HIDPARSER_SUCCESS) { 17267c478bd9Sstevel@tonic-gate if (token == R_ITEM_SET_DELIMITER) { 17277c478bd9Sstevel@tonic-gate if (delim_pre == B_FALSE) { 17287c478bd9Sstevel@tonic-gate if (scan_ifp->hidparser_tok_text[0] != 1) { 17297c478bd9Sstevel@tonic-gate hidparser_error_delim(NULL, 17307c478bd9Sstevel@tonic-gate HIDPARSER_DELIM_ERR1); 17317c478bd9Sstevel@tonic-gate } else { 17327c478bd9Sstevel@tonic-gate delim_pre = B_TRUE; 17337c478bd9Sstevel@tonic-gate } 17347c478bd9Sstevel@tonic-gate } else { 17357c478bd9Sstevel@tonic-gate if (scan_ifp->hidparser_tok_text[0] != 17367c478bd9Sstevel@tonic-gate 0) { 17377c478bd9Sstevel@tonic-gate hidparser_error_delim(NULL, 17387c478bd9Sstevel@tonic-gate HIDPARSER_DELIM_ERR2); 17397c478bd9Sstevel@tonic-gate } else { 17407c478bd9Sstevel@tonic-gate delim_pre = B_FALSE; 17417c478bd9Sstevel@tonic-gate } 17427c478bd9Sstevel@tonic-gate } 17437c478bd9Sstevel@tonic-gate (void) hidparser_LocalItem(scan_ifp); 17447c478bd9Sstevel@tonic-gate token = scan_ifp->hidparser_tok_token; 17457c478bd9Sstevel@tonic-gate } else if (hidparser_GlobalItem(scan_ifp) == 17467c478bd9Sstevel@tonic-gate HIDPARSER_SUCCESS) { 17477c478bd9Sstevel@tonic-gate token = scan_ifp->hidparser_tok_token; 17487c478bd9Sstevel@tonic-gate } else if (hidparser_LocalItem(scan_ifp) == HIDPARSER_SUCCESS) { 17497c478bd9Sstevel@tonic-gate token = scan_ifp->hidparser_tok_token; 17507c478bd9Sstevel@tonic-gate } 17517c478bd9Sstevel@tonic-gate } 17527c478bd9Sstevel@tonic-gate 17537c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); /* epsilon */ 17547c478bd9Sstevel@tonic-gate } 17557c478bd9Sstevel@tonic-gate 17567c478bd9Sstevel@tonic-gate 17577c478bd9Sstevel@tonic-gate /* 17587c478bd9Sstevel@tonic-gate * hidparser_GlobalItem: 17597c478bd9Sstevel@tonic-gate * Implements the Rule: 17607c478bd9Sstevel@tonic-gate * GlobalItem -> UsagePage 17617c478bd9Sstevel@tonic-gate * | LogicalMinimum 17627c478bd9Sstevel@tonic-gate * | LocgicalMaximum 17637c478bd9Sstevel@tonic-gate * | PhysicalMinimum 17647c478bd9Sstevel@tonic-gate * | PhysicalMaximum 17657c478bd9Sstevel@tonic-gate * | Unit 17667c478bd9Sstevel@tonic-gate * | Exponent 17677c478bd9Sstevel@tonic-gate * | ReportSize 17687c478bd9Sstevel@tonic-gate * | ReportCount 17697c478bd9Sstevel@tonic-gate * | ReportID 17707c478bd9Sstevel@tonic-gate */ 17717c478bd9Sstevel@tonic-gate static int 17727c478bd9Sstevel@tonic-gate hidparser_GlobalItem(hidparser_tok_t *scan_ifp) 17737c478bd9Sstevel@tonic-gate { 17747c478bd9Sstevel@tonic-gate 17757c478bd9Sstevel@tonic-gate int i; 17767c478bd9Sstevel@tonic-gate entity_attribute_stack_t *elem; 17777c478bd9Sstevel@tonic-gate 17787c478bd9Sstevel@tonic-gate switch (scan_ifp->hidparser_tok_token) { 17797c478bd9Sstevel@tonic-gate case R_ITEM_USAGE_PAGE: 17807c478bd9Sstevel@tonic-gate /* Error check */ 17817c478bd9Sstevel@tonic-gate for (i = 0; i < scan_ifp->hidparser_tok_leng; i++) { 17827c478bd9Sstevel@tonic-gate /* Undefined data value: 0 */ 17837c478bd9Sstevel@tonic-gate if (scan_ifp->hidparser_tok_text[i] == 0) { 17847c478bd9Sstevel@tonic-gate hidparser_report_err( 17857c478bd9Sstevel@tonic-gate HIDPARSER_ERR_WARN, 17867c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 17877c478bd9Sstevel@tonic-gate R_ITEM_USAGE_PAGE, 17887c478bd9Sstevel@tonic-gate 0, 17897c478bd9Sstevel@tonic-gate "Data field should be non-Zero"); 17907c478bd9Sstevel@tonic-gate } 17917c478bd9Sstevel@tonic-gate /* Reserved values 0x0A-0xFE */ 17927c478bd9Sstevel@tonic-gate else if ((scan_ifp->hidparser_tok_text[i] >= 17937c478bd9Sstevel@tonic-gate 0x0a) && 17947c478bd9Sstevel@tonic-gate (scan_ifp->hidparser_tok_text[i] <= 17957c478bd9Sstevel@tonic-gate 0xFE)) { 17967c478bd9Sstevel@tonic-gate hidparser_report_err( 17977c478bd9Sstevel@tonic-gate HIDPARSER_ERR_WARN, 17987c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 17997c478bd9Sstevel@tonic-gate R_ITEM_USAGE_PAGE, 18007c478bd9Sstevel@tonic-gate 1, 18017c478bd9Sstevel@tonic-gate "Data field should not use " 18027c478bd9Sstevel@tonic-gate "reserved values"); 18037c478bd9Sstevel@tonic-gate } 18047c478bd9Sstevel@tonic-gate } 18057c478bd9Sstevel@tonic-gate break; 18067c478bd9Sstevel@tonic-gate case R_ITEM_UNIT: 18077c478bd9Sstevel@tonic-gate /* FALLTHRU */ 18087c478bd9Sstevel@tonic-gate case R_ITEM_EXPONENT: 18097c478bd9Sstevel@tonic-gate /* 18107c478bd9Sstevel@tonic-gate * Error check: 18117c478bd9Sstevel@tonic-gate * Nibble 7 should be zero 18127c478bd9Sstevel@tonic-gate */ 18137c478bd9Sstevel@tonic-gate if (scan_ifp->hidparser_tok_leng == 4) { 18147c478bd9Sstevel@tonic-gate if ((scan_ifp->hidparser_tok_text[3] & 18157c478bd9Sstevel@tonic-gate 0xf0) != 0) { 18167c478bd9Sstevel@tonic-gate hidparser_report_err( 18177c478bd9Sstevel@tonic-gate HIDPARSER_ERR_WARN, 18187c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 18197c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_token, 18207c478bd9Sstevel@tonic-gate 0, 18217c478bd9Sstevel@tonic-gate "Data field reserved bits should " 18227c478bd9Sstevel@tonic-gate "be Zero"); 18237c478bd9Sstevel@tonic-gate } 18247c478bd9Sstevel@tonic-gate } 18257c478bd9Sstevel@tonic-gate break; 18267c478bd9Sstevel@tonic-gate case R_ITEM_REPORT_COUNT: 18277c478bd9Sstevel@tonic-gate /* 18287c478bd9Sstevel@tonic-gate * Error Check: 18297c478bd9Sstevel@tonic-gate * Report Count should be nonzero 18307c478bd9Sstevel@tonic-gate */ 18317c478bd9Sstevel@tonic-gate for (i = 0; i < scan_ifp->hidparser_tok_leng; i++) { 18327c478bd9Sstevel@tonic-gate if (scan_ifp->hidparser_tok_text[i]) 18337c478bd9Sstevel@tonic-gate break; 18347c478bd9Sstevel@tonic-gate } 18357c478bd9Sstevel@tonic-gate if (i == scan_ifp->hidparser_tok_leng) { 18367c478bd9Sstevel@tonic-gate hidparser_report_err( 18377c478bd9Sstevel@tonic-gate HIDPARSER_ERR_ERROR, 18387c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 18397c478bd9Sstevel@tonic-gate R_ITEM_REPORT_COUNT, 18407c478bd9Sstevel@tonic-gate 0, 18417c478bd9Sstevel@tonic-gate "Report Count = 0"); 18427c478bd9Sstevel@tonic-gate } 18437c478bd9Sstevel@tonic-gate break; 18447c478bd9Sstevel@tonic-gate case R_ITEM_REPORT_ID: 18457c478bd9Sstevel@tonic-gate /* 18467c478bd9Sstevel@tonic-gate * Error check: 18477c478bd9Sstevel@tonic-gate * Report Id should be nonzero & <= 255 18487c478bd9Sstevel@tonic-gate */ 18497c478bd9Sstevel@tonic-gate if (scan_ifp->hidparser_tok_leng != 1) { 18507c478bd9Sstevel@tonic-gate hidparser_report_err( 18517c478bd9Sstevel@tonic-gate HIDPARSER_ERR_ERROR, 18527c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 18537c478bd9Sstevel@tonic-gate R_ITEM_REPORT_ID, 18547c478bd9Sstevel@tonic-gate 1, 18557c478bd9Sstevel@tonic-gate "Must be contained in a byte"); 18567c478bd9Sstevel@tonic-gate } 18577c478bd9Sstevel@tonic-gate if (!scan_ifp->hidparser_tok_text[0]) { 18587c478bd9Sstevel@tonic-gate hidparser_report_err( 18597c478bd9Sstevel@tonic-gate HIDPARSER_ERR_ERROR, 18607c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 18617c478bd9Sstevel@tonic-gate R_ITEM_REPORT_ID, 18627c478bd9Sstevel@tonic-gate 0, 18637c478bd9Sstevel@tonic-gate "Report Id must be non-zero"); 18647c478bd9Sstevel@tonic-gate } 18657c478bd9Sstevel@tonic-gate break; 18667c478bd9Sstevel@tonic-gate case R_ITEM_LOGICAL_MINIMUM: 18677c478bd9Sstevel@tonic-gate break; 18687c478bd9Sstevel@tonic-gate case R_ITEM_LOGICAL_MAXIMUM: 18697c478bd9Sstevel@tonic-gate break; 18707c478bd9Sstevel@tonic-gate case R_ITEM_PHYSICAL_MINIMUM: 18717c478bd9Sstevel@tonic-gate break; 18727c478bd9Sstevel@tonic-gate case R_ITEM_PHYSICAL_MAXIMUM: 18737c478bd9Sstevel@tonic-gate break; 18747c478bd9Sstevel@tonic-gate case R_ITEM_REPORT_SIZE: 18757c478bd9Sstevel@tonic-gate break; 18767c478bd9Sstevel@tonic-gate case R_ITEM_PUSH: 18777c478bd9Sstevel@tonic-gate if (scan_ifp->hidparser_tok_leng != 0) { 18787c478bd9Sstevel@tonic-gate hidparser_report_err( 18797c478bd9Sstevel@tonic-gate HIDPARSER_ERR_ERROR, 18807c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 18817c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_token, 18827c478bd9Sstevel@tonic-gate 0, 18837c478bd9Sstevel@tonic-gate "Data Field size should be zero"); 18847c478bd9Sstevel@tonic-gate } else { 18857c478bd9Sstevel@tonic-gate elem = (entity_attribute_stack_t *)kmem_zalloc( 18867c478bd9Sstevel@tonic-gate sizeof (entity_attribute_stack_t), 18877c478bd9Sstevel@tonic-gate KM_SLEEP); 18887c478bd9Sstevel@tonic-gate 18897c478bd9Sstevel@tonic-gate elem->list = hidparser_cp_attribute_list( 18907c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_gitem_head); 18917c478bd9Sstevel@tonic-gate if (scan_ifp->hidparser_head) { 18927c478bd9Sstevel@tonic-gate elem->next = scan_ifp->hidparser_head; 18937c478bd9Sstevel@tonic-gate } 18947c478bd9Sstevel@tonic-gate scan_ifp->hidparser_head = elem; 18957c478bd9Sstevel@tonic-gate } 18967c478bd9Sstevel@tonic-gate 18977c478bd9Sstevel@tonic-gate break; 18987c478bd9Sstevel@tonic-gate case R_ITEM_POP: 18997c478bd9Sstevel@tonic-gate if (scan_ifp->hidparser_tok_leng != 0) { 19007c478bd9Sstevel@tonic-gate hidparser_report_err( 19017c478bd9Sstevel@tonic-gate HIDPARSER_ERR_ERROR, 19027c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 19037c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_token, 19047c478bd9Sstevel@tonic-gate 0, 19057c478bd9Sstevel@tonic-gate "Data Field size should be zero"); 19067c478bd9Sstevel@tonic-gate } else { 19077c478bd9Sstevel@tonic-gate /* Free the current global list */ 19087c478bd9Sstevel@tonic-gate hidparser_free_attribute_list(scan_ifp-> 19097c478bd9Sstevel@tonic-gate hidparser_tok_gitem_head); 19107c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_gitem_head = 19117c478bd9Sstevel@tonic-gate scan_ifp->hidparser_head->list; 19127c478bd9Sstevel@tonic-gate scan_ifp->hidparser_head->list = NULL; 19137c478bd9Sstevel@tonic-gate elem = scan_ifp->hidparser_head; 19147c478bd9Sstevel@tonic-gate scan_ifp->hidparser_head = elem->next; 19157c478bd9Sstevel@tonic-gate kmem_free(elem, 19167c478bd9Sstevel@tonic-gate sizeof (entity_attribute_stack_t)); 19177c478bd9Sstevel@tonic-gate } 19187c478bd9Sstevel@tonic-gate 19197c478bd9Sstevel@tonic-gate break; 19207c478bd9Sstevel@tonic-gate default: 19217c478bd9Sstevel@tonic-gate 19227c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 19237c478bd9Sstevel@tonic-gate 19247c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 19257c478bd9Sstevel@tonic-gate } 19267c478bd9Sstevel@tonic-gate 19277c478bd9Sstevel@tonic-gate hidparser_add_attribute(scan_ifp); 19287c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, hparser_log_handle, 1929112116d8Sfb209375 "hidparser_GlobalItem:index = 0x%lx token = 0x%x", 19307c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_index - 19317c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_leng - 1, 19327c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_token); 19337c478bd9Sstevel@tonic-gate hidparser_scan(scan_ifp); 19347c478bd9Sstevel@tonic-gate 19357c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 19367c478bd9Sstevel@tonic-gate } 19377c478bd9Sstevel@tonic-gate 19387c478bd9Sstevel@tonic-gate 19397c478bd9Sstevel@tonic-gate /* 19407c478bd9Sstevel@tonic-gate * hidparser_LocalItem: 19417c478bd9Sstevel@tonic-gate * Implements the Rule: 19427c478bd9Sstevel@tonic-gate * LocalItem -> Usage 19437c478bd9Sstevel@tonic-gate * | UsageMinimum 19447c478bd9Sstevel@tonic-gate * | UsageMaximum 19457c478bd9Sstevel@tonic-gate * | DesignatorIndex 19467c478bd9Sstevel@tonic-gate * | DesignatorMinimum 19477c478bd9Sstevel@tonic-gate * | StringIndex 19487c478bd9Sstevel@tonic-gate * | StringMinimum 19497c478bd9Sstevel@tonic-gate * | StringMaximum 19507c478bd9Sstevel@tonic-gate */ 19517c478bd9Sstevel@tonic-gate static int 19527c478bd9Sstevel@tonic-gate hidparser_LocalItem(hidparser_tok_t *scan_ifp) 19537c478bd9Sstevel@tonic-gate { 19547c478bd9Sstevel@tonic-gate int i; 19557c478bd9Sstevel@tonic-gate 19567c478bd9Sstevel@tonic-gate switch (scan_ifp->hidparser_tok_token) { 19577c478bd9Sstevel@tonic-gate case R_ITEM_USAGE: 19587c478bd9Sstevel@tonic-gate /* 19597c478bd9Sstevel@tonic-gate * Error Check: 19607c478bd9Sstevel@tonic-gate * Data Field should be nonzero 19617c478bd9Sstevel@tonic-gate */ 19627c478bd9Sstevel@tonic-gate for (i = 0; i < scan_ifp->hidparser_tok_leng; i++) { 19637c478bd9Sstevel@tonic-gate if (scan_ifp->hidparser_tok_text[i]) 19647c478bd9Sstevel@tonic-gate break; 19657c478bd9Sstevel@tonic-gate } 19667c478bd9Sstevel@tonic-gate if (i == scan_ifp->hidparser_tok_leng) { 19677c478bd9Sstevel@tonic-gate hidparser_report_err( 19687c478bd9Sstevel@tonic-gate HIDPARSER_ERR_WARN, 19697c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 19707c478bd9Sstevel@tonic-gate R_ITEM_USAGE, 19717c478bd9Sstevel@tonic-gate 0, 19727c478bd9Sstevel@tonic-gate "Data Field should be non-zero"); 19737c478bd9Sstevel@tonic-gate } 19747c478bd9Sstevel@tonic-gate /* FALLTHRU */ 19757c478bd9Sstevel@tonic-gate case R_ITEM_USAGE_MIN: 19767c478bd9Sstevel@tonic-gate /* FALLTHRU */ 19777c478bd9Sstevel@tonic-gate case R_ITEM_USAGE_MAX: 19787c478bd9Sstevel@tonic-gate /* FALLTHRU */ 19797c478bd9Sstevel@tonic-gate case R_ITEM_DESIGNATOR_INDEX: 19807c478bd9Sstevel@tonic-gate /* FALLTHRU */ 19817c478bd9Sstevel@tonic-gate case R_ITEM_DESIGNATOR_MIN: 19827c478bd9Sstevel@tonic-gate /* FALLTHRU */ 19837c478bd9Sstevel@tonic-gate case R_ITEM_STRING_INDEX: 19847c478bd9Sstevel@tonic-gate /* FALLTHRU */ 19857c478bd9Sstevel@tonic-gate case R_ITEM_STRING_MIN: 19867c478bd9Sstevel@tonic-gate /* FALLTHRU */ 19877c478bd9Sstevel@tonic-gate case R_ITEM_STRING_MAX: 19887c478bd9Sstevel@tonic-gate /* FALLTHRU */ 19897c478bd9Sstevel@tonic-gate case R_ITEM_SET_DELIMITER: 19907c478bd9Sstevel@tonic-gate hidparser_add_attribute(scan_ifp); 19917c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, hparser_log_handle, 1992112116d8Sfb209375 "hidparser_LocalItem:index = 0x%lx token = 0x%x", 19937c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_index - 19947c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_leng - 1, 19957c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_token); 19967c478bd9Sstevel@tonic-gate hidparser_scan(scan_ifp); 19977c478bd9Sstevel@tonic-gate 19987c478bd9Sstevel@tonic-gate return (HIDPARSER_SUCCESS); 19997c478bd9Sstevel@tonic-gate 20007c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 20017c478bd9Sstevel@tonic-gate default: 20027c478bd9Sstevel@tonic-gate break; 20037c478bd9Sstevel@tonic-gate } 20047c478bd9Sstevel@tonic-gate 20057c478bd9Sstevel@tonic-gate return (HIDPARSER_FAILURE); 20067c478bd9Sstevel@tonic-gate } 20077c478bd9Sstevel@tonic-gate 20087c478bd9Sstevel@tonic-gate 20097c478bd9Sstevel@tonic-gate /* 20107c478bd9Sstevel@tonic-gate * hidparser_allocate_entity: 20117c478bd9Sstevel@tonic-gate * Allocate Item of type 'type', length 'leng' and 20127c478bd9Sstevel@tonic-gate * params 'text'. Fill in the attributes allocated 20137c478bd9Sstevel@tonic-gate * so far from both the local and global item lists. 20147c478bd9Sstevel@tonic-gate * Make the child and sibling of the item NULL. 20157c478bd9Sstevel@tonic-gate */ 20167c478bd9Sstevel@tonic-gate static entity_item_t * 20177c478bd9Sstevel@tonic-gate hidparser_allocate_entity(hidparser_tok_t *scan_ifp) 20187c478bd9Sstevel@tonic-gate { 20197c478bd9Sstevel@tonic-gate entity_item_t *entity; 20207c478bd9Sstevel@tonic-gate entity_attribute_t *aend; 20217c478bd9Sstevel@tonic-gate 20227c478bd9Sstevel@tonic-gate int entity_type = scan_ifp->hidparser_tok_token; 20237c478bd9Sstevel@tonic-gate unsigned char *text = scan_ifp->hidparser_tok_text; 20247c478bd9Sstevel@tonic-gate int len = scan_ifp->hidparser_tok_leng; 20257c478bd9Sstevel@tonic-gate 20267c478bd9Sstevel@tonic-gate entity = kmem_zalloc(sizeof (entity_item_t), KM_SLEEP); 20277c478bd9Sstevel@tonic-gate entity->entity_item_type = entity_type; 20287c478bd9Sstevel@tonic-gate entity->entity_item_params_leng = len; 20297c478bd9Sstevel@tonic-gate 20307c478bd9Sstevel@tonic-gate if (len != 0) { 20317c478bd9Sstevel@tonic-gate entity->entity_item_params = kmem_zalloc(len, KM_SLEEP); 20327c478bd9Sstevel@tonic-gate (void) bcopy(text, entity->entity_item_params, len); 20337c478bd9Sstevel@tonic-gate } 20347c478bd9Sstevel@tonic-gate 20357c478bd9Sstevel@tonic-gate /* 20367c478bd9Sstevel@tonic-gate * Copy attributes from entity attribute state table if not 20377c478bd9Sstevel@tonic-gate * end collection. 20387c478bd9Sstevel@tonic-gate */ 20397c478bd9Sstevel@tonic-gate if (entity_type != R_ITEM_END_COLLECTION) { 20407c478bd9Sstevel@tonic-gate entity->entity_item_attributes = hidparser_cp_attribute_list( 20417c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_gitem_head); 20427c478bd9Sstevel@tonic-gate 20437c478bd9Sstevel@tonic-gate /* 20447c478bd9Sstevel@tonic-gate * append the control attributes, then clear out the control 20457c478bd9Sstevel@tonic-gate * attribute state table list 20467c478bd9Sstevel@tonic-gate */ 20477c478bd9Sstevel@tonic-gate if (entity->entity_item_attributes) { 20487c478bd9Sstevel@tonic-gate aend = hidparser_find_attribute_end( 20497c478bd9Sstevel@tonic-gate entity->entity_item_attributes); 20507c478bd9Sstevel@tonic-gate aend->entity_attribute_next = 20517c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_litem_head; 20527c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_litem_head = NULL; 20537c478bd9Sstevel@tonic-gate } else { 20547c478bd9Sstevel@tonic-gate entity->entity_item_attributes = 20557c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_litem_head; 20567c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_litem_head = NULL; 20577c478bd9Sstevel@tonic-gate } 20587c478bd9Sstevel@tonic-gate } 20597c478bd9Sstevel@tonic-gate 20607c478bd9Sstevel@tonic-gate entity->info.child = entity->entity_item_right_sibling = 0; 20617c478bd9Sstevel@tonic-gate 20627c478bd9Sstevel@tonic-gate return (entity); 20637c478bd9Sstevel@tonic-gate } 20647c478bd9Sstevel@tonic-gate 20657c478bd9Sstevel@tonic-gate 20667c478bd9Sstevel@tonic-gate /* 20677c478bd9Sstevel@tonic-gate * hidparser_add_attribute: 20687c478bd9Sstevel@tonic-gate * Add an attribute to the global or local item list 20697c478bd9Sstevel@tonic-gate * If the last 4th bit from right is 1, add to the local item list 20707c478bd9Sstevel@tonic-gate * Else add to the global item list 20717c478bd9Sstevel@tonic-gate */ 20727c478bd9Sstevel@tonic-gate static void 20737c478bd9Sstevel@tonic-gate hidparser_add_attribute(hidparser_tok_t *scan_ifp) 20747c478bd9Sstevel@tonic-gate { 20757c478bd9Sstevel@tonic-gate entity_attribute_t *newattrib, **previous, *elem; 20767c478bd9Sstevel@tonic-gate int entity = scan_ifp->hidparser_tok_token; 20777c478bd9Sstevel@tonic-gate unsigned char *text = scan_ifp->hidparser_tok_text; 20787c478bd9Sstevel@tonic-gate int len = scan_ifp->hidparser_tok_leng; 20797c478bd9Sstevel@tonic-gate 20807c478bd9Sstevel@tonic-gate if (len == 0) { 20817c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, hparser_log_handle, 20827c478bd9Sstevel@tonic-gate "hidparser_add_attribute: len = 0 for item = 0x%x", 20837c478bd9Sstevel@tonic-gate entity); 20847c478bd9Sstevel@tonic-gate 20857c478bd9Sstevel@tonic-gate return; 20867c478bd9Sstevel@tonic-gate } 20877c478bd9Sstevel@tonic-gate 20887c478bd9Sstevel@tonic-gate if (entity & HIDPARSER_ISLOCAL_MASK) { 20897c478bd9Sstevel@tonic-gate previous = &scan_ifp->hidparser_tok_litem_head; 20907c478bd9Sstevel@tonic-gate } else { 20917c478bd9Sstevel@tonic-gate previous = &scan_ifp->hidparser_tok_gitem_head; 20927c478bd9Sstevel@tonic-gate } 20937c478bd9Sstevel@tonic-gate 20947c478bd9Sstevel@tonic-gate elem = *previous; 20957c478bd9Sstevel@tonic-gate 20967c478bd9Sstevel@tonic-gate /* 20977c478bd9Sstevel@tonic-gate * remove attribute if it is already on list, except 20987c478bd9Sstevel@tonic-gate * for control attributes(local items), as we could have 20997c478bd9Sstevel@tonic-gate * multiple usages... 21007c478bd9Sstevel@tonic-gate * unless we want to hassle with checking for unique parameters. 21017c478bd9Sstevel@tonic-gate */ 21027c478bd9Sstevel@tonic-gate while (elem) { 21037c478bd9Sstevel@tonic-gate if (elem->entity_attribute_tag == entity && 21047c478bd9Sstevel@tonic-gate !(entity & HIDPARSER_ISLOCAL_MASK)) { 21057c478bd9Sstevel@tonic-gate *previous = elem->entity_attribute_next; 21067c478bd9Sstevel@tonic-gate kmem_free(elem->entity_attribute_value, 21077c478bd9Sstevel@tonic-gate elem->entity_attribute_length); 21087c478bd9Sstevel@tonic-gate kmem_free(elem, sizeof (entity_attribute_t)); 21097c478bd9Sstevel@tonic-gate elem = *previous; 21107c478bd9Sstevel@tonic-gate } else { 21117c478bd9Sstevel@tonic-gate previous = &elem->entity_attribute_next; 21127c478bd9Sstevel@tonic-gate elem = elem->entity_attribute_next; 21137c478bd9Sstevel@tonic-gate } 21147c478bd9Sstevel@tonic-gate } 21157c478bd9Sstevel@tonic-gate 21167c478bd9Sstevel@tonic-gate /* create new attribute for this entry */ 21177c478bd9Sstevel@tonic-gate newattrib = hidparser_alloc_attrib_list(1); 21187c478bd9Sstevel@tonic-gate newattrib->entity_attribute_tag = entity; 21197c478bd9Sstevel@tonic-gate newattrib->entity_attribute_value = kmem_zalloc(len, KM_SLEEP); 21207c478bd9Sstevel@tonic-gate (void) bcopy(text, newattrib->entity_attribute_value, len); 21217c478bd9Sstevel@tonic-gate newattrib->entity_attribute_length = len; 21227c478bd9Sstevel@tonic-gate 21237c478bd9Sstevel@tonic-gate /* attach to end of list */ 21247c478bd9Sstevel@tonic-gate *previous = newattrib; 21257c478bd9Sstevel@tonic-gate } 21267c478bd9Sstevel@tonic-gate 21277c478bd9Sstevel@tonic-gate 21287c478bd9Sstevel@tonic-gate /* 21297c478bd9Sstevel@tonic-gate * hidparser_alloc_attrib_list: 21307c478bd9Sstevel@tonic-gate * Allocate space for n attributes , create a linked list and 21317c478bd9Sstevel@tonic-gate * return the head 21327c478bd9Sstevel@tonic-gate */ 21337c478bd9Sstevel@tonic-gate static entity_attribute_t * 21347c478bd9Sstevel@tonic-gate hidparser_alloc_attrib_list(int count) 21357c478bd9Sstevel@tonic-gate { 21367c478bd9Sstevel@tonic-gate entity_attribute_t *head, *current; 21377c478bd9Sstevel@tonic-gate 21387c478bd9Sstevel@tonic-gate if (count <= 0) { 21397c478bd9Sstevel@tonic-gate 21407c478bd9Sstevel@tonic-gate return (NULL); 21417c478bd9Sstevel@tonic-gate } 21427c478bd9Sstevel@tonic-gate 21437c478bd9Sstevel@tonic-gate head = kmem_zalloc(sizeof (entity_attribute_t), KM_SLEEP); 21447c478bd9Sstevel@tonic-gate count--; 21457c478bd9Sstevel@tonic-gate current = head; 21467c478bd9Sstevel@tonic-gate while (count--) { 21477c478bd9Sstevel@tonic-gate current->entity_attribute_next = kmem_zalloc( 21487c478bd9Sstevel@tonic-gate sizeof (entity_attribute_t), KM_SLEEP); 21497c478bd9Sstevel@tonic-gate current = current->entity_attribute_next; 21507c478bd9Sstevel@tonic-gate } 21517c478bd9Sstevel@tonic-gate current->entity_attribute_next = NULL; 21527c478bd9Sstevel@tonic-gate 21537c478bd9Sstevel@tonic-gate return (head); 21547c478bd9Sstevel@tonic-gate } 21557c478bd9Sstevel@tonic-gate 21567c478bd9Sstevel@tonic-gate 21577c478bd9Sstevel@tonic-gate /* 21587c478bd9Sstevel@tonic-gate * hidparser_cp_attribute_list: 21597c478bd9Sstevel@tonic-gate * Copies the Global item list pointed to by head 21607c478bd9Sstevel@tonic-gate * We create a clone of the global item list here 21617c478bd9Sstevel@tonic-gate * because we want to retain the Global items to 21627c478bd9Sstevel@tonic-gate * the next Main Item. 21637c478bd9Sstevel@tonic-gate */ 21647c478bd9Sstevel@tonic-gate static entity_attribute_t * 21657c478bd9Sstevel@tonic-gate hidparser_cp_attribute_list(entity_attribute_t *head) 21667c478bd9Sstevel@tonic-gate { 21677c478bd9Sstevel@tonic-gate entity_attribute_t *return_value, *current_src, *current_dst; 21687c478bd9Sstevel@tonic-gate 21697c478bd9Sstevel@tonic-gate if (!head) { 21707c478bd9Sstevel@tonic-gate 21717c478bd9Sstevel@tonic-gate return (NULL); 21727c478bd9Sstevel@tonic-gate } 21737c478bd9Sstevel@tonic-gate 21747c478bd9Sstevel@tonic-gate current_src = head; 21757c478bd9Sstevel@tonic-gate current_dst = return_value = hidparser_alloc_attrib_list(1); 21767c478bd9Sstevel@tonic-gate 21777c478bd9Sstevel@tonic-gate while (current_src) { 21787c478bd9Sstevel@tonic-gate current_dst->entity_attribute_tag = 21797c478bd9Sstevel@tonic-gate current_src->entity_attribute_tag; 21807c478bd9Sstevel@tonic-gate current_dst->entity_attribute_length = 21817c478bd9Sstevel@tonic-gate current_src->entity_attribute_length; 21827c478bd9Sstevel@tonic-gate current_dst->entity_attribute_value = kmem_zalloc( 21837c478bd9Sstevel@tonic-gate current_dst->entity_attribute_length, KM_SLEEP); 21847c478bd9Sstevel@tonic-gate (void) bcopy(current_src->entity_attribute_value, 21857c478bd9Sstevel@tonic-gate current_dst->entity_attribute_value, 21867c478bd9Sstevel@tonic-gate current_src->entity_attribute_length); 21877c478bd9Sstevel@tonic-gate if (current_src->entity_attribute_next) { 21887c478bd9Sstevel@tonic-gate current_dst->entity_attribute_next = 21897c478bd9Sstevel@tonic-gate hidparser_alloc_attrib_list(1); 21907c478bd9Sstevel@tonic-gate } else { 21917c478bd9Sstevel@tonic-gate current_dst->entity_attribute_next = NULL; 21927c478bd9Sstevel@tonic-gate } 21937c478bd9Sstevel@tonic-gate current_src = current_src->entity_attribute_next; 21947c478bd9Sstevel@tonic-gate current_dst = current_dst->entity_attribute_next; 21957c478bd9Sstevel@tonic-gate } 21967c478bd9Sstevel@tonic-gate 21977c478bd9Sstevel@tonic-gate return (return_value); 21987c478bd9Sstevel@tonic-gate } 21997c478bd9Sstevel@tonic-gate 22007c478bd9Sstevel@tonic-gate 22017c478bd9Sstevel@tonic-gate /* 22027c478bd9Sstevel@tonic-gate * hidparser_find_attribute_end: 22037c478bd9Sstevel@tonic-gate * Find the last item in the attribute list pointed to by head 22047c478bd9Sstevel@tonic-gate */ 22057c478bd9Sstevel@tonic-gate static entity_attribute_t * 22067c478bd9Sstevel@tonic-gate hidparser_find_attribute_end(entity_attribute_t *head) 22077c478bd9Sstevel@tonic-gate { 22087c478bd9Sstevel@tonic-gate if (head == NULL) { 22097c478bd9Sstevel@tonic-gate 22107c478bd9Sstevel@tonic-gate return (NULL); 22117c478bd9Sstevel@tonic-gate } 22127c478bd9Sstevel@tonic-gate while (head->entity_attribute_next != NULL) { 22137c478bd9Sstevel@tonic-gate head = head->entity_attribute_next; 22147c478bd9Sstevel@tonic-gate } 22157c478bd9Sstevel@tonic-gate 22167c478bd9Sstevel@tonic-gate return (head); 22177c478bd9Sstevel@tonic-gate } 22187c478bd9Sstevel@tonic-gate 22197c478bd9Sstevel@tonic-gate 22207c478bd9Sstevel@tonic-gate /* 22217c478bd9Sstevel@tonic-gate * hidparser_find_item_end: 22227c478bd9Sstevel@tonic-gate * Search the siblings of items and find the last item in the list 22237c478bd9Sstevel@tonic-gate */ 22247c478bd9Sstevel@tonic-gate static entity_item_t * 22257c478bd9Sstevel@tonic-gate hidparser_find_item_end(entity_item_t *head) 22267c478bd9Sstevel@tonic-gate { 22277c478bd9Sstevel@tonic-gate if (!head) { 22287c478bd9Sstevel@tonic-gate 22297c478bd9Sstevel@tonic-gate return (NULL); 22307c478bd9Sstevel@tonic-gate } 22317c478bd9Sstevel@tonic-gate 22327c478bd9Sstevel@tonic-gate while (head->entity_item_right_sibling) { 22337c478bd9Sstevel@tonic-gate head = head->entity_item_right_sibling; 22347c478bd9Sstevel@tonic-gate } 22357c478bd9Sstevel@tonic-gate 22367c478bd9Sstevel@tonic-gate return (head); 22377c478bd9Sstevel@tonic-gate } 22387c478bd9Sstevel@tonic-gate 22397c478bd9Sstevel@tonic-gate 22407c478bd9Sstevel@tonic-gate /* 22417c478bd9Sstevel@tonic-gate * hidparser_free_report_descr_handle: 22427c478bd9Sstevel@tonic-gate * Free the parse tree pointed to by handle 22437c478bd9Sstevel@tonic-gate */ 22447c478bd9Sstevel@tonic-gate static void 22457c478bd9Sstevel@tonic-gate hidparser_free_report_descr_handle(entity_item_t *handle) 22467c478bd9Sstevel@tonic-gate { 22477c478bd9Sstevel@tonic-gate entity_item_t *next, *current, *child; 22487c478bd9Sstevel@tonic-gate 22497c478bd9Sstevel@tonic-gate current = handle; 22507c478bd9Sstevel@tonic-gate 22517c478bd9Sstevel@tonic-gate while (current) { 22527c478bd9Sstevel@tonic-gate child = current->info.child; 22537c478bd9Sstevel@tonic-gate next = current->entity_item_right_sibling; 22547c478bd9Sstevel@tonic-gate if (current->entity_item_type == R_ITEM_COLLECTION) { 22557c478bd9Sstevel@tonic-gate if (current->entity_item_params != NULL) 22567c478bd9Sstevel@tonic-gate kmem_free(current->entity_item_params, 22577c478bd9Sstevel@tonic-gate current->entity_item_params_leng); 22587c478bd9Sstevel@tonic-gate if (current->entity_item_attributes != NULL) 22597c478bd9Sstevel@tonic-gate hidparser_free_attribute_list( 22607c478bd9Sstevel@tonic-gate current->entity_item_attributes); 22617c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, hparser_log_handle, 22627c478bd9Sstevel@tonic-gate "FREE 1: %s", 22637c478bd9Sstevel@tonic-gate items[current->entity_item_type]); 22647c478bd9Sstevel@tonic-gate kmem_free(current, sizeof (entity_item_t)); 22657c478bd9Sstevel@tonic-gate (void) hidparser_free_report_descr_handle(child); 22667c478bd9Sstevel@tonic-gate } else { 22677c478bd9Sstevel@tonic-gate if (current->entity_item_params != NULL) { 22687c478bd9Sstevel@tonic-gate kmem_free(current->entity_item_params, 22697c478bd9Sstevel@tonic-gate current->entity_item_params_leng); 22707c478bd9Sstevel@tonic-gate } 22717c478bd9Sstevel@tonic-gate if (current->entity_item_attributes != NULL) { 22727c478bd9Sstevel@tonic-gate hidparser_free_attribute_list( 22737c478bd9Sstevel@tonic-gate current->entity_item_attributes); 22747c478bd9Sstevel@tonic-gate } 22757c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, 22767c478bd9Sstevel@tonic-gate hparser_log_handle, "FREE 2: %s", 22777c478bd9Sstevel@tonic-gate items[current->entity_item_type]); 22787c478bd9Sstevel@tonic-gate kmem_free(current, sizeof (entity_item_t)); 22797c478bd9Sstevel@tonic-gate } 22807c478bd9Sstevel@tonic-gate current = next; 22817c478bd9Sstevel@tonic-gate } 22827c478bd9Sstevel@tonic-gate 22837c478bd9Sstevel@tonic-gate } 22847c478bd9Sstevel@tonic-gate 22857c478bd9Sstevel@tonic-gate 22867c478bd9Sstevel@tonic-gate /* 22877c478bd9Sstevel@tonic-gate * hidparser_free_attribute_list: 22887c478bd9Sstevel@tonic-gate * Free the attribute list pointed to by head 22897c478bd9Sstevel@tonic-gate */ 22907c478bd9Sstevel@tonic-gate static void 22917c478bd9Sstevel@tonic-gate hidparser_free_attribute_list(entity_attribute_t *head) 22927c478bd9Sstevel@tonic-gate { 22937c478bd9Sstevel@tonic-gate entity_attribute_t *next, *current; 22947c478bd9Sstevel@tonic-gate 22957c478bd9Sstevel@tonic-gate current = head; 22967c478bd9Sstevel@tonic-gate 22977c478bd9Sstevel@tonic-gate while (current) { 22987c478bd9Sstevel@tonic-gate next = current->entity_attribute_next; 22997c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, 23007c478bd9Sstevel@tonic-gate hparser_log_handle, "FREE: %s value_length = %d", 23017c478bd9Sstevel@tonic-gate items[current->entity_attribute_tag], 23027c478bd9Sstevel@tonic-gate current->entity_attribute_length); 23037c478bd9Sstevel@tonic-gate 23047c478bd9Sstevel@tonic-gate if (current->entity_attribute_value != NULL) { 23057c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, 23067c478bd9Sstevel@tonic-gate hparser_log_handle, 23077c478bd9Sstevel@tonic-gate "\tvalue = 0x%x", 23087c478bd9Sstevel@tonic-gate current->entity_attribute_value[0]); 23097c478bd9Sstevel@tonic-gate kmem_free(current->entity_attribute_value, 23107c478bd9Sstevel@tonic-gate current->entity_attribute_length); 23117c478bd9Sstevel@tonic-gate } 23127c478bd9Sstevel@tonic-gate 23137c478bd9Sstevel@tonic-gate kmem_free(current, sizeof (entity_attribute_t)); 23147c478bd9Sstevel@tonic-gate current = next; 23157c478bd9Sstevel@tonic-gate } 23167c478bd9Sstevel@tonic-gate } 23177c478bd9Sstevel@tonic-gate 23187c478bd9Sstevel@tonic-gate 23197c478bd9Sstevel@tonic-gate /* 23207c478bd9Sstevel@tonic-gate * hidparser_initialize_items: 23217c478bd9Sstevel@tonic-gate * Initialize items array before start scanning and parsing. 23227c478bd9Sstevel@tonic-gate * This array of strings are used for printing purpose. 23237c478bd9Sstevel@tonic-gate */ 23247c478bd9Sstevel@tonic-gate static void 23257c478bd9Sstevel@tonic-gate hidparser_initialize_items(void) 23267c478bd9Sstevel@tonic-gate { 23277c478bd9Sstevel@tonic-gate items[R_ITEM_USAGE] = "Usage"; 23287c478bd9Sstevel@tonic-gate items[R_ITEM_USAGE_MIN] = "Usage Minimum"; 23297c478bd9Sstevel@tonic-gate items[R_ITEM_USAGE_MAX] = "Usage Maximum"; 23307c478bd9Sstevel@tonic-gate items[R_ITEM_DESIGNATOR_INDEX] = "Designator Index"; 23317c478bd9Sstevel@tonic-gate items[R_ITEM_DESIGNATOR_MIN] = "Designator Minimum"; 23327c478bd9Sstevel@tonic-gate items[R_ITEM_DESIGNATOR_MAX] = "Designator Maximum"; 23337c478bd9Sstevel@tonic-gate items[R_ITEM_STRING_INDEX] = "String Index"; 23347c478bd9Sstevel@tonic-gate items[R_ITEM_STRING_MIN] = "String Minimum"; 23357c478bd9Sstevel@tonic-gate items[R_ITEM_STRING_MAX] = "String Maximum"; 23367c478bd9Sstevel@tonic-gate 23377c478bd9Sstevel@tonic-gate 23387c478bd9Sstevel@tonic-gate items[R_ITEM_USAGE_PAGE] = "Usage Page"; 23397c478bd9Sstevel@tonic-gate items[R_ITEM_LOGICAL_MINIMUM] = "Logical Minimum"; 23407c478bd9Sstevel@tonic-gate items[R_ITEM_LOGICAL_MAXIMUM] = "Logical Maximum"; 23417c478bd9Sstevel@tonic-gate items[R_ITEM_PHYSICAL_MINIMUM] = "Physical Minimum"; 23427c478bd9Sstevel@tonic-gate items[R_ITEM_PHYSICAL_MAXIMUM] = "Physical Maximum"; 23437c478bd9Sstevel@tonic-gate items[R_ITEM_EXPONENT] = "Exponent"; 23447c478bd9Sstevel@tonic-gate items[R_ITEM_UNIT] = "Unit"; 23457c478bd9Sstevel@tonic-gate items[R_ITEM_REPORT_SIZE] = "Report Size"; 23467c478bd9Sstevel@tonic-gate items[R_ITEM_REPORT_ID] = "Report Id"; 23477c478bd9Sstevel@tonic-gate items[R_ITEM_REPORT_COUNT] = "Report Count"; 23487c478bd9Sstevel@tonic-gate items[R_ITEM_PUSH] = "Push"; 23497c478bd9Sstevel@tonic-gate items[R_ITEM_POP] = "Pop"; 23507c478bd9Sstevel@tonic-gate 23517c478bd9Sstevel@tonic-gate 23527c478bd9Sstevel@tonic-gate items[R_ITEM_INPUT] = "Input"; 23537c478bd9Sstevel@tonic-gate items[R_ITEM_OUTPUT] = "Output"; 23547c478bd9Sstevel@tonic-gate items[R_ITEM_COLLECTION] = "Collection"; 23557c478bd9Sstevel@tonic-gate items[R_ITEM_FEATURE] = "Feature"; 23567c478bd9Sstevel@tonic-gate items[R_ITEM_END_COLLECTION] = "End Collection"; 23577c478bd9Sstevel@tonic-gate 23587c478bd9Sstevel@tonic-gate items[R_ITEM_SET_DELIMITER] = "Delimiter"; 23597c478bd9Sstevel@tonic-gate } 23607c478bd9Sstevel@tonic-gate 23617c478bd9Sstevel@tonic-gate 23627c478bd9Sstevel@tonic-gate /* 23637c478bd9Sstevel@tonic-gate * hidparser_scan: 23647c478bd9Sstevel@tonic-gate * This function scans the input entity descriptor, sees the data 23657c478bd9Sstevel@tonic-gate * length, returns the next token, data bytes and length in the 23667c478bd9Sstevel@tonic-gate * scan_ifp structure. 23677c478bd9Sstevel@tonic-gate */ 23687c478bd9Sstevel@tonic-gate static void 23697c478bd9Sstevel@tonic-gate hidparser_scan(hidparser_tok_t *scan_ifp) 23707c478bd9Sstevel@tonic-gate { 23717c478bd9Sstevel@tonic-gate int count; 23727c478bd9Sstevel@tonic-gate int ch; 23737c478bd9Sstevel@tonic-gate int parsed_length; 23747c478bd9Sstevel@tonic-gate unsigned char *parsed_text; 23757c478bd9Sstevel@tonic-gate unsigned char *entity_descriptor; 23767c478bd9Sstevel@tonic-gate char err_str[32]; 23777c478bd9Sstevel@tonic-gate size_t entity_buffer_size, index; 23787c478bd9Sstevel@tonic-gate 23797c478bd9Sstevel@tonic-gate index = scan_ifp->hidparser_tok_index; 23807c478bd9Sstevel@tonic-gate entity_buffer_size = scan_ifp->hidparser_tok_max_bsize; 23817c478bd9Sstevel@tonic-gate parsed_length = 0; 23827c478bd9Sstevel@tonic-gate parsed_text = scan_ifp->hidparser_tok_text; 23837c478bd9Sstevel@tonic-gate entity_descriptor = scan_ifp->hidparser_tok_entity_descriptor; 23847c478bd9Sstevel@tonic-gate 23857c478bd9Sstevel@tonic-gate next_item: 23867c478bd9Sstevel@tonic-gate if (index <= entity_buffer_size -1) { 23877c478bd9Sstevel@tonic-gate 23887c478bd9Sstevel@tonic-gate ch = 0xFF & entity_descriptor[index]; 23897c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, 23907c478bd9Sstevel@tonic-gate hparser_log_handle, "scanner: index = 0x%lx ch = 0x%x", 23917c478bd9Sstevel@tonic-gate index, ch); 23927c478bd9Sstevel@tonic-gate 23937c478bd9Sstevel@tonic-gate index++; 23947c478bd9Sstevel@tonic-gate 23957c478bd9Sstevel@tonic-gate /* 23967c478bd9Sstevel@tonic-gate * Error checking: 23977c478bd9Sstevel@tonic-gate * Unrecognized items should be passed over 23987c478bd9Sstevel@tonic-gate * by the parser. 23997c478bd9Sstevel@tonic-gate * Section 5.4 24007c478bd9Sstevel@tonic-gate */ 24017c478bd9Sstevel@tonic-gate if (!(hidparser_isvalid_item(ch))) { 24027c478bd9Sstevel@tonic-gate (void) sprintf(err_str, "%s: 0x%2x", 24037c478bd9Sstevel@tonic-gate "Unknown or reserved item", ch); 24047c478bd9Sstevel@tonic-gate hidparser_report_err(HIDPARSER_ERR_ERROR, 24057c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 0, 0x3F, err_str); 24067c478bd9Sstevel@tonic-gate goto next_item; 24077c478bd9Sstevel@tonic-gate } 24087c478bd9Sstevel@tonic-gate 24097c478bd9Sstevel@tonic-gate if (ch == EXTENDED_ITEM) { 24107c478bd9Sstevel@tonic-gate parsed_length = entity_descriptor[index++]; 24117c478bd9Sstevel@tonic-gate ch = entity_descriptor[index++]; 24127c478bd9Sstevel@tonic-gate hidparser_report_err(HIDPARSER_ERR_WARN, 24137c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 24147c478bd9Sstevel@tonic-gate 0, 24157c478bd9Sstevel@tonic-gate 0x3E, 24167c478bd9Sstevel@tonic-gate "Long item defined"); 24177c478bd9Sstevel@tonic-gate } else { 24187c478bd9Sstevel@tonic-gate parsed_length = ch & 0x03; 24197c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, 24207c478bd9Sstevel@tonic-gate hparser_log_handle, 24217c478bd9Sstevel@tonic-gate "scanner: parsed_length = %x", parsed_length); 24227c478bd9Sstevel@tonic-gate /* 3 really means 4.. see p.21 HID */ 24237c478bd9Sstevel@tonic-gate if (parsed_length == 3) 24247c478bd9Sstevel@tonic-gate parsed_length++; 24257c478bd9Sstevel@tonic-gate } 24267c478bd9Sstevel@tonic-gate for (count = 0; count < parsed_length; count++) { 24277c478bd9Sstevel@tonic-gate parsed_text[count] = entity_descriptor[index]; 24287c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, hparser_log_handle, 24297c478bd9Sstevel@tonic-gate "scanner: parsed_text[%d] = 0x%x," 24307c478bd9Sstevel@tonic-gate "index = 0x%lx", 24317c478bd9Sstevel@tonic-gate count, parsed_text[count], index); 24327c478bd9Sstevel@tonic-gate index++; 24337c478bd9Sstevel@tonic-gate } 24347c478bd9Sstevel@tonic-gate 24357c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, 24367c478bd9Sstevel@tonic-gate hparser_log_handle, "scanner: lexical analyzer found 0x%x " 24377c478bd9Sstevel@tonic-gate "before translation", ch); 24387c478bd9Sstevel@tonic-gate 24397c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_index = index; 24407c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_leng = parsed_length; 24417c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_token = ch & 0xFC; 24427c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, 24437c478bd9Sstevel@tonic-gate hparser_log_handle, "scanner: aindex = 0x%lx", index); 24447c478bd9Sstevel@tonic-gate } else { 24457c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, 24467c478bd9Sstevel@tonic-gate hparser_log_handle, "scanner: eindex = 0x%lx", index); 24477c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_leng = 0; 24487c478bd9Sstevel@tonic-gate scan_ifp->hidparser_tok_token = 0; /* EOF */ 24497c478bd9Sstevel@tonic-gate } 24507c478bd9Sstevel@tonic-gate } 24517c478bd9Sstevel@tonic-gate 24527c478bd9Sstevel@tonic-gate 24537c478bd9Sstevel@tonic-gate /* 24547c478bd9Sstevel@tonic-gate * hidparser_report_err: 24557c478bd9Sstevel@tonic-gate * Construct and print the error code 24567c478bd9Sstevel@tonic-gate * Ref: Hidview error check list 24577c478bd9Sstevel@tonic-gate */ 24587c478bd9Sstevel@tonic-gate static void 24597c478bd9Sstevel@tonic-gate hidparser_report_err(int err_level, 24607c478bd9Sstevel@tonic-gate int err_type, 24617c478bd9Sstevel@tonic-gate int tag, 24627c478bd9Sstevel@tonic-gate int subcode, 24637c478bd9Sstevel@tonic-gate char *msg) 24647c478bd9Sstevel@tonic-gate { 24657c478bd9Sstevel@tonic-gate unsigned int BmParserErrorCode = 0; 24667c478bd9Sstevel@tonic-gate 24677c478bd9Sstevel@tonic-gate if (err_level) { 24687c478bd9Sstevel@tonic-gate BmParserErrorCode |= HIDPARSER_ERR_ERROR; 24697c478bd9Sstevel@tonic-gate } 24707c478bd9Sstevel@tonic-gate if (err_type) { 24717c478bd9Sstevel@tonic-gate BmParserErrorCode |= HIDPARSER_ERR_STANDARD; 24727c478bd9Sstevel@tonic-gate } 24737c478bd9Sstevel@tonic-gate BmParserErrorCode |= (tag << 8) & HIDPARSER_ERR_TAG_MASK; 24747c478bd9Sstevel@tonic-gate BmParserErrorCode |= subcode & HIDPARSER_ERR_SUBCODE_MASK; 24757c478bd9Sstevel@tonic-gate 24767c478bd9Sstevel@tonic-gate if (err_level) { 24777c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, hparser_log_handle, 24787c478bd9Sstevel@tonic-gate "err code = 0x%4x, err str = %s", 24797c478bd9Sstevel@tonic-gate BmParserErrorCode, msg); 24807c478bd9Sstevel@tonic-gate 24817c478bd9Sstevel@tonic-gate } else { 24827c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, hparser_log_handle, 24837c478bd9Sstevel@tonic-gate "wrn code = 0x%4x, wrn str = %s", 24847c478bd9Sstevel@tonic-gate BmParserErrorCode, msg); 24857c478bd9Sstevel@tonic-gate } 24867c478bd9Sstevel@tonic-gate } 24877c478bd9Sstevel@tonic-gate 24887c478bd9Sstevel@tonic-gate 24897c478bd9Sstevel@tonic-gate /* 24907c478bd9Sstevel@tonic-gate * hidparser_isvalid_item: 24917c478bd9Sstevel@tonic-gate * Find if the item tag is a valid one 24927c478bd9Sstevel@tonic-gate */ 24937c478bd9Sstevel@tonic-gate static int 24947c478bd9Sstevel@tonic-gate hidparser_isvalid_item(int tag) 24957c478bd9Sstevel@tonic-gate { 24967c478bd9Sstevel@tonic-gate if (tag == EXTENDED_ITEM) { 24977c478bd9Sstevel@tonic-gate 24987c478bd9Sstevel@tonic-gate return (1); 24997c478bd9Sstevel@tonic-gate } 25007c478bd9Sstevel@tonic-gate 25017c478bd9Sstevel@tonic-gate tag &= 0xFC; 25027c478bd9Sstevel@tonic-gate if ((tag == R_ITEM_INPUT) || 25037c478bd9Sstevel@tonic-gate (tag == R_ITEM_OUTPUT) || 25047c478bd9Sstevel@tonic-gate (tag == R_ITEM_COLLECTION) || 25057c478bd9Sstevel@tonic-gate (tag == R_ITEM_FEATURE) || 25067c478bd9Sstevel@tonic-gate (tag == R_ITEM_END_COLLECTION) || 25077c478bd9Sstevel@tonic-gate (tag == R_ITEM_USAGE_PAGE) || 25087c478bd9Sstevel@tonic-gate (tag == R_ITEM_LOGICAL_MINIMUM) || 25097c478bd9Sstevel@tonic-gate (tag == R_ITEM_LOGICAL_MAXIMUM) || 25107c478bd9Sstevel@tonic-gate (tag == R_ITEM_PHYSICAL_MINIMUM) || 25117c478bd9Sstevel@tonic-gate (tag == R_ITEM_PHYSICAL_MAXIMUM) || 25127c478bd9Sstevel@tonic-gate (tag == R_ITEM_EXPONENT) || 25137c478bd9Sstevel@tonic-gate (tag == R_ITEM_UNIT) || 25147c478bd9Sstevel@tonic-gate (tag == R_ITEM_REPORT_SIZE) || 25157c478bd9Sstevel@tonic-gate (tag == R_ITEM_REPORT_ID) || 25167c478bd9Sstevel@tonic-gate (tag == R_ITEM_REPORT_COUNT) || 25177c478bd9Sstevel@tonic-gate (tag == R_ITEM_PUSH) || 25187c478bd9Sstevel@tonic-gate (tag == R_ITEM_POP) || 25197c478bd9Sstevel@tonic-gate (tag == R_ITEM_USAGE) || 25207c478bd9Sstevel@tonic-gate (tag == R_ITEM_USAGE_MIN) || 25217c478bd9Sstevel@tonic-gate (tag == R_ITEM_USAGE_MAX) || 25227c478bd9Sstevel@tonic-gate (tag == R_ITEM_DESIGNATOR_INDEX) || 25237c478bd9Sstevel@tonic-gate (tag == R_ITEM_DESIGNATOR_MIN) || 25247c478bd9Sstevel@tonic-gate (tag == R_ITEM_DESIGNATOR_MAX) || 25257c478bd9Sstevel@tonic-gate (tag == R_ITEM_STRING_INDEX) || 25267c478bd9Sstevel@tonic-gate (tag == R_ITEM_STRING_MIN) || 25277c478bd9Sstevel@tonic-gate (tag == R_ITEM_STRING_MAX) || 25287c478bd9Sstevel@tonic-gate (tag == R_ITEM_SET_DELIMITER)) { 25297c478bd9Sstevel@tonic-gate 25307c478bd9Sstevel@tonic-gate return (1); 25317c478bd9Sstevel@tonic-gate } else { 25327c478bd9Sstevel@tonic-gate 25337c478bd9Sstevel@tonic-gate return (0); 25347c478bd9Sstevel@tonic-gate } 25357c478bd9Sstevel@tonic-gate } 25367c478bd9Sstevel@tonic-gate 25377c478bd9Sstevel@tonic-gate 25387c478bd9Sstevel@tonic-gate /* 25397c478bd9Sstevel@tonic-gate * hidparser_lookup_attribute: 25407c478bd9Sstevel@tonic-gate * Takes an item pointer(report structure) and a tag(e.g Logical 25417c478bd9Sstevel@tonic-gate * Min) as input. Returns the corresponding attribute structure. 25427c478bd9Sstevel@tonic-gate * Presently used for error checking only. 25437c478bd9Sstevel@tonic-gate */ 25447c478bd9Sstevel@tonic-gate static entity_attribute_t * 25457c478bd9Sstevel@tonic-gate hidparser_lookup_attribute(entity_item_t *item, int attr_tag) 25467c478bd9Sstevel@tonic-gate { 25477c478bd9Sstevel@tonic-gate entity_attribute_t *temp; 25487c478bd9Sstevel@tonic-gate 25497c478bd9Sstevel@tonic-gate if (item == NULL) { 25507c478bd9Sstevel@tonic-gate 25517c478bd9Sstevel@tonic-gate return (NULL); 25527c478bd9Sstevel@tonic-gate } 25537c478bd9Sstevel@tonic-gate 25547c478bd9Sstevel@tonic-gate temp = item->entity_item_attributes; 25557c478bd9Sstevel@tonic-gate while (temp != NULL) { 25567c478bd9Sstevel@tonic-gate if (temp->entity_attribute_tag == attr_tag) { 25577c478bd9Sstevel@tonic-gate 25587c478bd9Sstevel@tonic-gate return (temp); 25597c478bd9Sstevel@tonic-gate } 25607c478bd9Sstevel@tonic-gate 25617c478bd9Sstevel@tonic-gate temp = temp->entity_attribute_next; 25627c478bd9Sstevel@tonic-gate } 25637c478bd9Sstevel@tonic-gate 25647c478bd9Sstevel@tonic-gate return (NULL); 25657c478bd9Sstevel@tonic-gate } 25667c478bd9Sstevel@tonic-gate 25677c478bd9Sstevel@tonic-gate 25687c478bd9Sstevel@tonic-gate /* 25697c478bd9Sstevel@tonic-gate * hidparser_global_err_check: 25707c478bd9Sstevel@tonic-gate * Error checking for Global Items that need to be 25717c478bd9Sstevel@tonic-gate * performed in MainItem 25727c478bd9Sstevel@tonic-gate */ 25737c478bd9Sstevel@tonic-gate static void 25747c478bd9Sstevel@tonic-gate hidparser_global_err_check(entity_item_t *mainitem) 25757c478bd9Sstevel@tonic-gate { 25767c478bd9Sstevel@tonic-gate hidparser_check_minmax_val_signed(mainitem, R_ITEM_LOGICAL_MINIMUM, 25777c478bd9Sstevel@tonic-gate R_ITEM_LOGICAL_MAXIMUM, 0, 0); 25787c478bd9Sstevel@tonic-gate hidparser_check_minmax_val_signed(mainitem, R_ITEM_PHYSICAL_MINIMUM, 25797c478bd9Sstevel@tonic-gate R_ITEM_PHYSICAL_MAXIMUM, 0, 0); 25807c478bd9Sstevel@tonic-gate hidparser_check_correspondence(mainitem, R_ITEM_PHYSICAL_MINIMUM, 25817c478bd9Sstevel@tonic-gate R_ITEM_PHYSICAL_MAXIMUM, 0, 0, 25827c478bd9Sstevel@tonic-gate "Must have a corresponding Physical min", 25837c478bd9Sstevel@tonic-gate "Must have a corresponding Physical max"); 25847c478bd9Sstevel@tonic-gate hidparser_check_correspondence(mainitem, R_ITEM_PUSH, R_ITEM_POP, 25857c478bd9Sstevel@tonic-gate 1, 0, "Should have a corresponding Pop", 25867c478bd9Sstevel@tonic-gate "Must have a corresponding Push"); 25877c478bd9Sstevel@tonic-gate 25887c478bd9Sstevel@tonic-gate } 25897c478bd9Sstevel@tonic-gate 25907c478bd9Sstevel@tonic-gate 25917c478bd9Sstevel@tonic-gate /* 25927c478bd9Sstevel@tonic-gate * hidparser_mainitem_err_check: 25937c478bd9Sstevel@tonic-gate * Error checking for Main Items 25947c478bd9Sstevel@tonic-gate */ 25957c478bd9Sstevel@tonic-gate static void 25967c478bd9Sstevel@tonic-gate hidparser_mainitem_err_check(entity_item_t *mainitem) 25977c478bd9Sstevel@tonic-gate { 25987c478bd9Sstevel@tonic-gate int itemmask = 0; 25997c478bd9Sstevel@tonic-gate entity_attribute_t *attr; 26007c478bd9Sstevel@tonic-gate 26017c478bd9Sstevel@tonic-gate attr = mainitem->entity_item_attributes; 26027c478bd9Sstevel@tonic-gate 26037c478bd9Sstevel@tonic-gate if (attr != NULL) { 26047c478bd9Sstevel@tonic-gate while (attr) { 26057c478bd9Sstevel@tonic-gate switch (attr->entity_attribute_tag) { 26067c478bd9Sstevel@tonic-gate case R_ITEM_LOGICAL_MINIMUM: 26077c478bd9Sstevel@tonic-gate itemmask |= 0x01; 26087c478bd9Sstevel@tonic-gate break; 26097c478bd9Sstevel@tonic-gate case R_ITEM_LOGICAL_MAXIMUM: 26107c478bd9Sstevel@tonic-gate itemmask |= 0x02; 26117c478bd9Sstevel@tonic-gate break; 26127c478bd9Sstevel@tonic-gate case R_ITEM_REPORT_SIZE: 26137c478bd9Sstevel@tonic-gate itemmask |= 0x04; 26147c478bd9Sstevel@tonic-gate break; 26157c478bd9Sstevel@tonic-gate case R_ITEM_REPORT_COUNT: 26167c478bd9Sstevel@tonic-gate itemmask |= 0x08; 26177c478bd9Sstevel@tonic-gate break; 26187c478bd9Sstevel@tonic-gate case R_ITEM_USAGE_PAGE: 26197c478bd9Sstevel@tonic-gate itemmask |= 0x10; 26207c478bd9Sstevel@tonic-gate break; 26217c478bd9Sstevel@tonic-gate default: 26227c478bd9Sstevel@tonic-gate break; 26237c478bd9Sstevel@tonic-gate } /* switch */ 26247c478bd9Sstevel@tonic-gate attr = attr->entity_attribute_next; 26257c478bd9Sstevel@tonic-gate } /* while */ 26267c478bd9Sstevel@tonic-gate } /* if */ 26277c478bd9Sstevel@tonic-gate 26287c478bd9Sstevel@tonic-gate if ((mainitem->entity_item_type == R_ITEM_COLLECTION) || 26297c478bd9Sstevel@tonic-gate (mainitem->entity_item_type == R_ITEM_END_COLLECTION)) { 26307c478bd9Sstevel@tonic-gate 26317c478bd9Sstevel@tonic-gate return; 26327c478bd9Sstevel@tonic-gate } 26337c478bd9Sstevel@tonic-gate if (itemmask != 0x1f) { 26347c478bd9Sstevel@tonic-gate hidparser_report_err( 26357c478bd9Sstevel@tonic-gate HIDPARSER_ERR_ERROR, 26367c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 26377c478bd9Sstevel@tonic-gate mainitem->entity_item_type, 26387c478bd9Sstevel@tonic-gate 0, 26397c478bd9Sstevel@tonic-gate "Required Global/Local items must be defined"); 26407c478bd9Sstevel@tonic-gate } 26417c478bd9Sstevel@tonic-gate } 26427c478bd9Sstevel@tonic-gate 26437c478bd9Sstevel@tonic-gate 26447c478bd9Sstevel@tonic-gate /* 26457c478bd9Sstevel@tonic-gate * hidparser_local_err_check: 26467c478bd9Sstevel@tonic-gate * Error checking for Local items that is done when a MainItem 26477c478bd9Sstevel@tonic-gate * is encountered 26487c478bd9Sstevel@tonic-gate */ 26497c478bd9Sstevel@tonic-gate static void 26507c478bd9Sstevel@tonic-gate hidparser_local_err_check(entity_item_t *mainitem) 26517c478bd9Sstevel@tonic-gate { 26527c478bd9Sstevel@tonic-gate hidparser_check_correspondence(mainitem, R_ITEM_USAGE_MIN, 26537c478bd9Sstevel@tonic-gate R_ITEM_USAGE_MAX, 0, 0, 26547c478bd9Sstevel@tonic-gate "Must have a corresponding Usage Min", 26557c478bd9Sstevel@tonic-gate "Must have a corresponding Usage Max"); 26567c478bd9Sstevel@tonic-gate hidparser_check_minmax_val(mainitem, R_ITEM_USAGE_MIN, 26577c478bd9Sstevel@tonic-gate R_ITEM_USAGE_MAX, 1, 1); 26587c478bd9Sstevel@tonic-gate hidparser_check_correspondence(mainitem, R_ITEM_DESIGNATOR_MIN, 26597c478bd9Sstevel@tonic-gate R_ITEM_DESIGNATOR_MAX, 0, 0, 26607c478bd9Sstevel@tonic-gate "Must have a corresponding Designator min", 26617c478bd9Sstevel@tonic-gate "Must have a corresponding Designator Max"); 26627c478bd9Sstevel@tonic-gate hidparser_check_minmax_val(mainitem, R_ITEM_DESIGNATOR_MIN, 26637c478bd9Sstevel@tonic-gate R_ITEM_DESIGNATOR_MAX, 1, 1); 26647c478bd9Sstevel@tonic-gate hidparser_check_correspondence(mainitem, R_ITEM_STRING_MIN, 26657c478bd9Sstevel@tonic-gate R_ITEM_STRING_MAX, 0, 0, 26667c478bd9Sstevel@tonic-gate "Must have a corresponding String min", 26677c478bd9Sstevel@tonic-gate "Must have a corresponding String Max"); 26687c478bd9Sstevel@tonic-gate hidparser_check_minmax_val(mainitem, R_ITEM_STRING_MIN, 26697c478bd9Sstevel@tonic-gate R_ITEM_STRING_MAX, 1, 1); 26707c478bd9Sstevel@tonic-gate } 26717c478bd9Sstevel@tonic-gate 26727c478bd9Sstevel@tonic-gate 26737c478bd9Sstevel@tonic-gate /* 26747c478bd9Sstevel@tonic-gate * hidparser_find_unsigned_val: 26757c478bd9Sstevel@tonic-gate * Find the value for multibyte data 26767c478bd9Sstevel@tonic-gate * Ref: Section 5.8 of HID Spec 1.0 26777c478bd9Sstevel@tonic-gate */ 26787c478bd9Sstevel@tonic-gate static unsigned int 26797c478bd9Sstevel@tonic-gate hidparser_find_unsigned_val(entity_attribute_t *attr) 26807c478bd9Sstevel@tonic-gate { 26817c478bd9Sstevel@tonic-gate char *text; 26827c478bd9Sstevel@tonic-gate int len, i; 26837c478bd9Sstevel@tonic-gate unsigned int ret = 0; 26847c478bd9Sstevel@tonic-gate 26857c478bd9Sstevel@tonic-gate text = attr->entity_attribute_value; 26867c478bd9Sstevel@tonic-gate len = attr->entity_attribute_length; 26877c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++) { 26887c478bd9Sstevel@tonic-gate ret |= ((text[i] & 0xff) << (8*i)); 26897c478bd9Sstevel@tonic-gate } 26907c478bd9Sstevel@tonic-gate 26917c478bd9Sstevel@tonic-gate return (ret); 26927c478bd9Sstevel@tonic-gate } 26937c478bd9Sstevel@tonic-gate 26947c478bd9Sstevel@tonic-gate 26957c478bd9Sstevel@tonic-gate /* 26967c478bd9Sstevel@tonic-gate * hidparser_find_signed_val: 26977c478bd9Sstevel@tonic-gate * Find the value for signed multibyte data 26987c478bd9Sstevel@tonic-gate * Ref: Section 5.8 of HID Spec 1.0 26997c478bd9Sstevel@tonic-gate */ 27007c478bd9Sstevel@tonic-gate static signed int 27017c478bd9Sstevel@tonic-gate hidparser_find_signed_val(entity_attribute_t *attr) 27027c478bd9Sstevel@tonic-gate { 27037c478bd9Sstevel@tonic-gate char *text; 27047c478bd9Sstevel@tonic-gate int len, i; 27057c478bd9Sstevel@tonic-gate int ret = 0; 27067c478bd9Sstevel@tonic-gate 27077c478bd9Sstevel@tonic-gate text = attr->entity_attribute_value; 27087c478bd9Sstevel@tonic-gate len = attr->entity_attribute_length; 27097c478bd9Sstevel@tonic-gate 27107c478bd9Sstevel@tonic-gate for (i = 0; i < len - 1; i++) { 27117c478bd9Sstevel@tonic-gate ret |= ((text[i] & 0xff) << (8 * i)); 27127c478bd9Sstevel@tonic-gate } 27137c478bd9Sstevel@tonic-gate 27147c478bd9Sstevel@tonic-gate if (len > 0) { 27157c478bd9Sstevel@tonic-gate ret |= (text[i] << (8 * i)); 27167c478bd9Sstevel@tonic-gate } 27177c478bd9Sstevel@tonic-gate 27187c478bd9Sstevel@tonic-gate return (ret); 27197c478bd9Sstevel@tonic-gate } 27207c478bd9Sstevel@tonic-gate 27217c478bd9Sstevel@tonic-gate 27227c478bd9Sstevel@tonic-gate /* 27237c478bd9Sstevel@tonic-gate * hidparser_check_correspondence: 27247c478bd9Sstevel@tonic-gate * Check if the item item2 corresponding to item1 exists and vice versa 27257c478bd9Sstevel@tonic-gate * If not report the appropriate error 27267c478bd9Sstevel@tonic-gate */ 27277c478bd9Sstevel@tonic-gate static void 27287c478bd9Sstevel@tonic-gate hidparser_check_correspondence(entity_item_t *mainitem, 27297c478bd9Sstevel@tonic-gate int item_tag1, 27307c478bd9Sstevel@tonic-gate int item_tag2, 27317c478bd9Sstevel@tonic-gate int val1, 27327c478bd9Sstevel@tonic-gate int val2, 27337c478bd9Sstevel@tonic-gate char *str1, 27347c478bd9Sstevel@tonic-gate char *str2) 27357c478bd9Sstevel@tonic-gate { 27367c478bd9Sstevel@tonic-gate entity_attribute_t *temp1, *temp2; 27377c478bd9Sstevel@tonic-gate 27387c478bd9Sstevel@tonic-gate temp1 = hidparser_lookup_attribute(mainitem, item_tag1); 27397c478bd9Sstevel@tonic-gate temp2 = hidparser_lookup_attribute(mainitem, item_tag2); 27407c478bd9Sstevel@tonic-gate if ((temp1 != NULL) && (temp2 == NULL)) { 27417c478bd9Sstevel@tonic-gate hidparser_report_err( 27427c478bd9Sstevel@tonic-gate HIDPARSER_ERR_ERROR, 27437c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 27447c478bd9Sstevel@tonic-gate item_tag1, 27457c478bd9Sstevel@tonic-gate val1, 27467c478bd9Sstevel@tonic-gate str1); 27477c478bd9Sstevel@tonic-gate } 27487c478bd9Sstevel@tonic-gate if ((temp2 != NULL) && (temp1 == NULL)) { 27497c478bd9Sstevel@tonic-gate hidparser_report_err( 27507c478bd9Sstevel@tonic-gate HIDPARSER_ERR_ERROR, 27517c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 27527c478bd9Sstevel@tonic-gate item_tag2, 27537c478bd9Sstevel@tonic-gate val2, 27547c478bd9Sstevel@tonic-gate str2); 27557c478bd9Sstevel@tonic-gate } 27567c478bd9Sstevel@tonic-gate } 27577c478bd9Sstevel@tonic-gate 27587c478bd9Sstevel@tonic-gate 27597c478bd9Sstevel@tonic-gate /* 27607c478bd9Sstevel@tonic-gate * hidparser_check_minmax_val: 27617c478bd9Sstevel@tonic-gate * Check if the Min value <= Max and vice versa 27627c478bd9Sstevel@tonic-gate * Print for warnings and errors have been taken care separately. 27637c478bd9Sstevel@tonic-gate */ 27647c478bd9Sstevel@tonic-gate static void 27657c478bd9Sstevel@tonic-gate hidparser_check_minmax_val(entity_item_t *mainitem, 27667c478bd9Sstevel@tonic-gate int item_tag1, 27677c478bd9Sstevel@tonic-gate int item_tag2, 27687c478bd9Sstevel@tonic-gate int val1, 27697c478bd9Sstevel@tonic-gate int val2) 27707c478bd9Sstevel@tonic-gate { 27717c478bd9Sstevel@tonic-gate entity_attribute_t *temp1, *temp2; 27727c478bd9Sstevel@tonic-gate 27737c478bd9Sstevel@tonic-gate temp1 = hidparser_lookup_attribute(mainitem, item_tag1); 27747c478bd9Sstevel@tonic-gate temp2 = hidparser_lookup_attribute(mainitem, item_tag2); 27757c478bd9Sstevel@tonic-gate if ((temp1 != NULL) && (temp2 != NULL)) { 27767c478bd9Sstevel@tonic-gate if (hidparser_find_unsigned_val(temp1) > 27777c478bd9Sstevel@tonic-gate hidparser_find_unsigned_val(temp2)) { 27787c478bd9Sstevel@tonic-gate if ((item_tag1 == R_ITEM_LOGICAL_MINIMUM) || 27797c478bd9Sstevel@tonic-gate (item_tag1 == R_ITEM_PHYSICAL_MINIMUM)) { 27807c478bd9Sstevel@tonic-gate hidparser_report_err( 27817c478bd9Sstevel@tonic-gate HIDPARSER_ERR_WARN, 27827c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 27837c478bd9Sstevel@tonic-gate item_tag1, 27847c478bd9Sstevel@tonic-gate val1, 27857c478bd9Sstevel@tonic-gate "unsigned: Min should be <= to Max"); 27867c478bd9Sstevel@tonic-gate } else { 27877c478bd9Sstevel@tonic-gate hidparser_report_err( 27887c478bd9Sstevel@tonic-gate HIDPARSER_ERR_ERROR, 27897c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 27907c478bd9Sstevel@tonic-gate item_tag1, 27917c478bd9Sstevel@tonic-gate val1, 27927c478bd9Sstevel@tonic-gate "Min must be <= to Max"); 27937c478bd9Sstevel@tonic-gate } 27947c478bd9Sstevel@tonic-gate } 27957c478bd9Sstevel@tonic-gate if (hidparser_find_unsigned_val(temp2) < 27967c478bd9Sstevel@tonic-gate hidparser_find_unsigned_val(temp1)) { 27977c478bd9Sstevel@tonic-gate if ((item_tag2 == R_ITEM_LOGICAL_MAXIMUM) || 27987c478bd9Sstevel@tonic-gate (item_tag2 == R_ITEM_PHYSICAL_MAXIMUM)) { 27997c478bd9Sstevel@tonic-gate hidparser_report_err( 28007c478bd9Sstevel@tonic-gate HIDPARSER_ERR_ERROR, 28017c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 28027c478bd9Sstevel@tonic-gate item_tag2, 28037c478bd9Sstevel@tonic-gate val2, 28047c478bd9Sstevel@tonic-gate "unsigned: Max should be >= to Min"); 28057c478bd9Sstevel@tonic-gate } else { 28067c478bd9Sstevel@tonic-gate hidparser_report_err( 28077c478bd9Sstevel@tonic-gate HIDPARSER_ERR_ERROR, 28087c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 28097c478bd9Sstevel@tonic-gate item_tag2, 28107c478bd9Sstevel@tonic-gate val2, 28117c478bd9Sstevel@tonic-gate "Max must be >= to Min"); 28127c478bd9Sstevel@tonic-gate } 28137c478bd9Sstevel@tonic-gate } 28147c478bd9Sstevel@tonic-gate } /* if (temp1 != NULL) && (temp2 != NULL) */ 28157c478bd9Sstevel@tonic-gate } 28167c478bd9Sstevel@tonic-gate 28177c478bd9Sstevel@tonic-gate 28187c478bd9Sstevel@tonic-gate /* 28197c478bd9Sstevel@tonic-gate * hidparser_check_minmax_val_signed: 28207c478bd9Sstevel@tonic-gate * Check if the Min value <= Max and vice versa 28217c478bd9Sstevel@tonic-gate * Print for warnings and errors have been taken care separately. 28227c478bd9Sstevel@tonic-gate */ 28237c478bd9Sstevel@tonic-gate static void 28247c478bd9Sstevel@tonic-gate hidparser_check_minmax_val_signed(entity_item_t *mainitem, 28257c478bd9Sstevel@tonic-gate int item_tag1, 28267c478bd9Sstevel@tonic-gate int item_tag2, 28277c478bd9Sstevel@tonic-gate int val1, 28287c478bd9Sstevel@tonic-gate int val2) 28297c478bd9Sstevel@tonic-gate { 28307c478bd9Sstevel@tonic-gate entity_attribute_t *temp1, *temp2; 28317c478bd9Sstevel@tonic-gate 28327c478bd9Sstevel@tonic-gate temp1 = hidparser_lookup_attribute(mainitem, item_tag1); 28337c478bd9Sstevel@tonic-gate temp2 = hidparser_lookup_attribute(mainitem, item_tag2); 28347c478bd9Sstevel@tonic-gate if ((temp1 != NULL) && (temp2 != NULL)) { 28357c478bd9Sstevel@tonic-gate if (hidparser_find_signed_val(temp1) > 28367c478bd9Sstevel@tonic-gate hidparser_find_signed_val(temp2)) { 28377c478bd9Sstevel@tonic-gate if ((item_tag1 == R_ITEM_LOGICAL_MINIMUM) || 28387c478bd9Sstevel@tonic-gate (item_tag1 == R_ITEM_PHYSICAL_MINIMUM)) { 28397c478bd9Sstevel@tonic-gate hidparser_report_err( 28407c478bd9Sstevel@tonic-gate HIDPARSER_ERR_WARN, 28417c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 28427c478bd9Sstevel@tonic-gate item_tag1, 28437c478bd9Sstevel@tonic-gate val1, 28447c478bd9Sstevel@tonic-gate "signed: Min should be <= to Max"); 28457c478bd9Sstevel@tonic-gate } else { 28467c478bd9Sstevel@tonic-gate hidparser_report_err( 28477c478bd9Sstevel@tonic-gate HIDPARSER_ERR_ERROR, 28487c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 28497c478bd9Sstevel@tonic-gate item_tag1, 28507c478bd9Sstevel@tonic-gate val1, 28517c478bd9Sstevel@tonic-gate "Min must be <= to Max"); 28527c478bd9Sstevel@tonic-gate } 28537c478bd9Sstevel@tonic-gate } 28547c478bd9Sstevel@tonic-gate if (hidparser_find_signed_val(temp2) < 28557c478bd9Sstevel@tonic-gate hidparser_find_signed_val(temp1)) { 28567c478bd9Sstevel@tonic-gate if ((item_tag2 == R_ITEM_LOGICAL_MAXIMUM) || 28577c478bd9Sstevel@tonic-gate (item_tag2 == R_ITEM_PHYSICAL_MAXIMUM)) { 28587c478bd9Sstevel@tonic-gate hidparser_report_err( 28597c478bd9Sstevel@tonic-gate HIDPARSER_ERR_ERROR, 28607c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 28617c478bd9Sstevel@tonic-gate item_tag2, 28627c478bd9Sstevel@tonic-gate val2, 28637c478bd9Sstevel@tonic-gate "signed: Max should be >= to Min"); 28647c478bd9Sstevel@tonic-gate } else { 28657c478bd9Sstevel@tonic-gate hidparser_report_err( 28667c478bd9Sstevel@tonic-gate HIDPARSER_ERR_ERROR, 28677c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 28687c478bd9Sstevel@tonic-gate item_tag2, 28697c478bd9Sstevel@tonic-gate val2, 28707c478bd9Sstevel@tonic-gate "Max must be >= to Min"); 28717c478bd9Sstevel@tonic-gate } 28727c478bd9Sstevel@tonic-gate } 28737c478bd9Sstevel@tonic-gate } /* if (temp1 != NULL) && (temp2 != NULL) */ 28747c478bd9Sstevel@tonic-gate } 28757c478bd9Sstevel@tonic-gate 28767c478bd9Sstevel@tonic-gate 28777c478bd9Sstevel@tonic-gate /* 28787c478bd9Sstevel@tonic-gate * hidparser_error_delim: 28797c478bd9Sstevel@tonic-gate * Error check for Delimiter Sets 28807c478bd9Sstevel@tonic-gate */ 28817c478bd9Sstevel@tonic-gate static void 28827c478bd9Sstevel@tonic-gate hidparser_error_delim(entity_item_t *item, int err) 28837c478bd9Sstevel@tonic-gate { 28847c478bd9Sstevel@tonic-gate entity_attribute_t *attr; 28857c478bd9Sstevel@tonic-gate switch (err) { 28867c478bd9Sstevel@tonic-gate case HIDPARSER_DELIM_ERR1: 28877c478bd9Sstevel@tonic-gate hidparser_report_err( 28887c478bd9Sstevel@tonic-gate HIDPARSER_ERR_ERROR, 28897c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 28907c478bd9Sstevel@tonic-gate R_ITEM_SET_DELIMITER, 28917c478bd9Sstevel@tonic-gate 0, 28927c478bd9Sstevel@tonic-gate "Must be Delimiter Open"); 28937c478bd9Sstevel@tonic-gate 28947c478bd9Sstevel@tonic-gate break; 28957c478bd9Sstevel@tonic-gate case HIDPARSER_DELIM_ERR2: 28967c478bd9Sstevel@tonic-gate hidparser_report_err( 28977c478bd9Sstevel@tonic-gate HIDPARSER_ERR_ERROR, 28987c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 28997c478bd9Sstevel@tonic-gate R_ITEM_SET_DELIMITER, 29007c478bd9Sstevel@tonic-gate 0, 29017c478bd9Sstevel@tonic-gate "Must be Delimiter Close"); 29027c478bd9Sstevel@tonic-gate 29037c478bd9Sstevel@tonic-gate break; 29047c478bd9Sstevel@tonic-gate case HIDPARSER_DELIM_ERR3: 29057c478bd9Sstevel@tonic-gate attr = item->entity_item_attributes; 29067c478bd9Sstevel@tonic-gate while (attr != NULL) { 29077c478bd9Sstevel@tonic-gate if ((attr->entity_attribute_tag != 29087c478bd9Sstevel@tonic-gate R_ITEM_USAGE) && 29097c478bd9Sstevel@tonic-gate (attr->entity_attribute_tag != 29107c478bd9Sstevel@tonic-gate R_ITEM_USAGE_MIN) && 29117c478bd9Sstevel@tonic-gate (attr->entity_attribute_tag != 29127c478bd9Sstevel@tonic-gate R_ITEM_USAGE_MAX)) { 29137c478bd9Sstevel@tonic-gate hidparser_report_err( 29147c478bd9Sstevel@tonic-gate HIDPARSER_ERR_ERROR, 29157c478bd9Sstevel@tonic-gate HIDPARSER_ERR_STANDARD, 29167c478bd9Sstevel@tonic-gate R_ITEM_SET_DELIMITER, 29177c478bd9Sstevel@tonic-gate 3, 29187c478bd9Sstevel@tonic-gate "May only contain Usage, " 29197c478bd9Sstevel@tonic-gate "Usage Min and Usage Max"); 29207c478bd9Sstevel@tonic-gate } 29217c478bd9Sstevel@tonic-gate attr = attr->entity_attribute_next; 29227c478bd9Sstevel@tonic-gate } 29237c478bd9Sstevel@tonic-gate 29247c478bd9Sstevel@tonic-gate break; 29257c478bd9Sstevel@tonic-gate default: 29267c478bd9Sstevel@tonic-gate 29277c478bd9Sstevel@tonic-gate break; 29287c478bd9Sstevel@tonic-gate } 29297c478bd9Sstevel@tonic-gate } 29307c478bd9Sstevel@tonic-gate 29317c478bd9Sstevel@tonic-gate 29327c478bd9Sstevel@tonic-gate /* 29337c478bd9Sstevel@tonic-gate * hidparser_find_max_packet_size_from_report_descriptor: 29347c478bd9Sstevel@tonic-gate * find packet size of the largest report in the report descriptor 29357c478bd9Sstevel@tonic-gate */ 29367c478bd9Sstevel@tonic-gate void 29377c478bd9Sstevel@tonic-gate hidparser_find_max_packet_size_from_report_descriptor( 29387c478bd9Sstevel@tonic-gate hidparser_handle_t hparser_handle, 29397c478bd9Sstevel@tonic-gate hidparser_packet_info_t *hpack) 29407c478bd9Sstevel@tonic-gate { 29417c478bd9Sstevel@tonic-gate 29427c478bd9Sstevel@tonic-gate int rval, i; 29437c478bd9Sstevel@tonic-gate uint_t packet_size; 29447c478bd9Sstevel@tonic-gate uint_t max_packet_size; 29457c478bd9Sstevel@tonic-gate uint_t max_report_id; 29467c478bd9Sstevel@tonic-gate hidparser_report_id_list_t report_id_list; 29477c478bd9Sstevel@tonic-gate 29487c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, hparser_log_handle, 29497c478bd9Sstevel@tonic-gate "hidparser_find_max_packet_size_from_report_descriptor"); 29507c478bd9Sstevel@tonic-gate 29517c478bd9Sstevel@tonic-gate /* get a list of input reports */ 29527c478bd9Sstevel@tonic-gate rval = hidparser_get_report_id_list(hparser_handle, 29537c478bd9Sstevel@tonic-gate R_ITEM_INPUT, &report_id_list); 29547c478bd9Sstevel@tonic-gate if (rval != HIDPARSER_SUCCESS) { 29557c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, hparser_log_handle, 29567c478bd9Sstevel@tonic-gate "No report id used"); 29577c478bd9Sstevel@tonic-gate } else { 29587c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, hparser_log_handle, 29597c478bd9Sstevel@tonic-gate "%d unique report IDs found in hid report descriptor", 29607c478bd9Sstevel@tonic-gate report_id_list.no_of_report_ids); 29617c478bd9Sstevel@tonic-gate 29627c478bd9Sstevel@tonic-gate for (i = 0; i < (report_id_list.no_of_report_ids); i++) { 29637c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, hparser_log_handle, 29647c478bd9Sstevel@tonic-gate "report_id: %d", report_id_list.report_id[i]); 29657c478bd9Sstevel@tonic-gate } 29667c478bd9Sstevel@tonic-gate } 29677c478bd9Sstevel@tonic-gate 29687c478bd9Sstevel@tonic-gate if ((rval != HIDPARSER_SUCCESS) || 29697c478bd9Sstevel@tonic-gate (report_id_list.no_of_report_ids == 0)) { 29707c478bd9Sstevel@tonic-gate /* 29717c478bd9Sstevel@tonic-gate * since no report id is used, get the packet size 29727c478bd9Sstevel@tonic-gate * for the only report available 29737c478bd9Sstevel@tonic-gate */ 29747c478bd9Sstevel@tonic-gate (void) hidparser_get_packet_size(hparser_handle, 29757c478bd9Sstevel@tonic-gate 0, R_ITEM_INPUT, &packet_size); 29767c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, hparser_log_handle, 29777c478bd9Sstevel@tonic-gate "Not using report id prefix. HID packet size = %d", 29787c478bd9Sstevel@tonic-gate packet_size); 29797c478bd9Sstevel@tonic-gate 29807c478bd9Sstevel@tonic-gate hpack->max_packet_size = packet_size; 29817c478bd9Sstevel@tonic-gate hpack->report_id = HID_REPORT_ID_UNDEFINED; 29827c478bd9Sstevel@tonic-gate } else { 29837c478bd9Sstevel@tonic-gate /* 29847c478bd9Sstevel@tonic-gate * hid device uses multiple reports with report id prefix byte. 29857c478bd9Sstevel@tonic-gate * Find the longest input report. 29867c478bd9Sstevel@tonic-gate * See HID 8.4. 29877c478bd9Sstevel@tonic-gate */ 29887c478bd9Sstevel@tonic-gate max_packet_size = 0; 29897c478bd9Sstevel@tonic-gate max_report_id = 0; 29907c478bd9Sstevel@tonic-gate 29917c478bd9Sstevel@tonic-gate for (i = 0; i < (report_id_list.no_of_report_ids); i++) { 29927c478bd9Sstevel@tonic-gate (void) hidparser_get_packet_size(hparser_handle, 29937c478bd9Sstevel@tonic-gate report_id_list.report_id[i], R_ITEM_INPUT, 29947c478bd9Sstevel@tonic-gate &packet_size); 29957c478bd9Sstevel@tonic-gate if (packet_size > max_packet_size) { 29967c478bd9Sstevel@tonic-gate max_packet_size = packet_size; 29977c478bd9Sstevel@tonic-gate max_report_id = report_id_list.report_id[i]; 29987c478bd9Sstevel@tonic-gate } 29997c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, hparser_log_handle, 30007c478bd9Sstevel@tonic-gate "Report ID %d has a packet size of %d", 30017c478bd9Sstevel@tonic-gate report_id_list.report_id[i], packet_size); 30027c478bd9Sstevel@tonic-gate } 30037c478bd9Sstevel@tonic-gate 30047c478bd9Sstevel@tonic-gate hpack->max_packet_size = max_packet_size; 30057c478bd9Sstevel@tonic-gate hpack->report_id = max_report_id; 30067c478bd9Sstevel@tonic-gate 30077c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, hparser_log_handle, 30087c478bd9Sstevel@tonic-gate "Report ID %d has the maximum packet size of %d", 30097c478bd9Sstevel@tonic-gate max_report_id, max_packet_size); 30107c478bd9Sstevel@tonic-gate } 30117c478bd9Sstevel@tonic-gate } 3012