//***************************************************************************** // // Called by the USB stack for any activity involving one of our endpoints // other than EP0. This function is a fan out that merely directs the call to // the correct handler depending upon the endpoint and transaction direction // signaled in ui32Status. // //***************************************************************************** static void HandleEndpoints(void *pvBulkDevice, uint32_t ui32Status) { tUSBDBulkDevice *psBulkDevice; tBulkInstance *psInst; ASSERT(pvBulkDevice != 0); // // The bulk device structure pointer. // psBulkDevice = (tUSBDBulkDevice *)pvBulkDevice; // // Get a pointer to the bulk device instance data pointer // psInst = &psBulkDevice->sPrivateData; // // Handler for the bulk OUT data endpoint. // if(ui32Status & (0x10000 << USBEPToIndex(psInst->ui8OUTEndpoint))) { // // Data is being sent to us from the host. // ProcessDataFromHost(psBulkDevice, ui32Status); } // // Handler for the bulk IN data endpoint. // if(ui32Status & (1 << USBEPToIndex(psInst->ui8INEndpoint))) { ProcessDataToHost(psBulkDevice, ui32Status); } }
// interface. USB_CLASS_HID, // The interface class USB_HID_SCLASS_BOOT, // The interface sub-class. USB_HID_PROTOCOL_KEYB, // The interface protocol for the sub-class // specified above. 4, // The string index for this interface. }; static const uint8_t g_pui8HIDInEndpoint[HIDINENDPOINT_SIZE] = { // // Interrupt IN endpoint descriptor // 7, // The size of the endpoint descriptor. USB_DTYPE_ENDPOINT, // Descriptor type is an endpoint. USB_EP_DESC_IN | USBEPToIndex(USB_EP_1), USB_EP_ATTR_INT, // Endpoint is an interrupt endpoint. USBShort(USBFIFOSizeToBytes(USB_FIFO_SZ_64)), // The maximum packet size. 16, // The polling interval for this endpoint. }; static const uint8_t g_pui8HIDOutEndpoint[HIDOUTENDPOINT_SIZE] = { // // Interrupt OUT endpoint descriptor // 7, // The size of the endpoint descriptor. USB_DTYPE_ENDPOINT, // Descriptor type is an endpoint. USB_EP_DESC_OUT | USBEPToIndex(USB_EP_2), USB_EP_ATTR_INT, // Endpoint is an interrupt endpoint.
// interface. USB_CLASS_HID, // The interface class USB_HID_SCLASS_BOOT, // The interface sub-class. USB_HID_PROTOCOL_MOUSE, // The interface protocol for the sub-class // specified above. 4, // The string index for this interface. }; const uint8_t g_pui8HIDInEndpoint[HIDINENDPOINT_SIZE] = { // // Interrupt IN endpoint descriptor // 7, // The size of the endpoint descriptor. USB_DTYPE_ENDPOINT, // Descriptor type is an endpoint. USB_EP_DESC_IN | USBEPToIndex(USB_EP_1), USB_EP_ATTR_INT, // Endpoint is an interrupt endpoint. USBShort(USBFIFOSizeToBytes(USB_FIFO_SZ_64)), // The maximum packet size. 16, // The polling interval for this endpoint. }; //***************************************************************************** // // The report descriptor for the mouse class device. // //***************************************************************************** static const uint8_t g_pui8MouseReportDescriptor[] = { UsagePage(USB_HID_GENERIC_DESKTOP), Usage(USB_HID_MOUSE),
0, // The alternate setting for this // interface. 2, // The number of endpoints used by this // interface. USB_CLASS_VEND_SPECIFIC, // The interface class 0, // The interface sub-class. 0, // The interface protocol for the sub-class // specified above. 4, // The string index for this interface. // // Endpoint Descriptor // 7, // The size of the endpoint descriptor. USB_DTYPE_ENDPOINT, // Descriptor type is an endpoint. USB_EP_DESC_IN | USBEPToIndex(DATA_IN_ENDPOINT), USB_EP_ATTR_BULK, // Endpoint is a bulk endpoint. USBShort(DATA_IN_EP_MAX_SIZE), // The maximum packet size. 0, // The polling interval for this endpoint. // // Endpoint Descriptor // 7, // The size of the endpoint descriptor. USB_DTYPE_ENDPOINT, // Descriptor type is an endpoint. USB_EP_DESC_OUT | USBEPToIndex(DATA_OUT_ENDPOINT), USB_EP_ATTR_BULK, // Endpoint is a bulk endpoint. USBShort(DATA_OUT_EP_MAX_SIZE), // The maximum packet size. 0, // The polling interval for this endpoint. };
//***************************************************************************** // // 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); } }
//***************************************************************************** // // 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); } }
USB_ASDSTYPE_FORMAT_TYPE, // Audio Streaming format type. USB_AF_TYPE_TYPE_I, // Type I audio format type. 2, // Two audio channels. 2, // Two bytes per audio sub-frame. 16, // 16 bits per sample. 1, // One sample rate provided. USB3Byte(48000), // Only 48000 sample rate supported. // // Endpoint Descriptor // 9, // The size of the endpoint descriptor. USB_DTYPE_ENDPOINT, // Descriptor type is an endpoint. // OUT endpoint with address // ISOC_OUT_ENDPOINT. USB_EP_DESC_OUT | USBEPToIndex(ISOC_OUT_ENDPOINT), USB_EP_ATTR_ISOC | // Endpoint is an adaptive isochronous data USB_EP_ATTR_ISOC_ADAPT | // endpoint. USB_EP_ATTR_USAGE_DATA, USBShort(ISOC_OUT_EP_MAX_SIZE), // The maximum packet size. 1, // The polling interval for this endpoint. 0, // Refresh is unused. 0, // Synch endpoint address. // // Audio Streaming Isochronous Audio Data Endpoint Descriptor // 7, // The size of the descriptor. USB_ACSDT_ENDPOINT, // Audio Class Specific Endpoint // Descriptor. USB_ASDSTYPE_GENERAL, // This is a general descriptor.