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