Esempio n. 1
0
//------------------------------------------------------------------------------
/// Sends the current status of the device to the host.
/// \param pDriver  Pointer to a USBDDriver instance.
//------------------------------------------------------------------------------
static void GetDeviceStatus(const USBDDriver *pDriver)
{
    static unsigned short data;
    const USBConfigurationDescriptor *pConfiguration;

    data = 0;
    // Use different configuration depending on device speed
    if (USBD_IsHighSpeed()) {

        pConfiguration = pDriver->pDescriptors->pHsConfiguration;
    }
    else {

        pConfiguration = pDriver->pDescriptors->pFsConfiguration;
    }

    // Check current configuration for power mode (if device is configured)
    if (pDriver->cfgnum != 0) {

        if (USBConfigurationDescriptor_IsSelfPowered(pConfiguration)) {

            data |= 1;
        }
    }

    // Check if remote wake-up is enabled
    if (pDriver->isRemoteWakeUpEnabled) {

        data |= 2;
    }

    // Send the device status
    USBD_Write(0, &data, 2, 0, 0);
}
Esempio n. 2
0
/**
 * Returns the descriptor requested by the host.
 * \param type Descriptor type.
 * \param length Maximum number of bytes to send.
 * \return 1 if the request has been handled by this function, otherwise 0.
 */
static uint8_t HIDDTransferDriver_GetDescriptor(uint8_t type,
                                                uint8_t length)
{
    HIDDTransferDriver *pDrv = &hiddTransferDriver;
    HIDDFunction *pHidd = &pDrv->hidFunction;

    const USBConfigurationDescriptor *pConfiguration;
    HIDDescriptor *hidDescriptors[2];

    switch (type) {

        case HIDGenericDescriptor_REPORT:
            TRACE_INFO("Report ");

            /* Adjust length and send report descriptor */
            if (length > HIDDTransferDriver_REPORTDESCRIPTORSIZE) {

                length = HIDDTransferDriver_REPORTDESCRIPTORSIZE;
            }
            USBD_Write(0, &hiddTransferReportDescriptor, length, 0, 0);
            break;

        case HIDGenericDescriptor_HID:
            TRACE_INFO("HID ");

            /* Configuration descriptor is different depending on configuration */
            if (USBD_IsHighSpeed()) {

                pConfiguration =
                   pHidd->pUsbd->pDescriptors->pHsConfiguration;
            }
            else {

                pConfiguration =
                   pHidd->pUsbd->pDescriptors->pFsConfiguration;
            }

            /* Parse the device configuration to get the HID descriptor */
            USBConfigurationDescriptor_Parse(pConfiguration, 0, 0,
                                     (USBGenericDescriptor **) hidDescriptors);

            /* Adjust length and send HID descriptor */
            if (length > sizeof(HIDDescriptor)) {

                length = sizeof(HIDDescriptor);
            }
            USBD_Write(0, hidDescriptors[0], length, 0, 0);
            break;

        default:
            return 0;
    }

    return 1;
}
Esempio n. 3
0
/**
 * Configures the device by setting it into the Configured state and
 * initializing all endpoints.
 * \param pDriver  Pointer to a USBDDriver instance.
 * \param cfgnum  Configuration number to set.
 */
static void SetConfiguration(USBDDriver *pDriver, uint8_t cfgnum)
{
    USBEndpointDescriptor *pEndpoints[17];
    const USBConfigurationDescriptor *pConfiguration;

    /* Use different descriptor depending on device speed */

    if (USBD_IsHighSpeed()) {

        pConfiguration = pDriver->pDescriptors->pHsConfiguration;
    }
    else {

        pConfiguration = pDriver->pDescriptors->pFsConfiguration;
    }

    /* Set & save the desired configuration */
    USBD_SetConfiguration(cfgnum);

    pDriver->cfgnum = cfgnum;
    pDriver->isRemoteWakeUpEnabled =
        ((pConfiguration->bmAttributes & 0x20) > 0);

    /* If the configuration is not 0, configure endpoints */
    if (cfgnum != 0) {

        /* Parse configuration to get endpoint descriptors */
        USBConfigurationDescriptor_Parse(pConfiguration, 0, pEndpoints, 0);

        /* Configure endpoints */
        int i = 0;
        while (pEndpoints[i] != 0) {

            USBD_ConfigureEndpoint(pEndpoints[i]);
            i++;
        }
    }
    /* Should be done before send the ZLP */
    USBDDriverCallbacks_ConfigurationChanged(cfgnum);

    /* Acknowledge the request */
    USBD_Write(0, /* Endpoint #0 */
               0, /* No data buffer */
               0, /* No data buffer */
               (TransferCallback) 0,
               (void *)  0);
}
Esempio n. 4
0
//------------------------------------------------------------------------------
/// Configures the device by setting it into the Configured state and
/// initializing all endpoints.
/// \param pDriver  Pointer to a USBDDriver instance.
/// \param cfgnum  Configuration number to set.
//------------------------------------------------------------------------------
static void SetConfiguration(USBDDriver *pDriver, unsigned char cfgnum)
{
    USBEndpointDescriptor *pEndpoints[CHIP_USB_NUMENDPOINTS+1];
    const USBConfigurationDescriptor *pConfiguration;

    // Use different descriptor depending on device speed
    if (USBD_IsHighSpeed()) {

        pConfiguration = pDriver->pDescriptors->pHsConfiguration;
    }
    else {

        pConfiguration = pDriver->pDescriptors->pFsConfiguration;
    }

    // Set & save the desired configuration
    USBD_SetConfiguration(cfgnum);
    pDriver->cfgnum = cfgnum;

    // If the configuration is not 0, configure endpoints
    if (cfgnum != 0) {
    
        // Parse configuration to get endpoint descriptors
        USBConfigurationDescriptor_Parse(pConfiguration, 0, pEndpoints, 0);
    
        // Configure endpoints
        int i = 0;
        while (pEndpoints[i] != 0) {
    
            USBD_ConfigureEndpoint(pEndpoints[i]);
            i++;
        }
    }
    // Should be done before send the ZLP
    USBDDriverCallbacks_ConfigurationChanged(cfgnum);

    // Acknowledge the request
    USBD_Write(0, // Endpoint #0
               0, // No data buffer
               0, // No data buffer
               (TransferCallback) 0,
               (void *)  0);
}
Esempio n. 5
0
//------------------------------------------------------------------------------
/// Sends the requested USB descriptor to the host if available, or STALLs  the
/// request.
/// \param pDriver  Pointer to a USBDDriver instance.
/// \param type  Type of the requested descriptor
/// \param index  Index of the requested descriptor.
/// \param length  Maximum number of bytes to return.
//------------------------------------------------------------------------------
static void GetDescriptor(
    const USBDDriver *pDriver,
    unsigned char type,
    unsigned char indexRDesc,
    unsigned int length)
{
    const USBDeviceDescriptor *pDevice;
    const USBConfigurationDescriptor *pConfiguration;
    const USBDeviceQualifierDescriptor *pQualifier;
    const USBConfigurationDescriptor *pOtherSpeed;
    const USBGenericDescriptor **pStrings =
        (const USBGenericDescriptor **) pDriver->pDescriptors->pStrings;
    const USBGenericDescriptor *pString;
    unsigned char numStrings = pDriver->pDescriptors->numStrings;
    unsigned char terminateWithNull = 0;

    // Use different set of descriptors depending on device speed
    if (USBD_IsHighSpeed()) {

        TRACE_DEBUG("HS ");
        pDevice = pDriver->pDescriptors->pHsDevice;
        pConfiguration = pDriver->pDescriptors->pHsConfiguration;
        pQualifier = pDriver->pDescriptors->pHsQualifier;
        pOtherSpeed = pDriver->pDescriptors->pHsOtherSpeed;
    }
    else {

        TRACE_DEBUG("FS ");
        pDevice = pDriver->pDescriptors->pFsDevice;
        pConfiguration = pDriver->pDescriptors->pFsConfiguration;
        pQualifier = pDriver->pDescriptors->pFsQualifier;
        pOtherSpeed = pDriver->pDescriptors->pFsOtherSpeed;
    }

    // Check the descriptor type
    switch (type) {
        
        case USBGenericDescriptor_DEVICE:
            TRACE_INFO_WP("Dev ");

            // Adjust length and send descriptor
            if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice)) {

                length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice);
            }
            USBD_Write(0, pDevice, length, 0, 0);
            break;

        case USBGenericDescriptor_CONFIGURATION:
            TRACE_INFO_WP("Cfg ");

            // Adjust length and send descriptor
            if (length > USBConfigurationDescriptor_GetTotalLength(pConfiguration)) {

                length = USBConfigurationDescriptor_GetTotalLength(pConfiguration);
                terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
            }
            USBD_Write(0,
                       pConfiguration,
                       length,
                       terminateWithNull ? TerminateCtrlInWithNull : 0,
                       0);
            break;

        case USBGenericDescriptor_DEVICEQUALIFIER:
            TRACE_INFO_WP("Qua ");

            // Check if descriptor exists
            if (!pQualifier) {

                USBD_Stall(0);
            }
            else {

                // Adjust length and send descriptor
                if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier)) {

                    length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier);
                }
                USBD_Write(0, pQualifier, length, 0, 0);
            }
            break;

        case USBGenericDescriptor_OTHERSPEEDCONFIGURATION:
            TRACE_INFO_WP("OSC ");

            // Check if descriptor exists
            if (!pOtherSpeed) {

                USBD_Stall(0);
            }
            else {

                // Adjust length and send descriptor
                if (length > USBConfigurationDescriptor_GetTotalLength(pOtherSpeed)) {

                    length = USBConfigurationDescriptor_GetTotalLength(pOtherSpeed);
                    terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
                }
                USBD_Write(0,
                           pOtherSpeed,
                           length,
                           terminateWithNull ? TerminateCtrlInWithNull : 0,
                           0);
            }
            break;

        case USBGenericDescriptor_STRING:
            TRACE_INFO_WP("Str%d ", indexRDesc);

            // Check if descriptor exists
            if (indexRDesc > numStrings) {

                USBD_Stall(0);
            }
            else {

                pString = pStrings[indexRDesc];

                // Adjust length and send descriptor
                if (length > USBGenericDescriptor_GetLength(pString)) {

                    length = USBGenericDescriptor_GetLength(pString);
                    terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
                }
                USBD_Write(0,
                           pString,
                           length,
                           terminateWithNull ? TerminateCtrlInWithNull : 0,
                           0);
            }
            break;

        default:
            TRACE_WARNING(
                      "USBDDriver_GetDescriptor: Unknown descriptor type (%d)\n\r",
                      type);
            USBD_Stall(0);
    }
}
Esempio n. 6
0
// https://github.com/pbatard/libwdi/wiki/WCID-Devices
static void GetMSDescriptor(
    const USBDDriver *pDriver,
    uint16_t indexRDesc,
    uint32_t length)
{
    const USBDeviceDescriptor *pDevice;
    uint8_t terminateWithNull = 0;

    /* Use different set of descriptors depending on device speed */
    if (USBD_IsHighSpeed()) {
        TRACE_DEBUG("HS ");
        pDevice = pDriver->pDescriptors->pHsDevice;
    }
    else {
        TRACE_DEBUG("FS ");
        pDevice = pDriver->pDescriptors->pFsDevice;
    }

    /* Check the descriptor index */
    switch (indexRDesc) {
        // https://github.com/pbatard/libwdi/wiki/WCID-Devices
        case 0x0004: { // Extended Compat ID (Microsoft OS 1.0 Descriptors)
            const uint8_t extendedCompatID[] = {
                0x28, 0x00, 0x00, 0x00, // dwLength
                0x00, 0x01, // bcdVersion
                0x04, 0x00, // wIndex
                0x01, // bCount
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved
                0x00, // bFirstInterfaceNumber
                0x01, // Reserved
                0x57, 0x49, 0x4E, 0x55, 0x53, 0x42, 0x00, 0x00, // CompatibleID "WINUSB\0\0"
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // SubCompatibleID
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Reserved
            };
            const uint8_t extendedCompatIDLength = sizeof(extendedCompatID);

            /* Adjust length and send descriptor */
            if (length > extendedCompatIDLength) {
                length = extendedCompatIDLength;
                terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
            }

            terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);

            USBD_Write(0,
                       extendedCompatID,
                       length,
                       terminateWithNull ? TerminateCtrlInWithNull : 0,
                       0);

            break;
        }
        case 0x0005: { // Extended Properties (Microsoft OS 1.0 Descriptors)
            const uint8_t extendedProperties[] = {
                0x92, 0x00, 0x00, 0x00, // dwLength
                0x00, 0x01, // bcdVersion
                0x05, 0x00, // wIndex
                0x01, 0x00, // wCount
                0x88, 0x00, 0x00, 0x00, // dwSize
                0x07, 0x00, 0x00, 0x00, // dwPropertyDataType
                0x2a, 0x00, // wPropertyNameLength
                0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00,
                0x49, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x66, 0x00,
                0x61, 0x00, 0x63, 0x00, 0x65, 0x00, 0x47, 0x00, 0x55, 0x00, 0x49, 0x00,
                0x44, 0x00, 0x73, 0x00, 0x00, 0x00, // bPropertyName "DeviceInterfaceGUIDs\0"
                0x50, 0x00, 0x00, 0x00, // dwPropertyDataLength
                0x7b, 0x00, 0x38, 0x00, 0x37, 0x00, 0x30, 0x00, 0x30, 0x00, 0x31, 0x00,
                0x33, 0x00, 0x44, 0x00, 0x44, 0x00, 0x2d, 0x00, 0x46, 0x00, 0x42, 0x00,
                0x31, 0x00, 0x44, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x42, 0x00, 0x44, 0x00,
                0x37, 0x00, 0x2d, 0x00, 0x41, 0x00, 0x39, 0x00, 0x36, 0x00, 0x43, 0x00,
                0x2d, 0x00, 0x31, 0x00, 0x46, 0x00, 0x30, 0x00, 0x42, 0x00, 0x37, 0x00,
                0x44, 0x00, 0x33, 0x00, 0x31, 0x00, 0x41, 0x00, 0x46, 0x00, 0x34, 0x00,
                0x31, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, // bPropertyData "{870013DD-FB1D-4BD7-A96C-1F0B7D31AF41}\0\0"
            };
            const uint8_t extendedPropertiesLength = sizeof(extendedProperties);

            /* Adjust length and send descriptor */
            if (length > extendedPropertiesLength) {
                length = extendedPropertiesLength;
                terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
            }

            terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);

            USBD_Write(0,
                       extendedProperties,
                       length,
                       terminateWithNull ? TerminateCtrlInWithNull : 0,
                       0);

            break;
        }

        default:
            TRACE_WARNING(
                      "USBDDriver_GetMSDescriptor: Unknown descriptor index (%d)\n\r",
                      indexRDesc);
            USBD_Stall(0);
    }
}
Esempio n. 7
0
/**
 * Sends the requested USB descriptor to the host if available, or STALLs  the
 * request.
 * \param pDriver  Pointer to a USBDDriver instance.
 * \param type  Type of the requested descriptor
 * \param index  Index of the requested descriptor.
 * \param length  Maximum number of bytes to return.
 */
static void GetDescriptor(
    const USBDDriver *pDriver,
    uint8_t type,
    uint8_t indexRDesc,
    uint32_t length)
{
    const USBDeviceDescriptor *pDevice;
    const USBConfigurationDescriptor *pConfiguration;
    const USBDeviceQualifierDescriptor *pQualifier;
    const USBConfigurationDescriptor *pOtherSpeed;
    const USBGenericDescriptor **pStrings =
        (const USBGenericDescriptor **) pDriver->pDescriptors->pStrings;
    const USBGenericDescriptor *pString;
    uint8_t numStrings = pDriver->pDescriptors->numStrings;
    uint8_t terminateWithNull = 0;

    /* Use different set of descriptors depending on device speed */

    if (USBD_IsHighSpeed()) {

        TRACE_DEBUG("HS ");
        pDevice = pDriver->pDescriptors->pHsDevice;
        pConfiguration = pDriver->pDescriptors->pHsConfiguration;
        pQualifier = pDriver->pDescriptors->pHsQualifier;
        pOtherSpeed = pDriver->pDescriptors->pHsOtherSpeed;
    }
    else {

        TRACE_DEBUG("FS ");
        pDevice = pDriver->pDescriptors->pFsDevice;
        pConfiguration = pDriver->pDescriptors->pFsConfiguration;
        pQualifier = pDriver->pDescriptors->pFsQualifier;
        pOtherSpeed = pDriver->pDescriptors->pFsOtherSpeed;
    }

    /* Check the descriptor type */

    switch (type) {

        case USBGenericDescriptor_DEVICE:
            TRACE_INFO_WP("Dev ");

            /* Adjust length and send descriptor */

            if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice)) {

                length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice);
            }
            USBD_Write(0, pDevice, length, 0, 0);
            break;

        case USBGenericDescriptor_CONFIGURATION:
            TRACE_INFO_WP("Cfg ");

            /* Adjust length and send descriptor */

            if (length > USBConfigurationDescriptor_GetTotalLength(pConfiguration)) {

                length = USBConfigurationDescriptor_GetTotalLength(pConfiguration);
                terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
            }
            USBD_Write(0,
                       pConfiguration,
                       length,
                       terminateWithNull ? TerminateCtrlInWithNull : 0,
                       0);
            break;

        case USBGenericDescriptor_DEVICEQUALIFIER:
            TRACE_INFO_WP("Qua ");

            /* Check if descriptor exists */

            if (!pQualifier) {

                USBD_Stall(0);
            }
            else {

                /* Adjust length and send descriptor */

                if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier)) {

                    length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier);
                }
                USBD_Write(0, pQualifier, length, 0, 0);
            }
            break;

        case USBGenericDescriptor_OTHERSPEEDCONFIGURATION:
            TRACE_INFO_WP("OSC ");

            /* Check if descriptor exists */

            if (!pOtherSpeed) {

                USBD_Stall(0);
            }
            else {

                /* Adjust length and send descriptor */

                if (length > USBConfigurationDescriptor_GetTotalLength(pOtherSpeed)) {

                    length = USBConfigurationDescriptor_GetTotalLength(pOtherSpeed);
                    terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
                }
                USBD_Write(0,
                           pOtherSpeed,
                           length,
                           terminateWithNull ? TerminateCtrlInWithNull : 0,
                           0);
            }
            break;

        case USBGenericDescriptor_STRING:
            TRACE_INFO_WP("Str%d ", indexRDesc);

            /* Check if descriptor exists */
            if (indexRDesc == 0xEE) {
                // https://github.com/pbatard/libwdi/wiki/WCID-Devices
                const uint8_t osStringDescriptor[] = {
                    0x12, // bLength
                    USBGenericDescriptor_STRING, // bDescriptorType
                    0x4D, 0x00, 0x53, 0x00, 0x46, 0x00, 0x54, 0x00, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00, // qwSignature
                    USBGenericRequest_GETMSDESCRIPTOR, // bMS_VendorCode
                    0x00, // bPad
                };
                const uint8_t osStringDescriptorLength = sizeof(osStringDescriptor);

                /* Adjust length and send descriptor */
                if (length > osStringDescriptorLength) {
                    length = osStringDescriptorLength;
                    terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
                }

                USBD_Write(0,
                           osStringDescriptor,
                           length,
                           terminateWithNull ? TerminateCtrlInWithNull : 0,
                           0);
            }
            else if (indexRDesc >= numStrings) {
                USBD_Stall(0);
            }
            else {

                pString = pStrings[indexRDesc];

                /* Adjust length and send descriptor */

                if (length > USBGenericDescriptor_GetLength(pString)) {

                    length = USBGenericDescriptor_GetLength(pString);
                    terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
                }
                USBD_Write(0,
                           pString,
                           length,
                           terminateWithNull ? TerminateCtrlInWithNull : 0,
                           0);
            }
            break;

        default:
            TRACE_WARNING(
                      "USBDDriver_GetDescriptor: Unknown descriptor type (%d)\n\r",
                      type);
            USBD_Stall(0);
    }
}
Esempio n. 8
0
//------------------------------------------------------------------------------
/// Handles the given request if it is standard, otherwise STALLs it.
/// \param pDriver  Pointer to a USBDDriver instance.
/// \param pRequest  Pointer to a USBGenericRequest instance.
//------------------------------------------------------------------------------
void USBDDriver_RequestHandler(
    USBDDriver *pDriver,
    const USBGenericRequest *pRequest)
{
    unsigned char cfgnum;
    unsigned char infnum;
    unsigned char eptnum;
    unsigned char setting;
    unsigned char type;
    unsigned char index;
    unsigned int length;
    unsigned int address;

    trace_LOG(trace_INFO, "Std ");

    // Check request code
    switch (USBGenericRequest_GetRequest(pRequest)) {

        case USBGenericRequest_GETDESCRIPTOR:
            trace_LOG(trace_INFO, "gDesc ");

            // Send the requested descriptor
            type = USBGetDescriptorRequest_GetDescriptorType(pRequest);
            index = USBGetDescriptorRequest_GetDescriptorIndex(pRequest);
            length = USBGenericRequest_GetLength(pRequest);
            GetDescriptor(pDriver, type, index, length);
            break;

        case USBGenericRequest_SETADDRESS:
            trace_LOG(trace_INFO, "sAddr ");

            // Sends a zero-length packet and then set the device address
            address = USBSetAddressRequest_GetAddress(pRequest);

            if( USBD_IsHighSpeed() ) {

                USBD_SetAddress( address );
            }
            else {
                USBD_Write(0, 0, 0, (TransferCallback) USBD_SetAddress, (void *) address);
            }
            break;

        case USBGenericRequest_SETCONFIGURATION:
            trace_LOG(trace_INFO, "sCfg ");

            // Set the requested configuration
            cfgnum = USBSetConfigurationRequest_GetConfiguration(pRequest);
            SetConfiguration(pDriver, cfgnum);
            break;

        case USBGenericRequest_GETCONFIGURATION:
            trace_LOG(trace_INFO, "gCfg ");

            // Send the current configuration number
            GetConfiguration(pDriver);
            break;

        case USBGenericRequest_GETSTATUS:
            trace_LOG(trace_INFO, "gSta ");
    
            // Check who is the recipient
            switch (USBGenericRequest_GetRecipient(pRequest)) {
    
                case USBGenericRequest_DEVICE:
                    trace_LOG(trace_INFO, "Dev ");
    
                    // Send the device status
                    GetDeviceStatus(pDriver);
                    break;
    
                case USBGenericRequest_ENDPOINT:
                    trace_LOG(trace_INFO, "Ept ");
    
                    // Send the endpoint status
                    eptnum = USBGenericRequest_GetEndpointNumber(pRequest);
                    GetEndpointStatus(eptnum);
                    break;
    
                default:
                    trace_LOG(trace_WARNING,
                              "W: USBDDriver_RequestHandler: Unknown recipient (%d)\n\r",
                              USBGenericRequest_GetRecipient(pRequest));
                    USBD_Stall(0);
            }
            break;

        case USBGenericRequest_CLEARFEATURE:
            trace_LOG(trace_INFO, "cFeat ");

            // Check which is the requested feature
            switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {

                case USBFeatureRequest_ENDPOINTHALT:
                    trace_LOG(trace_INFO, "Hlt ");

                    // Unhalt endpoint and send a zero-length packet
                    USBD_Unhalt(USBGenericRequest_GetEndpointNumber(pRequest));
                    USBD_Write(0, 0, 0, 0, 0);
                    break;

                case USBFeatureRequest_DEVICEREMOTEWAKEUP:
                    trace_LOG(trace_INFO, "RmWU ");

                    // Disable remote wake-up and send a zero-length packet
                    pDriver->isRemoteWakeUpEnabled = 0;
                    USBD_Write(0, 0, 0, 0, 0);
                    break;

                default:
                    trace_LOG(trace_WARNING,
                              "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
                              USBFeatureRequest_GetFeatureSelector(pRequest));
                    USBD_Stall(0);
            }
            break;

    case USBGenericRequest_SETFEATURE:
        trace_LOG(trace_INFO, "sFeat ");

        // Check which is the selected feature
        switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {

            case USBFeatureRequest_DEVICEREMOTEWAKEUP:
                trace_LOG(trace_INFO, "RmWU ");

                // Enable remote wake-up and send a ZLP
                pDriver->isRemoteWakeUpEnabled = 1;
                USBD_Write(0, 0, 0, 0, 0);
                break;

            case USBFeatureRequest_ENDPOINTHALT:
                trace_LOG(trace_INFO, "Ept ");

                // Halt endpoint
                USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest));
                USBD_Write(0, 0, 0, 0, 0);
                break;

#if defined(BOARD_USB_UDPHS)

            case USBFeatureRequest_TESTMODE:
                // 7.1.20 Test Mode Support
                if ((USBGenericRequest_GetType(pRequest) == USBGenericRequest_DEVICE)
                    && ((USBGenericRequest_GetIndex(pRequest) & 0x000F) == 0)) {

                    // Handle test request
                    USBDDriver_Test(USBFeatureRequest_GetTestSelector(pRequest));
                }
                else {

                    USBD_Stall(0);
                }
                break;
#endif

            default:
                trace_LOG(trace_WARNING,
                          "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
                          USBFeatureRequest_GetFeatureSelector(pRequest));
                USBD_Stall(0);
        }
        break;

    case USBGenericRequest_SETINTERFACE:
        trace_LOG(trace_INFO, "sInterface ");

        infnum = USBInterfaceRequest_GetInterface(pRequest);
        setting = USBInterfaceRequest_GetAlternateSetting(pRequest);
        SetInterface(pDriver, infnum, setting);
        break;

    case USBGenericRequest_GETINTERFACE:
        trace_LOG(trace_INFO, "gInterface ");

        infnum = USBInterfaceRequest_GetInterface(pRequest);
        GetInterface(pDriver, infnum);
        break;

    default:
        trace_LOG(trace_WARNING,
                  "USBDDriver_RequestHandler: Unknown request code (%d)\n\r",
                  USBGenericRequest_GetRequest(pRequest));
        USBD_Stall(0);
    }
}
Esempio n. 9
0
//------------------------------------------------------------------------------
/// Sends the requested USB descriptor to the host if available, or STALLs  the
/// request.
/// \param pDriver  Pointer to a USBDDriver instance.
/// \param type  Type of the requested descriptor
/// \param index  Index of the requested descriptor.
/// \param length  Maximum number of bytes to return.
//------------------------------------------------------------------------------
static void GetDescriptor(
    const USBDDriver *pDriver,
    unsigned char type,
    unsigned char index,
    unsigned int length)
{
    const USBDeviceDescriptor *pDevice;
    const USBConfigurationDescriptor *pConfiguration;
    const USBDeviceQualifierDescriptor *pQualifier;
    const USBConfigurationDescriptor *pOtherSpeed;
    const USBGenericDescriptor **pStrings =
        (const USBGenericDescriptor **) pDriver->pDescriptors->pStrings;
    unsigned char numStrings = pDriver->pDescriptors->numStrings;
    const USBGenericDescriptor *pString;

    // Use different set of descriptors depending on device speed
    if (USBD_IsHighSpeed()) {

        trace_LOG(trace_DEBUG, "HS ");
        pDevice = pDriver->pDescriptors->pHsDevice;
        pConfiguration = pDriver->pDescriptors->pHsConfiguration;
        pQualifier = pDriver->pDescriptors->pHsQualifier;
        pOtherSpeed = pDriver->pDescriptors->pHsOtherSpeed;
    }
    else {

        trace_LOG(trace_DEBUG, "FS ");
        pDevice = pDriver->pDescriptors->pFsDevice;
        pConfiguration = pDriver->pDescriptors->pFsConfiguration;
        pQualifier = pDriver->pDescriptors->pFsQualifier;
        pOtherSpeed = pDriver->pDescriptors->pFsOtherSpeed;
    }

    // Check the descriptor type
    switch (type) {
        
        case USBGenericDescriptor_DEVICE:
            trace_LOG(trace_INFO, "Dev ");

            // Adjust length and send descriptor
            if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice)) {

                length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice);
            }
            USBD_Write(0, pDevice, length, 0, 0);
            break;

        case USBGenericDescriptor_CONFIGURATION:
            trace_LOG(trace_INFO, "Cfg ");

            // Adjust length and send descriptor
            if (length > USBConfigurationDescriptor_GetTotalLength(pConfiguration)) {

                length = USBConfigurationDescriptor_GetTotalLength(pConfiguration);
            }
            USBD_Write(0, pConfiguration, length, 0, 0);
            break;

        case USBGenericDescriptor_DEVICEQUALIFIER:
            trace_LOG(trace_INFO, "Qua ");

            // Check if descriptor exists
            if (!pQualifier) {

                USBD_Stall(0);
            }
            else {

                // Adjust length and send descriptor
                if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier)) {

                    length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier);
                }
                USBD_Write(0, pQualifier, length, 0, 0);
            }
            break;

        case USBGenericDescriptor_OTHERSPEEDCONFIGURATION:
            trace_LOG(trace_INFO, "OSC ");

            // Check if descriptor exists
            if (!pOtherSpeed) {

                USBD_Stall(0);
            }
            else {

                // Adjust length and send descriptor
                if (length > USBConfigurationDescriptor_GetTotalLength(pOtherSpeed)) {

                    length = USBConfigurationDescriptor_GetTotalLength(pOtherSpeed);
                }
                USBD_Write(0, pOtherSpeed, length, 0, 0);
            }
            break;

        case USBGenericDescriptor_STRING:
            trace_LOG(trace_INFO, "Str%d ", index);

            // Check if descriptor exists
            if (index > numStrings) {

                USBD_Stall(0);
            }
            else {

                pString = pStrings[index];

                // Adjust length and send descriptor
                if (length > USBGenericDescriptor_GetLength(pString)) {

                    length = USBGenericDescriptor_GetLength(pString);
                }
                USBD_Write(0, pString, length, 0, 0);
            }
            break;

        default:
            trace_LOG(trace_WARNING,
                      "USBDDriver_GetDescriptor: Unknown descriptor type (%d)\n\r",
                      type);
            USBD_Stall(0);
    }
}