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
);
127 RNDISInterfaceInfo
->State
.DataOUTPipeSize
= EndpointData
->EndpointSize
;
129 FoundEndpoints
|= RNDIS_FOUND_DATAPIPE_OUT
;
134 RNDISInterfaceInfo
->State
.IsActive
= true;
135 return RNDIS_ENUMERROR_NoError
;
138 static uint8_t DCOMP_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor
)
140 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
142 USB_Descriptor_Interface_t
* CurrentInterface
= DESCRIPTOR_PCAST(CurrentDescriptor
,
143 USB_Descriptor_Interface_t
);
145 if ((CurrentInterface
->Class
== RNDIS_CONTROL_CLASS
) &&
146 (CurrentInterface
->SubClass
== RNDIS_CONTROL_SUBCLASS
) &&
147 (CurrentInterface
->Protocol
== RNDIS_CONTROL_PROTOCOL
))
149 return DESCRIPTOR_SEARCH_Found
;
153 return DESCRIPTOR_SEARCH_NotFound
;
156 static uint8_t DCOMP_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor
)
158 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
160 USB_Descriptor_Interface_t
* CurrentInterface
= DESCRIPTOR_PCAST(CurrentDescriptor
,
161 USB_Descriptor_Interface_t
);
163 if ((CurrentInterface
->Class
== RNDIS_DATA_CLASS
) &&
164 (CurrentInterface
->SubClass
== RNDIS_DATA_SUBCLASS
) &&
165 (CurrentInterface
->Protocol
== RNDIS_DATA_PROTOCOL
))
167 return DESCRIPTOR_SEARCH_Found
;
171 return DESCRIPTOR_SEARCH_NotFound
;
174 static uint8_t DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor
)
176 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Endpoint
)
178 USB_Descriptor_Endpoint_t
* CurrentEndpoint
= DESCRIPTOR_PCAST(CurrentDescriptor
,
179 USB_Descriptor_Endpoint_t
);
181 uint8_t EndpointType
= (CurrentEndpoint
->Attributes
& EP_TYPE_MASK
);
183 if (((EndpointType
== EP_TYPE_BULK
) || (EndpointType
== EP_TYPE_INTERRUPT
)) &&
184 !(Pipe_IsEndpointBound(CurrentEndpoint
->EndpointAddress
)))
186 return DESCRIPTOR_SEARCH_Found
;
189 else if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
191 return DESCRIPTOR_SEARCH_Fail
;
194 return DESCRIPTOR_SEARCH_NotFound
;
197 static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
,
198 void* Buffer
, uint16_t Length
)
200 USB_ControlRequest
= (USB_Request_Header_t
)
202 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_INTERFACE
),
203 .bRequest
= REQ_SendEncapsulatedCommand
,
205 .wIndex
= RNDISInterfaceInfo
->State
.ControlInterfaceNumber
,
209 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
210 return USB_Host_SendControlRequest(Buffer
);
213 static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
,
214 void* Buffer
, uint16_t Length
)
216 USB_ControlRequest
= (USB_Request_Header_t
)
218 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
),
219 .bRequest
= REQ_GetEncapsulatedResponse
,
221 .wIndex
= RNDISInterfaceInfo
->State
.ControlInterfaceNumber
,
225 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
226 return USB_Host_SendControlRequest(Buffer
);
229 uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
)
233 RNDIS_KeepAlive_Message_t KeepAliveMessage
;
234 RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse
;
236 KeepAliveMessage
.MessageType
= REMOTE_NDIS_KEEPALIVE_MSG
;
237 KeepAliveMessage
.MessageLength
= sizeof(RNDIS_KeepAlive_Message_t
);
238 KeepAliveMessage
.RequestId
= RNDISInterfaceInfo
->State
.RequestID
++;
240 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &KeepAliveMessage
,
241 sizeof(RNDIS_KeepAlive_Message_t
))) != HOST_SENDCONTROL_Successful
)
246 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &KeepAliveMessageResponse
,
247 sizeof(RNDIS_KeepAlive_Complete_t
))) != HOST_SENDCONTROL_Successful
)
252 return HOST_SENDCONTROL_Successful
;
255 uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
)
259 RNDIS_Initialize_Message_t InitMessage
;
260 RNDIS_Initialize_Complete_t InitMessageResponse
;
262 InitMessage
.MessageType
= REMOTE_NDIS_INITIALIZE_MSG
;
263 InitMessage
.MessageLength
= sizeof(RNDIS_Initialize_Message_t
);
264 InitMessage
.RequestId
= RNDISInterfaceInfo
->State
.RequestID
++;
266 InitMessage
.MajorVersion
= REMOTE_NDIS_VERSION_MAJOR
;
267 InitMessage
.MinorVersion
= REMOTE_NDIS_VERSION_MINOR
;
268 InitMessage
.MaxTransferSize
= RNDISInterfaceInfo
->Config
.HostMaxPacketSize
;
270 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &InitMessage
,
271 sizeof(RNDIS_Initialize_Message_t
))) != HOST_SENDCONTROL_Successful
)
276 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &InitMessageResponse
,
277 sizeof(RNDIS_Initialize_Complete_t
))) != HOST_SENDCONTROL_Successful
)
282 if (InitMessageResponse
.Status
!= REMOTE_NDIS_STATUS_SUCCESS
)
283 return RNDIS_COMMAND_FAILED
;
285 RNDISInterfaceInfo
->State
.DeviceMaxPacketSize
= InitMessageResponse
.MaxTransferSize
;
287 return HOST_SENDCONTROL_Successful
;
290 uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, uint32_t Oid
, void* Buffer
, uint16_t Length
)
296 RNDIS_Set_Message_t SetMessage
;
297 uint8_t ContigiousBuffer
[Length
];
300 RNDIS_Set_Complete_t SetMessageResponse
;
302 SetMessageData
.SetMessage
.MessageType
= REMOTE_NDIS_SET_MSG
;
303 SetMessageData
.SetMessage
.MessageLength
= sizeof(RNDIS_Set_Message_t
) + Length
;
304 SetMessageData
.SetMessage
.RequestId
= RNDISInterfaceInfo
->State
.RequestID
++;
306 SetMessageData
.SetMessage
.Oid
= Oid
;
307 SetMessageData
.SetMessage
.InformationBufferLength
= Length
;
308 SetMessageData
.SetMessage
.InformationBufferOffset
= (sizeof(RNDIS_Set_Message_t
) - sizeof(RNDIS_Message_Header_t
));
309 SetMessageData
.SetMessage
.DeviceVcHandle
= 0;
311 memcpy(&SetMessageData
.ContigiousBuffer
, Buffer
, Length
);
313 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &SetMessageData
,
314 SetMessageData
.SetMessage
.MessageLength
)) != HOST_SENDCONTROL_Successful
)
319 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &SetMessageResponse
,
320 sizeof(RNDIS_Set_Complete_t
))) != HOST_SENDCONTROL_Successful
)
325 if (SetMessageResponse
.Status
!= REMOTE_NDIS_STATUS_SUCCESS
)
326 return RNDIS_COMMAND_FAILED
;
328 return HOST_SENDCONTROL_Successful
;
331 uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, uint32_t Oid
, void* Buffer
, uint16_t MaxLength
)
335 RNDIS_Query_Message_t QueryMessage
;
339 RNDIS_Query_Complete_t QueryMessageResponse
;
340 uint8_t ContigiousBuffer
[MaxLength
];
341 } QueryMessageResponseData
;
343 QueryMessage
.MessageType
= REMOTE_NDIS_QUERY_MSG
;
344 QueryMessage
.MessageLength
= sizeof(RNDIS_Query_Message_t
);
345 QueryMessage
.RequestId
= RNDISInterfaceInfo
->State
.RequestID
++;
347 QueryMessage
.Oid
= Oid
;
348 QueryMessage
.InformationBufferLength
= 0;
349 QueryMessage
.InformationBufferOffset
= 0;
350 QueryMessage
.DeviceVcHandle
= 0;
352 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &QueryMessage
,
353 sizeof(RNDIS_Query_Message_t
))) != HOST_SENDCONTROL_Successful
)
358 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &QueryMessageResponseData
,
359 sizeof(QueryMessageResponseData
))) != HOST_SENDCONTROL_Successful
)
364 if (QueryMessageResponseData
.QueryMessageResponse
.Status
!= REMOTE_NDIS_STATUS_SUCCESS
)
365 return RNDIS_COMMAND_FAILED
;
367 memcpy(Buffer
, &QueryMessageResponseData
.ContigiousBuffer
, MaxLength
);
369 return HOST_SENDCONTROL_Successful
;
372 bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
)
376 if ((USB_HostState
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
))
379 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
);
380 Pipe_SetPipeToken(PIPE_TOKEN_IN
);
384 PacketWaiting
= Pipe_IsINReceived();
388 return PacketWaiting
;
391 uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, void* Buffer
, uint16_t* PacketLength
)
395 if ((USB_HostState
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
))
396 return PIPE_READYWAIT_DeviceDisconnected
;
398 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
);
399 Pipe_SetPipeToken(PIPE_TOKEN_IN
);
402 if (!(Pipe_IsReadWriteAllowed()))
404 if (Pipe_IsINReceived())
409 return PIPE_RWSTREAM_NoError
;
412 RNDIS_Packet_Message_t DeviceMessage
;
414 if ((ErrorCode
= Pipe_Read_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
),
415 NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
)
420 *PacketLength
= (uint16_t)DeviceMessage
.DataLength
;
422 Pipe_Discard_Stream(DeviceMessage
.DataOffset
- (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
)),
425 Pipe_Read_Stream_LE(Buffer
, *PacketLength
, NO_STREAM_CALLBACK
);
427 if (!(Pipe_BytesInPipe()))
432 return PIPE_RWSTREAM_NoError
;
435 uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, void* Buffer
, uint16_t PacketLength
)
439 if ((USB_HostState
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
))
440 return PIPE_READYWAIT_DeviceDisconnected
;
442 RNDIS_Packet_Message_t DeviceMessage
;
444 memset(&DeviceMessage
, 0, sizeof(RNDIS_Packet_Message_t
));
445 DeviceMessage
.MessageType
= REMOTE_NDIS_PACKET_MSG
;
446 DeviceMessage
.MessageLength
= (sizeof(RNDIS_Packet_Message_t
) + PacketLength
);
447 DeviceMessage
.DataOffset
= (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
));
448 DeviceMessage
.DataLength
= PacketLength
;
450 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataOUTPipeNumber
);
453 if ((ErrorCode
= Pipe_Write_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
),
454 NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
)
459 Pipe_Write_Stream_LE(Buffer
, PacketLength
, NO_STREAM_CALLBACK
);
464 return PIPE_RWSTREAM_NoError
;