Ejemplo n.º 1
0
/*!
 * @brief Handle set current configuration request.
 *
 * This function is used to handle set current configuration 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_DeviceCh9SetConfiguration(usb_device_common_class_struct_t *classHandle,
                                                  usb_setup_struct_t *setup,
                                                  uint8_t **buffer,
                                                  uint32_t *length)
{
    uint8_t state;

    USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state);

    if ((kUSB_DeviceStateAddress != state) && (kUSB_DeviceStateConfigured != state))
    {
        return kStatus_USB_InvalidRequest;
    }

    /* The device state is changed to kUSB_DeviceStateConfigured */
    state = kUSB_DeviceStateConfigured;
    USB_DeviceSetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state);
    if (!setup->wValue)
    {
        /* If the new configuration is zero, the device state is changed to kUSB_DeviceStateAddress */
        state = kUSB_DeviceStateAddress;
        USB_DeviceSetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state);
    }

    /* Notify the class layer the configuration is changed */
    USB_DeviceClassEvent(classHandle->handle, kUSB_DeviceClassEventSetConfiguration, &setup->wValue);
    /* Notify the application the configuration is changed */
    return USB_DeviceClassCallback(classHandle->handle, kUSB_DeviceEventSetConfiguration, &setup->wValue);
}
/*!
 * @brief Handle the common class callback.
 *
 * This function handles the common class callback.
 *
 * @param handle          The device handle, got from the USB_DeviceInit.
 * @param event           The event codes. Please refer to the enumeration usb_device_event_t.
 * @param param           The param type is determined by the event code.
 *
 * @return A USB error code or kStatus_USB_Success.
 */
usb_status_t USB_DeviceClassCallback(usb_device_handle handle, uint32_t event, void *param)
{
    usb_device_common_class_struct_t *classHandle;
    usb_status_t error = kStatus_USB_Error;

    /* Get the common class handle according to the device handle. */
    error = USB_DeviceClassGetHandleByDeviceHandle(handle, &classHandle);
    if (kStatus_USB_Success != error)
    {
        return error;
    }

    if (kUSB_DeviceEventBusReset == event)
    {
        /* Initialize the control pipes */
        USB_DeviceControlPipeInit(handle, classHandle);

        /* Notify the classes the USB bus reset signal detected. */
        USB_DeviceClassEvent(handle, kUSB_DeviceClassEventDeviceReset, classHandle);
    }

    /* Call the application device callback function. */
    error = classHandle->configList->deviceCallback(handle, event, param);
    return error;
}
Ejemplo n.º 3
0
/*!
 * @brief Handle set the alternate setting of a interface request.
 *
 * This function is used to handle set the alternate setting of a interface 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_DeviceCh9SetInterface(usb_device_common_class_struct_t *classHandle,
                                              usb_setup_struct_t *setup,
                                              uint8_t **buffer,
                                              uint32_t *length)
{
    uint8_t state;

    USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state);

    if (state != kUSB_DeviceStateConfigured)
    {
        return kStatus_USB_InvalidRequest;
    }
    classHandle->standardTranscationBuffer = ((setup->wIndex & 0xFFU) << 8U) | (setup->wValue & 0xFFU);
    /* Notify the class driver the alternate setting of the interface is changed. */
    /* The Bit[15~8] is used to save the interface index, and the alternate setting is saved in Bit[7~0]. */
    USB_DeviceClassEvent(classHandle->handle, kUSB_DeviceClassEventSetInterface,
                         &classHandle->standardTranscationBuffer);
    /* Notify the application the alternate setting of the interface is changed. */
    /* The Bit[15~8] is used to save the interface index, and the alternate setting will is saved in Bit[7~0]. */
    return USB_DeviceClassCallback(classHandle->handle, kUSB_DeviceEventSetInterface,
                                   &classHandle->standardTranscationBuffer);
}
Ejemplo n.º 4
0
/*!
 * @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);
    }
Ejemplo n.º 5
0
/*!
 * @brief Handle set or clear device feature request.
 *
 * This function is used to handle set or clear device feature 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_DeviceCh9SetClearFeature(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;
    uint8_t isSet = 0U;

    USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state);

    if ((kUSB_DeviceStateAddress != state) && (kUSB_DeviceStateConfigured != state))
    {
        return error;
    }

    /* Identify the request is set or clear the feature. */
    if (USB_REQUEST_STANDARD_SET_FEATURE == setup->bRequest)
    {
        isSet = 1U;
    }

    if ((setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) == USB_REQUEST_TYPE_RECIPIENT_DEVICE)
    {
        /* Set or Clear the device featrue. */
        if (USB_REQUEST_STANDARD_FEATURE_SELECTOR_DEVICE_REMOTE_WAKEUP == setup->wValue)
        {
            /* Set or Clear the device remote wakeup featrue. */
            error = USB_DeviceClassCallback(classHandle->handle, kUSB_DeviceEventSetRemoteWakeup, &isSet);
        }
#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 (USB_REQUEST_STANDARD_FEATURE_SELECTOR_DEVICE_TEST_MODE == setup->wValue)
        {
            state = kUSB_DeviceStateTestMode;
            error = USB_DeviceSetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state);
        }
#endif
        else
        {
        }
    }
    else if ((setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) == USB_REQUEST_TYPE_RECIPIENT_ENDPOINT)
    {
        /* Set or Clear the endpoint featrue. */
        if (USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT == setup->wValue)
        {
            if (USB_CONTROL_ENDPOINT == (setup->wIndex & USB_ENDPOINT_NUMBER_MASK))
            {
                /* Set or Clear the control endpoint status(halt or not). */
                if (isSet)
                {
                    USB_DeviceStallEndpoint(classHandle->handle, (uint8_t)setup->wIndex);
                }
                else
                {
                    USB_DeviceUnstallEndpoint(classHandle->handle, (uint8_t)setup->wIndex);
                }
            }

            /* Set or Clear the endpoint status featrue. */
            if (isSet)
            {
                error = USB_DeviceClassEvent(classHandle->handle, kUSB_DeviceClassEventSetEndpointHalt, &setup->wIndex);
            }
            else
            {
                error =
                    USB_DeviceClassEvent(classHandle->handle, kUSB_DeviceClassEventClearEndpointHalt, &setup->wIndex);
            }
        }
        else
        {
        }
    }
    else
    {
    }

    return error;
}