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_DEVICE)
35 #define __INCLUDE_FROM_RNDIS_CLASS_DEVICE_C
36 #define __INCLUDE_FROM_RNDIS_DRIVER
39 static const uint32_t PROGMEM AdapterSupportedOIDList
[] =
41 OID_GEN_SUPPORTED_LIST
,
42 OID_GEN_PHYSICAL_MEDIUM
,
43 OID_GEN_HARDWARE_STATUS
,
44 OID_GEN_MEDIA_SUPPORTED
,
46 OID_GEN_MAXIMUM_FRAME_SIZE
,
47 OID_GEN_MAXIMUM_TOTAL_SIZE
,
49 OID_GEN_TRANSMIT_BLOCK_SIZE
,
50 OID_GEN_RECEIVE_BLOCK_SIZE
,
52 OID_GEN_VENDOR_DESCRIPTION
,
53 OID_GEN_CURRENT_PACKET_FILTER
,
54 OID_GEN_MAXIMUM_TOTAL_SIZE
,
55 OID_GEN_MEDIA_CONNECT_STATUS
,
60 OID_GEN_RCV_NO_BUFFER
,
61 OID_802_3_PERMANENT_ADDRESS
,
62 OID_802_3_CURRENT_ADDRESS
,
63 OID_802_3_MULTICAST_LIST
,
64 OID_802_3_MAXIMUM_LIST_SIZE
,
65 OID_802_3_RCV_ERROR_ALIGNMENT
,
66 OID_802_3_XMIT_ONE_COLLISION
,
67 OID_802_3_XMIT_MORE_COLLISIONS
,
70 void RNDIS_Device_ProcessControlRequest(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
72 if (!(Endpoint_IsSETUPReceived()))
75 if (USB_ControlRequest
.wIndex
!= RNDISInterfaceInfo
->Config
.ControlInterfaceNumber
)
78 switch (USB_ControlRequest
.bRequest
)
80 case REQ_SendEncapsulatedCommand
:
81 if (USB_ControlRequest
.bmRequestType
== (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_INTERFACE
))
83 Endpoint_ClearSETUP();
84 Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo
->State
.RNDISMessageBuffer
, USB_ControlRequest
.wLength
);
87 RNDIS_Device_ProcessRNDISControlMessage(RNDISInterfaceInfo
);
91 case REQ_GetEncapsulatedResponse
:
92 if (USB_ControlRequest
.bmRequestType
== (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
))
94 RNDIS_Message_Header_t
* MessageHeader
= (RNDIS_Message_Header_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
96 if (!(MessageHeader
->MessageLength
))
98 RNDISInterfaceInfo
->State
.RNDISMessageBuffer
[0] = 0;
99 MessageHeader
->MessageLength
= 1;
102 Endpoint_ClearSETUP();
103 Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo
->State
.RNDISMessageBuffer
, MessageHeader
->MessageLength
);
106 MessageHeader
->MessageLength
= 0;
113 bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
115 memset(&RNDISInterfaceInfo
->State
, 0x00, sizeof(RNDISInterfaceInfo
->State
));
117 if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo
->Config
.DataINEndpointNumber
, EP_TYPE_BULK
,
118 ENDPOINT_DIR_IN
, RNDISInterfaceInfo
->Config
.DataINEndpointSize
,
119 RNDISInterfaceInfo
->Config
.DataINEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE
: ENDPOINT_BANK_SINGLE
)))
124 if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo
->Config
.DataOUTEndpointNumber
, EP_TYPE_BULK
,
125 ENDPOINT_DIR_OUT
, RNDISInterfaceInfo
->Config
.DataOUTEndpointSize
,
126 RNDISInterfaceInfo
->Config
.DataOUTEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE
: ENDPOINT_BANK_SINGLE
)))
131 if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo
->Config
.NotificationEndpointNumber
, EP_TYPE_INTERRUPT
,
132 ENDPOINT_DIR_IN
, RNDISInterfaceInfo
->Config
.NotificationEndpointSize
,
133 RNDISInterfaceInfo
->Config
.NotificationEndpointDoubleBank ? ENDPOINT_BANK_DOUBLE
: ENDPOINT_BANK_SINGLE
)))
141 void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
143 if (USB_DeviceState
!= DEVICE_STATE_Configured
)
146 RNDIS_Message_Header_t
* MessageHeader
= (RNDIS_Message_Header_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
148 Endpoint_SelectEndpoint(RNDISInterfaceInfo
->Config
.NotificationEndpointNumber
);
150 if (Endpoint_IsINReady() && RNDISInterfaceInfo
->State
.ResponseReady
)
152 USB_Request_Header_t Notification
= (USB_Request_Header_t
)
154 .bmRequestType
= (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
),
155 .bRequest
= NOTIF_ResponseAvailable
,
161 Endpoint_Write_Stream_LE(&Notification
, sizeof(USB_Request_Header_t
), NO_STREAM_CALLBACK
);
165 RNDISInterfaceInfo
->State
.ResponseReady
= false;
168 if ((RNDISInterfaceInfo
->State
.CurrRNDISState
== RNDIS_Data_Initialized
) && !(MessageHeader
->MessageLength
))
170 RNDIS_Packet_Message_t RNDISPacketHeader
;
172 Endpoint_SelectEndpoint(RNDISInterfaceInfo
->Config
.DataOUTEndpointNumber
);
174 if (Endpoint_IsOUTReceived() && !(RNDISInterfaceInfo
->State
.FrameIN
.FrameInBuffer
))
176 Endpoint_Read_Stream_LE(&RNDISPacketHeader
, sizeof(RNDIS_Packet_Message_t
), NO_STREAM_CALLBACK
);
178 if (RNDISPacketHeader
.DataLength
> ETHERNET_FRAME_SIZE_MAX
)
180 Endpoint_StallTransaction();
184 Endpoint_Read_Stream_LE(RNDISInterfaceInfo
->State
.FrameIN
.FrameData
, RNDISPacketHeader
.DataLength
, NO_STREAM_CALLBACK
);
188 RNDISInterfaceInfo
->State
.FrameIN
.FrameLength
= RNDISPacketHeader
.DataLength
;
190 RNDISInterfaceInfo
->State
.FrameIN
.FrameInBuffer
= true;
193 Endpoint_SelectEndpoint(RNDISInterfaceInfo
->Config
.DataINEndpointNumber
);
195 if (Endpoint_IsINReady() && RNDISInterfaceInfo
->State
.FrameOUT
.FrameInBuffer
)
197 memset(&RNDISPacketHeader
, 0, sizeof(RNDIS_Packet_Message_t
));
199 RNDISPacketHeader
.MessageType
= REMOTE_NDIS_PACKET_MSG
;
200 RNDISPacketHeader
.MessageLength
= (sizeof(RNDIS_Packet_Message_t
) + RNDISInterfaceInfo
->State
.FrameOUT
.FrameLength
);
201 RNDISPacketHeader
.DataOffset
= (sizeof(RNDIS_Packet_Message_t
) - sizeof(RNDIS_Message_Header_t
));
202 RNDISPacketHeader
.DataLength
= RNDISInterfaceInfo
->State
.FrameOUT
.FrameLength
;
204 Endpoint_Write_Stream_LE(&RNDISPacketHeader
, sizeof(RNDIS_Packet_Message_t
), NO_STREAM_CALLBACK
);
205 Endpoint_Write_Stream_LE(RNDISInterfaceInfo
->State
.FrameOUT
.FrameData
, RNDISPacketHeader
.DataLength
, NO_STREAM_CALLBACK
);
208 RNDISInterfaceInfo
->State
.FrameOUT
.FrameInBuffer
= false;
213 void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
)
215 /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of
216 this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */
218 RNDIS_Message_Header_t
* MessageHeader
= (RNDIS_Message_Header_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
220 switch (MessageHeader
->MessageType
)
222 case REMOTE_NDIS_INITIALIZE_MSG
:
223 RNDISInterfaceInfo
->State
.ResponseReady
= true;
225 RNDIS_Initialize_Message_t
* INITIALIZE_Message
=
226 (RNDIS_Initialize_Message_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
227 RNDIS_Initialize_Complete_t
* INITIALIZE_Response
=
228 (RNDIS_Initialize_Complete_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
230 INITIALIZE_Response
->MessageType
= REMOTE_NDIS_INITIALIZE_CMPLT
;
231 INITIALIZE_Response
->MessageLength
= sizeof(RNDIS_Initialize_Complete_t
);
232 INITIALIZE_Response
->RequestId
= INITIALIZE_Message
->RequestId
;
233 INITIALIZE_Response
->Status
= REMOTE_NDIS_STATUS_SUCCESS
;
235 INITIALIZE_Response
->MajorVersion
= REMOTE_NDIS_VERSION_MAJOR
;
236 INITIALIZE_Response
->MinorVersion
= REMOTE_NDIS_VERSION_MINOR
;
237 INITIALIZE_Response
->DeviceFlags
= REMOTE_NDIS_DF_CONNECTIONLESS
;
238 INITIALIZE_Response
->Medium
= REMOTE_NDIS_MEDIUM_802_3
;
239 INITIALIZE_Response
->MaxPacketsPerTransfer
= 1;
240 INITIALIZE_Response
->MaxTransferSize
= (sizeof(RNDIS_Packet_Message_t
) + ETHERNET_FRAME_SIZE_MAX
);
241 INITIALIZE_Response
->PacketAlignmentFactor
= 0;
242 INITIALIZE_Response
->AFListOffset
= 0;
243 INITIALIZE_Response
->AFListSize
= 0;
245 RNDISInterfaceInfo
->State
.CurrRNDISState
= RNDIS_Initialized
;
248 case REMOTE_NDIS_HALT_MSG
:
249 RNDISInterfaceInfo
->State
.ResponseReady
= false;
250 MessageHeader
->MessageLength
= 0;
252 RNDISInterfaceInfo
->State
.CurrRNDISState
= RNDIS_Uninitialized
;
255 case REMOTE_NDIS_QUERY_MSG
:
256 RNDISInterfaceInfo
->State
.ResponseReady
= true;
258 RNDIS_Query_Message_t
* QUERY_Message
= (RNDIS_Query_Message_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
259 RNDIS_Query_Complete_t
* QUERY_Response
= (RNDIS_Query_Complete_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
260 uint32_t Query_Oid
= QUERY_Message
->Oid
;
262 void* QueryData
= &RNDISInterfaceInfo
->State
.RNDISMessageBuffer
[sizeof(RNDIS_Message_Header_t
) +
263 QUERY_Message
->InformationBufferOffset
];
264 void* ResponseData
= &RNDISInterfaceInfo
->State
.RNDISMessageBuffer
[sizeof(RNDIS_Query_Complete_t
)];
265 uint16_t ResponseSize
;
267 QUERY_Response
->MessageType
= REMOTE_NDIS_QUERY_CMPLT
;
268 QUERY_Response
->MessageLength
= sizeof(RNDIS_Query_Complete_t
);
270 if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo
, Query_Oid
, QueryData
, QUERY_Message
->InformationBufferLength
,
271 ResponseData
, &ResponseSize
))
273 QUERY_Response
->Status
= REMOTE_NDIS_STATUS_SUCCESS
;
274 QUERY_Response
->MessageLength
+= ResponseSize
;
276 QUERY_Response
->InformationBufferLength
= ResponseSize
;
277 QUERY_Response
->InformationBufferOffset
= (sizeof(RNDIS_Query_Complete_t
) - sizeof(RNDIS_Message_Header_t
));
281 QUERY_Response
->Status
= REMOTE_NDIS_STATUS_NOT_SUPPORTED
;
283 QUERY_Response
->InformationBufferLength
= 0;
284 QUERY_Response
->InformationBufferOffset
= 0;
288 case REMOTE_NDIS_SET_MSG
:
289 RNDISInterfaceInfo
->State
.ResponseReady
= true;
291 RNDIS_Set_Message_t
* SET_Message
= (RNDIS_Set_Message_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
292 RNDIS_Set_Complete_t
* SET_Response
= (RNDIS_Set_Complete_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
293 uint32_t SET_Oid
= SET_Message
->Oid
;
295 SET_Response
->MessageType
= REMOTE_NDIS_SET_CMPLT
;
296 SET_Response
->MessageLength
= sizeof(RNDIS_Set_Complete_t
);
297 SET_Response
->RequestId
= SET_Message
->RequestId
;
299 void* SetData
= &RNDISInterfaceInfo
->State
.RNDISMessageBuffer
[sizeof(RNDIS_Message_Header_t
) +
300 SET_Message
->InformationBufferOffset
];
302 SET_Response
->Status
= RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo
, SET_Oid
, SetData
,
303 SET_Message
->InformationBufferLength
) ?
304 REMOTE_NDIS_STATUS_SUCCESS
: REMOTE_NDIS_STATUS_NOT_SUPPORTED
;
306 case REMOTE_NDIS_RESET_MSG
:
307 RNDISInterfaceInfo
->State
.ResponseReady
= true;
309 RNDIS_Reset_Complete_t
* RESET_Response
= (RNDIS_Reset_Complete_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
311 RESET_Response
->MessageType
= REMOTE_NDIS_RESET_CMPLT
;
312 RESET_Response
->MessageLength
= sizeof(RNDIS_Reset_Complete_t
);
313 RESET_Response
->Status
= REMOTE_NDIS_STATUS_SUCCESS
;
314 RESET_Response
->AddressingReset
= 0;
317 case REMOTE_NDIS_KEEPALIVE_MSG
:
318 RNDISInterfaceInfo
->State
.ResponseReady
= true;
320 RNDIS_KeepAlive_Message_t
* KEEPALIVE_Message
=
321 (RNDIS_KeepAlive_Message_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
322 RNDIS_KeepAlive_Complete_t
* KEEPALIVE_Response
=
323 (RNDIS_KeepAlive_Complete_t
*)&RNDISInterfaceInfo
->State
.RNDISMessageBuffer
;
325 KEEPALIVE_Response
->MessageType
= REMOTE_NDIS_KEEPALIVE_CMPLT
;
326 KEEPALIVE_Response
->MessageLength
= sizeof(RNDIS_KeepAlive_Complete_t
);
327 KEEPALIVE_Response
->RequestId
= KEEPALIVE_Message
->RequestId
;
328 KEEPALIVE_Response
->Status
= REMOTE_NDIS_STATUS_SUCCESS
;
334 static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
,
336 void* const QueryData
,
337 const uint16_t QuerySize
,
339 uint16_t* const ResponseSize
)
346 case OID_GEN_SUPPORTED_LIST
:
347 *ResponseSize
= sizeof(AdapterSupportedOIDList
);
349 memcpy_P(ResponseData
, AdapterSupportedOIDList
, sizeof(AdapterSupportedOIDList
));
352 case OID_GEN_PHYSICAL_MEDIUM
:
353 *ResponseSize
= sizeof(uint32_t);
355 /* Indicate that the device is a true ethernet link */
356 *((uint32_t*)ResponseData
) = 0;
359 case OID_GEN_HARDWARE_STATUS
:
360 *ResponseSize
= sizeof(uint32_t);
362 *((uint32_t*)ResponseData
) = NDIS_HardwareStatus_Ready
;
365 case OID_GEN_MEDIA_SUPPORTED
:
366 case OID_GEN_MEDIA_IN_USE
:
367 *ResponseSize
= sizeof(uint32_t);
369 *((uint32_t*)ResponseData
) = REMOTE_NDIS_MEDIUM_802_3
;
372 case OID_GEN_VENDOR_ID
:
373 *ResponseSize
= sizeof(uint32_t);
375 /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
376 *((uint32_t*)ResponseData
) = 0x00FFFFFF;
379 case OID_GEN_MAXIMUM_FRAME_SIZE
:
380 case OID_GEN_TRANSMIT_BLOCK_SIZE
:
381 case OID_GEN_RECEIVE_BLOCK_SIZE
:
382 *ResponseSize
= sizeof(uint32_t);
384 *((uint32_t*)ResponseData
) = ETHERNET_FRAME_SIZE_MAX
;
387 case OID_GEN_VENDOR_DESCRIPTION
:
388 *ResponseSize
= (strlen(RNDISInterfaceInfo
->Config
.AdapterVendorDescription
) + 1);
390 memcpy(ResponseData
, RNDISInterfaceInfo
->Config
.AdapterVendorDescription
, *ResponseSize
);
393 case OID_GEN_MEDIA_CONNECT_STATUS
:
394 *ResponseSize
= sizeof(uint32_t);
396 *((uint32_t*)ResponseData
) = REMOTE_NDIS_MEDIA_STATE_CONNECTED
;
399 case OID_GEN_LINK_SPEED
:
400 *ResponseSize
= sizeof(uint32_t);
402 /* Indicate 10Mb/s link speed */
403 *((uint32_t*)ResponseData
) = 100000;
406 case OID_802_3_PERMANENT_ADDRESS
:
407 case OID_802_3_CURRENT_ADDRESS
:
408 *ResponseSize
= sizeof(MAC_Address_t
);
410 memcpy(ResponseData
, &RNDISInterfaceInfo
->Config
.AdapterMACAddress
, sizeof(MAC_Address_t
));
413 case OID_802_3_MAXIMUM_LIST_SIZE
:
414 *ResponseSize
= sizeof(uint32_t);
416 /* Indicate only one multicast address supported */
417 *((uint32_t*)ResponseData
) = 1;
420 case OID_GEN_CURRENT_PACKET_FILTER
:
421 *ResponseSize
= sizeof(uint32_t);
423 *((uint32_t*)ResponseData
) = RNDISInterfaceInfo
->State
.CurrPacketFilter
;
426 case OID_GEN_XMIT_OK
:
428 case OID_GEN_XMIT_ERROR
:
429 case OID_GEN_RCV_ERROR
:
430 case OID_GEN_RCV_NO_BUFFER
:
431 case OID_802_3_RCV_ERROR_ALIGNMENT
:
432 case OID_802_3_XMIT_ONE_COLLISION
:
433 case OID_802_3_XMIT_MORE_COLLISIONS
:
434 *ResponseSize
= sizeof(uint32_t);
436 /* Unused statistic OIDs - always return 0 for each */
437 *((uint32_t*)ResponseData
) = 0;
440 case OID_GEN_MAXIMUM_TOTAL_SIZE
:
441 *ResponseSize
= sizeof(uint32_t);
443 /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */
444 *((uint32_t*)ResponseData
) = (RNDIS_MESSAGE_BUFFER_SIZE
+ ETHERNET_FRAME_SIZE_MAX
);
452 static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t
* const RNDISInterfaceInfo
,
455 const uint16_t SetSize
)
461 case OID_GEN_CURRENT_PACKET_FILTER
:
462 RNDISInterfaceInfo
->State
.CurrPacketFilter
= *((uint32_t*)SetData
);
463 RNDISInterfaceInfo
->State
.CurrRNDISState
= ((RNDISInterfaceInfo
->State
.CurrPacketFilter
) ?
464 RNDIS_Data_Initialized
: RNDIS_Data_Initialized
);
467 case OID_802_3_MULTICAST_LIST
:
468 /* Do nothing - throw away the value from the host as it is unused */