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 /** 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_receiver_initialize            PORTABLE C      */
36 /*                                                           6.1.12       */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Chaoqiong Xiao, Microsoft Corporation                               */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function initializes the USB HID device receiver.              */
44 /*    This function is called by the class register function. It is only  */
45 /*    done once.                                                          */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    hid                                  Pointer to hid instance        */
50 /*    parameter                            Pointer to hid parameter       */
51 /*    receiver                             Pointer to fill pointer to     */
52 /*                                           allocated receiver instance  */
53 /*                                                                        */
54 /*  OUTPUT                                                                */
55 /*                                                                        */
56 /*    Completion Status                                                   */
57 /*                                                                        */
58 /*  CALLS                                                                 */
59 /*                                                                        */
60 /*    _ux_utility_memory_allocate           Allocate memory               */
61 /*    _ux_utility_memory_free               Free memory                   */
62 /*    _ux_utility_thread_create             Create thread                 */
63 /*    _ux_utility_thread_delete             Delete thread                 */
64 /*                                                                        */
65 /*  CALLED BY                                                             */
66 /*                                                                        */
67 /*    USBX Source Code                                                    */
68 /*                                                                        */
69 /*  RELEASE HISTORY                                                       */
70 /*                                                                        */
71 /*    DATE              NAME                      DESCRIPTION             */
72 /*                                                                        */
73 /*  01-31-2022     Chaoqiong Xiao           Initial Version 6.1.10        */
74 /*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
75 /*                                            added receiver callback,    */
76 /*                                            resulting in version 6.1.11 */
77 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
78 /*                                            added standalone receiver,  */
79 /*                                            resulting in version 6.1.12 */
80 /*                                                                        */
81 /**************************************************************************/
_ux_device_class_hid_receiver_initialize(UX_SLAVE_CLASS_HID * hid,UX_SLAVE_CLASS_HID_PARAMETER * parameter,UX_DEVICE_CLASS_HID_RECEIVER ** receiver)82 UINT  _ux_device_class_hid_receiver_initialize(UX_SLAVE_CLASS_HID *hid,
83                                     UX_SLAVE_CLASS_HID_PARAMETER *parameter,
84                                     UX_DEVICE_CLASS_HID_RECEIVER **receiver)
85 {
86 #if !defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT)
87     UX_PARAMETER_NOT_USED(hid);
88     UX_PARAMETER_NOT_USED(parameter);
89     UX_PARAMETER_NOT_USED(receiver);
90     return(UX_FUNCTION_NOT_SUPPORTED);
91 #else
92 ULONG                                   memory_size;
93 ULONG                                   events_size;
94 UCHAR                                   *memory_receiver;
95 UCHAR                                   *memory_events;
96 #if !defined(UX_DEVICE_STANDALONE)
97 UCHAR                                   *memory_stack;
98 #endif
99 UINT                                    status = UX_SUCCESS;
100 
101 
102     /* Validate parameters.  */
103     UX_ASSERT(parameter -> ux_device_class_hid_parameter_receiver_event_max_length <= UX_SLAVE_REQUEST_DATA_MAX_LENGTH);
104 
105     /* Allocate memory for receiver and receiver events.  */
106 
107     /* Memory of thread stack and receiver instance.  */
108 #if !defined(UX_DEVICE_STANDALONE)
109     UX_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG(UX_DEVICE_CLASS_HID_RECEIVER_THREAD_STACK_SIZE, sizeof(UX_DEVICE_CLASS_HID_RECEIVER)));
110     memory_size = UX_DEVICE_CLASS_HID_RECEIVER_THREAD_STACK_SIZE +
111                   sizeof(UX_DEVICE_CLASS_HID_RECEIVER);
112 #else
113     memory_size = sizeof(UX_DEVICE_CLASS_HID_RECEIVER);
114 #endif
115     UX_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG(parameter -> ux_device_class_hid_parameter_receiver_event_max_length, sizeof(ULONG)));
116 
117     /* Memory of events.  */
118     events_size  = parameter -> ux_device_class_hid_parameter_receiver_event_max_length + sizeof(ULONG);
119     UX_ASSERT(!UX_OVERFLOW_CHECK_MULV_ULONG(events_size, parameter -> ux_device_class_hid_parameter_receiver_event_max_number));
120     events_size *= parameter -> ux_device_class_hid_parameter_receiver_event_max_number;
121     UX_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG(memory_size, events_size));
122     memory_size += events_size;
123 
124     /* Allocate memory.  */
125     memory_receiver = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, memory_size);
126     if (memory_receiver == UX_NULL)
127         return(UX_MEMORY_INSUFFICIENT);
128 #if !defined(UX_DEVICE_STANDALONE)
129     memory_stack = memory_receiver + sizeof(UX_DEVICE_CLASS_HID_RECEIVER);
130     memory_events = memory_stack + UX_DEVICE_CLASS_HID_RECEIVER_THREAD_STACK_SIZE;
131 #else
132     memory_events = memory_receiver + sizeof(UX_DEVICE_CLASS_HID_RECEIVER);
133 #endif
134 
135     /* Store receiver instance pointer.  */
136     (*receiver) = (UX_DEVICE_CLASS_HID_RECEIVER *)memory_receiver;
137 
138 #if !defined(UX_DEVICE_STANDALONE)
139 
140     /* This instance needs to be running in a different thread. So start
141        a new thread. We pass a pointer to the class to the new thread.  This thread
142        does not start until we have a instance of the class. */
143     if (status == UX_SUCCESS)
144         status =  _ux_utility_thread_create(&(*receiver) -> ux_device_class_hid_receiver_thread,
145                     "ux_device_class_hid_receiver_thread",
146                     _ux_device_class_hid_receiver_thread,
147                     (ULONG) (ALIGN_TYPE) hid, (VOID *) memory_stack,
148                     UX_DEVICE_CLASS_HID_RECEIVER_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS,
149                     UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START);
150 #endif
151 
152     /* Check the creation of this thread.  */
153     if (status == UX_SUCCESS)
154     {
155 
156 #if !defined(UX_DEVICE_STANDALONE)
157         UX_THREAD_EXTENSION_PTR_SET(&((*receiver) -> ux_device_class_hid_receiver_thread), hid)
158 #else
159         hid -> ux_device_class_hid_read_state = UX_DEVICE_CLASS_HID_RECEIVER_START;
160         (*receiver) -> ux_device_class_hid_receiver_tasks_run = _ux_device_class_hid_receiver_tasks_run;
161 #endif
162 
163         /* Initialize event buffer size.  */
164         (*receiver) -> ux_device_class_hid_receiver_event_buffer_size =
165                     parameter -> ux_device_class_hid_parameter_receiver_event_max_length;
166 
167         /* Initialize events.  */
168         (*receiver) -> ux_device_class_hid_receiver_events =
169                         (UX_DEVICE_CLASS_HID_RECEIVED_EVENT *)(memory_events);
170         (*receiver) -> ux_device_class_hid_receiver_events_end =
171                         (UX_DEVICE_CLASS_HID_RECEIVED_EVENT *)(memory_receiver + memory_size);
172         (*receiver) -> ux_device_class_hid_receiver_event_read_pos =
173                     (*receiver) -> ux_device_class_hid_receiver_events;
174         (*receiver) -> ux_device_class_hid_receiver_event_save_pos =
175                     (*receiver) -> ux_device_class_hid_receiver_events;
176 
177         /* Initialize uninitialize function.  */
178         (*receiver) -> ux_device_class_hid_receiver_uninitialize = _ux_device_class_hid_receiver_uninitialize;
179 
180         /* Initialize callback function.  */
181         (*receiver) -> ux_device_class_hid_receiver_event_callback =
182                     parameter -> ux_device_class_hid_parameter_receiver_event_callback;
183 
184         /* Done success.  */
185         return(UX_SUCCESS);
186     }
187     else
188         status = (UX_THREAD_ERROR);
189 
190     /* Free allocated memory. */
191     _ux_utility_memory_free(*receiver);
192     (*receiver) =  UX_NULL;
193 
194     /* Return completion status.  */
195     return(status);
196 #endif
197 }
198