Add comments to the currently completed portions of the incomplete Test and Measureme...
[pub/USBasp.git] / LUFA / Drivers / USB / Class / Host / 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_HOST)
34
35 #define __INCLUDE_FROM_RNDIS_CLASS_HOST_C
36 #define __INCLUDE_FROM_RNDIS_DRIVER
37 #include "RNDIS.h"
38
39 uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
40 uint16_t ConfigDescriptorSize,
41 void* ConfigDescriptorData)
42 {
43 uint8_t FoundEndpoints = 0;
44
45 memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
46
47 if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
48 return RNDIS_ENUMERROR_InvalidConfigDescriptor;
49
50 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
51 DCOMP_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
52 {
53 return RNDIS_ENUMERROR_NoRNDISInterfaceFound;
54 }
55
56 RNDISInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_Interface_t).InterfaceNumber;
57
58 while (FoundEndpoints != (RNDIS_FOUND_NOTIFICATION_IN | RNDIS_FOUND_DATAPIPE_IN | RNDIS_FOUND_DATAPIPE_OUT))
59 {
60 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
61 DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
62 {
63 if (FoundEndpoints & RNDIS_FOUND_NOTIFICATION_IN)
64 {
65 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
66 DCOMP_RNDIS_Host_NextRNDISDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
67 {
68 return RNDIS_ENUMERROR_NoRNDISInterfaceFound;
69 }
70 }
71 else
72 {
73 FoundEndpoints = 0;
74
75 Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
76 Pipe_DisablePipe();
77 Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber);
78 Pipe_DisablePipe();
79 Pipe_SelectPipe(RNDISInterfaceInfo->Config.NotificationPipeNumber);
80 Pipe_DisablePipe();
81
82 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
83 DCOMP_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
84 {
85 return RNDIS_ENUMERROR_NoRNDISInterfaceFound;
86 }
87 }
88
89 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
90 DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
91 {
92 return RNDIS_ENUMERROR_EndpointsNotFound;
93 }
94 }
95
96 USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
97
98 if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
99 {
100 if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
101 {
102 Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.NotificationPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
103 EndpointData->EndpointAddress, EndpointData->EndpointSize,
104 RNDISInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
105 RNDISInterfaceInfo->State.NotificationPipeSize = EndpointData->EndpointSize;
106
107 Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS);
108
109 FoundEndpoints |= RNDIS_FOUND_NOTIFICATION_IN;
110 }
111 }
112 else
113 {
114 if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
115 {
116 Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
117 EndpointData->EndpointAddress, EndpointData->EndpointSize,
118 RNDISInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
119 RNDISInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
120
121 FoundEndpoints |= RNDIS_FOUND_DATAPIPE_IN;
122 }
123 else
124 {
125 Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
126 EndpointData->EndpointAddress, EndpointData->EndpointSize,
127 RNDISInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
128 RNDISInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
129
130 FoundEndpoints |= RNDIS_FOUND_DATAPIPE_OUT;
131 }
132 }
133 }
134
135 RNDISInterfaceInfo->State.IsActive = true;
136 return RNDIS_ENUMERROR_NoError;
137 }
138
139 static uint8_t DCOMP_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor)
140 {
141 if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
142 {
143 USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
144 USB_Descriptor_Interface_t);
145
146 if ((CurrentInterface->Class == RNDIS_CONTROL_CLASS) &&
147 (CurrentInterface->SubClass == RNDIS_CONTROL_SUBCLASS) &&
148 (CurrentInterface->Protocol == RNDIS_CONTROL_PROTOCOL))
149 {
150 return DESCRIPTOR_SEARCH_Found;
151 }
152 }
153
154 return DESCRIPTOR_SEARCH_NotFound;
155 }
156
157 static uint8_t DCOMP_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor)
158 {
159 if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
160 {
161 USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
162 USB_Descriptor_Interface_t);
163
164 if ((CurrentInterface->Class == RNDIS_DATA_CLASS) &&
165 (CurrentInterface->SubClass == RNDIS_DATA_SUBCLASS) &&
166 (CurrentInterface->Protocol == RNDIS_DATA_PROTOCOL))
167 {
168 return DESCRIPTOR_SEARCH_Found;
169 }
170 }
171
172 return DESCRIPTOR_SEARCH_NotFound;
173 }
174
175 static uint8_t DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor)
176 {
177 if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
178 {
179 USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor,
180 USB_Descriptor_Endpoint_t);
181
182 uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK);
183
184 if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
185 !(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress)))
186 {
187 return DESCRIPTOR_SEARCH_Found;
188 }
189 }
190 else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
191 {
192 return DESCRIPTOR_SEARCH_Fail;
193 }
194
195 return DESCRIPTOR_SEARCH_NotFound;
196 }
197
198 static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
199 void* Buffer,
200 const uint16_t Length)
201 {
202 USB_ControlRequest = (USB_Request_Header_t)
203 {
204 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
205 .bRequest = REQ_SendEncapsulatedCommand,
206 .wValue = 0,
207 .wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
208 .wLength = Length,
209 };
210
211 Pipe_SelectPipe(PIPE_CONTROLPIPE);
212 return USB_Host_SendControlRequest(Buffer);
213 }
214
215 static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
216 void* Buffer,
217 const uint16_t Length)
218 {
219 USB_ControlRequest = (USB_Request_Header_t)
220 {
221 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
222 .bRequest = REQ_GetEncapsulatedResponse,
223 .wValue = 0,
224 .wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
225 .wLength = Length,
226 };
227
228 Pipe_SelectPipe(PIPE_CONTROLPIPE);
229 return USB_Host_SendControlRequest(Buffer);
230 }
231
232 uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
233 {
234 uint8_t ErrorCode;
235
236 RNDIS_KeepAlive_Message_t KeepAliveMessage;
237 RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse;
238
239 KeepAliveMessage.MessageType = REMOTE_NDIS_KEEPALIVE_MSG;
240 KeepAliveMessage.MessageLength = sizeof(RNDIS_KeepAlive_Message_t);
241 KeepAliveMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
242
243 if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &KeepAliveMessage,
244 sizeof(RNDIS_KeepAlive_Message_t))) != HOST_SENDCONTROL_Successful)
245 {
246 return ErrorCode;
247 }
248
249 if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &KeepAliveMessageResponse,
250 sizeof(RNDIS_KeepAlive_Complete_t))) != HOST_SENDCONTROL_Successful)
251 {
252 return ErrorCode;
253 }
254
255 return HOST_SENDCONTROL_Successful;
256 }
257
258 uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
259 {
260 uint8_t ErrorCode;
261
262 RNDIS_Initialize_Message_t InitMessage;
263 RNDIS_Initialize_Complete_t InitMessageResponse;
264
265 InitMessage.MessageType = REMOTE_NDIS_INITIALIZE_MSG;
266 InitMessage.MessageLength = sizeof(RNDIS_Initialize_Message_t);
267 InitMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
268
269 InitMessage.MajorVersion = REMOTE_NDIS_VERSION_MAJOR;
270 InitMessage.MinorVersion = REMOTE_NDIS_VERSION_MINOR;
271 InitMessage.MaxTransferSize = RNDISInterfaceInfo->Config.HostMaxPacketSize;
272
273 if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &InitMessage,
274 sizeof(RNDIS_Initialize_Message_t))) != HOST_SENDCONTROL_Successful)
275 {
276 return ErrorCode;
277 }
278
279 if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &InitMessageResponse,
280 sizeof(RNDIS_Initialize_Complete_t))) != HOST_SENDCONTROL_Successful)
281 {
282 return ErrorCode;
283 }
284
285 if (InitMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
286 return RNDIS_COMMAND_FAILED;
287
288 RNDISInterfaceInfo->State.DeviceMaxPacketSize = InitMessageResponse.MaxTransferSize;
289
290 return HOST_SENDCONTROL_Successful;
291 }
292
293 uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
294 const uint32_t Oid,
295 void* Buffer,
296 const uint16_t Length)
297 {
298 uint8_t ErrorCode;
299
300 struct
301 {
302 RNDIS_Set_Message_t SetMessage;
303 uint8_t ContiguousBuffer[Length];
304 } SetMessageData;
305
306 RNDIS_Set_Complete_t SetMessageResponse;
307
308 SetMessageData.SetMessage.MessageType = REMOTE_NDIS_SET_MSG;
309 SetMessageData.SetMessage.MessageLength = sizeof(RNDIS_Set_Message_t) + Length;
310 SetMessageData.SetMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
311
312 SetMessageData.SetMessage.Oid = Oid;
313 SetMessageData.SetMessage.InformationBufferLength = Length;
314 SetMessageData.SetMessage.InformationBufferOffset = (sizeof(RNDIS_Set_Message_t) - sizeof(RNDIS_Message_Header_t));
315 SetMessageData.SetMessage.DeviceVcHandle = 0;
316
317 memcpy(&SetMessageData.ContiguousBuffer, Buffer, Length);
318
319 if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &SetMessageData,
320 SetMessageData.SetMessage.MessageLength)) != HOST_SENDCONTROL_Successful)
321 {
322 return ErrorCode;
323 }
324
325 if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &SetMessageResponse,
326 sizeof(RNDIS_Set_Complete_t))) != HOST_SENDCONTROL_Successful)
327 {
328 return ErrorCode;
329 }
330
331 if (SetMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
332 return RNDIS_COMMAND_FAILED;
333
334 return HOST_SENDCONTROL_Successful;
335 }
336
337 uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
338 const uint32_t Oid,
339 void* Buffer,
340 const uint16_t MaxLength)
341 {
342 uint8_t ErrorCode;
343
344 RNDIS_Query_Message_t QueryMessage;
345
346 struct
347 {
348 RNDIS_Query_Complete_t QueryMessageResponse;
349 uint8_t ContiguousBuffer[MaxLength];
350 } QueryMessageResponseData;
351
352 QueryMessage.MessageType = REMOTE_NDIS_QUERY_MSG;
353 QueryMessage.MessageLength = sizeof(RNDIS_Query_Message_t);
354 QueryMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
355
356 QueryMessage.Oid = Oid;
357 QueryMessage.InformationBufferLength = 0;
358 QueryMessage.InformationBufferOffset = 0;
359 QueryMessage.DeviceVcHandle = 0;
360
361 if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &QueryMessage,
362 sizeof(RNDIS_Query_Message_t))) != HOST_SENDCONTROL_Successful)
363 {
364 return ErrorCode;
365 }
366
367 if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &QueryMessageResponseData,
368 sizeof(QueryMessageResponseData))) != HOST_SENDCONTROL_Successful)
369 {
370 return ErrorCode;
371 }
372
373 if (QueryMessageResponseData.QueryMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
374 return RNDIS_COMMAND_FAILED;
375
376 memcpy(Buffer, &QueryMessageResponseData.ContiguousBuffer, MaxLength);
377
378 return HOST_SENDCONTROL_Successful;
379 }
380
381 bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
382 {
383 bool PacketWaiting;
384
385 if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
386 return false;
387
388 Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
389 Pipe_SetPipeToken(PIPE_TOKEN_IN);
390
391 Pipe_Unfreeze();
392
393 PacketWaiting = Pipe_IsINReceived();
394
395 Pipe_Freeze();
396
397 return PacketWaiting;
398 }
399
400 uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
401 void* Buffer,
402 uint16_t* const PacketLength)
403 {
404 uint8_t ErrorCode;
405
406 if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
407 return PIPE_READYWAIT_DeviceDisconnected;
408
409 Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
410 Pipe_SetPipeToken(PIPE_TOKEN_IN);
411 Pipe_Unfreeze();
412
413 if (!(Pipe_IsReadWriteAllowed()))
414 {
415 if (Pipe_IsINReceived())
416 Pipe_ClearIN();
417
418 *PacketLength = 0;
419 Pipe_Freeze();
420 return PIPE_RWSTREAM_NoError;
421 }
422
423 RNDIS_Packet_Message_t DeviceMessage;
424
425 if ((ErrorCode = Pipe_Read_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
426 NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
427 {
428 return ErrorCode;
429 }
430
431 *PacketLength = (uint16_t)DeviceMessage.DataLength;
432
433 Pipe_Discard_Stream(DeviceMessage.DataOffset - (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)),
434 NO_STREAM_CALLBACK);
435
436 Pipe_Read_Stream_LE(Buffer, *PacketLength, NO_STREAM_CALLBACK);
437
438 if (!(Pipe_BytesInPipe()))
439 Pipe_ClearIN();
440
441 Pipe_Freeze();
442
443 return PIPE_RWSTREAM_NoError;
444 }
445
446 uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
447 void* Buffer,
448 const uint16_t PacketLength)
449 {
450 uint8_t ErrorCode;
451
452 if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
453 return PIPE_READYWAIT_DeviceDisconnected;
454
455 RNDIS_Packet_Message_t DeviceMessage;
456
457 memset(&DeviceMessage, 0, sizeof(RNDIS_Packet_Message_t));
458 DeviceMessage.MessageType = REMOTE_NDIS_PACKET_MSG;
459 DeviceMessage.MessageLength = (sizeof(RNDIS_Packet_Message_t) + PacketLength);
460 DeviceMessage.DataOffset = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
461 DeviceMessage.DataLength = PacketLength;
462
463 Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber);
464 Pipe_Unfreeze();
465
466 if ((ErrorCode = Pipe_Write_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
467 NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
468 {
469 return ErrorCode;
470 }
471
472 Pipe_Write_Stream_LE(Buffer, PacketLength, NO_STREAM_CALLBACK);
473 Pipe_ClearOUT();
474
475 Pipe_Freeze();
476
477 return PIPE_RWSTREAM_NoError;
478 }
479
480 #endif