//***************************************************************************** // // This function is called to handle the interrupts on the isochronous endpoint // for the audio device class. // //***************************************************************************** static void HandleEndpoints(void *pvAudioDevice, uint32_t ui32Status) { uint32_t ui32EPStatus; tAudioInstance *psInst; tUSBDAudioDevice *psAudioDevice; uint32_t ui32Size; ASSERT(pvAudioDevice != 0); // // The audio device structure pointer. // psAudioDevice = (tUSBDAudioDevice *)pvAudioDevice; // // Create a pointer to the audio instance data. // psInst = &psAudioDevice->sPrivateData; // // Read out the current endpoint status. // ui32EPStatus = MAP_USBEndpointStatus(USB0_BASE, psInst->ui8OUTEndpoint); // // See if there is a receive interrupt pending. // if(ui32Status & ((uint32_t)0x10000 << USBEPToIndex(psInst->ui8OUTEndpoint))) { // // Get the amount of data available in the FIFO. // ui32Size = USBEndpointDataAvail(psInst->ui32USBBase, psInst->ui8OUTEndpoint); // // Clear the status bits. // MAP_USBDevEndpointStatusClear(USB0_BASE, psInst->ui8OUTEndpoint, ui32EPStatus); // // Configure the next DMA transfer. // USBLibDMATransfer(psInst->psDMAInstance, psInst->ui8OUTDMA, psInst->sBuffer.pvData, ui32Size); } else if((USBLibDMAChannelStatus(psInst->psDMAInstance, psInst->ui8OUTDMA) == USBLIBSTATUS_DMA_COMPLETE)) { USBEndpointDMADisable(USB0_BASE, psInst->ui8OUTEndpoint, USB_EP_DEV_OUT); // // Acknowledge that the data was read, this will not cause a bus // acknowledgment. // MAP_USBDevEndpointDataAck(USB0_BASE, psInst->ui8OUTEndpoint, 0); // // Inform the callback of the new data. // psInst->sBuffer.pfnCallback(psInst->sBuffer.pvData, psInst->sBuffer.ui32Size, USBD_AUDIO_EVENT_DATAOUT); } }
//***************************************************************************** // //! Reads a packet of data received from the USB host via the bulk data //! interface. //! //! \param pvBulkDevice is the pointer to the device instance structure as //! returned by USBDBulkInit(). //! \param pi8Data points to a buffer into which the received data will be //! written. //! \param ui32Length is the size of the buffer pointed to by pi8Data. //! \param bLast indicates whether the client will make a further call to //! read additional data from the packet. //! //! This function reads up to \e ui32Length bytes of data received from the USB //! host into the supplied application buffer. If the driver detects that the //! entire packet has been read, it is acknowledged to the host. //! //! The \e bLast parameter is ignored in this implementation since the end of //! a packet can be determined without relying upon the client to provide //! this information. //! //! \return Returns the number of bytes of data read. // //***************************************************************************** uint32_t USBDBulkPacketRead(void *pvBulkDevice, uint8_t *pi8Data, uint32_t ui32Length, bool bLast) { uint32_t ui32EPStatus, ui32Count, ui32Pkt; tBulkInstance *psInst; int32_t i32Retcode; ASSERT(pvBulkDevice); // // Get our instance data pointer // psInst = &((tUSBDBulkDevice *)pvBulkDevice)->sPrivateData; // // Does the relevant endpoint FIFO have a packet waiting for us? // ui32EPStatus = MAP_USBEndpointStatus(psInst->ui32USBBase, psInst->ui8OUTEndpoint); if(ui32EPStatus & USB_DEV_RX_PKT_RDY) { // // How many bytes are available for us to receive? // ui32Pkt = MAP_USBEndpointDataAvail(psInst->ui32USBBase, psInst->ui8OUTEndpoint); // // Get as much data as we can. // ui32Count = ui32Length; i32Retcode = MAP_USBEndpointDataGet(psInst->ui32USBBase, psInst->ui8OUTEndpoint, pi8Data, &ui32Count); // // Did we read the last of the packet data? // if(ui32Count == ui32Pkt) { // // Clear the endpoint status so that we know no packet is // waiting. // MAP_USBDevEndpointStatusClear(psInst->ui32USBBase, psInst->ui8OUTEndpoint, ui32EPStatus); // // Acknowledge the data, thus freeing the host to send the // next packet. // MAP_USBDevEndpointDataAck(psInst->ui32USBBase, psInst->ui8OUTEndpoint, true); // // Clear the flag we set to indicate that a packet read is // pending. // SetDeferredOpFlag(&psInst->ui16DeferredOpFlags, BULK_DO_PACKET_RX, false); } // // If all went well, tell the caller how many bytes they got. // if(i32Retcode != -1) { return(ui32Count); } } // // No packet was available or an error occurred while reading so tell // the caller no bytes were returned. // return(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); } }