common: Add NXP's USB serial code.
[gps-watch.git] / src / common / usb_device_ch9.c
1 /*
2  * The Clear BSD License
3  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
4  * Copyright 2016-2017 NXP
5  * All rights reserved.
6  * 
7  * Redistribution and use in source and binary forms, with or without modification,
8  * are permitted (subject to the limitations in the disclaimer below) provided
9  *  that the following conditions are met:
10  *
11  * o Redistributions of source code must retain the above copyright notice, this list
12  *   of conditions and the following disclaimer.
13  *
14  * o Redistributions in binary form must reproduce the above copyright notice, this
15  *   list of conditions and the following disclaimer in the documentation and/or
16  *   other materials provided with the distribution.
17  *
18  * o Neither the name of the copyright holder nor the names of its
19  *   contributors may be used to endorse or promote products derived from this
20  *   software without specific prior written permission.
21  *
22  * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
27  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 #include "usb_device_config.h"
36 #include "usb.h"
37
38 #include "usb_device.h"
39 #include "usb_device_dci.h"
40 #include "usb_device_ch9.h"
41
42 /*******************************************************************************
43  * Definitions
44  ******************************************************************************/
45
46 /*!
47  * @brief Standard request callback function typedef.
48  *
49  * This function is used to handle the standard request.
50  *
51  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
52  * @param setup           The pointer of the setup packet.
53  * @param buffer          It is an out parameter, is used to save the buffer address to response the host's request.
54  * @param length          It is an out parameter, the data length.
55  *
56  * @return A USB error code or kStatus_USB_Success.
57  */
58 typedef usb_status_t (*usb_standard_request_callback_t)(usb_device_handle handle,
59                                                         usb_setup_struct_t *setup,
60                                                         uint8_t **buffer,
61                                                         uint32_t *length);
62
63 /*******************************************************************************
64 * Prototypes
65 ******************************************************************************/
66 /*!
67  * @brief Get the setup packet buffer.
68  *
69  * The function is used to get the setup packet buffer to save the setup packet data.
70  *
71  * @param handle              The device handle.
72  * @param setupBuffer        It is an OUT parameter, return the setup buffer address to the caller.
73  *
74  * @return A USB error code or kStatus_USB_Success.
75  */
76 extern usb_status_t USB_DeviceGetSetupBuffer(usb_device_handle handle, usb_setup_struct_t **setupBuffer);
77
78 /*!
79  * @brief Handle the class request.
80  *
81  * The function is used to handle the class request.
82  *
83  * @param handle              The device handle.
84  * @param setup               The setup packet buffer address.
85  * @param length              It is an OUT parameter, return the data length need to be sent to host.
86  * @param buffer              It is an OUT parameter, return the data buffer address.
87  *
88  * @return A USB error code or kStatus_USB_Success.
89  */
90 extern usb_status_t USB_DeviceProcessClassRequest(usb_device_handle handle,
91                                                   usb_setup_struct_t *setup,
92                                                   uint32_t *length,
93                                                   uint8_t **buffer);
94
95 /*!
96  * @brief Get the buffer to save the class specific data sent from host.
97  *
98  * The function is used to get the buffer to save the class specific data sent from host.
99  * The function will be called when the device receives a setup pakcet, and the host needs to send data to the device in
100  * the data stage.
101  *
102  * @param handle              The device handle.
103  * @param setup               The setup packet buffer address.
104  * @param length              Pass the length the host needs to sent.
105  * @param buffer              It is an OUT parameter, return the data buffer address to save the host's data.
106  *
107  * @return A USB error code or kStatus_USB_Success.
108  */
109 extern usb_status_t USB_DeviceGetClassReceiveBuffer(usb_device_handle handle,
110                                                     usb_setup_struct_t *setup,
111                                                     uint32_t *length,
112                                                     uint8_t **buffer);
113
114 /* standard request */
115 /*!
116  * @brief Get the descritpor.
117  *
118  * The function is used to get the descritpor, including the device descritpor, configuration descriptor, and string
119  * descriptor, etc.
120  *
121  * @param handle              The device handle.
122  * @param setup               The setup packet buffer address.
123  * @param length              It is an OUT parameter, return the data length need to be sent to host.
124  * @param buffer              It is an OUT parameter, return the data buffer address.
125  *
126  * @return A USB error code or kStatus_USB_Success.
127  */
128 extern usb_status_t USB_DeviceGetDescriptor(usb_device_handle handle,
129                                             usb_setup_struct_t *setup,
130                                             uint32_t *length,
131                                             uint8_t **buffer);
132
133 /*!
134  * @brief Set the device configuration.
135  *
136  * The function is used to set the device configuration.
137  *
138  * @param handle              The device handle.
139  * @param configure           The configuration value.
140  *
141  * @return A USB error code or kStatus_USB_Success.
142  */
143 extern usb_status_t USB_DeviceSetConfigure(usb_device_handle handle, uint8_t configure);
144
145 /*!
146  * @brief Get the device configuration.
147  *
148  * The function is used to get the device configuration.
149  *
150  * @param handle              The device handle.
151  * @param configure           It is an OUT parameter, save the current configuration value.
152  *
153  * @return A USB error code or kStatus_USB_Success.
154  */
155 extern usb_status_t USB_DeviceGetConfigure(usb_device_handle handle, uint8_t *configure);
156
157 /*!
158  * @brief Set an interface alternate setting.
159  *
160  * The function is used to set an interface alternate setting.
161  *
162  * @param handle              The device handle.
163  * @param interface           The interface index.
164  * @param alternateSetting   The new alternate setting value.
165  *
166  * @return A USB error code or kStatus_USB_Success.
167  */
168 extern usb_status_t USB_DeviceSetInterface(usb_device_handle handle, uint8_t interface, uint8_t alternateSetting);
169
170 /*!
171  * @brief Get an interface alternate setting.
172  *
173  * The function is used to get an interface alternate setting.
174  *
175  * @param handle              The device handle.
176  * @param interface           The interface index.
177  * @param alternateSetting   It is an OUT parameter, save the new alternate setting value of the interface.
178  *
179  * @return A USB error code or kStatus_USB_Success.
180  */
181 extern usb_status_t USB_DeviceGetInterface(usb_device_handle handle, uint8_t interface, uint8_t *alternateSetting);
182
183 /*!
184  * @brief Configure a specified endpoint status.
185  *
186  * The function is used to configure a specified endpoint status, idle or halt.
187  *
188  * @param handle              The device handle.
189  * @param endpointAddress    The endpoint address, the BIT7 is the direction, 0 - USB_OUT, 1 - USB_IN.
190  * @param status              The new status of the endpoint, 0 - idle, 1 - halt.
191  *
192  * @return A USB error code or kStatus_USB_Success.
193  */
194 extern usb_status_t USB_DeviceConfigureEndpointStatus(usb_device_handle handle,
195                                                       uint8_t endpointAddress,
196                                                       uint8_t status);
197
198 /*!
199  * @brief Configure the device remote wakeup feature.
200  *
201  * The function is used to configure the device remote wakeup feature, enable or disbale the remote wakeup feature.
202  *
203  * @param handle              The device handle.
204  * @param enable              The new feature value of the device remote wakeup, 0 - disable, 1 - enable.
205  *
206  * @return A USB error code or kStatus_USB_Success.
207  */
208 extern usb_status_t USB_DeviceConfigureRemoteWakeup(usb_device_handle handle, uint8_t enable);
209
210 static usb_status_t USB_DeviceCh9GetStatus(usb_device_handle handle,
211                                            usb_setup_struct_t *setup,
212                                            uint8_t **buffer,
213                                            uint32_t *length);
214 static usb_status_t USB_DeviceCh9SetClearFeature(usb_device_handle handle,
215                                                  usb_setup_struct_t *setup,
216                                                  uint8_t **buffer,
217                                                  uint32_t *length);
218 static usb_status_t USB_DeviceCh9SetAddress(usb_device_handle handle,
219                                             usb_setup_struct_t *setup,
220                                             uint8_t **buffer,
221                                             uint32_t *length);
222 static usb_status_t USB_DeviceCh9GetDescriptor(usb_device_handle handle,
223                                                usb_setup_struct_t *setup,
224                                                uint8_t **buffer,
225                                                uint32_t *length);
226 static usb_status_t USB_DeviceCh9GetConfiguration(usb_device_handle handle,
227                                                   usb_setup_struct_t *setup,
228                                                   uint8_t **buffer,
229                                                   uint32_t *length);
230 static usb_status_t USB_DeviceCh9SetConfiguration(usb_device_handle handle,
231                                                   usb_setup_struct_t *setup,
232                                                   uint8_t **buffer,
233                                                   uint32_t *length);
234 static usb_status_t USB_DeviceCh9GetInterface(usb_device_handle handle,
235                                               usb_setup_struct_t *setup,
236                                               uint8_t **buffer,
237                                               uint32_t *length);
238 static usb_status_t USB_DeviceCh9SetInterface(usb_device_handle handle,
239                                               usb_setup_struct_t *setup,
240                                               uint8_t **buffer,
241                                               uint32_t *length);
242 static usb_status_t USB_DeviceCh9SynchFrame(usb_device_handle handle,
243                                             usb_setup_struct_t *setup,
244                                             uint8_t **buffer,
245                                             uint32_t *length);
246
247 /*******************************************************************************
248  * Variables
249  ******************************************************************************/
250
251 /* The function list to handle the standard request. */
252 static const usb_standard_request_callback_t s_UsbDeviceStandardRequest[] = {
253     USB_DeviceCh9GetStatus,
254     USB_DeviceCh9SetClearFeature,
255     (usb_standard_request_callback_t)NULL,
256     USB_DeviceCh9SetClearFeature,
257     (usb_standard_request_callback_t)NULL,
258     USB_DeviceCh9SetAddress,
259     USB_DeviceCh9GetDescriptor,
260     (usb_standard_request_callback_t)NULL, /* USB_DeviceCh9SetDescriptor */
261     USB_DeviceCh9GetConfiguration,
262     USB_DeviceCh9SetConfiguration,
263     USB_DeviceCh9GetInterface,
264     USB_DeviceCh9SetInterface,
265     USB_DeviceCh9SynchFrame,
266 };
267
268 /*
269  * The internal global variable.
270  * This variable is used in:
271  *           get status request
272  *           get configuration request
273  *           get interface request
274  *           set interface request
275  *           get sync frame request
276  */
277 static uint16_t s_UsbDeviceStandardRx;
278
279 /*******************************************************************************
280 * Code
281 ******************************************************************************/
282 /*!
283  * @brief Handle get status request.
284  *
285  * This function is used to handle get status request.
286  *
287  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
288  * @param setup           The pointer of the setup packet.
289  * @param buffer          It is an out parameter, is used to save the buffer address to response the host's request.
290  * @param length          It is an out parameter, the data length.
291  *
292  * @retval kStatus_USB_Success              The requst is handled successfully.
293  * @retval kStatus_USB_InvalidRequest       The request can not be handle in current device state,
294  *                                          or, the request is unsupported.
295  */
296 static usb_status_t USB_DeviceCh9GetStatus(usb_device_handle handle,
297                                            usb_setup_struct_t *setup,
298                                            uint8_t **buffer,
299                                            uint32_t *length)
300 {
301     usb_status_t error = kStatus_USB_InvalidRequest;
302     uint8_t state;
303
304     USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
305
306     if ((kUSB_DeviceStateAddress != state) && (kUSB_DeviceStateConfigured != state))
307     {
308         return error;
309     }
310
311     if ((setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) == USB_REQUEST_TYPE_RECIPIENT_DEVICE)
312     {
313         /* Get the device status */
314         error = USB_DeviceGetStatus(handle, kUSB_DeviceStatusDevice, &s_UsbDeviceStandardRx);
315         s_UsbDeviceStandardRx = s_UsbDeviceStandardRx & USB_GET_STATUS_DEVICE_MASK;
316         s_UsbDeviceStandardRx = USB_SHORT_TO_LITTLE_ENDIAN(s_UsbDeviceStandardRx);
317         /* The device status length must be USB_DEVICE_STATUS_SIZE. */
318         *length = USB_DEVICE_STATUS_SIZE;
319     }
320     else if ((setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) == USB_REQUEST_TYPE_RECIPIENT_INTERFACE)
321     {
322         /* Get the interface status */
323         error = kStatus_USB_Success;
324         s_UsbDeviceStandardRx = 0U;
325         /* The interface status length must be USB_INTERFACE_STATUS_SIZE. */
326         *length = USB_INTERFACE_STATUS_SIZE;
327     }
328     else if ((setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) == USB_REQUEST_TYPE_RECIPIENT_ENDPOINT)
329     {
330         /* Get the endpoint status */
331         usb_device_endpoint_status_struct_t endpointStatus;
332         endpointStatus.endpointAddress = (uint8_t)setup->wIndex;
333         endpointStatus.endpointStatus = kUSB_DeviceEndpointStateIdle;
334         error = USB_DeviceGetStatus(handle, kUSB_DeviceStatusEndpoint, &endpointStatus);
335         s_UsbDeviceStandardRx = endpointStatus.endpointStatus & USB_GET_STATUS_ENDPOINT_MASK;
336         s_UsbDeviceStandardRx = USB_SHORT_TO_LITTLE_ENDIAN(s_UsbDeviceStandardRx);
337         /* The endpoint status length must be USB_INTERFACE_STATUS_SIZE. */
338         *length = USB_ENDPOINT_STATUS_SIZE;
339     }
340     else
341     {
342     }
343     *buffer = (uint8_t *)&s_UsbDeviceStandardRx;
344
345     return error;
346 }
347
348 /*!
349  * @brief Handle set or clear device feature request.
350  *
351  * This function is used to handle set or clear device feature request.
352  *
353  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
354  * @param setup           The pointer of the setup packet.
355  * @param buffer          It is an out parameter, is used to save the buffer address to response the host's request.
356  * @param length          It is an out parameter, the data length.
357  *
358  * @retval kStatus_USB_Success              The requst is handled successfully.
359  * @retval kStatus_USB_InvalidRequest       The request can not be handle in current device state,
360  *                                          or, the request is unsupported.
361  */
362 static usb_status_t USB_DeviceCh9SetClearFeature(usb_device_handle handle,
363                                                  usb_setup_struct_t *setup,
364                                                  uint8_t **buffer,
365                                                  uint32_t *length)
366 {
367     usb_status_t error = kStatus_USB_InvalidRequest;
368     uint8_t state;
369     uint8_t isSet = 0U;
370
371     USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
372
373     if ((kUSB_DeviceStateAddress != state) && (kUSB_DeviceStateConfigured != state))
374     {
375         return error;
376     }
377
378     /* Identify the request is set or clear the feature. */
379     if (USB_REQUEST_STANDARD_SET_FEATURE == setup->bRequest)
380     {
381         isSet = 1U;
382     }
383
384     if ((setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) == USB_REQUEST_TYPE_RECIPIENT_DEVICE)
385     {
386         /* Set or Clear the device featrue. */
387         if (USB_REQUEST_STANDARD_FEATURE_SELECTOR_DEVICE_REMOTE_WAKEUP == setup->wValue)
388         {
389             /* Set or Clear the device remote wakeup featrue. */
390             error = USB_DeviceConfigureRemoteWakeup(handle, isSet);
391         }
392 #if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)) && \
393     (defined(USB_DEVICE_CONFIG_EHCI_TEST_MODE) && (USB_DEVICE_CONFIG_EHCI_TEST_MODE > 0U))
394         else if (USB_REQUEST_STANDARD_FEATURE_SELECTOR_DEVICE_TEST_MODE == setup->wValue)
395         {
396             state = kUSB_DeviceStateTestMode;
397             error = USB_DeviceSetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state);
398         }
399 #endif
400         else
401         {
402         }
403     }
404     else if ((setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) == USB_REQUEST_TYPE_RECIPIENT_ENDPOINT)
405     {
406         /* Set or Clear the endpoint featrue. */
407         if (USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT == setup->wValue)
408         {
409             if (USB_CONTROL_ENDPOINT == (setup->wIndex & USB_ENDPOINT_NUMBER_MASK))
410             {
411                 /* Set or Clear the control endpoint status(halt or not). */
412                 if (isSet)
413                 {
414                     USB_DeviceStallEndpoint(handle, (uint8_t)setup->wIndex);
415                 }
416                 else
417                 {
418                     USB_DeviceUnstallEndpoint(handle, (uint8_t)setup->wIndex);
419                 }
420             }
421
422             /* Set or Clear the endpoint status featrue. */
423             error = USB_DeviceConfigureEndpointStatus(handle, setup->wIndex, isSet);
424         }
425         else
426         {
427         }
428     }
429     else
430     {
431     }
432
433     return error;
434 }
435
436 /*!
437  * @brief Handle set address request.
438  *
439  * This function is used to handle set address request.
440  *
441  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
442  * @param setup           The pointer of the setup packet.
443  * @param buffer          It is an out parameter, is used to save the buffer address to response the host's request.
444  * @param length          It is an out parameter, the data length.
445  *
446  * @retval kStatus_USB_Success              The requst is handled successfully.
447  * @retval kStatus_USB_InvalidRequest       The request can not be handle in current device state.
448  */
449 static usb_status_t USB_DeviceCh9SetAddress(usb_device_handle handle,
450                                             usb_setup_struct_t *setup,
451                                             uint8_t **buffer,
452                                             uint32_t *length)
453 {
454     usb_status_t error = kStatus_USB_InvalidRequest;
455     uint8_t state;
456
457     USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
458
459     if ((kUSB_DeviceStateAddressing != state) && (kUSB_DeviceStateAddress != state) &&
460         (kUSB_DeviceStateDefault != state))
461     {
462         return error;
463     }
464
465     if (kUSB_DeviceStateAddressing != state)
466     {
467         /* If the device address is not setting, pass the address and the device state will change to
468          * kUSB_DeviceStateAddressing internally. */
469         state = setup->wValue & 0xFFU;
470         error = USB_DeviceSetStatus(handle, kUSB_DeviceStatusAddress, &state);
471     }
472     else
473     {
474         /* If the device address is setting, set device address and the address will be write into the controller
475          * internally. */
476         error = USB_DeviceSetStatus(handle, kUSB_DeviceStatusAddress, NULL);
477         /* And then change the device state to kUSB_DeviceStateAddress. */
478         if (kStatus_USB_Success == error)
479         {
480             state = kUSB_DeviceStateAddress;
481             error = USB_DeviceSetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
482         }
483     }
484
485     return error;
486 }
487
488 /*!
489  * @brief Handle get descriptor request.
490  *
491  * This function is used to handle get descriptor request.
492  *
493  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
494  * @param setup           The pointer of the setup packet.
495  * @param buffer          It is an out parameter, is used to save the buffer address to response the host's request.
496  * @param length          It is an out parameter, the data length.
497  *
498  * @retval kStatus_USB_Success              The requst is handled successfully.
499  * @retval kStatus_USB_InvalidRequest       The request can not be handle in current device state,
500  *                                          or, the request is unsupported.
501  */
502 static usb_status_t USB_DeviceCh9GetDescriptor(usb_device_handle handle,
503                                                usb_setup_struct_t *setup,
504                                                uint8_t **buffer,
505                                                uint32_t *length)
506 {
507     uint8_t state;
508
509     USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
510
511     if ((kUSB_DeviceStateAddress != state) && (kUSB_DeviceStateConfigured != state) &&
512         (kUSB_DeviceStateDefault != state))
513     {
514         return kStatus_USB_InvalidRequest;
515     }
516
517     return USB_DeviceGetDescriptor(handle, setup, length, buffer);
518 }
519
520 /*!
521  * @brief Handle get current configuration request.
522  *
523  * This function is used to handle get current configuration request.
524  *
525  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
526  * @param setup           The pointer of the setup packet.
527  * @param buffer          It is an out parameter, is used to save the buffer address to response the host's request.
528  * @param length          It is an out parameter, the data length.
529  *
530  * @retval kStatus_USB_Success              The requst is handled successfully.
531  * @retval kStatus_USB_InvalidRequest       The request can not be handle in current device state,
532  *                                          or, the request is unsupported.
533  */
534 static usb_status_t USB_DeviceCh9GetConfiguration(usb_device_handle handle,
535                                                   usb_setup_struct_t *setup,
536                                                   uint8_t **buffer,
537                                                   uint32_t *length)
538 {
539     uint8_t state;
540
541     USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
542
543     if ((kUSB_DeviceStateAddress != state) && ((kUSB_DeviceStateConfigured != state)))
544     {
545         return kStatus_USB_InvalidRequest;
546     }
547
548     *length = USB_CONFIGURE_SIZE;
549     *buffer = (uint8_t *)&s_UsbDeviceStandardRx;
550     return USB_DeviceGetConfigure(handle, (uint8_t *)&s_UsbDeviceStandardRx);
551 }
552
553 /*!
554  * @brief Handle set current configuration request.
555  *
556  * This function is used to handle set current configuration request.
557  *
558  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
559  * @param setup           The pointer of the setup packet.
560  * @param buffer          It is an out parameter, is used to save the buffer address to response the host's request.
561  * @param length          It is an out parameter, the data length.
562  *
563  * @retval kStatus_USB_Success              The requst is handled successfully.
564  * @retval kStatus_USB_InvalidRequest       The request can not be handle in current device state,
565  *                                          or, the request is unsupported.
566  */
567 static usb_status_t USB_DeviceCh9SetConfiguration(usb_device_handle handle,
568                                                   usb_setup_struct_t *setup,
569                                                   uint8_t **buffer,
570                                                   uint32_t *length)
571 {
572     uint8_t state;
573
574     USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
575
576     if ((kUSB_DeviceStateAddress != state) && (kUSB_DeviceStateConfigured != state))
577     {
578         return kStatus_USB_InvalidRequest;
579     }
580
581     /* The device state is changed to kUSB_DeviceStateConfigured */
582     state = kUSB_DeviceStateConfigured;
583     USB_DeviceSetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
584     if (!setup->wValue)
585     {
586         /* If the new configuration is zero, the device state is changed to kUSB_DeviceStateAddress */
587         state = kUSB_DeviceStateAddress;
588         USB_DeviceSetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
589     }
590
591     return USB_DeviceSetConfigure(handle, setup->wValue);
592 }
593
594 /*!
595  * @brief Handle get the alternate setting of a interface request.
596  *
597  * This function is used to handle get the alternate setting of a interface request.
598  *
599  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
600  * @param setup           The pointer of the setup packet.
601  * @param buffer          It is an out parameter, is used to save the buffer address to response the host's request.
602  * @param length          It is an out parameter, the data length.
603  *
604  * @retval kStatus_USB_Success              The requst is handled successfully.
605  * @retval kStatus_USB_InvalidRequest       The request can not be handle in current device state,
606  *                                          or, the request is unsupported.
607  */
608 static usb_status_t USB_DeviceCh9GetInterface(usb_device_handle handle,
609                                               usb_setup_struct_t *setup,
610                                               uint8_t **buffer,
611                                               uint32_t *length)
612 {
613     usb_status_t error = kStatus_USB_InvalidRequest;
614     uint8_t state;
615
616     USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
617
618     if (state != kUSB_DeviceStateConfigured)
619     {
620         return error;
621     }
622     *length = USB_INTERFACE_SIZE;
623     *buffer = (uint8_t *)&s_UsbDeviceStandardRx;
624
625     return USB_DeviceGetInterface(handle, setup->wIndex & 0xFFU, (uint8_t *)&s_UsbDeviceStandardRx);
626 }
627
628 /*!
629  * @brief Handle set the alternate setting of a interface request.
630  *
631  * This function is used to handle set the alternate setting of a interface request.
632  *
633  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
634  * @param setup           The pointer of the setup packet.
635  * @param buffer          It is an out parameter, is used to save the buffer address to response the host's request.
636  * @param length          It is an out parameter, the data length.
637  *
638  * @retval kStatus_USB_Success              The requst is handled successfully.
639  * @retval kStatus_USB_InvalidRequest       The request can not be handle in current device state,
640  *                                          or, the request is unsupported.
641  */
642 static usb_status_t USB_DeviceCh9SetInterface(usb_device_handle handle,
643                                               usb_setup_struct_t *setup,
644                                               uint8_t **buffer,
645                                               uint32_t *length)
646 {
647     uint8_t state;
648
649     USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
650
651     if (state != kUSB_DeviceStateConfigured)
652     {
653         return kStatus_USB_InvalidRequest;
654     }
655
656     return USB_DeviceSetInterface(handle, (setup->wIndex & 0xFFU), (setup->wValue & 0xFFU));
657 }
658
659 /*!
660  * @brief Handle get sync frame request.
661  *
662  * This function is used to handle get sync frame request.
663  *
664  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
665  * @param setup           The pointer of the setup packet.
666  * @param buffer          It is an out parameter, is used to save the buffer address to response the host's request.
667  * @param length          It is an out parameter, the data length.
668  *
669  * @retval kStatus_USB_Success              The requst is handled successfully.
670  * @retval kStatus_USB_InvalidRequest       The request can not be handle in current device state,
671  *                                          or, the request is unsupported.
672  */
673 static usb_status_t USB_DeviceCh9SynchFrame(usb_device_handle handle,
674                                             usb_setup_struct_t *setup,
675                                             uint8_t **buffer,
676                                             uint32_t *length)
677 {
678     usb_status_t error = kStatus_USB_InvalidRequest;
679     uint8_t state;
680
681     USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
682
683     if (state != kUSB_DeviceStateConfigured)
684     {
685         return error;
686     }
687
688     s_UsbDeviceStandardRx = setup->wIndex;
689     /* Get the sync frame value */
690     error = USB_DeviceGetStatus(handle, kUSB_DeviceStatusSynchFrame, &s_UsbDeviceStandardRx);
691     *buffer = (uint8_t *)&s_UsbDeviceStandardRx;
692     *length = sizeof(s_UsbDeviceStandardRx);
693
694     return error;
695 }
696
697 /*!
698  * @brief Send the reponse to the host.
699  *
700  * This function is used to send the reponse to the host.
701  *
702  * There are two cases this function will be called.
703  * Case one when a setup packet is received in control endpoint callback function:
704  *        1. If there is not data phase in the setup transfer, the function will prime an IN transfer with the data
705  * length is zero for status phase.
706  *        2. If there is an IN data phase, the function will prime an OUT transfer with the actual length to need to
707  * send for data phase. And then prime an IN transfer with the data length is zero for status phase.
708  *        3. If there is an OUT data phase, the function will prime an IN transfer with the actual length to want to
709  * receive for data phase.
710  *
711  * Case two when is not a setup packet received in control endpoint callback function:
712  *        1. The function will prime an IN transfer with data length is zero for status phase.
713  *
714  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
715  * @param setup           The pointer of the setup packet.
716  * @param error           The error code returned from the standard request fucntion.
717  * @param stage           The stage of the control transfer.
718  * @param buffer          It is an out parameter, is used to save the buffer address to response the host's request.
719  * @param length          It is an out parameter, the data length.
720  *
721  * @return A USB error code or kStatus_USB_Success.
722  */
723 static usb_status_t USB_DeviceControlCallbackFeedback(usb_device_handle handle,
724                                                       usb_setup_struct_t *setup,
725                                                       usb_status_t error,
726                                                       usb_device_control_read_write_sequence_t stage,
727                                                       uint8_t **buffer,
728                                                       uint32_t *length)
729 {
730     usb_status_t errorCode = kStatus_USB_Error;
731     uint8_t direction = USB_IN;
732
733     if (kStatus_USB_InvalidRequest == error)
734     {
735         /* Stall the control pipe when the request is unsupported. */
736         if ((!((setup->bmRequestType & USB_REQUEST_TYPE_TYPE_MASK) == USB_REQUEST_TYPE_TYPE_STANDARD)) &&
737             ((setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_OUT) && (setup->wLength) &&
738             (kUSB_DeviceControlPipeSetupStage == stage))
739         {
740             direction = USB_OUT;
741         }
742         errorCode = USB_DeviceStallEndpoint(
743             handle,
744             (USB_CONTROL_ENDPOINT) | (uint8_t)((uint32_t)direction << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT));
745     }
746     else
747     {
748         if (*length > setup->wLength)
749         {
750             *length = setup->wLength;
751         }
752         errorCode = USB_DeviceSendRequest(handle, (USB_CONTROL_ENDPOINT), *buffer, *length);
753
754         if ((kStatus_USB_Success == errorCode) &&
755             (USB_REQUEST_TYPE_DIR_IN == (setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK)))
756         {
757             errorCode = USB_DeviceRecvRequest(handle, (USB_CONTROL_ENDPOINT), (uint8_t *)NULL, 0U);
758         }
759     }
760     return errorCode;
761 }
762
763 /*!
764  * @brief Control endpoint callback function.
765  *
766  * This callback function is used to notify uplayer the tranfser result of a transfer.
767  * This callback pointer is passed when a sepcified endpoint initialied by calling API USB_DeviceInitEndpoint.
768  *
769  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
770  * @param message         The result of a transfer, includes transfer buffer, transfer length and whether is in setup
771  * phase for control pipe.
772  * @param callbackParam  The paramter for this callback. It is same with
773  * usb_device_endpoint_callback_struct_t::callbackParam.
774  *
775  * @return A USB error code or kStatus_USB_Success.
776  */
777 usb_status_t USB_DeviceControlCallback(usb_device_handle handle,
778                                        usb_device_endpoint_callback_message_struct_t *message,
779                                        void *callbackParam)
780 {
781     usb_setup_struct_t *deviceSetup;
782     uint8_t *setupOutBuffer;
783     uint8_t *buffer = (uint8_t *)NULL;
784     uint32_t length = 0U;
785     usb_status_t error = kStatus_USB_InvalidRequest;
786     uint8_t state;
787
788     if (USB_UNINITIALIZED_VAL_32 == message->length)
789     {
790         return error;
791     }
792
793     USB_DeviceGetSetupBuffer(handle, &deviceSetup);
794     USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
795
796     if (message->isSetup)
797     {
798         if ((USB_SETUP_PACKET_SIZE != message->length) || (NULL == message->buffer))
799         {
800             /* If a invalid setup is received, the control pipes should be de-init and init again.
801              * Due to the IP can not meet this require, it is revesed for feature.
802              */
803             /*
804             USB_DeviceDeinitEndpoint(handle,
805                          USB_CONTROL_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT));
806             USB_DeviceDeinitEndpoint(handle,
807                          USB_CONTROL_ENDPOINT | (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT));
808             USB_DeviceControlPipeInit(handle);
809             */
810             return error;
811         }
812         /* Receive a setup request */
813         usb_setup_struct_t *setup = (usb_setup_struct_t *)(message->buffer);
814         /* Copy the setup packet to the application buffer */
815         deviceSetup->wValue = USB_SHORT_FROM_LITTLE_ENDIAN(setup->wValue);
816         deviceSetup->wIndex = USB_SHORT_FROM_LITTLE_ENDIAN(setup->wIndex);
817         deviceSetup->wLength = USB_SHORT_FROM_LITTLE_ENDIAN(setup->wLength);
818         deviceSetup->bRequest = setup->bRequest;
819         deviceSetup->bmRequestType = setup->bmRequestType;
820
821         if ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_MASK) == USB_REQUEST_TYPE_TYPE_STANDARD)
822         {
823             /* Handle the standard request */
824             if (s_UsbDeviceStandardRequest[deviceSetup->bRequest] != (usb_standard_request_callback_t)NULL)
825             {
826                 error = s_UsbDeviceStandardRequest[deviceSetup->bRequest](handle, deviceSetup, &buffer, &length);
827             }
828         }
829         else
830         {
831             if ((deviceSetup->wLength) &&
832                 ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_OUT))
833             {
834                 /* Class or vendor request with the OUT data phase. */
835                 if ((deviceSetup->wLength) &&
836                     ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_CLASS) == USB_REQUEST_TYPE_TYPE_CLASS))
837                 {
838                     /* Get data buffer to receive the data from the host. */
839                     length = deviceSetup->wLength;
840                     error = USB_DeviceGetClassReceiveBuffer(handle, deviceSetup, &length, &setupOutBuffer);
841                     length = 0U;
842                 }
843                 else
844                 {
845                 }
846                 if (kStatus_USB_Success == error)
847                 {
848                     /* Prime an OUT transfer */
849                     error = USB_DeviceRecvRequest(handle, USB_CONTROL_ENDPOINT, setupOutBuffer, deviceSetup->wLength);
850                     return error;
851                 }
852             }
853             else
854             {
855                 /* Class or vendor request with the IN data phase. */
856                 if (((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_CLASS) == USB_REQUEST_TYPE_TYPE_CLASS))
857                 {
858                     /* Get data buffer to response the host. */
859                     error = USB_DeviceProcessClassRequest(handle, deviceSetup, &length, &buffer);
860                 }
861                 else
862                 {
863                 }
864             }
865         }
866         /* Send the reponse to the host. */
867         error = USB_DeviceControlCallbackFeedback(handle, deviceSetup, error, kUSB_DeviceControlPipeSetupStage, &buffer,
868                                                   &length);
869     }
870     else if (kUSB_DeviceStateAddressing == state)
871     {
872         /* Set the device address to controller. */
873         error = s_UsbDeviceStandardRequest[deviceSetup->bRequest](handle, deviceSetup, &buffer, &length);
874     }
875 #if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)) && \
876     (defined(USB_DEVICE_CONFIG_EHCI_TEST_MODE) && (USB_DEVICE_CONFIG_EHCI_TEST_MODE > 0U))
877     else if (kUSB_DeviceStateTestMode == state)
878     {
879         uint8_t portTestControl = (uint8_t)(deviceSetup->wIndex >> 8);
880         /* Set the controller.into test mode. */
881         error = USB_DeviceSetStatus(handle, kUSB_DeviceStatusTestMode, &portTestControl);
882     }
883 #endif
884     else if ((message->length) && (deviceSetup->wLength) &&
885              ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_OUT))
886     {
887         if (((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_CLASS) == USB_REQUEST_TYPE_TYPE_CLASS))
888         {
889             /* Data received in OUT phase, and notify the class driver. */
890             error = USB_DeviceProcessClassRequest(handle, deviceSetup, &message->length, &message->buffer);
891         }
892         else
893         {
894         }
895         /* Send the reponse to the host. */
896         error = USB_DeviceControlCallbackFeedback(handle, deviceSetup, error, kUSB_DeviceControlPipeDataStage, &buffer,
897                                                   &length);
898     }
899     else
900     {
901     }
902     return error;
903 }
904
905 /*!
906  * @brief Control endpoint initialization function.
907  *
908  * This callback function is used to initialize the control pipes.
909  *
910  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
911  * @param param           The up layer handle.
912  *
913  * @return A USB error code or kStatus_USB_Success.
914  */
915 usb_status_t USB_DeviceControlPipeInit(usb_device_handle handle)
916 {
917     usb_device_endpoint_init_struct_t epInitStruct;
918     usb_device_endpoint_callback_struct_t endpointCallback;
919     usb_status_t error;
920
921     endpointCallback.callbackFn = USB_DeviceControlCallback;
922     endpointCallback.callbackParam = handle;
923
924     epInitStruct.zlt = 1U;
925     epInitStruct.transferType = USB_ENDPOINT_CONTROL;
926     epInitStruct.endpointAddress = USB_CONTROL_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
927     epInitStruct.maxPacketSize = USB_CONTROL_MAX_PACKET_SIZE;
928     /* Initialize the control IN pipe */
929     error = USB_DeviceInitEndpoint(handle, &epInitStruct, &endpointCallback);
930
931     if (kStatus_USB_Success != error)
932     {
933         return error;
934     }
935     epInitStruct.endpointAddress = USB_CONTROL_ENDPOINT | (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
936     /* Initialize the control OUT pipe */
937     error = USB_DeviceInitEndpoint(handle, &epInitStruct, &endpointCallback);
938
939     if (kStatus_USB_Success != error)
940     {
941         USB_DeviceDeinitEndpoint(handle,
942                                  USB_CONTROL_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT));
943         return error;
944     }
945
946     return kStatus_USB_Success;
947 }