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