Fix low level host mode demos not correctly fetching the next endpoint when an invalid interface is discarded.

Update the pipe configuration routines in the host mode class drivers so that they use the same new code to enumerate compatible devices to increase reliability. Add support to the host mode class drivers for non-sequential (but non-overlapping with other interface) pipe numbers.
pull/1469/head
Dean Camera 14 years ago
parent 158afe9109
commit 7166c7ba3e

@ -96,6 +96,9 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Descriptor not found, error out */ /* Descriptor not found, error out */
return NoCompatibleInterfaceFound; return NoCompatibleInterfaceFound;
} }
/* Skip the remainder of the loop as we have not found an endpoint yet */
continue;
} }
/* Retrieve the endpoint address from the endpoint descriptor */ /* Retrieve the endpoint address from the endpoint descriptor */

@ -87,6 +87,9 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Descriptor not found, error out */ /* Descriptor not found, error out */
return NoCompatibleInterfaceFound; return NoCompatibleInterfaceFound;
} }
/* Skip the remainder of the loop as we have not found an endpoint yet */
continue;
} }
/* Retrieve the endpoint address from the endpoint descriptor */ /* Retrieve the endpoint address from the endpoint descriptor */

@ -87,6 +87,9 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Descriptor not found, error out */ /* Descriptor not found, error out */
return NoCompatibleInterfaceFound; return NoCompatibleInterfaceFound;
} }
/* Skip the remainder of the loop as we have not found an endpoint yet */
continue;
} }
/* Retrieve the endpoint address from the endpoint descriptor */ /* Retrieve the endpoint address from the endpoint descriptor */

@ -83,7 +83,7 @@ uint8_t ProcessConfigurationDescriptor(void)
} }
/* Save the HID report size for later use */ /* Save the HID report size for later use */
HIDReportSize = DESCRIPTOR_CAST(CurrConfigLocation, USB_Descriptor_HID_t).HIDReportLength; HIDReportSize = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_HID_t)->HIDReportLength;
while (!(DataINEndpoint)) while (!(DataINEndpoint))
{ {
@ -108,7 +108,10 @@ uint8_t ProcessConfigurationDescriptor(void)
} }
/* Save the HID report size for later use */ /* Save the HID report size for later use */
HIDReportSize = DESCRIPTOR_CAST(CurrConfigLocation, USB_Descriptor_HID_t).HIDReportLength; HIDReportSize = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_HID_t)->HIDReportLength;
/* Skip the remainder of the loop as we have not found an endpoint yet */
continue;
} }
/* Retrieve the endpoint address from the endpoint descriptor */ /* Retrieve the endpoint address from the endpoint descriptor */

@ -92,6 +92,9 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Descriptor not found, error out */ /* Descriptor not found, error out */
return NoCompatibleInterfaceFound; return NoCompatibleInterfaceFound;
} }
/* Skip the remainder of the loop as we have not found an endpoint yet */
continue;
} }
/* Retrieve the endpoint address from the endpoint descriptor */ /* Retrieve the endpoint address from the endpoint descriptor */

@ -92,6 +92,9 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Descriptor not found, error out */ /* Descriptor not found, error out */
return NoCompatibleInterfaceFound; return NoCompatibleInterfaceFound;
} }
/* Skip the remainder of the loop as we have not found an endpoint yet */
continue;
} }
/* Retrieve the endpoint address from the endpoint descriptor */ /* Retrieve the endpoint address from the endpoint descriptor */

@ -87,6 +87,9 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Descriptor not found, error out */ /* Descriptor not found, error out */
return NoCompatibleInterfaceFound; return NoCompatibleInterfaceFound;
} }
/* Skip the remainder of the loop as we have not found an endpoint yet */
continue;
} }
/* Retrieve the endpoint address from the endpoint descriptor */ /* Retrieve the endpoint address from the endpoint descriptor */

@ -83,7 +83,7 @@ uint8_t ProcessConfigurationDescriptor(void)
} }
/* Save the HID report size for later use */ /* Save the HID report size for later use */
HIDReportSize = DESCRIPTOR_CAST(CurrConfigLocation, USB_Descriptor_HID_t).HIDReportLength; HIDReportSize = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_HID_t)->HIDReportLength;
while (!(DataINEndpoint)) while (!(DataINEndpoint))
{ {
@ -108,7 +108,10 @@ uint8_t ProcessConfigurationDescriptor(void)
} }
/* Save the HID report size for later use */ /* Save the HID report size for later use */
HIDReportSize = DESCRIPTOR_CAST(CurrConfigLocation, USB_Descriptor_HID_t).HIDReportLength; HIDReportSize = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_HID_t)->HIDReportLength;
/* Skip the remainder of the loop as we have not found an endpoint yet */
continue;
} }
/* Retrieve the endpoint address from the endpoint descriptor */ /* Retrieve the endpoint address from the endpoint descriptor */

@ -75,8 +75,8 @@ uint8_t ProcessConfigurationDescriptor(void)
} }
/* Save Printer interface details for later use */ /* Save Printer interface details for later use */
PrinterInterfaceNumber = DESCRIPTOR_CAST(CurrConfigLocation, USB_Descriptor_Interface_t).InterfaceNumber; PrinterInterfaceNumber = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Interface_t)->InterfaceNumber;
PrinterAltSetting = DESCRIPTOR_CAST(CurrConfigLocation, USB_Descriptor_Interface_t).AlternateSetting; PrinterAltSetting = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Interface_t)->AlternateSetting;
while (!(DataINEndpoint) || !(DataOUTEndpoint)) while (!(DataINEndpoint) || !(DataOUTEndpoint))
{ {
@ -97,8 +97,11 @@ uint8_t ProcessConfigurationDescriptor(void)
} }
/* Save Printer interface details for later use */ /* Save Printer interface details for later use */
PrinterInterfaceNumber = DESCRIPTOR_CAST(CurrConfigLocation, USB_Descriptor_Interface_t).InterfaceNumber; PrinterInterfaceNumber = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Interface_t)->InterfaceNumber;
PrinterAltSetting = DESCRIPTOR_CAST(CurrConfigLocation, USB_Descriptor_Interface_t).AlternateSetting; PrinterAltSetting = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Interface_t)->AlternateSetting;
/* Skip the remainder of the loop as we have not found an endpoint yet */
continue;
} }
/* Retrieve the endpoint address from the endpoint descriptor */ /* Retrieve the endpoint address from the endpoint descriptor */

@ -110,6 +110,9 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Clear any found endpoints */ /* Clear any found endpoints */
NotificationEndpoint = NULL; 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 */ /* Retrieve the endpoint address from the endpoint descriptor */

@ -94,6 +94,9 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Descriptor not found, error out */ /* Descriptor not found, error out */
return NoCompatibleInterfaceFound; return NoCompatibleInterfaceFound;
} }
/* Skip the remainder of the loop as we have not found an endpoint yet */
continue;
} }
/* Retrieve the endpoint address from the endpoint descriptor */ /* Retrieve the endpoint address from the endpoint descriptor */

@ -110,6 +110,9 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Clear any found endpoints */ /* Clear any found endpoints */
NotificationEndpoint = NULL; 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 */ /* Retrieve the endpoint address from the endpoint descriptor */

@ -116,6 +116,10 @@
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing the * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing the
* given Audio interface is selected. * given Audio interface is selected.
* *
* \note The endpoint index numbers as given in the interface's configuration structure must not overlap with any other
* interface, or endpoint bank corruption will occur. Gaps in the allocated endpoint numbers or non-sequential indexes
* within a single interface is allowed, but no two interfaces of any type have have interleaved endpoint indexes.
*
* \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state. * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
* *
* \return Boolean true if the endpoints were successfully configured, false otherwise. * \return Boolean true if the endpoints were successfully configured, false otherwise.

@ -151,6 +151,10 @@
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing
* the given CDC interface is selected. * the given CDC interface is selected.
* *
* \note The endpoint index numbers as given in the interface's configuration structure must not overlap with any other
* interface, or endpoint bank corruption will occur. Gaps in the allocated endpoint numbers or non-sequential indexes
* within a single interface is allowed, but no two interfaces of any type have have interleaved endpoint indexes.
*
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state. * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
* *
* \return Boolean true if the endpoints were successfully configured, false otherwise. * \return Boolean true if the endpoints were successfully configured, false otherwise.

@ -128,6 +128,10 @@
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration
* containing the given HID interface is selected. * containing the given HID interface is selected.
* *
* \note The endpoint index numbers as given in the interface's configuration structure must not overlap with any other
* interface, or endpoint bank corruption will occur. Gaps in the allocated endpoint numbers or non-sequential indexes
* within a single interface is allowed, but no two interfaces of any type have have interleaved endpoint indexes.
*
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state. * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state.
* *
* \return Boolean true if the endpoints were successfully configured, false otherwise. * \return Boolean true if the endpoints were successfully configured, false otherwise.

@ -106,6 +106,10 @@
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration
* containing the given MIDI interface is selected. * containing the given MIDI interface is selected.
* *
* \note The endpoint index numbers as given in the interface's configuration structure must not overlap with any other
* interface, or endpoint bank corruption will occur. Gaps in the allocated endpoint numbers or non-sequential indexes
* within a single interface is allowed, but no two interfaces of any type have have interleaved endpoint indexes.
*
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state. * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state.
* *
* \return Boolean true if the endpoints were successfully configured, false otherwise. * \return Boolean true if the endpoints were successfully configured, false otherwise.

@ -116,6 +116,10 @@
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration
* containing the given Mass Storage interface is selected. * containing the given Mass Storage interface is selected.
* *
* \note The endpoint index numbers as given in the interface's configuration structure must not overlap with any other
* interface, or endpoint bank corruption will occur. Gaps in the allocated endpoint numbers or non-sequential indexes
* within a single interface is allowed, but no two interfaces of any type have have interleaved endpoint indexes.
*
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state. * \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state.
* *
* \return Boolean true if the endpoints were successfully configured, false otherwise. * \return Boolean true if the endpoints were successfully configured, false otherwise.

@ -124,6 +124,10 @@
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration
* containing the given HID interface is selected. * containing the given HID interface is selected.
* *
* \note The endpoint index numbers as given in the interface's configuration structure must not overlap with any other
* interface, or endpoint bank corruption will occur. Gaps in the allocated endpoint numbers or non-sequential indexes
* within a single interface is allowed, but no two interfaces of any type have have interleaved endpoint indexes.
*
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing a RNDIS Class configuration and state. * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing a RNDIS Class configuration and state.
* *
* \return Boolean true if the endpoints were successfully configured, false otherwise. * \return Boolean true if the endpoints were successfully configured, false otherwise.

@ -40,7 +40,9 @@ uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo
uint16_t ConfigDescriptorSize, uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData) void* ConfigDescriptorData)
{ {
uint8_t FoundEndpoints = 0; USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
USB_Descriptor_Endpoint_t* NotificationEndpoint = NULL;
memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State)); memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));
@ -50,93 +52,93 @@ uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
return CDC_ENUMERROR_NoCDCInterfaceFound; return CDC_ENUMERROR_NoCompatibleInterfaceFound;
} }
CDCInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_Interface_t).InterfaceNumber; CDCInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_PCAST(ConfigDescriptorData,
USB_Descriptor_Interface_t)->InterfaceNumber;
while (FoundEndpoints != (CDC_FOUND_NOTIFICATION_IN | CDC_FOUND_DATAPIPE_IN | CDC_FOUND_DATAPIPE_OUT)) while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(NotificationEndpoint))
{ {
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
if (FoundEndpoints & CDC_FOUND_NOTIFICATION_IN) if (NotificationEndpoint)
{ {
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_CDC_Host_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_CDC_Host_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
return CDC_ENUMERROR_NoCDCInterfaceFound; return CDC_ENUMERROR_NoCompatibleInterfaceFound;
} }
DataINEndpoint = NULL;
DataOUTEndpoint = NULL;
} }
else 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, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
return CDC_ENUMERROR_NoCDCInterfaceFound; return CDC_ENUMERROR_NoCompatibleInterfaceFound;
}
} }
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, CDCInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_PCAST(ConfigDescriptorData,
DCOMP_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) USB_Descriptor_Interface_t)->InterfaceNumber;
{
return CDC_ENUMERROR_EndpointsNotFound; NotificationEndpoint = NULL;
} }
continue;
} }
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); 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) if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
{ {
Pipe_ConfigurePipe(CDCInterfaceInfo->Config.NotificationPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
EndpointData->EndpointAddress, EndpointData->EndpointSize, NotificationEndpoint = EndpointData;
CDCInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); else
CDCInterfaceInfo->State.NotificationPipeSize = EndpointData->EndpointSize; DataINEndpoint = EndpointData;
Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS);
FoundEndpoints |= CDC_FOUND_NOTIFICATION_IN;
}
} }
else else
{ {
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) DataOUTEndpoint = EndpointData;
}
}
for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
{ {
Pipe_ConfigurePipe(CDCInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN, if (PipeNum == CDCInterfaceInfo->Config.DataINPipeNumber)
EndpointData->EndpointAddress, EndpointData->EndpointSize, {
Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN,
DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize,
CDCInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); CDCInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
CDCInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize; CDCInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
FoundEndpoints |= CDC_FOUND_DATAPIPE_IN;
} }
else else if (PipeNum == CDCInterfaceInfo->Config.DataOUTPipeNumber)
{ {
Pipe_ConfigurePipe(CDCInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT, Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT,
EndpointData->EndpointAddress, EndpointData->EndpointSize, DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize,
CDCInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); CDCInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
CDCInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize; CDCInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
FoundEndpoints |= CDC_FOUND_DATAPIPE_OUT;
} }
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.ControlLineStates.HostToDevice = (CDC_CONTROL_LINE_OUT_RTS | CDC_CONTROL_LINE_OUT_DTR); 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.ControlLineStates.DeviceToHost = (CDC_CONTROL_LINE_IN_DCD | CDC_CONTROL_LINE_IN_DSR);
CDCInterfaceInfo->State.IsActive = true; CDCInterfaceInfo->State.IsActive = true;
return CDC_ENUMERROR_NoError; return CDC_ENUMERROR_NoError;
} }

@ -143,8 +143,7 @@
{ {
CDC_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */ CDC_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
CDC_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */ CDC_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
CDC_ENUMERROR_NoCDCInterfaceFound = 2, /**< A compatible CDC interface was not found in the device's Configuration Descriptor. */ CDC_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible CDC interface was not found in the device's Configuration Descriptor. */
CDC_ENUMERROR_EndpointsNotFound = 3, /**< Compatible CDC endpoints were not found in the device's CDC interface. */
}; };
/* Function Prototypes: */ /* Function Prototypes: */
@ -161,6 +160,10 @@
* This should be called once after the stack has enumerated the attached device, while the host state machine is in * This should be called once after the stack has enumerated the attached device, while the host state machine is in
* the Addressed state. * the Addressed state.
* *
* \note The pipe index numbers as given in the interface's configuration structure must not overlap with any other
* interface, or pipe bank corruption will occur. Gaps in the allocated pipe numbers or non-sequential indexes
* within a single interface is allowed, but no two interfaces of any type have have interleaved pipe indexes.
*
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing an CDC Class host configuration and state. * \param[in,out] CDCInterfaceInfo Pointer to a structure containing an CDC Class host configuration and state.
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor. * \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor. * \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor.
@ -316,10 +319,6 @@
#define CDC_DATA_SUBCLASS 0x00 #define CDC_DATA_SUBCLASS 0x00
#define CDC_DATA_PROTOCOL 0x00 #define CDC_DATA_PROTOCOL 0x00
#define CDC_FOUND_DATAPIPE_IN (1 << 0)
#define CDC_FOUND_DATAPIPE_OUT (1 << 1)
#define CDC_FOUND_NOTIFICATION_IN (1 << 2)
/* Function Prototypes: */ /* Function Prototypes: */
#if defined(__INCLUDE_FROM_CDC_CLASS_HOST_C) #if defined(__INCLUDE_FROM_CDC_CLASS_HOST_C)
static int CDC_Host_putchar(char c, static int CDC_Host_putchar(char c,

@ -40,21 +40,22 @@ uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo
uint16_t ConfigDescriptorSize, uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData) void* ConfigDescriptorData)
{ {
uint8_t FoundEndpoints = 0; USB_Descriptor_Interface_t* CurrentHIDInterface;
USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State)); memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State));
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration) if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
return HID_ENUMERROR_InvalidConfigDescriptor; return HID_ENUMERROR_InvalidConfigDescriptor;
USB_Descriptor_Interface_t* CurrentHIDInterface;
do do
{ {
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_HID_Host_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_HID_Host_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
return HID_ENUMERROR_NoHIDInterfaceFound; return HID_ENUMERROR_NoCompatibleInterfaceFound;
} }
CurrentHIDInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t); CurrentHIDInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
@ -65,47 +66,80 @@ uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo
HIDInterfaceInfo->State.SupportsBootProtocol = (CurrentHIDInterface->SubClass != HID_BOOTP_NonBootProtocol); HIDInterfaceInfo->State.SupportsBootProtocol = (CurrentHIDInterface->SubClass != HID_BOOTP_NonBootProtocol);
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_HID_NextHID) != DESCRIPTOR_SEARCH_COMP_Found) if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_HID_NextHID) != DESCRIPTOR_SEARCH_COMP_Found)
return HID_ENUMERROR_NoHIDDescriptorFound; return HID_ENUMERROR_NoCompatibleInterfaceFound;
HIDInterfaceInfo->State.HIDReportSize = DESCRIPTOR_CAST(ConfigDescriptorData, USB_HID_Descriptor_HID_t).HIDReportLength; HIDInterfaceInfo->State.HIDReportSize = DESCRIPTOR_PCAST(ConfigDescriptorData,
USB_HID_Descriptor_HID_t)->HIDReportLength;
while (FoundEndpoints != (HID_FOUND_DATAPIPE_IN | HID_FOUND_DATAPIPE_OUT)) while (!(DataINEndpoint) || !(DataOUTEndpoint))
{ {
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_HID_Host_NextHIDInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_HID_Host_NextHIDInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
if (FoundEndpoints & HID_FOUND_DATAPIPE_IN) if (DataINEndpoint || DataOUTEndpoint)
break; break;
return HID_ENUMERROR_EndpointsNotFound; do
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_HID_Host_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return HID_ENUMERROR_NoCompatibleInterfaceFound;
}
CurrentHIDInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
} while (HIDInterfaceInfo->Config.HIDInterfaceProtocol &&
(CurrentHIDInterface->Protocol != HIDInterfaceInfo->Config.HIDInterfaceProtocol));
HIDInterfaceInfo->State.InterfaceNumber = CurrentHIDInterface->InterfaceNumber;
HIDInterfaceInfo->State.SupportsBootProtocol = (CurrentHIDInterface->SubClass != HID_BOOTP_NonBootProtocol);
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DCOMP_HID_NextHID) != DESCRIPTOR_SEARCH_COMP_Found)
return HID_ENUMERROR_NoCompatibleInterfaceFound;
HIDInterfaceInfo->State.HIDReportSize = DESCRIPTOR_PCAST(ConfigDescriptorData,
USB_HID_Descriptor_HID_t)->HIDReportLength;
DataINEndpoint = NULL;
DataOUTEndpoint = NULL;
continue;
} }
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) 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(HIDInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, Pipe_ConfigurePipe(PipeNum, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
EndpointData->EndpointAddress, EndpointData->EndpointSize, DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize,
HIDInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); HIDInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
HIDInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize; Pipe_SetInterruptPeriod(DataINEndpoint->PollingIntervalMS);
FoundEndpoints |= HID_FOUND_DATAPIPE_IN; HIDInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
} }
else else if (PipeNum == HIDInterfaceInfo->Config.DataOUTPipeNumber)
{ {
Pipe_ConfigurePipe(HIDInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_OUT, Pipe_ConfigurePipe(PipeNum, EP_TYPE_INTERRUPT, PIPE_TOKEN_OUT,
EndpointData->EndpointAddress, EndpointData->EndpointSize, DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize,
HIDInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); HIDInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
HIDInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize; Pipe_SetInterruptPeriod(DataOUTEndpoint->PollingIntervalMS);
HIDInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
HIDInterfaceInfo->State.DeviceUsesOUTPipe = true; HIDInterfaceInfo->State.DeviceUsesOUTPipe = true;
FoundEndpoints |= HID_FOUND_DATAPIPE_OUT;
} }
} }
HIDInterfaceInfo->State.LargestReportSize = 8; HIDInterfaceInfo->State.LargestReportSize = 8;
HIDInterfaceInfo->State.IsActive = true; HIDInterfaceInfo->State.IsActive = true;
return HID_ENUMERROR_NoError; return HID_ENUMERROR_NoError;
} }

@ -139,9 +139,7 @@
{ {
HID_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */ HID_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
HID_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */ HID_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
HID_ENUMERROR_NoHIDInterfaceFound = 2, /**< A compatible HID interface was not found in the device's Configuration Descriptor. */ HID_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible HID interface was not found in the device's Configuration Descriptor. */
HID_ENUMERROR_NoHIDDescriptorFound = 3, /**< The HID descriptor was not found in the device's HID interface. */
HID_ENUMERROR_EndpointsNotFound = 4, /**< Compatible HID endpoints were not found in the device's HID interface. */
}; };
/* Function Prototypes: */ /* Function Prototypes: */
@ -151,6 +149,11 @@
* device. This should be called once after the stack has enumerated the attached device, while the host state * device. This should be called once after the stack has enumerated the attached device, while the host state
* machine is in the Addressed state. * machine is in the Addressed state.
* *
* \note The pipe index numbers as given in the interface's configuration structure must not overlap with any other
* interface, or pipe bank corruption will occur. Gaps in the allocated pipe numbers or non-sequential indexes
* within a single interface is allowed, but no two interfaces of any type have have interleaved pipe indexes.
* \n\n
*
* \note Once the device pipes are configured, the HID device's reporting protocol <b>must</b> be set via a call * \note Once the device pipes are configured, the HID device's reporting protocol <b>must</b> be set via a call
* to either the \ref HID_Host_SetBootProtocol() or \ref HID_Host_SetReportProtocol() function. * to either the \ref HID_Host_SetBootProtocol() or \ref HID_Host_SetReportProtocol() function.
* *
@ -292,9 +295,6 @@
/* Macros: */ /* Macros: */
#define HID_INTERFACE_CLASS 0x03 #define HID_INTERFACE_CLASS 0x03
#define HID_FOUND_DATAPIPE_IN (1 << 0)
#define HID_FOUND_DATAPIPE_OUT (1 << 1)
/* Function Prototypes: */ /* Function Prototypes: */
#if defined(__INCLUDE_FROM_HID_CLASS_HOST_C) #if defined(__INCLUDE_FROM_HID_CLASS_HOST_C)
static uint8_t DCOMP_HID_Host_NextHIDInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1); static uint8_t DCOMP_HID_Host_NextHIDInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);

@ -40,7 +40,8 @@ uint8_t MIDI_Host_ConfigurePipes(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceI
uint16_t ConfigDescriptorSize, uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData) void* ConfigDescriptorData)
{ {
uint8_t FoundEndpoints = 0; USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
memset(&MIDIInterfaceInfo->State, 0x00, sizeof(MIDIInterfaceInfo->State)); memset(&MIDIInterfaceInfo->State, 0x00, sizeof(MIDIInterfaceInfo->State));
@ -50,40 +51,61 @@ uint8_t MIDI_Host_ConfigurePipes(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceI
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_MIDI_Host_NextMIDIStreamingInterface) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_MIDI_Host_NextMIDIStreamingInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
return MIDI_ENUMERROR_NoStreamingInterfaceFound; return MIDI_ENUMERROR_NoCompatibleInterfaceFound;
} }
while (FoundEndpoints != (MIDI_FOUND_DATAPIPE_IN | MIDI_FOUND_DATAPIPE_OUT)) MIDIInterfaceInfo->State.InterfaceNumber = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t)->InterfaceNumber;
while (!(DataINEndpoint) || !(DataOUTEndpoint))
{ {
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_MIDI_Host_NextMIDIStreamingDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_MIDI_Host_NextMIDIStreamingDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
return MIDI_ENUMERROR_EndpointsNotFound; DataINEndpoint = NULL;
DataOUTEndpoint = NULL;
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_MIDI_Host_NextMIDIStreamingInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return MIDI_ENUMERROR_NoCompatibleInterfaceFound;
}
MIDIInterfaceInfo->State.InterfaceNumber = DESCRIPTOR_PCAST(ConfigDescriptorData,
USB_Descriptor_Interface_t)->InterfaceNumber;
continue;
} }
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
DataINEndpoint = EndpointData;
else
DataOUTEndpoint = EndpointData;
}
for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
{ {
Pipe_ConfigurePipe(MIDIInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN, if (PipeNum == MIDIInterfaceInfo->Config.DataINPipeNumber)
EndpointData->EndpointAddress, EndpointData->EndpointSize, {
Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN,
DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize,
MIDIInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); MIDIInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
MIDIInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
FoundEndpoints |= MIDI_FOUND_DATAPIPE_IN; MIDIInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
} }
else else if (PipeNum == MIDIInterfaceInfo->Config.DataOUTPipeNumber)
{ {
Pipe_ConfigurePipe(MIDIInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT, Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT,
EndpointData->EndpointAddress, EndpointData->EndpointSize, DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize,
MIDIInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); MIDIInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
MIDIInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
FoundEndpoints |= MIDI_FOUND_DATAPIPE_OUT; MIDIInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
} }
} }
MIDIInterfaceInfo->State.IsActive = true; MIDIInterfaceInfo->State.IsActive = true;
return MIDI_ENUMERROR_NoError; return MIDI_ENUMERROR_NoError;
} }

@ -93,6 +93,7 @@
* after \ref MIDI_Host_ConfigurePipes() is called and the Host state machine is in the * after \ref MIDI_Host_ConfigurePipes() is called and the Host state machine is in the
* Configured state. * Configured state.
*/ */
uint8_t InterfaceNumber; /**< Interface index of the MIDI interface within the attached device. */
uint16_t DataINPipeSize; /**< Size in bytes of the MIDI Streaming Data interface's IN data pipe. */ uint16_t DataINPipeSize; /**< Size in bytes of the MIDI Streaming Data interface's IN data pipe. */
uint16_t DataOUTPipeSize; /**< Size in bytes of the MIDI Streaming Data interface's OUT data pipe. */ uint16_t DataOUTPipeSize; /**< Size in bytes of the MIDI Streaming Data interface's OUT data pipe. */
@ -108,8 +109,7 @@
{ {
MIDI_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */ MIDI_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
MIDI_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */ MIDI_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
MIDI_ENUMERROR_NoStreamingInterfaceFound = 2, /**< A compatible MIDI interface was not found in the device's Configuration Descriptor. */ MIDI_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible MIDI interface was not found in the device's Configuration Descriptor. */
MIDI_ENUMERROR_EndpointsNotFound = 3, /**< Compatible MIDI data endpoints were not found in the device's MIDI interface. */
}; };
/* Function Prototypes: */ /* Function Prototypes: */
@ -119,6 +119,10 @@
* This should be called once after the stack has enumerated the attached device, while the host state machine is in * This should be called once after the stack has enumerated the attached device, while the host state machine is in
* the Addressed state. * the Addressed state.
* *
* \note The pipe index numbers as given in the interface's configuration structure must not overlap with any other
* interface, or pipe bank corruption will occur. Gaps in the allocated pipe numbers or non-sequential indexes
* within a single interface is allowed, but no two interfaces of any type have have interleaved pipe indexes.
*
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing an MIDI Class host configuration and state. * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing an MIDI Class host configuration and state.
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor. * \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor. * \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor.
@ -185,9 +189,6 @@
#define MIDI_STREAMING_SUBCLASS 0x03 #define MIDI_STREAMING_SUBCLASS 0x03
#define MIDI_STREAMING_PROTOCOL 0x00 #define MIDI_STREAMING_PROTOCOL 0x00
#define MIDI_FOUND_DATAPIPE_IN (1 << 0)
#define MIDI_FOUND_DATAPIPE_OUT (1 << 1)
/* Function Prototypes: */ /* Function Prototypes: */
#if defined(__INCLUDE_FROM_MIDI_CLASS_HOST_C) #if defined(__INCLUDE_FROM_MIDI_CLASS_HOST_C)
static uint8_t DCOMP_MIDI_Host_NextMIDIStreamingInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1); static uint8_t DCOMP_MIDI_Host_NextMIDIStreamingInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);

@ -38,58 +38,78 @@
uint8_t MS_Host_ConfigurePipes(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, uint8_t MS_Host_ConfigurePipes(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
uint16_t ConfigDescriptorSize, uint16_t ConfigDescriptorSize,
void* DeviceConfigDescriptor) void* ConfigDescriptorData)
{ {
uint8_t FoundEndpoints = 0; USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
memset(&MSInterfaceInfo->State, 0x00, sizeof(MSInterfaceInfo->State)); memset(&MSInterfaceInfo->State, 0x00, sizeof(MSInterfaceInfo->State));
if (DESCRIPTOR_TYPE(DeviceConfigDescriptor) != DTYPE_Configuration) if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
return MS_ENUMERROR_InvalidConfigDescriptor; return MS_ENUMERROR_InvalidConfigDescriptor;
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_MS_NextMSInterface) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_MS_Host_NextMSInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
return MS_ENUMERROR_NoMSInterfaceFound; return MS_ENUMERROR_NoCompatibleInterfaceFound;
} }
MSInterfaceInfo->State.InterfaceNumber = DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Interface_t)->InterfaceNumber; MSInterfaceInfo->State.InterfaceNumber = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t)->InterfaceNumber;
while (FoundEndpoints != (MS_FOUND_DATAPIPE_IN | MS_FOUND_DATAPIPE_OUT)) while (!(DataINEndpoint) || !(DataOUTEndpoint))
{ {
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_MS_NextMSInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_MS_Host_NextMSInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
return MS_ENUMERROR_EndpointsNotFound; DataINEndpoint = NULL;
DataOUTEndpoint = NULL;
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_MS_Host_NextMSInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return MS_ENUMERROR_NoCompatibleInterfaceFound;
}
MSInterfaceInfo->State.InterfaceNumber = DESCRIPTOR_PCAST(ConfigDescriptorData,
USB_Descriptor_Interface_t)->InterfaceNumber;
continue;
} }
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Endpoint_t); USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
DataINEndpoint = EndpointData;
else
DataOUTEndpoint = EndpointData;
}
for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
{
if (PipeNum == MSInterfaceInfo->Config.DataINPipeNumber)
{ {
Pipe_ConfigurePipe(MSInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN, Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN,
EndpointData->EndpointAddress, EndpointData->EndpointSize, DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize,
MSInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); MSInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
MSInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
FoundEndpoints |= MS_FOUND_DATAPIPE_IN; MSInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
} }
else else if (PipeNum == MSInterfaceInfo->Config.DataOUTPipeNumber)
{ {
Pipe_ConfigurePipe(MSInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT, Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT,
EndpointData->EndpointAddress, EndpointData->EndpointSize, DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize,
MSInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); MSInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
MSInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
FoundEndpoints |= MS_FOUND_DATAPIPE_OUT; MSInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
} }
} }
MSInterfaceInfo->State.IsActive = true; MSInterfaceInfo->State.IsActive = true;
return MS_ENUMERROR_NoError; return MS_ENUMERROR_NoError;
} }
static uint8_t DCOMP_MS_NextMSInterface(void* const CurrentDescriptor) static uint8_t DCOMP_MS_Host_NextMSInterface(void* const CurrentDescriptor)
{ {
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface) if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
{ {
@ -107,7 +127,7 @@ static uint8_t DCOMP_MS_NextMSInterface(void* const CurrentDescriptor)
return DESCRIPTOR_SEARCH_NotFound; return DESCRIPTOR_SEARCH_NotFound;
} }
static uint8_t DCOMP_MS_NextMSInterfaceEndpoint(void* const CurrentDescriptor) static uint8_t DCOMP_MS_Host_NextMSInterfaceEndpoint(void* const CurrentDescriptor)
{ {
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint) if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
{ {

@ -126,8 +126,7 @@
{ {
MS_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */ MS_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
MS_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */ MS_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
MS_ENUMERROR_NoMSInterfaceFound = 2, /**< A compatible Mass Storage interface was not found in the device's Configuration Descriptor. */ MS_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible Mass Storage interface was not found in the device's Configuration Descriptor. */
MS_ENUMERROR_EndpointsNotFound = 3, /**< Compatible Mass Storage endpoints were not found in the device's interfaces. */
}; };
/* Function Prototypes: */ /* Function Prototypes: */
@ -137,15 +136,19 @@
* is found within the device. This should be called once after the stack has enumerated the attached device, while * is found within the device. This should be called once after the stack has enumerated the attached device, while
* the host state machine is in the Addressed state. * the host state machine is in the Addressed state.
* *
* \note The pipe index numbers as given in the interface's configuration structure must not overlap with any other
* interface, or pipe bank corruption will occur. Gaps in the allocated pipe numbers or non-sequential indexes
* within a single interface is allowed, but no two interfaces of any type have have interleaved pipe indexes.
*
* \param[in,out] MSInterfaceInfo Pointer to a structure containing an MS Class host configuration and state. * \param[in,out] MSInterfaceInfo Pointer to a structure containing an MS Class host configuration and state.
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor. * \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor. * \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
* *
* \return A value from the \ref MS_Host_EnumerationFailure_ErrorCodes_t enum. * \return A value from the \ref MS_Host_EnumerationFailure_ErrorCodes_t enum.
*/ */
uint8_t MS_Host_ConfigurePipes(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, uint8_t MS_Host_ConfigurePipes(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
uint16_t ConfigDescriptorSize, uint16_t ConfigDescriptorSize,
void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3); void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
/** Sends a MASS STORAGE RESET control request to the attached device, resetting the Mass Storage Interface /** Sends a MASS STORAGE RESET control request to the attached device, resetting the Mass Storage Interface
* and readying it for the next Mass Storage command. * and readying it for the next Mass Storage command.
@ -321,13 +324,10 @@
#define COMMAND_DATA_TIMEOUT_MS 10000 #define COMMAND_DATA_TIMEOUT_MS 10000
#define MS_FOUND_DATAPIPE_IN (1 << 0)
#define MS_FOUND_DATAPIPE_OUT (1 << 1)
/* Function Prototypes: */ /* Function Prototypes: */
#if defined(__INCLUDE_FROM_MS_CLASS_HOST_C) #if defined(__INCLUDE_FROM_MS_CLASS_HOST_C)
static uint8_t DCOMP_MS_NextMSInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1); static uint8_t DCOMP_MS_Host_NextMSInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
static uint8_t DCOMP_MS_NextMSInterfaceEndpoint(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1); static uint8_t DCOMP_MS_Host_NextMSInterfaceEndpoint(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
static uint8_t MS_Host_SendCommand(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, static uint8_t MS_Host_SendCommand(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
MS_CommandBlockWrapper_t* const SCSICommandBlock, MS_CommandBlockWrapper_t* const SCSICommandBlock,

@ -40,7 +40,8 @@ uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceI
uint16_t ConfigDescriptorSize, uint16_t ConfigDescriptorSize,
void* DeviceConfigDescriptor) void* DeviceConfigDescriptor)
{ {
uint8_t FoundEndpoints = 0; USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
memset(&PRNTInterfaceInfo->State, 0x00, sizeof(PRNTInterfaceInfo->State)); memset(&PRNTInterfaceInfo->State, 0x00, sizeof(PRNTInterfaceInfo->State));
@ -50,45 +51,66 @@ uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceI
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
DCOMP_PRNT_NextPRNTInterface) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_PRNT_NextPRNTInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
return PRNT_ENUMERROR_NoPrinterInterfaceFound; return PRNT_ENUMERROR_NoCompatibleInterfaceFound;
} }
USB_Descriptor_Interface_t* PrinterInterface = DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Interface_t); PRNTInterfaceInfo->State.InterfaceNumber = DESCRIPTOR_PCAST(DeviceConfigDescriptor,
USB_Descriptor_Interface_t)->InterfaceNumber;
PRNTInterfaceInfo->State.AlternateSetting = DESCRIPTOR_PCAST(DeviceConfigDescriptor,
USB_Descriptor_Interface_t)->AlternateSetting;
PRNTInterfaceInfo->State.InterfaceNumber = PrinterInterface->InterfaceNumber; while (!(DataINEndpoint) || !(DataOUTEndpoint))
PRNTInterfaceInfo->State.AlternateSetting = PrinterInterface->AlternateSetting;
while (FoundEndpoints != (PRNT_FOUND_DATAPIPE_IN | PRNT_FOUND_DATAPIPE_OUT))
{ {
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
DCOMP_PRNT_NextPRNTInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_PRNT_NextPRNTInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
return PRNT_ENUMERROR_EndpointsNotFound; DataINEndpoint = NULL;
DataOUTEndpoint = NULL;
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
DCOMP_PRNT_NextPRNTInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return PRNT_ENUMERROR_NoCompatibleInterfaceFound;
}
PRNTInterfaceInfo->State.InterfaceNumber = DESCRIPTOR_PCAST(DeviceConfigDescriptor,
USB_Descriptor_Interface_t)->InterfaceNumber;
PRNTInterfaceInfo->State.AlternateSetting = DESCRIPTOR_PCAST(DeviceConfigDescriptor,
USB_Descriptor_Interface_t)->AlternateSetting;
continue;
} }
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Endpoint_t); USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Endpoint_t);
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
DataINEndpoint = EndpointData;
else
DataOUTEndpoint = EndpointData;
}
for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
{ {
Pipe_ConfigurePipe(PRNTInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN, if (PipeNum == PRNTInterfaceInfo->Config.DataINPipeNumber)
EndpointData->EndpointAddress, EndpointData->EndpointSize, {
Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN,
DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize,
PRNTInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); PRNTInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
PRNTInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
FoundEndpoints |= PRNT_FOUND_DATAPIPE_IN; PRNTInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
} }
else else if (PipeNum == PRNTInterfaceInfo->Config.DataOUTPipeNumber)
{ {
Pipe_ConfigurePipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT, Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT,
EndpointData->EndpointAddress, EndpointData->EndpointSize, DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize,
PRNTInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); PRNTInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
PRNTInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
FoundEndpoints |= PRNT_FOUND_DATAPIPE_OUT; PRNTInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
} }
} }
PRNTInterfaceInfo->State.IsActive = true; PRNTInterfaceInfo->State.IsActive = true;
return PRNT_ENUMERROR_NoError; return PRNT_ENUMERROR_NoError;
} }

@ -109,8 +109,7 @@
{ {
PRNT_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */ PRNT_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
PRNT_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */ PRNT_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
PRNT_ENUMERROR_NoPrinterInterfaceFound = 2, /**< A compatible Printer interface was not found in the device's Configuration Descriptor. */ PRNT_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible Printer interface was not found in the device's Configuration Descriptor. */
PRNT_ENUMERROR_EndpointsNotFound = 3, /**< Compatible Printer endpoints were not found in the device's interfaces. */
}; };
/* Function Prototypes: */ /* Function Prototypes: */
@ -128,6 +127,10 @@
* the device. This should be called once after the stack has enumerated the attached device, while the host state * the device. This should be called once after the stack has enumerated the attached device, while the host state
* machine is in the Addressed state. * machine is in the Addressed state.
* *
* \note The pipe index numbers as given in the interface's configuration structure must not overlap with any other
* interface, or pipe bank corruption will occur. Gaps in the allocated pipe numbers or non-sequential indexes
* within a single interface is allowed, but no two interfaces of any type have have interleaved pipe indexes.
*
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state. * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor. * \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor. * \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor.
@ -266,9 +269,6 @@
#define REQ_GetPortStatus 1 #define REQ_GetPortStatus 1
#define REQ_SoftReset 2 #define REQ_SoftReset 2
#define PRNT_FOUND_DATAPIPE_IN (1 << 0)
#define PRNT_FOUND_DATAPIPE_OUT (1 << 1)
/* Function Prototypes: */ /* Function Prototypes: */
#if defined(__INCLUDE_FROM_PRINTER_CLASS_HOST_C) #if defined(__INCLUDE_FROM_PRINTER_CLASS_HOST_C)
static uint8_t DCOMP_PRNT_NextPRNTInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1); static uint8_t DCOMP_PRNT_NextPRNTInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);

@ -40,7 +40,9 @@ uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfa
uint16_t ConfigDescriptorSize, uint16_t ConfigDescriptorSize,
void* ConfigDescriptorData) void* ConfigDescriptorData)
{ {
uint8_t FoundEndpoints = 0; USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
USB_Descriptor_Endpoint_t* NotificationEndpoint = NULL;
memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State)); memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
@ -50,89 +52,91 @@ uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfa
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
return RNDIS_ENUMERROR_NoRNDISInterfaceFound; return RNDIS_ENUMERROR_NoCompatibleInterfaceFound;
} }
RNDISInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_Interface_t).InterfaceNumber; RNDISInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_PCAST(ConfigDescriptorData,
USB_Descriptor_Interface_t)->InterfaceNumber;
while (FoundEndpoints != (RNDIS_FOUND_NOTIFICATION_IN | RNDIS_FOUND_DATAPIPE_IN | RNDIS_FOUND_DATAPIPE_OUT)) while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(NotificationEndpoint))
{ {
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
if (FoundEndpoints & RNDIS_FOUND_NOTIFICATION_IN) if (NotificationEndpoint)
{ {
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_RNDIS_Host_NextRNDISDataInterface) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_RNDIS_Host_NextRNDISDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
return RNDIS_ENUMERROR_NoRNDISInterfaceFound; return RNDIS_ENUMERROR_NoCompatibleInterfaceFound;
} }
DataINEndpoint = NULL;
DataOUTEndpoint = NULL;
} }
else 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, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
return RNDIS_ENUMERROR_NoRNDISInterfaceFound; return RNDIS_ENUMERROR_NoCompatibleInterfaceFound;
}
} }
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, RNDISInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_PCAST(ConfigDescriptorData,
DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) USB_Descriptor_Interface_t)->InterfaceNumber;
{
return RNDIS_ENUMERROR_EndpointsNotFound; NotificationEndpoint = NULL;
} }
continue;
} }
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); 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) if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
{ {
Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.NotificationPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
EndpointData->EndpointAddress, EndpointData->EndpointSize, NotificationEndpoint = EndpointData;
RNDISInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); else
RNDISInterfaceInfo->State.NotificationPipeSize = EndpointData->EndpointSize; DataINEndpoint = EndpointData;
Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS);
FoundEndpoints |= RNDIS_FOUND_NOTIFICATION_IN;
}
} }
else else
{ {
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) DataOUTEndpoint = EndpointData;
}
}
for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
{
if (PipeNum == RNDISInterfaceInfo->Config.DataINPipeNumber)
{ {
Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN, Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN,
EndpointData->EndpointAddress, EndpointData->EndpointSize, DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize,
RNDISInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); RNDISInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
RNDISInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
FoundEndpoints |= RNDIS_FOUND_DATAPIPE_IN; RNDISInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
} }
else else if (PipeNum == RNDISInterfaceInfo->Config.DataOUTPipeNumber)
{ {
Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT, Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT,
EndpointData->EndpointAddress, EndpointData->EndpointSize, DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize,
RNDISInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); RNDISInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
RNDISInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
FoundEndpoints |= RNDIS_FOUND_DATAPIPE_OUT; RNDISInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
} }
else if (PipeNum == RNDISInterfaceInfo->Config.NotificationPipeNumber)
{
Pipe_ConfigurePipe(PipeNum, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
NotificationEndpoint->EndpointAddress, NotificationEndpoint->EndpointSize,
RNDISInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
Pipe_SetInterruptPeriod(NotificationEndpoint->PollingIntervalMS);
RNDISInterfaceInfo->State.NotificationPipeSize = NotificationEndpoint->EndpointSize;
} }
} }
RNDISInterfaceInfo->State.IsActive = true; RNDISInterfaceInfo->State.IsActive = true;
return RNDIS_ENUMERROR_NoError; return RNDIS_ENUMERROR_NoError;
} }

@ -123,8 +123,7 @@
{ {
RNDIS_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */ RNDIS_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
RNDIS_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */ RNDIS_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
RNDIS_ENUMERROR_NoRNDISInterfaceFound = 2, /**< A compatible RNDIS interface was not found in the device's Configuration Descriptor. */ RNDIS_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible RNDIS interface was not found in the device's Configuration Descriptor. */
RNDIS_ENUMERROR_EndpointsNotFound = 3, /**< Compatible RNDIS endpoints were not found in the device's RNDIS interface. */
}; };
/* Macros: */ /* Macros: */
@ -138,6 +137,10 @@
* This should be called once after the stack has enumerated the attached device, while the host state machine is in * This should be called once after the stack has enumerated the attached device, while the host state machine is in
* the Addressed state. * the Addressed state.
* *
* \note The pipe index numbers as given in the interface's configuration structure must not overlap with any other
* interface, or pipe bank corruption will occur. Gaps in the allocated pipe numbers or non-sequential indexes
* within a single interface is allowed, but no two interfaces of any type have have interleaved pipe indexes.
*
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state. * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor. * \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor. * \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor.
@ -263,10 +266,6 @@
#define RNDIS_DATA_SUBCLASS 0x00 #define RNDIS_DATA_SUBCLASS 0x00
#define RNDIS_DATA_PROTOCOL 0x00 #define RNDIS_DATA_PROTOCOL 0x00
#define RNDIS_FOUND_DATAPIPE_IN (1 << 0)
#define RNDIS_FOUND_DATAPIPE_OUT (1 << 1)
#define RNDIS_FOUND_NOTIFICATION_IN (1 << 2)
/* Function Prototypes: */ /* Function Prototypes: */
#if defined(__INCLUDE_FROM_RNDIS_CLASS_HOST_C) #if defined(__INCLUDE_FROM_RNDIS_CLASS_HOST_C)
static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,

@ -38,65 +38,88 @@
uint8_t SI_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, uint8_t SI_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
uint16_t ConfigDescriptorSize, uint16_t ConfigDescriptorSize,
void* DeviceConfigDescriptor) void* ConfigDescriptorData)
{ {
uint8_t FoundEndpoints = 0; USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
USB_Descriptor_Endpoint_t* EventsEndpoint = NULL;
memset(&SIInterfaceInfo->State, 0x00, sizeof(SIInterfaceInfo->State)); memset(&SIInterfaceInfo->State, 0x00, sizeof(SIInterfaceInfo->State));
if (DESCRIPTOR_TYPE(DeviceConfigDescriptor) != DTYPE_Configuration) if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
return SI_ENUMERROR_InvalidConfigDescriptor; return SI_ENUMERROR_InvalidConfigDescriptor;
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_SI_Host_NextSIInterface) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_SI_Host_NextSIInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
return SI_ENUMERROR_NoSIInterfaceFound; return SI_ENUMERROR_NoCompatibleInterfaceFound;
} }
while (FoundEndpoints != (SI_FOUND_EVENTS_IN | SI_FOUND_DATAPIPE_IN | SI_FOUND_DATAPIPE_OUT)) SIInterfaceInfo->State.InterfaceNumber = DESCRIPTOR_PCAST(ConfigDescriptorData,
USB_Descriptor_Interface_t)->InterfaceNumber;
while (!(DataINEndpoint) || !(DataOUTEndpoint))
{ {
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor, if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_SI_Host_NextSIInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) DCOMP_SI_Host_NextSIInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
return SI_ENUMERROR_EndpointsNotFound; DataINEndpoint = NULL;
} DataOUTEndpoint = NULL;
EventsEndpoint = NULL;
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Endpoint_t);
if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT) if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
{ DCOMP_SI_Host_NextSIInterface) != DESCRIPTOR_SEARCH_COMP_Found)
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
{ {
Pipe_ConfigurePipe(SIInterfaceInfo->Config.EventsPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, return SI_ENUMERROR_NoCompatibleInterfaceFound;
EndpointData->EndpointAddress, EndpointData->EndpointSize, }
SIInterfaceInfo->Config.EventsPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
SIInterfaceInfo->State.EventsPipeSize = EndpointData->EndpointSize;
Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS); SIInterfaceInfo->State.InterfaceNumber = DESCRIPTOR_PCAST(ConfigDescriptorData,
USB_Descriptor_Interface_t)->InterfaceNumber;
FoundEndpoints |= SI_FOUND_EVENTS_IN; 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 else
{ {
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) DataOUTEndpoint = EndpointData;
}
}
for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
{
if (PipeNum == SIInterfaceInfo->Config.DataINPipeNumber)
{ {
Pipe_ConfigurePipe(SIInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN, Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN,
EndpointData->EndpointAddress, EndpointData->EndpointSize, DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize,
SIInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); SIInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
SIInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
FoundEndpoints |= SI_FOUND_DATAPIPE_IN; SIInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
} }
else else if (PipeNum == SIInterfaceInfo->Config.DataOUTPipeNumber)
{ {
Pipe_ConfigurePipe(SIInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT, Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT,
EndpointData->EndpointAddress, EndpointData->EndpointSize, DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize,
SIInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE); SIInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
SIInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
FoundEndpoints |= SI_FOUND_DATAPIPE_OUT; 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;
} }
} }

@ -100,6 +100,7 @@
* after \ref SI_Host_ConfigurePipes() is called and the Host state machine is in the * after \ref SI_Host_ConfigurePipes() is called and the Host state machine is in the
* Configured state. * Configured state.
*/ */
uint8_t InterfaceNumber; /**< Interface index of the Mass Storage interface within the attached device. */
uint16_t DataINPipeSize; /**< Size in bytes of the Still Image interface's IN data pipe. */ uint16_t DataINPipeSize; /**< Size in bytes of the Still Image interface's IN data pipe. */
uint16_t DataOUTPipeSize; /**< Size in bytes of the Still Image interface's OUT data pipe. */ uint16_t DataOUTPipeSize; /**< Size in bytes of the Still Image interface's OUT data pipe. */
@ -119,12 +120,9 @@
{ {
SI_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */ SI_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
SI_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */ SI_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
SI_ENUMERROR_NoSIInterfaceFound = 2, /**< A compatible Still Image interface was not found in the device's SI_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible Still Image interface was not found in the device's
* Configuration Descriptor. * Configuration Descriptor.
*/ */
SI_ENUMERROR_EndpointsNotFound = 3, /**< Compatible Still Image data endpoints were not found in the
* device's Still Image interface.
*/
}; };
/* Function Prototypes: */ /* Function Prototypes: */
@ -134,15 +132,19 @@
* found within the device. This should be called once after the stack has enumerated the attached device, while * found within the device. This should be called once after the stack has enumerated the attached device, while
* the host state machine is in the Addressed state. * the host state machine is in the Addressed state.
* *
* \note The pipe index numbers as given in the interface's configuration structure must not overlap with any other
* interface, or pipe bank corruption will occur. Gaps in the allocated pipe numbers or non-sequential indexes
* within a single interface is allowed, but no two interfaces of any type have have interleaved pipe indexes.
*
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state. * \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor. * \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor. * \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
* *
* \return A value from the \ref SI_Host_EnumerationFailure_ErrorCodes_t enum. * \return A value from the \ref SI_Host_EnumerationFailure_ErrorCodes_t enum.
*/ */
uint8_t SI_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, uint8_t SI_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
uint16_t ConfigDescriptorSize, uint16_t ConfigDescriptorSize,
void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3); void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
/** Opens a new PIMA session with the attached device. This should be used before any session-orientated PIMA commands /** Opens a new PIMA session with the attached device. This should be used before any session-orientated PIMA commands
* are issued to the device. Only one session can be open at the one time. * are issued to the device. Only one session can be open at the one time.
@ -309,10 +311,6 @@
#define STILL_IMAGE_SUBCLASS 0x01 #define STILL_IMAGE_SUBCLASS 0x01
#define STILL_IMAGE_PROTOCOL 0x01 #define STILL_IMAGE_PROTOCOL 0x01
#define SI_FOUND_EVENTS_IN (1 << 0)
#define SI_FOUND_DATAPIPE_IN (1 << 1)
#define SI_FOUND_DATAPIPE_OUT (1 << 2)
#define COMMAND_DATA_TIMEOUT_MS 10000 #define COMMAND_DATA_TIMEOUT_MS 10000
/* Function Prototypes: */ /* Function Prototypes: */

@ -52,7 +52,7 @@ uint8_t USB_Host_GetDeviceConfigDescriptor(uint8_t ConfigNumber, uint16_t* const
if ((ErrorCode = USB_Host_SendControlRequest(ConfigHeader)) != HOST_SENDCONTROL_Successful) if ((ErrorCode = USB_Host_SendControlRequest(ConfigHeader)) != HOST_SENDCONTROL_Successful)
return ErrorCode; return ErrorCode;
*ConfigSizePtr = DESCRIPTOR_CAST(ConfigHeader, USB_Descriptor_Configuration_Header_t).TotalConfigurationSize; *ConfigSizePtr = DESCRIPTOR_PCAST(ConfigHeader, USB_Descriptor_Configuration_Header_t)->TotalConfigurationSize;
if (*ConfigSizePtr > BufferSize) if (*ConfigSizePtr > BufferSize)
return HOST_GETCONFIG_BuffOverflow; return HOST_GETCONFIG_BuffOverflow;

@ -45,7 +45,7 @@
* - Removed the EVENT_USB_InitFailure() event, not specifying a USB mode now defaults to UID selection mode * - Removed the EVENT_USB_InitFailure() event, not specifying a USB mode now defaults to UID selection mode
* - Renamed and moved class driver common constant definitions to make the naming scheme more uniform * - Renamed and moved class driver common constant definitions to make the naming scheme more uniform
* - Changed default value for the reset polarity parameter in the AVRISP-MKII project so that it defaults to active low drive * - Changed default value for the reset polarity parameter in the AVRISP-MKII project so that it defaults to active low drive
* - Rewritten configuration descriptor parser for all host mode projects and class drivers to ensure better compatibility * - Changed configuration descriptor parser for all host mode projects and class drivers to ensure better compatibility with devices
* *
* <b>Fixed:</b> * <b>Fixed:</b>
* - Fixed USB_GetHIDReportItemInfo() function modifying the given report item's data when the report item does not exist * - Fixed USB_GetHIDReportItemInfo() function modifying the given report item's data when the report item does not exist

@ -50,7 +50,9 @@ uint8_t ProcessConfigurationDescriptor(void)
uint8_t ConfigDescriptorData[512]; uint8_t ConfigDescriptorData[512];
void* CurrConfigLocation = ConfigDescriptorData; void* CurrConfigLocation = ConfigDescriptorData;
uint16_t CurrConfigBytesRem; uint16_t CurrConfigBytesRem;
uint8_t FoundEndpoints = 0;
USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
/* Retrieve the entire configuration descriptor into the allocated buffer */ /* Retrieve the entire configuration descriptor into the allocated buffer */
switch (USB_Host_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData))) switch (USB_Host_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData)))
@ -65,49 +67,61 @@ uint8_t ProcessConfigurationDescriptor(void)
return ControlError; return ControlError;
} }
/* Get the HID interface from the configuration descriptor */ /* Get the first HID interface from the configuration descriptor */
if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
DComp_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found) DComp_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
/* Descriptor not found, error out */ /* Descriptor not found, error out */
return NoHIDInterfaceFound; return NoCompatibleInterfaceFound;
} }
while (FoundEndpoints != ((1 << HID_DATA_IN_PIPE) | (1 << HID_DATA_OUT_PIPE))) while (!(DataINEndpoint) || !(DataOUTEndpoint))
{ {
/* Get the next HID interface's data endpoint descriptor */ /* Get the next HID interface's data endpoint descriptor */
if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation, if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
DComp_NextInterfaceHIDDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) DComp_NextHIDInterfaceDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{ {
/* Not all HID devices have an OUT endpoint - if we've reached the end of the HID descriptor /* 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 */ * but only found the mandatory IN endpoint, it's safe to continue with the device enumeration */
if (FoundEndpoints == (1 << HID_DATA_IN_PIPE)) if (DataINEndpoint)
break; break;
/* Clear any found endpoints */
DataOUTEndpoint = NULL;
/* 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 */ /* Descriptor not found, error out */
return NoEndpointFound; return NoCompatibleInterfaceFound;
}
/* Skip the remainder of the loop as we have not found an endpoint yet */
continue;
} }
/* Retrieve the endpoint address from the endpoint descriptor */ /* Retrieve the endpoint address from the endpoint descriptor */
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t); USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Endpoint_t);
/* If the endpoint is a IN type endpoint */ /* If the endpoint is a IN type endpoint */
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
{ DataINEndpoint = EndpointData;
else
DataOUTEndpoint = EndpointData;
}
/* Configure the HID data IN pipe */ /* Configure the HID data IN pipe */
Pipe_ConfigurePipe(HID_DATA_IN_PIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, Pipe_ConfigurePipe(HID_DATA_IN_PIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, PIPE_BANK_SINGLE);
Pipe_SetInterruptPeriod(DataINEndpoint->PollingIntervalMS);
FoundEndpoints |= (1 << HID_DATA_IN_PIPE); /* Check if the HID interface contained an optional OUT data endpoint */
} if (DataOUTEndpoint)
else
{ {
/* Configure the HID data OUT pipe */ /* Configure the HID data OUT pipe */
Pipe_ConfigurePipe(HID_DATA_OUT_PIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_OUT, Pipe_ConfigurePipe(HID_DATA_OUT_PIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_OUT,
EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, PIPE_BANK_SINGLE);
FoundEndpoints |= (1 << HID_DATA_OUT_PIPE);
}
} }
/* Valid data found, return success */ /* Valid data found, return success */
@ -148,7 +162,7 @@ uint8_t DComp_NextHIDInterface(void* CurrentDescriptor)
* *
* \return A value from the DSEARCH_Return_ErrorCodes_t enum * \return A value from the DSEARCH_Return_ErrorCodes_t enum
*/ */
uint8_t DComp_NextInterfaceHIDDataEndpoint(void* CurrentDescriptor) uint8_t DComp_NextHIDInterfaceDataEndpoint(void* CurrentDescriptor)
{ {
/* Determine the type of the current descriptor */ /* Determine the type of the current descriptor */
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint) if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)

@ -45,6 +45,12 @@
/** Interface Class value for the Human Interface Device class. */ /** Interface Class value for the Human Interface Device class. */
#define HID_CLASS 0x03 #define HID_CLASS 0x03
/** Pipe number for the HID data IN pipe. */
#define HID_DATA_IN_PIPE 1
/** Pipe number for the HID data OUT pipe. */
#define HID_DATA_OUT_PIPE 2
/* Enums: */ /* Enums: */
/** Enum for the possible return codes of the \ref ProcessConfigurationDescriptor() function. */ /** Enum for the possible return codes of the \ref ProcessConfigurationDescriptor() function. */
enum GenericHIDHost_GetConfigDescriptorDataCodes_t enum GenericHIDHost_GetConfigDescriptorDataCodes_t
@ -53,14 +59,13 @@
ControlError = 1, /**< A control request to the device failed to complete successfully */ ControlError = 1, /**< A control request to the device failed to complete successfully */
DescriptorTooLarge = 2, /**< The device's Configuration Descriptor is too large to process */ DescriptorTooLarge = 2, /**< The device's Configuration Descriptor is too large to process */
InvalidConfigDataReturned = 3, /**< The device returned an invalid Configuration Descriptor */ InvalidConfigDataReturned = 3, /**< The device returned an invalid Configuration Descriptor */
NoHIDInterfaceFound = 4, /**< A compatible HID interface was not found in the device's Configuration Descriptor */ NoCompatibleInterfaceFound = 4, /**< A compatible interface with the required endpoints was not found */
NoEndpointFound = 5, /**< A compatible HID IN endpoint was not found in the device's HID interface */
}; };
/* Function Prototypes: */ /* Function Prototypes: */
uint8_t ProcessConfigurationDescriptor(void); uint8_t ProcessConfigurationDescriptor(void);
uint8_t DComp_NextHIDInterface(void* CurrentDescriptor); uint8_t DComp_NextHIDInterface(void* CurrentDescriptor);
uint8_t DComp_NextInterfaceHIDDataEndpoint(void* CurrentDescriptor); uint8_t DComp_NextHIDInterfaceDataEndpoint(void* CurrentDescriptor);
#endif #endif

@ -54,12 +54,6 @@
#include "ConfigDescriptor.h" #include "ConfigDescriptor.h"
/* Macros: */ /* Macros: */
/** Pipe number for the HID data IN pipe. */
#define HID_DATA_IN_PIPE 1
/** Pipe number for the HID data OUT pipe. */
#define HID_DATA_OUT_PIPE 2
/** HID Class specific request to send a HID report to the device. */ /** HID Class specific request to send a HID report to the device. */
#define REQ_SetReport 0x09 #define REQ_SetReport 0x09

Loading…
Cancel
Save