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