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_deactivate PORTABLE C */
37 /* 6.1.10 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function is called when this instance of the HID has been */
45 /* removed from the bus either directly or indirectly. The interrupt */
46 /* pipe will be destroyed and the instanced removed. */
47 /* */
48 /* INPUT */
49 /* */
50 /* command Pointer to command */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* Completion Status */
55 /* */
56 /* CALLS */
57 /* */
58 /* (ux_host_class_hid_client_handler) HID client handler */
59 /* _ux_host_class_hid_instance_clean HID instance clean */
60 /* _ux_host_stack_class_instance_destroy Destroy the class instance */
61 /* _ux_host_stack_endpoint_transfer_abort */
62 /* Abort transfer */
63 /* _ux_utility_memory_free Release memory block */
64 /* _ux_host_semaphore_delete Delete semaphore */
65 /* _ux_host_semaphore_get Get semaphore */
66 /* _ux_utility_thread_schedule_other Schedule other threads */
67 /* */
68 /* CALLED BY */
69 /* */
70 /* HID Class */
71 /* */
72 /* RELEASE HISTORY */
73 /* */
74 /* DATE NAME DESCRIPTION */
75 /* */
76 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
77 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
78 /* resulting in version 6.1 */
79 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
80 /* added standalone support, */
81 /* resulting in version 6.1.10 */
82 /* */
83 /**************************************************************************/
_ux_host_class_hid_deactivate(UX_HOST_CLASS_COMMAND * command)84 UINT _ux_host_class_hid_deactivate(UX_HOST_CLASS_COMMAND *command)
85 {
86
87 UX_HOST_CLASS_HID *hid;
88 UX_HOST_CLASS_HID_CLIENT_COMMAND hid_client_command;
89 UX_TRANSFER *transfer_request;
90 #if !defined(UX_HOST_STANDALONE)
91 UINT status;
92 #endif
93
94
95 /* Get the instance for this class. */
96 hid = (UX_HOST_CLASS_HID *) command -> ux_host_class_command_instance;
97
98 /* The HID is being shut down. */
99 hid -> ux_host_class_hid_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN;
100
101 #if !defined(UX_HOST_STANDALONE)
102
103 /* Protect thread reentry to this instance. */
104 status = _ux_host_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER);
105 if (status != UX_SUCCESS)
106
107 /* Return error. */
108 return(status);
109 #endif
110
111 #if defined(UX_HOST_STANDALONE)
112 if (hid -> ux_host_class_hid_interrupt_endpoint)
113 #endif
114 {
115
116 /* We need to abort transactions on the interrupt pipe. */
117 _ux_host_stack_endpoint_transfer_abort(hid -> ux_host_class_hid_interrupt_endpoint);
118
119 /* If the Hid class instance has a interrupt pipe with a data payload associated with it
120 it must be freed. */
121 transfer_request = &hid -> ux_host_class_hid_interrupt_endpoint -> ux_endpoint_transfer_request;
122
123 /* Then de allocate the memory. */
124 _ux_utility_memory_free(transfer_request -> ux_transfer_request_data_pointer);
125 }
126
127 #if defined(UX_HOST_STANDALONE)
128 if (hid -> ux_host_class_hid_allocated)
129 _ux_utility_memory_free(hid -> ux_host_class_hid_allocated);
130 #endif
131
132 /* We need to inform the HID client, if any, of the deactivation. */
133 hid_client_command.ux_host_class_hid_client_command_instance = (VOID *) hid;
134 hid_client_command.ux_host_class_hid_client_command_container = (VOID *) hid -> ux_host_class_hid_class;
135 hid_client_command.ux_host_class_hid_client_command_request = UX_HOST_CLASS_COMMAND_DEACTIVATE;
136
137 /* Call the HID client with a deactivate command if there was a client registered. */
138 if (hid -> ux_host_class_hid_client != UX_NULL)
139 hid -> ux_host_class_hid_client -> ux_host_class_hid_client_handler(&hid_client_command);
140
141 /* Clean all the HID memory fields. */
142 _ux_host_class_hid_instance_clean(hid);
143
144 /* The enumeration thread needs to sleep a while to allow the application or the class that may be using
145 endpoints to exit properly. */
146 _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM);
147
148 /* Destroy the instance. */
149 _ux_host_stack_class_instance_destroy(hid -> ux_host_class_hid_class, (VOID *) hid);
150
151 /* Destroy the semaphore. */
152 _ux_host_semaphore_delete(&hid -> ux_host_class_hid_semaphore);
153
154 /* Before we free the device resources, we need to inform the application
155 that the device is removed. */
156 if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
157 {
158
159 /* Inform the application the device is removed. */
160 _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, hid -> ux_host_class_hid_class, (VOID *) hid);
161 }
162
163 /* If trace is enabled, insert this event into the trace buffer. */
164 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_DEACTIVATE, hid, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
165
166 /* If trace is enabled, register this object. */
167 UX_TRACE_OBJECT_UNREGISTER(hid);
168
169 /* The HID is now free again. */
170 _ux_utility_memory_free(hid);
171
172 /* Return successful completion. */
173 return(UX_SUCCESS);
174 }
175
176