1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** USBX Component                                                        */
16 /**                                                                       */
17 /**   HID Class                                                           */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 
23 /* Include necessary system files.  */
24 
25 #define UX_SOURCE_CODE
26 
27 #include "ux_api.h"
28 #include "ux_host_class_hid.h"
29 #include "ux_host_stack.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _ux_host_class_hid_activate                         PORTABLE C      */
37 /*                                                           6.1.12       */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function performs the enumeration of the HID class.            */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    command                               Pointer to command            */
49 /*                                                                        */
50 /*  OUTPUT                                                                */
51 /*                                                                        */
52 /*    Completion Status                                                   */
53 /*                                                                        */
54 /*  CALLS                                                                 */
55 /*                                                                        */
56 /*    _ux_host_class_hid_client_search      HID client search             */
57 /*    _ux_host_class_hid_configure          Configure HID                 */
58 /*    _ux_host_class_hid_descriptor_parse   Parse descriptor              */
59 /*    _ux_host_class_hid_interrupt_endpoint_search  Search endpoint       */
60 /*    _ux_host_class_hid_instance_clean     Clean up instance resources   */
61 /*    _ux_host_stack_class_instance_create  Create class instance         */
62 /*    _ux_host_stack_class_instance_destroy Destroy class instance        */
63 /*    _ux_utility_memory_allocate           Allocate memory block         */
64 /*    _ux_utility_memory_free               Free memory                   */
65 /*    _ux_host_semaphore_create             Create semaphore              */
66 /*                                                                        */
67 /*  CALLED BY                                                             */
68 /*                                                                        */
69 /*    HID Class                                                           */
70 /*                                                                        */
71 /*  RELEASE HISTORY                                                       */
72 /*                                                                        */
73 /*    DATE              NAME                      DESCRIPTION             */
74 /*                                                                        */
75 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
76 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
77 /*                                            resulting in version 6.1    */
78 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
79 /*                                            added standalone support,   */
80 /*                                            resulting in version 6.1.10 */
81 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
82 /*                                            fixed parameter/variable    */
83 /*                                            names conflict C++ keyword, */
84 /*                                            resulting in version 6.1.12 */
85 /*                                                                        */
86 /**************************************************************************/
_ux_host_class_hid_activate(UX_HOST_CLASS_COMMAND * command)87 UINT  _ux_host_class_hid_activate(UX_HOST_CLASS_COMMAND  *command)
88 {
89 
90 UX_INTERFACE        *interface_ptr;
91 UX_HOST_CLASS_HID   *hid;
92 UINT                status;
93 
94 
95     /* The HID is always activated by the interface descriptor and not the
96        device descriptor.  */
97     interface_ptr =  (UX_INTERFACE *) command -> ux_host_class_command_container;
98 
99     /* Instantiate this HID class */
100     hid =  _ux_utility_memory_allocate(UX_NO_ALIGN,  UX_REGULAR_MEMORY,sizeof(UX_HOST_CLASS_HID));
101     if (hid == UX_NULL)
102         return(UX_MEMORY_INSUFFICIENT);
103 
104     /* Store the class container into this instance.  */
105     hid -> ux_host_class_hid_class =  command -> ux_host_class_command_class_ptr;
106 
107     /* Store the interface container into the HID class instance.  */
108     hid -> ux_host_class_hid_interface =  interface_ptr;
109 
110     /* Store the device container into the HID class instance.  */
111     hid -> ux_host_class_hid_device =  interface_ptr -> ux_interface_configuration -> ux_configuration_device;
112 
113     /* This instance of the device must also be stored in the interface container.  */
114     interface_ptr -> ux_interface_class_instance =  (VOID *) hid;
115 
116     /* Create this class instance.  */
117     _ux_host_stack_class_instance_create(command -> ux_host_class_command_class_ptr, (VOID *) hid);
118 
119 #if defined(UX_HOST_STANDALONE)
120 
121     /* Set class tasks function.  */
122     hid -> ux_host_class_hid_class -> ux_host_class_task_function = _ux_host_class_hid_tasks_run;
123 
124     /* Set activate state to first step.  */
125     hid -> ux_host_class_hid_enum_state = UX_STATE_WAIT;
126 
127     status = UX_SUCCESS;
128     return(status);
129 #else
130 
131     /* Configure the HID.  */
132     status =  _ux_host_class_hid_configure(hid);
133 
134     /* If configure is done success, goes on. */
135     if (status == UX_SUCCESS)
136     {
137 
138         /* Get the HID descriptor and parse it.  */
139         status =  _ux_host_class_hid_descriptor_parse(hid);
140     }
141 
142     /* If HID descriptor parse is done success, goes on. */
143     if (status == UX_SUCCESS)
144     {
145 
146         /* Search the HID interrupt endpoint but do not start it.  */
147         status =  _ux_host_class_hid_interrupt_endpoint_search(hid);
148     }
149 
150     /* If HID interrupt endpoint is found, goes on. */
151     if (status == UX_SUCCESS)
152     {
153 
154         /* Create the semaphore to protect multiple threads from accessing the same
155         storage instance.  */
156         status =  _ux_host_semaphore_create(&hid -> ux_host_class_hid_semaphore, "ux_host_class_hid_semaphore", 1);
157 
158         if (status == UX_SUCCESS)
159         {
160 
161             /* If all is fine, try to locate the HID client for this HID device.  */
162             _ux_host_class_hid_client_search(hid);
163 
164             /* Mark the HID class as live now.  */
165             hid -> ux_host_class_hid_state =  UX_HOST_CLASS_INSTANCE_LIVE;
166 
167             /* We may need to inform the application if a function has been programmed in the system structure.  */
168             if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
169             {
170 
171                 /* Call system change function.  */
172                 _ux_system_host ->  ux_system_host_change_function(UX_DEVICE_INSERTION, hid -> ux_host_class_hid_class, (VOID *) hid);
173             }
174 
175             /* If trace is enabled, insert this event into the trace buffer.  */
176             UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_ACTIVATE, hid, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
177 
178             /* If trace is enabled, register this object.  */
179             UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, hid, 0, 0, 0)
180 
181             /* Return completion code.  */
182             return(status);
183         }
184         else
185         {
186             status = UX_SEMAPHORE_ERROR;
187         }
188     }
189 
190     /* Clean interrupt endpoint.  */
191     if (hid -> ux_host_class_hid_interrupt_endpoint &&
192         hid -> ux_host_class_hid_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer)
193         _ux_utility_memory_free(hid -> ux_host_class_hid_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer);
194 
195     /* Clean instance. */
196     _ux_host_class_hid_instance_clean(hid);
197 
198     /* Error, destroy the class instance and return error code. */
199     _ux_host_stack_class_instance_destroy(hid -> ux_host_class_hid_class, (VOID *) hid);
200 
201     /* Unmount instance. */
202     interface_ptr -> ux_interface_class_instance = UX_NULL;
203 
204     /* Free instance. */
205     _ux_utility_memory_free(hid);
206 
207     /* Return error code. */
208     return(status);
209 
210 #endif
211 }
212 
213