/*! * @brief Handle get sync frame request. * * This function is used to handle get sync frame request. * * @param handle The device handle. It equals the value returned from USB_DeviceInit. * @param setup The pointer of the setup packet. * @param buffer It is an out parameter, is used to save the buffer address to response the host's request. * @param length It is an out parameter, the data length. * * @retval kStatus_USB_Success The requst is handled successfully. * @retval kStatus_USB_InvalidRequest The request can not be handle in current device state, * or, the request is unsupported. */ static usb_status_t USB_DeviceCh9SynchFrame(usb_device_common_class_struct_t *classHandle, usb_setup_struct_t *setup, uint8_t **buffer, uint32_t *length) { usb_status_t error = kStatus_USB_InvalidRequest; uint8_t state; USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state); if (state != kUSB_DeviceStateConfigured) { return error; } classHandle->standardTranscationBuffer = USB_SHORT_FROM_LITTLE_ENDIAN(setup->wIndex); /* Get the sync frame value */ error = USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusSynchFrame, &classHandle->standardTranscationBuffer); *buffer = (uint8_t *)&classHandle->standardTranscationBuffer; *length = sizeof(classHandle->standardTranscationBuffer); return error; }
/*! * @brief Control endpoint callback function. * * This callback function is used to notify uplayer the tranfser result of a transfer. * This callback pointer is passed when a sepcified endpoint initialied by calling API USB_DeviceInitEndpoint. * * @param handle The device handle. It equals the value returned from USB_DeviceInit. * @param message The result of a transfer, includes transfer buffer, transfer length and whether is in setup * phase for control pipe. * @param callbackParam The paramter for this callback. It is same with * usb_device_endpoint_callback_struct_t::callbackParam. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceControlCallback(usb_device_handle handle, usb_device_endpoint_callback_message_struct_t *message, void *callbackParam) { usb_setup_struct_t *deviceSetup; usb_device_common_class_struct_t *classHandle; uint8_t *buffer = (uint8_t *)NULL; uint32_t length = 0U; usb_status_t error = kStatus_USB_InvalidRequest; uint8_t state; if ((0xFFFFFFFFU == message->length) || (NULL == callbackParam)) { return error; } classHandle = (usb_device_common_class_struct_t *)callbackParam; deviceSetup = (usb_setup_struct_t *)&classHandle->setupBuffer[0]; USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state); if (message->isSetup) { if ((USB_SETUP_PACKET_SIZE != message->length) || (NULL == message->buffer)) { /* If a invalid setup is received, the control pipes should be de-init and init again. * Due to the IP can not meet this require, it is revesed for feature. */ /* USB_DeviceDeinitEndpoint(handle, USB_CONTROL_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)); USB_DeviceDeinitEndpoint(handle, USB_CONTROL_ENDPOINT | (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)); USB_DeviceControlPipeInit(handle, callbackParam); */ return error; } /* Receive a setup request */ usb_setup_struct_t *setup = (usb_setup_struct_t *)(message->buffer); /* Copy the setup packet to the application buffer */ deviceSetup->wValue = USB_SHORT_FROM_LITTLE_ENDIAN(setup->wValue); deviceSetup->wIndex = USB_SHORT_FROM_LITTLE_ENDIAN(setup->wIndex); deviceSetup->wLength = USB_SHORT_FROM_LITTLE_ENDIAN(setup->wLength); deviceSetup->bRequest = setup->bRequest; deviceSetup->bmRequestType = setup->bmRequestType; if ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_MASK) == USB_REQUEST_TYPE_TYPE_STANDARD) { /* Handle the standard request */ if (s_UsbDeviceStandardRequest[deviceSetup->bRequest] != (usb_standard_request_callback_t)NULL) { error = s_UsbDeviceStandardRequest[deviceSetup->bRequest](classHandle, deviceSetup, &buffer, &length); } } else { if ((deviceSetup->wLength) && ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_OUT)) { /* Class or vendor request with the OUT data phase. */ if ((deviceSetup->wLength) && ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_CLASS) == USB_REQUEST_TYPE_TYPE_CLASS)) { /* Get data buffer to receive the data from the host. */ usb_device_control_request_struct_t controlRequest; controlRequest.buffer = (uint8_t *)NULL; controlRequest.isSetup = 1U; controlRequest.setup = deviceSetup; controlRequest.length = deviceSetup->wLength; error = USB_DeviceClassEvent(handle, kUSB_DeviceClassEventClassRequest, &controlRequest); length = controlRequest.length; buffer = controlRequest.buffer; } else if ((deviceSetup->wLength) && ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_VENDOR) == USB_REQUEST_TYPE_TYPE_VENDOR)) { /* Get data buffer to receive the data from the host. */ usb_device_control_request_struct_t controlRequest; controlRequest.buffer = (uint8_t *)NULL; controlRequest.isSetup = 1U; controlRequest.setup = deviceSetup; controlRequest.length = deviceSetup->wLength; error = USB_DeviceClassCallback(handle, kUSB_DeviceEventVendorRequest, &controlRequest); length = controlRequest.length; buffer = controlRequest.buffer; } else { } if (kStatus_USB_Success == error) { /* Prime an OUT transfer */ error = USB_DeviceRecvRequest(handle, USB_CONTROL_ENDPOINT, buffer, deviceSetup->wLength); return error; } } else { /* Class or vendor request with the IN data phase. */ if (((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_CLASS) == USB_REQUEST_TYPE_TYPE_CLASS)) { /* Get data buffer to response the host. */ usb_device_control_request_struct_t controlRequest; controlRequest.buffer = (uint8_t *)NULL; controlRequest.isSetup = 1U; controlRequest.setup = deviceSetup; controlRequest.length = deviceSetup->wLength; error = USB_DeviceClassEvent(handle, kUSB_DeviceClassEventClassRequest, &controlRequest); length = controlRequest.length; buffer = controlRequest.buffer; } else if (((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_VENDOR) == USB_REQUEST_TYPE_TYPE_VENDOR)) { /* Get data buffer to response the host. */ usb_device_control_request_struct_t controlRequest; controlRequest.buffer = (uint8_t *)NULL; controlRequest.isSetup = 1U; controlRequest.setup = deviceSetup; controlRequest.length = deviceSetup->wLength; error = USB_DeviceClassCallback(handle, kUSB_DeviceEventVendorRequest, &controlRequest); length = controlRequest.length; buffer = controlRequest.buffer; } else { } } } /* Send the reponse to the host. */ error = USB_DeviceControlCallbackFeedback(handle, deviceSetup, error, kUSB_DeviceControlPipeSetupStage, &buffer, &length); } else if (kUSB_DeviceStateAddressing == state) { /* Set the device address to controller. */ error = s_UsbDeviceStandardRequest[deviceSetup->bRequest](classHandle, deviceSetup, &buffer, &length); } #if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)) && \ (defined(USB_DEVICE_CONFIG_EHCI_TEST_MODE) && (USB_DEVICE_CONFIG_EHCI_TEST_MODE > 0U)) else if (kUSB_DeviceStateTestMode == state) { uint8_t portTestControl = (uint8_t)(deviceSetup->wIndex >> 8); /* Set the controller.into test mode. */ error = USB_DeviceSetStatus(handle, kUSB_DeviceStatusTestMode, &portTestControl); }