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 RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, 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* RNDISControlInterface = NULL; memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State)); if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return RNDIS_ENUMERROR_InvalidConfigDescriptor; RNDISControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t); while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(NotificationEndpoint)) { if (!(RNDISControlInterface) || USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { if (NotificationEndpoint) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_RNDIS_Host_NextRNDISDataInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return RNDIS_ENUMERROR_NoCompatibleInterfaceFound; } DataINEndpoint = NULL; DataOUTEndpoint = NULL; } else { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return RNDIS_ENUMERROR_NoCompatibleInterfaceFound; } RNDISControlInterface = 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; } } 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 == RNDISInterfaceInfo->Config.DataINPipeNumber) { Size = le16_to_cpu(DataINEndpoint->EndpointSize); EndpointAddress = DataINEndpoint->EndpointAddress; Token = PIPE_TOKEN_IN; Type = EP_TYPE_BULK; DoubleBanked = RNDISInterfaceInfo->Config.DataINPipeDoubleBank; InterruptPeriod = 0; RNDISInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; } else if (PipeNum == RNDISInterfaceInfo->Config.DataOUTPipeNumber) { Size = le16_to_cpu(DataOUTEndpoint->EndpointSize); EndpointAddress = DataOUTEndpoint->EndpointAddress; Token = PIPE_TOKEN_OUT; Type = EP_TYPE_BULK; DoubleBanked = RNDISInterfaceInfo->Config.DataOUTPipeDoubleBank; InterruptPeriod = 0; RNDISInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; } else if (PipeNum == RNDISInterfaceInfo->Config.NotificationPipeNumber) { Size = le16_to_cpu(NotificationEndpoint->EndpointSize); EndpointAddress = NotificationEndpoint->EndpointAddress; Token = PIPE_TOKEN_IN; Type = EP_TYPE_INTERRUPT; DoubleBanked = RNDISInterfaceInfo->Config.NotificationPipeDoubleBank; InterruptPeriod = NotificationEndpoint->PollingIntervalMS; RNDISInterfaceInfo->State.NotificationPipeSize = NotificationEndpoint->EndpointSize; } else { continue; } if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size, DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) { return CDC_ENUMERROR_PipeConfigurationFailed; } if (InterruptPeriod) Pipe_SetInterruptPeriod(InterruptPeriod); } RNDISInterfaceInfo->State.ControlInterfaceNumber = RNDISControlInterface->InterfaceNumber; RNDISInterfaceInfo->State.IsActive = true; return RNDIS_ENUMERROR_NoError; }
uint8_t USB_Host_GetDeviceConfigDescriptor(const uint8_t corenum, 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(corenum,PIPE_CONTROLPIPE); if ((ErrorCode = USB_Host_SendControlRequest(corenum,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(corenum,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); }
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; }
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_NextHID) != 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_DESCRIPTOR_DIR_IN) DataINEndpoint = EndpointData; else DataOUTEndpoint = EndpointData; } for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) { if (PipeNum == HIDInterfaceInfo->Config.DataINPipeNumber) { Pipe_ConfigurePipe(PipeNum, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, HIDInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); Pipe_SetInterruptPeriod(DataINEndpoint->PollingIntervalMS); HIDInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; } else if (PipeNum == HIDInterfaceInfo->Config.DataOUTPipeNumber) { Pipe_ConfigurePipe(PipeNum, EP_TYPE_INTERRUPT, PIPE_TOKEN_OUT, DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, HIDInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); Pipe_SetInterruptPeriod(DataOUTEndpoint->PollingIntervalMS); HIDInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; HIDInterfaceInfo->State.DeviceUsesOUTPipe = true; } } HIDInterfaceInfo->State.InterfaceNumber = HIDInterface->InterfaceNumber; HIDInterfaceInfo->State.HIDReportSize = HIDDescriptor->HIDReportLength; HIDInterfaceInfo->State.SupportsBootProtocol = (HIDInterface->SubClass != HID_CSCP_NonBootProtocol); HIDInterfaceInfo->State.LargestReportSize = 8; HIDInterfaceInfo->State.IsActive = true; return HID_ENUMERROR_NoError; }
uint8_t MIDI_Host_ConfigurePipes(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo, uint16_t ConfigDescriptorSize, void* ConfigDescriptorData) { USB_Descriptor_Endpoint_t* DataINEndpoint = NULL; USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL; USB_Descriptor_Interface_t* MIDIInterface = NULL; memset(&MIDIInterfaceInfo->State, 0x00, sizeof(MIDIInterfaceInfo->State)); if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return MIDI_ENUMERROR_InvalidConfigDescriptor; while (!(DataINEndpoint) || !(DataOUTEndpoint)) { if (!(MIDIInterface) || USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_MIDI_Host_NextMIDIStreamingDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_MIDI_Host_NextMIDIStreamingInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return MIDI_ENUMERROR_NoCompatibleInterfaceFound; } MIDIInterface = 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_DESCRIPTOR_DIR_IN) DataINEndpoint = EndpointData; else DataOUTEndpoint = EndpointData; } for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++) { if (PipeNum == MIDIInterfaceInfo->Config.DataINPipeNumber) { Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN, DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, MIDIInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); MIDIInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; } else if (PipeNum == MIDIInterfaceInfo->Config.DataOUTPipeNumber) { Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT, DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, MIDIInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); MIDIInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; } } MIDIInterfaceInfo->State.InterfaceNumber = MIDIInterface->InterfaceNumber; MIDIInterfaceInfo->State.IsActive = true; return MIDI_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; uint8_t portnum = SIInterfaceInfo->Config.PortNumber; 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; } } 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 == SIInterfaceInfo->Config.DataINPipeNumber) { Size = DataINEndpoint->EndpointSize; EndpointAddress = DataINEndpoint->EndpointAddress; Token = PIPE_TOKEN_IN; Type = EP_TYPE_BULK; DoubleBanked = SIInterfaceInfo->Config.DataINPipeDoubleBank; InterruptPeriod = 0; SIInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize; } else if (PipeNum == SIInterfaceInfo->Config.DataOUTPipeNumber) { Size = DataOUTEndpoint->EndpointSize; EndpointAddress = DataOUTEndpoint->EndpointAddress; Token = PIPE_TOKEN_OUT; Type = EP_TYPE_BULK; DoubleBanked = SIInterfaceInfo->Config.DataOUTPipeDoubleBank; InterruptPeriod = 0; SIInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize; } else if (PipeNum == SIInterfaceInfo->Config.EventsPipeNumber) { Size = EventsEndpoint->EndpointSize; EndpointAddress = EventsEndpoint->EndpointAddress; Token = PIPE_TOKEN_IN; Type = EP_TYPE_INTERRUPT; DoubleBanked = SIInterfaceInfo->Config.EventsPipeDoubleBank; InterruptPeriod = EventsEndpoint->PollingIntervalMS; SIInterfaceInfo->State.EventsPipeSize = EventsEndpoint->EndpointSize; } else { continue; } if (!(Pipe_ConfigurePipe(portnum,PipeNum, Type, Token, EndpointAddress, Size, DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE))) { return SI_ENUMERROR_PipeConfigurationFailed; } if (InterruptPeriod) Pipe_SetInterruptPeriod(InterruptPeriod); } SIInterfaceInfo->State.InterfaceNumber = StillImageInterface->InterfaceNumber; SIInterfaceInfo->State.IsActive = true; return SI_ENUMERROR_NoError; }
// Called in ISR context // Called by USBDevice on Endpoint0 request // This is used to handle extensions to standard requests // and class specific requests // Return true if class handles this request bool USBHID::USBCallback_request() { bool success = false; CONTROL_TRANSFER * transfer = getTransferPtr(); uint8_t *hidDescriptor; // Process additional standard requests if ((transfer->setup.bmRequestType.Type == STANDARD_TYPE)) { switch (transfer->setup.bRequest) { case GET_DESCRIPTOR: switch (DESCRIPTOR_TYPE(transfer->setup.wValue)) { case REPORT_DESCRIPTOR: if ((reportDesc() != NULL) \ && (reportDescLength() != 0)) { transfer->remaining = reportDescLength(); transfer->ptr = reportDesc(); transfer->direction = DEVICE_TO_HOST; success = true; } break; case HID_DESCRIPTOR: // Find the HID descriptor, after the configuration descriptor hidDescriptor = findDescriptor(HID_DESCRIPTOR); if (hidDescriptor != NULL) { transfer->remaining = HID_DESCRIPTOR_LENGTH; transfer->ptr = hidDescriptor; transfer->direction = DEVICE_TO_HOST; success = true; } break; default: break; } break; default: break; } } // Process class-specific requests if (transfer->setup.bmRequestType.Type == CLASS_TYPE) { switch (transfer->setup.bRequest) { case SET_REPORT: // First byte will be used for report ID outputReport.data[0] = transfer->setup.wValue & 0xff; outputReport.length = transfer->setup.wLength + 1; transfer->remaining = sizeof(outputReport.data) - 1; transfer->ptr = &outputReport.data[1]; transfer->direction = HOST_TO_DEVICE; transfer->notify = true; success = true; default: break; } } return success; }