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 /** USBX Component                                                        */
15 /**                                                                       */
16 /**   Device HID Class                                                    */
17 /**                                                                       */
18 /**************************************************************************/
19 /**************************************************************************/
20 
21 #define UX_SOURCE_CODE
22 
23 
24 /* Include necessary system files.  */
25 
26 #include "ux_api.h"
27 #include "ux_device_class_hid.h"
28 #include "ux_device_stack.h"
29 
30 
31 /**************************************************************************/
32 /*                                                                        */
33 /*  FUNCTION                                               RELEASE        */
34 /*                                                                        */
35 /*    _ux_device_class_hid_event_set                      PORTABLE C      */
36 /*                                                           6.3.0        */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Chaoqiong Xiao, Microsoft Corporation                               */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function sends an event to the hid class. It is processed      */
44 /*    asynchronously by the interrupt thread.                             */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    hid                                      Address of hid class       */
49 /*    event                                    Pointer of the event       */
50 /*                                                                        */
51 /*  OUTPUT                                                                */
52 /*                                                                        */
53 /*    status                                   UX_SUCCESS if there is an  */
54 /*                                             event                      */
55 /*  CALLS                                                                 */
56 /*                                                                        */
57 /*    _ux_utility_memory_copy                  Copy memory                */
58 /*    _ux_device_event_flags_set               Set event flags            */
59 /*                                                                        */
60 /*  CALLED BY                                                             */
61 /*                                                                        */
62 /*    ThreadX                                                             */
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 /*                                            added standalone support,   */
71 /*                                            verified memset and memcpy  */
72 /*                                            cases, used UX prefix to    */
73 /*                                            refer to TX symbols instead */
74 /*                                            of using them directly,     */
75 /*                                            resulting in version 6.1    */
76 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
77 /*                                            added standalone support,   */
78 /*                                            resulting in version 6.1.10 */
79 /*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
80 /*                                            resulting in version 6.1.11 */
81 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s),          */
82 /*                                            added zero copy support,    */
83 /*                                            resulting in version 6.3.0  */
84 /*                                                                        */
85 /**************************************************************************/
_ux_device_class_hid_event_set(UX_SLAVE_CLASS_HID * hid,UX_SLAVE_CLASS_HID_EVENT * hid_event)86 UINT  _ux_device_class_hid_event_set(UX_SLAVE_CLASS_HID *hid,
87                                       UX_SLAVE_CLASS_HID_EVENT *hid_event)
88 {
89 
90 UX_DEVICE_CLASS_HID_EVENT   *current_hid_event;
91 UX_DEVICE_CLASS_HID_EVENT   *next_hid_event;
92 UCHAR                       *next_position;
93 
94     /* If trace is enabled, insert this event into the trace buffer.  */
95     UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_HID_EVENT_SET, hid, hid_event, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
96 
97     /* Current position of the head.  */
98     current_hid_event =  hid -> ux_device_class_hid_event_array_head;
99 
100     /* If the pointer is NULL, the round robin buffer has not been activated.  */
101     if (current_hid_event == UX_NULL)
102         return (UX_ERROR);
103 
104     /* Calculate the next position.  */
105     next_position = (UCHAR *)current_hid_event + UX_DEVICE_CLASS_HID_EVENT_QUEUE_ITEM_SIZE(hid);
106     if (next_position >= (UCHAR *)hid -> ux_device_class_hid_event_array_end)
107         next_position = (UCHAR *)hid -> ux_device_class_hid_event_array;
108     next_hid_event = (UX_DEVICE_CLASS_HID_EVENT *)next_position;
109 
110     /* Any place left for this event ? */
111     if (next_hid_event == hid -> ux_device_class_hid_event_array_tail)
112         return (UX_ERROR);
113 
114     /* There is an event to report, get the current pointer to the event.  */
115     current_hid_event =  hid -> ux_device_class_hid_event_array_head;
116 
117     /* Update the head.  */
118     hid -> ux_device_class_hid_event_array_head = next_hid_event;
119 
120     /* Check if this event has a report ID.  */
121     if (hid -> ux_device_class_hid_report_id == UX_TRUE)
122     {
123 
124         /* Yes, there's a report ID. Check to see if our event buffer can also
125            fit the extra byte.  */
126         if (hid_event -> ux_device_class_hid_event_length + 1 > UX_DEVICE_CLASS_HID_EVENT_MAX_LENGTH(hid))
127         {
128 
129             /* Error trap. */
130             _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT);
131 
132             /* If trace is enabled, insert this event into the trace buffer.  */
133             UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
134 
135             /* Return overflow error.  */
136             return(UX_MEMORY_INSUFFICIENT);
137         }
138 
139         /* Store the report ID.  */
140         *UX_DEVICE_CLASS_HID_EVENT_BUFFER(current_hid_event) =  (UCHAR)(hid_event -> ux_device_class_hid_event_report_id);
141 
142         /* Store the data itself.  */
143         _ux_utility_memory_copy(UX_DEVICE_CLASS_HID_EVENT_BUFFER(current_hid_event) + 1,
144                                 hid_event -> ux_device_class_hid_event_buffer,
145                                 hid_event -> ux_device_class_hid_event_length); /* Use case of memcpy is verified. */
146 
147         /* fill in the event structure from the user.  */
148         current_hid_event -> ux_device_class_hid_event_length =  hid_event -> ux_device_class_hid_event_length + 1;
149     }
150     else
151     {
152 
153         /* No report ID to consider.  */
154 
155         /* Store copy of data so application can free event there (easier use).  */
156         _ux_utility_memory_copy(UX_DEVICE_CLASS_HID_EVENT_BUFFER(current_hid_event),
157                                 hid_event -> ux_device_class_hid_event_buffer,
158                                 hid_event -> ux_device_class_hid_event_length); /* Use case of memcpy is verified. */
159 
160         /* fill in the event structure from the user.  */
161         current_hid_event -> ux_device_class_hid_event_length = hid_event -> ux_device_class_hid_event_length;
162     }
163 
164 #if defined(UX_DEVICE_STANDALONE)
165 
166     /* Set state machine to start sending if no transfer on going.  */
167     if (hid -> ux_device_class_hid_event_state != UX_STATE_WAIT &&
168         hid -> ux_device_class_hid_event_state != UX_STATE_EXIT)
169         hid -> ux_device_class_hid_event_state = UX_STATE_RESET;
170 #else
171 
172     /* Set an event to wake up the interrupt thread.  */
173     _ux_device_event_flags_set(&hid -> ux_device_class_hid_event_flags_group, UX_DEVICE_CLASS_HID_NEW_EVENT, UX_OR);
174 #endif
175 
176     /* Return event status to the user.  */
177     return(UX_SUCCESS);
178 }
179 
180 
181 /**************************************************************************/
182 /*                                                                        */
183 /*  FUNCTION                                               RELEASE        */
184 /*                                                                        */
185 /*    _uxe_device_class_hid_event_set                     PORTABLE C      */
186 /*                                                           6.3.0        */
187 /*  AUTHOR                                                                */
188 /*                                                                        */
189 /*    Chaoqiong Xiao, Microsoft Corporation                               */
190 /*                                                                        */
191 /*  DESCRIPTION                                                           */
192 /*                                                                        */
193 /*    This function checks errors in HID event set function call.         */
194 /*                                                                        */
195 /*  INPUT                                                                 */
196 /*                                                                        */
197 /*    hid                                   Pointer to hid instance       */
198 /*    hid_event                             Pointer to hid event          */
199 /*                                                                        */
200 /*  OUTPUT                                                                */
201 /*                                                                        */
202 /*    None                                                                */
203 /*                                                                        */
204 /*  CALLS                                                                 */
205 /*                                                                        */
206 /*    _ux_device_class_hid_event_set        Set an HID event              */
207 /*                                                                        */
208 /*  CALLED BY                                                             */
209 /*                                                                        */
210 /*    Application                                                         */
211 /*                                                                        */
212 /*  RELEASE HISTORY                                                       */
213 /*                                                                        */
214 /*    DATE              NAME                      DESCRIPTION             */
215 /*                                                                        */
216 /*  10-31-2023     Chaoqiong Xiao           Initial Version 6.3.0         */
217 /*                                                                        */
218 /**************************************************************************/
_uxe_device_class_hid_event_set(UX_SLAVE_CLASS_HID * hid,UX_SLAVE_CLASS_HID_EVENT * hid_event)219 UINT  _uxe_device_class_hid_event_set(UX_SLAVE_CLASS_HID *hid,
220                                       UX_SLAVE_CLASS_HID_EVENT *hid_event)
221 {
222 
223     /* Sanity checks.  */
224     if ((hid == UX_NULL) || (hid_event == UX_NULL))
225         return(UX_INVALID_PARAMETER);
226 
227     /* Invoke function to get event.  */
228     return(_ux_device_class_hid_event_set(hid, hid_event));
229 }
230