1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** USBX Component                                                        */
16 /**                                                                       */
17 /**   HID Class                                                           */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 
23 /* Include necessary system files.  */
24 
25 #define UX_SOURCE_CODE
26 
27 #include "ux_api.h"
28 #include "ux_host_class_hid.h"
29 #include "ux_host_stack.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _ux_host_class_hid_local_item_parse                 PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function parses a local item from the report descriptor.       */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    hid                                   Pointer to HID class          */
49 /*    item                                  Pointer to item               */
50 /*    descriptor                            Pointer to descriptor         */
51 /*                                                                        */
52 /*  OUTPUT                                                                */
53 /*                                                                        */
54 /*    Completion Status                                                   */
55 /*                                                                        */
56 /*  CALLS                                                                 */
57 /*                                                                        */
58 /*    _ux_host_class_hid_item_data_get      Get data item                 */
59 /*                                                                        */
60 /*  CALLED BY                                                             */
61 /*                                                                        */
62 /*    HID Class                                                           */
63 /*                                                                        */
64 /*  RELEASE HISTORY                                                       */
65 /*                                                                        */
66 /*    DATE              NAME                      DESCRIPTION             */
67 /*                                                                        */
68 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
69 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
70 /*                                            resulting in version 6.1    */
71 /*                                                                        */
72 /**************************************************************************/
_ux_host_class_hid_local_item_parse(UX_HOST_CLASS_HID * hid,UX_HOST_CLASS_HID_ITEM * item,UCHAR * descriptor)73 UINT  _ux_host_class_hid_local_item_parse(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_ITEM *item, UCHAR *descriptor)
74 {
75 
76 UX_HOST_CLASS_HID_PARSER    *hid_parser;
77 ULONG                       usage;
78 ULONG                       usage_min;
79 ULONG                       usage_max;
80 ULONG                       delimiter_set;
81 
82     /* Get the temporary parser structure pointer.  */
83     hid_parser =  &hid -> ux_host_class_hid_parser;
84 
85     /* Analyze the tag.  */
86     switch (item -> ux_host_class_hid_item_report_tag)
87     {
88 
89     case UX_HOST_CLASS_HID_LOCAL_TAG_USAGE:
90 
91         /* Local usage tag, check if we have an overflow.  */
92         if (hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_number_usage == UX_HOST_CLASS_HID_USAGES)
93         {
94 
95             /* Error trap. */
96             _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_USAGE_OVERFLOW);
97 
98             /* If trace is enabled, insert this event into the trace buffer.  */
99             UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_USAGE_OVERFLOW, hid, 0, 0, UX_TRACE_ERRORS, 0, 0)
100 
101             return(UX_HOST_CLASS_HID_USAGE_OVERFLOW);
102         }
103 
104         /* Obtain the usage from the descriptor.  */
105         usage =  _ux_host_class_hid_item_data_get(descriptor, item);
106 
107         /* Combine the global usage with the local usage to form a unique usage ID.  */
108         usage |= (hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_usage_page << 16);
109 
110         /* Add the usage to the local usage table.  */
111         hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usages[hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_number_usage] =  usage;
112 
113         /* We have one more usage now.  */
114         hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_number_usage++;
115 
116         break;
117 
118 
119     case UX_HOST_CLASS_HID_LOCAL_TAG_USAGE_MINIMUM:
120 
121         /* Usage Minimum tag.  */
122         hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usage_min =
123                                                 (ULONG) _ux_host_class_hid_item_data_get(descriptor, item);
124 
125         break;
126 
127 
128     case UX_HOST_CLASS_HID_LOCAL_TAG_USAGE_MAXIMUM:
129 
130         /* Usage Maximum tag.  */
131         hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usage_max =
132                                                 (ULONG) _ux_host_class_hid_item_data_get(descriptor, item);
133 
134         /* Check if the maximum value is coherent with the minimum.  */
135         if (hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usage_max < hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usage_min)
136         {
137 
138             /* Error trap. */
139             _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_MIN_MAX_ERROR);
140 
141             /* If trace is enabled, insert this event into the trace buffer.  */
142             UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_MIN_MAX_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0)
143 
144             return(UX_HOST_CLASS_HID_MIN_MAX_ERROR);
145         }
146 
147         /* Get the boundaries for the usage values which are defined when encountering the USAGE MAX tag.  */
148         usage_min =  (ULONG)(hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usage_min);
149         usage_max =  (ULONG)(hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usage_max);
150 
151         while (usage_min <= usage_max)
152         {
153 
154             /* Check if we can still add this usage.  */
155             if (hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_number_usage == UX_HOST_CLASS_HID_USAGES)
156             {
157 
158                 /* Error trap. */
159                 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_USAGE_OVERFLOW);
160 
161                 /* If trace is enabled, insert this event into the trace buffer.  */
162                 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_USAGE_OVERFLOW, hid, 0, 0, UX_TRACE_ERRORS, 0, 0)
163 
164                 return(UX_HOST_CLASS_HID_USAGE_OVERFLOW);
165 
166             }
167 
168             /* Combine the global usage with the local usage to form a unique usage ID.  */
169             usage =  usage_min | (hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_usage_page << 16);
170 
171             /* Add the usage to the local usage table.  */
172             hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usages[hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_number_usage] =  usage;
173 
174             /* We have one more usage now.  */
175             hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_number_usage++;
176 
177             /* Next usage value.  */
178             usage_min++;
179         }
180 
181         break;
182 
183     case UX_HOST_CLASS_HID_LOCAL_TAG_DELIMITER:
184 
185         /* Obtain the delimiter set from the descriptor.  */
186         delimiter_set =  _ux_host_class_hid_item_data_get(descriptor, item);
187 
188         /* We should have either an open or a close.  */
189         switch (delimiter_set)
190         {
191 
192         case UX_HOST_CLASS_HID_DELIMITER_OPEN:
193 
194             /* Recursive delimiter opens are not supported.  */
195             if (hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_delimiter_level == 1)
196             {
197 
198                 /* Error trap. */
199                 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_DELIMITER_ERROR);
200 
201                 return(UX_HOST_CLASS_HID_DELIMITER_ERROR);
202             }
203 
204             /* Mark the opening of the delimiter.  */
205             hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_delimiter_level =  1;
206 
207             break;
208 
209         case UX_HOST_CLASS_HID_DELIMITER_CLOSE:
210 
211             /* Ensure we had an open delimiter before.  */
212             if (hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_delimiter_level == 0)
213             {
214 
215                 /* Error trap. */
216                 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_DELIMITER_ERROR);
217 
218                 return(UX_HOST_CLASS_HID_DELIMITER_ERROR);
219             }
220 
221             /* Mark the closing of the delimiter.  */
222             hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_delimiter_level =  0;
223 
224             break;
225 
226         default:
227 
228             /* Error trap. */
229             _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_DELIMITER_ERROR);
230 
231             /* We got a wrong delimiter set.  */
232             return(UX_HOST_CLASS_HID_DELIMITER_ERROR);
233         }
234         break;
235 
236     default:
237 
238         /* Error trap. */
239         _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_TAG_UNSUPPORTED);
240 
241         /* If trace is enabled, insert this event into the trace buffer.  */
242         UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_TAG_UNSUPPORTED, hid, 0, 0, UX_TRACE_ERRORS, 0, 0)
243 
244         /* This tag is either unknown or unsupported.  */
245         return(UX_HOST_CLASS_HID_TAG_UNSUPPORTED);
246     }
247 
248     /* Return status. Always SUCCESS if we get here.*/
249     return(UX_SUCCESS);
250 }
251 
252