aboutsummaryrefslogtreecommitdiffstats
path: root/LUFA/Drivers
diff options
context:
space:
mode:
authorDean Camera <dean@fourwalledcubicle.com>2009-11-26 04:46:31 +0000
committerDean Camera <dean@fourwalledcubicle.com>2009-11-26 04:46:31 +0000
commit5aa2b26261389cfbdfae8e793be4b8150ddc7a0a (patch)
tree98cd416fe1b9407956892a22e5b01b3018ccbb09 /LUFA/Drivers
parentf37d21bbe961a72e4d6527767aacf843e3af412c (diff)
downloadlufa-5aa2b26261389cfbdfae8e793be4b8150ddc7a0a.tar.gz
lufa-5aa2b26261389cfbdfae8e793be4b8150ddc7a0a.tar.bz2
lufa-5aa2b26261389cfbdfae8e793be4b8150ddc7a0a.zip
Added new RNDIS Host class driver and the beginnings of a RNDISEthernetHost Class Driver demo.
Fixed all Class drivers to ensure they have appropriate guards on each function to ensure the device is enumerated before running, fixed error codes on all guards to return "DeviceDisconnected" where possble. Renamed HOST_SENDCONTROL_DeviceDisconnect enum value to HOST_SENDCONTROL_DeviceDisconnected to be in line with the rest of the library enum error codes.
Diffstat (limited to 'LUFA/Drivers')
-rw-r--r--LUFA/Drivers/USB/Class/Common/RNDIS.h3
-rw-r--r--LUFA/Drivers/USB/Class/Common/RNDISConstants.h (renamed from LUFA/Drivers/USB/Class/Device/RNDISConstants.h)13
-rw-r--r--LUFA/Drivers/USB/Class/Device/CDC.c6
-rw-r--r--LUFA/Drivers/USB/Class/Device/MIDI.c2
-rw-r--r--LUFA/Drivers/USB/Class/Host/CDC.c8
-rw-r--r--LUFA/Drivers/USB/Class/Host/CDC.h2
-rw-r--r--LUFA/Drivers/USB/Class/Host/HID.c8
-rw-r--r--LUFA/Drivers/USB/Class/Host/MIDI.c4
-rw-r--r--LUFA/Drivers/USB/Class/Host/MassStorage.c20
-rw-r--r--LUFA/Drivers/USB/Class/Host/Printer.c3
-rw-r--r--LUFA/Drivers/USB/Class/Host/RNDIS.c446
-rw-r--r--LUFA/Drivers/USB/Class/Host/RNDIS.h248
-rw-r--r--LUFA/Drivers/USB/Class/Host/StillImage.c27
-rw-r--r--LUFA/Drivers/USB/Class/RNDIS.h9
-rw-r--r--LUFA/Drivers/USB/LowLevel/HostChapter9.h10
-rw-r--r--LUFA/Drivers/USB/USB.h4
16 files changed, 769 insertions, 44 deletions
diff --git a/LUFA/Drivers/USB/Class/Common/RNDIS.h b/LUFA/Drivers/USB/Class/Common/RNDIS.h
index b2566d300..85aced548 100644
--- a/LUFA/Drivers/USB/Class/Common/RNDIS.h
+++ b/LUFA/Drivers/USB/Class/Common/RNDIS.h
@@ -44,6 +44,7 @@
/* Includes: */
#include "../../USB.h"
#include "CDC.h"
+ #include "RNDISConstants.h"
#include <string.h>
@@ -68,7 +69,7 @@
/** Maximum size in bytes of a RNDIS control message which can be sent or received */
#define RNDIS_MESSAGE_BUFFER_SIZE 128
- /** Maximum size in bytes of an Ethernet frame which can be sent or received */
+ /** Maximum size in bytes of an Ethernet frame according to the Ethernet standard */
#define ETHERNET_FRAME_SIZE_MAX 1500
/** Notification request value for a RNDIS Response Available notification */
diff --git a/LUFA/Drivers/USB/Class/Device/RNDISConstants.h b/LUFA/Drivers/USB/Class/Common/RNDISConstants.h
index c36213d2e..1d16dedc1 100644
--- a/LUFA/Drivers/USB/Class/Device/RNDISConstants.h
+++ b/LUFA/Drivers/USB/Class/Common/RNDISConstants.h
@@ -67,6 +67,19 @@
#define REMOTE_NDIS_DF_CONNECTIONLESS 0x00000001UL
#define REMOTE_NDIS_DF_CONNECTION_ORIENTED 0x00000002UL
+
+ #define REMOTE_NDIS_PACKET_DIRECTED 0x00000001UL
+ #define REMOTE_NDIS_PACKET_MULTICAST 0x00000002UL
+ #define REMOTE_NDIS_PACKET_ALL_MULTICAST 0x00000004UL
+ #define REMOTE_NDIS_PACKET_BROADCAST 0x00000008UL
+ #define REMOTE_NDIS_PACKET_SOURCE_ROUTING 0x00000010UL
+ #define REMOTE_NDIS_PACKET_PROMISCUOUS 0x00000020UL
+ #define REMOTE_NDIS_PACKET_SMT 0x00000040UL
+ #define REMOTE_NDIS_PACKET_ALL_LOCAL 0x00000080UL
+ #define REMOTE_NDIS_PACKET_GROUP 0x00001000UL
+ #define REMOTE_NDIS_PACKET_ALL_FUNCTIONAL 0x00002000UL
+ #define REMOTE_NDIS_PACKET_FUNCTIONAL 0x00004000UL
+ #define REMOTE_NDIS_PACKET_MAC_FRAME 0x00008000UL
#define OID_GEN_SUPPORTED_LIST 0x00010101UL
#define OID_GEN_HARDWARE_STATUS 0x00010102UL
diff --git a/LUFA/Drivers/USB/Class/Device/CDC.c b/LUFA/Drivers/USB/Class/Device/CDC.c
index aafe48076..024278ad3 100644
--- a/LUFA/Drivers/USB/Class/Device/CDC.c
+++ b/LUFA/Drivers/USB/Class/Device/CDC.c
@@ -129,7 +129,7 @@ void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* CDCInterfaceInfo)
uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, char* const Data, const uint16_t Length)
{
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
- return ENDPOINT_READYWAIT_NoError;
+ return ENDPOINT_RWSTREAM_DeviceDisconnected;
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
return Endpoint_Write_Stream_LE(Data, Length, NO_STREAM_CALLBACK);
@@ -138,7 +138,7 @@ uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo
uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, const uint8_t Data)
{
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
- return ENDPOINT_READYWAIT_NoError;
+ return ENDPOINT_RWSTREAM_DeviceDisconnected;
Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);
@@ -159,7 +159,7 @@ uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
{
if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
- return ENDPOINT_READYWAIT_NoError;
+ return ENDPOINT_RWSTREAM_DeviceDisconnected;
uint8_t ErrorCode;
diff --git a/LUFA/Drivers/USB/Class/Device/MIDI.c b/LUFA/Drivers/USB/Class/Device/MIDI.c
index 2685ab0ae..b49bb7341 100644
--- a/LUFA/Drivers/USB/Class/Device/MIDI.c
+++ b/LUFA/Drivers/USB/Class/Device/MIDI.c
@@ -73,7 +73,7 @@ void MIDI_Device_USBTask(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
uint8_t MIDI_Device_SendEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo, MIDI_EventPacket_t* const Event)
{
if (USB_DeviceState != DEVICE_STATE_Configured)
- return ENDPOINT_RWSTREAM_NoError;
+ return ENDPOINT_RWSTREAM_DeviceDisconnected;
Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpointNumber);
diff --git a/LUFA/Drivers/USB/Class/Host/CDC.c b/LUFA/Drivers/USB/Class/Host/CDC.c
index cf9dc1ebb..d1e63b591 100644
--- a/LUFA/Drivers/USB/Class/Host/CDC.c
+++ b/LUFA/Drivers/USB/Class/Host/CDC.c
@@ -273,7 +273,7 @@ uint8_t CDC_Host_SendControlLineStateChange(USB_ClassInfo_CDC_Host_t* const CDCI
uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, char* Data, const uint16_t Length)
{
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
- return PIPE_READYWAIT_NoError;
+ return PIPE_READYWAIT_DeviceDisconnected;
uint8_t ErrorCode;
@@ -300,7 +300,7 @@ uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, ch
uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, const uint8_t Data)
{
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
- return PIPE_READYWAIT_NoError;;
+ return PIPE_READYWAIT_DeviceDisconnected;
uint8_t ErrorCode;
@@ -338,7 +338,7 @@ uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo
uint16_t BytesInPipe = 0;
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
- return BytesInPipe;
+ return 0;
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber);
Pipe_SetPipeToken(PIPE_TOKEN_IN);
@@ -358,7 +358,7 @@ uint8_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
uint8_t ReceivedByte = 0;
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
- return ReceivedByte;
+ return 0;
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber);
Pipe_SetPipeToken(PIPE_TOKEN_IN);
diff --git a/LUFA/Drivers/USB/Class/Host/CDC.h b/LUFA/Drivers/USB/Class/Host/CDC.h
index 4e035d97e..d1ad49c27 100644
--- a/LUFA/Drivers/USB/Class/Host/CDC.h
+++ b/LUFA/Drivers/USB/Class/Host/CDC.h
@@ -91,7 +91,7 @@
bool BidirectionalDataEndpoints; /**< Indicates if the attached CDC interface uses bidirectional data endpoints,
* and this has only the IN pipe configured (with \ref Pipe_SetPipeToken()
- * used to switch the pipe's direction
+ * used to switch the pipe's direction)
*/
struct
diff --git a/LUFA/Drivers/USB/Class/Host/HID.c b/LUFA/Drivers/USB/Class/Host/HID.c
index a82fe537f..9c02b697e 100644
--- a/LUFA/Drivers/USB/Class/Host/HID.c
+++ b/LUFA/Drivers/USB/Class/Host/HID.c
@@ -176,7 +176,7 @@ uint8_t HID_Host_ReceiveReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceI
uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo, void* Buffer)
{
if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
- return false;
+ return PIPE_READYWAIT_DeviceDisconnected;
uint8_t ErrorCode;
@@ -219,9 +219,6 @@ uint8_t HID_Host_SendReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo
#endif
void* Buffer, const uint16_t ReportSize)
{
- if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
- return false;
-
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
if (HIDInterfaceInfo->State.DeviceUsesOUTPipe)
{
@@ -282,9 +279,6 @@ bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
{
- if (HIDInterfaceInfo->State.UsingBootProtocol)
- return HOST_SENDCONTROL_Successful;
-
uint8_t ErrorCode;
USB_ControlRequest = (USB_Request_Header_t)
diff --git a/LUFA/Drivers/USB/Class/Host/MIDI.c b/LUFA/Drivers/USB/Class/Host/MIDI.c
index 5d3b148a0..104c73858 100644
--- a/LUFA/Drivers/USB/Class/Host/MIDI.c
+++ b/LUFA/Drivers/USB/Class/Host/MIDI.c
@@ -130,7 +130,7 @@ void MIDI_Host_USBTask(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo)
uint8_t MIDI_Host_SendEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo, MIDI_EventPacket_t* const Event)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
- return HOST_SENDCONTROL_DeviceDisconnect;
+ return HOST_SENDCONTROL_DeviceDisconnected;
Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataOUTPipeNumber);
@@ -150,7 +150,7 @@ uint8_t MIDI_Host_SendEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterface
bool MIDI_Host_ReceiveEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo, MIDI_EventPacket_t* const Event)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
- return HOST_SENDCONTROL_DeviceDisconnect;
+ return HOST_SENDCONTROL_DeviceDisconnected;
Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataINPipeNumber);
diff --git a/LUFA/Drivers/USB/Class/Host/MassStorage.c b/LUFA/Drivers/USB/Class/Host/MassStorage.c
index d1622c17d..75b8ef485 100644
--- a/LUFA/Drivers/USB/Class/Host/MassStorage.c
+++ b/LUFA/Drivers/USB/Class/Host/MassStorage.c
@@ -289,9 +289,6 @@ static uint8_t MS_Host_GetReturnedStatus(USB_ClassInfo_MS_Host_t* const MSInterf
uint8_t MS_Host_ResetMSInterface(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo)
{
- if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
- return HOST_SENDCONTROL_DeviceDisconnect;
-
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
@@ -308,9 +305,6 @@ uint8_t MS_Host_ResetMSInterface(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo)
uint8_t MS_Host_GetMaxLUN(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, uint8_t* const MaxLUNIndex)
{
- if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
- return HOST_SENDCONTROL_DeviceDisconnect;
-
uint8_t ErrorCode;
USB_ControlRequest = (USB_Request_Header_t)
@@ -334,7 +328,7 @@ uint8_t MS_Host_GetInquiryData(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, c
SCSI_Inquiry_Response_t* const InquiryData)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
- return HOST_SENDCONTROL_DeviceDisconnect;
+ return HOST_SENDCONTROL_DeviceDisconnected;
uint8_t ErrorCode;
@@ -370,7 +364,7 @@ uint8_t MS_Host_GetInquiryData(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, c
uint8_t MS_Host_TestUnitReady(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, const uint8_t LUNIndex)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
- return HOST_SENDCONTROL_DeviceDisconnect;
+ return HOST_SENDCONTROL_DeviceDisconnected;
uint8_t ErrorCode;
@@ -407,7 +401,7 @@ uint8_t MS_Host_ReadDeviceCapacity(USB_ClassInfo_MS_Host_t* const MSInterfaceInf
SCSI_Capacity_t* const DeviceCapacity)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
- return HOST_SENDCONTROL_DeviceDisconnect;
+ return HOST_SENDCONTROL_DeviceDisconnected;
uint8_t ErrorCode;
@@ -451,7 +445,7 @@ uint8_t MS_Host_RequestSense(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, con
SCSI_Request_Sense_Response_t* const SenseData)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
- return HOST_SENDCONTROL_DeviceDisconnect;
+ return HOST_SENDCONTROL_DeviceDisconnected;
uint8_t ErrorCode;
@@ -488,7 +482,7 @@ uint8_t MS_Host_PreventAllowMediumRemoval(USB_ClassInfo_MS_Host_t* const MSInter
const bool PreventRemoval)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
- return HOST_SENDCONTROL_DeviceDisconnect;
+ return HOST_SENDCONTROL_DeviceDisconnected;
uint8_t ErrorCode;
@@ -525,7 +519,7 @@ uint8_t MS_Host_ReadDeviceBlocks(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
const uint8_t Blocks, const uint16_t BlockSize, void* BlockBuffer)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
- return HOST_SENDCONTROL_DeviceDisconnect;
+ return HOST_SENDCONTROL_DeviceDisconnected;
uint8_t ErrorCode;
@@ -566,7 +560,7 @@ uint8_t MS_Host_WriteDeviceBlocks(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo
const uint8_t Blocks, const uint16_t BlockSize, void* BlockBuffer)
{
if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
- return HOST_SENDCONTROL_DeviceDisconnect;
+ return HOST_SENDCONTROL_DeviceDisconnected;
uint8_t ErrorCode;
diff --git a/LUFA/Drivers/USB/Class/Host/Printer.c b/LUFA/Drivers/USB/Class/Host/Printer.c
index 192e17f86..d85ac15cf 100644
--- a/LUFA/Drivers/USB/Class/Host/Printer.c
+++ b/LUFA/Drivers/USB/Class/Host/Printer.c
@@ -187,6 +187,9 @@ uint8_t PRNT_Host_SendData(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, v
{
uint8_t ErrorCode;
+ if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
Pipe_Unfreeze();
diff --git a/LUFA/Drivers/USB/Class/Host/RNDIS.c b/LUFA/Drivers/USB/Class/Host/RNDIS.c
new file mode 100644
index 000000000..e44d05fab
--- /dev/null
+++ b/LUFA/Drivers/USB/Class/Host/RNDIS.c
@@ -0,0 +1,446 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2009.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, and distribute this software
+ and its documentation for any purpose and without fee is hereby
+ granted, provided that the above copyright notice appear in all
+ copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../HighLevel/USBMode.h"
+#if defined(USB_CAN_BE_HOST)
+
+#define INCLUDE_FROM_RNDIS_CLASS_HOST_C
+#include "RNDIS.h"
+
+uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData)
+{
+ uint8_t FoundEndpoints = 0;
+
+ memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
+
+ if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
+ return RNDIS_ENUMERROR_InvalidConfigDescriptor;
+
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DComp_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return RNDIS_ENUMERROR_NoRNDISInterfaceFound;
+ }
+
+ RNDISInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_Interface_t).InterfaceNumber;
+
+ while (FoundEndpoints != (RNDIS_FOUND_NOTIFICATION_IN | RNDIS_FOUND_DATAPIPE_IN | RNDIS_FOUND_DATAPIPE_OUT))
+ {
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DComp_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ if (FoundEndpoints & RNDIS_FOUND_NOTIFICATION_IN)
+ {
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DComp_RNDIS_Host_NextRNDISDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return RNDIS_ENUMERROR_NoRNDISInterfaceFound;
+ }
+ }
+ else
+ {
+ FoundEndpoints = 0;
+
+ Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
+ Pipe_DisablePipe();
+ Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber);
+ Pipe_DisablePipe();
+ Pipe_SelectPipe(RNDISInterfaceInfo->Config.NotificationPipeNumber);
+ Pipe_DisablePipe();
+
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DComp_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return RNDIS_ENUMERROR_NoRNDISInterfaceFound;
+ }
+ }
+
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DComp_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return RNDIS_ENUMERROR_EndpointsNotFound;
+ }
+ }
+
+ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
+
+ if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
+ {
+ if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
+ {
+ Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.NotificationPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
+ EndpointData->EndpointAddress, EndpointData->EndpointSize,
+ RNDISInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
+ RNDISInterfaceInfo->State.NotificationPipeSize = EndpointData->EndpointSize;
+
+ Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS);
+
+ FoundEndpoints |= RNDIS_FOUND_NOTIFICATION_IN;
+ }
+ }
+ else
+ {
+ if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
+ {
+ if (Pipe_IsEndpointBound(EndpointData->EndpointAddress))
+ {
+ RNDISInterfaceInfo->State.BidirectionalDataEndpoints = true;
+ Pipe_DisablePipe();
+ }
+
+ Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
+ EndpointData->EndpointAddress, EndpointData->EndpointSize,
+ RNDISInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
+ RNDISInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
+
+ FoundEndpoints |= RNDIS_FOUND_DATAPIPE_IN;
+ }
+ else
+ {
+ if (Pipe_IsEndpointBound(EndpointData->EndpointAddress))
+ {
+ RNDISInterfaceInfo->State.BidirectionalDataEndpoints = true;
+ }
+ else
+ {
+ Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
+ EndpointData->EndpointAddress, EndpointData->EndpointSize,
+ RNDISInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
+ }
+
+ RNDISInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
+
+ FoundEndpoints |= RNDIS_FOUND_DATAPIPE_OUT;
+ }
+ }
+ }
+
+ RNDISInterfaceInfo->State.IsActive = true;
+ return RNDIS_ENUMERROR_NoError;
+}
+
+static uint8_t DComp_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor)
+{
+ if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
+ {
+ USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
+ USB_Descriptor_Interface_t);
+
+ if ((CurrentInterface->Class == RNDIS_CONTROL_CLASS) &&
+ (CurrentInterface->SubClass == RNDIS_CONTROL_SUBCLASS) &&
+ (CurrentInterface->Protocol == RNDIS_CONTROL_PROTOCOL))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+static uint8_t DComp_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor)
+{
+ if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
+ {
+ USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
+ USB_Descriptor_Interface_t);
+
+ if ((CurrentInterface->Class == RNDIS_DATA_CLASS) &&
+ (CurrentInterface->SubClass == RNDIS_DATA_SUBCLASS) &&
+ (CurrentInterface->Protocol == RNDIS_DATA_PROTOCOL))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+static uint8_t DComp_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor)
+{
+ if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
+ {
+ USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor,
+ USB_Descriptor_Endpoint_t);
+
+ uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK);
+
+ if ((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+ else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
+ {
+ return DESCRIPTOR_SEARCH_Fail;
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+void RNDIS_Host_USBTask(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
+{
+
+}
+
+static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ void* Buffer, uint16_t Length)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = REQ_SendEncapsulatedCommand,
+ .wValue = 0,
+ .wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
+ .wLength = Length,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+ return USB_Host_SendControlRequest(Buffer);
+}
+
+static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ void* Buffer, uint16_t Length)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = REQ_GetEncapsulatedResponse,
+ .wValue = 0,
+ .wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
+ .wLength = Length,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+ return USB_Host_SendControlRequest(Buffer);
+}
+
+uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
+{
+ uint8_t ErrorCode;
+
+ RNDIS_KeepAlive_Message_t KeepAliveMessage;
+ RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse;
+
+ KeepAliveMessage.MessageType = REMOTE_NDIS_KEEPALIVE_MSG;
+ KeepAliveMessage.MessageLength = sizeof(RNDIS_KeepAlive_Message_t);
+ KeepAliveMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
+
+ if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &KeepAliveMessage,
+ sizeof(RNDIS_KeepAlive_Message_t))) != HOST_SENDCONTROL_Successful)
+ {
+ return ErrorCode;
+ }
+
+ if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &KeepAliveMessageResponse,
+ sizeof(RNDIS_KeepAlive_Complete_t))) != HOST_SENDCONTROL_Successful)
+ {
+ return ErrorCode;
+ }
+
+ return HOST_SENDCONTROL_Successful;
+}
+
+uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
+{
+ uint8_t ErrorCode;
+
+ RNDIS_Initialize_Message_t InitMessage;
+ RNDIS_Initialize_Complete_t InitMessageResponse;
+
+ InitMessage.MessageType = REMOTE_NDIS_INITIALIZE_MSG;
+ InitMessage.MessageLength = sizeof(RNDIS_Initialize_Message_t);
+ InitMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
+
+ InitMessage.MajorVersion = REMOTE_NDIS_VERSION_MAJOR;
+ InitMessage.MinorVersion = REMOTE_NDIS_VERSION_MINOR;
+ InitMessage.MaxTransferSize = RNDISInterfaceInfo->Config.HostMaxPacketSize;
+
+ if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &InitMessage,
+ sizeof(RNDIS_Initialize_Message_t))) != HOST_SENDCONTROL_Successful)
+ {
+ return ErrorCode;
+ }
+
+ if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &InitMessageResponse,
+ sizeof(RNDIS_Initialize_Complete_t))) != HOST_SENDCONTROL_Successful)
+ {
+ return ErrorCode;
+ }
+
+ if (InitMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
+ return RNDIS_COMMAND_FAILED;
+
+ RNDISInterfaceInfo->State.DeviceMaxPacketSize = InitMessageResponse.MaxTransferSize;
+
+ return HOST_SENDCONTROL_Successful;
+}
+
+uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint32_t Oid, void* Buffer, uint16_t Length)
+{
+ uint8_t ErrorCode;
+
+ struct
+ {
+ RNDIS_Set_Message_t SetMessage;
+ uint8_t ContigiousBuffer[Length];
+ } SetMessageData;
+
+ RNDIS_Set_Complete_t SetMessageResponse;
+
+ SetMessageData.SetMessage.MessageType = REMOTE_NDIS_SET_MSG;
+ SetMessageData.SetMessage.MessageLength = sizeof(RNDIS_Set_Message_t) + Length;
+ SetMessageData.SetMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
+
+ SetMessageData.SetMessage.Oid = Oid;
+ SetMessageData.SetMessage.InformationBufferLength = Length;
+ SetMessageData.SetMessage.InformationBufferOffset = (sizeof(RNDIS_Set_Message_t) - sizeof(RNDIS_Message_Header_t));
+ SetMessageData.SetMessage.DeviceVcHandle = 0;
+
+ memcpy(&SetMessageData.ContigiousBuffer, Buffer, Length);
+
+ if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &SetMessageData,
+ SetMessageData.SetMessage.MessageLength)) != HOST_SENDCONTROL_Successful)
+ {
+ return ErrorCode;
+ }
+
+ if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &SetMessageResponse,
+ sizeof(RNDIS_Set_Complete_t))) != HOST_SENDCONTROL_Successful)
+ {
+ return ErrorCode;
+ }
+
+ if (SetMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
+ return RNDIS_COMMAND_FAILED;
+
+ return HOST_SENDCONTROL_Successful;
+}
+
+uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint32_t Oid, void* Buffer, uint16_t MaxLength)
+{
+ uint8_t ErrorCode;
+
+ RNDIS_Query_Message_t QueryMessage;
+
+ struct
+ {
+ RNDIS_Query_Complete_t QueryMessageResponse;
+ uint8_t ContigiousBuffer[MaxLength];
+ } QueryMessageResponseData;
+
+ QueryMessage.MessageType = REMOTE_NDIS_QUERY_MSG;
+ QueryMessage.MessageLength = sizeof(RNDIS_Query_Message_t);
+ QueryMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
+
+ QueryMessage.Oid = Oid;
+ QueryMessage.InformationBufferLength = 0;
+ QueryMessage.InformationBufferOffset = 0;
+ QueryMessage.DeviceVcHandle = 0;
+
+ if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &QueryMessage,
+ sizeof(RNDIS_Query_Message_t))) != HOST_SENDCONTROL_Successful)
+ {
+ return ErrorCode;
+ }
+
+ if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &QueryMessageResponseData,
+ sizeof(QueryMessageResponseData))) != HOST_SENDCONTROL_Successful)
+ {
+ return ErrorCode;
+ }
+
+ if (QueryMessageResponseData.QueryMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
+ return RNDIS_COMMAND_FAILED;
+
+ memcpy(Buffer, &QueryMessageResponseData.ContigiousBuffer, MaxLength);
+
+ return HOST_SENDCONTROL_Successful;
+}
+
+bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
+{
+ bool PacketWaiting;
+
+ if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
+ return false;
+
+ Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
+ Pipe_SetPipeToken(PIPE_TOKEN_IN);
+
+ Pipe_Unfreeze();
+
+ PacketWaiting = Pipe_IsINReceived();
+
+ Pipe_Freeze();
+
+ return PacketWaiting;
+}
+
+uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, void* Buffer, uint16_t* PacketLength)
+{
+ uint8_t ErrorCode;
+
+ if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
+ Pipe_SetPipeToken(PIPE_TOKEN_IN);
+ Pipe_Unfreeze();
+
+ if (!(Pipe_IsReadWriteAllowed()))
+ {
+ *PacketLength = 0;
+ Pipe_Freeze();
+ return PIPE_RWSTREAM_NoError;
+ }
+
+ RNDIS_Packet_Message_t DeviceMessage;
+
+ if ((ErrorCode = Pipe_Read_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
+ NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
+ {
+ return ErrorCode;
+ }
+
+ *PacketLength = (uint16_t)DeviceMessage.DataLength;
+
+ Pipe_Discard_Stream(DeviceMessage.DataOffset - (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)),
+ NO_STREAM_CALLBACK);
+
+ Pipe_Read_Stream_LE(Buffer, *PacketLength, NO_STREAM_CALLBACK);
+ Pipe_ClearIN();
+
+ Pipe_Freeze();
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+#endif
diff --git a/LUFA/Drivers/USB/Class/Host/RNDIS.h b/LUFA/Drivers/USB/Class/Host/RNDIS.h
new file mode 100644
index 000000000..4c384b6fc
--- /dev/null
+++ b/LUFA/Drivers/USB/Class/Host/RNDIS.h
@@ -0,0 +1,248 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2009.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.fourwalledcubicle.com
+*/
+
+/*
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, and distribute this software
+ and its documentation for any purpose and without fee is hereby
+ granted, provided that the above copyright notice appear in all
+ copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \ingroup Group_USBClassRNDIS
+ * @defgroup Group_USBClassRNDISHost RNDIS Class Host Mode Driver
+ *
+ * \section Sec_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Host/RNDIS.c
+ *
+ * \section Module Description
+ * Host Mode USB Class driver framework interface, for the Microsoft RNDIS Ethernet
+ * USB Class driver.
+ *
+ * @{
+ */
+
+#ifndef __RNDIS_CLASS_HOST_H__
+#define __RNDIS_CLASS_HOST_H__
+
+ /* Includes: */
+ #include "../../USB.h"
+ #include "../Common/RNDIS.h"
+
+ #include <stdio.h>
+ #include <string.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Type Defines: */
+ /** Class state structure. An instance of this structure should be made within the user application,
+ * and passed to each of the RNDIS class driver functions as the RNDISInterfaceInfo parameter. This
+ * stores each RNDIS interface's configuration and state information.
+ */
+ typedef struct
+ {
+ const struct
+ {
+ uint8_t DataINPipeNumber; /**< Pipe number of the RNDIS interface's IN data pipe */
+ bool DataINPipeDoubleBank; /** Indicates if the RNDIS interface's IN data pipe should use double banking */
+
+ uint8_t DataOUTPipeNumber; /**< Pipe number of the RNDIS interface's OUT data pipe */
+ bool DataOUTPipeDoubleBank; /** Indicates if the RNDIS interface's OUT data pipe should use double banking */
+
+ uint8_t NotificationPipeNumber; /**< Pipe number of the RNDIS interface's IN notification endpoint, if used */
+ bool NotificationPipeDoubleBank; /** Indicates if the RNDIS interface's notification pipe should use double banking */
+
+ uint32_t HostMaxPacketSize; /**< Maximum size of a packet which can be buffered by the host */
+ } Config; /**< Config data for the USB class interface within the device. All elements in this section
+ * <b>must</b> be set or the interface will fail to enumerate and operate correctly.
+ */
+ struct
+ {
+ bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
+ * after \ref RNDIS_Host_ConfigurePipes() is called and the Host state machine is in the
+ * Configured state
+ */
+ uint8_t ControlInterfaceNumber; /**< Interface index of the RNDIS control interface within the attached device */
+
+ uint16_t DataINPipeSize; /**< Size in bytes of the RNDIS interface's IN data pipe */
+ uint16_t DataOUTPipeSize; /**< Size in bytes of the RNDIS interface's OUT data pipe */
+ uint16_t NotificationPipeSize; /**< Size in bytes of the RNDIS interface's IN notification pipe, if used */
+
+ bool BidirectionalDataEndpoints; /**< Indicates if the attached RNDIS interface uses bidirectional data endpoints,
+ * and this has only the IN pipe configured (with \ref Pipe_SetPipeToken()
+ * used to switch the pipe's direction)
+ */
+ uint32_t DeviceMaxPacketSize; /**< Maximum size of a packet which can be buffered by the attached RNDIS device */
+
+ uint32_t RequestID; /**< Request ID counter to give a unique ID for each command/response pair */
+ } State; /**< State data for the USB class interface within the device. All elements in this section
+ * <b>may</b> be set to initial values, but may also be ignored to default to sane values when
+ * the interface is enumerated.
+ */
+ } USB_ClassInfo_RNDIS_Host_t;
+
+ /* Enums: */
+ /** Enum for the possible error codes returned by the \ref RNDIS_Host_ConfigurePipes() function. */
+ enum RNDISHost_EnumerationFailure_ErrorCodes_t
+ {
+ 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 */
+ };
+
+ /* Macros: */
+ /** Additional error code for RNDIS functions when a device returns a logical command failure */
+ #define RNDIS_COMMAND_FAILED 0xC0
+
+ /* Function Prototypes: */
+ /** General management task for a given RNDIS host class interface, required for the correct operation of the interface. This should
+ * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
+ */
+ void RNDIS_Host_USBTask(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Host interface configuration routine, to configure a given RNDIS host interface instance using the Configuration
+ * Descriptor read from an attached USB device. This function automatically updates the given RNDIS Host instance's
+ * state values and configures the pipes required to communicate with the interface if it 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] 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
+ *
+ * \return A value from the \ref RNDISHost_EnumerationFailure_ErrorCodes_t enum
+ */
+ uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint16_t ConfigDescriptorSize,
+ void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Sends a RNDIS KEEPALIVE command to the device, to ensure that it does not enter standby mode after periods
+ * of long inactivity.
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
+ *
+ * \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a
+ * logical command failure
+ */
+ uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Initializes the attached RNDIS device's RNDIS interface. This should be called after the device's pipes have been
+ * configured via the call to \ref RNDIS_Host_ConfigurePipes().
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
+ * \param[in] HostMaxPacketSize Size of the packet buffer on the host
+ * \param[out] DeviceMaxPacketSize Pointer to where the packet buffer size of the device is to be stored
+ *
+ * \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a
+ * logical command failure
+ */
+ uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sets a given RNDIS property of an attached RNDIS device.
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
+ * \param[in] Oid OID number of the parameter to set
+ * \param[in] Buffer Pointer to where the property data is to be sourced from
+ * \param[in] Length Length in bytes of the property data to sent to the device
+ *
+ * \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a
+ * logical command failure
+ */
+ uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint32_t Oid, void* Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Gets a given RNDIS property of an attached RNDIS device.
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
+ * \param[in] Oid OID number of the parameter to get
+ * \param[in] Buffer Pointer to where the property data is to be written to
+ * \param[in] MaxLength Length in bytes of the destination buffer size
+ *
+ * \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a
+ * logical command failure
+ */
+ uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint32_t Oid, void* Buffer,
+ uint16_t MaxLength) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Determines if a packet is currently waiting for the host to read in and process.
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
+ *
+ * \return Boolean true if a packet is waiting to be read in by the host, false otherwise
+ */
+
+ bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo);
+
+ /** Retrieves the next pending packet from the device, discarding the remainder of the RNDIS packet header to leave
+ * only the packet contents for processing by the host in the nominated buffer.
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
+ * \param[out] Buffer Pointer to a buffer where the packer data is to be written to
+ * \param[out] PacketLength Pointer to where the length in bytes of the read packet is to be stored
+ *
+ * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum
+ */
+ uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, void* Buffer, uint16_t* PacketLength)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2) ATTR_NON_NULL_PTR_ARG(3);
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define RNDIS_CONTROL_CLASS 0x02
+ #define RNDIS_CONTROL_SUBCLASS 0x02
+ #define RNDIS_CONTROL_PROTOCOL 0xFF
+ #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)
+ static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ void* Buffer, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ void* Buffer, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ static uint8_t DComp_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t DComp_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t DComp_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor);
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
diff --git a/LUFA/Drivers/USB/Class/Host/StillImage.c b/LUFA/Drivers/USB/Class/Host/StillImage.c
index fe14084a9..5a958cf44 100644
--- a/LUFA/Drivers/USB/Class/Host/StillImage.c
+++ b/LUFA/Drivers/USB/Class/Host/StillImage.c
@@ -151,6 +151,9 @@ static uint8_t SImage_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInte
{
uint8_t ErrorCode;
+ if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
PIMAHeader->TransactionID = SIInterfaceInfo->State.TransactionID++;
Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
@@ -177,6 +180,9 @@ static uint8_t SImage_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SII
{
uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;
+ if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
Pipe_Unfreeze();
@@ -240,6 +246,9 @@ uint8_t SImage_Host_SendData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, voi
{
uint8_t ErrorCode;
+ if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
Pipe_Unfreeze();
@@ -255,6 +264,9 @@ uint8_t SImage_Host_ReadData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, voi
{
uint8_t ErrorCode;
+ if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
Pipe_Unfreeze();
@@ -269,6 +281,9 @@ bool SImage_Host_IsEventReceived(USB_ClassInfo_SI_Host_t* SIInterfaceInfo)
{
bool IsEventReceived = false;
+ if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
+ return false;
+
Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipeNumber);
Pipe_Unfreeze();
@@ -284,6 +299,9 @@ uint8_t SImage_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t* const SIInterfac
{
uint8_t ErrorCode;
+ if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipeNumber);
Pipe_Unfreeze();
@@ -298,7 +316,7 @@ uint8_t SImage_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t* const SIInterfac
uint8_t SImage_Host_OpenSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
- return HOST_SENDCONTROL_DeviceDisconnect;
+ return HOST_SENDCONTROL_DeviceDisconnected;
uint8_t ErrorCode;
@@ -328,7 +346,7 @@ uint8_t SImage_Host_OpenSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
uint8_t SImage_Host_CloseSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
{
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
- return HOST_SENDCONTROL_DeviceDisconnect;
+ return HOST_SENDCONTROL_DeviceDisconnected;
uint8_t ErrorCode;
@@ -358,7 +376,7 @@ uint8_t SImage_Host_SendCommand(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
const uint8_t TotalParams, uint32_t* Params)
{
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
- return HOST_SENDCONTROL_DeviceDisconnect;
+ return HOST_SENDCONTROL_DeviceDisconnected;
uint8_t ErrorCode;
@@ -382,6 +400,9 @@ uint8_t SImage_Host_ReceiveResponse(USB_ClassInfo_SI_Host_t* const SIInterfaceIn
uint8_t ErrorCode;
SI_PIMA_Container_t PIMABlock;
+ if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
+ return HOST_SENDCONTROL_DeviceDisconnected;
+
if ((ErrorCode = SImage_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
return ErrorCode;
diff --git a/LUFA/Drivers/USB/Class/RNDIS.h b/LUFA/Drivers/USB/Class/RNDIS.h
index b4387907b..987a7e491 100644
--- a/LUFA/Drivers/USB/Class/RNDIS.h
+++ b/LUFA/Drivers/USB/Class/RNDIS.h
@@ -34,11 +34,12 @@
* \section Sec_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/USB/Class/Device/RNDIS.c
+ * - LUFA/Drivers/USB/Class/Host/RNDIS.c
*
* \section Module Description
* RNDIS Class Driver module. This module contains an internal implementation of the Microsoft USB RNDIS Networking
- * Class, for Device USB mode only. User applications can use this class driver instead of implementing the RNDIS
- * class manually via the low-level LUFA APIs.
+ * Class, for both Device and Host USB modes. User applications can use this class driver instead of implementing the
+ * RNDIS class manually via the low-level LUFA APIs.
*
* This module is designed to simplify the user code by exposing only the required interface needed to interface with
* Hosts using the USB RNDIS Class.
@@ -60,6 +61,10 @@
#include "Device/RNDIS.h"
#endif
+ #if defined(USB_CAN_BE_HOST)
+ #include "Host/RNDIS.h"
+ #endif
+
#endif
/** @} */
diff --git a/LUFA/Drivers/USB/LowLevel/HostChapter9.h b/LUFA/Drivers/USB/LowLevel/HostChapter9.h
index 7550bcd04..bdecdddcf 100644
--- a/LUFA/Drivers/USB/LowLevel/HostChapter9.h
+++ b/LUFA/Drivers/USB/LowLevel/HostChapter9.h
@@ -53,15 +53,15 @@
*/
enum USB_Host_SendControlErrorCodes_t
{
- HOST_SENDCONTROL_Successful = 0, /**< No error occurred in the request transfer. */
- HOST_SENDCONTROL_DeviceDisconnect = 1, /**< The attached device was disconnected during the
+ HOST_SENDCONTROL_Successful = 0, /**< No error occurred in the request transfer. */
+ HOST_SENDCONTROL_DeviceDisconnected = 1, /**< The attached device was disconnected during the
* request transfer.
*/
- HOST_SENDCONTROL_PipeError = 2, /**< An error occurred in the pipe while sending the request. */
- HOST_SENDCONTROL_SetupStalled = 3, /**< The attached device stalled the request, usually
+ HOST_SENDCONTROL_PipeError = 2, /**< An error occurred in the pipe while sending the request. */
+ HOST_SENDCONTROL_SetupStalled = 3, /**< The attached device stalled the request, usually
* indicating that the request is unsupported on the device.
*/
- HOST_SENDCONTROL_SoftwareTimeOut = 4, /**< The request or data transfer timed out. */
+ HOST_SENDCONTROL_SoftwareTimeOut = 4, /**< The request or data transfer timed out. */
};
/* Function Prototypes: */
diff --git a/LUFA/Drivers/USB/USB.h b/LUFA/Drivers/USB/USB.h
index 223967008..f1d7d5be5 100644
--- a/LUFA/Drivers/USB/USB.h
+++ b/LUFA/Drivers/USB/USB.h
@@ -113,13 +113,13 @@
* </tr>
* <tr>
* <td>Printer</td>
- * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">No</td>
* <td bgcolor="#00EE00">Yes</td>
* </tr>
* <tr>
* <td>RNDIS</td>
* <td bgcolor="#00EE00">Yes</td>
- * <td bgcolor="#EE0000">No</td>
+ * <td bgcolor="#EE0000">Yes</td>
* </tr>
* <tr>
* <td>Still Image</td>