Added new USB_DeviceState variable to keep track of the current Device mode USB state.
[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 if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->Config.DataINEndpointNumber, EP_TYPE_BULK,
116 ENDPOINT_DIR_IN, RNDISInterfaceInfo->Config.DataINEndpointSize,
117 ENDPOINT_BANK_SINGLE)))
118 {
119 return false;
120 }
121
122 if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpointNumber, EP_TYPE_BULK,
123 ENDPOINT_DIR_OUT, RNDISInterfaceInfo->Config.DataOUTEndpointSize,
124 ENDPOINT_BANK_SINGLE)))
125 {
126 return false;
127 }
128
129 if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->Config.NotificationEndpointNumber, EP_TYPE_INTERRUPT,
130 ENDPOINT_DIR_IN, RNDISInterfaceInfo->Config.NotificationEndpointSize,
131 ENDPOINT_BANK_SINGLE)))
132 {
133 return false;
134 }
135
136 return true;
137 }
138
139 void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
140 {
141 if (USB_DeviceState != DEVICE_STATE_Configured)
142 return;
143
144 RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
145
146 Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpointNumber);
147
148 if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady)
149 {
150 USB_Request_Header_t Notification = (USB_Request_Header_t)
151 {
152 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
153 .bRequest = NOTIF_ResponseAvailable,
154 .wValue = 0,
155 .wIndex = 0,
156 .wLength = 0,
157 };
158
159 Endpoint_Write_Stream_LE(&Notification, sizeof(Notification), NO_STREAM_CALLBACK);
160
161 Endpoint_ClearIN();
162
163 RNDISInterfaceInfo->State.ResponseReady = false;
164 }
165
166 if ((RNDISInterfaceInfo->State.CurrRNDISState == RNDIS_Data_Initialized) && !(MessageHeader->MessageLength))
167 {
168 RNDIS_Packet_Message_t RNDISPacketHeader;
169
170 Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpointNumber);
171
172 if (Endpoint_IsOUTReceived() && !(RNDISInterfaceInfo->State.FrameIN.FrameInBuffer))
173 {
174 Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NO_STREAM_CALLBACK);
175
176 if (RNDISPacketHeader.DataLength > ETHERNET_FRAME_SIZE_MAX)
177 {
178 Endpoint_StallTransaction();
179 return;
180 }
181
182 Endpoint_Read_Stream_LE(RNDISInterfaceInfo->State.FrameIN.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK);
183
184 Endpoint_ClearOUT();
185
186 RNDISInterfaceInfo->State.FrameIN.FrameLength = RNDISPacketHeader.DataLength;
187
188 RNDISInterfaceInfo->State.FrameIN.FrameInBuffer = true;
189 }
190
191 Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpointNumber);
192
193 if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer)
194 {
195 memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t));
196
197 RNDISPacketHeader.MessageType = REMOTE_NDIS_PACKET_MSG;
198 RNDISPacketHeader.MessageLength = (sizeof(RNDIS_Packet_Message_t) + RNDISInterfaceInfo->State.FrameOUT.FrameLength);
199 RNDISPacketHeader.DataOffset = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
200 RNDISPacketHeader.DataLength = RNDISInterfaceInfo->State.FrameOUT.FrameLength;
201
202 Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NO_STREAM_CALLBACK);
203 Endpoint_Write_Stream_LE(RNDISInterfaceInfo->State.FrameOUT.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK);
204 Endpoint_ClearIN();
205
206 RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer = false;
207 }
208 }
209 }
210
211 void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
212 {
213 /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of
214 this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */
215
216 RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
217
218 switch (MessageHeader->MessageType)
219 {
220 case REMOTE_NDIS_INITIALIZE_MSG:
221 RNDISInterfaceInfo->State.ResponseReady = true;
222
223 RNDIS_Initialize_Message_t* INITIALIZE_Message =
224 (RNDIS_Initialize_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
225 RNDIS_Initialize_Complete_t* INITIALIZE_Response =
226 (RNDIS_Initialize_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
227
228 INITIALIZE_Response->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
229 INITIALIZE_Response->MessageLength = sizeof(RNDIS_Initialize_Complete_t);
230 INITIALIZE_Response->RequestId = INITIALIZE_Message->RequestId;
231 INITIALIZE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
232
233 INITIALIZE_Response->MajorVersion = REMOTE_NDIS_VERSION_MAJOR;
234 INITIALIZE_Response->MinorVersion = REMOTE_NDIS_VERSION_MINOR;
235 INITIALIZE_Response->DeviceFlags = REMOTE_NDIS_DF_CONNECTIONLESS;
236 INITIALIZE_Response->Medium = REMOTE_NDIS_MEDIUM_802_3;
237 INITIALIZE_Response->MaxPacketsPerTransfer = 1;
238 INITIALIZE_Response->MaxTransferSize = (sizeof(RNDIS_Packet_Message_t) + ETHERNET_FRAME_SIZE_MAX);
239 INITIALIZE_Response->PacketAlignmentFactor = 0;
240 INITIALIZE_Response->AFListOffset = 0;
241 INITIALIZE_Response->AFListSize = 0;
242
243 RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Initialized;
244
245 break;
246 case REMOTE_NDIS_HALT_MSG:
247 RNDISInterfaceInfo->State.ResponseReady = false;
248 MessageHeader->MessageLength = 0;
249
250 RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Uninitialized;
251
252 break;
253 case REMOTE_NDIS_QUERY_MSG:
254 RNDISInterfaceInfo->State.ResponseReady = true;
255
256 RNDIS_Query_Message_t* QUERY_Message = (RNDIS_Query_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
257 RNDIS_Query_Complete_t* QUERY_Response = (RNDIS_Query_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
258 uint32_t Query_Oid = QUERY_Message->Oid;
259
260 void* QueryData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
261 QUERY_Message->InformationBufferOffset];
262 void* ResponseData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Query_Complete_t)];
263 uint16_t ResponseSize;
264
265 QUERY_Response->MessageType = REMOTE_NDIS_QUERY_CMPLT;
266 QUERY_Response->MessageLength = sizeof(RNDIS_Query_Complete_t);
267
268 if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo, Query_Oid, QueryData, QUERY_Message->InformationBufferLength,
269 ResponseData, &ResponseSize))
270 {
271 QUERY_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
272 QUERY_Response->MessageLength += ResponseSize;
273
274 QUERY_Response->InformationBufferLength = ResponseSize;
275 QUERY_Response->InformationBufferOffset = (sizeof(RNDIS_Query_Complete_t) - sizeof(RNDIS_Message_Header_t));
276 }
277 else
278 {
279 QUERY_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;
280
281 QUERY_Response->InformationBufferLength = 0;
282 QUERY_Response->InformationBufferOffset = 0;
283 }
284
285 break;
286 case REMOTE_NDIS_SET_MSG:
287 RNDISInterfaceInfo->State.ResponseReady = true;
288
289 RNDIS_Set_Message_t* SET_Message = (RNDIS_Set_Message_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
290 RNDIS_Set_Complete_t* SET_Response = (RNDIS_Set_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
291 uint32_t SET_Oid = SET_Message->Oid;
292
293 SET_Response->MessageType = REMOTE_NDIS_SET_CMPLT;
294 SET_Response->MessageLength = sizeof(RNDIS_Set_Complete_t);
295 SET_Response->RequestId = SET_Message->RequestId;
296
297 void* SetData = &RNDISInterfaceInfo->State.RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
298 SET_Message->InformationBufferOffset];
299
300 if (RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo, SET_Oid, SetData, SET_Message->InformationBufferLength))
301 SET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
302 else
303 SET_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;
304
305 break;
306 case REMOTE_NDIS_RESET_MSG:
307 RNDISInterfaceInfo->State.ResponseReady = true;
308
309 RNDIS_Reset_Complete_t* RESET_Response = (RNDIS_Reset_Complete_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;
310
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;
315
316 break;
317 case REMOTE_NDIS_KEEPALIVE_MSG:
318 RNDISInterfaceInfo->State.ResponseReady = true;
319
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;
324
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;
329
330 break;
331 }
332 }
333
334 static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
335 const uint32_t OId, void* const QueryData, const uint16_t QuerySize,
336 void* ResponseData, uint16_t* const ResponseSize)
337 {
338 switch (OId)
339 {
340 case OID_GEN_SUPPORTED_LIST:
341 *ResponseSize = sizeof(AdapterSupportedOIDList);
342
343 memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));
344
345 return true;
346 case OID_GEN_PHYSICAL_MEDIUM:
347 *ResponseSize = sizeof(uint32_t);
348
349 /* Indicate that the device is a true ethernet link */
350 *((uint32_t*)ResponseData) = 0;
351
352 return true;
353 case OID_GEN_HARDWARE_STATUS:
354 *ResponseSize = sizeof(uint32_t);
355
356 *((uint32_t*)ResponseData) = NDIS_HardwareStatus_Ready;
357
358 return true;
359 case OID_GEN_MEDIA_SUPPORTED:
360 case OID_GEN_MEDIA_IN_USE:
361 *ResponseSize = sizeof(uint32_t);
362
363 *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIUM_802_3;
364
365 return true;
366 case OID_GEN_VENDOR_ID:
367 *ResponseSize = sizeof(uint32_t);
368
369 /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
370 *((uint32_t*)ResponseData) = 0x00FFFFFF;
371
372 return true;
373 case OID_GEN_MAXIMUM_FRAME_SIZE:
374 case OID_GEN_TRANSMIT_BLOCK_SIZE:
375 case OID_GEN_RECEIVE_BLOCK_SIZE:
376 *ResponseSize = sizeof(uint32_t);
377
378 *((uint32_t*)ResponseData) = ETHERNET_FRAME_SIZE_MAX;
379
380 return true;
381 case OID_GEN_VENDOR_DESCRIPTION:
382 *ResponseSize = (strlen(RNDISInterfaceInfo->Config.AdapterVendorDescription) + 1);
383
384 memcpy(ResponseData, RNDISInterfaceInfo->Config.AdapterVendorDescription, *ResponseSize);
385
386 return true;
387 case OID_GEN_MEDIA_CONNECT_STATUS:
388 *ResponseSize = sizeof(uint32_t);
389
390 *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIA_STATE_CONNECTED;
391
392 return true;
393 case OID_GEN_LINK_SPEED:
394 *ResponseSize = sizeof(uint32_t);
395
396 /* Indicate 10Mb/s link speed */
397 *((uint32_t*)ResponseData) = 100000;
398
399 return true;
400 case OID_802_3_PERMANENT_ADDRESS:
401 case OID_802_3_CURRENT_ADDRESS:
402 *ResponseSize = sizeof(MAC_Address_t);
403
404 memcpy(ResponseData, &RNDISInterfaceInfo->Config.AdapterMACAddress, sizeof(MAC_Address_t));
405
406 return true;
407 case OID_802_3_MAXIMUM_LIST_SIZE:
408 *ResponseSize = sizeof(uint32_t);
409
410 /* Indicate only one multicast address supported */
411 *((uint32_t*)ResponseData) = 1;
412
413 return true;
414 case OID_GEN_CURRENT_PACKET_FILTER:
415 *ResponseSize = sizeof(uint32_t);
416
417 *((uint32_t*)ResponseData) = RNDISInterfaceInfo->State.CurrPacketFilter;
418
419 return true;
420 case OID_GEN_XMIT_OK:
421 case OID_GEN_RCV_OK:
422 case OID_GEN_XMIT_ERROR:
423 case OID_GEN_RCV_ERROR:
424 case OID_GEN_RCV_NO_BUFFER:
425 case OID_802_3_RCV_ERROR_ALIGNMENT:
426 case OID_802_3_XMIT_ONE_COLLISION:
427 case OID_802_3_XMIT_MORE_COLLISIONS:
428 *ResponseSize = sizeof(uint32_t);
429
430 /* Unused statistic OIDs - always return 0 for each */
431 *((uint32_t*)ResponseData) = 0;
432
433 return true;
434 case OID_GEN_MAXIMUM_TOTAL_SIZE:
435 *ResponseSize = sizeof(uint32_t);
436
437 /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */
438 *((uint32_t*)ResponseData) = (RNDIS_MESSAGE_BUFFER_SIZE + ETHERNET_FRAME_SIZE_MAX);
439
440 return true;
441 default:
442 return false;
443 }
444 }
445
446 static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo, const uint32_t OId, void* SetData,
447 const uint16_t SetSize)
448 {
449 switch (OId)
450 {
451 case OID_GEN_CURRENT_PACKET_FILTER:
452 RNDISInterfaceInfo->State.CurrPacketFilter = *((uint32_t*)SetData);
453 RNDISInterfaceInfo->State.CurrRNDISState = ((RNDISInterfaceInfo->State.CurrPacketFilter) ?
454 RNDIS_Data_Initialized : RNDIS_Data_Initialized);
455
456 return true;
457 case OID_802_3_MULTICAST_LIST:
458 /* Do nothing - throw away the value from the host as it is unused */
459
460 return true;
461 default:
462 return false;
463 }
464 }
465
466 #endif