//***************************************************************************** // // Device instance specific handler. // //***************************************************************************** static void HandleDevice(void *pvBulkDevice, uint32_t ui32Request, void *pvRequestData) { tBulkInstance *psInst; uint8_t *pui8Data; tUSBDBulkDevice *psBulkDevice; // // The bulk device structure pointer. // psBulkDevice = (tUSBDBulkDevice *)pvBulkDevice; // // Get a pointer to the bulk device instance data pointer // psInst = &psBulkDevice->sPrivateData; // // Create the 8-bit array used by the events supported by the USB Bulk // class. // pui8Data = (uint8_t *)pvRequestData; switch(ui32Request) { // // This was an interface change event. // case USB_EVENT_COMP_IFACE_CHANGE: { psInst->ui8Interface = pui8Data[1]; break; } // // This was an endpoint change event. // case USB_EVENT_COMP_EP_CHANGE: { // // Determine if this is an IN or OUT endpoint that has changed. // if(pui8Data[0] & USB_EP_DESC_IN) { psInst->ui8INEndpoint = IndexToUSBEP((pui8Data[1] & 0x7f)); } else { // // Extract the new endpoint number. // psInst->ui8OUTEndpoint = IndexToUSBEP(pui8Data[1] & 0x7f); } break; } default: { break; } } }
//***************************************************************************** // //! Configure the USB controller appropriately for the device whose //! configuration descriptor is passed. //! //! \param psDevInst is a pointer to the device instance being configured. //! \param psConfig is a pointer to the configuration descriptor that the //! USB controller is to be set up to support. //! //! This function may be used to initialize a USB controller to operate as //! the device whose configuration descriptor is passed. The function //! enables the USB controller, partitions the FIFO appropriately and //! configures each endpoint required by the configuration. If the supplied //! configuration supports multiple alternate settings for any interface, //! the USB FIFO is set up assuming the worst case use (largest packet size //! for a given endpoint in any alternate setting using that endpoint) to //! allow for on-the-fly alternate setting changes later. On return from this //! function, the USB controller is configured for correct operation of //! the default configuration of the device described by the descriptor passed. //! //! \return Returns \b true on success or \b false on failure. // //***************************************************************************** bool USBDeviceConfig(tDCDInstance *psDevInst, const tConfigHeader *psConfig) { uint32_t ui32Loop, ui32Count, ui32NumInterfaces, ui32EpIndex, ui32EpType, ui32MaxPkt, ui32NumEndpoints, ui32Flags, ui32BytesUsed, ui32Section; tInterfaceDescriptor *psInterface; tEndpointDescriptor *psEndpoint; tUSBEndpointInfo psEPInfo[NUM_USB_EP - 1]; // // A valid device instance is required. // ASSERT(psDevInst != 0); // // Catch bad pointers in a debug build. // ASSERT(psConfig); // // Clear out our endpoint info. // for(ui32Loop = 0; ui32Loop < (NUM_USB_EP - 1); ui32Loop++) { psEPInfo[ui32Loop].pui32Size[EP_INFO_IN] = 0; psEPInfo[ui32Loop].pui32Size[EP_INFO_OUT] = 0; } // // How many (total) endpoints does this configuration describe? // ui32NumEndpoints = USBDCDConfigDescGetNum(psConfig, USB_DTYPE_ENDPOINT); // // How many interfaces are included? // ui32NumInterfaces = USBDCDConfigDescGetNum(psConfig, USB_DTYPE_INTERFACE); // // Look at each endpoint and determine the largest max packet size for // each endpoint. This will determine how we partition the USB FIFO. // for(ui32Loop = 0; ui32Loop < ui32NumEndpoints; ui32Loop++) { // // Get a pointer to the endpoint descriptor. // psEndpoint = (tEndpointDescriptor *)USBDCDConfigDescGet( psConfig, USB_DTYPE_ENDPOINT, ui32Loop, &ui32Section); // // Extract the endpoint number and whether it is an IN or OUT // endpoint. // ui32EpIndex = (uint32_t) psEndpoint->bEndpointAddress & USB_EP_DESC_NUM_M; ui32EpType = (psEndpoint->bEndpointAddress & USB_EP_DESC_IN) ? EP_INFO_IN : EP_INFO_OUT; // // Make sure the endpoint number is valid for our controller. If not, // return false to indicate an error. Note that 0 is invalid since // you shouldn't reference endpoint 0 in the config descriptor. // if((ui32EpIndex >= NUM_USB_EP) || (ui32EpIndex == 0)) { return(false); } // // Does this endpoint have a max packet size requirement larger than // any previous use we have seen? // if(psEndpoint->wMaxPacketSize > psEPInfo[ui32EpIndex - 1].pui32Size[ui32EpType]) { // // Yes - remember the new maximum packet size. // psEPInfo[ui32EpIndex - 1].pui32Size[ui32EpType] = psEndpoint->wMaxPacketSize; } } // // At this point, we have determined the maximum packet size required // for each endpoint by any possible alternate setting of any interface // in this configuration. Now determine the endpoint settings required // for the interface setting we are actually going to use. // for(ui32Loop = 0; ui32Loop < ui32NumInterfaces; ui32Loop++) { // // Get the next interface descriptor in the configuration descriptor. // psInterface = USBDCDConfigGetInterface(psConfig, ui32Loop, USB_DESC_ANY, &ui32Section); // // Is this the default interface (bAlternateSetting set to 0)? // if(psInterface && (psInterface->bAlternateSetting == 0)) { // // This is an interface we are interested in so gather the // information on its endpoints. // ui32NumEndpoints = (uint32_t)psInterface->bNumEndpoints; // // Walk through each endpoint in this interface and configure // it appropriately. // for(ui32Count = 0; ui32Count < ui32NumEndpoints; ui32Count++) { // // Get a pointer to the endpoint descriptor. // psEndpoint = USBDCDConfigGetInterfaceEndpoint(psConfig, psInterface->bInterfaceNumber, psInterface->bAlternateSetting, ui32Count); // // Make sure we got a good pointer. // if(psEndpoint) { // // Determine maximum packet size and flags from the // endpoint descriptor. // GetEPDescriptorType(psEndpoint, &ui32EpIndex, &ui32MaxPkt, &ui32Flags); // // Make sure no-one is trying to configure endpoint 0. // if(!ui32EpIndex) { return(false); } // // Set the endpoint configuration. // USBDevEndpointConfigSet(USB0_BASE, IndexToUSBEP(ui32EpIndex), ui32MaxPkt, ui32Flags); } } } } // // At this point, we have configured all the endpoints that are to be // used by this configuration's alternate setting 0. Now we go on and // partition the FIFO based on the maximum packet size information we // extracted earlier. Endpoint 0 is automatically configured to use the // first MAX_PACKET_SIZE_EP0 bytes of the FIFO so we start from there. // ui32Count = MAX_PACKET_SIZE_EP0; for(ui32Loop = 1; ui32Loop < NUM_USB_EP; ui32Loop++) { // // Configure the IN endpoint at this index if it is referred to // anywhere. // if(psEPInfo[ui32Loop - 1].pui32Size[EP_INFO_IN]) { // // What FIFO size flag do we use for this endpoint? // ui32MaxPkt = GetEndpointFIFOSize( psEPInfo[ui32Loop - 1].pui32Size[EP_INFO_IN], &ui32BytesUsed); // // The FIFO space could not be allocated. // if(ui32BytesUsed == 0) { return(false); } // // Now actually configure the FIFO for this endpoint. // USBFIFOConfigSet(USB0_BASE, IndexToUSBEP(ui32Loop), ui32Count, ui32MaxPkt, USB_EP_DEV_IN); ui32Count += ui32BytesUsed; } // // Configure the OUT endpoint at this index. // if(psEPInfo[ui32Loop - 1].pui32Size[EP_INFO_OUT]) { // // What FIFO size flag do we use for this endpoint? // ui32MaxPkt = GetEndpointFIFOSize( psEPInfo[ui32Loop - 1].pui32Size[EP_INFO_OUT], &ui32BytesUsed); // // The FIFO space could not be allocated. // if(ui32BytesUsed == 0) { return(false); } // // Now actually configure the FIFO for this endpoint. // USBFIFOConfigSet(USB0_BASE, IndexToUSBEP(ui32Loop), ui32Count, ui32MaxPkt, USB_EP_DEV_OUT); ui32Count += ui32BytesUsed; } } // // If we get to the end, all is well. // return(true); }
//***************************************************************************** // //! Configure the affected USB endpoints appropriately for one alternate //! interface setting. //! //! \param psDevInst is a pointer to the device instance being configured. //! \param psConfig is a pointer to the configuration descriptor that contains //! the interface whose alternate settings is to be configured. //! \param ui8InterfaceNum is the number of the interface whose alternate //! setting is to be configured. This number corresponds to the //! bInterfaceNumber field in the desired interface descriptor. //! \param ui8AlternateSetting is the alternate setting number for the desired //! interface. This number corresponds to the bAlternateSetting field in the //! desired interface descriptor. //! //! This function may be used to reconfigure the endpoints of an interface //! for operation in one of the interface's alternate settings. Note that this //! function assumes that the endpoint FIFO settings will not need to change //! and only the endpoint mode is changed. This assumption is valid if the //! USB controller was initialized using a previous call to USBDCDConfig(). //! //! In reconfiguring the interface endpoints, any additional configuration //! bits set in the endpoint configuration other than the direction (\b //! USB_EP_DEV_IN or \b USB_EP_DEV_OUT) and mode (\b USB_EP_MODE_MASK) are //! preserved. //! //! \return Returns \b true on success or \b false on failure. // //***************************************************************************** bool USBDeviceConfigAlternate(tDCDInstance *psDevInst, const tConfigHeader *psConfig, uint8_t ui8InterfaceNum, uint8_t ui8AlternateSetting) { uint32_t ui32NumInterfaces, ui32NumEndpoints, ui32Loop, ui32Count, ui32MaxPkt, ui32Flags, ui32Section, ui32EpIndex; tInterfaceDescriptor *psInterface; tEndpointDescriptor *psEndpoint; // // How many interfaces are included in the descriptor? // ui32NumInterfaces = USBDCDConfigDescGetNum(psConfig, USB_DTYPE_INTERFACE); // // Find the interface descriptor for the supplied interface and alternate // setting numbers. // for(ui32Loop = 0; ui32Loop < ui32NumInterfaces; ui32Loop++) { // // Get the next interface descriptor in the configuration descriptor. // psInterface = USBDCDConfigGetInterface(psConfig, ui32Loop, USB_DESC_ANY, &ui32Section); // // Is this the default interface (bAlternateSetting set to 0)? // if(psInterface && (psInterface->bInterfaceNumber == ui8InterfaceNum) && (psInterface->bAlternateSetting == ui8AlternateSetting)) { // // This is an interface we are interested in and the descriptor // representing the alternate setting we want so go ahead and // reconfigure the endpoints. // // // How many endpoints does this interface have? // ui32NumEndpoints = (uint32_t)psInterface->bNumEndpoints; // // Walk through each endpoint in turn. // for(ui32Count = 0; ui32Count < ui32NumEndpoints; ui32Count++) { // // Get a pointer to the endpoint descriptor. // psEndpoint = USBDCDConfigGetInterfaceEndpoint(psConfig, psInterface->bInterfaceNumber, psInterface->bAlternateSetting, ui32Count); // // Make sure we got a good pointer. // if(psEndpoint) { // // Determine maximum packet size and flags from the // endpoint descriptor. // GetEPDescriptorType(psEndpoint, &ui32EpIndex, &ui32MaxPkt, &ui32Flags); // // Make sure no-one is trying to configure endpoint 0. // if(!ui32EpIndex) { return(false); } // // Set the endpoint configuration. // USBDevEndpointConfigSet(USB0_BASE, IndexToUSBEP(ui32EpIndex), ui32MaxPkt, ui32Flags); } } // // At this point, we have reconfigured the desired interface so // return indicating all is well. // return(true); } } return(false); }
//***************************************************************************** // // Device instance specific handler. // //***************************************************************************** static void HandleDevice(void *pvAudioDevice, uint32_t ui32Request, void *pvRequestData) { tAudioInstance *psInst; uint8_t *pui8Data; tUSBDAudioDevice *psAudioDevice; // // The audio device structure pointer. // psAudioDevice = (tUSBDAudioDevice *)pvAudioDevice; // // Create a pointer to the audio instance data. // psInst = &psAudioDevice->sPrivateData; // // Create the 8-bit array used by the events supported by the USB CDC // serial class. // pui8Data = (uint8_t *)pvRequestData; switch(ui32Request) { // // This was an interface change event. // case USB_EVENT_COMP_IFACE_CHANGE: { // // Save the change to the appropriate interface number. // if(pui8Data[0] == AUDIO_INTERFACE_CONTROL) { psInst->ui8InterfaceControl = pui8Data[1]; } else if(pui8Data[0] == AUDIO_INTERFACE_OUTPUT) { psInst->ui8InterfaceAudio = pui8Data[1]; } break; } // // This was an endpoint change event. // case USB_EVENT_COMP_EP_CHANGE: { // // Determine if this is an IN or OUT endpoint that has changed. // if((pui8Data[0] & USB_EP_DESC_IN) == 0) { // // Extract the new endpoint number without the DIR bit. // psInst->ui8OUTEndpoint = IndexToUSBEP(pui8Data[1] & 0x7f); // // If the DMA channel has already been allocated then clear // that channel and prepare to possibly use a new one. // if(psInst->ui8OUTDMA != 0) { USBLibDMAChannelRelease(psInst->psDMAInstance, psInst->ui8OUTDMA); } // // Allocate a DMA channel to the endpoint. // psInst->ui8OUTDMA = USBLibDMAChannelAllocate(psInst->psDMAInstance, psInst->ui8OUTEndpoint, ISOC_OUT_EP_MAX_SIZE, (USB_DMA_EP_RX | USB_DMA_EP_TYPE_ISOC | USB_DMA_EP_DEVICE)); // // Set the DMA individual transfer size. // USBLibDMAUnitSizeSet(psInst->psDMAInstance, psInst->ui8OUTDMA, 32); // // Set the DMA arbitration size. // USBLibDMAArbSizeSet(psInst->psDMAInstance, psInst->ui8OUTDMA, 16); } break; } // // Handle class specific reconfiguring of the configuration descriptor // once the composite class has built the full descriptor. // case USB_EVENT_COMP_CONFIG: { // // This sets the bFirstInterface of the Interface Association // descriptor to the first interface which is the control // interface used by this instance. // pui8Data[2] = psInst->ui8InterfaceControl; break; } default: { break; } } }