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