static uint8_t DCOMP_PRNT_NextPRNTInterface(void* CurrentDescriptor) { if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) { if ((DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Class == PRINTER_CLASS) && (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).SubClass == PRINTER_SUBCLASS) && (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Protocol == PRINTER_PROTOCOL)) { return DESCRIPTOR_SEARCH_Found; } } 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 Interface descriptor of the correct Keyboard HID Class and Protocol values. * * \return A value from the DSEARCH_Return_ErrorCodes_t enum */ uint8_t DComp_NextKeyboardInterface(void* CurrentDescriptor) { if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) { /* Check the HID descriptor class and protocol, break out if correct class/protocol interface found */ if ((DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Class == KEYBOARD_CLASS) && (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Protocol == KEYBOARD_PROTOCOL)) { return DESCRIPTOR_SEARCH_Found; } } 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 Interface descriptor of the correct Still Image Class, Subclass and Protocol values. * * \return A value from the DSEARCH_Return_ErrorCodes_t enum */ uint8_t DComp_NextStillImageInterface(void* CurrentDescriptor) { if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) { /* Check the descriptor class and protocol, break out if correct class/protocol interface found */ if ((DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Class == SIMAGE_CLASS) && (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).SubClass == SIMAGE_SUBCLASS) && (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Protocol == SIMAGE_PROTOCOL)) { return DESCRIPTOR_SEARCH_Found; } } 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 Interface descriptor of the correct CDC data Class, Subclass and Protocol values. * * \return A value from the DSEARCH_Return_ErrorCodes_t enum */ uint8_t DComp_NextCDCDataInterface(void* CurrentDescriptor) { if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) { /* Check the CDC descriptor class, subclass and protocol, break out if correct data interface found */ if ((DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Class == CDC_DATA_CLASS) && (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).SubClass == CDC_DATA_SUBCLASS) && (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Protocol == CDC_DATA_PROTOCOL)) { return DESCRIPTOR_SEARCH_Found; } } 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 Interface descriptor of the correct Mouse HID Class and Protocol values. * * \return A value from the DSEARCH_Return_ErrorCodes_t enum */ uint8_t DComp_NextMouseInterface(void* CurrentDescriptor) { /* Determine if the current descriptor is an interface descriptor */ if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) { /* Check the HID descriptor class and protocol, break out if correct class/protocol interface found */ if ((DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Class == MOUSE_CLASS) && (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Protocol == MOUSE_PROTOCOL)) { /* Indicate that the descriptor being searched for has been found */ return DESCRIPTOR_SEARCH_Found; } } /* Current descriptor does not match what this comparator is looking for */ 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 \ref MouseHostWithParser_GetConfigDescriptorDataCodes_t enum. */ uint8_t ProcessConfigurationDescriptor(void) { uint8_t ConfigDescriptorData[512]; void* CurrConfigLocation = ConfigDescriptorData; uint16_t CurrConfigBytesRem; /* 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 mouse interface from the configuration descriptor */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextMouseInterface) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoHIDInterfaceFound; } /* Get the mouse interface's HID descriptor */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextHID) != DESCRIPTOR_SEARCH_COMP_Found) { /* Descriptor not found, error out */ return NoHIDDescriptorFound; } /* Save the HID report size for later use */ HIDReportSize = DESCRIPTOR_CAST(CurrConfigLocation, USB_Descriptor_HID_t).HIDReportLength; /* Get the mouse interface's data endpoint descriptor */ if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, DComp_NextMouseInterfaceDataEndpoint) != 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(CurrConfigLocation, USB_Descriptor_Endpoint_t); /* Configure the mouse data pipe */ Pipe_ConfigurePipe(MOUSE_DATAPIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); /* Valid data found, return success */ return SuccessfulConfigRead; }
/** 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 IN 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_NextInterfaceKeyboardDataEndpoint(void* CurrentDescriptor) { if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint) { if (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Endpoint_t).EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) return DESCRIPTOR_SEARCH_Found; } else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) { return DESCRIPTOR_SEARCH_Fail; } return DESCRIPTOR_SEARCH_NotFound; }
static uint8_t DCOMP_PRNT_NextPRNTInterfaceEndpoint(void* CurrentDescriptor) { if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint) { uint8_t EndpointType = (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Endpoint_t).Attributes & EP_TYPE_MASK); if (EndpointType == EP_TYPE_BULK) 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 IN or OUT endpoint, or interrupt IN endpoint within the current interface, * aborting the search if another interface descriptor is found before the required endpoint (so that it may be compared * using a different comparator to determine if it is another CDC class interface). * * \return A value from the DSEARCH_Return_ErrorCodes_t enum */ uint8_t DComp_NextInterfaceCDCDataEndpoint(void* CurrentDescriptor) { if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint) { uint8_t EndpointType = (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Endpoint_t).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; }
/** 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 of the correct MSD interface, aborting the search if * another interface descriptor is found before the next endpoint. * * \return A value from the DSEARCH_Return_ErrorCodes_t enum */ uint8_t DComp_NextMSInterfaceBulkDataEndpoint(void* CurrentDescriptor) { if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint) { uint8_t EndpointType = (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Endpoint_t).Attributes & EP_TYPE_MASK); /* Check the endpoint type, break out if correct BULK type endpoint found */ if (EndpointType == EP_TYPE_BULK) 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 IN 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_NextMouseInterfaceDataEndpoint(void* CurrentDescriptor) { /* Determine the type of the current descriptor */ if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint) { /* Check if the current Endpoint descriptor is of type IN */ if (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Endpoint_t).EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { /* Indicate that the descriptor being searched for has been found */ return DESCRIPTOR_SEARCH_Found; } } else if (DESCRIPTOR_TYPE(CurrentDescriptor) == 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; }
uint8_t USB_Host_GetDeviceConfigDescriptor(uint8_t ConfigNumber, uint16_t* const ConfigSizePtr, void* BufferPtr, 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 = DESCRIPTOR_CAST(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 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 USB_Host_GetDeviceConfigDescriptor(uint16_t* const ConfigSizePtr, void* BufferPtr) { uint8_t ErrorCode; USB_HostRequest = (USB_Host_Request_Header_t) { bmRequestType: (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE), bRequest: REQ_GetDescriptor, wValue: (DTYPE_Configuration << 8), wIndex: 0, wLength: sizeof(USB_Descriptor_Configuration_Header_t), }; if (BufferPtr == NULL) { BufferPtr = alloca(sizeof(USB_Descriptor_Configuration_Header_t)); ErrorCode = USB_Host_SendControlRequest(BufferPtr); #if defined(USE_NONSTANDARD_DESCRIPTOR_NAMES) *ConfigSizePtr = DESCRIPTOR_CAST(BufferPtr, USB_Descriptor_Configuration_Header_t).TotalConfigurationSize; #else *ConfigSizePtr = DESCRIPTOR_CAST(BufferPtr, USB_Descriptor_Configuration_Header_t).wTotalLength; #endif } else { USB_HostRequest.wLength = *ConfigSizePtr; ErrorCode = USB_Host_SendControlRequest(BufferPtr); } return ErrorCode; } void USB_Host_GetNextDescriptorOfType(uint16_t* const BytesRem, uint8_t** const CurrConfigLoc, const uint8_t Type) { while (*BytesRem) { USB_Host_GetNextDescriptor(BytesRem, CurrConfigLoc); if (DESCRIPTOR_TYPE(*CurrConfigLoc) == Type) return; } } void USB_Host_GetNextDescriptorOfTypeBefore(uint16_t* const BytesRem, uint8_t** const CurrConfigLoc, const uint8_t Type, const uint8_t BeforeType) { while (*BytesRem) { USB_Host_GetNextDescriptor(BytesRem, CurrConfigLoc); if (DESCRIPTOR_TYPE(*CurrConfigLoc) == Type) { return; } else if (DESCRIPTOR_TYPE(*CurrConfigLoc) == BeforeType) { *BytesRem = 0; return; } } } void USB_Host_GetNextDescriptorOfTypeAfter(uint16_t* const BytesRem, uint8_t** const CurrConfigLoc, const uint8_t Type, const uint8_t AfterType) { USB_Host_GetNextDescriptorOfType(BytesRem, CurrConfigLoc, AfterType); if (*BytesRem) USB_Host_GetNextDescriptorOfType(BytesRem, CurrConfigLoc, Type); }
uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint16_t ConfigDescriptorSize, void* ConfigDescriptorData) { uint8_t FoundEndpoints = 0; memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State)); if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) return RNDIS_ENUMERROR_InvalidConfigDescriptor; if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return RNDIS_ENUMERROR_NoRNDISInterfaceFound; } RNDISInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_Interface_t).InterfaceNumber; while (FoundEndpoints != (RNDIS_FOUND_NOTIFICATION_IN | RNDIS_FOUND_DATAPIPE_IN | RNDIS_FOUND_DATAPIPE_OUT)) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { if (FoundEndpoints & RNDIS_FOUND_NOTIFICATION_IN) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_RNDIS_Host_NextRNDISDataInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return RNDIS_ENUMERROR_NoRNDISInterfaceFound; } } else { FoundEndpoints = 0; Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber); Pipe_DisablePipe(); Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber); Pipe_DisablePipe(); Pipe_SelectPipe(RNDISInterfaceInfo->Config.NotificationPipeNumber); Pipe_DisablePipe(); if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) { return RNDIS_ENUMERROR_NoRNDISInterfaceFound; } } if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { return RNDIS_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(RNDISInterfaceInfo->Config.NotificationPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, RNDISInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); RNDISInterfaceInfo->State.NotificationPipeSize = EndpointData->EndpointSize; Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS); FoundEndpoints |= RNDIS_FOUND_NOTIFICATION_IN; } } else { if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, RNDISInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); RNDISInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize; FoundEndpoints |= RNDIS_FOUND_DATAPIPE_IN; } else { Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT, EndpointData->EndpointAddress, EndpointData->EndpointSize, RNDISInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); RNDISInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize; FoundEndpoints |= RNDIS_FOUND_DATAPIPE_OUT; } } } RNDISInterfaceInfo->State.IsActive = true; return RNDIS_ENUMERROR_NoError; }
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; }