3 Copyright (C) Dean Camera, 2010.
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
10 Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
21 The author disclaim all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
31 #define __INCLUDE_FROM_USB_DRIVER
32 #include "../../HighLevel/USBMode.h"
33 #if defined(USB_CAN_BE_HOST)
35 #define __INCLUDE_FROM_RNDIS_CLASS_HOST_C
36 #define __INCLUDE_FROM_RNDIS_DRIVER
39 uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, uint16_t ConfigDescriptorSize
,
40 void* ConfigDescriptorData
)
42 uint8_t FoundEndpoints
= 0;
44 memset(&RNDISInterfaceInfo
->State
, 0x00, sizeof(RNDISInterfaceInfo
->State
));
46 if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
)
47 return RNDIS_ENUMERROR_InvalidConfigDescriptor
;
49 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
50 DComp_RNDIS_Host_NextRNDISControlInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
52 return RNDIS_ENUMERROR_NoRNDISInterfaceFound
;
55 RNDISInterfaceInfo
->State
.ControlInterfaceNumber
= DESCRIPTOR_CAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
).InterfaceNumber
;
57 while (FoundEndpoints
!= (RNDIS_FOUND_NOTIFICATION_IN
| RNDIS_FOUND_DATAPIPE_IN
| RNDIS_FOUND_DATAPIPE_OUT
))
59 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
60 DComp_RNDIS_Host_NextRNDISInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
)
62 if (FoundEndpoints
& RNDIS_FOUND_NOTIFICATION_IN
)
64 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
65 DComp_RNDIS_Host_NextRNDISDataInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
67 return RNDIS_ENUMERROR_NoRNDISInterfaceFound
;
74 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
);
76 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataOUTPipeNumber
);
78 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.NotificationPipeNumber
);
81 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
82 DComp_RNDIS_Host_NextRNDISControlInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
84 return RNDIS_ENUMERROR_NoRNDISInterfaceFound
;
88 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
89 DComp_RNDIS_Host_NextRNDISInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
)
91 return RNDIS_ENUMERROR_EndpointsNotFound
;
95 USB_Descriptor_Endpoint_t
* EndpointData
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
);
97 if ((EndpointData
->Attributes
& EP_TYPE_MASK
) == EP_TYPE_INTERRUPT
)
99 if (EndpointData
->EndpointAddress
& ENDPOINT_DESCRIPTOR_DIR_IN
)
101 Pipe_ConfigurePipe(RNDISInterfaceInfo
->Config
.NotificationPipeNumber
, EP_TYPE_INTERRUPT
, PIPE_TOKEN_IN
,
102 EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
,
103 RNDISInterfaceInfo
->Config
.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE
: PIPE_BANK_SINGLE
);
104 RNDISInterfaceInfo
->State
.NotificationPipeSize
= EndpointData
->EndpointSize
;
106 Pipe_SetInterruptPeriod(EndpointData
->PollingIntervalMS
);
108 FoundEndpoints
|= RNDIS_FOUND_NOTIFICATION_IN
;
113 if (EndpointData
->EndpointAddress
& ENDPOINT_DESCRIPTOR_DIR_IN
)
115 Pipe_ConfigurePipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
, EP_TYPE_BULK
, PIPE_TOKEN_IN
,
116 EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
,
117 RNDISInterfaceInfo
->Config
.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE
: PIPE_BANK_SINGLE
);
118 RNDISInterfaceInfo
->State
.DataINPipeSize
= EndpointData
->EndpointSize
;
120 FoundEndpoints
|= RNDIS_FOUND_DATAPIPE_IN
;
124 Pipe_ConfigurePipe(RNDISInterfaceInfo
->Config
.DataOUTPipeNumber
, EP_TYPE_BULK
, PIPE_TOKEN_OUT
,
125 EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
,
126 RNDISInterfaceInfo
->Config
.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE
: PIPE_BANK_SINGLE
);
128 RNDISInterfaceInfo
->State
.DataOUTPipeSize
= EndpointData
->EndpointSize
;
130 FoundEndpoints
|= RNDIS_FOUND_DATAPIPE_OUT
;
135 RNDISInterfaceInfo
->State
.IsActive
= true;
136 return RNDIS_ENUMERROR_NoError
;
139 static uint8_t DComp_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor
)
141 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
143 USB_Descriptor_Interface_t
* CurrentInterface
= DESCRIPTOR_PCAST(CurrentDescriptor
,
144 USB_Descriptor_Interface_t
);
146 if ((CurrentInterface
->Class
== RNDIS_CONTROL_CLASS
) &&
147 (CurrentInterface
->SubClass
== RNDIS_CONTROL_SUBCLASS
) &&
148 (CurrentInterface
->Protocol
== RNDIS_CONTROL_PROTOCOL
))
150 return DESCRIPTOR_SEARCH_Found
;
154 return DESCRIPTOR_SEARCH_NotFound
;
157 static uint8_t DComp_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor
)
159 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
161 USB_Descriptor_Interface_t
* CurrentInterface
= DESCRIPTOR_PCAST(CurrentDescriptor
,
162 USB_Descriptor_Interface_t
);
164 if ((CurrentInterface
->Class
== RNDIS_DATA_CLASS
) &&
165 (CurrentInterface
->SubClass
== RNDIS_DATA_SUBCLASS
) &&
166 (CurrentInterface
->Protocol
== RNDIS_DATA_PROTOCOL
))
168 return DESCRIPTOR_SEARCH_Found
;
172 return DESCRIPTOR_SEARCH_NotFound
;
175 static uint8_t DComp_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor
)
177 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Endpoint
)
179 USB_Descriptor_Endpoint_t
* CurrentEndpoint
= DESCRIPTOR_PCAST(CurrentDescriptor
,
180 USB_Descriptor_Endpoint_t
);
182 uint8_t EndpointType
= (CurrentEndpoint
->Attributes
& EP_TYPE_MASK
);
184 if (((EndpointType
== EP_TYPE_BULK
) || (EndpointType
== EP_TYPE_INTERRUPT
)) &&
185 !(Pipe_IsEndpointBound(CurrentEndpoint
->EndpointAddress
)))
187 return DESCRIPTOR_SEARCH_Found
;
190 else if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
192 return DESCRIPTOR_SEARCH_Fail
;
195 return DESCRIPTOR_SEARCH_NotFound
;
198 static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
,
199 void* Buffer
, uint16_t Length
)
201 USB_ControlRequest
= (USB_Request_Header_t
)
203 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_INTERFACE
),
204 .bRequest
= REQ_SendEncapsulatedCommand
,
206 .wIndex
= RNDISInterfaceInfo
->State
.ControlInterfaceNumber
,
210 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
211 return USB_Host_SendControlRequest(Buffer
);
214 static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
,
215 void* Buffer
, uint16_t Length
)
217 USB_ControlRequest
= (USB_Request_Header_t
)
219 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
),
220 .bRequest
= REQ_GetEncapsulatedResponse
,
222 .wIndex
= RNDISInterfaceInfo
->State
.ControlInterfaceNumber
,
226 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
227 return USB_Host_SendControlRequest(Buffer
);
230 uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
)
234 RNDIS_KeepAlive_Message_t KeepAliveMessage
;
235 RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse
;
237 KeepAliveMessage
.MessageType
= REMOTE_NDIS_KEEPALIVE_MSG
;
238 KeepAliveMessage
.MessageLength
= sizeof(RNDIS_KeepAlive_Message_t
);
239 KeepAliveMessage
.RequestId
= RNDISInterfaceInfo
->State
.RequestID
++;
241 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &KeepAliveMessage
,
242 sizeof(RNDIS_KeepAlive_Message_t
))) != HOST_SENDCONTROL_Successful
)
247 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &KeepAliveMessageResponse
,
248 sizeof(RNDIS_KeepAlive_Complete_t
))) != HOST_SENDCONTROL_Successful
)
253 return HOST_SENDCONTROL_Successful
;
256 uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
)
260 RNDIS_Initialize_Message_t InitMessage
;
261 RNDIS_Initialize_Complete_t InitMessageResponse
;
263 InitMessage
.MessageType
= REMOTE_NDIS_INITIALIZE_MSG
;
264 InitMessage
.MessageLength
= sizeof(RNDIS_Initialize_Message_t
);
265 InitMessage
.RequestId
= RNDISInterfaceInfo
->State
.RequestID
++;
267 InitMessage
.MajorVersion
= REMOTE_NDIS_VERSION_MAJOR
;
268 InitMessage
.MinorVersion
= REMOTE_NDIS_VERSION_MINOR
;
269 InitMessage
.MaxTransferSize
= RNDISInterfaceInfo
->Config
.HostMaxPacketSize
;
271 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &InitMessage
,
272 sizeof(RNDIS_Initialize_Message_t
))) != HOST_SENDCONTROL_Successful
)
277 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &InitMessageResponse
,
278 sizeof(RNDIS_Initialize_Complete_t
))) != HOST_SENDCONTROL_Successful
)
283 if (InitMessageResponse
.Status
!= REMOTE_NDIS_STATUS_SUCCESS
)
284 return RNDIS_COMMAND_FAILED
;
286 RNDISInterfaceInfo
->State
.DeviceMaxPacketSize
= InitMessageResponse
.MaxTransferSize
;
288 return HOST_SENDCONTROL_Successful
;
291 uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, uint32_t Oid
, void* Buffer
, uint16_t Length
)
297 RNDIS_Set_Message_t SetMessage
;
298 uint8_t ContigiousBuffer
[Length
];
301 RNDIS_Set_Complete_t SetMessageResponse
;
303 SetMessageData
.SetMessage
.MessageType
= REMOTE_NDIS_SET_MSG
;
304 SetMessageData
.SetMessage
.MessageLength
= sizeof(RNDIS_Set_Message_t
) + Length
;
305 SetMessageData
.SetMessage
.RequestId
= RNDISInterfaceInfo
->State
.RequestID
++;
307 SetMessageData
.SetMessage
.Oid
= Oid
;
308 SetMessageData
.SetMessage
.InformationBufferLength
= Length
;
309 SetMessageData
.SetMessage
.InformationBufferOffset
= (sizeof(RNDIS_Set_Message_t
) - sizeof(RNDIS_Message_Header_t
));
310 SetMessageData
.SetMessage
.DeviceVcHandle
= 0;
312 memcpy(&SetMessageData
.ContigiousBuffer
, Buffer
, Length
);
314 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &SetMessageData
,
315 SetMessageData
.SetMessage
.MessageLength
)) != HOST_SENDCONTROL_Successful
)
320 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &SetMessageResponse
,
321 sizeof(RNDIS_Set_Complete_t
))) != HOST_SENDCONTROL_Successful
)
326 if (SetMessageResponse
.Status
!= REMOTE_NDIS_STATUS_SUCCESS
)
327 return RNDIS_COMMAND_FAILED
;
329 return HOST_SENDCONTROL_Successful
;
332 uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, uint32_t Oid
, void* Buffer
, uint16_t MaxLength
)
336 RNDIS_Query_Message_t QueryMessage
;
340 RNDIS_Query_Complete_t QueryMessageResponse
;
341 uint8_t ContigiousBuffer
[MaxLength
];
342 } QueryMessageResponseData
;
344 QueryMessage
.MessageType
= REMOTE_NDIS_QUERY_MSG
;
345 QueryMessage
.MessageLength
= sizeof(RNDIS_Query_Message_t
);
346 QueryMessage
.RequestId
= RNDISInterfaceInfo
->State
.RequestID
++;
348 QueryMessage
.Oid
= Oid
;
349 QueryMessage
.InformationBufferLength
= 0;
350 QueryMessage
.InformationBufferOffset
= 0;
351 QueryMessage
.DeviceVcHandle
= 0;
353 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &QueryMessage
,
354 sizeof(RNDIS_Query_Message_t
))) != HOST_SENDCONTROL_Successful
)
359 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &QueryMessageResponseData
,
360 sizeof(QueryMessageResponseData
))) != HOST_SENDCONTROL_Successful
)
365 if (QueryMessageResponseData
.QueryMessageResponse
.Status
!= REMOTE_NDIS_STATUS_SUCCESS
)
366 return RNDIS_COMMAND_FAILED
;
368 memcpy(Buffer
, &QueryMessageResponseData
.ContigiousBuffer
, MaxLength
);
370 return HOST_SENDCONTROL_Successful
;
373 bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
)
377 if ((USB_HostState
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
))
380 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
);
381 Pipe_SetPipeToken(PIPE_TOKEN_IN
);
385 PacketWaiting
= (Pipe_IsINReceived() && Pipe_BytesInPipe());
389 return PacketWaiting
;
392 uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, void* Buffer
, uint16_t* PacketLength
)
396 if ((USB_HostState
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
))
397 return PIPE_READYWAIT_DeviceDisconnected
;
399 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
);
400 Pipe_SetPipeToken(PIPE_TOKEN_IN
);
403 if (!(Pipe_IsReadWriteAllowed()))
405 if (Pipe_IsINReceived())
410 return PIPE_RWSTREAM_NoError
;
413 RNDIS_Packet_Message_t DeviceMessage
;
415 if ((ErrorCode
= Pipe_Read_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
),
416 NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
)
421 *PacketLength
= (uint16_t)DeviceMessage
.DataLength
;
423 Pipe_Discard_Stream(DeviceMessage
.DataOffset
- (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
)),
426 Pipe_Read_Stream_LE(Buffer
, *PacketLength
, NO_STREAM_CALLBACK
);
428 if (!(Pipe_BytesInPipe()))
433 return PIPE_RWSTREAM_NoError
;
436 uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, void* Buffer
, uint16_t PacketLength
)
440 if ((USB_HostState
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
))
441 return PIPE_READYWAIT_DeviceDisconnected
;
443 RNDIS_Packet_Message_t DeviceMessage
;
445 memset(&DeviceMessage
, 0, sizeof(RNDIS_Packet_Message_t
));
446 DeviceMessage
.MessageType
= REMOTE_NDIS_PACKET_MSG
;
447 DeviceMessage
.MessageLength
= (sizeof(RNDIS_Packet_Message_t
) + PacketLength
);
448 DeviceMessage
.DataOffset
= (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
));
449 DeviceMessage
.DataLength
= PacketLength
;
451 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataOUTPipeNumber
);
454 if ((ErrorCode
= Pipe_Write_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
),
455 NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
)
460 Pipe_Write_Stream_LE(Buffer
, PacketLength
, NO_STREAM_CALLBACK
);
465 return PIPE_RWSTREAM_NoError
;