3 Copyright (C) Dean Camera, 2011.
5 dean [at] fourwalledcubicle [dot] com
10 Copyright 2011 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 "../../Core/USBMode.h"
34 #if defined(USB_CAN_BE_DEVICE)
36 #define __INCLUDE_FROM_RNDIS_DRIVER
37 #define __INCLUDE_FROM_RNDIS_DEVICE_C
40 static const uint32_t PROGMEM AdapterSupportedOIDList
[] =
42 OID_GEN_SUPPORTED_LIST
,
43 OID_GEN_PHYSICAL_MEDIUM
,
44 OID_GEN_HARDWARE_STATUS
,
45 OID_GEN_MEDIA_SUPPORTED
,
47 OID_GEN_MAXIMUM_FRAME_SIZE
,
48 OID_GEN_MAXIMUM_TOTAL_SIZE
,
50 OID_GEN_TRANSMIT_BLOCK_SIZE
,
51 OID_GEN_RECEIVE_BLOCK_SIZE
,
53 OID_GEN_VENDOR_DESCRIPTION
,
54 OID_GEN_CURRENT_PACKET_FILTER
,
55 OID_GEN_MAXIMUM_TOTAL_SIZE
,
56 OID_GEN_MEDIA_CONNECT_STATUS
,
61 OID_GEN_RCV_NO_BUFFER
,
62 OID_802_3_PERMANENT_ADDRESS
,
63 OID_802_3_CURRENT_ADDRESS
,
64 OID_802_3_MULTICAST_LIST
,
65 OID_802_3_MAXIMUM_LIST_SIZE
,
66 OID_802_3_RCV_ERROR_ALIGNMENT
,
67 OID_802_3_XMIT_ONE_COLLISION
,
68 OID_802_3_XMIT_MORE_COLLISIONS
,
71 void RNDIS_Device_ProcessControlRequest(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
73 if (!(Endpoint_IsSETUPReceived()))
76 if (USB_ControlRequest
.wIndex
!= RNDISInterfaceInfo
->Config
.ControlInterfaceNumber
)
79 switch (USB_ControlRequest
.bRequest
)
81 case RNDIS_REQ_SendEncapsulatedCommand
:
82 if (USB_ControlRequest
.bmRequestType
== (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_INTERFACE
))
84 Endpoint_ClearSETUP();
85 Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo
->State
.RNDISMessageBuffer
, USB_ControlRequest
.wLength
);
88 RNDIS_Device_ProcessRNDISControlMessage(RNDISInterfaceInfo
);
92 case RNDIS_REQ_GetEncapsulatedResponse
:
93 if (USB_ControlRequest
.bmRequestType
== (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
))
95 RNDIS_Message_Header_t
* MessageHeader
= (RNDIS_Message_Header_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
97 if (!(MessageHeader
->MessageLength
))
99 RNDISInterfaceInfo
->State
.RNDISMessageBuffer
[0] = 0;
100 MessageHeader
->MessageLength
= 1;
103 Endpoint_ClearSETUP();
104 Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo
->State
.RNDISMessageBuffer
, MessageHeader
->MessageLength
);
107 MessageHeader
->MessageLength
= 0;
114 bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
116 memset(&RNDISInterfaceInfo
->State
, 0x00, sizeof(RNDISInterfaceInfo
->State
));
118 for (uint8_t EndpointNum
= 1; EndpointNum
< ENDPOINT_TOTAL_ENDPOINTS
; EndpointNum
++)
125 if (EndpointNum
== RNDISInterfaceInfo
->Config
.DataINEndpointNumber
)
127 Size
= RNDISInterfaceInfo
->Config
.DataINEndpointSize
;
128 Direction
= ENDPOINT_DIR_IN
;
130 DoubleBanked
= RNDISInterfaceInfo
->Config
.DataINEndpointDoubleBank
;
132 else if (EndpointNum
== RNDISInterfaceInfo
->Config
.DataOUTEndpointNumber
)
134 Size
= RNDISInterfaceInfo
->Config
.DataOUTEndpointSize
;
135 Direction
= ENDPOINT_DIR_OUT
;
137 DoubleBanked
= RNDISInterfaceInfo
->Config
.DataOUTEndpointDoubleBank
;
139 else if (EndpointNum
== RNDISInterfaceInfo
->Config
.NotificationEndpointNumber
)
141 Size
= RNDISInterfaceInfo
->Config
.NotificationEndpointSize
;
142 Direction
= ENDPOINT_DIR_IN
;
143 Type
= EP_TYPE_INTERRUPT
;
144 DoubleBanked
= RNDISInterfaceInfo
->Config
.NotificationEndpointDoubleBank
;
151 if (!(Endpoint_ConfigureEndpoint(EndpointNum
, Type
, Direction
, Size
,
152 DoubleBanked ? ENDPOINT_BANK_DOUBLE
: ENDPOINT_BANK_SINGLE
)))
161 void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
163 if (USB_DeviceState
!= DEVICE_STATE_Configured
)
166 Endpoint_SelectEndpoint(RNDISInterfaceInfo
->Config
.NotificationEndpointNumber
);
168 if (Endpoint_IsINReady() && RNDISInterfaceInfo
->State
.ResponseReady
)
170 USB_Request_Header_t Notification
= (USB_Request_Header_t
)
172 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
),
173 .bRequest
= RNDIS_NOTIF_ResponseAvailable
,
179 Endpoint_Write_Stream_LE(&Notification
, sizeof(USB_Request_Header_t
), NULL
);
183 RNDISInterfaceInfo
->State
.ResponseReady
= false;
187 void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
189 /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of
190 this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */
192 RNDIS_Message_Header_t
* MessageHeader
= (RNDIS_Message_Header_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
194 switch (MessageHeader
->MessageType
)
196 case REMOTE_NDIS_INITIALIZE_MSG
:
197 RNDISInterfaceInfo
->State
.ResponseReady
= true;
199 RNDIS_Initialize_Message_t
* INITIALIZE_Message
=
200 (RNDIS_Initialize_Message_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
201 RNDIS_Initialize_Complete_t
* INITIALIZE_Response
=
202 (RNDIS_Initialize_Complete_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
204 INITIALIZE_Response
->MessageType
= REMOTE_NDIS_INITIALIZE_CMPLT
;
205 INITIALIZE_Response
->MessageLength
= sizeof(RNDIS_Initialize_Complete_t
);
206 INITIALIZE_Response
->RequestId
= INITIALIZE_Message
->RequestId
;
207 INITIALIZE_Response
->Status
= REMOTE_NDIS_STATUS_SUCCESS
;
209 INITIALIZE_Response
->MajorVersion
= REMOTE_NDIS_VERSION_MAJOR
;
210 INITIALIZE_Response
->MinorVersion
= REMOTE_NDIS_VERSION_MINOR
;
211 INITIALIZE_Response
->DeviceFlags
= REMOTE_NDIS_DF_CONNECTIONLESS
;
212 INITIALIZE_Response
->Medium
= REMOTE_NDIS_MEDIUM_802_3
;
213 INITIALIZE_Response
->MaxPacketsPerTransfer
= 1;
214 INITIALIZE_Response
->MaxTransferSize
= (sizeof(RNDIS_Packet_Message_t
) + ETHERNET_FRAME_SIZE_MAX
);
215 INITIALIZE_Response
->PacketAlignmentFactor
= 0;
216 INITIALIZE_Response
->AFListOffset
= 0;
217 INITIALIZE_Response
->AFListSize
= 0;
219 RNDISInterfaceInfo
->State
.CurrRNDISState
= RNDIS_Initialized
;
222 case REMOTE_NDIS_HALT_MSG
:
223 RNDISInterfaceInfo
->State
.ResponseReady
= false;
224 MessageHeader
->MessageLength
= 0;
226 RNDISInterfaceInfo
->State
.CurrRNDISState
= RNDIS_Uninitialized
;
229 case REMOTE_NDIS_QUERY_MSG
:
230 RNDISInterfaceInfo
->State
.ResponseReady
= true;
232 RNDIS_Query_Message_t
* QUERY_Message
= (RNDIS_Query_Message_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
233 RNDIS_Query_Complete_t
* QUERY_Response
= (RNDIS_Query_Complete_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
234 uint32_t Query_Oid
= QUERY_Message
->Oid
;
236 void* QueryData
= &RNDISInterfaceInfo
->State
.RNDISMessageBuffer
[sizeof(RNDIS_Message_Header_t
) +
237 QUERY_Message
->InformationBufferOffset
];
238 void* ResponseData
= &RNDISInterfaceInfo
->State
.RNDISMessageBuffer
[sizeof(RNDIS_Query_Complete_t
)];
239 uint16_t ResponseSize
;
241 QUERY_Response
->MessageType
= REMOTE_NDIS_QUERY_CMPLT
;
242 QUERY_Response
->MessageLength
= sizeof(RNDIS_Query_Complete_t
);
244 if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo
, Query_Oid
, QueryData
, QUERY_Message
->InformationBufferLength
,
245 ResponseData
, &ResponseSize
))
247 QUERY_Response
->Status
= REMOTE_NDIS_STATUS_SUCCESS
;
248 QUERY_Response
->MessageLength
+= ResponseSize
;
250 QUERY_Response
->InformationBufferLength
= ResponseSize
;
251 QUERY_Response
->InformationBufferOffset
= (sizeof(RNDIS_Query_Complete_t
) - sizeof(RNDIS_Message_Header_t
));
255 QUERY_Response
->Status
= REMOTE_NDIS_STATUS_NOT_SUPPORTED
;
257 QUERY_Response
->InformationBufferLength
= 0;
258 QUERY_Response
->InformationBufferOffset
= 0;
262 case REMOTE_NDIS_SET_MSG
:
263 RNDISInterfaceInfo
->State
.ResponseReady
= true;
265 RNDIS_Set_Message_t
* SET_Message
= (RNDIS_Set_Message_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
266 RNDIS_Set_Complete_t
* SET_Response
= (RNDIS_Set_Complete_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
267 uint32_t SET_Oid
= SET_Message
->Oid
;
269 SET_Response
->MessageType
= REMOTE_NDIS_SET_CMPLT
;
270 SET_Response
->MessageLength
= sizeof(RNDIS_Set_Complete_t
);
271 SET_Response
->RequestId
= SET_Message
->RequestId
;
273 void* SetData
= &RNDISInterfaceInfo
->State
.RNDISMessageBuffer
[sizeof(RNDIS_Message_Header_t
) +
274 SET_Message
->InformationBufferOffset
];
276 SET_Response
->Status
= RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo
, SET_Oid
, SetData
,
277 SET_Message
->InformationBufferLength
) ?
278 REMOTE_NDIS_STATUS_SUCCESS
: REMOTE_NDIS_STATUS_NOT_SUPPORTED
;
280 case REMOTE_NDIS_RESET_MSG
:
281 RNDISInterfaceInfo
->State
.ResponseReady
= true;
283 RNDIS_Reset_Complete_t
* RESET_Response
= (RNDIS_Reset_Complete_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
285 RESET_Response
->MessageType
= REMOTE_NDIS_RESET_CMPLT
;
286 RESET_Response
->MessageLength
= sizeof(RNDIS_Reset_Complete_t
);
287 RESET_Response
->Status
= REMOTE_NDIS_STATUS_SUCCESS
;
288 RESET_Response
->AddressingReset
= 0;
291 case REMOTE_NDIS_KEEPALIVE_MSG
:
292 RNDISInterfaceInfo
->State
.ResponseReady
= true;
294 RNDIS_KeepAlive_Message_t
* KEEPALIVE_Message
=
295 (RNDIS_KeepAlive_Message_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
296 RNDIS_KeepAlive_Complete_t
* KEEPALIVE_Response
=
297 (RNDIS_KeepAlive_Complete_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
299 KEEPALIVE_Response
->MessageType
= REMOTE_NDIS_KEEPALIVE_CMPLT
;
300 KEEPALIVE_Response
->MessageLength
= sizeof(RNDIS_KeepAlive_Complete_t
);
301 KEEPALIVE_Response
->RequestId
= KEEPALIVE_Message
->RequestId
;
302 KEEPALIVE_Response
->Status
= REMOTE_NDIS_STATUS_SUCCESS
;
308 static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
,
310 void* const QueryData
,
311 const uint16_t QuerySize
,
313 uint16_t* const ResponseSize
)
320 case OID_GEN_SUPPORTED_LIST
:
321 *ResponseSize
= sizeof(AdapterSupportedOIDList
);
323 memcpy_P(ResponseData
, AdapterSupportedOIDList
, sizeof(AdapterSupportedOIDList
));
326 case OID_GEN_PHYSICAL_MEDIUM
:
327 *ResponseSize
= sizeof(uint32_t);
329 /* Indicate that the device is a true ethernet link */
330 *((uint32_t*)ResponseData
) = 0;
333 case OID_GEN_HARDWARE_STATUS
:
334 *ResponseSize
= sizeof(uint32_t);
336 *((uint32_t*)ResponseData
) = NDIS_HardwareStatus_Ready
;
339 case OID_GEN_MEDIA_SUPPORTED
:
340 case OID_GEN_MEDIA_IN_USE
:
341 *ResponseSize
= sizeof(uint32_t);
343 *((uint32_t*)ResponseData
) = REMOTE_NDIS_MEDIUM_802_3
;
346 case OID_GEN_VENDOR_ID
:
347 *ResponseSize
= sizeof(uint32_t);
349 /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
350 *((uint32_t*)ResponseData
) = 0x00FFFFFF;
353 case OID_GEN_MAXIMUM_FRAME_SIZE
:
354 case OID_GEN_TRANSMIT_BLOCK_SIZE
:
355 case OID_GEN_RECEIVE_BLOCK_SIZE
:
356 *ResponseSize
= sizeof(uint32_t);
358 *((uint32_t*)ResponseData
) = ETHERNET_FRAME_SIZE_MAX
;
361 case OID_GEN_VENDOR_DESCRIPTION
:
362 *ResponseSize
= (strlen(RNDISInterfaceInfo
->Config
.AdapterVendorDescription
) + 1);
364 memcpy(ResponseData
, RNDISInterfaceInfo
->Config
.AdapterVendorDescription
, *ResponseSize
);
367 case OID_GEN_MEDIA_CONNECT_STATUS
:
368 *ResponseSize
= sizeof(uint32_t);
370 *((uint32_t*)ResponseData
) = REMOTE_NDIS_MEDIA_STATE_CONNECTED
;
373 case OID_GEN_LINK_SPEED
:
374 *ResponseSize
= sizeof(uint32_t);
376 /* Indicate 10Mb/s link speed */
377 *((uint32_t*)ResponseData
) = 100000;
380 case OID_802_3_PERMANENT_ADDRESS
:
381 case OID_802_3_CURRENT_ADDRESS
:
382 *ResponseSize
= sizeof(MAC_Address_t
);
384 memcpy(ResponseData
, &RNDISInterfaceInfo
->Config
.AdapterMACAddress
, sizeof(MAC_Address_t
));
387 case OID_802_3_MAXIMUM_LIST_SIZE
:
388 *ResponseSize
= sizeof(uint32_t);
390 /* Indicate only one multicast address supported */
391 *((uint32_t*)ResponseData
) = 1;
394 case OID_GEN_CURRENT_PACKET_FILTER
:
395 *ResponseSize
= sizeof(uint32_t);
397 *((uint32_t*)ResponseData
) = RNDISInterfaceInfo
->State
.CurrPacketFilter
;
400 case OID_GEN_XMIT_OK
:
402 case OID_GEN_XMIT_ERROR
:
403 case OID_GEN_RCV_ERROR
:
404 case OID_GEN_RCV_NO_BUFFER
:
405 case OID_802_3_RCV_ERROR_ALIGNMENT
:
406 case OID_802_3_XMIT_ONE_COLLISION
:
407 case OID_802_3_XMIT_MORE_COLLISIONS
:
408 *ResponseSize
= sizeof(uint32_t);
410 /* Unused statistic OIDs - always return 0 for each */
411 *((uint32_t*)ResponseData
) = 0;
414 case OID_GEN_MAXIMUM_TOTAL_SIZE
:
415 *ResponseSize
= sizeof(uint32_t);
417 /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */
418 *((uint32_t*)ResponseData
) = (RNDIS_MESSAGE_BUFFER_SIZE
+ ETHERNET_FRAME_SIZE_MAX
);
426 static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
,
429 const uint16_t SetSize
)
435 case OID_GEN_CURRENT_PACKET_FILTER
:
436 RNDISInterfaceInfo
->State
.CurrPacketFilter
= *((uint32_t*)SetData
);
437 RNDISInterfaceInfo
->State
.CurrRNDISState
= ((RNDISInterfaceInfo
->State
.CurrPacketFilter
) ?
438 RNDIS_Data_Initialized
: RNDIS_Data_Initialized
);
441 case OID_802_3_MULTICAST_LIST
:
442 /* Do nothing - throw away the value from the host as it is unused */
450 bool RNDIS_Device_IsPacketReceived(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
452 if ((USB_DeviceState
!= DEVICE_STATE_Configured
) ||
453 (RNDISInterfaceInfo
->State
.CurrRNDISState
!= RNDIS_Data_Initialized
))
458 Endpoint_SelectEndpoint(RNDISInterfaceInfo
->Config
.DataOUTEndpointNumber
);
459 return Endpoint_IsOUTReceived();
462 uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
,
464 uint16_t* const PacketLength
)
466 if ((USB_DeviceState
!= DEVICE_STATE_Configured
) ||
467 (RNDISInterfaceInfo
->State
.CurrRNDISState
!= RNDIS_Data_Initialized
))
469 return ENDPOINT_RWSTREAM_DeviceDisconnected
;
472 Endpoint_SelectEndpoint(RNDISInterfaceInfo
->Config
.DataOUTEndpointNumber
);
476 if (!(Endpoint_IsOUTReceived()))
477 return ENDPOINT_RWSTREAM_NoError
;
479 RNDIS_Packet_Message_t RNDISPacketHeader
;
480 Endpoint_Read_Stream_LE(&RNDISPacketHeader
, sizeof(RNDIS_Packet_Message_t
), NULL
);
482 if (RNDISPacketHeader
.DataLength
> ETHERNET_FRAME_SIZE_MAX
)
484 Endpoint_StallTransaction();
486 return RNDIS_ERROR_LOGICAL_CMD_FAILED
;
489 *PacketLength
= (uint16_t)RNDISPacketHeader
.DataLength
;
491 Endpoint_Read_Stream_LE(Buffer
, RNDISPacketHeader
.DataLength
, NULL
);
494 return ENDPOINT_RWSTREAM_NoError
;
497 uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
,
499 const uint16_t PacketLength
)
503 if ((USB_DeviceState
!= DEVICE_STATE_Configured
) ||
504 (RNDISInterfaceInfo
->State
.CurrRNDISState
!= RNDIS_Data_Initialized
))
506 return ENDPOINT_RWSTREAM_DeviceDisconnected
;
509 Endpoint_SelectEndpoint(RNDISInterfaceInfo
->Config
.DataINEndpointNumber
);
511 if ((ErrorCode
= Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError
)
514 RNDIS_Packet_Message_t RNDISPacketHeader
;
516 memset(&RNDISPacketHeader
, 0, sizeof(RNDIS_Packet_Message_t
));
518 RNDISPacketHeader
.MessageType
= REMOTE_NDIS_PACKET_MSG
;
519 RNDISPacketHeader
.MessageLength
= (sizeof(RNDIS_Packet_Message_t
) + PacketLength
);
520 RNDISPacketHeader
.DataOffset
= (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
));
521 RNDISPacketHeader
.DataLength
= PacketLength
;
523 Endpoint_Write_Stream_LE(&RNDISPacketHeader
, sizeof(RNDIS_Packet_Message_t
), NULL
);
524 Endpoint_Write_Stream_LE(Buffer
, PacketLength
, NULL
);
527 return ENDPOINT_RWSTREAM_NoError
;