1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** USBX Component */
17 /** */
18 /** HID Class */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23
24 /* Include necessary system files. */
25
26 #define UX_SOURCE_CODE
27
28 #include "ux_api.h"
29 #include "ux_host_class_hid.h"
30 #include "ux_host_stack.h"
31
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _ux_host_class_hid_report_compress PORTABLE C */
38 /* 6.1 */
39 /* AUTHOR */
40 /* */
41 /* Chaoqiong Xiao, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function will compress a client report into a report buffer. */
46 /* */
47 /* INPUT */
48 /* */
49 /* hid Pointer to HID class */
50 /* client_report Pointer to client report */
51 /* report_buffer Pointer to report buffer */
52 /* report_length Length of report */
53 /* */
54 /* OUTPUT */
55 /* */
56 /* Completion Status */
57 /* */
58 /* CALLS */
59 /* */
60 /* None */
61 /* */
62 /* CALLED BY */
63 /* */
64 /* HID Class */
65 /* */
66 /* RELEASE HISTORY */
67 /* */
68 /* DATE NAME DESCRIPTION */
69 /* */
70 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
71 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
72 /* resulting in version 6.1 */
73 /* */
74 /**************************************************************************/
_ux_host_class_hid_report_compress(UX_HOST_CLASS_HID * hid,UX_HOST_CLASS_HID_CLIENT_REPORT * client_report,UCHAR * report_buffer,ULONG report_length)75 UINT _ux_host_class_hid_report_compress(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report,
76 UCHAR *report_buffer, ULONG report_length)
77 {
78
79 UX_HOST_CLASS_HID_REPORT *hid_report;
80 UX_HOST_CLASS_HID_FIELD *hid_field;
81 ULONG field_usage;
82 ULONG field_report_count;
83 ULONG field_report_size;
84 ULONG *client_buffer;
85 ULONG client_value;
86 UCHAR value;
87 ULONG data_offset_bit;
88 UCHAR is_valid_usage;
89
90 UX_PARAMETER_NOT_USED(hid);
91 UX_PARAMETER_NOT_USED(report_length);
92
93 /* Get the report pointer from the caller. */
94 hid_report = client_report -> ux_host_class_hid_client_report;
95
96 /* Get the pointer to the user buffer. */
97 client_buffer = client_report -> ux_host_class_hid_client_report_buffer;
98
99 /* Get the first field associated with the report. */
100 hid_field = hid_report -> ux_host_class_hid_report_field;
101
102 /* Set data offset bit. */
103 data_offset_bit = 0;
104
105 /* We need to compress each field defined in the report. */
106 while (hid_field != UX_NULL)
107 {
108
109 /* Each report field has a report count value. This count is used to extract
110 values from the incoming report and build each usage/value instance. */
111 for (field_report_count = 0; field_report_count < hid_field -> ux_host_class_hid_field_report_count; field_report_count++)
112 {
113
114 /* Ensure the usage in the client buffer is valid. How we determine
115 this depends on whether the field is VARIABLE or ARRAY. */
116 is_valid_usage = UX_FALSE;
117 if (hid_field -> ux_host_class_hid_field_value & UX_HOST_CLASS_HID_ITEM_VARIABLE)
118 {
119
120 /* Go through the usage array to try and find the client's usage. */
121 for (field_usage = 0; field_usage < hid_field -> ux_host_class_hid_field_number_usage; field_usage++)
122 {
123
124 /* Is this a usage we've recorded? */
125 if (*client_buffer == hid_field -> ux_host_class_hid_field_usages[field_usage])
126 {
127
128 /* Yes, this is a valid usage. */
129 is_valid_usage = UX_TRUE;
130 break;
131 }
132 }
133 }
134 else
135 {
136
137 /* Is the usage page valid? */
138 if (((*client_buffer & 0xffff0000) >> 16) == hid_field -> ux_host_class_hid_field_usage_page)
139 {
140
141 /* Is the usage in the min and max range? */
142 if ((*client_buffer & 0xffff) >= hid_field -> ux_host_class_hid_field_usage_min &&
143 (*client_buffer & 0xffff) <= hid_field -> ux_host_class_hid_field_usage_max)
144 {
145
146 /* Yes, this is a valid usage. */
147 is_valid_usage = UX_TRUE;
148 }
149 }
150 }
151
152 /* Is the usage invalid? */
153 if (is_valid_usage == UX_FALSE)
154 {
155
156 /* Error trap. */
157 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_ERROR);
158
159 /* If trace is enabled, insert this event into the trace buffer. */
160 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0)
161
162 return(UX_HOST_CLASS_HID_REPORT_ERROR);
163 }
164
165 /* Skip the usage and point the buffer to the value. */
166 client_buffer++;
167
168 /* Read the client value. */
169 client_value = *client_buffer++;
170
171 /* Build the value field in the report buffer bit by bit. */
172 for (field_report_size = hid_field -> ux_host_class_hid_field_report_size; field_report_size > 0; field_report_size--)
173 {
174
175 /* Isolate each bit from the report value. */
176 value = (UCHAR) client_value & 1;
177
178 /* Shift the isolated bit to its right space in the report byte. */
179 value = (UCHAR)(value << data_offset_bit);
180
181 /* Update the report with the bit value. */
182 *report_buffer |= value;
183
184 /* Move to next bit. */
185 data_offset_bit++;
186
187 /* Are we on a byte boundary. */
188 if ((data_offset_bit & 7) == 0)
189 {
190
191 /* If so increment the report address. */
192 report_buffer++;
193
194 /* Reset offset bit. */
195 data_offset_bit = 0;
196 }
197
198 /* Move to the next bit. */
199 client_value = client_value >> 1;
200 }
201 }
202
203 /* Move to the next field. */
204 hid_field = hid_field -> ux_host_class_hid_field_next_field;
205 }
206
207 /* Return successful completion. */
208 return(UX_SUCCESS);
209 }
210