c7bf482c317f54c6a4c8b8d990468070dedaed52
[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, uint16_t ConfigDescriptorSize,
40 void* ConfigDescriptorData)
41 {
42 uint8_t FoundEndpoints = 0;
43
44 memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
45
46 if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
47 return RNDIS_ENUMERROR_InvalidConfigDescriptor;
48
49 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
50 DComp_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
51 {
52 return RNDIS_ENUMERROR_NoRNDISInterfaceFound;
53 }
54
55 RNDISInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_Interface_t).InterfaceNumber;
56
57 while (FoundEndpoints != (RNDIS_FOUND_NOTIFICATION_IN | RNDIS_FOUND_DATAPIPE_IN | RNDIS_FOUND_DATAPIPE_OUT))
58 {
59 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
60 DComp_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
61 {
62 if (FoundEndpoints & RNDIS_FOUND_NOTIFICATION_IN)
63 {
64 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
65 DComp_RNDIS_Host_NextRNDISDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
66 {
67 return RNDIS_ENUMERROR_NoRNDISInterfaceFound;
68 }
69 }
70 else
71 {
72 FoundEndpoints = 0;
73
74 Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
75 Pipe_DisablePipe();
76 Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber);
77 Pipe_DisablePipe();
78 Pipe_SelectPipe(RNDISInterfaceInfo->Config.NotificationPipeNumber);
79 Pipe_DisablePipe();
80
81 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
82 DComp_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
83 {
84 return RNDIS_ENUMERROR_NoRNDISInterfaceFound;
85 }
86 }
87
88 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
89 DComp_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
90 {
91 return RNDIS_ENUMERROR_EndpointsNotFound;
92 }
93 }
94
95 USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
96
97 if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
98 {
99 if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
100 {
101 Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.NotificationPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
102 EndpointData->EndpointAddress, EndpointData->EndpointSize,
103 RNDISInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
104 RNDISInterfaceInfo->State.NotificationPipeSize = EndpointData->EndpointSize;
105
106 Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS);
107
108 FoundEndpoints |= RNDIS_FOUND_NOTIFICATION_IN;
109 }
110 }
111 else
112 {
113 if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
114 {
115 Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
116 EndpointData->EndpointAddress, EndpointData->EndpointSize,
117 RNDISInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
118 RNDISInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
119
120 FoundEndpoints |= RNDIS_FOUND_DATAPIPE_IN;
121 }
122 else
123 {
124 Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
125 EndpointData->EndpointAddress, EndpointData->EndpointSize,
126 RNDISInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
127
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, uint16_t Length)
200 {
201 USB_ControlRequest = (USB_Request_Header_t)
202 {
203 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
204 .bRequest = REQ_SendEncapsulatedCommand,
205 .wValue = 0,
206 .wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
207 .wLength = Length,
208 };
209
210 Pipe_SelectPipe(PIPE_CONTROLPIPE);
211 return USB_Host_SendControlRequest(Buffer);
212 }
213
214 static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
215 void* Buffer, uint16_t Length)
216 {
217 USB_ControlRequest = (USB_Request_Header_t)
218 {
219 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
220 .bRequest = REQ_GetEncapsulatedResponse,
221 .wValue = 0,
222 .wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
223 .wLength = Length,
224 };
225
226 Pipe_SelectPipe(PIPE_CONTROLPIPE);
227 return USB_Host_SendControlRequest(Buffer);
228 }
229
230 uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
231 {
232 uint8_t ErrorCode;
233
234 RNDIS_KeepAlive_Message_t KeepAliveMessage;
235 RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse;
236
237 KeepAliveMessage.MessageType = REMOTE_NDIS_KEEPALIVE_MSG;
238 KeepAliveMessage.MessageLength = sizeof(RNDIS_KeepAlive_Message_t);
239 KeepAliveMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
240
241 if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &KeepAliveMessage,
242 sizeof(RNDIS_KeepAlive_Message_t))) != HOST_SENDCONTROL_Successful)
243 {
244 return ErrorCode;
245 }
246
247 if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &KeepAliveMessageResponse,
248 sizeof(RNDIS_KeepAlive_Complete_t))) != HOST_SENDCONTROL_Successful)
249 {
250 return ErrorCode;
251 }
252
253 return HOST_SENDCONTROL_Successful;
254 }
255
256 uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
257 {
258 uint8_t ErrorCode;
259
260 RNDIS_Initialize_Message_t InitMessage;
261 RNDIS_Initialize_Complete_t InitMessageResponse;
262
263 InitMessage.MessageType = REMOTE_NDIS_INITIALIZE_MSG;
264 InitMessage.MessageLength = sizeof(RNDIS_Initialize_Message_t);
265 InitMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
266
267 InitMessage.MajorVersion = REMOTE_NDIS_VERSION_MAJOR;
268 InitMessage.MinorVersion = REMOTE_NDIS_VERSION_MINOR;
269 InitMessage.MaxTransferSize = RNDISInterfaceInfo->Config.HostMaxPacketSize;
270
271 if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &InitMessage,
272 sizeof(RNDIS_Initialize_Message_t))) != HOST_SENDCONTROL_Successful)
273 {
274 return ErrorCode;
275 }
276
277 if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &InitMessageResponse,
278 sizeof(RNDIS_Initialize_Complete_t))) != HOST_SENDCONTROL_Successful)
279 {
280 return ErrorCode;
281 }
282
283 if (InitMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
284 return RNDIS_COMMAND_FAILED;
285
286 RNDISInterfaceInfo->State.DeviceMaxPacketSize = InitMessageResponse.MaxTransferSize;
287
288 return HOST_SENDCONTROL_Successful;
289 }
290
291 uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint32_t Oid, void* Buffer, uint16_t Length)
292 {
293 uint8_t ErrorCode;
294
295 struct
296 {
297 RNDIS_Set_Message_t SetMessage;
298 uint8_t ContigiousBuffer[Length];
299 } SetMessageData;
300
301 RNDIS_Set_Complete_t SetMessageResponse;
302
303 SetMessageData.SetMessage.MessageType = REMOTE_NDIS_SET_MSG;
304 SetMessageData.SetMessage.MessageLength = sizeof(RNDIS_Set_Message_t) + Length;
305 SetMessageData.SetMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
306
307 SetMessageData.SetMessage.Oid = Oid;
308 SetMessageData.SetMessage.InformationBufferLength = Length;
309 SetMessageData.SetMessage.InformationBufferOffset = (sizeof(RNDIS_Set_Message_t) - sizeof(RNDIS_Message_Header_t));
310 SetMessageData.SetMessage.DeviceVcHandle = 0;
311
312 memcpy(&SetMessageData.ContigiousBuffer, Buffer, Length);
313
314 if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &SetMessageData,
315 SetMessageData.SetMessage.MessageLength)) != HOST_SENDCONTROL_Successful)
316 {
317 return ErrorCode;
318 }
319
320 if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &SetMessageResponse,
321 sizeof(RNDIS_Set_Complete_t))) != HOST_SENDCONTROL_Successful)
322 {
323 return ErrorCode;
324 }
325
326 if (SetMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
327 return RNDIS_COMMAND_FAILED;
328
329 return HOST_SENDCONTROL_Successful;
330 }
331
332 uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint32_t Oid, void* Buffer, uint16_t MaxLength)
333 {
334 uint8_t ErrorCode;
335
336 RNDIS_Query_Message_t QueryMessage;
337
338 struct
339 {
340 RNDIS_Query_Complete_t QueryMessageResponse;
341 uint8_t ContigiousBuffer[MaxLength];
342 } QueryMessageResponseData;
343
344 QueryMessage.MessageType = REMOTE_NDIS_QUERY_MSG;
345 QueryMessage.MessageLength = sizeof(RNDIS_Query_Message_t);
346 QueryMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
347
348 QueryMessage.Oid = Oid;
349 QueryMessage.InformationBufferLength = 0;
350 QueryMessage.InformationBufferOffset = 0;
351 QueryMessage.DeviceVcHandle = 0;
352
353 if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &QueryMessage,
354 sizeof(RNDIS_Query_Message_t))) != HOST_SENDCONTROL_Successful)
355 {
356 return ErrorCode;
357 }
358
359 if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &QueryMessageResponseData,
360 sizeof(QueryMessageResponseData))) != HOST_SENDCONTROL_Successful)
361 {
362 return ErrorCode;
363 }
364
365 if (QueryMessageResponseData.QueryMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
366 return RNDIS_COMMAND_FAILED;
367
368 memcpy(Buffer, &QueryMessageResponseData.ContigiousBuffer, MaxLength);
369
370 return HOST_SENDCONTROL_Successful;
371 }
372
373 bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
374 {
375 bool PacketWaiting;
376
377 if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
378 return false;
379
380 Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
381 Pipe_SetPipeToken(PIPE_TOKEN_IN);
382
383 Pipe_Unfreeze();
384
385 PacketWaiting = (Pipe_IsINReceived() && Pipe_BytesInPipe());
386
387 Pipe_Freeze();
388
389 return PacketWaiting;
390 }
391
392 uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, void* Buffer, uint16_t* PacketLength)
393 {
394 uint8_t ErrorCode;
395
396 if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
397 return PIPE_READYWAIT_DeviceDisconnected;
398
399 Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
400 Pipe_SetPipeToken(PIPE_TOKEN_IN);
401 Pipe_Unfreeze();
402
403 if (!(Pipe_IsReadWriteAllowed()))
404 {
405 if (Pipe_IsINReceived())
406 Pipe_ClearIN();
407
408 *PacketLength = 0;
409 Pipe_Freeze();
410 return PIPE_RWSTREAM_NoError;
411 }
412
413 RNDIS_Packet_Message_t DeviceMessage;
414
415 if ((ErrorCode = Pipe_Read_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
416 NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
417 {
418 return ErrorCode;
419 }
420
421 *PacketLength = (uint16_t)DeviceMessage.DataLength;
422
423 Pipe_Discard_Stream(DeviceMessage.DataOffset - (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)),
424 NO_STREAM_CALLBACK);
425
426 Pipe_Read_Stream_LE(Buffer, *PacketLength, NO_STREAM_CALLBACK);
427
428 if (!(Pipe_BytesInPipe()))
429 Pipe_ClearIN();
430
431 Pipe_Freeze();
432
433 return PIPE_RWSTREAM_NoError;
434 }
435
436 uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, void* Buffer, uint16_t PacketLength)
437 {
438 uint8_t ErrorCode;
439
440 if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
441 return PIPE_READYWAIT_DeviceDisconnected;
442
443 RNDIS_Packet_Message_t DeviceMessage;
444
445 memset(&DeviceMessage, 0, sizeof(RNDIS_Packet_Message_t));
446 DeviceMessage.MessageType = REMOTE_NDIS_PACKET_MSG;
447 DeviceMessage.MessageLength = (sizeof(RNDIS_Packet_Message_t) + PacketLength);
448 DeviceMessage.DataOffset = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
449 DeviceMessage.DataLength = PacketLength;
450
451 Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber);
452 Pipe_Unfreeze();
453
454 if ((ErrorCode = Pipe_Write_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
455 NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
456 {
457 return ErrorCode;
458 }
459
460 Pipe_Write_Stream_LE(Buffer, PacketLength, NO_STREAM_CALLBACK);
461 Pipe_ClearOUT();
462
463 Pipe_Freeze();
464
465 return PIPE_RWSTREAM_NoError;
466 }
467
468 #endif