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_CLASS_HID_INTERRUPT_OUT_SUPPORT) && defined(UX_DEVICE_STANDALONE) 33 /**************************************************************************/ 34 /* */ 35 /* FUNCTION RELEASE */ 36 /* */ 37 /* _ux_device_class_hid_receiver_tasks_run PORTABLE C */ 38 /* 6.1.12 */ 39 /* AUTHOR */ 40 /* */ 41 /* Chaoqiong Xiao, Microsoft Corporation */ 42 /* */ 43 /* DESCRIPTION */ 44 /* */ 45 /* This function is task function of the hid interrupt OUT endpoint. */ 46 /* It's for standalone mode. */ 47 /* */ 48 /* INPUT */ 49 /* */ 50 /* hid HID instance */ 51 /* */ 52 /* OUTPUT */ 53 /* */ 54 /* None */ 55 /* */ 56 /* CALLS */ 57 /* */ 58 /* _ux_device_stack_transfer_run Request transfer */ 59 /* _ux_utility_memory_copy Copy memory */ 60 /* */ 61 /* CALLED BY */ 62 /* */ 63 /* USBX Device HID */ 64 /* */ 65 /* RELEASE HISTORY */ 66 /* */ 67 /* DATE NAME DESCRIPTION */ 68 /* */ 69 /* 07-29-2022 Chaoqiong Xiao Initial Version 6.1.12 */ 70 /* */ 71 /**************************************************************************/ _ux_device_class_hid_receiver_tasks_run(UX_SLAVE_CLASS_HID * hid)72UINT _ux_device_class_hid_receiver_tasks_run(UX_SLAVE_CLASS_HID *hid) 73 { 74 75 UX_SLAVE_DEVICE *device; 76 UX_DEVICE_CLASS_HID_RECEIVER *receiver; 77 UX_DEVICE_CLASS_HID_RECEIVED_EVENT *pos; 78 UCHAR *next_pos; 79 UX_SLAVE_ENDPOINT *endpoint; 80 UX_SLAVE_TRANSFER *transfer; 81 UINT status; 82 UCHAR *buffer; 83 ULONG temp; 84 85 86 /* Get the pointer to the device. */ 87 device = &_ux_system_slave -> ux_system_slave_device; 88 89 /* Check device state. */ 90 if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) 91 return(UX_STATE_EXIT); 92 93 /* Get receiver instance. */ 94 receiver = hid -> ux_device_class_hid_receiver; 95 if (receiver == UX_NULL) 96 return(UX_STATE_EXIT); 97 98 /* Get endpoint. */ 99 endpoint = hid -> ux_device_class_hid_read_endpoint; 100 if (endpoint == UX_NULL) 101 return(UX_STATE_EXIT); 102 103 /* Event buffer available, issue request to get data. */ 104 transfer = &endpoint -> ux_slave_endpoint_transfer_request; 105 106 /* Run read/receiver states. */ 107 switch(hid -> ux_device_class_hid_read_state) 108 { 109 case UX_DEVICE_CLASS_HID_RECEIVER_START: 110 111 /* Check if there is buffer available. */ 112 pos = receiver -> ux_device_class_hid_receiver_event_save_pos; 113 if (pos -> ux_device_class_hid_received_event_length != 0) 114 { 115 116 /* Buffer is full, keep waiting. */ 117 return(UX_STATE_IDLE); 118 } 119 120 /* Set request length. */ 121 hid -> ux_device_class_hid_read_requested_length = 122 receiver -> ux_device_class_hid_receiver_event_buffer_size; 123 124 /* Move state. */ 125 hid -> ux_device_class_hid_read_state = UX_DEVICE_CLASS_HID_RECEIVER_WAIT; 126 127 /* Fall through. */ 128 case UX_DEVICE_CLASS_HID_RECEIVER_WAIT: 129 130 /* Send the request to the device controller. */ 131 status = _ux_device_stack_transfer_run(transfer, 132 hid -> ux_device_class_hid_read_requested_length, 133 hid -> ux_device_class_hid_read_requested_length); 134 135 /* Error case. */ 136 if (status < UX_STATE_NEXT) 137 { 138 139 hid -> ux_device_class_hid_read_state = UX_DEVICE_CLASS_HID_RECEIVER_ERROR; 140 hid -> ux_device_class_hid_read_status = 141 transfer -> ux_slave_transfer_request_completion_code; 142 return(UX_STATE_ERROR); 143 } 144 145 /* Success case. */ 146 if (status == UX_STATE_NEXT) 147 { 148 149 /* Ignore ZLP case. */ 150 if (transfer -> ux_slave_transfer_request_actual_length == 0) 151 { 152 153 /* Restart receiving. */ 154 hid -> ux_device_class_hid_read_state = UX_DEVICE_CLASS_HID_RECEIVER_START; 155 return(UX_STATE_NEXT); 156 } 157 158 /* Save received event data and length. */ 159 pos = receiver -> ux_device_class_hid_receiver_event_save_pos; 160 buffer = (UCHAR *)&pos -> ux_device_class_hid_received_event_data; 161 temp = transfer -> ux_slave_transfer_request_actual_length; 162 _ux_utility_memory_copy(buffer, 163 transfer -> ux_slave_transfer_request_data_pointer, 164 temp); /* Use case of memcpy is verified. */ 165 166 /* Advance the save position. */ 167 next_pos = (UCHAR *)pos + receiver -> ux_device_class_hid_receiver_event_buffer_size + sizeof(ULONG); 168 if (next_pos >= (UCHAR *)receiver -> ux_device_class_hid_receiver_events_end) 169 next_pos = (UCHAR *)receiver -> ux_device_class_hid_receiver_events; 170 receiver -> ux_device_class_hid_receiver_event_save_pos = (UX_DEVICE_CLASS_HID_RECEIVED_EVENT *)next_pos; 171 172 /* Save received data length (it's valid now). */ 173 pos -> ux_device_class_hid_received_event_length = temp; 174 175 /* Notify application that a event is received. */ 176 if (receiver -> ux_device_class_hid_receiver_event_callback) 177 receiver -> ux_device_class_hid_receiver_event_callback(hid); 178 179 /* Restart receiving. */ 180 hid -> ux_device_class_hid_read_state = UX_DEVICE_CLASS_HID_RECEIVER_START; 181 return(UX_STATE_NEXT); 182 } 183 184 /* Keep waiting. */ 185 return(UX_STATE_WAIT); 186 187 default: /* Nothing to do by default. */ 188 break; 189 } 190 191 /* Task is idle. */ 192 return(UX_STATE_IDLE); 193 } 194 #endif 195