Пример #1
0
//****************************************************************************
//
// This function is called by the USB device stack whenever a non-standard
// request is received.
//
// \param pvInstance
// \param pUSBRequest points to the request received.
//
// This call  will be passed on to the device classes if they have a handler
// for this function.
//
// \return None.
//
//****************************************************************************
static void
HandleRequests(void *pvInstance, tUSBRequest *pUSBRequest)
{
    unsigned long ulIdx;
    const tDeviceInfo *pDeviceInfo;
    tUSBDCompositeDevice *psDevice;

    //
    // Create the device instance pointer.
    //
    psDevice = (tUSBDCompositeDevice *)pvInstance;

    //
    // Determine which device this request is intended for.  We have to be
    // careful here to send this to the callback for the correct device
    // depending upon whether it is a request sent to the device, the interface
    // or the endpoint.
    //
    switch(pUSBRequest->bmRequestType & USB_RTYPE_RECIPIENT_M)
    {
        case USB_RTYPE_INTERFACE:
        {
            ulIdx = InterfaceToIndex(psDevice, (pUSBRequest->wIndex & 0xFF));
            break;
        }

        case USB_RTYPE_ENDPOINT:
        {
            ulIdx = EndpointToIndex(psDevice, (pUSBRequest->wIndex & 0x0F),
                             (pUSBRequest->wIndex & 0x80) ? true : false);
            break;
        }

        //
        // Requests sent to the device or any other recipient can't be
        // handled here since we have no way of telling where they are
        // supposed to be handled.  As a result, we just stall them.
        //
        // If your composite device has some device-specific requests that need
        // to be handled at the device (rather than interface or endpoint)
        // level, you should add code here to handle them.
        //
        case USB_RTYPE_DEVICE:
        case USB_RTYPE_OTHER:
        default:
        {
            ulIdx = INVALID_DEVICE_INDEX;
            break;
        }
    }

    //
    // Did we find a device class to pass the request to?
    //
    if(ulIdx != INVALID_DEVICE_INDEX)
    {
        //
        // Get a pointer to the individual device instance.
        //
        pDeviceInfo = psDevice->psDevices[ulIdx].psDevice;

        //
        // Does this device have a RequestHandler callback?
        //
        if(pDeviceInfo->sCallbacks.pfnRequestHandler)
        {
            //
            // Remember this device index so that we can correctly route any
            // data notification callbacks to it.
            //
            psDevice->psPrivateData->ulEP0Owner = ulIdx;

            //
            // Yes - call the device to retrieve the descriptor.
            //
            pDeviceInfo->sCallbacks.pfnRequestHandler(
                    psDevice->psDevices[ulIdx].pvInstance, pUSBRequest);
        }
        else
        {
            //
            // Oops - we can't satisfy the request so stall EP0 to indicate
            // an error.
            //
            USBDCDStallEP0(
                       USB_BASE_TO_INDEX(psDevice->psPrivateData->ulUSBBase));
        }
    }
    else
    {
        //
        // We are unable to satisfy the descriptor request so stall EP0 to
        // indicate an error.
        //
        USBDCDStallEP0(USB_BASE_TO_INDEX(psDevice->psPrivateData->ulUSBBase));
    }

}
Пример #2
0
//*****************************************************************************
//
// This function is called by the USB device stack whenever a non-standard
// request is received.
//
// \param pvAudioDevice is the instance data for this request.
// \param psUSBRequest points to the request received.
//
// This call parses the provided request structure to the type of request and
// will respond to all commands that are understood by the class.
//
// \return None.
//
//*****************************************************************************
static void
HandleRequests(void *pvAudioDevice, tUSBRequest *psUSBRequest)
{
    uint32_t ui32Control, ui32Recipient, ui32Stall;
    tAudioInstance *psInst;
    tUSBDAudioDevice *psAudioDevice;

    ASSERT(pvAudioDevice != 0);

    //
    // The audio device structure pointer.
    //
    psAudioDevice = (tUSBDAudioDevice *)pvAudioDevice;

    //
    // Create a pointer to the audio instance data.
    //
    psInst = &psAudioDevice->sPrivateData;

    //
    // Make sure to acknowledge that the data was read, this will not send and
    // ACK that has already been done at this point.  This just tells the
    // hardware that the data was read.
    //
    MAP_USBDevEndpointDataAck(USB0_BASE, USB_EP_0, false);

    //
    // Don't stall by default.
    //
    ui32Stall = 0;

    //
    // Get the request type.
    //
    ui32Recipient = psUSBRequest->bmRequestType & USB_RTYPE_RECIPIENT_M;

    //
    // Save the request type and request value.
    //
    psInst->ui16RequestType = psUSBRequest->bmRequestType;
    psInst->ui8Request = psUSBRequest->bRequest;

    //
    // Check if this is an endpoint request to the audio streaming endpoint.
    //
    if((ui32Recipient == USB_RTYPE_ENDPOINT) &&
       (readusb16_t(&(psUSBRequest->wIndex)) == USBEPToIndex(psInst->ui8OUTEndpoint)))
    {
        //
        // Determine the type of request.
        //
        switch(psInst->ui8Request)
        {
            case USB_AC_SET_CUR:
            {
                //
                // Handle retrieving the sample rate.
                //
                if(readusb16_t(&(psUSBRequest->wValue)) == SAMPLING_FREQ_CONTROL)
                {
                    //
                    // Retrieve the requested sample rate.
                    //
                    USBDCDRequestDataEP0(0,
                                         (uint8_t *)&psInst->ui32SampleRate,
                                         3);

                    //
                    // Save what we are updating.
                    //
                    psInst->ui16Update = SAMPLING_FREQ_CONTROL;
                }
                break;
            }
            case USB_AC_GET_CUR:
            {
                //
                // Handle retrieving the sample rate.
                //
                if(readusb16_t(&(psUSBRequest->wValue)) == SAMPLING_FREQ_CONTROL)
                {
                    //
                    // Send back the current sample rate.
                    //
                    USBDCDSendDataEP0(0,
                                      (uint8_t *)&psInst->ui32SampleRate,
                                      3);
                }
                break;
            }
            default:
            {
                //
                // Stall on unknown commands.
                //
                ui32Stall = 1;
                break;
            }
        }
    }
    else if(ui32Recipient == USB_RTYPE_INTERFACE)
    {
        //
        // Make sure the request was for the control interface.
        //
        if((uint8_t)readusb16_t(&(psUSBRequest->wIndex)) != psInst->ui8InterfaceControl)
        {
            return;
        }

        //
        // Extract the control value from the message.
        //
        ui32Control = readusb16_t(&(psUSBRequest->wValue)) & USB_CS_CONTROL_M;

        //
        // Handle an audio control request to the feature control unit.
        //
        if(((uint32_t)AUDIO_CONTROL_ID << 8) ==
           (readusb16_t(&(psUSBRequest->wIndex)) & USB_CS_CONTROL_M))
        {
            //
            // Determine the type of request.
            //
            switch(psInst->ui8Request)
            {
                case USB_AC_GET_MAX:
                {
                    if(ui32Control == VOLUME_CONTROL)
                    {
                        //
                        // Return the maximum volume setting.
                        //
                        USBDCDSendDataEP0(0,
                                          (uint8_t *)&psInst->i16VolumeMax,
                                          2);
                    }
                    else
                    {
                        //
                        // Stall on unknown commands.
                        //
                        ui32Stall = 1;
                    }
                    break;
                }
                case USB_AC_GET_MIN:
                {
                    if(ui32Control == VOLUME_CONTROL)
                    {
                        //
                        // Return the minimum volume setting.
                        //
                        USBDCDSendDataEP0(0,
                                          (uint8_t *)&psInst->i16VolumeMin,
                                          2);
                    }
                    else
                    {
                        //
                        // Stall on unknown commands.
                        //
                        ui32Stall = 1;
                    }
                    break;
                }
                case USB_AC_GET_RES:
                {
                    if(ui32Control == VOLUME_CONTROL)
                    {
                        //
                        // Return the volume step setting.
                        //
                        USBDCDSendDataEP0(0,
                                          (uint8_t *)&psInst->i16VolumeStep,
                                          2);
                    }
                    else
                    {
                        //
                        // Stall on unknown commands.
                        //
                        ui32Stall = 1;
                    }
                    break;
                }
                case USB_AC_GET_CUR:
                {
                    if(ui32Control == VOLUME_CONTROL)
                    {
                        //
                        // Send back the current volume level.
                        //
                        USBDCDSendDataEP0(0,
                                          (uint8_t *)&psInst->i16Volume,
                                          2);
                    }
                    else if(ui32Control == MUTE_CONTROL)
                    {
                        //
                        // Send back the current mute value.
                        //
                        USBDCDSendDataEP0(0,
                                          (uint8_t *)&psInst->ui8Mute, 1);
                    }
                    else
                    {
                        //
                        // Stall on unknown commands.
                        //
                        ui32Stall = 1;
                    }
                    break;
                }
                case USB_AC_SET_CUR:
                {
                    if(ui32Control == VOLUME_CONTROL)
                    {
                        //
                        // Read the new volume level.
                        //
                        USBDCDRequestDataEP0(0,
                                             (uint8_t *)&psInst->i16Volume,
                                             2);

                        //
                        // Save what we are updating.
                        //
                        psInst->ui16Update = VOLUME_CONTROL;
                    }
                    else if(ui32Control == MUTE_CONTROL)
                    {
                        //
                        // Read the new mute setting.
                        //
                        USBDCDRequestDataEP0(0,
                                             (uint8_t *)&psInst->ui8Mute,
                                             1);

                        //
                        // Save what we are updating.
                        //
                        psInst->ui16Update = MUTE_CONTROL;
                    }
                    else
                    {
                        //
                        // Stall on unknown commands.
                        //
                        ui32Stall = 1;
                    }
                    break;
                }
                case USB_AC_SET_RES:
                {
                    if(ui32Control == VOLUME_CONTROL)
                    {
                        //
                        // Read the new volume step setting.
                        //
                        USBDCDRequestDataEP0(0,
                            (uint8_t *)&psInst->i16VolumeStep, 2);

                        //
                        // Save what we are updating.
                        //
                        psInst->ui16Update = VOLUME_CONTROL;
                    }
                    else
                    {
                        //
                        // Stall on unknown commands.
                        //
                        ui32Stall = 1;
                    }
                    break;
                }
                default:
                {
                    //
                    // Stall on unknown commands.
                    //
                    ui32Stall = 1;
                    break;
                }
            }
        }
    }

    //
    // Stall on all unknown commands.
    //
    if(ui32Stall)
    {
        USBDCDStallEP0(0);
    }
}