State information for class drivers is now zeroed out during enumeration (both in...
[pub/USBasp.git] / LUFA / Drivers / USB / Class / Device / RNDIS.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2009.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
7 */
8
9 /*
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, and distribute this software
13 and its documentation for any purpose and without fee is hereby
14 granted, provided that the above copyright notice appear in all
15 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 #include "../../HighLevel/USBMode.h"
32 #if defined(USB_CAN_BE_DEVICE)
33
34 #define INCLUDE_FROM_RNDIS_CLASS_DEVICE_C
35 #include "RNDIS.h"
36
37 static const uint32_t PROGMEM AdapterSupportedOIDList[] =
38 {
39 OID_GEN_SUPPORTED_LIST,
40 OID_GEN_PHYSICAL_MEDIUM,
41 OID_GEN_HARDWARE_STATUS,
42 OID_GEN_MEDIA_SUPPORTED,
43 OID_GEN_MEDIA_IN_USE,
44 OID_GEN_MAXIMUM_FRAME_SIZE,
45 OID_GEN_MAXIMUM_TOTAL_SIZE,
46 OID_GEN_LINK_SPEED,
47 OID_GEN_TRANSMIT_BLOCK_SIZE,
48 OID_GEN_RECEIVE_BLOCK_SIZE,
49 OID_GEN_VENDOR_ID,
50 OID_GEN_VENDOR_DESCRIPTION,
51 OID_GEN_CURRENT_PACKET_FILTER,
52 OID_GEN_MAXIMUM_TOTAL_SIZE,
53 OID_GEN_MEDIA_CONNECT_STATUS,
54 OID_GEN_XMIT_OK,
55 OID_GEN_RCV_OK,
56 OID_GEN_XMIT_ERROR,
57 OID_GEN_RCV_ERROR,
58 OID_GEN_RCV_NO_BUFFER,
59 OID_802_3_PERMANENT_ADDRESS,
60 OID_802_3_CURRENT_ADDRESS,
61 OID_802_3_MULTICAST_LIST,
62 OID_802_3_MAXIMUM_LIST_SIZE,
63 OID_802_3_RCV_ERROR_ALIGNMENT,
64 OID_802_3_XMIT_ONE_COLLISION,
65 OID_802_3_XMIT_MORE_COLLISIONS,
66 };
67
68 void RNDIS_Device_ProcessControlPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
69 {
70 if (!(Endpoint_IsSETUPReceived()))
71 return;
72
73 if (USB_ControlRequest.wIndex != RNDISInterfaceInfo->Config.ControlInterfaceNumber)
74 return;
75
76 switch (USB_ControlRequest.bRequest)
77 {
78 case REQ_SendEncapsulatedCommand:
79 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
80 {
81 Endpoint_ClearSETUP();
82
83 Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo->State.RNDISMessageBuffer, USB_ControlRequest.wLength);
84 Endpoint_ClearIN();
85
86 RNDIS_Device_ProcessRNDISControlMessage(RNDISInterfaceInfo);
87 }
88
89 break;
90 case REQ_GetEncapsulatedResponse:
91 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
92 {
93 Endpoint_ClearSETUP();
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_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 if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->Config.DataINEndpointNumber, EP_TYPE_BULK,
118 ENDPOINT_DIR_IN, RNDISInterfaceInfo->Config.DataINEndpointSize,
119 ENDPOINT_BANK_SINGLE)))
120 {
121 return false;
122 }
123
124 if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpointNumber, EP_TYPE_BULK,
125 ENDPOINT_DIR_OUT, RNDISInterfaceInfo->Config.DataOUTEndpointSize,
126 ENDPOINT_BANK_SINGLE)))
127 {
128 return false;
129 }
130
131 if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->Config.NotificationEndpointNumber, EP_TYPE_INTERRUPT,
132 ENDPOINT_DIR_IN, RNDISInterfaceInfo->Config.NotificationEndpointSize,
133 ENDPOINT_BANK_SINGLE)))
134 {
135 return false;
136 }
137
138 return true;
139 }
140
141 void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
142 {
143 if (USB_DeviceState != DEVICE_STATE_Configured)
144 return;
145
146 RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
147
148 Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpointNumber);
149
150 if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady)
151 {
152 USB_Request_Header_t Notification = (USB_Request_Header_t)
153 {
154 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
155 .bRequest = NOTIF_ResponseAvailable,
156 .wValue = 0,
157 .wIndex = 0,
158 .wLength = 0,
159 };
160
161 Endpoint_Write_Stream_LE(&Notification, sizeof(Notification), NO_STREAM_CALLBACK);
162
163 Endpoint_ClearIN();
164
165 RNDISInterfaceInfo->State.ResponseReady = false;
166 }
167
168 if ((RNDISInterfaceInfo->State.CurrRNDISState == RNDIS_Data_Initialized) && !(MessageHeader->MessageLength))
169 {
170 RNDIS_Packet_Message_t RNDISPacketHeader;
171
172 Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpointNumber);
173
174 if (Endpoint_IsOUTReceived() && !(RNDISInterfaceInfo->State.FrameIN.FrameInBuffer))
175 {
176 Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NO_STREAM_CALLBACK);
177
178 if (RNDISPacketHeader.DataLength > ETHERNET_FRAME_SIZE_MAX)
179 {
180 Endpoint_StallTransaction();
181 return;
182 }
183
184 Endpoint_Read_Stream_LE(RNDISInterfaceInfo->State.FrameIN.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK);
185
186 Endpoint_ClearOUT();
187
188 RNDISInterfaceInfo->State.FrameIN.FrameLength = RNDISPacketHeader.DataLength;
189
190 RNDISInterfaceInfo->State.FrameIN.FrameInBuffer = true;
191 }
192
193 Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpointNumber);
194
195 if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer)
196 {
197 memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t));
198
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;
203
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);
206 Endpoint_ClearIN();
207
208 RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer = false;
209 }
210 }
211 }
212
213 void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
214 {
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. */
217
218 RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
219
220 switch (MessageHeader->MessageType)
221 {
222 case REMOTE_NDIS_INITIALIZE_MSG:
223 RNDISInterfaceInfo->State.ResponseReady = true;
224
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;
229
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;
234
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;
244
245 RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Initialized;
246
247 break;
248 case REMOTE_NDIS_HALT_MSG:
249 RNDISInterfaceInfo->State.ResponseReady = false;
250 MessageHeader->MessageLength = 0;
251
252 RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Uninitialized;
253
254 break;
255 case REMOTE_NDIS_QUERY_MSG:
256 RNDISInterfaceInfo->State.ResponseReady = true;
257
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;
261
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;
266
267 QUERY_Response->MessageType = REMOTE_NDIS_QUERY_CMPLT;
268 QUERY_Response->MessageLength = sizeof(RNDIS_Query_Complete_t);
269
270 if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo, Query_Oid, QueryData, QUERY_Message->InformationBufferLength,
271 ResponseData, &ResponseSize))
272 {
273 QUERY_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
274 QUERY_Response->MessageLength += ResponseSize;
275
276 QUERY_Response->InformationBufferLength = ResponseSize;
277 QUERY_Response->InformationBufferOffset = (sizeof(RNDIS_Query_Complete_t) - sizeof(RNDIS_Message_Header_t));
278 }
279 else
280 {
281 QUERY_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;
282
283 QUERY_Response->InformationBufferLength = 0;
284 QUERY_Response->InformationBufferOffset = 0;
285 }
286
287 break;
288 case REMOTE_NDIS_SET_MSG:
289 RNDISInterfaceInfo->State.ResponseReady = true;
290
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;
294
295 SET_Response->MessageType = REMOTE_NDIS_SET_CMPLT;
296 SET_Response->MessageLength = sizeof(RNDIS_Set_Complete_t);
297 SET_Response->RequestId = SET_Message->RequestId;
298
299 void* SetData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
300 SET_Message->InformationBufferOffset];
301
302 if (RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo, SET_Oid, SetData, SET_Message->InformationBufferLength))
303 SET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
304 else
305 SET_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;
306
307 break;
308 case REMOTE_NDIS_RESET_MSG:
309 RNDISInterfaceInfo->State.ResponseReady = true;
310
311 RNDIS_Reset_Complete_t* RESET_Response = (RNDIS_Reset_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
312
313 RESET_Response->MessageType = REMOTE_NDIS_RESET_CMPLT;
314 RESET_Response->MessageLength = sizeof(RNDIS_Reset_Complete_t);
315 RESET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
316 RESET_Response->AddressingReset = 0;
317
318 break;
319 case REMOTE_NDIS_KEEPALIVE_MSG:
320 RNDISInterfaceInfo->State.ResponseReady = true;
321
322 RNDIS_KeepAlive_Message_t* KEEPALIVE_Message =
323 (RNDIS_KeepAlive_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
324 RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response =
325 (RNDIS_KeepAlive_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
326
327 KEEPALIVE_Response->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
328 KEEPALIVE_Response->MessageLength = sizeof(RNDIS_KeepAlive_Complete_t);
329 KEEPALIVE_Response->RequestId = KEEPALIVE_Message->RequestId;
330 KEEPALIVE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
331
332 break;
333 }
334 }
335
336 static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
337 const uint32_t OId, void* const QueryData, const uint16_t QuerySize,
338 void* ResponseData, uint16_t* const ResponseSize)
339 {
340 switch (OId)
341 {
342 case OID_GEN_SUPPORTED_LIST:
343 *ResponseSize = sizeof(AdapterSupportedOIDList);
344
345 memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));
346
347 return true;
348 case OID_GEN_PHYSICAL_MEDIUM:
349 *ResponseSize = sizeof(uint32_t);
350
351 /* Indicate that the device is a true ethernet link */
352 *((uint32_t*)ResponseData) = 0;
353
354 return true;
355 case OID_GEN_HARDWARE_STATUS:
356 *ResponseSize = sizeof(uint32_t);
357
358 *((uint32_t*)ResponseData) = NDIS_HardwareStatus_Ready;
359
360 return true;
361 case OID_GEN_MEDIA_SUPPORTED:
362 case OID_GEN_MEDIA_IN_USE:
363 *ResponseSize = sizeof(uint32_t);
364
365 *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIUM_802_3;
366
367 return true;
368 case OID_GEN_VENDOR_ID:
369 *ResponseSize = sizeof(uint32_t);
370
371 /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
372 *((uint32_t*)ResponseData) = 0x00FFFFFF;
373
374 return true;
375 case OID_GEN_MAXIMUM_FRAME_SIZE:
376 case OID_GEN_TRANSMIT_BLOCK_SIZE:
377 case OID_GEN_RECEIVE_BLOCK_SIZE:
378 *ResponseSize = sizeof(uint32_t);
379
380 *((uint32_t*)ResponseData) = ETHERNET_FRAME_SIZE_MAX;
381
382 return true;
383 case OID_GEN_VENDOR_DESCRIPTION:
384 *ResponseSize = (strlen(RNDISInterfaceInfo->Config.AdapterVendorDescription) + 1);
385
386 memcpy(ResponseData, RNDISInterfaceInfo->Config.AdapterVendorDescription, *ResponseSize);
387
388 return true;
389 case OID_GEN_MEDIA_CONNECT_STATUS:
390 *ResponseSize = sizeof(uint32_t);
391
392 *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIA_STATE_CONNECTED;
393
394 return true;
395 case OID_GEN_LINK_SPEED:
396 *ResponseSize = sizeof(uint32_t);
397
398 /* Indicate 10Mb/s link speed */
399 *((uint32_t*)ResponseData) = 100000;
400
401 return true;
402 case OID_802_3_PERMANENT_ADDRESS:
403 case OID_802_3_CURRENT_ADDRESS:
404 *ResponseSize = sizeof(MAC_Address_t);
405
406 memcpy(ResponseData, &RNDISInterfaceInfo->Config.AdapterMACAddress, sizeof(MAC_Address_t));
407
408 return true;
409 case OID_802_3_MAXIMUM_LIST_SIZE:
410 *ResponseSize = sizeof(uint32_t);
411
412 /* Indicate only one multicast address supported */
413 *((uint32_t*)ResponseData) = 1;
414
415 return true;
416 case OID_GEN_CURRENT_PACKET_FILTER:
417 *ResponseSize = sizeof(uint32_t);
418
419 *((uint32_t*)ResponseData) = RNDISInterfaceInfo->State.CurrPacketFilter;
420
421 return true;
422 case OID_GEN_XMIT_OK:
423 case OID_GEN_RCV_OK:
424 case OID_GEN_XMIT_ERROR:
425 case OID_GEN_RCV_ERROR:
426 case OID_GEN_RCV_NO_BUFFER:
427 case OID_802_3_RCV_ERROR_ALIGNMENT:
428 case OID_802_3_XMIT_ONE_COLLISION:
429 case OID_802_3_XMIT_MORE_COLLISIONS:
430 *ResponseSize = sizeof(uint32_t);
431
432 /* Unused statistic OIDs - always return 0 for each */
433 *((uint32_t*)ResponseData) = 0;
434
435 return true;
436 case OID_GEN_MAXIMUM_TOTAL_SIZE:
437 *ResponseSize = sizeof(uint32_t);
438
439 /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */
440 *((uint32_t*)ResponseData) = (RNDIS_MESSAGE_BUFFER_SIZE + ETHERNET_FRAME_SIZE_MAX);
441
442 return true;
443 default:
444 return false;
445 }
446 }
447
448 static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, const uint32_t OId, void* SetData,
449 const uint16_t SetSize)
450 {
451 switch (OId)
452 {
453 case OID_GEN_CURRENT_PACKET_FILTER:
454 RNDISInterfaceInfo->State.CurrPacketFilter = *((uint32_t*)SetData);
455 RNDISInterfaceInfo->State.CurrRNDISState = ((RNDISInterfaceInfo->State.CurrPacketFilter) ?
456 RNDIS_Data_Initialized : RNDIS_Data_Initialized);
457
458 return true;
459 case OID_802_3_MULTICAST_LIST:
460 /* Do nothing - throw away the value from the host as it is unused */
461
462 return true;
463 default:
464 return false;
465 }
466 }
467
468 #endif