Fix low level host mode demos not correctly fetching the next endpoint when an invali...
[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 USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
44 USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
45 USB_Descriptor_Endpoint_t* NotificationEndpoint = NULL;
46
47 memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
48
49 if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
50 return RNDIS_ENUMERROR_InvalidConfigDescriptor;
51
52 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
53 DCOMP_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
54 {
55 return RNDIS_ENUMERROR_NoCompatibleInterfaceFound;
56 }
57
58 RNDISInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_PCAST(ConfigDescriptorData,
59 USB_Descriptor_Interface_t)->InterfaceNumber;
60
61 while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(NotificationEndpoint))
62 {
63 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
64 DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
65 {
66 if (NotificationEndpoint)
67 {
68 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
69 DCOMP_RNDIS_Host_NextRNDISDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
70 {
71 return RNDIS_ENUMERROR_NoCompatibleInterfaceFound;
72 }
73
74 DataINEndpoint = NULL;
75 DataOUTEndpoint = NULL;
76 }
77 else
78 {
79 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
80 DCOMP_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
81 {
82 return RNDIS_ENUMERROR_NoCompatibleInterfaceFound;
83 }
84
85 RNDISInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_PCAST(ConfigDescriptorData,
86 USB_Descriptor_Interface_t)->InterfaceNumber;
87
88 NotificationEndpoint = NULL;
89 }
90
91 continue;
92 }
93
94 USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
95
96 if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
97 {
98 if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
99 NotificationEndpoint = EndpointData;
100 else
101 DataINEndpoint = EndpointData;
102 }
103 else
104 {
105 DataOUTEndpoint = EndpointData;
106 }
107 }
108
109 for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
110 {
111 if (PipeNum == RNDISInterfaceInfo->Config.DataINPipeNumber)
112 {
113 Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN,
114 DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize,
115 RNDISInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
116
117 RNDISInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
118 }
119 else if (PipeNum == RNDISInterfaceInfo->Config.DataOUTPipeNumber)
120 {
121 Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT,
122 DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize,
123 RNDISInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
124
125 RNDISInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
126 }
127 else if (PipeNum == RNDISInterfaceInfo->Config.NotificationPipeNumber)
128 {
129 Pipe_ConfigurePipe(PipeNum, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
130 NotificationEndpoint->EndpointAddress, NotificationEndpoint->EndpointSize,
131 RNDISInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
132 Pipe_SetInterruptPeriod(NotificationEndpoint->PollingIntervalMS);
133
134 RNDISInterfaceInfo->State.NotificationPipeSize = NotificationEndpoint->EndpointSize;
135 }
136 }
137
138 RNDISInterfaceInfo->State.IsActive = true;
139
140 return RNDIS_ENUMERROR_NoError;
141 }
142
143 static uint8_t DCOMP_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor)
144 {
145 if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
146 {
147 USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
148 USB_Descriptor_Interface_t);
149
150 if ((CurrentInterface->Class == RNDIS_CONTROL_CLASS) &&
151 (CurrentInterface->SubClass == RNDIS_CONTROL_SUBCLASS) &&
152 (CurrentInterface->Protocol == RNDIS_CONTROL_PROTOCOL))
153 {
154 return DESCRIPTOR_SEARCH_Found;
155 }
156 }
157
158 return DESCRIPTOR_SEARCH_NotFound;
159 }
160
161 static uint8_t DCOMP_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor)
162 {
163 if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
164 {
165 USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
166 USB_Descriptor_Interface_t);
167
168 if ((CurrentInterface->Class == RNDIS_DATA_CLASS) &&
169 (CurrentInterface->SubClass == RNDIS_DATA_SUBCLASS) &&
170 (CurrentInterface->Protocol == RNDIS_DATA_PROTOCOL))
171 {
172 return DESCRIPTOR_SEARCH_Found;
173 }
174 }
175
176 return DESCRIPTOR_SEARCH_NotFound;
177 }
178
179 static uint8_t DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor)
180 {
181 if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
182 {
183 USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor,
184 USB_Descriptor_Endpoint_t);
185
186 uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK);
187
188 if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
189 !(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress)))
190 {
191 return DESCRIPTOR_SEARCH_Found;
192 }
193 }
194 else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
195 {
196 return DESCRIPTOR_SEARCH_Fail;
197 }
198
199 return DESCRIPTOR_SEARCH_NotFound;
200 }
201
202 static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
203 void* Buffer,
204 const uint16_t Length)
205 {
206 USB_ControlRequest = (USB_Request_Header_t)
207 {
208 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
209 .bRequest = RNDIS_REQ_SendEncapsulatedCommand,
210 .wValue = 0,
211 .wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
212 .wLength = Length,
213 };
214
215 Pipe_SelectPipe(PIPE_CONTROLPIPE);
216 return USB_Host_SendControlRequest(Buffer);
217 }
218
219 static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
220 void* Buffer,
221 const uint16_t Length)
222 {
223 USB_ControlRequest = (USB_Request_Header_t)
224 {
225 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
226 .bRequest = RNDIS_REQ_GetEncapsulatedResponse,
227 .wValue = 0,
228 .wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
229 .wLength = Length,
230 };
231
232 Pipe_SelectPipe(PIPE_CONTROLPIPE);
233 return USB_Host_SendControlRequest(Buffer);
234 }
235
236 uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
237 {
238 uint8_t ErrorCode;
239
240 RNDIS_KeepAlive_Message_t KeepAliveMessage;
241 RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse;
242
243 KeepAliveMessage.MessageType = REMOTE_NDIS_KEEPALIVE_MSG;
244 KeepAliveMessage.MessageLength = sizeof(RNDIS_KeepAlive_Message_t);
245 KeepAliveMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
246
247 if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &KeepAliveMessage,
248 sizeof(RNDIS_KeepAlive_Message_t))) != HOST_SENDCONTROL_Successful)
249 {
250 return ErrorCode;
251 }
252
253 if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &KeepAliveMessageResponse,
254 sizeof(RNDIS_KeepAlive_Complete_t))) != HOST_SENDCONTROL_Successful)
255 {
256 return ErrorCode;
257 }
258
259 return HOST_SENDCONTROL_Successful;
260 }
261
262 uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
263 {
264 uint8_t ErrorCode;
265
266 RNDIS_Initialize_Message_t InitMessage;
267 RNDIS_Initialize_Complete_t InitMessageResponse;
268
269 InitMessage.MessageType = REMOTE_NDIS_INITIALIZE_MSG;
270 InitMessage.MessageLength = sizeof(RNDIS_Initialize_Message_t);
271 InitMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
272
273 InitMessage.MajorVersion = REMOTE_NDIS_VERSION_MAJOR;
274 InitMessage.MinorVersion = REMOTE_NDIS_VERSION_MINOR;
275 InitMessage.MaxTransferSize = RNDISInterfaceInfo->Config.HostMaxPacketSize;
276
277 if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &InitMessage,
278 sizeof(RNDIS_Initialize_Message_t))) != HOST_SENDCONTROL_Successful)
279 {
280 return ErrorCode;
281 }
282
283 if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &InitMessageResponse,
284 sizeof(RNDIS_Initialize_Complete_t))) != HOST_SENDCONTROL_Successful)
285 {
286 return ErrorCode;
287 }
288
289 if (InitMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
290 return RNDIS_COMMAND_FAILED;
291
292 RNDISInterfaceInfo->State.DeviceMaxPacketSize = InitMessageResponse.MaxTransferSize;
293
294 return HOST_SENDCONTROL_Successful;
295 }
296
297 uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
298 const uint32_t Oid,
299 void* Buffer,
300 const uint16_t Length)
301 {
302 uint8_t ErrorCode;
303
304 struct
305 {
306 RNDIS_Set_Message_t SetMessage;
307 uint8_t ContiguousBuffer[Length];
308 } SetMessageData;
309
310 RNDIS_Set_Complete_t SetMessageResponse;
311
312 SetMessageData.SetMessage.MessageType = REMOTE_NDIS_SET_MSG;
313 SetMessageData.SetMessage.MessageLength = sizeof(RNDIS_Set_Message_t) + Length;
314 SetMessageData.SetMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
315
316 SetMessageData.SetMessage.Oid = Oid;
317 SetMessageData.SetMessage.InformationBufferLength = Length;
318 SetMessageData.SetMessage.InformationBufferOffset = (sizeof(RNDIS_Set_Message_t) - sizeof(RNDIS_Message_Header_t));
319 SetMessageData.SetMessage.DeviceVcHandle = 0;
320
321 memcpy(&SetMessageData.ContiguousBuffer, Buffer, Length);
322
323 if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &SetMessageData,
324 SetMessageData.SetMessage.MessageLength)) != HOST_SENDCONTROL_Successful)
325 {
326 return ErrorCode;
327 }
328
329 if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &SetMessageResponse,
330 sizeof(RNDIS_Set_Complete_t))) != HOST_SENDCONTROL_Successful)
331 {
332 return ErrorCode;
333 }
334
335 if (SetMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
336 return RNDIS_COMMAND_FAILED;
337
338 return HOST_SENDCONTROL_Successful;
339 }
340
341 uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
342 const uint32_t Oid,
343 void* Buffer,
344 const uint16_t MaxLength)
345 {
346 uint8_t ErrorCode;
347
348 RNDIS_Query_Message_t QueryMessage;
349
350 struct
351 {
352 RNDIS_Query_Complete_t QueryMessageResponse;
353 uint8_t ContiguousBuffer[MaxLength];
354 } QueryMessageResponseData;
355
356 QueryMessage.MessageType = REMOTE_NDIS_QUERY_MSG;
357 QueryMessage.MessageLength = sizeof(RNDIS_Query_Message_t);
358 QueryMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
359
360 QueryMessage.Oid = Oid;
361 QueryMessage.InformationBufferLength = 0;
362 QueryMessage.InformationBufferOffset = 0;
363 QueryMessage.DeviceVcHandle = 0;
364
365 if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &QueryMessage,
366 sizeof(RNDIS_Query_Message_t))) != HOST_SENDCONTROL_Successful)
367 {
368 return ErrorCode;
369 }
370
371 if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &QueryMessageResponseData,
372 sizeof(QueryMessageResponseData))) != HOST_SENDCONTROL_Successful)
373 {
374 return ErrorCode;
375 }
376
377 if (QueryMessageResponseData.QueryMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
378 return RNDIS_COMMAND_FAILED;
379
380 memcpy(Buffer, &QueryMessageResponseData.ContiguousBuffer, MaxLength);
381
382 return HOST_SENDCONTROL_Successful;
383 }
384
385 bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
386 {
387 bool PacketWaiting;
388
389 if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
390 return false;
391
392 Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
393
394 Pipe_Unfreeze();
395 PacketWaiting = Pipe_IsINReceived();
396 Pipe_Freeze();
397
398 return PacketWaiting;
399 }
400
401 uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
402 void* Buffer,
403 uint16_t* const PacketLength)
404 {
405 uint8_t ErrorCode;
406
407 if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
408 return PIPE_READYWAIT_DeviceDisconnected;
409
410 Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
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