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 */
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 */

@ -87,6 +87,9 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Descriptor not found, error out */
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 */

@ -87,6 +87,9 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Descriptor not found, error out */
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 */

@ -83,7 +83,7 @@ uint8_t ProcessConfigurationDescriptor(void)
}
/* 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))
{
@ -108,7 +108,10 @@ uint8_t ProcessConfigurationDescriptor(void)
}
/* 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 */

@ -92,6 +92,9 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Descriptor not found, error out */
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 */

@ -92,6 +92,9 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Descriptor not found, error out */
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 */

@ -87,6 +87,9 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Descriptor not found, error out */
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 */

@ -83,7 +83,7 @@ uint8_t ProcessConfigurationDescriptor(void)
}
/* 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))
{
@ -108,7 +108,10 @@ uint8_t ProcessConfigurationDescriptor(void)
}
/* 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 */

@ -75,8 +75,8 @@ uint8_t ProcessConfigurationDescriptor(void)
}
/* Save Printer interface details for later use */
PrinterInterfaceNumber = DESCRIPTOR_CAST(CurrConfigLocation, USB_Descriptor_Interface_t).InterfaceNumber;
PrinterAltSetting = DESCRIPTOR_CAST(CurrConfigLocation, USB_Descriptor_Interface_t).AlternateSetting;
PrinterInterfaceNumber = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Interface_t)->InterfaceNumber;
PrinterAltSetting = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Interface_t)->AlternateSetting;
while (!(DataINEndpoint) || !(DataOUTEndpoint))
{
@ -97,8 +97,11 @@ uint8_t ProcessConfigurationDescriptor(void)
}
/* Save Printer interface details for later use */
PrinterInterfaceNumber = DESCRIPTOR_CAST(CurrConfigLocation, USB_Descriptor_Interface_t).InterfaceNumber;
PrinterAltSetting = DESCRIPTOR_CAST(CurrConfigLocation, USB_Descriptor_Interface_t).AlternateSetting;
PrinterInterfaceNumber = DESCRIPTOR_PCAST(CurrConfigLocation, USB_Descriptor_Interface_t)->InterfaceNumber;
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 */
@ -106,7 +109,7 @@ uint8_t ProcessConfigurationDescriptor(void)
/* If the endpoint is a IN type endpoint */
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
DataINEndpoint = EndpointData;
DataINEndpoint = EndpointData;
else
DataOUTEndpoint = EndpointData;
}

@ -110,6 +110,9 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Clear any found endpoints */
NotificationEndpoint = NULL;
}
/* Skip the remainder of the loop as we have not found an endpoint yet */
continue;
}
/* Retrieve the endpoint address from the endpoint descriptor */

@ -94,6 +94,9 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Descriptor not found, error out */
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 */

@ -110,6 +110,9 @@ uint8_t ProcessConfigurationDescriptor(void)
/* Clear any found endpoints */
NotificationEndpoint = NULL;
}
/* Skip the remainder of the loop as we have not found an endpoint yet */
continue;
}
/* Retrieve the endpoint address from the endpoint descriptor */

@ -116,6 +116,10 @@
* \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing the
* 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.
*
* \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
* 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.
*
* \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
* 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.
*
* \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
* 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.
*
* \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
* 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.
*
* \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
* 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.
*
* \return Boolean true if the endpoints were successfully configured, false otherwise.

@ -40,103 +40,105 @@ uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo
uint16_t ConfigDescriptorSize,
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));
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;
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,
DCOMP_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{
if (FoundEndpoints & CDC_FOUND_NOTIFICATION_IN)
if (NotificationEndpoint)
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_CDC_Host_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_CDC_Host_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return CDC_ENUMERROR_NoCDCInterfaceFound;
}
return CDC_ENUMERROR_NoCompatibleInterfaceFound;
}
DataINEndpoint = NULL;
DataOUTEndpoint = NULL;
}
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)
DCOMP_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return CDC_ENUMERROR_NoCDCInterfaceFound;
return CDC_ENUMERROR_NoCompatibleInterfaceFound;
}
}
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{
return CDC_ENUMERROR_EndpointsNotFound;
CDCInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_PCAST(ConfigDescriptorData,
USB_Descriptor_Interface_t)->InterfaceNumber;
NotificationEndpoint = NULL;
}
continue;
}
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,
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;
}
if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
NotificationEndpoint = EndpointData;
else
DataINEndpoint = EndpointData;
}
else
{
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
{
Pipe_ConfigurePipe(CDCInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
EndpointData->EndpointAddress, EndpointData->EndpointSize,
CDCInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
DataOUTEndpoint = EndpointData;
}
}
for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
{
if (PipeNum == CDCInterfaceInfo->Config.DataINPipeNumber)
{
Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN,
DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize,
CDCInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
CDCInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
CDCInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
}
else if (PipeNum == CDCInterfaceInfo->Config.DataOUTPipeNumber)
{
Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT,
DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize,
CDCInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
FoundEndpoints |= CDC_FOUND_DATAPIPE_IN;
}
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.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
}
else if (PipeNum == CDCInterfaceInfo->Config.NotificationPipeNumber)
{
Pipe_ConfigurePipe(PipeNum, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
NotificationEndpoint->EndpointAddress, NotificationEndpoint->EndpointSize,
CDCInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
Pipe_SetInterruptPeriod(NotificationEndpoint->PollingIntervalMS);
CDCInterfaceInfo->State.NotificationPipeSize = NotificationEndpoint->EndpointSize;
}
}
CDCInterfaceInfo->State.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;
}

@ -143,8 +143,7 @@
{
CDC_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
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_EndpointsNotFound = 3, /**< Compatible CDC endpoints were not found in the device's CDC interface. */
CDC_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible CDC interface was not found in the device's Configuration Descriptor. */
};
/* 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
* 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] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor.
@ -315,10 +318,6 @@
#define CDC_DATA_CLASS 0x0A
#define CDC_DATA_SUBCLASS 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: */
#if defined(__INCLUDE_FROM_CDC_CLASS_HOST_C)

@ -40,21 +40,22 @@ uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo
uint16_t ConfigDescriptorSize,
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));
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
return HID_ENUMERROR_InvalidConfigDescriptor;
USB_Descriptor_Interface_t* CurrentHIDInterface;
do
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_HID_Host_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return HID_ENUMERROR_NoHIDInterfaceFound;
return HID_ENUMERROR_NoCompatibleInterfaceFound;
}
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);
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,
DCOMP_HID_Host_NextHIDInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{
if (FoundEndpoints & HID_FOUND_DATAPIPE_IN)
if (DataINEndpoint || DataOUTEndpoint)
break;
do
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_HID_Host_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return HID_ENUMERROR_NoCompatibleInterfaceFound;
}
return HID_ENUMERROR_EndpointsNotFound;
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);
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,
EndpointData->EndpointAddress, EndpointData->EndpointSize,
Pipe_ConfigurePipe(PipeNum, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize,
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,
EndpointData->EndpointAddress, EndpointData->EndpointSize,
Pipe_ConfigurePipe(PipeNum, EP_TYPE_INTERRUPT, PIPE_TOKEN_OUT,
DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize,
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;
FoundEndpoints |= HID_FOUND_DATAPIPE_OUT;
}
}
HIDInterfaceInfo->State.LargestReportSize = 8;
HIDInterfaceInfo->State.IsActive = true;
return HID_ENUMERROR_NoError;
}

@ -139,9 +139,7 @@
{
HID_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
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_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. */
HID_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible HID interface was not found in the device's Configuration Descriptor. */
};
/* Function Prototypes: */
@ -151,6 +149,11 @@
* device. This should be called once after the stack has enumerated the attached device, while 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.
* \n\n
*
* \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.
*
@ -291,9 +294,6 @@
#if !defined(__DOXYGEN__)
/* Macros: */
#define HID_INTERFACE_CLASS 0x03
#define HID_FOUND_DATAPIPE_IN (1 << 0)
#define HID_FOUND_DATAPIPE_OUT (1 << 1)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_HID_CLASS_HOST_C)

@ -40,50 +40,72 @@ uint8_t MIDI_Host_ConfigurePipes(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceI
uint16_t ConfigDescriptorSize,
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));
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
return MIDI_ENUMERROR_InvalidConfigDescriptor;
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_MIDI_Host_NextMIDIStreamingInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return MIDI_ENUMERROR_NoStreamingInterfaceFound;
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,
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);
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
DataINEndpoint = EndpointData;
else
DataOUTEndpoint = EndpointData;
}
for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
{
if (PipeNum == MIDIInterfaceInfo->Config.DataINPipeNumber)
{
Pipe_ConfigurePipe(MIDIInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
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->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,
EndpointData->EndpointAddress, EndpointData->EndpointSize,
Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT,
DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize,
MIDIInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
MIDIInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
FoundEndpoints |= MIDI_FOUND_DATAPIPE_OUT;
MIDIInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
}
}
MIDIInterfaceInfo->State.IsActive = true;
return MIDI_ENUMERROR_NoError;
}

@ -89,10 +89,11 @@
*/
struct
{
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
* after \ref MIDI_Host_ConfigurePipes() is called and the Host state machine is in the
* Configured state.
*/
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
* after \ref MIDI_Host_ConfigurePipes() is called and the Host state machine is in the
* 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 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_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_EndpointsNotFound = 3, /**< Compatible MIDI data endpoints were not found in the device's MIDI interface. */
MIDI_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible MIDI interface was not found in the device's Configuration Descriptor. */
};
/* 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
* 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] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor.
@ -184,9 +188,6 @@
#define MIDI_STREAMING_CLASS 0x01
#define MIDI_STREAMING_SUBCLASS 0x03
#define MIDI_STREAMING_PROTOCOL 0x00
#define MIDI_FOUND_DATAPIPE_IN (1 << 0)
#define MIDI_FOUND_DATAPIPE_OUT (1 << 1)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_MIDI_CLASS_HOST_C)

@ -38,58 +38,78 @@
uint8_t MS_Host_ConfigurePipes(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
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));
if (DESCRIPTOR_TYPE(DeviceConfigDescriptor) != DTYPE_Configuration)
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
return MS_ENUMERROR_InvalidConfigDescriptor;
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
DCOMP_MS_NextMSInterface) != DESCRIPTOR_SEARCH_COMP_Found)
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
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;
while (FoundEndpoints != (MS_FOUND_DATAPIPE_IN | MS_FOUND_DATAPIPE_OUT))
MSInterfaceInfo->State.InterfaceNumber = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t)->InterfaceNumber;
while (!(DataINEndpoint) || !(DataOUTEndpoint))
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
DCOMP_MS_NextMSInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
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)
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,
EndpointData->EndpointAddress, EndpointData->EndpointSize,
MSInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
MSInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
FoundEndpoints |= MS_FOUND_DATAPIPE_IN;
Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN,
DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize,
MSInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
MSInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
}
else
else if (PipeNum == MSInterfaceInfo->Config.DataOUTPipeNumber)
{
Pipe_ConfigurePipe(MSInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
EndpointData->EndpointAddress, EndpointData->EndpointSize,
MSInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
MSInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
FoundEndpoints |= MS_FOUND_DATAPIPE_OUT;
}
Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT,
DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize,
MSInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
MSInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
}
}
MSInterfaceInfo->State.IsActive = true;
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)
{
@ -107,7 +127,7 @@ static uint8_t DCOMP_MS_NextMSInterface(void* const CurrentDescriptor)
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)
{

@ -93,11 +93,11 @@
*/
struct
{
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
* after \ref MS_Host_ConfigurePipes() is called and the Host state machine is in the
* Configured state.
*/
uint8_t InterfaceNumber; /**< Interface index of the Mass Storage interface within the attached device. */
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
* after \ref MS_Host_ConfigurePipes() is called and the Host state machine is in the
* Configured state.
*/
uint8_t InterfaceNumber; /**< Interface index of the Mass Storage interface within the attached device. */
uint16_t DataINPipeSize; /**< Size in bytes of the Mass Storage interface's IN data pipe. */
uint16_t DataOUTPipeSize; /**< Size in bytes of the Mass Storage interface's OUT data pipe. */
@ -126,8 +126,7 @@
{
MS_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
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_EndpointsNotFound = 3, /**< Compatible Mass Storage endpoints were not found in the device's interfaces. */
MS_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible Mass Storage interface was not found in the device's Configuration Descriptor. */
};
/* 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
* the host state machine is in the Addressed 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] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor.
* \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] ConfigDescriptorSize Length of 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.
*/
uint8_t MS_Host_ConfigurePipes(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
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
* and readying it for the next Mass Storage command.
@ -320,14 +323,11 @@
#define COMMAND_DIRECTION_DATA_IN (1 << 7)
#define COMMAND_DATA_TIMEOUT_MS 10000
#define MS_FOUND_DATAPIPE_IN (1 << 0)
#define MS_FOUND_DATAPIPE_OUT (1 << 1)
/* Function Prototypes: */
#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_NextMSInterfaceEndpoint(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_Host_NextMSInterfaceEndpoint(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
static uint8_t MS_Host_SendCommand(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
MS_CommandBlockWrapper_t* const SCSICommandBlock,

@ -40,8 +40,9 @@ uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceI
uint16_t ConfigDescriptorSize,
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));
if (DESCRIPTOR_TYPE(DeviceConfigDescriptor) != DTYPE_Configuration)
@ -50,45 +51,66 @@ uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceI
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
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 = PrinterInterface->InterfaceNumber;
PRNTInterfaceInfo->State.AlternateSetting = PrinterInterface->AlternateSetting;
PRNTInterfaceInfo->State.InterfaceNumber = DESCRIPTOR_PCAST(DeviceConfigDescriptor,
USB_Descriptor_Interface_t)->InterfaceNumber;
PRNTInterfaceInfo->State.AlternateSetting = DESCRIPTOR_PCAST(DeviceConfigDescriptor,
USB_Descriptor_Interface_t)->AlternateSetting;
while (FoundEndpoints != (PRNT_FOUND_DATAPIPE_IN | PRNT_FOUND_DATAPIPE_OUT))
while (!(DataINEndpoint) || !(DataOUTEndpoint))
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
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);
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
DataINEndpoint = EndpointData;
else
DataOUTEndpoint = EndpointData;
}
for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
{
if (PipeNum == PRNTInterfaceInfo->Config.DataINPipeNumber)
{
Pipe_ConfigurePipe(PRNTInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
EndpointData->EndpointAddress, EndpointData->EndpointSize,
PRNTInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
PRNTInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
FoundEndpoints |= PRNT_FOUND_DATAPIPE_IN;
Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN,
DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize,
PRNTInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
PRNTInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
}
else
else if (PipeNum == PRNTInterfaceInfo->Config.DataOUTPipeNumber)
{
Pipe_ConfigurePipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
EndpointData->EndpointAddress, EndpointData->EndpointSize,
PRNTInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
PRNTInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
FoundEndpoints |= PRNT_FOUND_DATAPIPE_OUT;
}
Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT,
DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize,
PRNTInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
PRNTInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
}
}
PRNTInterfaceInfo->State.IsActive = true;
return PRNT_ENUMERROR_NoError;
}

@ -109,8 +109,7 @@
{
PRNT_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
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_EndpointsNotFound = 3, /**< Compatible Printer endpoints were not found in the device's interfaces. */
PRNT_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible Printer interface was not found in the device's Configuration Descriptor. */
};
/* 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
* 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] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor.
@ -265,9 +268,6 @@
#define REQ_GetDeviceID 0
#define REQ_GetPortStatus 1
#define REQ_SoftReset 2
#define PRNT_FOUND_DATAPIPE_IN (1 << 0)
#define PRNT_FOUND_DATAPIPE_OUT (1 << 1)
/* Function Prototypes: */
#if defined(__INCLUDE_FROM_PRINTER_CLASS_HOST_C)

@ -40,99 +40,103 @@ uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfa
uint16_t ConfigDescriptorSize,
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));
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;
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,
DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{
if (FoundEndpoints & RNDIS_FOUND_NOTIFICATION_IN)
if (NotificationEndpoint)
{
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_RNDIS_Host_NextRNDISDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_RNDIS_Host_NextRNDISDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return RNDIS_ENUMERROR_NoRNDISInterfaceFound;
}
return RNDIS_ENUMERROR_NoCompatibleInterfaceFound;
}
DataINEndpoint = NULL;
DataOUTEndpoint = NULL;
}
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)
DCOMP_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
return RNDIS_ENUMERROR_NoRNDISInterfaceFound;
return RNDIS_ENUMERROR_NoCompatibleInterfaceFound;
}
}
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
{
return RNDIS_ENUMERROR_EndpointsNotFound;
RNDISInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_PCAST(ConfigDescriptorData,
USB_Descriptor_Interface_t)->InterfaceNumber;
NotificationEndpoint = NULL;
}
continue;
}
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,
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;
}
if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
NotificationEndpoint = EndpointData;
else
DataINEndpoint = EndpointData;
}
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;
DataOUTEndpoint = EndpointData;
}
}
for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
{
if (PipeNum == RNDISInterfaceInfo->Config.DataINPipeNumber)
{
Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN,
DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize,
RNDISInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
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.DataINPipeSize = DataINEndpoint->EndpointSize;
}
else if (PipeNum == RNDISInterfaceInfo->Config.DataOUTPipeNumber)
{
Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT,
DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize,
RNDISInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
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;
return RNDIS_ENUMERROR_NoError;
}

@ -123,8 +123,7 @@
{
RNDIS_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
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_EndpointsNotFound = 3, /**< Compatible RNDIS endpoints were not found in the device's RNDIS interface. */
RNDIS_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible RNDIS interface was not found in the device's Configuration Descriptor. */
};
/* 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
* 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] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor.
@ -262,10 +265,6 @@
#define RNDIS_DATA_CLASS 0x0A
#define RNDIS_DATA_SUBCLASS 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: */
#if defined(__INCLUDE_FROM_RNDIS_CLASS_HOST_C)

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

@ -96,10 +96,11 @@
*/
struct
{
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
* after \ref SI_Host_ConfigurePipes() is called and the Host state machine is in the
* Configured state.
*/
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
* after \ref SI_Host_ConfigurePipes() is called and the Host state machine is in the
* 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 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_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.
*/
SI_ENUMERROR_EndpointsNotFound = 3, /**< Compatible Still Image data endpoints were not found in the
* device's Still Image interface.
*/
};
/* Function Prototypes: */
@ -134,15 +132,19 @@
* 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.
*
* \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] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor.
* \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] ConfigDescriptorSize Length of 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.
*/
uint8_t SI_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
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
* 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_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
/* 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)
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)
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
* - 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
* - 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>
* - 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];
void* CurrConfigLocation = ConfigDescriptorData;
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 */
switch (USB_Host_GetDeviceConfigDescriptor(1, &CurrConfigBytesRem, ConfigDescriptorData, sizeof(ConfigDescriptorData)))
@ -65,50 +67,62 @@ uint8_t ProcessConfigurationDescriptor(void)
return ControlError;
}
/* Get the HID interface from the configuration descriptor */
/* Get the first HID interface from the configuration descriptor */
if (USB_GetNextDescriptorComp(&CurrConfigBytesRem, &CurrConfigLocation,
DComp_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found)
{
/* 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 */
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
* 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;
/* Descriptor not found, error out */
return NoEndpointFound;
/* 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 */
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 */
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 (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
{
/* Configure the HID data IN pipe */
Pipe_ConfigurePipe(HID_DATA_IN_PIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE);
FoundEndpoints |= (1 << HID_DATA_IN_PIPE);
}
DataINEndpoint = EndpointData;
else
{
/* Configure the HID data OUT pipe */
Pipe_ConfigurePipe(HID_DATA_OUT_PIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_OUT,
EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE);
FoundEndpoints |= (1 << HID_DATA_OUT_PIPE);
}
DataOUTEndpoint = EndpointData;
}
/* Configure the HID data IN pipe */
Pipe_ConfigurePipe(HID_DATA_IN_PIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize, PIPE_BANK_SINGLE);
Pipe_SetInterruptPeriod(DataINEndpoint->PollingIntervalMS);
/* Check if the HID interface contained an optional OUT data endpoint */
if (DataOUTEndpoint)
{
/* Configure the HID data OUT pipe */
Pipe_ConfigurePipe(HID_DATA_OUT_PIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_OUT,
DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize, PIPE_BANK_SINGLE);
}
/* Valid data found, return success */
return SuccessfulConfigRead;
@ -148,7 +162,7 @@ uint8_t DComp_NextHIDInterface(void* CurrentDescriptor)
*
* \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 */
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)

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

@ -54,12 +54,6 @@
#include "ConfigDescriptor.h"
/* 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. */
#define REQ_SetReport 0x09

Loading…
Cancel
Save