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 /** USBX Component                                                        */
16 /**                                                                       */
17 /**   Device HID Class                                                    */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define UX_SOURCE_CODE
23 
24 
25 /* Include necessary system files.  */
26 
27 #include "ux_api.h"
28 #include "ux_device_class_hid.h"
29 #include "ux_device_stack.h"
30 
31 
32 #if defined(UX_DEVICE_STANDALONE)
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _ux_device_class_hid_tasks_run                      PORTABLE C      */
38 /*                                                           6.1.10       */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Chaoqiong Xiao, Microsoft Corporation                               */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function is the background task of the hid.                    */
46 /*                                                                        */
47 /*    It's for standalone mode.                                           */
48 /*                                                                        */
49 /*  INPUT                                                                 */
50 /*                                                                        */
51 /*    hid_class                                 Address of hid class      */
52 /*                                                container               */
53 /*                                                                        */
54 /*  OUTPUT                                                                */
55 /*                                                                        */
56 /*    State machine status                                                */
57 /*    UX_STATE_EXIT                         Device not configured         */
58 /*    UX_STATE_IDLE                         No interrupt transfer running */
59 /*    UX_STATE_WAIT                         Interrupt IN transfer running */
60 /*                                                                        */
61 /*  CALLS                                                                 */
62 /*                                                                        */
63 /*    _ux_device_class_hid_event_get        Get HID event                 */
64 /*    _ux_device_stack_transfer_run         Run transfer state machine    */
65 /*    _ux_utility_memory_copy               Copy memory                   */
66 /*                                                                        */
67 /*  CALLED BY                                                             */
68 /*                                                                        */
69 /*    USBX Device Stack                                                   */
70 /*                                                                        */
71 /*  RELEASE HISTORY                                                       */
72 /*                                                                        */
73 /*    DATE              NAME                      DESCRIPTION             */
74 /*                                                                        */
75 /*  01-31-2022     Chaoqiong Xiao           Initial Version 6.1.10        */
76 /*                                                                        */
77 /**************************************************************************/
_ux_device_class_hid_tasks_run(VOID * instance)78 UINT _ux_device_class_hid_tasks_run(VOID *instance)
79 {
80 
81 UX_SLAVE_CLASS_HID          *hid;
82 UX_SLAVE_DEVICE             *device;
83 UX_SLAVE_CLASS_HID_EVENT    *hid_event;
84 UX_SLAVE_TRANSFER           *trans;
85 ULONG                       tick, elapsed;
86 UINT                        status;
87 
88 
89     /* Get HID instance.  */
90     hid = (UX_SLAVE_CLASS_HID *) instance;
91 
92     /* Get the pointer to the device.  */
93     device =  &_ux_system_slave -> ux_system_slave_device;
94 
95     /* Check if the device is configured.  */
96     if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
97     {
98         hid -> ux_device_class_hid_event_state = UX_STATE_EXIT;
99         return(UX_STATE_EXIT);
100     }
101 
102 #if defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT)
103     if (hid -> ux_device_class_hid_receiver)
104         hid -> ux_device_class_hid_receiver -> ux_device_class_hid_receiver_tasks_run(hid);
105 #endif
106 
107     /* Run HID state machine.  */
108     switch(hid -> ux_device_class_hid_event_state)
109     {
110     case UX_STATE_EXIT:
111 
112         /* There is nothing to do in this state.  */
113         return (UX_STATE_EXIT);
114 
115     case UX_STATE_RESET:
116 
117         /* Start timeout waiting.  */
118         hid -> ux_device_class_hid_event_wait_start = _ux_utility_time_get();
119         hid -> ux_device_class_hid_event_state = UX_STATE_IDLE;
120 
121         /* Fall through.  */
122     case UX_STATE_IDLE:
123 
124         /* Check if there is event ready.  */
125         hid_event = &hid -> ux_device_class_hid_event;
126         status = _ux_device_class_hid_event_get(hid, hid_event);
127 
128         /* If there is no event, check idle rate.  */
129         if (status != UX_SUCCESS)
130         {
131 
132             /* Check idle rate setting.  */
133             if (hid -> ux_device_class_hid_event_wait_timeout == UX_WAIT_FOREVER)
134             {
135 
136                 /* There is no background idle report, keep waiting.  */
137                 return(UX_STATE_IDLE);
138             }
139 
140             /* Check wait timeout.  */
141             tick = _ux_utility_time_get();
142             elapsed = _ux_utility_time_elapsed(hid -> ux_device_class_hid_event_wait_start, tick);
143             if (elapsed < hid -> ux_device_class_hid_event_wait_timeout)
144             {
145 
146                 /* Keep waiting.  */
147                 return(UX_STATE_IDLE);
148             }
149 
150             /* Send the last event in buffer.  */
151         }
152 
153         /* Prepare the request to send event.  */
154         trans = &hid -> ux_device_class_hid_interrupt_endpoint ->
155                                             ux_slave_endpoint_transfer_request;
156         _ux_utility_memory_copy(trans -> ux_slave_transfer_request_data_pointer,
157                                 hid_event -> ux_device_class_hid_event_buffer,
158                                 hid_event -> ux_device_class_hid_event_length); /* Use case of memcpy is verified. */
159         trans -> ux_slave_transfer_request_requested_length =
160                                 hid_event -> ux_device_class_hid_event_length;
161         UX_SLAVE_TRANSFER_STATE_RESET(trans);
162         hid -> ux_device_class_hid_event_state = UX_STATE_WAIT;
163 
164         /* Fall through.  */
165     case UX_STATE_WAIT:
166 
167         /* Run transfer state machine.  */
168         trans = &hid -> ux_device_class_hid_interrupt_endpoint ->
169                                             ux_slave_endpoint_transfer_request;
170         hid_event = &hid -> ux_device_class_hid_event;
171         status = _ux_device_stack_transfer_run(trans,
172                                 hid_event -> ux_device_class_hid_event_length,
173                                 hid_event -> ux_device_class_hid_event_length);
174 
175         /* Any error or success case.  */
176         if (status <= UX_STATE_NEXT)
177         {
178 
179             /* Next round.  */
180             hid -> ux_device_class_hid_event_state = UX_STATE_RESET;
181             return(UX_STATE_IDLE);
182         }
183 
184         /* Wait.  */
185         return(UX_STATE_WAIT);
186 
187     default:
188 
189         /* Just go back to normal state.  */
190         hid -> ux_device_class_hid_event_state = UX_STATE_RESET;
191         return(UX_STATE_IDLE);
192     }
193 }
194 #endif
195