1 /*
2  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "usb_host_config.h"
10 #include "usb_host.h"
11 #include "usb_host_hci.h"
12 #include "usb_host_devices.h"
13 #include "usb_host_framework.h"
14 /*******************************************************************************
15  * Definitions
16  ******************************************************************************/
17 
18 /* Component ID definition, used by tools. */
19 #ifndef FSL_COMPONENT_ID
20 #define FSL_COMPONENT_ID "middleware.usb.host.fatfs_usb_stack"
21 #endif
22 
23 /*******************************************************************************
24  * Prototypes
25  ******************************************************************************/
26 
27 /*******************************************************************************
28  * Variables
29  ******************************************************************************/
30 
31 /*******************************************************************************
32  * Code
33  ******************************************************************************/
34 
USB_HostCh9RequestCommon(usb_host_device_instance_t * deviceInstance,usb_host_transfer_t * transfer,uint8_t * buffer,uint32_t bufferLen)35 usb_status_t USB_HostCh9RequestCommon(usb_host_device_instance_t *deviceInstance,
36                                       usb_host_transfer_t *transfer,
37                                       uint8_t *buffer,
38                                       uint32_t bufferLen)
39 {
40     /* initialize transfer */
41     transfer->setupPacket->wLength = USB_SHORT_TO_LITTLE_ENDIAN((uint16_t)bufferLen);
42     transfer->transferBuffer       = buffer;
43     transfer->transferLength       = bufferLen;
44 
45     if (USB_HostSendSetup(deviceInstance->hostHandle, deviceInstance->controlPipe, transfer) !=
46         kStatus_USB_Success) /* send setup transfer */
47     {
48 #ifdef HOST_ECHO
49         usb_echo("failed for USB_HostSendSetup\r\n");
50 #endif
51         (void)USB_HostFreeTransfer(deviceInstance->hostHandle, transfer);
52         return kStatus_USB_Error;
53     }
54     return kStatus_USB_Success;
55 }
56 
USB_HostStandardGetStatus(usb_host_device_instance_t * deviceInstance,usb_host_transfer_t * transfer,void * param)57 usb_status_t USB_HostStandardGetStatus(usb_host_device_instance_t *deviceInstance,
58                                        usb_host_transfer_t *transfer,
59                                        void *param)
60 {
61     usb_host_get_status_param_t *statusParam;
62     uint8_t length;
63 
64     /* initialize transfer */
65     statusParam                          = (usb_host_get_status_param_t *)param;
66     transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_STANDARD;
67     if (statusParam->requestType == (uint8_t)kRequestDevice)
68     {
69         transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_DEVICE;
70     }
71     else if (statusParam->requestType == (uint8_t)kRequestInterface)
72     {
73         transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
74     }
75     else
76     {
77         transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_ENDPOINT;
78     }
79     transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(statusParam->statusSelector);
80 
81     length = 2;
82     if (statusParam->statusSelector == USB_REQUEST_STANDARD_GET_STATUS_OTG_STATUS_SELECTOR)
83     {
84         length = 1;
85     }
86     return USB_HostCh9RequestCommon(deviceInstance, transfer, statusParam->statusBuffer, length);
87 }
88 
USB_HostStandardSetClearFeature(usb_host_device_instance_t * deviceInstance,usb_host_transfer_t * transfer,void * param)89 usb_status_t USB_HostStandardSetClearFeature(usb_host_device_instance_t *deviceInstance,
90                                              usb_host_transfer_t *transfer,
91                                              void *param)
92 {
93     usb_host_process_feature_param_t *featureParam;
94 
95     /* initialize transfer */
96     featureParam = (usb_host_process_feature_param_t *)param;
97     if (featureParam->requestType == (uint8_t)kRequestDevice)
98     {
99         transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_DEVICE;
100     }
101     else if (featureParam->requestType == (uint8_t)kRequestInterface)
102     {
103         transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
104     }
105     else
106     {
107         transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_ENDPOINT;
108     }
109     transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(featureParam->featureSelector);
110     transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(featureParam->interfaceOrEndpoint);
111 
112     return USB_HostCh9RequestCommon(deviceInstance, transfer, NULL, 0);
113 }
114 
USB_HostStandardSetAddress(usb_host_device_instance_t * deviceInstance,usb_host_transfer_t * transfer,void * param)115 usb_status_t USB_HostStandardSetAddress(usb_host_device_instance_t *deviceInstance,
116                                         usb_host_transfer_t *transfer,
117                                         void *param)
118 {
119     uint8_t address;
120 
121     /* initialize transfer */
122     address                       = *(uint8_t *)param;
123     transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(address);
124 
125     return USB_HostCh9RequestCommon(deviceInstance, transfer, NULL, 0);
126 }
127 
USB_HostStandardSetGetDescriptor(usb_host_device_instance_t * deviceInstance,usb_host_transfer_t * transfer,void * param)128 usb_status_t USB_HostStandardSetGetDescriptor(usb_host_device_instance_t *deviceInstance,
129                                               usb_host_transfer_t *transfer,
130                                               void *param)
131 {
132     usb_host_process_descriptor_param_t *descriptorParam;
133 
134     /* initialize transfer */
135     descriptorParam               = (usb_host_process_descriptor_param_t *)param;
136     transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(
137         (uint16_t)((uint16_t)descriptorParam->descriptorType << 8) | descriptorParam->descriptorIndex);
138     transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(descriptorParam->languageId);
139     return USB_HostCh9RequestCommon(deviceInstance, transfer, descriptorParam->descriptorBuffer,
140                                     descriptorParam->descriptorLength);
141 }
142 
USB_HostStandardGetInterface(usb_host_device_instance_t * deviceInstance,usb_host_transfer_t * transfer,void * param)143 usb_status_t USB_HostStandardGetInterface(usb_host_device_instance_t *deviceInstance,
144                                           usb_host_transfer_t *transfer,
145                                           void *param)
146 {
147     usb_host_get_interface_param_t *interfaceParam;
148 
149     /* initialize transfer */
150     interfaceParam = (usb_host_get_interface_param_t *)param;
151     transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN;
152     transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
153     transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(interfaceParam->interface);
154 
155     return USB_HostCh9RequestCommon(deviceInstance, transfer, interfaceParam->alternateInterfaceBuffer, 1);
156 }
157 
USB_HostStandardSetInterface(usb_host_device_instance_t * deviceInstance,usb_host_transfer_t * transfer,void * param)158 usb_status_t USB_HostStandardSetInterface(usb_host_device_instance_t *deviceInstance,
159                                           usb_host_transfer_t *transfer,
160                                           void *param)
161 {
162     usb_host_set_interface_param_t *setParam;
163 
164     /* initialize transfer */
165     setParam = (usb_host_set_interface_param_t *)param;
166     transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
167     transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(setParam->interface);
168     transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(setParam->alternateSetting);
169 
170     return USB_HostCh9RequestCommon(deviceInstance, transfer, NULL, 0);
171 }
172 
USB_HostStandardSyncFrame(usb_host_device_instance_t * deviceInstance,usb_host_transfer_t * transfer,void * param)173 usb_status_t USB_HostStandardSyncFrame(usb_host_device_instance_t *deviceInstance,
174                                        usb_host_transfer_t *transfer,
175                                        void *param)
176 {
177     usb_host_synch_frame_param_t *frameParam;
178 
179     /* initialize transfer */
180     frameParam = (usb_host_synch_frame_param_t *)param;
181     transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN;
182     transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_ENDPOINT;
183     transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(frameParam->endpoint);
184 
185     return USB_HostCh9RequestCommon(deviceInstance, transfer, frameParam->frameNumberBuffer, 2);
186 }
187 
USB_HostRequestControl(usb_device_handle deviceHandle,uint8_t usbRequest,usb_host_transfer_t * transfer,void * param)188 usb_status_t USB_HostRequestControl(usb_device_handle deviceHandle,
189                                     uint8_t usbRequest,
190                                     usb_host_transfer_t *transfer,
191                                     void *param)
192 {
193     usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
194     usb_status_t status                        = kStatus_USB_Error;
195 
196     if (deviceHandle == NULL)
197     {
198         return kStatus_USB_InvalidHandle;
199     }
200 
201     /* reset transfer fields */
202     transfer->setupPacket->bmRequestType = 0x00;
203     transfer->setupPacket->bRequest      = usbRequest;
204     transfer->setupPacket->wIndex        = 0;
205     transfer->setupPacket->wLength       = 0;
206     transfer->setupPacket->wValue        = 0;
207 
208     switch (usbRequest)
209     {
210         case USB_REQUEST_STANDARD_GET_STATUS: /* standard get status request */
211             status = USB_HostStandardGetStatus(deviceInstance, transfer, param);
212             break;
213 
214         case USB_REQUEST_STANDARD_CLEAR_FEATURE: /* standard clear status request */
215         case USB_REQUEST_STANDARD_SET_FEATURE:   /* standard set feature request */
216             status = USB_HostStandardSetClearFeature(deviceInstance, transfer, param);
217             break;
218 
219         case USB_REQUEST_STANDARD_SET_ADDRESS: /* standard set address request */
220             status = USB_HostStandardSetAddress(deviceInstance, transfer, param);
221             break;
222 
223         case USB_REQUEST_STANDARD_GET_DESCRIPTOR: /* standard get descriptor request */
224         case USB_REQUEST_STANDARD_SET_DESCRIPTOR: /* standard set descriptor request */
225             if (usbRequest == USB_REQUEST_STANDARD_GET_DESCRIPTOR)
226             {
227                 transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN;
228             }
229             status = USB_HostStandardSetGetDescriptor(deviceInstance, transfer, param);
230             break;
231 
232         case USB_REQUEST_STANDARD_GET_CONFIGURATION: /* standard get configuration descriptor request */
233             transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN;
234             status =
235                 USB_HostCh9RequestCommon((usb_host_device_instance_t *)deviceHandle, transfer, (uint8_t *)param, 1);
236             break;
237 
238         case USB_REQUEST_STANDARD_SET_CONFIGURATION: /* standard set configuration request */
239             transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(*((uint8_t *)param));
240             status = USB_HostCh9RequestCommon((usb_host_device_instance_t *)deviceHandle, transfer, NULL, 0);
241             break;
242 
243         case USB_REQUEST_STANDARD_GET_INTERFACE: /* standard get interface request */
244             status = USB_HostStandardGetInterface(deviceInstance, transfer, param);
245             break;
246 
247         case USB_REQUEST_STANDARD_SET_INTERFACE: /* standard set interface request */
248             status = USB_HostStandardSetInterface(deviceInstance, transfer, param);
249             break;
250 
251         case USB_REQUEST_STANDARD_SYNCH_FRAME: /* standard synch frame request */
252             status = USB_HostStandardSyncFrame(deviceInstance, transfer, param);
253             break;
254 
255         default:
256             /*no action*/
257             break;
258     }
259 
260     return status;
261 }
262