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 #include "../../HighLevel/USBMode.h"
32 #if defined(USB_CAN_BE_HOST)
34 #define INCLUDE_FROM_RNDIS_CLASS_HOST_C
37 uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, uint16_t ConfigDescriptorSize
,
38 void* ConfigDescriptorData
)
40 uint8_t FoundEndpoints
= 0;
42 memset(&RNDISInterfaceInfo
->State
, 0x00, sizeof(RNDISInterfaceInfo
->State
));
44 if (DESCRIPTOR_TYPE(ConfigDescriptorData
) != DTYPE_Configuration
)
45 return RNDIS_ENUMERROR_InvalidConfigDescriptor
;
47 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
48 DComp_RNDIS_Host_NextRNDISControlInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
50 return RNDIS_ENUMERROR_NoRNDISInterfaceFound
;
53 RNDISInterfaceInfo
->State
.ControlInterfaceNumber
= DESCRIPTOR_CAST(ConfigDescriptorData
, USB_Descriptor_Interface_t
).InterfaceNumber
;
55 while (FoundEndpoints
!= (RNDIS_FOUND_NOTIFICATION_IN
| RNDIS_FOUND_DATAPIPE_IN
| RNDIS_FOUND_DATAPIPE_OUT
))
57 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
58 DComp_RNDIS_Host_NextRNDISInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
)
60 if (FoundEndpoints
& RNDIS_FOUND_NOTIFICATION_IN
)
62 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
63 DComp_RNDIS_Host_NextRNDISDataInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
65 return RNDIS_ENUMERROR_NoRNDISInterfaceFound
;
72 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
);
74 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataOUTPipeNumber
);
76 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.NotificationPipeNumber
);
79 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
80 DComp_RNDIS_Host_NextRNDISControlInterface
) != DESCRIPTOR_SEARCH_COMP_Found
)
82 return RNDIS_ENUMERROR_NoRNDISInterfaceFound
;
86 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize
, &ConfigDescriptorData
,
87 DComp_RNDIS_Host_NextRNDISInterfaceEndpoint
) != DESCRIPTOR_SEARCH_COMP_Found
)
89 return RNDIS_ENUMERROR_EndpointsNotFound
;
93 USB_Descriptor_Endpoint_t
* EndpointData
= DESCRIPTOR_PCAST(ConfigDescriptorData
, USB_Descriptor_Endpoint_t
);
95 if ((EndpointData
->Attributes
& EP_TYPE_MASK
) == EP_TYPE_INTERRUPT
)
97 if (EndpointData
->EndpointAddress
& ENDPOINT_DESCRIPTOR_DIR_IN
)
99 Pipe_ConfigurePipe(RNDISInterfaceInfo
->Config
.NotificationPipeNumber
, EP_TYPE_INTERRUPT
, PIPE_TOKEN_IN
,
100 EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
,
101 RNDISInterfaceInfo
->Config
.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE
: PIPE_BANK_SINGLE
);
102 RNDISInterfaceInfo
->State
.NotificationPipeSize
= EndpointData
->EndpointSize
;
104 Pipe_SetInterruptPeriod(EndpointData
->PollingIntervalMS
);
106 FoundEndpoints
|= RNDIS_FOUND_NOTIFICATION_IN
;
111 if (EndpointData
->EndpointAddress
& ENDPOINT_DESCRIPTOR_DIR_IN
)
113 Pipe_ConfigurePipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
, EP_TYPE_BULK
, PIPE_TOKEN_IN
,
114 EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
,
115 RNDISInterfaceInfo
->Config
.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE
: PIPE_BANK_SINGLE
);
116 RNDISInterfaceInfo
->State
.DataINPipeSize
= EndpointData
->EndpointSize
;
118 FoundEndpoints
|= RNDIS_FOUND_DATAPIPE_IN
;
122 Pipe_ConfigurePipe(RNDISInterfaceInfo
->Config
.DataOUTPipeNumber
, EP_TYPE_BULK
, PIPE_TOKEN_OUT
,
123 EndpointData
->EndpointAddress
, EndpointData
->EndpointSize
,
124 RNDISInterfaceInfo
->Config
.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE
: PIPE_BANK_SINGLE
);
126 RNDISInterfaceInfo
->State
.DataOUTPipeSize
= EndpointData
->EndpointSize
;
128 FoundEndpoints
|= RNDIS_FOUND_DATAPIPE_OUT
;
133 RNDISInterfaceInfo
->State
.IsActive
= true;
134 return RNDIS_ENUMERROR_NoError
;
137 static uint8_t DComp_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor
)
139 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
141 USB_Descriptor_Interface_t
* CurrentInterface
= DESCRIPTOR_PCAST(CurrentDescriptor
,
142 USB_Descriptor_Interface_t
);
144 if ((CurrentInterface
->Class
== RNDIS_CONTROL_CLASS
) &&
145 (CurrentInterface
->SubClass
== RNDIS_CONTROL_SUBCLASS
) &&
146 (CurrentInterface
->Protocol
== RNDIS_CONTROL_PROTOCOL
))
148 return DESCRIPTOR_SEARCH_Found
;
152 return DESCRIPTOR_SEARCH_NotFound
;
155 static uint8_t DComp_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor
)
157 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
159 USB_Descriptor_Interface_t
* CurrentInterface
= DESCRIPTOR_PCAST(CurrentDescriptor
,
160 USB_Descriptor_Interface_t
);
162 if ((CurrentInterface
->Class
== RNDIS_DATA_CLASS
) &&
163 (CurrentInterface
->SubClass
== RNDIS_DATA_SUBCLASS
) &&
164 (CurrentInterface
->Protocol
== RNDIS_DATA_PROTOCOL
))
166 return DESCRIPTOR_SEARCH_Found
;
170 return DESCRIPTOR_SEARCH_NotFound
;
173 static uint8_t DComp_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor
)
175 if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Endpoint
)
177 USB_Descriptor_Endpoint_t
* CurrentEndpoint
= DESCRIPTOR_PCAST(CurrentDescriptor
,
178 USB_Descriptor_Endpoint_t
);
180 uint8_t EndpointType
= (CurrentEndpoint
->Attributes
& EP_TYPE_MASK
);
182 if ((EndpointType
== EP_TYPE_BULK
) || (EndpointType
== EP_TYPE_INTERRUPT
))
184 return DESCRIPTOR_SEARCH_Found
;
187 else if (DESCRIPTOR_TYPE(CurrentDescriptor
) == DTYPE_Interface
)
189 return DESCRIPTOR_SEARCH_Fail
;
192 return DESCRIPTOR_SEARCH_NotFound
;
195 static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
,
196 void* Buffer
, uint16_t Length
)
198 USB_ControlRequest
= (USB_Request_Header_t
)
200 .bmRequestType
= (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_INTERFACE
),
201 .bRequest
= REQ_SendEncapsulatedCommand
,
203 .wIndex
= RNDISInterfaceInfo
->State
.ControlInterfaceNumber
,
207 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
208 return USB_Host_SendControlRequest(Buffer
);
211 static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
,
212 void* Buffer
, uint16_t Length
)
214 USB_ControlRequest
= (USB_Request_Header_t
)
216 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
),
217 .bRequest
= REQ_GetEncapsulatedResponse
,
219 .wIndex
= RNDISInterfaceInfo
->State
.ControlInterfaceNumber
,
223 Pipe_SelectPipe(PIPE_CONTROLPIPE
);
224 return USB_Host_SendControlRequest(Buffer
);
227 uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
)
231 RNDIS_KeepAlive_Message_t KeepAliveMessage
;
232 RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse
;
234 KeepAliveMessage
.MessageType
= REMOTE_NDIS_KEEPALIVE_MSG
;
235 KeepAliveMessage
.MessageLength
= sizeof(RNDIS_KeepAlive_Message_t
);
236 KeepAliveMessage
.RequestId
= RNDISInterfaceInfo
->State
.RequestID
++;
238 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &KeepAliveMessage
,
239 sizeof(RNDIS_KeepAlive_Message_t
))) != HOST_SENDCONTROL_Successful
)
244 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &KeepAliveMessageResponse
,
245 sizeof(RNDIS_KeepAlive_Complete_t
))) != HOST_SENDCONTROL_Successful
)
250 return HOST_SENDCONTROL_Successful
;
253 uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
)
257 RNDIS_Initialize_Message_t InitMessage
;
258 RNDIS_Initialize_Complete_t InitMessageResponse
;
260 InitMessage
.MessageType
= REMOTE_NDIS_INITIALIZE_MSG
;
261 InitMessage
.MessageLength
= sizeof(RNDIS_Initialize_Message_t
);
262 InitMessage
.RequestId
= RNDISInterfaceInfo
->State
.RequestID
++;
264 InitMessage
.MajorVersion
= REMOTE_NDIS_VERSION_MAJOR
;
265 InitMessage
.MinorVersion
= REMOTE_NDIS_VERSION_MINOR
;
266 InitMessage
.MaxTransferSize
= RNDISInterfaceInfo
->Config
.HostMaxPacketSize
;
268 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &InitMessage
,
269 sizeof(RNDIS_Initialize_Message_t
))) != HOST_SENDCONTROL_Successful
)
274 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &InitMessageResponse
,
275 sizeof(RNDIS_Initialize_Complete_t
))) != HOST_SENDCONTROL_Successful
)
280 if (InitMessageResponse
.Status
!= REMOTE_NDIS_STATUS_SUCCESS
)
281 return RNDIS_COMMAND_FAILED
;
283 RNDISInterfaceInfo
->State
.DeviceMaxPacketSize
= InitMessageResponse
.MaxTransferSize
;
285 return HOST_SENDCONTROL_Successful
;
288 uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, uint32_t Oid
, void* Buffer
, uint16_t Length
)
294 RNDIS_Set_Message_t SetMessage
;
295 uint8_t ContigiousBuffer
[Length
];
298 RNDIS_Set_Complete_t SetMessageResponse
;
300 SetMessageData
.SetMessage
.MessageType
= REMOTE_NDIS_SET_MSG
;
301 SetMessageData
.SetMessage
.MessageLength
= sizeof(RNDIS_Set_Message_t
) + Length
;
302 SetMessageData
.SetMessage
.RequestId
= RNDISInterfaceInfo
->State
.RequestID
++;
304 SetMessageData
.SetMessage
.Oid
= Oid
;
305 SetMessageData
.SetMessage
.InformationBufferLength
= Length
;
306 SetMessageData
.SetMessage
.InformationBufferOffset
= (sizeof(RNDIS_Set_Message_t
) - sizeof(RNDIS_Message_Header_t
));
307 SetMessageData
.SetMessage
.DeviceVcHandle
= 0;
309 memcpy(&SetMessageData
.ContigiousBuffer
, Buffer
, Length
);
311 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &SetMessageData
,
312 SetMessageData
.SetMessage
.MessageLength
)) != HOST_SENDCONTROL_Successful
)
317 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &SetMessageResponse
,
318 sizeof(RNDIS_Set_Complete_t
))) != HOST_SENDCONTROL_Successful
)
323 if (SetMessageResponse
.Status
!= REMOTE_NDIS_STATUS_SUCCESS
)
324 return RNDIS_COMMAND_FAILED
;
326 return HOST_SENDCONTROL_Successful
;
329 uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, uint32_t Oid
, void* Buffer
, uint16_t MaxLength
)
333 RNDIS_Query_Message_t QueryMessage
;
337 RNDIS_Query_Complete_t QueryMessageResponse
;
338 uint8_t ContigiousBuffer
[MaxLength
];
339 } QueryMessageResponseData
;
341 QueryMessage
.MessageType
= REMOTE_NDIS_QUERY_MSG
;
342 QueryMessage
.MessageLength
= sizeof(RNDIS_Query_Message_t
);
343 QueryMessage
.RequestId
= RNDISInterfaceInfo
->State
.RequestID
++;
345 QueryMessage
.Oid
= Oid
;
346 QueryMessage
.InformationBufferLength
= 0;
347 QueryMessage
.InformationBufferOffset
= 0;
348 QueryMessage
.DeviceVcHandle
= 0;
350 if ((ErrorCode
= RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo
, &QueryMessage
,
351 sizeof(RNDIS_Query_Message_t
))) != HOST_SENDCONTROL_Successful
)
356 if ((ErrorCode
= RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo
, &QueryMessageResponseData
,
357 sizeof(QueryMessageResponseData
))) != HOST_SENDCONTROL_Successful
)
362 if (QueryMessageResponseData
.QueryMessageResponse
.Status
!= REMOTE_NDIS_STATUS_SUCCESS
)
363 return RNDIS_COMMAND_FAILED
;
365 memcpy(Buffer
, &QueryMessageResponseData
.ContigiousBuffer
, MaxLength
);
367 return HOST_SENDCONTROL_Successful
;
370 bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
)
374 if ((USB_HostState
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
))
377 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
);
378 Pipe_SetPipeToken(PIPE_TOKEN_IN
);
382 PacketWaiting
= (Pipe_IsINReceived() && Pipe_BytesInPipe());
386 return PacketWaiting
;
389 uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, void* Buffer
, uint16_t* PacketLength
)
393 if ((USB_HostState
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
))
394 return PIPE_READYWAIT_DeviceDisconnected
;
396 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataINPipeNumber
);
397 Pipe_SetPipeToken(PIPE_TOKEN_IN
);
400 if (!(Pipe_IsReadWriteAllowed()))
402 if (Pipe_IsINReceived())
407 return PIPE_RWSTREAM_NoError
;
410 RNDIS_Packet_Message_t DeviceMessage
;
412 if ((ErrorCode
= Pipe_Read_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
),
413 NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
)
418 *PacketLength
= (uint16_t)DeviceMessage
.DataLength
;
420 Pipe_Discard_Stream(DeviceMessage
.DataOffset
- (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
)),
423 Pipe_Read_Stream_LE(Buffer
, *PacketLength
, NO_STREAM_CALLBACK
);
425 if (!(Pipe_BytesInPipe()))
430 return PIPE_RWSTREAM_NoError
;
433 uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t
* const RNDISInterfaceInfo
, void* Buffer
, uint16_t PacketLength
)
437 if ((USB_HostState
!= HOST_STATE_Configured
) || !(RNDISInterfaceInfo
->State
.IsActive
))
438 return PIPE_READYWAIT_DeviceDisconnected
;
440 RNDIS_Packet_Message_t DeviceMessage
;
442 memset(&DeviceMessage
, 0, sizeof(RNDIS_Packet_Message_t
));
443 DeviceMessage
.MessageType
= REMOTE_NDIS_PACKET_MSG
;
444 DeviceMessage
.MessageLength
= (sizeof(RNDIS_Packet_Message_t
) + PacketLength
);
445 DeviceMessage
.DataOffset
= (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
));
446 DeviceMessage
.DataLength
= PacketLength
;
448 Pipe_SelectPipe(RNDISInterfaceInfo
->Config
.DataOUTPipeNumber
);
451 if ((ErrorCode
= Pipe_Write_Stream_LE(&DeviceMessage
, sizeof(RNDIS_Packet_Message_t
),
452 NO_STREAM_CALLBACK
)) != PIPE_RWSTREAM_NoError
)
457 Pipe_Write_Stream_LE(Buffer
, PacketLength
, NO_STREAM_CALLBACK
);
462 return PIPE_RWSTREAM_NoError
;