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 Keyboard Client */
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_class_hid_keyboard.h"
31 #include "ux_host_stack.h"
32
33
34 #if defined(UX_HOST_STANDALONE)
35
36 #define UX_HOST_CLASS_HID_KEYBOARD_ENUM_START (UX_STATE_WAIT)
37 #define UX_HOST_CLASS_HID_KEYBOARD_ENUM_SET_REPORT (UX_STATE_STACK_STEP + 0)
38 #define UX_HOST_CLASS_HID_KEYBOARD_ENUM_SET_IDLE (UX_STATE_STACK_STEP + 1)
39 #define UX_HOST_CLASS_HID_KEYBOARD_ENUM_CMD_WAIT (UX_STATE_STACK_STEP + 2)
40 #define UX_HOST_CLASS_HID_KEYBOARD_ENUM_PERIODIC_START (UX_STATE_STACK_STEP + 3)
41 #define UX_HOST_CLASS_HID_KEYBOARD_ENUM_DONE (UX_STATE_STACK_STEP + 4)
42
43
44 static inline UINT _ux_host_class_hid_keyboard_activate_wait(UX_HOST_CLASS_HID_CLIENT_COMMAND *command);
45 #endif
46
47
48 /**************************************************************************/
49 /* */
50 /* FUNCTION RELEASE */
51 /* */
52 /* _ux_host_class_hid_keyboard_entry PORTABLE C */
53 /* 6.1.10 */
54 /* AUTHOR */
55 /* */
56 /* Chaoqiong Xiao, Microsoft Corporation */
57 /* */
58 /* DESCRIPTION */
59 /* */
60 /* This function is the entry point of the HID keyboard client. */
61 /* This function is called by the HID class after it has parsed a new */
62 /* HID report descriptor and is searching for a HID client. */
63 /* */
64 /* INPUT */
65 /* */
66 /* command Pointer to command */
67 /* */
68 /* OUTPUT */
69 /* */
70 /* Completion Status */
71 /* */
72 /* CALLS */
73 /* */
74 /* _ux_host_class_hid_keyboard_activate */
75 /* Activate HID keyboard */
76 /* _ux_host_class_hid_keyboard_deactivate */
77 /* Deactivate HID keyboard */
78 /* */
79 /* CALLED BY */
80 /* */
81 /* HID Class */
82 /* */
83 /* RELEASE HISTORY */
84 /* */
85 /* DATE NAME DESCRIPTION */
86 /* */
87 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
88 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
89 /* resulting in version 6.1 */
90 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
91 /* added standalone support, */
92 /* resulting in version 6.1.10 */
93 /* */
94 /**************************************************************************/
_ux_host_class_hid_keyboard_entry(UX_HOST_CLASS_HID_CLIENT_COMMAND * command)95 UINT _ux_host_class_hid_keyboard_entry(UX_HOST_CLASS_HID_CLIENT_COMMAND *command)
96 {
97
98 UINT status;
99
100
101 /* The command request will tell us we need to do here, either a enumeration
102 query, an activation or a deactivation. */
103 switch (command -> ux_host_class_hid_client_command_request)
104 {
105
106
107 case UX_HOST_CLASS_COMMAND_QUERY:
108
109 /* The query command is used to let the HID class know if we want to own
110 this device or not */
111 if ((command -> ux_host_class_hid_client_command_page == UX_HOST_CLASS_HID_PAGE_GENERIC_DESKTOP_CONTROLS) &&
112 (command -> ux_host_class_hid_client_command_usage == UX_HOST_CLASS_HID_GENERIC_DESKTOP_KEYBOARD))
113 return(UX_SUCCESS);
114 else
115 return(UX_NO_CLASS_MATCH);
116
117
118 case UX_HOST_CLASS_COMMAND_ACTIVATE:
119
120 /* The activate command is used by the HID class to start the HID client. */
121 status = _ux_host_class_hid_keyboard_activate(command);
122
123 /* Return completion status. */
124 return(status);
125
126
127 #if defined(UX_HOST_STANDALONE)
128 case UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT:
129
130 return(_ux_host_class_hid_keyboard_activate_wait(command));
131 #endif
132
133
134 case UX_HOST_CLASS_COMMAND_DEACTIVATE:
135
136 /* The deactivate command is used by the HID class when it received a deactivate
137 command from the USBX stack and there was a HID client attached to the HID instance */
138 status = _ux_host_class_hid_keyboard_deactivate(command);
139
140 /* Return completion status. */
141 return(status);
142 }
143
144 /* Return error status. */
145 return(UX_ERROR);
146 }
147
148 #if defined(UX_HOST_STANDALONE)
_ux_host_class_hid_keyboard_activate_wait(UX_HOST_CLASS_HID_CLIENT_COMMAND * command)149 static inline UINT _ux_host_class_hid_keyboard_activate_wait(UX_HOST_CLASS_HID_CLIENT_COMMAND *command)
150 {
151
152 UX_HOST_CLASS_HID *hid;
153 UX_HOST_CLASS_HID_CLIENT *hid_client;
154 UX_HOST_CLASS_HID_KEYBOARD *keyboard;
155 UINT status;
156
157 /* Get the instance to the HID class. */
158 hid = command -> ux_host_class_hid_client_command_instance;
159
160 /* And of the HID client. */
161 hid_client = hid -> ux_host_class_hid_client;
162
163 /* And of the keyboard instance. */
164 keyboard = (UX_HOST_CLASS_HID_KEYBOARD *) hid_client -> ux_host_class_hid_client_local_instance;
165
166 /* Run states. */
167 switch(keyboard -> ux_host_class_hid_keyboard_enum_state)
168 {
169 case UX_HOST_CLASS_HID_KEYBOARD_ENUM_START:
170 /* Fall through. */
171 case UX_HOST_CLASS_HID_KEYBOARD_ENUM_SET_REPORT:
172
173 /* Update LED in task. */
174 keyboard -> ux_host_class_hid_keyboard_out_state = UX_STATE_WAIT;
175 keyboard -> ux_host_class_hid_keyboard_enum_state =
176 UX_HOST_CLASS_HID_KEYBOARD_ENUM_CMD_WAIT;
177 keyboard -> ux_host_class_hid_keyboard_next_state =
178 UX_HOST_CLASS_HID_KEYBOARD_ENUM_SET_IDLE;
179 return(UX_STATE_WAIT);
180
181 case UX_HOST_CLASS_HID_KEYBOARD_ENUM_CMD_WAIT:
182
183 /* LEDs processed in background task. */
184 if (keyboard -> ux_host_class_hid_keyboard_out_state != UX_STATE_WAIT)
185 {
186 if (keyboard -> ux_host_class_hid_keyboard_status != UX_SUCCESS)
187 keyboard -> ux_host_class_hid_keyboard_enum_state =
188 UX_HOST_CLASS_HID_KEYBOARD_ENUM_DONE;
189 else
190 keyboard -> ux_host_class_hid_keyboard_enum_state =
191 keyboard -> ux_host_class_hid_keyboard_next_state;
192 }
193 return(UX_STATE_WAIT);
194
195 case UX_HOST_CLASS_HID_KEYBOARD_ENUM_SET_IDLE:
196
197 /* Run SET_IDLE states. */
198 status = _ux_host_class_hid_idle_set_run(hid, 0,
199 keyboard -> ux_host_class_hid_keyboard_id);
200 if (status < UX_STATE_WAIT)
201 {
202 keyboard -> ux_host_class_hid_keyboard_status =
203 hid -> ux_host_class_hid_status;
204
205 /* Set_Idle is mandatory, if there is error enum fail. */
206 if (keyboard -> ux_host_class_hid_keyboard_status == UX_SUCCESS)
207 keyboard -> ux_host_class_hid_keyboard_enum_state =
208 UX_HOST_CLASS_HID_KEYBOARD_ENUM_PERIODIC_START;
209 else
210 keyboard -> ux_host_class_hid_keyboard_enum_state =
211 UX_HOST_CLASS_HID_KEYBOARD_ENUM_DONE;
212
213 }
214 return(UX_STATE_WAIT);
215
216 case UX_HOST_CLASS_HID_KEYBOARD_ENUM_PERIODIC_START:
217
218 /* Start the periodic report. */
219 status = _ux_host_class_hid_periodic_report_start(hid);
220 keyboard -> ux_host_class_hid_keyboard_status = status;
221
222 /* Fall through. */
223 case UX_HOST_CLASS_HID_KEYBOARD_ENUM_DONE:
224
225 /* Anything failed, Free resources. */
226 if (keyboard -> ux_host_class_hid_keyboard_status != UX_SUCCESS)
227 {
228
229 /* Detach instance. */
230 hid_client -> ux_host_class_hid_client_local_instance = UX_NULL;
231
232 /* Free usage state. */
233 if (keyboard -> ux_host_class_hid_keyboard_key_state)
234 _ux_utility_memory_free(keyboard -> ux_host_class_hid_keyboard_key_state);
235
236 /* Free usage array. */
237 if (keyboard -> ux_host_class_hid_keyboard_usage_array)
238 _ux_utility_memory_free(keyboard -> ux_host_class_hid_keyboard_usage_array);
239
240 /* Free instance. */
241 _ux_utility_memory_free(keyboard);
242
243 return(UX_STATE_ERROR);
244 }
245
246 /* Now keyboard instance is live. */
247 keyboard -> ux_host_class_hid_keyboard_state = UX_HOST_CLASS_INSTANCE_LIVE;
248
249 /* If all is fine and the device is mounted, we may need to inform the application
250 if a function has been programmed in the system structure. */
251 if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
252 {
253
254 /* Call system change function. */
255 _ux_system_host -> ux_system_host_change_function(UX_HID_CLIENT_INSERTION, hid -> ux_host_class_hid_class, (VOID *) hid_client);
256 }
257
258 /* If trace is enabled, insert this event into the trace buffer. */
259 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_KEYBOARD_ACTIVATE, hid, keyboard, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
260
261 /* Enumeration idle. */
262 keyboard -> ux_host_class_hid_keyboard_enum_state = UX_STATE_IDLE;
263 return(UX_STATE_NEXT);
264
265 default: /* IDLE, Other states. */
266 return(UX_STATE_NEXT);
267 }
268 }
269 #endif
270