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