//**************************************************************************** // // 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)); } }
//***************************************************************************** // // 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); } }