Descriptors.c 12.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/*
             LUFA Library
     Copyright (C) Dean Camera, 2009.
              
  dean [at] fourwalledcubicle [dot] com
      www.fourwalledcubicle.com
*/

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

  Permission to use, copy, modify, and distribute this software
  and its documentation for any purpose and without fee is hereby
  granted, provided that the above copyright notice appear in all
  copies and that both that the copyright notice and this
  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
  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.
*/

/** \file
 *
 *  USB Device Descriptors, for library use when in USB device mode. Descriptors are special 
 *  computer-readable structures which the host requests upon device enumeration, to determine
 *  the device's capabilities and functions.  
 */

#include "Descriptors.h"

/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall
 *  device characteristics, including the supported USB version, control endpoint size and the
 *  number of device configurations. The descriptor is read out by the USB host when the enumeration
 *  process begins.
 */
USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
{
47
	.Header                 = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
48
		
49
50
51
52
	.USBSpecification       = VERSION_BCD(01.10),
	.Class                  = 0xEF,
	.SubClass               = 0x02,
	.Protocol               = 0x01,
53
				
54
	.Endpoint0Size          = FIXED_CONTROL_ENDPOINT_SIZE,
55
		
56
57
58
	.VendorID               = 0x03EB,
	.ProductID              = 0x204E,
	.ReleaseNumber          = 0x0000,
59
		
60
61
	.ManufacturerStrIndex   = 0x01,
	.ProductStrIndex        = 0x02,
62
	.SerialNumStrIndex      = USE_INTERNAL_SERIAL,
63
		
64
	.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
65
66
67
68
69
70
71
72
73
};

/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
 *  of the device in one of its supported configurations, including information about any device interfaces
 *  and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
 *  a configuration so that the host may correctly communicate with the USB device.
 */
USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
{
74
	.Config = 
75
		{
76
			.Header                 = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
77

78
79
			.TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
			.TotalInterfaces        = 4,
80
				
81
82
			.ConfigurationNumber    = 1,
			.ConfigurationStrIndex  = NO_DESCRIPTOR,
83
				
84
			.ConfigAttributes       = (USB_CONFIG_ATTR_BUSPOWERED | USB_CONFIG_ATTR_SELFPOWERED),
85
			
86
			.MaxPowerConsumption    = USB_CONFIG_POWER_MA(100)
87
88
		},
		
89
	.IAD1 = 
90
		{
91
			.Header                 = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation},
92

93
94
			.FirstInterfaceIndex    = 0,
			.TotalInterfaces        = 2,
95

96
97
98
			.Class                  = 0x02,
			.SubClass               = 0x02,
			.Protocol               = 0x01,
99

100
			.IADStrIndex            = NO_DESCRIPTOR
101
102
		},

103
	.CDC1_CCI_Interface = 
104
		{
105
			.Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
106

107
108
			.InterfaceNumber        = 0,
			.AlternateSetting       = 0,
109
			
110
			.TotalEndpoints         = 1,
111
				
112
113
114
			.Class                  = 0x02,
			.SubClass               = 0x02,
			.Protocol               = 0x01,
115
				
116
			.InterfaceStrIndex      = NO_DESCRIPTOR
117
118
		},

119
	.CDC1_Functional_IntHeader = 
120
		{
121
122
			.Header                 = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(2)), .Type = 0x24},
			.SubType                = 0x00,
123
			
124
			.Data                   = {0x01, 0x10}
125
126
		},

127
	.CDC1_Functional_CallManagement = 
128
		{
129
130
			.Header                 = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(2)), .Type = 0x24},
			.SubType                = 0x01,
131
			
132
			.Data                   = {0x03, 0x01}
133
134
		},

135
	.CDC1_Functional_AbstractControlManagement = 
136
		{
137
138
			.Header                 = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(1)), .Type = 0x24},
			.SubType                = 0x02,
139
			
140
			.Data                   = {0x06}
141
142
		},
		
143
	.CDC1_Functional_Union = 
144
		{
145
146
			.Header                 = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(2)), .Type = 0x24},
			.SubType                = 0x06,
147
			
148
			.Data                   = {0x00, 0x01}
149
150
		},

151
	.CDC1_ManagementEndpoint = 
152
		{
153
			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
154
										 
155
			.EndpointAddress        = (ENDPOINT_DESCRIPTOR_DIR_IN | CDC1_NOTIFICATION_EPNUM),
156
			.Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
157
158
			.EndpointSize           = CDC_NOTIFICATION_EPSIZE,
			.PollingIntervalMS      = 0xFF
159
160
		},

161
	.CDC1_DCI_Interface = 
162
		{
163
			.Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
164

165
166
			.InterfaceNumber        = 1,
			.AlternateSetting       = 0,
167
			
168
			.TotalEndpoints         = 2,
169
				
170
171
172
			.Class                  = 0x0A,
			.SubClass               = 0x00,
			.Protocol               = 0x00,
173
				
174
			.InterfaceStrIndex      = NO_DESCRIPTOR
175
176
		},

177
	.CDC1_DataOutEndpoint = 
178
		{
179
			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
180
										 
181
			.EndpointAddress        = (ENDPOINT_DESCRIPTOR_DIR_OUT | CDC1_RX_EPNUM),
182
			.Attributes             = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
183
184
			.EndpointSize           = CDC_TXRX_EPSIZE,
			.PollingIntervalMS      = 0x00
185
186
		},
		
187
	.CDC1_DataInEndpoint = 
188
		{
189
			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
190
										 
191
			.EndpointAddress        = (ENDPOINT_DESCRIPTOR_DIR_IN | CDC1_TX_EPNUM),
192
			.Attributes             = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
193
194
			.EndpointSize           = CDC_TXRX_EPSIZE,
			.PollingIntervalMS      = 0x00
195
196
		},

197
	.IAD2 = 
198
		{
199
			.Header                 = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation},
200

201
202
			.FirstInterfaceIndex    = 2,
			.TotalInterfaces        = 2,
203

204
205
206
			.Class                  = 0x02,
			.SubClass               = 0x02,
			.Protocol               = 0x01,
207

208
			.IADStrIndex            = NO_DESCRIPTOR
209
210
		},

211
	.CDC2_CCI_Interface = 
212
		{
213
			.Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
214

215
216
			.InterfaceNumber        = 2,
			.AlternateSetting       = 0,
217
			
218
			.TotalEndpoints         = 1,
219
				
220
221
222
			.Class                  = 0x02,
			.SubClass               = 0x02,
			.Protocol               = 0x01,
223
				
224
			.InterfaceStrIndex      = NO_DESCRIPTOR
225
226
		},

227
	.CDC2_Functional_IntHeader = 
228
		{
229
230
			.Header                 = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(2)), .Type = 0x24},
			.SubType                = 0x00,
231
			
232
			.Data                   = {0x01, 0x10}
233
234
		},

235
	.CDC2_Functional_CallManagement = 
236
		{
237
238
			.Header                 = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(2)), .Type = 0x24},
			.SubType                = 0x01,
239
			
240
			.Data                   = {0x03, 0x03}
241
242
		},

243
	.CDC2_Functional_AbstractControlManagement = 
244
		{
245
246
			.Header                 = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(1)), .Type = 0x24},
			.SubType                = 0x02,
247
			
248
			.Data                   = {0x06}
249
250
		},
		
251
	.CDC2_Functional_Union = 
252
		{
253
254
			.Header                 = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(2)), .Type = 0x24},
			.SubType                = 0x06,
255
			
256
			.Data                   = {0x02, 0x03}
257
258
		},

259
	.CDC2_ManagementEndpoint = 
260
		{
261
			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
262
										 
263
			.EndpointAddress        = (ENDPOINT_DESCRIPTOR_DIR_IN | CDC2_NOTIFICATION_EPNUM),
264
			.Attributes             = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
265
266
			.EndpointSize           = CDC_NOTIFICATION_EPSIZE,
			.PollingIntervalMS      = 0xFF
267
268
		},

269
	.CDC2_DCI_Interface = 
270
		{
271
			.Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
272

273
274
			.InterfaceNumber        = 3,
			.AlternateSetting       = 0,
275
			
276
			.TotalEndpoints         = 2,
277
				
278
279
280
			.Class                  = 0x0A,
			.SubClass               = 0x00,
			.Protocol               = 0x00,
281
				
282
			.InterfaceStrIndex      = NO_DESCRIPTOR
283
284
		},

285
	.CDC2_DataOutEndpoint = 
286
		{
287
			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
288
										 
289
			.EndpointAddress        = (ENDPOINT_DESCRIPTOR_DIR_OUT | CDC2_RX_EPNUM),
290
			.Attributes             = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
291
292
			.EndpointSize           = CDC_TXRX_EPSIZE,
			.PollingIntervalMS      = 0x00
293
294
		},
		
295
	.CDC2_DataInEndpoint = 
296
		{
297
			.Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
298
										 
299
			.EndpointAddress        = (ENDPOINT_DESCRIPTOR_DIR_IN | CDC2_TX_EPNUM),
300
			.Attributes             = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
301
302
			.EndpointSize           = CDC_TXRX_EPSIZE,
			.PollingIntervalMS      = 0x00
303
304
305
306
307
308
309
310
311
		}
};

/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
 *  the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
 *  via the language ID table available at USB.org what languages the device supports for its string descriptors.
 */
USB_Descriptor_String_t PROGMEM LanguageString =
{
312
	.Header                 = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
313
		
314
	.UnicodeString          = {LANGUAGE_ID_ENG}
315
316
317
318
319
320
321
322
};

/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
 *  form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
 *  Descriptor.
 */
USB_Descriptor_String_t PROGMEM ManufacturerString =
{
323
	.Header                 = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String},
324
		
325
	.UnicodeString          = L"Dean Camera"
326
327
328
329
330
331
332
333
};

/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
 *  and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
 *  Descriptor.
 */
USB_Descriptor_String_t PROGMEM ProductString =
{
334
	.Header                 = {.Size = USB_STRING_LEN(13), .Type = DTYPE_String},
335
		
336
	.UnicodeString          = L"LUFA Dual CDC Demo"
337
338
};

339
/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
340
 *  documentation) by the application code so that the address and size of a requested descriptor can be given
341
 *  to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
342
343
344
 *  is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
 *  USB host.
 */
345
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
346
347
348
349
350
351
352
353
354
355
{
	const uint8_t  DescriptorType   = (wValue >> 8);
	const uint8_t  DescriptorNumber = (wValue & 0xFF);

	void*    Address = NULL;
	uint16_t Size    = NO_DESCRIPTOR;

	switch (DescriptorType)
	{
		case DTYPE_Device:
356
			Address = (void*)&DeviceDescriptor;
357
358
			Size    = sizeof(USB_Descriptor_Device_t);
			break;
359
		case DTYPE_Configuration: 
360
			Address = (void*)&ConfigurationDescriptor;
361
362
			Size    = sizeof(USB_Descriptor_Configuration_t);
			break;
363
		case DTYPE_String: 
364
365
			switch (DescriptorNumber)
			{
366
				case 0x00: 
367
					Address = (void*)&LanguageString;
368
369
					Size    = pgm_read_byte(&LanguageString.Header.Size);
					break;
370
				case 0x01: 
371
					Address = (void*)&ManufacturerString;
372
373
					Size    = pgm_read_byte(&ManufacturerString.Header.Size);
					break;
374
				case 0x02: 
375
					Address = (void*)&ProductString;
376
377
378
379
380
381
382
383
384
385
					Size    = pgm_read_byte(&ProductString.Header.Size);
					break;
			}
			
			break;
	}
	
	*DescriptorAddress = Address;	
	return Size;
}