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
,
40 uint16_t ConfigDescriptorSize
,
41 void* ConfigDescriptorData
)
43 uint8_t FoundEndpoints
= 0;
45 memset(&RNDISInterfaceInfo
->State
, 0x00, sizeof(RNDISInterfaceInfo
->State
));
47 if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
)
48 return RNDIS_ENUMERROR_InvalidConfigDescriptor
;
50 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
51 DCOMP_RNDIS_Host_NextRNDISControlInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
53 return RNDIS_ENUMERROR_NoRNDISInterfaceFound
;
56 RNDISInterfaceInfo
->State
.ControlInterfaceNumber
= DESCRIPTOR_CAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
).InterfaceNumber
;
58 while (FoundEndpoints
!= (RNDIS_FOUND_NOTIFICATION_IN
| RNDIS_FOUND_DATAPIPE_IN
| RNDIS_FOUND_DATAPIPE_OUT
))
60 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
61 DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
)
63 if (FoundEndpoints
& RNDIS_FOUND_NOTIFICATION_IN
)
65 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
66 DCOMP_RNDIS_Host_NextRNDISDataInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
68 return RNDIS_ENUMERROR_NoRNDISInterfaceFound
;
75 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
);
77 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataOUTPipeNumber
);
79 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.NotificationPipeNumber
);
82 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
83 DCOMP_RNDIS_Host_NextRNDISControlInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
85 return RNDIS_ENUMERROR_NoRNDISInterfaceFound
;
89 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
90 DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
)
92 return RNDIS_ENUMERROR_EndpointsNotFound
;
96 USB_Descriptor_Endpoint_t
* EndpointData
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
);
98 if ((EndpointData
->Attributes
& EP_TYPE_MASK
) == EP_TYPE_INTERRUPT
)
100 if (EndpointData
->EndpointAddress
& ENDPOINT_DESCRIPTOR_DIR_IN
)
102 Pipe_ConfigurePipe(RNDISInterfaceInfo
->Config
.NotificationPipeNumber
, EP_TYPE_INTERRUPT
, PIPE_TOKEN_IN
,
103 EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
,
104 RNDISInterfaceInfo
->Config
.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE
: PIPE_BANK_SINGLE
);
105 RNDISInterfaceInfo
->State
.NotificationPipeSize
= EndpointData
->EndpointSize
;
107 Pipe_SetInterruptPeriod(EndpointData
->PollingIntervalMS
);
109 FoundEndpoints
|= RNDIS_FOUND_NOTIFICATION_IN
;
114 if (EndpointData
->EndpointAddress
& ENDPOINT_DESCRIPTOR_DIR_IN
)
116 Pipe_ConfigurePipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
, EP_TYPE_BULK
, PIPE_TOKEN_IN
,
117 EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
,
118 RNDISInterfaceInfo
->Config
.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE
: PIPE_BANK_SINGLE
);
119 RNDISInterfaceInfo
->State
.DataINPipeSize
= EndpointData
->EndpointSize
;
121 FoundEndpoints
|= RNDIS_FOUND_DATAPIPE_IN
;
125 Pipe_ConfigurePipe(RNDISInterfaceInfo
->Config
.DataOUTPipeNumber
, EP_TYPE_BULK
, PIPE_TOKEN_OUT
,
126 EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
,
127 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
,
200 const uint16_t Length
)
202 USB_ControlRequest
= (USB_Request_Header_t
)
204 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_INTERFACE
),
205 .bRequest
= RNDIS_REQ_SendEncapsulatedCommand
,
207 .wIndex
= RNDISInterfaceInfo
->State
.ControlInterfaceNumber
,
211 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
212 return USB_Host_SendControlRequest(Buffer
);
215 static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
,
217 const uint16_t Length
)
219 USB_ControlRequest
= (USB_Request_Header_t
)
221 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
),
222 .bRequest
= RNDIS_REQ_GetEncapsulatedResponse
,
224 .wIndex
= RNDISInterfaceInfo
->State
.ControlInterfaceNumber
,
228 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
229 return USB_Host_SendControlRequest(Buffer
);
232 uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
)
236 RNDIS_KeepAlive_Message_t KeepAliveMessage
;
237 RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse
;
239 KeepAliveMessage
.MessageType
= REMOTE_NDIS_KEEPALIVE_MSG
;
240 KeepAliveMessage
.MessageLength
= sizeof(RNDIS_KeepAlive_Message_t
);
241 KeepAliveMessage
.RequestId
= RNDISInterfaceInfo
->State
.RequestID
++;
243 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &KeepAliveMessage
,
244 sizeof(RNDIS_KeepAlive_Message_t
))) != HOST_SENDCONTROL_Successful
)
249 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &KeepAliveMessageResponse
,
250 sizeof(RNDIS_KeepAlive_Complete_t
))) != HOST_SENDCONTROL_Successful
)
255 return HOST_SENDCONTROL_Successful
;
258 uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
)
262 RNDIS_Initialize_Message_t InitMessage
;
263 RNDIS_Initialize_Complete_t InitMessageResponse
;
265 InitMessage
.MessageType
= REMOTE_NDIS_INITIALIZE_MSG
;
266 InitMessage
.MessageLength
= sizeof(RNDIS_Initialize_Message_t
);
267 InitMessage
.RequestId
= RNDISInterfaceInfo
->State
.RequestID
++;
269 InitMessage
.MajorVersion
= REMOTE_NDIS_VERSION_MAJOR
;
270 InitMessage
.MinorVersion
= REMOTE_NDIS_VERSION_MINOR
;
271 InitMessage
.MaxTransferSize
= RNDISInterfaceInfo
->Config
.HostMaxPacketSize
;
273 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &InitMessage
,
274 sizeof(RNDIS_Initialize_Message_t
))) != HOST_SENDCONTROL_Successful
)
279 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &InitMessageResponse
,
280 sizeof(RNDIS_Initialize_Complete_t
))) != HOST_SENDCONTROL_Successful
)
285 if (InitMessageResponse
.Status
!= REMOTE_NDIS_STATUS_SUCCESS
)
286 return RNDIS_COMMAND_FAILED
;
288 RNDISInterfaceInfo
->State
.DeviceMaxPacketSize
= InitMessageResponse
.MaxTransferSize
;
290 return HOST_SENDCONTROL_Successful
;
293 uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
,
296 const uint16_t Length
)
302 RNDIS_Set_Message_t SetMessage
;
303 uint8_t ContiguousBuffer
[Length
];
306 RNDIS_Set_Complete_t SetMessageResponse
;
308 SetMessageData
.SetMessage
.MessageType
= REMOTE_NDIS_SET_MSG
;
309 SetMessageData
.SetMessage
.MessageLength
= sizeof(RNDIS_Set_Message_t
) + Length
;
310 SetMessageData
.SetMessage
.RequestId
= RNDISInterfaceInfo
->State
.RequestID
++;
312 SetMessageData
.SetMessage
.Oid
= Oid
;
313 SetMessageData
.SetMessage
.InformationBufferLength
= Length
;
314 SetMessageData
.SetMessage
.InformationBufferOffset
= (sizeof(RNDIS_Set_Message_t
) - sizeof(RNDIS_Message_Header_t
));
315 SetMessageData
.SetMessage
.DeviceVcHandle
= 0;
317 memcpy(&SetMessageData
.ContiguousBuffer
, Buffer
, Length
);
319 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &SetMessageData
,
320 SetMessageData
.SetMessage
.MessageLength
)) != HOST_SENDCONTROL_Successful
)
325 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &SetMessageResponse
,
326 sizeof(RNDIS_Set_Complete_t
))) != HOST_SENDCONTROL_Successful
)
331 if (SetMessageResponse
.Status
!= REMOTE_NDIS_STATUS_SUCCESS
)
332 return RNDIS_COMMAND_FAILED
;
334 return HOST_SENDCONTROL_Successful
;
337 uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
,
340 const uint16_t MaxLength
)
344 RNDIS_Query_Message_t QueryMessage
;
348 RNDIS_Query_Complete_t QueryMessageResponse
;
349 uint8_t ContiguousBuffer
[MaxLength
];
350 } QueryMessageResponseData
;
352 QueryMessage
.MessageType
= REMOTE_NDIS_QUERY_MSG
;
353 QueryMessage
.MessageLength
= sizeof(RNDIS_Query_Message_t
);
354 QueryMessage
.RequestId
= RNDISInterfaceInfo
->State
.RequestID
++;
356 QueryMessage
.Oid
= Oid
;
357 QueryMessage
.InformationBufferLength
= 0;
358 QueryMessage
.InformationBufferOffset
= 0;
359 QueryMessage
.DeviceVcHandle
= 0;
361 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &QueryMessage
,
362 sizeof(RNDIS_Query_Message_t
))) != HOST_SENDCONTROL_Successful
)
367 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &QueryMessageResponseData
,
368 sizeof(QueryMessageResponseData
))) != HOST_SENDCONTROL_Successful
)
373 if (QueryMessageResponseData
.QueryMessageResponse
.Status
!= REMOTE_NDIS_STATUS_SUCCESS
)
374 return RNDIS_COMMAND_FAILED
;
376 memcpy(Buffer
, &QueryMessageResponseData
.ContiguousBuffer
, MaxLength
);
378 return HOST_SENDCONTROL_Successful
;
381 bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
)
385 if ((USB_HostState
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
))
388 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
);
391 PacketWaiting
= Pipe_IsINReceived();
394 return PacketWaiting
;
397 uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
,
399 uint16_t* const PacketLength
)
403 if ((USB_HostState
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
))
404 return PIPE_READYWAIT_DeviceDisconnected
;
406 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
);
409 if (!(Pipe_IsReadWriteAllowed()))
411 if (Pipe_IsINReceived())
416 return PIPE_RWSTREAM_NoError
;
419 RNDIS_Packet_Message_t DeviceMessage
;
421 if ((ErrorCode
= Pipe_Read_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
),
422 NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
)
427 *PacketLength
= (uint16_t)DeviceMessage
.DataLength
;
429 Pipe_Discard_Stream(DeviceMessage
.DataOffset
- (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
)),
432 Pipe_Read_Stream_LE(Buffer
, *PacketLength
, NO_STREAM_CALLBACK
);
434 if (!(Pipe_BytesInPipe()))
439 return PIPE_RWSTREAM_NoError
;
442 uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
,
444 const uint16_t PacketLength
)
448 if ((USB_HostState
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
))
449 return PIPE_READYWAIT_DeviceDisconnected
;
451 RNDIS_Packet_Message_t DeviceMessage
;
453 memset(&DeviceMessage
, 0, sizeof(RNDIS_Packet_Message_t
));
454 DeviceMessage
.MessageType
= REMOTE_NDIS_PACKET_MSG
;
455 DeviceMessage
.MessageLength
= (sizeof(RNDIS_Packet_Message_t
) + PacketLength
);
456 DeviceMessage
.DataOffset
= (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
));
457 DeviceMessage
.DataLength
= PacketLength
;
459 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataOUTPipeNumber
);
462 if ((ErrorCode
= Pipe_Write_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
),
463 NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
)
468 Pipe_Write_Stream_LE(Buffer
, PacketLength
, NO_STREAM_CALLBACK
);
473 return PIPE_RWSTREAM_NoError
;