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
UX_OVERFLOW_CHECK_MULC_ULONG(UX_HOST_CLASS_HID_MAX_CLIENTS,sizeof (UX_HOST_CLASS_HID_CLIENT))32 UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG(UX_HOST_CLASS_HID_MAX_CLIENTS, sizeof(UX_HOST_CLASS_HID_CLIENT)), UX_HOST_CLASS_HID_MAX_CLIENTS_mem_alloc_ovf)
33
34 /**************************************************************************/
35 /* */
36 /* FUNCTION RELEASE */
37 /* */
38 /* _ux_host_class_hid_client_register PORTABLE C */
39 /* 6.1.12 */
40 /* AUTHOR */
41 /* */
42 /* Chaoqiong Xiao, Microsoft Corporation */
43 /* */
44 /* DESCRIPTION */
45 /* */
46 /* This function registers a USB HID client to the HID class. The */
47 /* mechanism is similar to the USB stack class registration. The Class */
48 /* must specify an entry point for the USB stack to send commands */
49 /* such as: */
50 /* */
51 /* UX_HOST_CLASS_COMMAND_QUERY */
52 /* UX_HOST_CLASS_COMMAND_ACTIVATE */
53 /* UX_HOST_CLASS_COMMAND_DESTROY */
54 /* */
55 /* Note: The C string of hid_client_name must be NULL-terminated and */
56 /* the length of it (without the NULL-terminator itself) must be no */
57 /* larger than UX_HOST_CLASS_HID_MAX_CLIENT_NAME_LENGTH. */
58 /* */
59 /* INPUT */
60 /* */
61 /* hid_client_name Name of HID client */
62 /* hid_client_handler Handler for HID client */
63 /* */
64 /* OUTPUT */
65 /* */
66 /* Completion Status */
67 /* */
68 /* CALLS */
69 /* */
70 /* _ux_host_stack_class_get Get class */
71 /* _ux_utility_memory_allocate Allocate memory block */
72 /* _ux_utility_memory_copy Copy memory block */
73 /* _ux_utility_string_length_check Check C string and return */
74 /* length if null-terminated */
75 /* */
76 /* CALLED BY */
77 /* */
78 /* Application */
79 /* HID Class */
80 /* */
81 /* RELEASE HISTORY */
82 /* */
83 /* DATE NAME DESCRIPTION */
84 /* */
85 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
86 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
87 /* verified memset and memcpy */
88 /* cases, */
89 /* resulting in version 6.1 */
90 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
91 /* fixed parameter/variable */
92 /* names conflict C++ keyword, */
93 /* resulting in version 6.1.12 */
94 /* */
95 /**************************************************************************/
96 UINT _ux_host_class_hid_client_register(UCHAR *hid_client_name,
97 UINT (*hid_client_handler)(struct UX_HOST_CLASS_HID_CLIENT_COMMAND_STRUCT *))
98 {
99
100 UX_HOST_CLASS *class_ptr;
101 ULONG hid_client_index;
102 UINT status;
103 UX_HOST_CLASS_HID_CLIENT *hid_client;
104 UINT client_name_length = 0;
105
106 /* If trace is enabled, insert this event into the trace buffer. */
107 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_CLIENT_REGISTER, hid_client_name, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
108
109 /* Get the length of the client name (exclude null-terminator). */
110 status = _ux_utility_string_length_check(hid_client_name, &client_name_length, UX_HOST_CLASS_HID_MAX_CLIENT_NAME_LENGTH);
111 if (status)
112 return(status);
113
114 /* We need to locate our class container. */
115 status = _ux_host_stack_class_get(_ux_system_host_class_hid_name, &class_ptr);
116
117 /* If we cannot get the class container, it means the HID class was not registered. */
118 if (status != UX_SUCCESS)
119 return(status);
120
121 /* From the class container, we get the client pointer which has the list of
122 HID clients. If the pointer is NULL, the client list was not assigned. */
123 if (class_ptr -> ux_host_class_client == UX_NULL)
124 {
125
126 /* Allocate memory for the class client.
127 * Allocate size overflow static checked outside the function.
128 */
129 class_ptr -> ux_host_class_client = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY,
130 sizeof(UX_HOST_CLASS_HID_CLIENT)*UX_HOST_CLASS_HID_MAX_CLIENTS);
131
132 /* Check for successful allocation. */
133 if (class_ptr -> ux_host_class_client == UX_NULL)
134 return(UX_MEMORY_INSUFFICIENT);
135 }
136
137 /* De-reference the client pointer into a HID client array pointer. */
138 hid_client = (UX_HOST_CLASS_HID_CLIENT *) class_ptr -> ux_host_class_client;
139
140 /* We need to parse the HID client handler table to find an empty spot. */
141 for (hid_client_index = 0; hid_client_index < UX_HOST_CLASS_HID_MAX_CLIENTS; hid_client_index++)
142 {
143
144 /* Check if this HID client is already used. */
145 if (hid_client -> ux_host_class_hid_client_status == UX_UNUSED)
146 {
147
148 /* We have found a free container for the HID client. Copy the name (with null-terminator). */
149 _ux_utility_memory_copy(hid_client -> ux_host_class_hid_client_name, hid_client_name, client_name_length + 1); /* Use case of memcpy is verified. */
150
151 /* Memorize the handler address of this client. */
152 hid_client -> ux_host_class_hid_client_handler = hid_client_handler;
153
154 /* Mark it as being in use. */
155 hid_client -> ux_host_class_hid_client_status = UX_USED;
156
157 /* Return successful completion. */
158 return(UX_SUCCESS);
159 }
160 else
161 {
162
163 /* Do a sanity check to make sure the handler is not already installed by
164 mistake. To verify this, we simple check for the handler entry point. */
165 if (hid_client -> ux_host_class_hid_client_handler == hid_client_handler)
166 {
167
168 /* Error trap. */
169 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_ALREADY_INSTALLED);
170
171 /* If trace is enabled, insert this event into the trace buffer. */
172 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_ALREADY_INSTALLED, hid_client_name, 0, 0, UX_TRACE_ERRORS, 0, 0)
173
174 return(UX_HOST_CLASS_ALREADY_INSTALLED);
175 }
176 }
177
178 /* Try the next class. */
179 hid_client++;
180 }
181
182 /* Error trap. */
183 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_ARRAY_FULL);
184
185 /* If trace is enabled, insert this event into the trace buffer. */
186 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_ARRAY_FULL, hid_client_name, 0, 0, UX_TRACE_ERRORS, 0, 0)
187
188 /* No more entries in the class table. */
189 return(UX_MEMORY_ARRAY_FULL);
190 }
191
192