RNDIS.c 16.4 KB
Newer Older
1
2
3
/*
             LUFA Library
     Copyright (C) Dean Camera, 2010.
4

5
  dean [at] fourwalledcubicle [dot] com
6
           www.lufa-lib.org
7
8
9
10
11
*/

/*
  Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)

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
17
18
  permission notice and warranty disclaimer appear in supporting
  documentation, and that the name of the author not be used in
  advertising or publicity pertaining to distribution of the
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  software without specific, written prior permission.

  The author disclaim all warranties with regard to this
  software, including all implied warranties of merchantability
  and fitness.  In no event shall the author be liable for any
  special, indirect or consequential damages or any damages
  whatsoever resulting from loss of use, data or profits, whether
  in an action of contract, negligence or other tortious action,
  arising out of or in connection with the use or performance of
  this software.
*/

#define  __INCLUDE_FROM_USB_DRIVER
#include "../../HighLevel/USBMode.h"
#if defined(USB_CAN_BE_HOST)

#define  __INCLUDE_FROM_RNDIS_DRIVER
36
#define  __INCLUDE_FROM_RNDIS_HOST_C
37
38
#include "RNDIS.h"

39
40
41
uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
                                  uint16_t ConfigDescriptorSize,
                                  void* ConfigDescriptorData)
42
{
43
44
45
46
	USB_Descriptor_Endpoint_t*  DataINEndpoint        = NULL;
	USB_Descriptor_Endpoint_t*  DataOUTEndpoint       = NULL;
	USB_Descriptor_Endpoint_t*  NotificationEndpoint  = NULL;
	USB_Descriptor_Interface_t* RNDISControlInterface = NULL;
47
48
49
50
51

	memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));

	if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
	  return RNDIS_ENUMERROR_InvalidConfigDescriptor;
52

53
	RNDISControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
54

55
	while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(NotificationEndpoint))
56
	{
57
58
		if (!(RNDISControlInterface) ||
		    USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
59
		                              DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
60
		{
61
			if (NotificationEndpoint)
62
			{
63
64
				if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
											  DCOMP_RNDIS_Host_NextRNDISDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
65
				{
66
					return RNDIS_ENUMERROR_NoCompatibleInterfaceFound;
67
				}
68
69
70

				DataINEndpoint  = NULL;
				DataOUTEndpoint = NULL;
71
72
73
74
			}
			else
			{
				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
89
		USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);

90
		if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
91
		{
92
93
94
95
			if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
			  NotificationEndpoint = EndpointData;
			else
			  DataINEndpoint = EndpointData;
96
97
98
		}
		else
		{
99
100
101
			DataOUTEndpoint = EndpointData;
		}
	}
102

103
104
	for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
	{
105
106
107
108
109
110
111
		uint16_t Size;
		uint8_t  Type;
		uint8_t  Token;
		uint8_t  EndpointAddress;
		uint8_t  InterruptPeriod;
		bool     DoubleBanked;

112
113
		if (PipeNum == RNDISInterfaceInfo->Config.DataINPipeNumber)
		{
114
115
116
117
118
119
			Size            = DataINEndpoint->EndpointSize;
			EndpointAddress = DataINEndpoint->EndpointAddress;
			Token           = PIPE_TOKEN_IN;
			Type            = EP_TYPE_BULK;
			DoubleBanked    = RNDISInterfaceInfo->Config.DataINPipeDoubleBank;
			InterruptPeriod = 0;
120

121
122
123
124
			RNDISInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
		}
		else if (PipeNum == RNDISInterfaceInfo->Config.DataOUTPipeNumber)
		{
125
126
127
128
129
130
			Size            = DataOUTEndpoint->EndpointSize;
			EndpointAddress = DataOUTEndpoint->EndpointAddress;
			Token           = PIPE_TOKEN_OUT;
			Type            = EP_TYPE_BULK;
			DoubleBanked    = RNDISInterfaceInfo->Config.DataOUTPipeDoubleBank;
			InterruptPeriod = 0;
131
132
133
134
135

			RNDISInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
		}
		else if (PipeNum == RNDISInterfaceInfo->Config.NotificationPipeNumber)
		{
136
137
138
139
140
141
			Size            = NotificationEndpoint->EndpointSize;
			EndpointAddress = NotificationEndpoint->EndpointAddress;
			Token           = PIPE_TOKEN_IN;
			Type            = EP_TYPE_INTERRUPT;
			DoubleBanked    = RNDISInterfaceInfo->Config.NotificationPipeDoubleBank;
			InterruptPeriod = NotificationEndpoint->PollingIntervalMS;
142
143

			RNDISInterfaceInfo->State.NotificationPipeSize = NotificationEndpoint->EndpointSize;
144
		}
145
146
147
148
149
150
151
152
153
154
155
156
157
		else
		{
			continue;
		}
		
		if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size,
		                         DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE)))
		{
			return CDC_ENUMERROR_PipeConfigurationFailed;
		}
		
		if (InterruptPeriod)
		  Pipe_SetInterruptPeriod(InterruptPeriod);
158
159
	}

160
	RNDISInterfaceInfo->State.ControlInterfaceNumber = RNDISControlInterface->InterfaceNumber;
161
	RNDISInterfaceInfo->State.IsActive = true;
162

163
164
165
	return RNDIS_ENUMERROR_NoError;
}

166
static uint8_t DCOMP_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor)
167
{
168
169
170
	USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);

	if (Header->Type == DTYPE_Interface)
171
	{
172
		USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
173

174
175
176
		if ((Interface->Class    == CDC_CSCP_CDCClass)    &&
		    (Interface->SubClass == CDC_CSCP_ACMSubclass) &&
		    (Interface->Protocol == CDC_CSCP_VendorSpecificProtocol))
177
178
179
180
		{
			return DESCRIPTOR_SEARCH_Found;
		}
	}
181

182
183
184
	return DESCRIPTOR_SEARCH_NotFound;
}

185
static uint8_t DCOMP_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor)
186
{
187
188
189
	USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);

	if (Header->Type == DTYPE_Interface)
190
	{
191
192
		USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor,
		                                                         USB_Descriptor_Interface_t);
193

194
195
196
		if ((Interface->Class    == CDC_CSCP_CDCDataClass)   &&
		    (Interface->SubClass == CDC_CSCP_NoDataSubclass) &&
		    (Interface->Protocol == CDC_CSCP_NoDataProtocol))
197
198
199
200
		{
			return DESCRIPTOR_SEARCH_Found;
		}
	}
201

202
203
204
	return DESCRIPTOR_SEARCH_NotFound;
}

205
static uint8_t DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor)
206
{
207
208
209
	USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);

	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
219
220
		{
			return DESCRIPTOR_SEARCH_Found;
		}
	}
221
	else if (Header->Type == DTYPE_Interface)
222
223
224
225
226
227
228
229
	{
		return DESCRIPTOR_SEARCH_Fail;
	}

	return DESCRIPTOR_SEARCH_NotFound;
}

static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
230
231
                                             void* Buffer,
                                             const uint16_t Length)
232
233
234
235
{
	USB_ControlRequest = (USB_Request_Header_t)
		{
			.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
236
			.bRequest      = RNDIS_REQ_SendEncapsulatedCommand,
237
238
239
240
241
242
243
244
245
246
			.wValue        = 0,
			.wIndex        = RNDISInterfaceInfo->State.ControlInterfaceNumber,
			.wLength       = Length,
		};

	Pipe_SelectPipe(PIPE_CONTROLPIPE);
	return USB_Host_SendControlRequest(Buffer);
}

static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
247
248
                                             void* Buffer,
                                             const uint16_t Length)
249
250
251
252
{
	USB_ControlRequest = (USB_Request_Header_t)
		{
			.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
253
			.bRequest      = RNDIS_REQ_GetEncapsulatedResponse,
254
255
256
257
			.wValue        = 0,
			.wIndex        = RNDISInterfaceInfo->State.ControlInterfaceNumber,
			.wLength       = Length,
		};
258

259
260
261
262
263
264
265
266
267
268
	Pipe_SelectPipe(PIPE_CONTROLPIPE);
	return USB_Host_SendControlRequest(Buffer);
}

uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
{
	uint8_t ErrorCode;

	RNDIS_KeepAlive_Message_t  KeepAliveMessage;
	RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse;
269

270
271
272
273
274
275
276
277
278
	KeepAliveMessage.MessageType     = REMOTE_NDIS_KEEPALIVE_MSG;
	KeepAliveMessage.MessageLength   = sizeof(RNDIS_KeepAlive_Message_t);
	KeepAliveMessage.RequestId       = RNDISInterfaceInfo->State.RequestID++;

	if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &KeepAliveMessage,
	                                               sizeof(RNDIS_KeepAlive_Message_t))) != HOST_SENDCONTROL_Successful)
	{
		return ErrorCode;
	}
279

280
281
282
283
284
	if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &KeepAliveMessageResponse,
	                                               sizeof(RNDIS_KeepAlive_Complete_t))) != HOST_SENDCONTROL_Successful)
	{
		return ErrorCode;
	}
285

286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
	return HOST_SENDCONTROL_Successful;
}

uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
{
	uint8_t ErrorCode;

	RNDIS_Initialize_Message_t  InitMessage;
	RNDIS_Initialize_Complete_t InitMessageResponse;

	InitMessage.MessageType     = REMOTE_NDIS_INITIALIZE_MSG;
	InitMessage.MessageLength   = sizeof(RNDIS_Initialize_Message_t);
	InitMessage.RequestId       = RNDISInterfaceInfo->State.RequestID++;

	InitMessage.MajorVersion    = REMOTE_NDIS_VERSION_MAJOR;
	InitMessage.MinorVersion    = REMOTE_NDIS_VERSION_MINOR;
	InitMessage.MaxTransferSize = RNDISInterfaceInfo->Config.HostMaxPacketSize;
303

304
305
306
307
308
	if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &InitMessage,
	                                               sizeof(RNDIS_Initialize_Message_t))) != HOST_SENDCONTROL_Successful)
	{
		return ErrorCode;
	}
309

310
311
312
313
314
315
316
317
	if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &InitMessageResponse,
	                                               sizeof(RNDIS_Initialize_Complete_t))) != HOST_SENDCONTROL_Successful)
	{
		return ErrorCode;
	}

	if (InitMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
	  return RNDIS_COMMAND_FAILED;
318

319
	RNDISInterfaceInfo->State.DeviceMaxPacketSize = InitMessageResponse.MaxTransferSize;
320

321
322
323
	return HOST_SENDCONTROL_Successful;
}

324
325
326
327
uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
                                    const uint32_t Oid,
                                    void* Buffer,
                                    const uint16_t Length)
328
329
330
331
332
333
{
	uint8_t ErrorCode;

	struct
	{
		RNDIS_Set_Message_t SetMessage;
334
		uint8_t             ContiguousBuffer[Length];
335
	} SetMessageData;
336

337
	RNDIS_Set_Complete_t SetMessageResponse;
338

339
340
341
	SetMessageData.SetMessage.MessageType    = REMOTE_NDIS_SET_MSG;
	SetMessageData.SetMessage.MessageLength  = sizeof(RNDIS_Set_Message_t) + Length;
	SetMessageData.SetMessage.RequestId      = RNDISInterfaceInfo->State.RequestID++;
342

343
344
345
346
	SetMessageData.SetMessage.Oid            = Oid;
	SetMessageData.SetMessage.InformationBufferLength = Length;
	SetMessageData.SetMessage.InformationBufferOffset = (sizeof(RNDIS_Set_Message_t) - sizeof(RNDIS_Message_Header_t));
	SetMessageData.SetMessage.DeviceVcHandle = 0;
347

348
	memcpy(&SetMessageData.ContiguousBuffer, Buffer, Length);
349
350
351
352
353
354

	if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &SetMessageData,
	                                               SetMessageData.SetMessage.MessageLength)) != HOST_SENDCONTROL_Successful)
	{
		return ErrorCode;
	}
355

356
357
358
359
360
361
362
363
	if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &SetMessageResponse,
	                                               sizeof(RNDIS_Set_Complete_t))) != HOST_SENDCONTROL_Successful)
	{
		return ErrorCode;
	}

	if (SetMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
	  return RNDIS_COMMAND_FAILED;
364

365
366
367
	return HOST_SENDCONTROL_Successful;
}

368
369
370
371
uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
                                      const uint32_t Oid,
                                      void* Buffer,
                                      const uint16_t MaxLength)
372
373
374
375
376
377
378
379
{
	uint8_t ErrorCode;

	RNDIS_Query_Message_t QueryMessage;

	struct
	{
		RNDIS_Query_Complete_t QueryMessageResponse;
380
		uint8_t                ContiguousBuffer[MaxLength];
381
382
383
384
385
	} QueryMessageResponseData;

	QueryMessage.MessageType    = REMOTE_NDIS_QUERY_MSG;
	QueryMessage.MessageLength  = sizeof(RNDIS_Query_Message_t);
	QueryMessage.RequestId      = RNDISInterfaceInfo->State.RequestID++;
386

387
388
389
390
391
392
393
394
395
396
	QueryMessage.Oid            = Oid;
	QueryMessage.InformationBufferLength = 0;
	QueryMessage.InformationBufferOffset = 0;
	QueryMessage.DeviceVcHandle = 0;

	if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &QueryMessage,
	                                               sizeof(RNDIS_Query_Message_t))) != HOST_SENDCONTROL_Successful)
	{
		return ErrorCode;
	}
397

398
399
400
401
402
403
404
405
406
	if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &QueryMessageResponseData,
	                                               sizeof(QueryMessageResponseData))) != HOST_SENDCONTROL_Successful)
	{
		return ErrorCode;
	}

	if (QueryMessageResponseData.QueryMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
	  return RNDIS_COMMAND_FAILED;

407
	memcpy(Buffer, &QueryMessageResponseData.ContiguousBuffer, MaxLength);
408
409
410
411
412
413
414
415
416
417
418
419

	return HOST_SENDCONTROL_Successful;
}

bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
{
	bool PacketWaiting;

	if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
	  return false;

	Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
420

421
	Pipe_Unfreeze();
422
	PacketWaiting = Pipe_IsINReceived();
423
	Pipe_Freeze();
424

425
426
427
	return PacketWaiting;
}

428
429
430
uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
                              void* Buffer,
                              uint16_t* const PacketLength)
431
432
433
434
435
436
437
438
{
	uint8_t ErrorCode;

	if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
	  return PIPE_READYWAIT_DeviceDisconnected;

	Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
	Pipe_Unfreeze();
439

440
441
442
443
	if (!(Pipe_IsReadWriteAllowed()))
	{
		if (Pipe_IsINReceived())
		  Pipe_ClearIN();
444

445
446
447
448
449
450
		*PacketLength = 0;
		Pipe_Freeze();
		return PIPE_RWSTREAM_NoError;
	}

	RNDIS_Packet_Message_t DeviceMessage;
451

452
453
454
455
456
457
458
	if ((ErrorCode = Pipe_Read_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
	                                     NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
	{
		return ErrorCode;
	}

	*PacketLength = (uint16_t)DeviceMessage.DataLength;
459

460
461
	Pipe_Discard_Stream(DeviceMessage.DataOffset - (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)),
	                    NO_STREAM_CALLBACK);
462

463
	Pipe_Read_Stream_LE(Buffer, *PacketLength, NO_STREAM_CALLBACK);
464

465
466
467
468
	if (!(Pipe_BytesInPipe()))
	  Pipe_ClearIN();

	Pipe_Freeze();
469

470
471
472
	return PIPE_RWSTREAM_NoError;
}

473
474
475
uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
                              void* Buffer,
                              const uint16_t PacketLength)
476
477
478
479
480
481
482
483
484
485
486
487
488
{
	uint8_t ErrorCode;

	if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
	  return PIPE_READYWAIT_DeviceDisconnected;

	RNDIS_Packet_Message_t DeviceMessage;

	memset(&DeviceMessage, 0, sizeof(RNDIS_Packet_Message_t));
	DeviceMessage.MessageType   = REMOTE_NDIS_PACKET_MSG;
	DeviceMessage.MessageLength = (sizeof(RNDIS_Packet_Message_t) + PacketLength);
	DeviceMessage.DataOffset    = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
	DeviceMessage.DataLength    = PacketLength;
489

490
491
492
493
494
495
496
497
498
499
500
501
502
	Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber);
	Pipe_Unfreeze();

	if ((ErrorCode = Pipe_Write_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
	                                      NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
	{
		return ErrorCode;
	}

	Pipe_Write_Stream_LE(Buffer, PacketLength, NO_STREAM_CALLBACK);
	Pipe_ClearOUT();

	Pipe_Freeze();
503

504
505
506
507
	return PIPE_RWSTREAM_NoError;
}

#endif
508