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_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 bulk 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_NextInterfaceBulkEndpoint(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) && (!(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_NextRNDISInterfaceEndpoint(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)) && !(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress))) { return DESCRIPTOR_SEARCH_Found; } } else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) { return DESCRIPTOR_SEARCH_Fail; } return DESCRIPTOR_SEARCH_NotFound; }
uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, uint16_t ConfigDescriptorSize, void* ConfigDescriptorData) { uint8_t FoundEndpoints = 0; memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State)); if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return CDC_ENUMERROR_InvalidConfigDescriptor; if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return CDC_ENUMERROR_NoCDCInterfaceFound; } CDCInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_Interface_t).InterfaceNumber; while (FoundEndpoints != (CDC_FOUND_NOTIFICATION_IN | CDC_FOUND_DATAPIPE_IN | CDC_FOUND_DATAPIPE_OUT)) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { if (FoundEndpoints & CDC_FOUND_NOTIFICATION_IN) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_CDC_Host_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return CDC_ENUMERROR_NoCDCInterfaceFound; } } else { FoundEndpoints = 0; Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber); Pipe_DisablePipe(); Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipeNumber); Pipe_DisablePipe(); Pipe_SelectPipe(CDCInterfaceInfo->Config.NotificationPipeNumber); Pipe_DisablePipe(); if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return CDC_ENUMERROR_NoCDCInterfaceFound; } } if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { return CDC_ENUMERROR_EndpointsNotFound; } } USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT) { if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { Pipe_ConfigurePipe(CDCInterfaceInfo->Config.NotificationPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, CDCInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); CDCInterfaceInfo->State.NotificationPipeSize = EndpointData->EndpointSize; Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS); FoundEndpoints |= CDC_FOUND_NOTIFICATION_IN; } } else { if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { if (Pipe_IsEndpointBound(EndpointData->EndpointAddress)) { CDCInterfaceInfo->State.BidirectionalDataEndpoints = true; Pipe_DisablePipe(); } Pipe_ConfigurePipe(CDCInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, CDCInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); CDCInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize; FoundEndpoints |= CDC_FOUND_DATAPIPE_IN; } else { if (Pipe_IsEndpointBound(EndpointData->EndpointAddress)) { CDCInterfaceInfo->State.BidirectionalDataEndpoints = true; } else { Pipe_ConfigurePipe(CDCInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT, EndpointData->EndpointAddress, EndpointData->EndpointSize, CDCInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); } CDCInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize; FoundEndpoints |= CDC_FOUND_DATAPIPE_OUT; } } } 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; }
/** 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; 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 CDC control interface from the configuration descriptor */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoCDCInterfaceFound; } /* Get the IN and OUT data and IN notification endpoints for the CDC interface */ while (FoundEndpoints != ((1 << CDC_NOTIFICATIONPIPE) | (1 << CDC_DATAPIPE_IN) | (1 << CDC_DATAPIPE_OUT))) { /* Fetch the next bulk or interrupt endpoint from the current CDC interface */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextCDCDataInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { /* Check to see if the control interface's notification pipe has been found, if so search for the data interface */ if (FoundEndpoints & (1 << CDC_NOTIFICATIONPIPE)) { /* Get the next CDC data interface from the configuration descriptor (CDC class has two CDC interfaces) */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoCDCInterfaceFound; } } else { /* Clear the found endpoints mask, since any already processed endpoints aren't in the CDC interface we need */ FoundEndpoints = 0; /* Disable any already configured pipes from the invalid CDC interfaces */ Pipe_SelectPipe(CDC_NOTIFICATIONPIPE); Pipe_DisablePipe(); Pipe_SelectPipe(CDC_DATAPIPE_IN); Pipe_DisablePipe(); Pipe_SelectPipe(CDC_DATAPIPE_OUT); Pipe_DisablePipe(); /* Get the next CDC control interface from the configuration descriptor (CDC class has two CDC interfaces) */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoCDCInterfaceFound; } } /* Fetch the next bulk or interrupt endpoint from the current CDC interface */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextCDCDataInterfaceEndpoint) != 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 found endpoint is a interrupt or bulk type descriptor */ if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT) { /* If the endpoint is a IN type interrupt endpoint */ if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { /* Configure the notification pipe */ Pipe_ConfigurePipe(CDC_NOTIFICATIONPIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS); /* Set the flag indicating that the notification pipe has been found */ FoundEndpoints |= (1 << CDC_NOTIFICATIONPIPE); } } else { /* Check if the endpoint is a bulk IN or bulk OUT endpoint */ if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { /* Kill the configured OUT pipe if the data endpoints are bidirectional */ if (Pipe_IsEndpointBound(EndpointData->EndpointAddress)) Pipe_DisablePipe(); /* Configure the data IN pipe */ Pipe_ConfigurePipe(CDC_DATAPIPE_IN, EP_TYPE_BULK, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); /* Set the flag indicating that the data IN pipe has been found */ FoundEndpoints |= (1 << CDC_DATAPIPE_IN); } else { /* Only configure the OUT data pipe if the data endpoints haev not shown to be bidirectional */ if (!(Pipe_IsEndpointBound(EndpointData->EndpointAddress))) { /* Configure the data OUT pipe */ Pipe_ConfigurePipe(CDC_DATAPIPE_OUT, EP_TYPE_BULK, PIPE_TOKEN_OUT, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); } /* Set the flag indicating that the data OUT pipe has been found */ FoundEndpoints |= (1 << CDC_DATAPIPE_OUT); } } } /* Valid data found, return success */ return SuccessfulConfigRead; }