/** Parses the given Configuration descriptor (followed by relevant
 *  interface, endpoint and class-specific descriptors) into three arrays.
 *  *Each array must have its size equal or greater to the number of
 *  descriptors it stores plus one*. A null-value is inserted after the last
 *  descriptor of each type to indicate the array end.
 *
 *  Note that if the pointer to an array is null (0), nothing is stored in
 *  it.
 *  \param configuration Pointer to the start of the whole Configuration
 *                       descriptor.
 *  \param interfaces    Pointer to the Interface descriptor array.
 *  \param endpoints     Pointer to the Endpoint descriptor array.
 *  \param others        Pointer to the class-specific descriptor array.
 */
void USBConfigurationDescriptor_Parse(
    const USBConfigurationDescriptor *configuration,
    USBInterfaceDescriptor **interfaces,
    USBEndpointDescriptor **endpoints,
    USBGenericDescriptor **others)
{
    /* Get size of configuration to parse */
    int size = USBConfigurationDescriptor_GetTotalLength(configuration);
    size -= sizeof(USBConfigurationDescriptor);

    /* Start parsing descriptors */
    USBGenericDescriptor *descriptor = (USBGenericDescriptor *) configuration;
    while (size > 0) {

        /* Get next descriptor */
        descriptor = USBGenericDescriptor_GetNextDescriptor(descriptor);
        size -= USBGenericDescriptor_GetLength(descriptor);

        /* Store descriptor in correponding array */
        if (USBGenericDescriptor_GetType(descriptor)
             == USBGenericDescriptor_INTERFACE) {

            if (interfaces) {

                *interfaces = (USBInterfaceDescriptor *) descriptor;
                interfaces++;
            }
        }
        else if (USBGenericDescriptor_GetType(descriptor)
                  == USBGenericDescriptor_ENDPOINT) {

            if (endpoints) {

                *endpoints = (USBEndpointDescriptor *) descriptor;
                endpoints++;
            }
        }
        else if (others) {

            *others = descriptor;
            others++;
        }
    }

    /* Null-terminate arrays */
    if (interfaces) {

        *interfaces = 0;
    }
    if (endpoints) {

        *endpoints = 0;
    }
    if (others) {

        *others = 0;
    }
}
Exemple #2
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);
    }
}
Exemple #3
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);
    }
}
//------------------------------------------------------------------------------
/// 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 USBGenericDescriptor **pStrings =
        (const USBGenericDescriptor **) pDriver->pDescriptors->pStrings;
    unsigned char numStrings = pDriver->pDescriptors->numStrings;
    const USBGenericDescriptor *pString;

	pDevice = pDriver->pDescriptors->pFsDevice;
	pConfiguration = pDriver->pDescriptors->pFsConfiguration;

    // 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);
            }
            USBD_Write(0, pConfiguration, length, 0, 0);
            break;

        case USBGenericDescriptor_STRING:
            TRACE_INFO_WP("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_WARNING(
                      "USBDDriver_GetDescriptor: Unknown descriptor type (%d)\n\r",
                      type);
            USBD_Stall(0);
    }
}
Exemple #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 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);
    }
}