Move out many of the common class driver constants into grouped enums, to make them...
[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 = RNDIS_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 = RNDIS_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
390 Pipe_Unfreeze();
391 PacketWaiting = Pipe_IsINReceived();
392 Pipe_Freeze();
393
394 return PacketWaiting;
395 }
396
397 uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
398 void* Buffer,
399 uint16_t* const PacketLength)
400 {
401 uint8_t ErrorCode;
402
403 if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
404 return PIPE_READYWAIT_DeviceDisconnected;
405
406 Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
407 Pipe_Unfreeze();
408
409 if (!(Pipe_IsReadWriteAllowed()))
410 {
411 if (Pipe_IsINReceived())
412 Pipe_ClearIN();
413
414 *PacketLength = 0;
415 Pipe_Freeze();
416 return PIPE_RWSTREAM_NoError;
417 }
418
419 RNDIS_Packet_Message_t DeviceMessage;
420
421 if ((ErrorCode = Pipe_Read_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
422 NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
423 {
424 return ErrorCode;
425 }
426
427 *PacketLength = (uint16_t)DeviceMessage.DataLength;
428
429 Pipe_Discard_Stream(DeviceMessage.DataOffset - (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)),
430 NO_STREAM_CALLBACK);
431
432 Pipe_Read_Stream_LE(Buffer, *PacketLength, NO_STREAM_CALLBACK);
433
434 if (!(Pipe_BytesInPipe()))
435 Pipe_ClearIN();
436
437 Pipe_Freeze();
438
439 return PIPE_RWSTREAM_NoError;
440 }
441
442 uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
443 void* Buffer,
444 const uint16_t PacketLength)
445 {
446 uint8_t ErrorCode;
447
448 if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
449 return PIPE_READYWAIT_DeviceDisconnected;
450
451 RNDIS_Packet_Message_t DeviceMessage;
452
453 memset(&DeviceMessage, 0, sizeof(RNDIS_Packet_Message_t));
454 DeviceMessage.MessageType = REMOTE_NDIS_PACKET_MSG;
455 DeviceMessage.MessageLength = (sizeof(RNDIS_Packet_Message_t) + PacketLength);
456 DeviceMessage.DataOffset = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
457 DeviceMessage.DataLength = PacketLength;
458
459 Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber);
460 Pipe_Unfreeze();
461
462 if ((ErrorCode = Pipe_Write_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
463 NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
464 {
465 return ErrorCode;
466 }
467
468 Pipe_Write_Stream_LE(Buffer, PacketLength, NO_STREAM_CALLBACK);
469 Pipe_ClearOUT();
470
471 Pipe_Freeze();
472
473 return PIPE_RWSTREAM_NoError;
474 }
475
476 #endif