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