Changed over www.fourwalledcubicle.com links to the new www.lufa-lib.org redirect...
[pub/USBasp.git] / LUFA / Drivers / USB / Class / Device / RNDIS.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2010.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
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.
20
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
28 this software.
29 */
30
31 #define __INCLUDE_FROM_USB_DRIVER
32 #include "../../HighLevel/USBMode.h"
33 #if defined(USB_CAN_BE_DEVICE)
34
35 #define __INCLUDE_FROM_RNDIS_DRIVER
36 #define __INCLUDE_FROM_RNDIS_DEVICE_C
37 #include "RNDIS.h"
38
39 static const uint32_t PROGMEM AdapterSupportedOIDList[] =
40 {
41 OID_GEN_SUPPORTED_LIST,
42 OID_GEN_PHYSICAL_MEDIUM,
43 OID_GEN_HARDWARE_STATUS,
44 OID_GEN_MEDIA_SUPPORTED,
45 OID_GEN_MEDIA_IN_USE,
46 OID_GEN_MAXIMUM_FRAME_SIZE,
47 OID_GEN_MAXIMUM_TOTAL_SIZE,
48 OID_GEN_LINK_SPEED,
49 OID_GEN_TRANSMIT_BLOCK_SIZE,
50 OID_GEN_RECEIVE_BLOCK_SIZE,
51 OID_GEN_VENDOR_ID,
52 OID_GEN_VENDOR_DESCRIPTION,
53 OID_GEN_CURRENT_PACKET_FILTER,
54 OID_GEN_MAXIMUM_TOTAL_SIZE,
55 OID_GEN_MEDIA_CONNECT_STATUS,
56 OID_GEN_XMIT_OK,
57 OID_GEN_RCV_OK,
58 OID_GEN_XMIT_ERROR,
59 OID_GEN_RCV_ERROR,
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,
68 };
69
70 void RNDIS_Device_ProcessControlRequest(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
71 {
72 if (!(Endpoint_IsSETUPReceived()))
73 return;
74
75 if (USB_ControlRequest.wIndex != RNDISInterfaceInfo->Config.ControlInterfaceNumber)
76 return;
77
78 switch (USB_ControlRequest.bRequest)
79 {
80 case RNDIS_REQ_SendEncapsulatedCommand:
81 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
82 {
83 Endpoint_ClearSETUP();
84 Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo->State.RNDISMessageBuffer, USB_ControlRequest.wLength);
85 Endpoint_ClearIN();
86
87 RNDIS_Device_ProcessRNDISControlMessage(RNDISInterfaceInfo);
88 }
89
90 break;
91 case RNDIS_REQ_GetEncapsulatedResponse:
92 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
93 {
94 RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
95
96 if (!(MessageHeader->MessageLength))
97 {
98 RNDISInterfaceInfo->State.RNDISMessageBuffer[0] = 0;
99 MessageHeader->MessageLength = 1;
100 }
101
102 Endpoint_ClearSETUP();
103 Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->State.RNDISMessageBuffer, MessageHeader->MessageLength);
104 Endpoint_ClearOUT();
105
106 MessageHeader->MessageLength = 0;
107 }
108
109 break;
110 }
111 }
112
113 bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
114 {
115 memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
116
117 for (uint8_t EndpointNum = 1; EndpointNum < ENDPOINT_TOTAL_ENDPOINTS; EndpointNum++)
118 {
119 uint16_t Size;
120 uint8_t Type;
121 uint8_t Direction;
122 bool DoubleBanked;
123
124 if (EndpointNum == RNDISInterfaceInfo->Config.DataINEndpointNumber)
125 {
126 Size = RNDISInterfaceInfo->Config.DataINEndpointSize;
127 Direction = ENDPOINT_DIR_IN;
128 Type = EP_TYPE_BULK;
129 DoubleBanked = RNDISInterfaceInfo->Config.DataINEndpointDoubleBank;
130 }
131 else if (EndpointNum == RNDISInterfaceInfo->Config.DataOUTEndpointNumber)
132 {
133 Size = RNDISInterfaceInfo->Config.DataOUTEndpointSize;
134 Direction = ENDPOINT_DIR_OUT;
135 Type = EP_TYPE_BULK;
136 DoubleBanked = RNDISInterfaceInfo->Config.DataOUTEndpointDoubleBank;
137 }
138 else if (EndpointNum == RNDISInterfaceInfo->Config.NotificationEndpointNumber)
139 {
140 Size = RNDISInterfaceInfo->Config.NotificationEndpointSize;
141 Direction = ENDPOINT_DIR_IN;
142 Type = EP_TYPE_INTERRUPT;
143 DoubleBanked = RNDISInterfaceInfo->Config.NotificationEndpointDoubleBank;
144 }
145 else
146 {
147 continue;
148 }
149
150 if (!(Endpoint_ConfigureEndpoint(EndpointNum, Type, Direction, Size,
151 DoubleBanked ? ENDPOINT_BANK_DOUBLE : ENDPOINT_BANK_SINGLE)))
152 {
153 return false;
154 }
155 }
156
157 return true;
158 }
159
160 void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
161 {
162 if (USB_DeviceState != DEVICE_STATE_Configured)
163 return;
164
165 RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
166
167 Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpointNumber);
168
169 if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady)
170 {
171 USB_Request_Header_t Notification = (USB_Request_Header_t)
172 {
173 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
174 .bRequest = RNDIS_NOTIF_ResponseAvailable,
175 .wValue = 0,
176 .wIndex = 0,
177 .wLength = 0,
178 };
179
180 Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NO_STREAM_CALLBACK);
181
182 Endpoint_ClearIN();
183
184 RNDISInterfaceInfo->State.ResponseReady = false;
185 }
186
187 if ((RNDISInterfaceInfo->State.CurrRNDISState == RNDIS_Data_Initialized) && !(MessageHeader->MessageLength))
188 {
189 RNDIS_Packet_Message_t RNDISPacketHeader;
190
191 Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpointNumber);
192
193 if (Endpoint_IsOUTReceived() && !(RNDISInterfaceInfo->State.FrameIN.FrameInBuffer))
194 {
195 Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NO_STREAM_CALLBACK);
196
197 if (RNDISPacketHeader.DataLength > ETHERNET_FRAME_SIZE_MAX)
198 {
199 Endpoint_StallTransaction();
200 return;
201 }
202
203 Endpoint_Read_Stream_LE(RNDISInterfaceInfo->State.FrameIN.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK);
204
205 Endpoint_ClearOUT();
206
207 RNDISInterfaceInfo->State.FrameIN.FrameLength = RNDISPacketHeader.DataLength;
208
209 RNDISInterfaceInfo->State.FrameIN.FrameInBuffer = true;
210 }
211
212 Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpointNumber);
213
214 if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer)
215 {
216 memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t));
217
218 RNDISPacketHeader.MessageType = REMOTE_NDIS_PACKET_MSG;
219 RNDISPacketHeader.MessageLength = (sizeof(RNDIS_Packet_Message_t) + RNDISInterfaceInfo->State.FrameOUT.FrameLength);
220 RNDISPacketHeader.DataOffset = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
221 RNDISPacketHeader.DataLength = RNDISInterfaceInfo->State.FrameOUT.FrameLength;
222
223 Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NO_STREAM_CALLBACK);
224 Endpoint_Write_Stream_LE(RNDISInterfaceInfo->State.FrameOUT.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK);
225 Endpoint_ClearIN();
226
227 RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer = false;
228 }
229 }
230 }
231
232 void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
233 {
234 /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of
235 this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */
236
237 RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
238
239 switch (MessageHeader->MessageType)
240 {
241 case REMOTE_NDIS_INITIALIZE_MSG:
242 RNDISInterfaceInfo->State.ResponseReady = true;
243
244 RNDIS_Initialize_Message_t* INITIALIZE_Message =
245 (RNDIS_Initialize_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
246 RNDIS_Initialize_Complete_t* INITIALIZE_Response =
247 (RNDIS_Initialize_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
248
249 INITIALIZE_Response->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
250 INITIALIZE_Response->MessageLength = sizeof(RNDIS_Initialize_Complete_t);
251 INITIALIZE_Response->RequestId = INITIALIZE_Message->RequestId;
252 INITIALIZE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
253
254 INITIALIZE_Response->MajorVersion = REMOTE_NDIS_VERSION_MAJOR;
255 INITIALIZE_Response->MinorVersion = REMOTE_NDIS_VERSION_MINOR;
256 INITIALIZE_Response->DeviceFlags = REMOTE_NDIS_DF_CONNECTIONLESS;
257 INITIALIZE_Response->Medium = REMOTE_NDIS_MEDIUM_802_3;
258 INITIALIZE_Response->MaxPacketsPerTransfer = 1;
259 INITIALIZE_Response->MaxTransferSize = (sizeof(RNDIS_Packet_Message_t) + ETHERNET_FRAME_SIZE_MAX);
260 INITIALIZE_Response->PacketAlignmentFactor = 0;
261 INITIALIZE_Response->AFListOffset = 0;
262 INITIALIZE_Response->AFListSize = 0;
263
264 RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Initialized;
265
266 break;
267 case REMOTE_NDIS_HALT_MSG:
268 RNDISInterfaceInfo->State.ResponseReady = false;
269 MessageHeader->MessageLength = 0;
270
271 RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Uninitialized;
272
273 break;
274 case REMOTE_NDIS_QUERY_MSG:
275 RNDISInterfaceInfo->State.ResponseReady = true;
276
277 RNDIS_Query_Message_t* QUERY_Message = (RNDIS_Query_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
278 RNDIS_Query_Complete_t* QUERY_Response = (RNDIS_Query_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
279 uint32_t Query_Oid = QUERY_Message->Oid;
280
281 void* QueryData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
282 QUERY_Message->InformationBufferOffset];
283 void* ResponseData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Query_Complete_t)];
284 uint16_t ResponseSize;
285
286 QUERY_Response->MessageType = REMOTE_NDIS_QUERY_CMPLT;
287 QUERY_Response->MessageLength = sizeof(RNDIS_Query_Complete_t);
288
289 if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo, Query_Oid, QueryData, QUERY_Message->InformationBufferLength,
290 ResponseData, &ResponseSize))
291 {
292 QUERY_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
293 QUERY_Response->MessageLength += ResponseSize;
294
295 QUERY_Response->InformationBufferLength = ResponseSize;
296 QUERY_Response->InformationBufferOffset = (sizeof(RNDIS_Query_Complete_t) - sizeof(RNDIS_Message_Header_t));
297 }
298 else
299 {
300 QUERY_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;
301
302 QUERY_Response->InformationBufferLength = 0;
303 QUERY_Response->InformationBufferOffset = 0;
304 }
305
306 break;
307 case REMOTE_NDIS_SET_MSG:
308 RNDISInterfaceInfo->State.ResponseReady = true;
309
310 RNDIS_Set_Message_t* SET_Message = (RNDIS_Set_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
311 RNDIS_Set_Complete_t* SET_Response = (RNDIS_Set_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
312 uint32_t SET_Oid = SET_Message->Oid;
313
314 SET_Response->MessageType = REMOTE_NDIS_SET_CMPLT;
315 SET_Response->MessageLength = sizeof(RNDIS_Set_Complete_t);
316 SET_Response->RequestId = SET_Message->RequestId;
317
318 void* SetData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
319 SET_Message->InformationBufferOffset];
320
321 SET_Response->Status = RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo, SET_Oid, SetData,
322 SET_Message->InformationBufferLength) ?
323 REMOTE_NDIS_STATUS_SUCCESS : REMOTE_NDIS_STATUS_NOT_SUPPORTED;
324 break;
325 case REMOTE_NDIS_RESET_MSG:
326 RNDISInterfaceInfo->State.ResponseReady = true;
327
328 RNDIS_Reset_Complete_t* RESET_Response = (RNDIS_Reset_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
329
330 RESET_Response->MessageType = REMOTE_NDIS_RESET_CMPLT;
331 RESET_Response->MessageLength = sizeof(RNDIS_Reset_Complete_t);
332 RESET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
333 RESET_Response->AddressingReset = 0;
334
335 break;
336 case REMOTE_NDIS_KEEPALIVE_MSG:
337 RNDISInterfaceInfo->State.ResponseReady = true;
338
339 RNDIS_KeepAlive_Message_t* KEEPALIVE_Message =
340 (RNDIS_KeepAlive_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
341 RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response =
342 (RNDIS_KeepAlive_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
343
344 KEEPALIVE_Response->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
345 KEEPALIVE_Response->MessageLength = sizeof(RNDIS_KeepAlive_Complete_t);
346 KEEPALIVE_Response->RequestId = KEEPALIVE_Message->RequestId;
347 KEEPALIVE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
348
349 break;
350 }
351 }
352
353 static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
354 const uint32_t OId,
355 void* const QueryData,
356 const uint16_t QuerySize,
357 void* ResponseData,
358 uint16_t* const ResponseSize)
359 {
360 (void)QueryData;
361 (void)QuerySize;
362
363 switch (OId)
364 {
365 case OID_GEN_SUPPORTED_LIST:
366 *ResponseSize = sizeof(AdapterSupportedOIDList);
367
368 memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));
369
370 return true;
371 case OID_GEN_PHYSICAL_MEDIUM:
372 *ResponseSize = sizeof(uint32_t);
373
374 /* Indicate that the device is a true ethernet link */
375 *((uint32_t*)ResponseData) = 0;
376
377 return true;
378 case OID_GEN_HARDWARE_STATUS:
379 *ResponseSize = sizeof(uint32_t);
380
381 *((uint32_t*)ResponseData) = NDIS_HardwareStatus_Ready;
382
383 return true;
384 case OID_GEN_MEDIA_SUPPORTED:
385 case OID_GEN_MEDIA_IN_USE:
386 *ResponseSize = sizeof(uint32_t);
387
388 *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIUM_802_3;
389
390 return true;
391 case OID_GEN_VENDOR_ID:
392 *ResponseSize = sizeof(uint32_t);
393
394 /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
395 *((uint32_t*)ResponseData) = 0x00FFFFFF;
396
397 return true;
398 case OID_GEN_MAXIMUM_FRAME_SIZE:
399 case OID_GEN_TRANSMIT_BLOCK_SIZE:
400 case OID_GEN_RECEIVE_BLOCK_SIZE:
401 *ResponseSize = sizeof(uint32_t);
402
403 *((uint32_t*)ResponseData) = ETHERNET_FRAME_SIZE_MAX;
404
405 return true;
406 case OID_GEN_VENDOR_DESCRIPTION:
407 *ResponseSize = (strlen(RNDISInterfaceInfo->Config.AdapterVendorDescription) + 1);
408
409 memcpy(ResponseData, RNDISInterfaceInfo->Config.AdapterVendorDescription, *ResponseSize);
410
411 return true;
412 case OID_GEN_MEDIA_CONNECT_STATUS:
413 *ResponseSize = sizeof(uint32_t);
414
415 *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIA_STATE_CONNECTED;
416
417 return true;
418 case OID_GEN_LINK_SPEED:
419 *ResponseSize = sizeof(uint32_t);
420
421 /* Indicate 10Mb/s link speed */
422 *((uint32_t*)ResponseData) = 100000;
423
424 return true;
425 case OID_802_3_PERMANENT_ADDRESS:
426 case OID_802_3_CURRENT_ADDRESS:
427 *ResponseSize = sizeof(MAC_Address_t);
428
429 memcpy(ResponseData, &RNDISInterfaceInfo->Config.AdapterMACAddress, sizeof(MAC_Address_t));
430
431 return true;
432 case OID_802_3_MAXIMUM_LIST_SIZE:
433 *ResponseSize = sizeof(uint32_t);
434
435 /* Indicate only one multicast address supported */
436 *((uint32_t*)ResponseData) = 1;
437
438 return true;
439 case OID_GEN_CURRENT_PACKET_FILTER:
440 *ResponseSize = sizeof(uint32_t);
441
442 *((uint32_t*)ResponseData) = RNDISInterfaceInfo->State.CurrPacketFilter;
443
444 return true;
445 case OID_GEN_XMIT_OK:
446 case OID_GEN_RCV_OK:
447 case OID_GEN_XMIT_ERROR:
448 case OID_GEN_RCV_ERROR:
449 case OID_GEN_RCV_NO_BUFFER:
450 case OID_802_3_RCV_ERROR_ALIGNMENT:
451 case OID_802_3_XMIT_ONE_COLLISION:
452 case OID_802_3_XMIT_MORE_COLLISIONS:
453 *ResponseSize = sizeof(uint32_t);
454
455 /* Unused statistic OIDs - always return 0 for each */
456 *((uint32_t*)ResponseData) = 0;
457
458 return true;
459 case OID_GEN_MAXIMUM_TOTAL_SIZE:
460 *ResponseSize = sizeof(uint32_t);
461
462 /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */
463 *((uint32_t*)ResponseData) = (RNDIS_MESSAGE_BUFFER_SIZE + ETHERNET_FRAME_SIZE_MAX);
464
465 return true;
466 default:
467 return false;
468 }
469 }
470
471 static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
472 const uint32_t OId,
473 const void* SetData,
474 const uint16_t SetSize)
475 {
476 (void)SetSize;
477
478 switch (OId)
479 {
480 case OID_GEN_CURRENT_PACKET_FILTER:
481 RNDISInterfaceInfo->State.CurrPacketFilter = *((uint32_t*)SetData);
482 RNDISInterfaceInfo->State.CurrRNDISState = ((RNDISInterfaceInfo->State.CurrPacketFilter) ?
483 RNDIS_Data_Initialized : RNDIS_Data_Initialized);
484
485 return true;
486 case OID_802_3_MULTICAST_LIST:
487 /* Do nothing - throw away the value from the host as it is unused */
488
489 return true;
490 default:
491 return false;
492 }
493 }
494
495 #endif
496