More Doxygen fixes - ensure no undocumented function parameters.
[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_t* RNDISInterfaceInfo)
69 {
70 if (!(Endpoint_IsSETUPReceived()))
71 return;
72
73 if (USB_ControlRequest.wIndex != RNDISInterfaceInfo->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->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->RNDISMessageBuffer;
96
97 if (!(MessageHeader->MessageLength))
98 {
99 RNDISInterfaceInfo->RNDISMessageBuffer[0] = 0;
100 MessageHeader->MessageLength = 1;
101 }
102
103 Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->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_t* RNDISInterfaceInfo)
114 {
115 if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->DataINEndpointNumber, EP_TYPE_BULK,
116 ENDPOINT_DIR_IN, RNDISInterfaceInfo->DataINEndpointSize,
117 ENDPOINT_BANK_SINGLE)))
118 {
119 return false;
120 }
121
122 if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->DataOUTEndpointNumber, EP_TYPE_BULK,
123 ENDPOINT_DIR_OUT, RNDISInterfaceInfo->DataOUTEndpointSize,
124 ENDPOINT_BANK_SINGLE)))
125 {
126 return false;
127 }
128
129 if (!(Endpoint_ConfigureEndpoint(RNDISInterfaceInfo->NotificationEndpointNumber, EP_TYPE_INTERRUPT,
130 ENDPOINT_DIR_IN, RNDISInterfaceInfo->NotificationEndpointSize,
131 ENDPOINT_BANK_SINGLE)))
132 {
133 return false;
134 }
135
136 return true;
137 }
138
139 void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo)
140 {
141 if (!(USB_IsConnected))
142 return;
143
144 RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
145
146 Endpoint_SelectEndpoint(RNDISInterfaceInfo->NotificationEndpointNumber);
147
148 if (Endpoint_IsINReady() && RNDISInterfaceInfo->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->ResponseReady = false;
164 }
165
166 if ((RNDISInterfaceInfo->CurrRNDISState == RNDIS_Data_Initialized) && !(MessageHeader->MessageLength))
167 {
168 RNDIS_PACKET_MSG_t RNDISPacketHeader;
169
170 Endpoint_SelectEndpoint(RNDISInterfaceInfo->DataOUTEndpointNumber);
171
172 if (Endpoint_IsOUTReceived() && !(RNDISInterfaceInfo->FrameIN.FrameInBuffer))
173 {
174 Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_PACKET_MSG_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->FrameIN.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK);
183
184 Endpoint_ClearOUT();
185
186 RNDISInterfaceInfo->FrameIN.FrameLength = RNDISPacketHeader.DataLength;
187
188 RNDISInterfaceInfo->FrameIN.FrameInBuffer = true;
189 }
190
191 Endpoint_SelectEndpoint(RNDISInterfaceInfo->DataINEndpointNumber);
192
193 if (Endpoint_IsINReady() && RNDISInterfaceInfo->FrameOUT.FrameInBuffer)
194 {
195 memset(&RNDISPacketHeader, 0, sizeof(RNDIS_PACKET_MSG_t));
196
197 RNDISPacketHeader.MessageType = REMOTE_NDIS_PACKET_MSG;
198 RNDISPacketHeader.MessageLength = (sizeof(RNDIS_PACKET_MSG_t) + RNDISInterfaceInfo->FrameOUT.FrameLength);
199 RNDISPacketHeader.DataOffset = (sizeof(RNDIS_PACKET_MSG_t) - sizeof(RNDIS_Message_Header_t));
200 RNDISPacketHeader.DataLength = RNDISInterfaceInfo->FrameOUT.FrameLength;
201
202 Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_PACKET_MSG_t), NO_STREAM_CALLBACK);
203 Endpoint_Write_Stream_LE(RNDISInterfaceInfo->FrameOUT.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK);
204 Endpoint_ClearIN();
205
206 RNDISInterfaceInfo->FrameOUT.FrameInBuffer = false;
207 }
208 }
209 }
210
211 void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_t* 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->RNDISMessageBuffer;
217
218 switch (MessageHeader->MessageType)
219 {
220 case REMOTE_NDIS_INITIALIZE_MSG:
221 RNDISInterfaceInfo->ResponseReady = true;
222
223 RNDIS_INITIALIZE_MSG_t* INITIALIZE_Message = (RNDIS_INITIALIZE_MSG_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
224 RNDIS_INITIALIZE_CMPLT_t* INITIALIZE_Response = (RNDIS_INITIALIZE_CMPLT_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
225
226 INITIALIZE_Response->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
227 INITIALIZE_Response->MessageLength = sizeof(RNDIS_INITIALIZE_CMPLT_t);
228 INITIALIZE_Response->RequestId = INITIALIZE_Message->RequestId;
229 INITIALIZE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
230
231 INITIALIZE_Response->MajorVersion = REMOTE_NDIS_VERSION_MAJOR;
232 INITIALIZE_Response->MinorVersion = REMOTE_NDIS_VERSION_MINOR;
233 INITIALIZE_Response->DeviceFlags = REMOTE_NDIS_DF_CONNECTIONLESS;
234 INITIALIZE_Response->Medium = REMOTE_NDIS_MEDIUM_802_3;
235 INITIALIZE_Response->MaxPacketsPerTransfer = 1;
236 INITIALIZE_Response->MaxTransferSize = (sizeof(RNDIS_PACKET_MSG_t) + ETHERNET_FRAME_SIZE_MAX);
237 INITIALIZE_Response->PacketAlignmentFactor = 0;
238 INITIALIZE_Response->AFListOffset = 0;
239 INITIALIZE_Response->AFListSize = 0;
240
241 RNDISInterfaceInfo->CurrRNDISState = RNDIS_Initialized;
242
243 break;
244 case REMOTE_NDIS_HALT_MSG:
245 RNDISInterfaceInfo->ResponseReady = false;
246 MessageHeader->MessageLength = 0;
247
248 RNDISInterfaceInfo->CurrRNDISState = RNDIS_Uninitialized;
249
250 break;
251 case REMOTE_NDIS_QUERY_MSG:
252 RNDISInterfaceInfo->ResponseReady = true;
253
254 RNDIS_QUERY_MSG_t* QUERY_Message = (RNDIS_QUERY_MSG_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
255 RNDIS_QUERY_CMPLT_t* QUERY_Response = (RNDIS_QUERY_CMPLT_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
256 uint32_t Query_Oid = QUERY_Message->Oid;
257
258 void* QueryData = &RNDISInterfaceInfo->RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
259 QUERY_Message->InformationBufferOffset];
260 void* ResponseData = &RNDISInterfaceInfo->RNDISMessageBuffer[sizeof(RNDIS_QUERY_CMPLT_t)];
261 uint16_t ResponseSize;
262
263 QUERY_Response->MessageType = REMOTE_NDIS_QUERY_CMPLT;
264 QUERY_Response->MessageLength = sizeof(RNDIS_QUERY_CMPLT_t);
265
266 if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo, Query_Oid, QueryData, QUERY_Message->InformationBufferLength,
267 ResponseData, &ResponseSize))
268 {
269 QUERY_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
270 QUERY_Response->MessageLength += ResponseSize;
271
272 QUERY_Response->InformationBufferLength = ResponseSize;
273 QUERY_Response->InformationBufferOffset = (sizeof(RNDIS_QUERY_CMPLT_t) - sizeof(RNDIS_Message_Header_t));
274 }
275 else
276 {
277 QUERY_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;
278
279 QUERY_Response->InformationBufferLength = 0;
280 QUERY_Response->InformationBufferOffset = 0;
281 }
282
283 break;
284 case REMOTE_NDIS_SET_MSG:
285 RNDISInterfaceInfo->ResponseReady = true;
286
287 RNDIS_SET_MSG_t* SET_Message = (RNDIS_SET_MSG_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
288 RNDIS_SET_CMPLT_t* SET_Response = (RNDIS_SET_CMPLT_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
289 uint32_t SET_Oid = SET_Message->Oid;
290
291 SET_Response->MessageType = REMOTE_NDIS_SET_CMPLT;
292 SET_Response->MessageLength = sizeof(RNDIS_SET_CMPLT_t);
293 SET_Response->RequestId = SET_Message->RequestId;
294
295 void* SetData = &RNDISInterfaceInfo->RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +
296 SET_Message->InformationBufferOffset];
297
298 if (RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo, SET_Oid, SetData, SET_Message->InformationBufferLength))
299 SET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
300 else
301 SET_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;
302
303 break;
304 case REMOTE_NDIS_RESET_MSG:
305 RNDISInterfaceInfo->ResponseReady = true;
306
307 RNDIS_RESET_CMPLT_t* RESET_Response = (RNDIS_RESET_CMPLT_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
308
309 RESET_Response->MessageType = REMOTE_NDIS_RESET_CMPLT;
310 RESET_Response->MessageLength = sizeof(RNDIS_RESET_CMPLT_t);
311 RESET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
312 RESET_Response->AddressingReset = 0;
313
314 break;
315 case REMOTE_NDIS_KEEPALIVE_MSG:
316 RNDISInterfaceInfo->ResponseReady = true;
317
318 RNDIS_KEEPALIVE_MSG_t* KEEPALIVE_Message = (RNDIS_KEEPALIVE_MSG_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
319 RNDIS_KEEPALIVE_CMPLT_t* KEEPALIVE_Response = (RNDIS_KEEPALIVE_CMPLT_t*)&RNDISInterfaceInfo->RNDISMessageBuffer;
320
321 KEEPALIVE_Response->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
322 KEEPALIVE_Response->MessageLength = sizeof(RNDIS_KEEPALIVE_CMPLT_t);
323 KEEPALIVE_Response->RequestId = KEEPALIVE_Message->RequestId;
324 KEEPALIVE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;
325
326 break;
327 }
328 }
329
330 static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo,
331 uint32_t OId, void* QueryData, uint16_t QuerySize,
332 void* ResponseData, uint16_t* ResponseSize)
333 {
334 switch (OId)
335 {
336 case OID_GEN_SUPPORTED_LIST:
337 *ResponseSize = sizeof(AdapterSupportedOIDList);
338
339 memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));
340
341 return true;
342 case OID_GEN_PHYSICAL_MEDIUM:
343 *ResponseSize = sizeof(uint32_t);
344
345 /* Indicate that the device is a true ethernet link */
346 *((uint32_t*)ResponseData) = 0;
347
348 return true;
349 case OID_GEN_HARDWARE_STATUS:
350 *ResponseSize = sizeof(uint32_t);
351
352 *((uint32_t*)ResponseData) = NDIS_HardwareStatus_Ready;
353
354 return true;
355 case OID_GEN_MEDIA_SUPPORTED:
356 case OID_GEN_MEDIA_IN_USE:
357 *ResponseSize = sizeof(uint32_t);
358
359 *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIUM_802_3;
360
361 return true;
362 case OID_GEN_VENDOR_ID:
363 *ResponseSize = sizeof(uint32_t);
364
365 /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
366 *((uint32_t*)ResponseData) = 0x00FFFFFF;
367
368 return true;
369 case OID_GEN_MAXIMUM_FRAME_SIZE:
370 case OID_GEN_TRANSMIT_BLOCK_SIZE:
371 case OID_GEN_RECEIVE_BLOCK_SIZE:
372 *ResponseSize = sizeof(uint32_t);
373
374 *((uint32_t*)ResponseData) = ETHERNET_FRAME_SIZE_MAX;
375
376 return true;
377 case OID_GEN_VENDOR_DESCRIPTION:
378 *ResponseSize = (strlen(RNDISInterfaceInfo->AdapterVendorDescription) + 1);
379
380 memcpy(ResponseData, RNDISInterfaceInfo->AdapterVendorDescription, *ResponseSize);
381
382 return true;
383 case OID_GEN_MEDIA_CONNECT_STATUS:
384 *ResponseSize = sizeof(uint32_t);
385
386 *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIA_STATE_CONNECTED;
387
388 return true;
389 case OID_GEN_LINK_SPEED:
390 *ResponseSize = sizeof(uint32_t);
391
392 /* Indicate 10Mb/s link speed */
393 *((uint32_t*)ResponseData) = 100000;
394
395 return true;
396 case OID_802_3_PERMANENT_ADDRESS:
397 case OID_802_3_CURRENT_ADDRESS:
398 *ResponseSize = sizeof(MAC_Address_t);
399
400 memcpy(ResponseData, &RNDISInterfaceInfo->AdapterMACAddress, sizeof(MAC_Address_t));
401
402 return true;
403 case OID_802_3_MAXIMUM_LIST_SIZE:
404 *ResponseSize = sizeof(uint32_t);
405
406 /* Indicate only one multicast address supported */
407 *((uint32_t*)ResponseData) = 1;
408
409 return true;
410 case OID_GEN_CURRENT_PACKET_FILTER:
411 *ResponseSize = sizeof(uint32_t);
412
413 *((uint32_t*)ResponseData) = RNDISInterfaceInfo->CurrPacketFilter;
414
415 return true;
416 case OID_GEN_XMIT_OK:
417 case OID_GEN_RCV_OK:
418 case OID_GEN_XMIT_ERROR:
419 case OID_GEN_RCV_ERROR:
420 case OID_GEN_RCV_NO_BUFFER:
421 case OID_802_3_RCV_ERROR_ALIGNMENT:
422 case OID_802_3_XMIT_ONE_COLLISION:
423 case OID_802_3_XMIT_MORE_COLLISIONS:
424 *ResponseSize = sizeof(uint32_t);
425
426 /* Unused statistic OIDs - always return 0 for each */
427 *((uint32_t*)ResponseData) = 0;
428
429 return true;
430 case OID_GEN_MAXIMUM_TOTAL_SIZE:
431 *ResponseSize = sizeof(uint32_t);
432
433 /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */
434 *((uint32_t*)ResponseData) = (RNDIS_MESSAGE_BUFFER_SIZE + ETHERNET_FRAME_SIZE_MAX);
435
436 return true;
437 default:
438 return false;
439 }
440 }
441
442 static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo, uint32_t OId, void* SetData, uint16_t SetSize)
443 {
444 switch (OId)
445 {
446 case OID_GEN_CURRENT_PACKET_FILTER:
447 RNDISInterfaceInfo->CurrPacketFilter = *((uint32_t*)SetData);
448 RNDISInterfaceInfo->CurrRNDISState = ((RNDISInterfaceInfo->CurrPacketFilter) ?
449 RNDIS_Data_Initialized : RNDIS_Data_Initialized);
450
451 return true;
452 case OID_802_3_MULTICAST_LIST:
453 /* Do nothing - throw away the value from the host as it is unused */
454
455 return true;
456 default:
457 return false;
458 }
459 }
460
461 #endif