]> git.gir.st - tmk_keyboard.git/blob - protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/RNDISClassHost.c
Squashed 'tmk_core/' content from commit 05caacc
[tmk_keyboard.git] / protocol / lufa / LUFA-120730 / LUFA / Drivers / USB / Class / Host / RNDISClassHost.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2012.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2012 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 "../../Core/USBMode.h"
33
34 #if defined(USB_CAN_BE_HOST)
35
36 #define __INCLUDE_FROM_RNDIS_DRIVER
37 #define __INCLUDE_FROM_RNDIS_HOST_C
38 #include "RNDISClassHost.h"
39
40 uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
41 uint16_t ConfigDescriptorSize,
42 void* ConfigDescriptorData)
43 {
44 USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
45 USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
46 USB_Descriptor_Endpoint_t* NotificationEndpoint = NULL;
47 USB_Descriptor_Interface_t* RNDISControlInterface = NULL;
48
49 memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
50
51 if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
52 return RNDIS_ENUMERROR_InvalidConfigDescriptor;
53
54 RNDISControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
55
56 while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(NotificationEndpoint))
57 {
58 if (!(RNDISControlInterface) ||
59 USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
60 DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
61 {
62 if (NotificationEndpoint)
63 {
64 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
65 DCOMP_RNDIS_Host_NextRNDISDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
66 {
67 return RNDIS_ENUMERROR_NoCompatibleInterfaceFound;
68 }
69
70 DataINEndpoint = NULL;
71 DataOUTEndpoint = NULL;
72 }
73 else
74 {
75 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
76 DCOMP_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
77 {
78 return RNDIS_ENUMERROR_NoCompatibleInterfaceFound;
79 }
80
81 RNDISControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
82
83 NotificationEndpoint = NULL;
84 }
85
86 continue;
87 }
88
89 USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
90
91 if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
92 {
93 if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
94 NotificationEndpoint = EndpointData;
95 else
96 DataINEndpoint = EndpointData;
97 }
98 else
99 {
100 DataOUTEndpoint = EndpointData;
101 }
102 }
103
104 RNDISInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
105 RNDISInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
106 RNDISInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK;
107
108 RNDISInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
109 RNDISInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
110 RNDISInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
111
112 RNDISInterfaceInfo->Config.NotificationPipe.Size = le16_to_cpu(NotificationEndpoint->EndpointSize);
113 RNDISInterfaceInfo->Config.NotificationPipe.EndpointAddress = NotificationEndpoint->EndpointAddress;
114 RNDISInterfaceInfo->Config.NotificationPipe.Type = EP_TYPE_INTERRUPT;
115
116 if (!(Pipe_ConfigurePipeTable(&RNDISInterfaceInfo->Config.DataINPipe, 1)))
117 return false;
118
119 if (!(Pipe_ConfigurePipeTable(&RNDISInterfaceInfo->Config.DataOUTPipe, 1)))
120 return false;
121
122 if (!(Pipe_ConfigurePipeTable(&RNDISInterfaceInfo->Config.NotificationPipe, 1)))
123 return false;
124
125 RNDISInterfaceInfo->State.ControlInterfaceNumber = RNDISControlInterface->InterfaceNumber;
126 RNDISInterfaceInfo->State.IsActive = true;
127
128 return RNDIS_ENUMERROR_NoError;
129 }
130
131 static uint8_t DCOMP_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor)
132 {
133 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
134
135 if (Header->Type == DTYPE_Interface)
136 {
137 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
138
139 if ((Interface->Class == CDC_CSCP_CDCClass) &&
140 (Interface->SubClass == CDC_CSCP_ACMSubclass) &&
141 (Interface->Protocol == CDC_CSCP_VendorSpecificProtocol))
142 {
143 return DESCRIPTOR_SEARCH_Found;
144 }
145 }
146
147 return DESCRIPTOR_SEARCH_NotFound;
148 }
149
150 static uint8_t DCOMP_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor)
151 {
152 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
153
154 if (Header->Type == DTYPE_Interface)
155 {
156 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor,
157 USB_Descriptor_Interface_t);
158
159 if ((Interface->Class == CDC_CSCP_CDCDataClass) &&
160 (Interface->SubClass == CDC_CSCP_NoDataSubclass) &&
161 (Interface->Protocol == CDC_CSCP_NoDataProtocol))
162 {
163 return DESCRIPTOR_SEARCH_Found;
164 }
165 }
166
167 return DESCRIPTOR_SEARCH_NotFound;
168 }
169
170 static uint8_t DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor)
171 {
172 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
173
174 if (Header->Type == DTYPE_Endpoint)
175 {
176 USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
177
178 uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
179
180 if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
181 !(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
182 {
183 return DESCRIPTOR_SEARCH_Found;
184 }
185 }
186 else if (Header->Type == DTYPE_Interface)
187 {
188 return DESCRIPTOR_SEARCH_Fail;
189 }
190
191 return DESCRIPTOR_SEARCH_NotFound;
192 }
193
194 static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
195 void* Buffer,
196 const uint16_t Length)
197 {
198 USB_ControlRequest = (USB_Request_Header_t)
199 {
200 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
201 .bRequest = RNDIS_REQ_SendEncapsulatedCommand,
202 .wValue = 0,
203 .wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
204 .wLength = Length,
205 };
206
207 Pipe_SelectPipe(PIPE_CONTROLPIPE);
208
209 return USB_Host_SendControlRequest(Buffer);
210 }
211
212 static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
213 void* Buffer,
214 const uint16_t Length)
215 {
216 USB_ControlRequest = (USB_Request_Header_t)
217 {
218 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
219 .bRequest = RNDIS_REQ_GetEncapsulatedResponse,
220 .wValue = 0,
221 .wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
222 .wLength = Length,
223 };
224
225 Pipe_SelectPipe(PIPE_CONTROLPIPE);
226
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 = CPU_TO_LE32(REMOTE_NDIS_KEEPALIVE_MSG);
238 KeepAliveMessage.MessageLength = CPU_TO_LE32(sizeof(RNDIS_KeepAlive_Message_t));
239 KeepAliveMessage.RequestId = cpu_to_le32(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 = CPU_TO_LE32(REMOTE_NDIS_INITIALIZE_MSG);
264 InitMessage.MessageLength = CPU_TO_LE32(sizeof(RNDIS_Initialize_Message_t));
265 InitMessage.RequestId = cpu_to_le32(RNDISInterfaceInfo->State.RequestID++);
266
267 InitMessage.MajorVersion = CPU_TO_LE32(REMOTE_NDIS_VERSION_MAJOR);
268 InitMessage.MinorVersion = CPU_TO_LE32(REMOTE_NDIS_VERSION_MINOR);
269 InitMessage.MaxTransferSize = cpu_to_le32(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 != CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS))
284 return RNDIS_ERROR_LOGICAL_CMD_FAILED;
285
286 RNDISInterfaceInfo->State.DeviceMaxPacketSize = le32_to_cpu(InitMessageResponse.MaxTransferSize);
287
288 return HOST_SENDCONTROL_Successful;
289 }
290
291 uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
292 const uint32_t Oid,
293 void* Buffer,
294 const uint16_t Length)
295 {
296 uint8_t ErrorCode;
297
298 struct
299 {
300 RNDIS_Set_Message_t SetMessage;
301 uint8_t ContiguousBuffer[Length];
302 } SetMessageData;
303
304 RNDIS_Set_Complete_t SetMessageResponse;
305
306 SetMessageData.SetMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_SET_MSG);
307 SetMessageData.SetMessage.MessageLength = cpu_to_le32(sizeof(RNDIS_Set_Message_t) + Length);
308 SetMessageData.SetMessage.RequestId = cpu_to_le32(RNDISInterfaceInfo->State.RequestID++);
309
310 SetMessageData.SetMessage.Oid = cpu_to_le32(Oid);
311 SetMessageData.SetMessage.InformationBufferLength = cpu_to_le32(Length);
312 SetMessageData.SetMessage.InformationBufferOffset = CPU_TO_LE32(sizeof(RNDIS_Set_Message_t) - sizeof(RNDIS_Message_Header_t));
313 SetMessageData.SetMessage.DeviceVcHandle = CPU_TO_LE32(0);
314
315 memcpy(&SetMessageData.ContiguousBuffer, Buffer, Length);
316
317 if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &SetMessageData,
318 (sizeof(RNDIS_Set_Message_t) + Length))) != HOST_SENDCONTROL_Successful)
319 {
320 return ErrorCode;
321 }
322
323 if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &SetMessageResponse,
324 sizeof(RNDIS_Set_Complete_t))) != HOST_SENDCONTROL_Successful)
325 {
326 return ErrorCode;
327 }
328
329 if (SetMessageResponse.Status != CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS))
330 return RNDIS_ERROR_LOGICAL_CMD_FAILED;
331
332 return HOST_SENDCONTROL_Successful;
333 }
334
335 uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
336 const uint32_t Oid,
337 void* Buffer,
338 const uint16_t MaxLength)
339 {
340 uint8_t ErrorCode;
341
342 RNDIS_Query_Message_t QueryMessage;
343
344 struct
345 {
346 RNDIS_Query_Complete_t QueryMessageResponse;
347 uint8_t ContiguousBuffer[MaxLength];
348 } QueryMessageResponseData;
349
350 QueryMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_QUERY_MSG);
351 QueryMessage.MessageLength = CPU_TO_LE32(sizeof(RNDIS_Query_Message_t));
352 QueryMessage.RequestId = cpu_to_le32(RNDISInterfaceInfo->State.RequestID++);
353
354 QueryMessage.Oid = cpu_to_le32(Oid);
355 QueryMessage.InformationBufferLength = CPU_TO_LE32(0);
356 QueryMessage.InformationBufferOffset = CPU_TO_LE32(0);
357 QueryMessage.DeviceVcHandle = CPU_TO_LE32(0);
358
359 if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &QueryMessage,
360 sizeof(RNDIS_Query_Message_t))) != HOST_SENDCONTROL_Successful)
361 {
362 return ErrorCode;
363 }
364
365 if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &QueryMessageResponseData,
366 sizeof(QueryMessageResponseData))) != HOST_SENDCONTROL_Successful)
367 {
368 return ErrorCode;
369 }
370
371 if (QueryMessageResponseData.QueryMessageResponse.Status != CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS))
372 return RNDIS_ERROR_LOGICAL_CMD_FAILED;
373
374 memcpy(Buffer, &QueryMessageResponseData.ContiguousBuffer, MaxLength);
375
376 return HOST_SENDCONTROL_Successful;
377 }
378
379 bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
380 {
381 bool PacketWaiting;
382
383 if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
384 return false;
385
386 Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipe.Address);
387
388 Pipe_Unfreeze();
389 PacketWaiting = Pipe_IsINReceived();
390 Pipe_Freeze();
391
392 return PacketWaiting;
393 }
394
395 uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
396 void* Buffer,
397 uint16_t* const PacketLength)
398 {
399 uint8_t ErrorCode;
400
401 if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
402 return PIPE_READYWAIT_DeviceDisconnected;
403
404 Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipe.Address);
405 Pipe_Unfreeze();
406
407 if (!(Pipe_IsReadWriteAllowed()))
408 {
409 if (Pipe_IsINReceived())
410 Pipe_ClearIN();
411
412 *PacketLength = 0;
413 Pipe_Freeze();
414 return PIPE_RWSTREAM_NoError;
415 }
416
417 RNDIS_Packet_Message_t DeviceMessage;
418
419 if ((ErrorCode = Pipe_Read_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
420 NULL)) != PIPE_RWSTREAM_NoError)
421 {
422 return ErrorCode;
423 }
424
425 *PacketLength = (uint16_t)le32_to_cpu(DeviceMessage.DataLength);
426
427 Pipe_Discard_Stream(le32_to_cpu(DeviceMessage.DataOffset) -
428 (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)),
429 NULL);
430
431 Pipe_Read_Stream_LE(Buffer, *PacketLength, NULL);
432
433 if (!(Pipe_BytesInPipe()))
434 Pipe_ClearIN();
435
436 Pipe_Freeze();
437
438 return PIPE_RWSTREAM_NoError;
439 }
440
441 uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
442 void* Buffer,
443 const uint16_t PacketLength)
444 {
445 uint8_t ErrorCode;
446
447 if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
448 return PIPE_READYWAIT_DeviceDisconnected;
449
450 RNDIS_Packet_Message_t DeviceMessage;
451
452 memset(&DeviceMessage, 0, sizeof(RNDIS_Packet_Message_t));
453 DeviceMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_PACKET_MSG);
454 DeviceMessage.MessageLength = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) + PacketLength);
455 DeviceMessage.DataOffset = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
456 DeviceMessage.DataLength = cpu_to_le32(PacketLength);
457
458 Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataOUTPipe.Address);
459 Pipe_Unfreeze();
460
461 if ((ErrorCode = Pipe_Write_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
462 NULL)) != PIPE_RWSTREAM_NoError)
463 {
464 return ErrorCode;
465 }
466
467 Pipe_Write_Stream_LE(Buffer, PacketLength, NULL);
468 Pipe_ClearOUT();
469
470 Pipe_Freeze();
471
472 return PIPE_RWSTREAM_NoError;
473 }
474
475 #endif
476
Imprint / Impressum