2 * The Clear BSD License
3 * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
4 * Copyright 2016-2017 NXP
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:
11 * o Redistributions of source code must retain the above copyright notice, this list
12 * of conditions and the following disclaimer.
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.
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.
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.
35 #include "usb_device_config.h"
38 #include "usb_device.h"
39 #include "usb_device_dci.h"
40 #include "usb_device_ch9.h"
42 /*******************************************************************************
44 ******************************************************************************/
47 * @brief Standard request callback function typedef.
49 * This function is used to handle the standard request.
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.
56 * @return A USB error code or kStatus_USB_Success.
58 typedef usb_status_t (*usb_standard_request_callback_t)(usb_device_handle handle,
59 usb_setup_struct_t *setup,
63 /*******************************************************************************
65 ******************************************************************************/
67 * @brief Get the setup packet buffer.
69 * The function is used to get the setup packet buffer to save the setup packet data.
71 * @param handle The device handle.
72 * @param setupBuffer It is an OUT parameter, return the setup buffer address to the caller.
74 * @return A USB error code or kStatus_USB_Success.
76 extern usb_status_t USB_DeviceGetSetupBuffer(usb_device_handle handle, usb_setup_struct_t **setupBuffer);
79 * @brief Handle the class request.
81 * The function is used to handle the class request.
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.
88 * @return A USB error code or kStatus_USB_Success.
90 extern usb_status_t USB_DeviceProcessClassRequest(usb_device_handle handle,
91 usb_setup_struct_t *setup,
96 * @brief Get the buffer to save the class specific data sent from host.
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
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.
107 * @return A USB error code or kStatus_USB_Success.
109 extern usb_status_t USB_DeviceGetClassReceiveBuffer(usb_device_handle handle,
110 usb_setup_struct_t *setup,
114 /* standard request */
116 * @brief Get the descritpor.
118 * The function is used to get the descritpor, including the device descritpor, configuration descriptor, and string
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.
126 * @return A USB error code or kStatus_USB_Success.
128 extern usb_status_t USB_DeviceGetDescriptor(usb_device_handle handle,
129 usb_setup_struct_t *setup,
134 * @brief Set the device configuration.
136 * The function is used to set the device configuration.
138 * @param handle The device handle.
139 * @param configure The configuration value.
141 * @return A USB error code or kStatus_USB_Success.
143 extern usb_status_t USB_DeviceSetConfigure(usb_device_handle handle, uint8_t configure);
146 * @brief Get the device configuration.
148 * The function is used to get the device configuration.
150 * @param handle The device handle.
151 * @param configure It is an OUT parameter, save the current configuration value.
153 * @return A USB error code or kStatus_USB_Success.
155 extern usb_status_t USB_DeviceGetConfigure(usb_device_handle handle, uint8_t *configure);
158 * @brief Set an interface alternate setting.
160 * The function is used to set an interface alternate setting.
162 * @param handle The device handle.
163 * @param interface The interface index.
164 * @param alternateSetting The new alternate setting value.
166 * @return A USB error code or kStatus_USB_Success.
168 extern usb_status_t USB_DeviceSetInterface(usb_device_handle handle, uint8_t interface, uint8_t alternateSetting);
171 * @brief Get an interface alternate setting.
173 * The function is used to get an interface alternate setting.
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.
179 * @return A USB error code or kStatus_USB_Success.
181 extern usb_status_t USB_DeviceGetInterface(usb_device_handle handle, uint8_t interface, uint8_t *alternateSetting);
184 * @brief Configure a specified endpoint status.
186 * The function is used to configure a specified endpoint status, idle or halt.
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.
192 * @return A USB error code or kStatus_USB_Success.
194 extern usb_status_t USB_DeviceConfigureEndpointStatus(usb_device_handle handle,
195 uint8_t endpointAddress,
199 * @brief Configure the device remote wakeup feature.
201 * The function is used to configure the device remote wakeup feature, enable or disbale the remote wakeup feature.
203 * @param handle The device handle.
204 * @param enable The new feature value of the device remote wakeup, 0 - disable, 1 - enable.
206 * @return A USB error code or kStatus_USB_Success.
208 extern usb_status_t USB_DeviceConfigureRemoteWakeup(usb_device_handle handle, uint8_t enable);
210 static usb_status_t USB_DeviceCh9GetStatus(usb_device_handle handle,
211 usb_setup_struct_t *setup,
214 static usb_status_t USB_DeviceCh9SetClearFeature(usb_device_handle handle,
215 usb_setup_struct_t *setup,
218 static usb_status_t USB_DeviceCh9SetAddress(usb_device_handle handle,
219 usb_setup_struct_t *setup,
222 static usb_status_t USB_DeviceCh9GetDescriptor(usb_device_handle handle,
223 usb_setup_struct_t *setup,
226 static usb_status_t USB_DeviceCh9GetConfiguration(usb_device_handle handle,
227 usb_setup_struct_t *setup,
230 static usb_status_t USB_DeviceCh9SetConfiguration(usb_device_handle handle,
231 usb_setup_struct_t *setup,
234 static usb_status_t USB_DeviceCh9GetInterface(usb_device_handle handle,
235 usb_setup_struct_t *setup,
238 static usb_status_t USB_DeviceCh9SetInterface(usb_device_handle handle,
239 usb_setup_struct_t *setup,
242 static usb_status_t USB_DeviceCh9SynchFrame(usb_device_handle handle,
243 usb_setup_struct_t *setup,
247 /*******************************************************************************
249 ******************************************************************************/
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,
269 * The internal global variable.
270 * This variable is used in:
272 * get configuration request
273 * get interface request
274 * set interface request
275 * get sync frame request
277 static uint16_t s_UsbDeviceStandardRx;
279 /*******************************************************************************
281 ******************************************************************************/
283 * @brief Handle get status request.
285 * This function is used to handle get status request.
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.
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.
296 static usb_status_t USB_DeviceCh9GetStatus(usb_device_handle handle,
297 usb_setup_struct_t *setup,
301 usb_status_t error = kStatus_USB_InvalidRequest;
304 USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
306 if ((kUSB_DeviceStateAddress != state) && (kUSB_DeviceStateConfigured != state))
311 if ((setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) == USB_REQUEST_TYPE_RECIPIENT_DEVICE)
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;
320 else if ((setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) == USB_REQUEST_TYPE_RECIPIENT_INTERFACE)
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;
328 else if ((setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) == USB_REQUEST_TYPE_RECIPIENT_ENDPOINT)
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;
343 *buffer = (uint8_t *)&s_UsbDeviceStandardRx;
349 * @brief Handle set or clear device feature request.
351 * This function is used to handle set or clear device feature request.
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.
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.
362 static usb_status_t USB_DeviceCh9SetClearFeature(usb_device_handle handle,
363 usb_setup_struct_t *setup,
367 usb_status_t error = kStatus_USB_InvalidRequest;
371 USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
373 if ((kUSB_DeviceStateAddress != state) && (kUSB_DeviceStateConfigured != state))
378 /* Identify the request is set or clear the feature. */
379 if (USB_REQUEST_STANDARD_SET_FEATURE == setup->bRequest)
384 if ((setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) == USB_REQUEST_TYPE_RECIPIENT_DEVICE)
386 /* Set or Clear the device featrue. */
387 if (USB_REQUEST_STANDARD_FEATURE_SELECTOR_DEVICE_REMOTE_WAKEUP == setup->wValue)
389 /* Set or Clear the device remote wakeup featrue. */
390 error = USB_DeviceConfigureRemoteWakeup(handle, isSet);
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)
396 state = kUSB_DeviceStateTestMode;
397 error = USB_DeviceSetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state);
404 else if ((setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) == USB_REQUEST_TYPE_RECIPIENT_ENDPOINT)
406 /* Set or Clear the endpoint featrue. */
407 if (USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT == setup->wValue)
409 if (USB_CONTROL_ENDPOINT == (setup->wIndex & USB_ENDPOINT_NUMBER_MASK))
411 /* Set or Clear the control endpoint status(halt or not). */
414 USB_DeviceStallEndpoint(handle, (uint8_t)setup->wIndex);
418 USB_DeviceUnstallEndpoint(handle, (uint8_t)setup->wIndex);
422 /* Set or Clear the endpoint status featrue. */
423 error = USB_DeviceConfigureEndpointStatus(handle, setup->wIndex, isSet);
437 * @brief Handle set address request.
439 * This function is used to handle set address request.
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.
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.
449 static usb_status_t USB_DeviceCh9SetAddress(usb_device_handle handle,
450 usb_setup_struct_t *setup,
454 usb_status_t error = kStatus_USB_InvalidRequest;
457 USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
459 if ((kUSB_DeviceStateAddressing != state) && (kUSB_DeviceStateAddress != state) &&
460 (kUSB_DeviceStateDefault != state))
465 if (kUSB_DeviceStateAddressing != state)
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);
474 /* If the device address is setting, set device address and the address will be write into the controller
476 error = USB_DeviceSetStatus(handle, kUSB_DeviceStatusAddress, NULL);
477 /* And then change the device state to kUSB_DeviceStateAddress. */
478 if (kStatus_USB_Success == error)
480 state = kUSB_DeviceStateAddress;
481 error = USB_DeviceSetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
489 * @brief Handle get descriptor request.
491 * This function is used to handle get descriptor request.
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.
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.
502 static usb_status_t USB_DeviceCh9GetDescriptor(usb_device_handle handle,
503 usb_setup_struct_t *setup,
509 USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
511 if ((kUSB_DeviceStateAddress != state) && (kUSB_DeviceStateConfigured != state) &&
512 (kUSB_DeviceStateDefault != state))
514 return kStatus_USB_InvalidRequest;
517 return USB_DeviceGetDescriptor(handle, setup, length, buffer);
521 * @brief Handle get current configuration request.
523 * This function is used to handle get current configuration request.
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.
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.
534 static usb_status_t USB_DeviceCh9GetConfiguration(usb_device_handle handle,
535 usb_setup_struct_t *setup,
541 USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
543 if ((kUSB_DeviceStateAddress != state) && ((kUSB_DeviceStateConfigured != state)))
545 return kStatus_USB_InvalidRequest;
548 *length = USB_CONFIGURE_SIZE;
549 *buffer = (uint8_t *)&s_UsbDeviceStandardRx;
550 return USB_DeviceGetConfigure(handle, (uint8_t *)&s_UsbDeviceStandardRx);
554 * @brief Handle set current configuration request.
556 * This function is used to handle set current configuration request.
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.
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.
567 static usb_status_t USB_DeviceCh9SetConfiguration(usb_device_handle handle,
568 usb_setup_struct_t *setup,
574 USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
576 if ((kUSB_DeviceStateAddress != state) && (kUSB_DeviceStateConfigured != state))
578 return kStatus_USB_InvalidRequest;
581 /* The device state is changed to kUSB_DeviceStateConfigured */
582 state = kUSB_DeviceStateConfigured;
583 USB_DeviceSetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
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);
591 return USB_DeviceSetConfigure(handle, setup->wValue);
595 * @brief Handle get the alternate setting of a interface request.
597 * This function is used to handle get the alternate setting of a interface request.
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.
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.
608 static usb_status_t USB_DeviceCh9GetInterface(usb_device_handle handle,
609 usb_setup_struct_t *setup,
613 usb_status_t error = kStatus_USB_InvalidRequest;
616 USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
618 if (state != kUSB_DeviceStateConfigured)
622 *length = USB_INTERFACE_SIZE;
623 *buffer = (uint8_t *)&s_UsbDeviceStandardRx;
625 return USB_DeviceGetInterface(handle, setup->wIndex & 0xFFU, (uint8_t *)&s_UsbDeviceStandardRx);
629 * @brief Handle set the alternate setting of a interface request.
631 * This function is used to handle set the alternate setting of a interface request.
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.
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.
642 static usb_status_t USB_DeviceCh9SetInterface(usb_device_handle handle,
643 usb_setup_struct_t *setup,
649 USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
651 if (state != kUSB_DeviceStateConfigured)
653 return kStatus_USB_InvalidRequest;
656 return USB_DeviceSetInterface(handle, (setup->wIndex & 0xFFU), (setup->wValue & 0xFFU));
660 * @brief Handle get sync frame request.
662 * This function is used to handle get sync frame request.
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.
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.
673 static usb_status_t USB_DeviceCh9SynchFrame(usb_device_handle handle,
674 usb_setup_struct_t *setup,
678 usb_status_t error = kStatus_USB_InvalidRequest;
681 USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
683 if (state != kUSB_DeviceStateConfigured)
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);
698 * @brief Send the reponse to the host.
700 * This function is used to send the reponse to the host.
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.
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.
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.
721 * @return A USB error code or kStatus_USB_Success.
723 static usb_status_t USB_DeviceControlCallbackFeedback(usb_device_handle handle,
724 usb_setup_struct_t *setup,
726 usb_device_control_read_write_sequence_t stage,
730 usb_status_t errorCode = kStatus_USB_Error;
731 uint8_t direction = USB_IN;
733 if (kStatus_USB_InvalidRequest == error)
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))
742 errorCode = USB_DeviceStallEndpoint(
744 (USB_CONTROL_ENDPOINT) | (uint8_t)((uint32_t)direction << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT));
748 if (*length > setup->wLength)
750 *length = setup->wLength;
752 errorCode = USB_DeviceSendRequest(handle, (USB_CONTROL_ENDPOINT), *buffer, *length);
754 if ((kStatus_USB_Success == errorCode) &&
755 (USB_REQUEST_TYPE_DIR_IN == (setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK)))
757 errorCode = USB_DeviceRecvRequest(handle, (USB_CONTROL_ENDPOINT), (uint8_t *)NULL, 0U);
764 * @brief Control endpoint callback function.
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.
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.
775 * @return A USB error code or kStatus_USB_Success.
777 usb_status_t USB_DeviceControlCallback(usb_device_handle handle,
778 usb_device_endpoint_callback_message_struct_t *message,
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;
788 if (USB_UNINITIALIZED_VAL_32 == message->length)
793 USB_DeviceGetSetupBuffer(handle, &deviceSetup);
794 USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state);
796 if (message->isSetup)
798 if ((USB_SETUP_PACKET_SIZE != message->length) || (NULL == message->buffer))
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.
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);
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;
821 if ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_MASK) == USB_REQUEST_TYPE_TYPE_STANDARD)
823 /* Handle the standard request */
824 if (s_UsbDeviceStandardRequest[deviceSetup->bRequest] != (usb_standard_request_callback_t)NULL)
826 error = s_UsbDeviceStandardRequest[deviceSetup->bRequest](handle, deviceSetup, &buffer, &length);
831 if ((deviceSetup->wLength) &&
832 ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_OUT))
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))
838 /* Get data buffer to receive the data from the host. */
839 length = deviceSetup->wLength;
840 error = USB_DeviceGetClassReceiveBuffer(handle, deviceSetup, &length, &setupOutBuffer);
846 if (kStatus_USB_Success == error)
848 /* Prime an OUT transfer */
849 error = USB_DeviceRecvRequest(handle, USB_CONTROL_ENDPOINT, setupOutBuffer, deviceSetup->wLength);
855 /* Class or vendor request with the IN data phase. */
856 if (((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_CLASS) == USB_REQUEST_TYPE_TYPE_CLASS))
858 /* Get data buffer to response the host. */
859 error = USB_DeviceProcessClassRequest(handle, deviceSetup, &length, &buffer);
866 /* Send the reponse to the host. */
867 error = USB_DeviceControlCallbackFeedback(handle, deviceSetup, error, kUSB_DeviceControlPipeSetupStage, &buffer,
870 else if (kUSB_DeviceStateAddressing == state)
872 /* Set the device address to controller. */
873 error = s_UsbDeviceStandardRequest[deviceSetup->bRequest](handle, deviceSetup, &buffer, &length);
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)
879 uint8_t portTestControl = (uint8_t)(deviceSetup->wIndex >> 8);
880 /* Set the controller.into test mode. */
881 error = USB_DeviceSetStatus(handle, kUSB_DeviceStatusTestMode, &portTestControl);
884 else if ((message->length) && (deviceSetup->wLength) &&
885 ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_OUT))
887 if (((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_CLASS) == USB_REQUEST_TYPE_TYPE_CLASS))
889 /* Data received in OUT phase, and notify the class driver. */
890 error = USB_DeviceProcessClassRequest(handle, deviceSetup, &message->length, &message->buffer);
895 /* Send the reponse to the host. */
896 error = USB_DeviceControlCallbackFeedback(handle, deviceSetup, error, kUSB_DeviceControlPipeDataStage, &buffer,
906 * @brief Control endpoint initialization function.
908 * This callback function is used to initialize the control pipes.
910 * @param handle The device handle. It equals the value returned from USB_DeviceInit.
911 * @param param The up layer handle.
913 * @return A USB error code or kStatus_USB_Success.
915 usb_status_t USB_DeviceControlPipeInit(usb_device_handle handle)
917 usb_device_endpoint_init_struct_t epInitStruct;
918 usb_device_endpoint_callback_struct_t endpointCallback;
921 endpointCallback.callbackFn = USB_DeviceControlCallback;
922 endpointCallback.callbackParam = handle;
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);
931 if (kStatus_USB_Success != error)
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);
939 if (kStatus_USB_Success != error)
941 USB_DeviceDeinitEndpoint(handle,
942 USB_CONTROL_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT));
946 return kStatus_USB_Success;