uint8_t MIDI_Host_ConfigurePipes(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo, uint16_t ConfigDescriptorSize, void* ConfigDescriptorData) { uint8_t FoundEndpoints = 0; memset(&MIDIInterfaceInfo->State, 0x00, sizeof(MIDIInterfaceInfo->State)); if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return MIDI_ENUMERROR_InvalidConfigDescriptor; if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_MIDI_Host_NextMIDIStreamingInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return MIDI_ENUMERROR_NoStreamingInterfaceFound; } while (FoundEndpoints != (MIDI_FOUND_DATAPIPE_IN | MIDI_FOUND_DATAPIPE_OUT)) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_MIDI_Host_NextMIDIStreamingDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { return MIDI_ENUMERROR_EndpointsNotFound; } USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { Pipe_ConfigurePipe(MIDIInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, MIDIInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); MIDIInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize; FoundEndpoints |= MIDI_FOUND_DATAPIPE_IN; } else { Pipe_ConfigurePipe(MIDIInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT, EndpointData->EndpointAddress, EndpointData->EndpointSize, MIDIInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); MIDIInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize; FoundEndpoints |= MIDI_FOUND_DATAPIPE_OUT; } } MIDIInterfaceInfo->State.IsActive = true; return MIDI_ENUMERROR_NoError; }
static uint8_t DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor) { USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t); if (Header->Type == DTYPE_Endpoint) { USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t); uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK); if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) && !(Pipe_IsEndpointBound(Endpoint->EndpointAddress))) { return DESCRIPTOR_SEARCH_Found; } } else if (Header->Type == DTYPE_Interface) { return DESCRIPTOR_SEARCH_Fail; } return DESCRIPTOR_SEARCH_NotFound; }
static uint8_t DCOMP_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor) { if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) { USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t); if ((CurrentInterface->Class == RNDIS_DATA_CLASS) && (CurrentInterface->SubClass == RNDIS_DATA_SUBCLASS) && (CurrentInterface->Protocol == RNDIS_DATA_PROTOCOL)) { return DESCRIPTOR_SEARCH_Found; } } return DESCRIPTOR_SEARCH_NotFound; }
static uint8_t DCOMP_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor) { if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint) { USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t); if (!(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress))) return DESCRIPTOR_SEARCH_Found; } else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) { return DESCRIPTOR_SEARCH_Fail; } return DESCRIPTOR_SEARCH_NotFound; }
static uint8_t DComp_CDC_Host_NextCDCControlInterface(void* const CurrentDescriptor) { if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) { USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t); if ((CurrentInterface->Class == CDC_CONTROL_CLASS) && (CurrentInterface->SubClass == CDC_CONTROL_SUBCLASS) && (CurrentInterface->Protocol == CDC_CONTROL_PROTOCOL)) { return DESCRIPTOR_SEARCH_Found; } } return DESCRIPTOR_SEARCH_NotFound; }
static uint8_t DComp_MIDI_Host_NextMIDIStreamingInterface(void* const CurrentDescriptor) { if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) { USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t); if ((CurrentInterface->Class == MIDI_STREAMING_CLASS) && (CurrentInterface->SubClass == MIDI_STREAMING_SUBCLASS) && (CurrentInterface->Protocol == MIDI_STREAMING_PROTOCOL)) { return DESCRIPTOR_SEARCH_Found; } } return DESCRIPTOR_SEARCH_NotFound; }
uint8_t DComp_SI_Host_NextSIInterface(void* CurrentDescriptor) { if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) { USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t); if ((CurrentInterface->Class == STILL_IMAGE_CLASS) && (CurrentInterface->SubClass == STILL_IMAGE_SUBCLASS) && (CurrentInterface->Protocol == STILL_IMAGE_PROTOCOL)) { return DESCRIPTOR_SEARCH_Found; } } return DESCRIPTOR_SEARCH_NotFound; }
static uint8_t DComp_MIDI_Host_NextMIDIStreamingDataEndpoint(void* const CurrentDescriptor) { if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint) { USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t); uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK); if ((EndpointType == EP_TYPE_BULK) && !(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress))) return DESCRIPTOR_SEARCH_Found; } else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) { return DESCRIPTOR_SEARCH_Fail; } return DESCRIPTOR_SEARCH_NotFound; }
/** Descriptor comparator function. This comparator function is can be called while processing an attached USB device's * configuration descriptor, to search for a specific sub descriptor. It can also be used to abort the configuration * descriptor processing if an incompatible descriptor configuration is found. * * This comparator searches for the next Endpoint descriptor inside the current interface descriptor, * aborting the search if another interface descriptor is found before the required endpoint. * * \return A value from the DSEARCH_Return_ErrorCodes_t enum */ uint8_t DComp_NextHIDInterfaceDataEndpoint(void* CurrentDescriptor) { USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t); /* Determine the type of the current descriptor */ if (Header->Type == DTYPE_Endpoint) { /* Indicate that the descriptor being searched for has been found */ return DESCRIPTOR_SEARCH_Found; } else if (Header->Type == DTYPE_Interface) { /* Indicate that the search has failed prematurely and should be aborted */ return DESCRIPTOR_SEARCH_Fail; } /* Current descriptor does not match what this comparator is looking for */ return DESCRIPTOR_SEARCH_NotFound; }
static uint8_t DComp_CDC_Host_NextCDCInterfaceEndpoint(void* const CurrentDescriptor) { if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint) { USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t); uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK); if ((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) { return DESCRIPTOR_SEARCH_Found; } } else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) { return DESCRIPTOR_SEARCH_Fail; } return DESCRIPTOR_SEARCH_NotFound; }
uint8_t DComp_SI_Host_NextSIInterfaceEndpoint(void* CurrentDescriptor) { if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint) { USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t); uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK); if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) && (!(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress)))) { return DESCRIPTOR_SEARCH_Found; } } else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) { return DESCRIPTOR_SEARCH_Fail; } return DESCRIPTOR_SEARCH_NotFound; }
/** Reads and processes an attached device's descriptors, to determine compatibility and pipe configurations. This * routine will read in the entire configuration descriptor, and configure the hosts pipes to correctly communicate * with compatible devices. * * This routine searches for a HID interface descriptor containing at least one Interrupt type IN endpoint and HID descriptor. * * \return An error code from the KeyboardHostWithParser_GetConfigDescriptorDataCodes_t enum. */ uint8_t ProcessConfigurationDescriptor(void) { uint8_t* ConfigDescriptorData; uint16_t ConfigDescriptorSize; /* Get Configuration Descriptor size from the device */ if (USB_GetDeviceConfigDescriptor(&ConfigDescriptorSize, NULL) != HOST_SENDCONTROL_Successful) return ControlError; /* Ensure that the Configuration Descriptor isn't too large */ if (ConfigDescriptorSize > MAX_CONFIG_DESCRIPTOR_SIZE) return DescriptorTooLarge; /* Allocate enough memory for the entire config descriptor */ ConfigDescriptorData = alloca(ConfigDescriptorSize); /* Retrieve the entire configuration descriptor into the allocated buffer */ USB_GetDeviceConfigDescriptor(&ConfigDescriptorSize, ConfigDescriptorData); /* Validate returned data - ensure first entry is a configuration header descriptor */ if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return InvalidConfigDataReturned; /* Get the keyboard interface from the configuration descriptor */ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_NextKeyboardInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoHIDInterfaceFound; } /* Get the keyboard interface's HID descriptor */ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_NextHID) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoHIDDescriptorFound; } /* Save the HID report size for later use */ HIDReportSize = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_HID_t).HIDReportLength; /* Get the keyboard interface's data endpoint descriptor */ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_NextInterfaceKeyboardDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoEndpointFound; } /* Retrieve the endpoint address from the endpoint descriptor */ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); /* Configure the keyboard data pipe */ Pipe_ConfigurePipe(KEYBOARD_DATAPIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); Pipe_SetInfiniteINRequests(); /* Valid data found, return success */ return SuccessfulConfigRead; }
uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo, uint16_t ConfigDescriptorSize, void* ConfigDescriptorData) { USB_Descriptor_Endpoint_t* DataINEndpoint = NULL; USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL; USB_Descriptor_Interface_t* HIDInterface = NULL; USB_HID_Descriptor_HID_t* HIDDescriptor = NULL; memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State)); if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return HID_ENUMERROR_InvalidConfigDescriptor; while (!(DataINEndpoint) || !(DataOUTEndpoint)) { if (!(HIDInterface) || USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_HID_Host_NextHIDInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { if (DataINEndpoint || DataOUTEndpoint) break; do { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_HID_Host_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return HID_ENUMERROR_NoCompatibleInterfaceFound; } HIDInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t); } while (HIDInterfaceInfo->Config.HIDInterfaceProtocol && (HIDInterface->Protocol != HIDInterfaceInfo->Config.HIDInterfaceProtocol)); if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_HID_Host_NextHIDDescriptor) != DESCRIPTOR_SEARCH_COMP_Found) { return HID_ENUMERROR_NoCompatibleInterfaceFound; } HIDDescriptor = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_HID_Descriptor_HID_t); DataINEndpoint = NULL; DataOUTEndpoint = NULL; continue; } USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN) DataINEndpoint = EndpointData; else DataOUTEndpoint = EndpointData; } HIDInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize); HIDInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress; HIDInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_INTERRUPT; HIDInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); HIDInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress; HIDInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_INTERRUPT; if (!(Pipe_ConfigurePipeTable(&HIDInterfaceInfo->Config.DataINPipe, 1))) return false; if (!(Pipe_ConfigurePipeTable(&HIDInterfaceInfo->Config.DataOUTPipe, 1))) return false; HIDInterfaceInfo->State.InterfaceNumber = HIDInterface->InterfaceNumber; HIDInterfaceInfo->State.HIDReportSize = LE16_TO_CPU(HIDDescriptor->HIDReportLength); HIDInterfaceInfo->State.SupportsBootProtocol = (HIDInterface->SubClass != HID_CSCP_NonBootProtocol); HIDInterfaceInfo->State.LargestReportSize = 8; HIDInterfaceInfo->State.IsActive = true; return HID_ENUMERROR_NoError; }
/** Reads and processes an attached device's descriptors, to determine compatibility and pipe configurations. This * routine will read in the entire configuration descriptor, and configure the hosts pipes to correctly communicate * with compatible devices. * * This routine searches for a CDC interface descriptor containing bulk data IN and OUT endpoints, and an interrupt event endpoint. * * \return An error code from the \ref CDCHost_GetConfigDescriptorDataCodes_t enum. */ uint8_t ProcessConfigurationDescriptor(void) { uint8_t ConfigDescriptorData[512]; void* CurrConfigLocation = ConfigDescriptorData; uint16_t CurrConfigBytesRem; USB_Descriptor_Interface_t* CDCControlInterface = NULL; USB_Descriptor_Endpoint_t* DataINEndpoint = NULL; USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL; USB_Descriptor_Endpoint_t* NotificationEndpoint = NULL; /* Retrieve the entire configuration descriptor into the allocated buffer */ switch (USB_Host_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData))) { case HOST_GETCONFIG_Successful: break; case HOST_GETCONFIG_InvalidData: return InvalidConfigDataReturned; case HOST_GETCONFIG_BuffOverflow: return DescriptorTooLarge; default: return ControlError; } while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(NotificationEndpoint)) { /* See if we've found a likely compatible interface, and if there is an endpoint within that interface */ if (!(CDCControlInterface) || USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextCDCDataInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { /* Check if we have already found the control interface's notification endpoint or not */ if (NotificationEndpoint) { /* Get the next CDC data interface from the configuration descriptor */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoCompatibleInterfaceFound; } /* Clear any found endpoints */ DataINEndpoint = NULL; DataOUTEndpoint = NULL; } else { /* Get the next CDC control interface from the configuration descriptor */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoCompatibleInterfaceFound; } /* Save the interface in case we need to refer back to it later */ CDCControlInterface = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Interface_t); /* Clear any found endpoints */ NotificationEndpoint = NULL; } /* Skip the remainder of the loop as we have not found an endpoint yet */ continue; } /* Retrieve the endpoint address from the endpoint descriptor */ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Endpoint_t); /* If the endpoint is a IN type endpoint */ if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN) { /* Check if the found endpoint is a interrupt or bulk type descriptor */ if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT) NotificationEndpoint = EndpointData; else DataINEndpoint = EndpointData; } else { DataOUTEndpoint = EndpointData; } } /* Configure the CDC data IN pipe */ Pipe_ConfigurePipe(CDC_DATA_IN_PIPE, EP_TYPE_BULK, DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, 1); /* Configure the CDC data OUT pipe */ Pipe_ConfigurePipe(CDC_DATA_OUT_PIPE, EP_TYPE_BULK, DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, 1); /* Configure the CDC notification pipe */ Pipe_ConfigurePipe(CDC_NOTIFICATION_PIPE, EP_TYPE_INTERRUPT, NotificationEndpoint->EndpointAddress, NotificationEndpoint->EndpointSize, 1); Pipe_SetInterruptPeriod(NotificationEndpoint->PollingIntervalMS); /* Valid data found, return success */ return SuccessfulConfigRead; }
/** Reads and processes an attached device's descriptors, to determine compatibility and pipe configurations. This * routine will read in the entire configuration descriptor, and configure the hosts pipes to correctly communicate * with compatible devices. * * This routine searches for a MSD interface descriptor containing bulk IN and OUT data endpoints. * * \return An error code from the \ref MassStorageHost_GetConfigDescriptorDataCodes_t enum. */ uint8_t ProcessConfigurationDescriptor(void) { uint8_t ConfigDescriptorData[512]; void* CurrConfigLocation = ConfigDescriptorData; uint16_t CurrConfigBytesRem; USB_Descriptor_Interface_t* MSInterface = NULL; USB_Descriptor_Endpoint_t* DataINEndpoint = NULL; USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL; /* Retrieve the entire configuration descriptor into the allocated buffer */ switch (USB_Host_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData))) { case HOST_GETCONFIG_Successful: break; case HOST_GETCONFIG_InvalidData: return InvalidConfigDataReturned; case HOST_GETCONFIG_BuffOverflow: return DescriptorTooLarge; default: return ControlError; } while (!(DataINEndpoint) || !(DataOUTEndpoint)) { /* See if we've found a likely compatible interface, and if there is an endpoint within that interface */ if (!(MSInterface) || USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextMSInterfaceBulkDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { /* Get the next Mass Storage interface from the configuration descriptor */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextMSInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoCompatibleInterfaceFound; } /* Save the interface in case we need to refer back to it later */ MSInterface = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Interface_t); /* Clear any found endpoints */ DataINEndpoint = NULL; DataOUTEndpoint = NULL; /* Skip the remainder of the loop as we have not found an endpoint yet */ continue; } /* Retrieve the endpoint address from the endpoint descriptor */ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Endpoint_t); /* If the endpoint is a IN type endpoint */ if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) DataINEndpoint = EndpointData; else DataOUTEndpoint = EndpointData; } /* Configure the Mass Storage data IN pipe */ Pipe_ConfigurePipe(MASS_STORE_DATA_IN_PIPE, EP_TYPE_BULK, PIPE_TOKEN_IN, DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, PIPE_BANK_SINGLE); /* Configure the Mass Storage data OUT pipe */ Pipe_ConfigurePipe(MASS_STORE_DATA_OUT_PIPE, EP_TYPE_BULK, PIPE_TOKEN_OUT, DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, PIPE_BANK_SINGLE); /* Valid data found, return success */ return SuccessfulConfigRead; }
uint8_t Audio_Host_ConfigurePipes(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo, uint16_t ConfigDescriptorSize, void* ConfigDescriptorData) { USB_Descriptor_Endpoint_t* DataINEndpoint = NULL; USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL; USB_Descriptor_Interface_t* AudioControlInterface = NULL; USB_Descriptor_Interface_t* AudioStreamingInterface = NULL; memset(&AudioInterfaceInfo->State, 0x00, sizeof(AudioInterfaceInfo->State)); if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return AUDIO_ENUMERROR_InvalidConfigDescriptor; while ((AudioInterfaceInfo->Config.DataINPipe.Address && !(DataINEndpoint)) || (AudioInterfaceInfo->Config.DataOUTPipe.Address && !(DataOUTEndpoint))) { if (!(AudioControlInterface) || USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_Audio_Host_NextAudioInterfaceDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { if (!(AudioControlInterface) || USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_Audio_Host_NextAudioStreamInterface) != DESCRIPTOR_SEARCH_COMP_Found) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_Audio_Host_NextAudioControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return AUDIO_ENUMERROR_NoCompatibleInterfaceFound; } AudioControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t); if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_Audio_Host_NextAudioStreamInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return AUDIO_ENUMERROR_NoCompatibleInterfaceFound; } } AudioStreamingInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t); DataINEndpoint = NULL; DataOUTEndpoint = NULL; continue; } USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN) DataINEndpoint = EndpointData; else DataOUTEndpoint = EndpointData; } AudioInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize); AudioInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress; AudioInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_ISOCHRONOUS; AudioInterfaceInfo->Config.DataINPipe.Banks = 2; AudioInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); AudioInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress; AudioInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_ISOCHRONOUS; AudioInterfaceInfo->Config.DataOUTPipe.Banks = 2; if (!(Pipe_ConfigurePipeTable(&AudioInterfaceInfo->Config.DataINPipe, 1))) return false; if (!(Pipe_ConfigurePipeTable(&AudioInterfaceInfo->Config.DataOUTPipe, 1))) return false; AudioInterfaceInfo->State.ControlInterfaceNumber = AudioControlInterface->InterfaceNumber; AudioInterfaceInfo->State.StreamingInterfaceNumber = AudioStreamingInterface->InterfaceNumber; AudioInterfaceInfo->State.EnabledStreamingAltIndex = AudioStreamingInterface->AlternateSetting; AudioInterfaceInfo->State.IsActive = true; return AUDIO_ENUMERROR_NoError; }
uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, uint16_t ConfigDescriptorSize, void* ConfigDescriptorData) { USB_Descriptor_Endpoint_t* DataINEndpoint = NULL; USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL; USB_Descriptor_Interface_t* PrinterInterface = NULL; memset(&PRNTInterfaceInfo->State, 0x00, sizeof(PRNTInterfaceInfo->State)); if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return PRNT_ENUMERROR_InvalidConfigDescriptor; while (!(DataINEndpoint) || !(DataOUTEndpoint)) { if (!(PrinterInterface) || USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_PRNT_Host_NextPRNTInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return PRNT_ENUMERROR_NoCompatibleInterfaceFound; } PrinterInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t); DataINEndpoint = NULL; DataOUTEndpoint = NULL; continue; } USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN) DataINEndpoint = EndpointData; else DataOUTEndpoint = EndpointData; } PRNTInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize); PRNTInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress; PRNTInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK; PRNTInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); PRNTInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress; PRNTInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK; if (!(Pipe_ConfigurePipeTable(&PRNTInterfaceInfo->Config.DataINPipe, 1))) return PRNT_ENUMERROR_PipeConfigurationFailed; if (!(Pipe_ConfigurePipeTable(&PRNTInterfaceInfo->Config.DataOUTPipe, 1))) return PRNT_ENUMERROR_PipeConfigurationFailed; PRNTInterfaceInfo->State.InterfaceNumber = PrinterInterface->InterfaceNumber; PRNTInterfaceInfo->State.AlternateSetting = PrinterInterface->AlternateSetting; PRNTInterfaceInfo->State.IsActive = true; return PRNT_ENUMERROR_NoError; }
uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo, uint16_t ConfigDescriptorSize, void* ConfigDescriptorData) { USB_Descriptor_Endpoint_t* DataINEndpoint = NULL; USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL; USB_Descriptor_Interface_t* HIDInterface = NULL; USB_HID_Descriptor_HID_t* HIDDescriptor = NULL; uint8_t portnum = HIDInterfaceInfo->Config.PortNumber; memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State)); if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return HID_ENUMERROR_InvalidConfigDescriptor; while (!(DataINEndpoint) || !(DataOUTEndpoint)) { if (!(HIDInterface) || USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_HID_Host_NextHIDInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { if (DataINEndpoint || DataOUTEndpoint) break; do { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_HID_Host_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return HID_ENUMERROR_NoCompatibleInterfaceFound; } HIDInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t); } while (HIDInterfaceInfo->Config.HIDInterfaceProtocol && (HIDInterface->Protocol != HIDInterfaceInfo->Config.HIDInterfaceProtocol)); if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_HID_Host_NextHIDDescriptor) != DESCRIPTOR_SEARCH_COMP_Found) { return HID_ENUMERROR_NoCompatibleInterfaceFound; } HIDDescriptor = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_HID_Descriptor_HID_t); DataINEndpoint = NULL; DataOUTEndpoint = NULL; continue; } USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN) DataINEndpoint = EndpointData; else DataOUTEndpoint = EndpointData; } for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) { uint16_t Size; uint8_t Type; uint8_t Token; uint8_t EndpointAddress; uint8_t InterruptPeriod; bool DoubleBanked; if (PipeNum == HIDInterfaceInfo->Config.DataINPipeNumber) { Size = le16_to_cpu(DataINEndpoint->EndpointSize); EndpointAddress = DataINEndpoint->EndpointAddress; Token = PIPE_TOKEN_IN; Type = EP_TYPE_INTERRUPT; DoubleBanked = HIDInterfaceInfo->Config.DataINPipeDoubleBank; InterruptPeriod = DataINEndpoint->PollingIntervalMS; HIDInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; } else if (PipeNum == HIDInterfaceInfo->Config.DataOUTPipeNumber) { if (DataOUTEndpoint == NULL) continue; Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); EndpointAddress = DataOUTEndpoint->EndpointAddress; Token = PIPE_TOKEN_OUT; Type = EP_TYPE_INTERRUPT; DoubleBanked = HIDInterfaceInfo->Config.DataOUTPipeDoubleBank; InterruptPeriod = DataOUTEndpoint->PollingIntervalMS; HIDInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; HIDInterfaceInfo->State.DeviceUsesOUTPipe = true; } else { continue; } if (!(Pipe_ConfigurePipe(portnum,PipeNum, Type, Token, EndpointAddress, Size, DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) { return HID_ENUMERROR_PipeConfigurationFailed; } if (InterruptPeriod) Pipe_SetInterruptPeriod(InterruptPeriod); } HIDInterfaceInfo->State.InterfaceNumber = HIDInterface->InterfaceNumber; HIDInterfaceInfo->State.HIDReportSize = LE16_TO_CPU(HIDDescriptor->HIDReportLength); HIDInterfaceInfo->State.SupportsBootProtocol = (HIDInterface->SubClass != HID_CSCP_NonBootProtocol); HIDInterfaceInfo->State.LargestReportSize = 8; HIDInterfaceInfo->State.IsActive = true; return HID_ENUMERROR_NoError; }
uint8_t USB_Host_GetDeviceConfigDescriptor(const uint8_t ConfigNumber, uint16_t* const ConfigSizePtr, void* const BufferPtr, const uint16_t BufferSize) { uint8_t ErrorCode; uint8_t ConfigHeader[sizeof(USB_Descriptor_Configuration_Header_t)]; USB_ControlRequest = (USB_Request_Header_t) { .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE), .bRequest = REQ_GetDescriptor, .wValue = ((DTYPE_Configuration << 8) | (ConfigNumber - 1)), .wIndex = 0, .wLength = sizeof(USB_Descriptor_Configuration_Header_t), }; Pipe_SelectPipe(PIPE_CONTROLPIPE); if ((ErrorCode = USB_Host_SendControlRequest(ConfigHeader)) != HOST_SENDCONTROL_Successful) return ErrorCode; *ConfigSizePtr = le16_to_cpu(DESCRIPTOR_PCAST(ConfigHeader, USB_Descriptor_Configuration_Header_t)->TotalConfigurationSize); if (*ConfigSizePtr > BufferSize) return HOST_GETCONFIG_BuffOverflow; USB_ControlRequest.wLength = *ConfigSizePtr; if ((ErrorCode = USB_Host_SendControlRequest(BufferPtr)) != HOST_SENDCONTROL_Successful) return ErrorCode; if (DESCRIPTOR_TYPE(BufferPtr) != DTYPE_Configuration) return HOST_GETCONFIG_InvalidData; return HOST_GETCONFIG_Successful; } #endif void USB_GetNextDescriptorOfType(uint16_t* const BytesRem, void** const CurrConfigLoc, const uint8_t Type) { while (*BytesRem) { USB_GetNextDescriptor(BytesRem, CurrConfigLoc); if (DESCRIPTOR_TYPE(*CurrConfigLoc) == Type) return; } } void USB_GetNextDescriptorOfTypeBefore(uint16_t* const BytesRem, void** const CurrConfigLoc, const uint8_t Type, const uint8_t BeforeType) { while (*BytesRem) { USB_GetNextDescriptor(BytesRem, CurrConfigLoc); if (DESCRIPTOR_TYPE(*CurrConfigLoc) == Type) { return; } else if (DESCRIPTOR_TYPE(*CurrConfigLoc) == BeforeType) { *BytesRem = 0; return; } } } void USB_GetNextDescriptorOfTypeAfter(uint16_t* const BytesRem, void** const CurrConfigLoc, const uint8_t Type, const uint8_t AfterType) { USB_GetNextDescriptorOfType(BytesRem, CurrConfigLoc, AfterType); if (*BytesRem) USB_GetNextDescriptorOfType(BytesRem, CurrConfigLoc, Type); }
/** Reads and processes an attached device's descriptors, to determine compatibility and pipe configurations. This * routine will read in the entire configuration descriptor, and configure the hosts pipes to correctly communicate * with compatible devices. * * This routine searches for a HID interface descriptor containing at least one Interrupt type IN endpoint and HID descriptor. * * \return An error code from the \ref MouseHostWithParser_GetConfigDescriptorDataCodes_t enum. */ uint8_t ProcessConfigurationDescriptor(void) { uint8_t ConfigDescriptorData[512]; void* CurrConfigLocation = ConfigDescriptorData; uint16_t CurrConfigBytesRem; USB_Descriptor_Interface_t* HIDInterface = NULL; USB_HID_Descriptor_HID_t* HIDDescriptor = NULL; USB_Descriptor_Endpoint_t* DataINEndpoint = NULL; /* Retrieve the entire configuration descriptor into the allocated buffer */ switch (USB_Host_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData))) { case HOST_GETCONFIG_Successful: break; case HOST_GETCONFIG_InvalidData: return InvalidConfigDataReturned; case HOST_GETCONFIG_BuffOverflow: return DescriptorTooLarge; default: return ControlError; } while (!(DataINEndpoint)) { /* See if we've found a likely compatible interface, and if there is an endpoint within that interface */ if (!(HIDInterface) || USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextMouseInterfaceDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { /* Get the next HID interface from the configuration descriptor */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextMouseInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoCompatibleInterfaceFound; } /* Save the interface in case we need to refer back to it later */ HIDInterface = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Interface_t); /* Get the HID descriptor from the configuration descriptor */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextHID) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoCompatibleInterfaceFound; } /* Save the HID descriptor for later use */ HIDDescriptor = DESCRIPTOR_PCAST(CurrConfigLocation, USB_HID_Descriptor_HID_t); /* Skip the remainder of the loop as we have not found an endpoint yet */ continue; } /* Retrieve the endpoint address from the endpoint descriptor */ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Endpoint_t); /* If the endpoint is a IN type endpoint */ if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) DataINEndpoint = EndpointData; } /* Configure the HID data IN pipe */ Pipe_ConfigurePipe(MOUSE_DATA_IN_PIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, PIPE_BANK_SINGLE); Pipe_SetInterruptPeriod(DataINEndpoint->PollingIntervalMS); /* Get the HID report size from the HID report descriptor */ HIDReportSize = HIDDescriptor->HIDReportLength; /* Valid data found, return success */ return SuccessfulConfigRead; }
/** Reads and processes an attached device's descriptors, to determine compatibility and pipe configurations. This * routine will read in the entire configuration descriptor, and configure the hosts pipes to correctly communicate * with compatible devices. * * This routine searches for a MSD interface descriptor containing bulk IN and OUT data endpoints. * * \return An error code from the \ref MassStorageHost_GetConfigDescriptorDataCodes_t enum. */ uint8_t ProcessConfigurationDescriptor(void) { uint8_t ConfigDescriptorData[512]; void* CurrConfigLocation = ConfigDescriptorData; uint16_t CurrConfigBytesRem; uint8_t FoundEndpoints = 0; /* Retrieve the entire configuration descriptor into the allocated buffer */ switch (USB_Host_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData))) { case HOST_GETCONFIG_Successful: break; case HOST_GETCONFIG_InvalidData: return InvalidConfigDataReturned; case HOST_GETCONFIG_BuffOverflow: return DescriptorTooLarge; default: return ControlError; } /* Get the mass storage interface from the configuration descriptor */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextMSInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoInterfaceFound; } /* Get the IN and OUT data endpoints for the mass storage interface */ while (FoundEndpoints != ((1 << MASS_STORE_DATA_IN_PIPE) | (1 << MASS_STORE_DATA_OUT_PIPE))) { /* Fetch the next bulk endpoint from the current mass storage interface */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextMSInterfaceBulkDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoEndpointFound; } USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Endpoint_t); /* Check if the endpoint is a bulk IN or bulk OUT endpoint, set appropriate globals */ if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { /* Configure the data IN pipe */ Pipe_ConfigurePipe(MASS_STORE_DATA_IN_PIPE, EP_TYPE_BULK, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_DOUBLE); /* Set the flag indicating that the data IN pipe has been found */ FoundEndpoints |= (1 << MASS_STORE_DATA_IN_PIPE); } else { /* Configure the data OUT pipe */ Pipe_ConfigurePipe(MASS_STORE_DATA_OUT_PIPE, EP_TYPE_BULK, PIPE_TOKEN_OUT, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_DOUBLE); /* Set the flag indicating that the data OUT pipe has been found */ FoundEndpoints |= (1 << MASS_STORE_DATA_OUT_PIPE); } } /* Valid data found, return success */ return SuccessfulConfigRead; }
/** Reads and processes an attached device's descriptors, to determine compatibility and pipe configurations. This * routine will read in the entire configuration descriptor, and configure the hosts pipes to correctly communicate * with compatible devices. * * This routine searches for a BT interface descriptor containing bulk IN and OUT data endpoints. * * \return An error code from the \ref BluetoothHost_GetConfigDescriptorDataCodes_t enum. */ uint8_t ProcessConfigurationDescriptor(void) { uint8_t ConfigDescriptorData[512]; void* CurrConfigLocation = ConfigDescriptorData; uint16_t CurrConfigBytesRem; USB_Descriptor_Endpoint_t* DataINEndpoint = NULL; USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL; USB_Descriptor_Endpoint_t* EventsEndpoint = NULL; /* Retrieve the entire configuration descriptor into the allocated buffer */ switch (USB_Host_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData))) { case HOST_GETCONFIG_Successful: break; case HOST_GETCONFIG_InvalidData: return InvalidConfigDataReturned; case HOST_GETCONFIG_BuffOverflow: return DescriptorTooLarge; default: return DevControlError; } /* The Bluetooth USB transport addendum mandates that the data (not streaming voice) endpoints be in the first interface descriptor (interface 0) */ USB_GetNextDescriptorOfType(&CurrConfigBytesRem, &CurrConfigLocation, DTYPE_Interface); /* Ensure that an interface was found, and the end of the descriptor was not reached */ if (!(CurrConfigBytesRem)) return NoCompatibleInterfaceFound; while (!(DataINEndpoint) || !(DataOUTEndpoint)) { /* Get the next Bluetooth interface's data endpoint descriptor */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextInterfaceBluetoothDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { /* Data endpoints not found within the first bluetooth device interface, error out */ return NoCompatibleInterfaceFound; } /* Retrieve the endpoint address from the endpoint descriptor */ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Endpoint_t); /* If the endpoint is a IN type endpoint */ if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN) { /* Check if the found endpoint is a interrupt or bulk type descriptor */ if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT) EventsEndpoint = EndpointData; else DataINEndpoint = EndpointData; } else { DataOUTEndpoint = EndpointData; } } /* Configure the Bluetooth data IN pipe */ Pipe_ConfigurePipe(BLUETOOTH_DATA_IN_PIPE, EP_TYPE_BULK, PIPE_TOKEN_IN, DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, PIPE_BANK_SINGLE); /* Configure the Bluetooth data OUT pipe */ Pipe_ConfigurePipe(BLUETOOTH_DATA_OUT_PIPE, EP_TYPE_BULK, PIPE_TOKEN_OUT, DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, PIPE_BANK_SINGLE); /* Configure the Bluetooth events pipe */ Pipe_ConfigurePipe(BLUETOOTH_EVENTS_PIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, EventsEndpoint->EndpointAddress, EventsEndpoint->EndpointSize, PIPE_BANK_SINGLE); Pipe_SetInterruptPeriod(EventsEndpoint->PollingIntervalMS); /* Valid data found, return success */ return SuccessfulConfigRead; }
uint8_t Audio_Host_ConfigurePipes(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo, uint16_t ConfigDescriptorSize, void* ConfigDescriptorData) { USB_Descriptor_Endpoint_t* DataINEndpoint = NULL; USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL; USB_Descriptor_Interface_t* AudioControlInterface = NULL; USB_Descriptor_Interface_t* AudioStreamingInterface = NULL; memset(&AudioInterfaceInfo->State, 0x00, sizeof(AudioInterfaceInfo->State)); if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return AUDIO_ENUMERROR_InvalidConfigDescriptor; while ((AudioInterfaceInfo->Config.DataINPipeNumber && !(DataINEndpoint)) || (AudioInterfaceInfo->Config.DataOUTPipeNumber && !(DataOUTEndpoint))) { if (!(AudioControlInterface) || USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_Audio_Host_NextAudioInterfaceDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { if (!(AudioControlInterface) || USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_Audio_Host_NextAudioStreamInterface) != DESCRIPTOR_SEARCH_COMP_Found) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_Audio_Host_NextAudioControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return AUDIO_ENUMERROR_NoCompatibleInterfaceFound; } AudioControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t); if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_Audio_Host_NextAudioStreamInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return AUDIO_ENUMERROR_NoCompatibleInterfaceFound; } } AudioStreamingInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t); DataINEndpoint = NULL; DataOUTEndpoint = NULL; continue; } USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN) DataINEndpoint = EndpointData; else DataOUTEndpoint = EndpointData; } for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) { uint16_t Size; uint8_t Type; uint8_t Token; uint8_t EndpointAddress; bool DoubleBanked; if (PipeNum == AudioInterfaceInfo->Config.DataINPipeNumber) { Size = le16_to_cpu(DataINEndpoint->EndpointSize); EndpointAddress = DataINEndpoint->EndpointAddress; Token = PIPE_TOKEN_IN; Type = EP_TYPE_ISOCHRONOUS; DoubleBanked = true; AudioInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; } else if (PipeNum == AudioInterfaceInfo->Config.DataOUTPipeNumber) { Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); EndpointAddress = DataOUTEndpoint->EndpointAddress; Token = PIPE_TOKEN_OUT; Type = EP_TYPE_ISOCHRONOUS; DoubleBanked = true; AudioInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; } else { continue; } if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) { return AUDIO_ENUMERROR_PipeConfigurationFailed; } } AudioInterfaceInfo->State.ControlInterfaceNumber = AudioControlInterface->InterfaceNumber; AudioInterfaceInfo->State.StreamingInterfaceNumber = AudioStreamingInterface->InterfaceNumber; AudioInterfaceInfo->State.EnabledStreamingAltIndex = AudioStreamingInterface->AlternateSetting; AudioInterfaceInfo->State.IsActive = true; return AUDIO_ENUMERROR_NoError; }
uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, uint16_t ConfigDescriptorSize, void* ConfigDescriptorData) { USB_Descriptor_Endpoint_t* DataINEndpoint = NULL; USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL; USB_Descriptor_Interface_t* PrinterInterface = NULL; memset(&PRNTInterfaceInfo->State, 0x00, sizeof(PRNTInterfaceInfo->State)); if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return PRNT_ENUMERROR_InvalidConfigDescriptor; while (!(DataINEndpoint) || !(DataOUTEndpoint)) { if (!(PrinterInterface) || USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_PRNT_Host_NextPRNTInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return PRNT_ENUMERROR_NoCompatibleInterfaceFound; } PrinterInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t); DataINEndpoint = NULL; DataOUTEndpoint = NULL; continue; } USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN) DataINEndpoint = EndpointData; else DataOUTEndpoint = EndpointData; } for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) { uint16_t Size; uint8_t Type; uint8_t Token; uint8_t EndpointAddress; bool DoubleBanked; if (PipeNum == PRNTInterfaceInfo->Config.DataINPipeNumber) { Size = le16_to_cpu(DataINEndpoint->EndpointSize); EndpointAddress = DataINEndpoint->EndpointAddress; Token = PIPE_TOKEN_IN; Type = EP_TYPE_BULK; DoubleBanked = PRNTInterfaceInfo->Config.DataINPipeDoubleBank; PRNTInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; } else if (PipeNum == PRNTInterfaceInfo->Config.DataOUTPipeNumber) { Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); EndpointAddress = DataOUTEndpoint->EndpointAddress; Token = PIPE_TOKEN_OUT; Type = EP_TYPE_BULK; DoubleBanked = PRNTInterfaceInfo->Config.DataOUTPipeDoubleBank; PRNTInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; } else { continue; } if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) { return PRNT_ENUMERROR_PipeConfigurationFailed; } } PRNTInterfaceInfo->State.InterfaceNumber = PrinterInterface->InterfaceNumber; PRNTInterfaceInfo->State.AlternateSetting = PrinterInterface->AlternateSetting; PRNTInterfaceInfo->State.IsActive = true; return PRNT_ENUMERROR_NoError; }
/** Reads and processes an attached device's descriptors, to determine compatibility and pipe configurations. This * routine will read in the entire configuration descriptor, and configure the hosts pipes to correctly communicate * with compatible devices. * * This routine searches for a Streaming Audio interface descriptor containing a valid Isochronous audio endpoint. * * \return An error code from the \ref AudioHost_GetConfigDescriptorDataCodes_t enum. */ uint8_t ProcessConfigurationDescriptor(void) { uint8_t ConfigDescriptorData[512]; void* CurrConfigLocation = ConfigDescriptorData; uint16_t CurrConfigBytesRem; USB_Descriptor_Interface_t* AudioControlInterface = NULL; USB_Descriptor_Interface_t* AudioStreamingInterface = NULL; USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL; /* Retrieve the entire configuration descriptor into the allocated buffer */ switch (USB_Host_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData))) { case HOST_GETCONFIG_Successful: break; case HOST_GETCONFIG_InvalidData: return InvalidConfigDataReturned; case HOST_GETCONFIG_BuffOverflow: return DescriptorTooLarge; default: return ControlError; } while (!(DataOUTEndpoint)) { /* See if we've found a likely compatible interface, and if there is an endpoint within that interface */ if (!(AudioControlInterface) || USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextAudioInterfaceDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { /* Check if we haven't found an Audio Control interface yet, or if we have run out of related Audio Streaming interfaces */ if (!(AudioControlInterface) || USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextAudioStreamInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Find a new Audio Control interface if the current one doesn't contain a compatible streaming interface */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextAudioControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoCompatibleInterfaceFound; } /* Save the interface in case we need to refer back to it later */ AudioControlInterface = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Interface_t); /* Find the next Audio Streaming interface within that Audio Control interface */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextAudioStreamInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoCompatibleInterfaceFound; } } /* Save the interface in case we need to refer back to it later */ AudioStreamingInterface = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Interface_t); /* Skip the remainder of the loop as we have not found an endpoint yet */ continue; } /* Retrieve the endpoint address from the endpoint descriptor */ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Endpoint_t); /* Save the endpoint if it is an OUT type endpoint */ if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_OUT) DataOUTEndpoint = EndpointData; } StreamingInterfaceIndex = AudioStreamingInterface->InterfaceNumber; StreamingInterfaceAltSetting = AudioStreamingInterface->AlternateSetting; StreamingEndpointAddress = DataOUTEndpoint->EndpointAddress; /* Configure the Audio data OUT pipe */ Pipe_ConfigurePipe(AUDIO_DATA_OUT_PIPE, EP_TYPE_ISOCHRONOUS, DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, 2); /* Valid data found, return success */ return SuccessfulConfigRead; }
uint8_t SI_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, uint16_t ConfigDescriptorSize, void* ConfigDescriptorData) { USB_Descriptor_Endpoint_t* DataINEndpoint = NULL; USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL; USB_Descriptor_Endpoint_t* EventsEndpoint = NULL; USB_Descriptor_Interface_t* StillImageInterface = NULL; memset(&SIInterfaceInfo->State, 0x00, sizeof(SIInterfaceInfo->State)); if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return SI_ENUMERROR_InvalidConfigDescriptor; while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(EventsEndpoint)) { if (!(StillImageInterface) || USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_SI_Host_NextSIInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_SI_Host_NextSIInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return SI_ENUMERROR_NoCompatibleInterfaceFound; } StillImageInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t); DataINEndpoint = NULL; DataOUTEndpoint = NULL; EventsEndpoint = NULL; continue; } USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN) { if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT) EventsEndpoint = EndpointData; else DataINEndpoint = EndpointData; } else { DataOUTEndpoint = EndpointData; } } SIInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize); SIInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress; SIInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK; SIInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); SIInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress; SIInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK; SIInterfaceInfo->Config.EventsPipe.Size = le16_to_cpu(EventsEndpoint->EndpointSize); SIInterfaceInfo->Config.EventsPipe.EndpointAddress = EventsEndpoint->EndpointAddress; SIInterfaceInfo->Config.EventsPipe.Type = EP_TYPE_INTERRUPT; if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.DataINPipe, 1))) return SI_ENUMERROR_PipeConfigurationFailed; if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.DataOUTPipe, 1))) return SI_ENUMERROR_PipeConfigurationFailed; if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.EventsPipe, 1))) return SI_ENUMERROR_PipeConfigurationFailed; SIInterfaceInfo->State.InterfaceNumber = StillImageInterface->InterfaceNumber; SIInterfaceInfo->State.IsActive = true; return SI_ENUMERROR_NoError; }
uint8_t SI_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, uint16_t ConfigDescriptorSize, void* ConfigDescriptorData) { USB_Descriptor_Endpoint_t* DataINEndpoint = NULL; USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL; USB_Descriptor_Endpoint_t* EventsEndpoint = NULL; USB_Descriptor_Interface_t* StillImageInterface = NULL; memset(&SIInterfaceInfo->State, 0x00, sizeof(SIInterfaceInfo->State)); if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return SI_ENUMERROR_InvalidConfigDescriptor; while (!(DataINEndpoint) || !(DataOUTEndpoint)) { if (!(StillImageInterface) || USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_SI_Host_NextSIInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_SI_Host_NextSIInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return SI_ENUMERROR_NoCompatibleInterfaceFound; } StillImageInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t); DataINEndpoint = NULL; DataOUTEndpoint = NULL; EventsEndpoint = NULL; continue; } USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT) EventsEndpoint = EndpointData; else DataINEndpoint = EndpointData; } else { DataOUTEndpoint = EndpointData; } } for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) { if (PipeNum == SIInterfaceInfo->Config.DataINPipeNumber) { Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN, DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, SIInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); SIInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; } else if (PipeNum == SIInterfaceInfo->Config.DataOUTPipeNumber) { Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT, DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, SIInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); SIInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; } else if (PipeNum == SIInterfaceInfo->Config.EventsPipeNumber) { Pipe_ConfigurePipe(PipeNum, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, EventsEndpoint->EndpointAddress, EventsEndpoint->EndpointSize, SIInterfaceInfo->Config.EventsPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); Pipe_SetInterruptPeriod(EventsEndpoint->PollingIntervalMS); SIInterfaceInfo->State.EventsPipeSize = EventsEndpoint->EndpointSize; } } SIInterfaceInfo->State.InterfaceNumber = StillImageInterface->InterfaceNumber; SIInterfaceInfo->State.IsActive = true; return SI_ENUMERROR_NoError; }
/** Reads and processes an attached device's descriptors, to determine compatibility and pipe configurations. This * routine will read in the entire configuration descriptor, and configure the hosts pipes to correctly communicate * with compatible devices. * * This routine searches for a HID interface descriptor containing at least one Interrupt type IN endpoint. * * \return An error code from the \ref GenericHIDHost_GetConfigDescriptorDataCodes_t enum. */ uint8_t ProcessConfigurationDescriptor(void) { uint8_t ConfigDescriptorData[512]; void* CurrConfigLocation = ConfigDescriptorData; uint16_t CurrConfigBytesRem; USB_Descriptor_Interface_t* HIDInterface = NULL; USB_Descriptor_Endpoint_t* DataINEndpoint = NULL; USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL; /* Retrieve the entire configuration descriptor into the allocated buffer */ switch (USB_Host_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData))) { case HOST_GETCONFIG_Successful: break; case HOST_GETCONFIG_InvalidData: return InvalidConfigDataReturned; case HOST_GETCONFIG_BuffOverflow: return DescriptorTooLarge; default: return ControlError; } while (!(DataINEndpoint) || !(DataOUTEndpoint)) { /* See if we've found a likely compatible interface, and if there is an endpoint within that interface */ if (!(HIDInterface) || USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextHIDInterfaceDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { /* Not all HID devices have an OUT endpoint - if we've reached the end of the HID descriptor * but only found the mandatory IN endpoint, it's safe to continue with the device enumeration */ if (DataINEndpoint) break; /* Get the next HID interface from the configuration descriptor */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoCompatibleInterfaceFound; } /* Save the interface in case we need to refer back to it later */ HIDInterface = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Interface_t); /* Clear any found endpoints */ DataOUTEndpoint = NULL; /* Skip the remainder of the loop as we have not found an endpoint yet */ continue; } /* Retrieve the endpoint address from the endpoint descriptor */ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Endpoint_t); /* If the endpoint is a IN type endpoint */ if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN) DataINEndpoint = EndpointData; else DataOUTEndpoint = EndpointData; } /* Configure the HID data IN pipe */ Pipe_ConfigurePipe(HID_DATA_IN_PIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, PIPE_BANK_SINGLE); Pipe_SetInterruptPeriod(DataINEndpoint->PollingIntervalMS); /* Check if the HID interface contained an optional OUT data endpoint */ if (DataOUTEndpoint) { /* Configure the HID data OUT pipe */ Pipe_ConfigurePipe(HID_DATA_OUT_PIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_OUT, DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, PIPE_BANK_SINGLE); } /* Valid data found, return success */ return SuccessfulConfigRead; }
uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, uint16_t ConfigDescriptorSize, void* ConfigDescriptorData) { USB_Descriptor_Endpoint_t* DataINEndpoint = NULL; USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL; USB_Descriptor_Endpoint_t* NotificationEndpoint = NULL; USB_Descriptor_Interface_t* CDCControlInterface = NULL; memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State)); if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return CDC_ENUMERROR_InvalidConfigDescriptor; while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(NotificationEndpoint)) { if (!(CDCControlInterface) || USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { if (NotificationEndpoint) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_CDC_Host_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return CDC_ENUMERROR_NoCompatibleInterfaceFound; } DataINEndpoint = NULL; DataOUTEndpoint = NULL; } else { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return CDC_ENUMERROR_NoCompatibleInterfaceFound; } CDCControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t); NotificationEndpoint = NULL; } continue; } USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT) NotificationEndpoint = EndpointData; else DataINEndpoint = EndpointData; } else { DataOUTEndpoint = EndpointData; } } for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) { if (PipeNum == CDCInterfaceInfo->Config.DataINPipeNumber) { Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN, DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, CDCInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); CDCInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; } else if (PipeNum == CDCInterfaceInfo->Config.DataOUTPipeNumber) { Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT, DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, CDCInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); CDCInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; } else if (PipeNum == CDCInterfaceInfo->Config.NotificationPipeNumber) { Pipe_ConfigurePipe(PipeNum, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, NotificationEndpoint->EndpointAddress, NotificationEndpoint->EndpointSize, CDCInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); Pipe_SetInterruptPeriod(NotificationEndpoint->PollingIntervalMS); CDCInterfaceInfo->State.NotificationPipeSize = NotificationEndpoint->EndpointSize; } } CDCInterfaceInfo->State.ControlInterfaceNumber = CDCControlInterface->InterfaceNumber; CDCInterfaceInfo->State.ControlLineStates.HostToDevice = (CDC_CONTROL_LINE_OUT_RTS | CDC_CONTROL_LINE_OUT_DTR); CDCInterfaceInfo->State.ControlLineStates.DeviceToHost = (CDC_CONTROL_LINE_IN_DCD | CDC_CONTROL_LINE_IN_DSR); CDCInterfaceInfo->State.IsActive = true; return CDC_ENUMERROR_NoError; }
uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, uint16_t ConfigDescriptorSize, void* ConfigDescriptorData) { USB_Descriptor_Endpoint_t* DataINEndpoint = NULL; USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL; USB_Descriptor_Endpoint_t* NotificationEndpoint = NULL; USB_Descriptor_Interface_t* CDCControlInterface = NULL; memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State)); if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return CDC_ENUMERROR_InvalidConfigDescriptor; while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(NotificationEndpoint)) { if (!(CDCControlInterface) || USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { if (NotificationEndpoint) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_CDC_Host_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return CDC_ENUMERROR_NoCompatibleInterfaceFound; } DataINEndpoint = NULL; DataOUTEndpoint = NULL; } else { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return CDC_ENUMERROR_NoCompatibleInterfaceFound; } CDCControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t); NotificationEndpoint = NULL; } continue; } USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN) { if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT) NotificationEndpoint = EndpointData; else DataINEndpoint = EndpointData; } else { DataOUTEndpoint = EndpointData; } } CDCInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize); CDCInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress; CDCInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK; CDCInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); CDCInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress; CDCInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK; CDCInterfaceInfo->Config.NotificationPipe.Size = le16_to_cpu(NotificationEndpoint->EndpointSize); CDCInterfaceInfo->Config.NotificationPipe.EndpointAddress = NotificationEndpoint->EndpointAddress; CDCInterfaceInfo->Config.NotificationPipe.Type = EP_TYPE_INTERRUPT; if (!(Pipe_ConfigurePipeTable(&CDCInterfaceInfo->Config.DataINPipe, 1))) return false; if (!(Pipe_ConfigurePipeTable(&CDCInterfaceInfo->Config.DataOUTPipe, 1))) return false; if (!(Pipe_ConfigurePipeTable(&CDCInterfaceInfo->Config.NotificationPipe, 1))) return false; CDCInterfaceInfo->State.ControlInterfaceNumber = CDCControlInterface->InterfaceNumber; CDCInterfaceInfo->State.ControlLineStates.HostToDevice = (CDC_CONTROL_LINE_OUT_RTS | CDC_CONTROL_LINE_OUT_DTR); CDCInterfaceInfo->State.ControlLineStates.DeviceToHost = (CDC_CONTROL_LINE_IN_DCD | CDC_CONTROL_LINE_IN_DSR); CDCInterfaceInfo->State.IsActive = true; return CDC_ENUMERROR_NoError; }