Project

General

Profile

Download (21.6 KB) Statistics
| Branch: | Tag: | Revision:
1
/* AT91SAM7 USB interface code for OpenPCD 
2
 * (C) 2006 by Harald Welte <laforge@gnumonks.org>
3
 *
4
 *  This program is free software; you can redistribute it and/or modify
5
 *  it under the terms of the GNU General Public License as published by 
6
 *  the Free Software Foundation; either version 2 of the License, or
7
 *  (at your option) any later version.
8
 *
9
 *  This program is distributed in the hope that it will be useful,
10
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 *  GNU General Public License for more details.
13
 *
14
 *  You should have received a copy of the GNU General Public License
15
 *  along with this program; if not, write to the Free Software
16
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * based on existing AT91SAM7 UDP CDC ACM example code, licensed as followed:
19
 *----------------------------------------------------------------------------
20
 *      ATMEL Microcontroller Software Support  -  ROUSSET  -
21
 *----------------------------------------------------------------------------
22
 * The software is delivered "AS IS" without warranty or condition of any
23
 * kind, either express, implied or statutory. This includes without
24
 * limitation any warranty or condition with respect to merchantability or
25
 * fitness for any particular purpose, or against the infringements of
26
 * intellectual property rights of others.
27
 *----------------------------------------------------------------------------
28
 */
29

    
30
#include <errno.h>
31
#include <usb_ch9.h>
32
#include <sys/types.h>
33
#include <asm/atomic.h>
34
#include <lib_AT91SAM7.h>
35
#include <openpcd.h>
36

    
37
#include <usb_strings_app.h>
38

    
39
#include <os/pcd_enumerate.h>
40
#include <os/req_ctx.h>
41
#include <dfu/dfu.h>
42
#include "../openpcd.h"
43
#include <os/dbgu.h>
44

    
45
#include "../config.h"
46

    
47
//#define DEBUG_UDP_IRQ
48
//#define DEBUG_UDP_IRQ_IN
49
//#define DEBUG_UDP_IRQ_OUT
50
//#define DEBUG_UDP_EP0
51

    
52
#ifdef DEBUG_UDP_IRQ
53
#define DEBUGI(x, args ...)	DEBUGP(x, ## args)
54
#else
55
#define DEBUGI(x, args ...)	do { } while (0)
56
#endif
57

    
58
#ifdef DEBUG_UDP_IRQ_IN
59
#define DEBUGII(x, args ...)	DEBUGP(x, ## args)
60
#else
61
#define DEBUGII(x, args ...)	do { } while (0)
62
#endif
63

    
64
#ifdef DEBUG_UDP_IRQ_OUT
65
#define DEBUGIO(x, args ...)	DEBUGP(x, ## args)
66
#else
67
#define DEBUGIO(x, args ...)	do { } while (0)
68
#endif
69

    
70
#ifdef DEBUG_UDP_EP0
71
#define DEBUGE(x, args ...)	DEBUGP(x, ## args)
72
#else
73
#define DEBUGE(x, args ...)	do { } while (0)
74
#endif
75

    
76
#define CONFIG_DFU
77

    
78
#ifdef CONFIG_DFU
79
static const struct dfuapi *dfu = DFU_API_LOCATION;
80
#define udp_init		dfu->udp_init
81
#define udp_ep0_send_data	dfu->ep0_send_data
82
#define udp_ep0_send_zlp	dfu->ep0_send_zlp
83
#define udp_ep0_send_stall	dfu->ep0_send_stall
84
#else
85
#error non-DFU builds currently not supported (yet) again
86
#endif
87

    
88
#ifdef CONFIG_USB_HID
89
#include "usb_descriptors_hid.h"
90
#else
91
#include "usb_descriptors_openpcd.h"
92
#endif
93

    
94
static struct udp_pcd upcd;
95

    
96
struct epstate {
97
	uint32_t state_busy;
98
	uint32_t state_pending;
99
};
100

    
101
static const struct epstate epstate[] = {
102
	[0] =	{ .state_busy = RCTX_STATE_UDP_EP0_BUSY,
103
		  .state_pending = RCTX_STATE_UDP_EP0_PENDING },
104
	[1] =	{ .state_busy = RCTX_STATE_UDP_EP1_BUSY,
105
		  .state_pending = RCTX_STATE_UDP_EP1_PENDING },
106
	[2] =	{ .state_busy = RCTX_STATE_UDP_EP2_BUSY,
107
		  .state_pending = RCTX_STATE_UDP_EP2_PENDING },
108
	[3] =	{ .state_busy = RCTX_STATE_UDP_EP3_BUSY,
109
		  .state_pending = RCTX_STATE_UDP_EP3_PENDING },
110
};
111

    
112
static void reset_ep(unsigned int ep)
113
{
114
	AT91PS_UDP pUDP = upcd.pUdp;
115
	struct req_ctx *rctx;
116

    
117
	atomic_set(&upcd.ep[ep].pkts_in_transit, 0);
118

    
119
	/* free all currently transmitting contexts */
120
	while ((rctx = req_ctx_find_get(0, epstate[ep].state_busy,
121
				       RCTX_STATE_FREE))) {}
122
	/* free all currently pending contexts */
123
	while ((rctx = req_ctx_find_get(0, epstate[ep].state_pending,
124
				       RCTX_STATE_FREE))) {}
125

    
126
	pUDP->UDP_RSTEP |= (1 << ep);
127
	pUDP->UDP_RSTEP &= ~(1 << ep);
128
	pUDP->UDP_CSR[ep] = AT91C_UDP_EPEDS;
129

    
130
	upcd.ep[ep].incomplete.rctx = NULL;
131
}
132

    
133
static void udp_ep0_handler(void);
134

    
135
void udp_unthrottle(void)
136
{
137
	AT91PS_UDP pUDP = upcd.pUdp;
138
	pUDP->UDP_IER = AT91C_UDP_EPINT1;
139
}
140

    
141
int udp_refill_ep(int ep)
142
{
143
	uint16_t i;
144
	AT91PS_UDP pUDP = upcd.pUdp;
145
	struct req_ctx *rctx;
146
	unsigned int start, end;
147

    
148
	/* If we're not configured by the host yet, there is no point
149
	 * in trying to send data to it... */
150
	if (!upcd.cur_config) {
151
		return -ENXIO;
152
	}
153
	
154
	/* If there are already two packets in transit, the DPR of
155
	 * the SAM7 UDC doesn't have space for more data */
156
	if (atomic_read(&upcd.ep[ep].pkts_in_transit) == 2)
157
		return -EBUSY;
158

    
159
	/* disable endpoint interrup */
160
	pUDP->UDP_IDR |= 1 << ep;
161

    
162
	/* If we have an incompletely-transmitted req_ctx (>EP size),
163
	 * we need to transmit the rest and finish the transaction */
164
	if (upcd.ep[ep].incomplete.rctx) {
165
		rctx = upcd.ep[ep].incomplete.rctx;
166
		start = upcd.ep[ep].incomplete.bytes_sent;
167
	} else {
168
		/* get pending rctx and start transmitting from zero */
169
		rctx = req_ctx_find_get(0, epstate[ep].state_pending, 
170
					epstate[ep].state_busy);
171
		if (!rctx) {
172
			/* re-enable endpoint interrupt */
173
			pUDP->UDP_IER |= 1 << ep;
174
			return 0;
175
		}
176
		if (rctx->tot_len == 0) {
177
			/* re-enable endpoint interrupt */
178
			pUDP->UDP_IER |= 1 << ep;
179
			req_ctx_put(rctx);
180
			return 0;
181
		}
182
		DEBUGPCR("USBT(D=%08X, L=%04u, P=$02u) H4/T4: %02X %02X %02X %02X / %02X %02X %02X %02X",
183
			 rctx->data, rctx->tot_len, req_ctx_count(epstate[ep].state_pending),
184
			 rctx->data[4], rctx->data[5], rctx->data[6], rctx->data[7],
185
			 rctx->data[rctx->tot_len - 4], rctx->data[rctx->tot_len - 3],
186
			 rctx->data[rctx->tot_len - 2], rctx->data[rctx->tot_len - 1]);
187

    
188
		start = 0;
189

    
190
		upcd.ep[ep].incomplete.bytes_sent = 0;
191
	}
192

    
193
	if (rctx->tot_len - start <= AT91C_EP_IN_SIZE)
194
		end = rctx->tot_len;
195
	else
196
		end = start + AT91C_EP_IN_SIZE;
197

    
198
	/* fill FIFO/DPR */
199
	for (i = start; i < end; i++) 
200
		pUDP->UDP_FDR[ep] = rctx->data[i];
201

    
202
	if (atomic_inc_return(&upcd.ep[ep].pkts_in_transit) == 1) {
203
		/* not been transmitting before, start transmit */
204
		pUDP->UDP_CSR[ep] |= AT91C_UDP_TXPKTRDY;
205
	}
206

    
207
	if (end == rctx->tot_len) {
208
		/* CASE 1: return context to pool, if
209
		 * - packet transfer < AT91C_EP_OUT_SIZE
210
		 * - after ZLP of transfer == AT91C_EP_OUT_SIZE
211
		 * - after ZLP of transfer % AT91C_EP_OUT_SIZE == 0
212
		 * - after last packet of transfer % AT91C_EP_OUT_SIZE != 0
213
		 */
214
		upcd.ep[ep].incomplete.rctx = NULL;
215
		req_ctx_put(rctx);
216
	} else {
217
		/* CASE 2: mark transfer as incomplete, if
218
		 * - after data of transfer == AT91C_EP_OUT_SIZE
219
		 * - after data of transfer > AT91C_EP_OUT_SIZE
220
		 * - after last packet of transfer % AT91C_EP_OUT_SIZE == 0
221
	         */
222
		upcd.ep[ep].incomplete.rctx = rctx;
223
		upcd.ep[ep].incomplete.bytes_sent += end - start;
224
	}
225

    
226
	/* re-enable endpoint interrupt */
227
	pUDP->UDP_IER |= 1 << ep;
228

    
229
	return 1;
230
}
231

    
232
static void udp_irq(void)
233
{
234
	uint32_t csr;
235
	AT91PS_UDP pUDP = upcd.pUdp;
236
	AT91_REG isr = pUDP->UDP_ISR;
237

    
238
	DEBUGI("udp_irq(imr=0x%04x, isr=0x%04x, state=%d): ", 
239
		pUDP->UDP_IMR, isr, upcd.state);
240

    
241
	if (isr & AT91C_UDP_ENDBUSRES) {
242
		DEBUGI("ENDBUSRES ");
243
		pUDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
244
		pUDP->UDP_IER = AT91C_UDP_EPINT0;
245
		reset_ep(0);
246
		reset_ep(1);
247
		reset_ep(2);
248
		reset_ep(3);
249

    
250
		/* Enable the function */
251
		pUDP->UDP_FADDR = AT91C_UDP_FEN;
252

    
253
		/* Configure endpoint 0 */
254
		pUDP->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
255
		upcd.cur_config = 0;
256
		upcd.state = USB_STATE_DEFAULT;
257
		
258
#ifdef CONFIG_DFU
259
		if (*dfu->dfu_state == DFU_STATE_appDETACH) {
260
			DEBUGI("DFU_SWITCH ");
261
			/* now we need to switch to DFU mode */
262
			dfu->dfu_switch();
263
			goto out;
264
		}
265
#endif
266
	}
267

    
268
	if (isr & AT91C_UDP_EPINT0) {
269
		DEBUGI("EP0INT(Control) ");
270
		udp_ep0_handler();
271
	}
272
	if (isr & AT91C_UDP_EPINT1) {
273
		uint32_t cur_rcv_bank = upcd.cur_rcv_bank;
274
		uint16_t i, pkt_size;
275
		struct req_ctx *rctx;
276

    
277
		csr = pUDP->UDP_CSR[1];
278
		pkt_size = csr >> 16;
279

    
280
		DEBUGI("EP1INT(Out, CSR=0x%08x) ", csr);
281
		if (cur_rcv_bank == AT91C_UDP_RX_DATA_BK1)
282
			DEBUGIO("cur_bank=1 ");
283
		else if (cur_rcv_bank == AT91C_UDP_RX_DATA_BK0)
284
			DEBUGIO("cur_bank=0 ");
285
		else
286
			DEBUGIO("cur_bank INVALID ");
287

    
288
		if (csr & AT91C_UDP_RX_DATA_BK1)
289
			DEBUGIO("BANK1 ");
290
		if (csr & AT91C_UDP_RX_DATA_BK0)
291
			DEBUGIO("BANK0 ");
292

    
293
		if (!(csr & cur_rcv_bank))
294
			goto cont_ep2;
295

    
296
		if (upcd.ep[1].incomplete.rctx) {
297
			DEBUGIO("continue_incompl_RCTX ");
298
			rctx = upcd.ep[1].incomplete.rctx;
299
		} else {
300
			/* allocate new req_ctx  */
301
			DEBUGIO("alloc_new_RCTX ");
302
		
303
			/* whether to get a big or a small req_ctx */
304
			if (pkt_size >= AT91C_EP_IN_SIZE)
305
				rctx = req_ctx_find_get(1, RCTX_STATE_FREE,
306
						 RCTX_STATE_UDP_RCV_BUSY);
307
			else 
308
				rctx = req_ctx_find_get(0, RCTX_STATE_FREE,
309
						 RCTX_STATE_UDP_RCV_BUSY);
310

    
311
			if (!rctx) {
312
				/* disable interrupts for now */
313
				pUDP->UDP_IDR = AT91C_UDP_EPINT1;
314
				DEBUGP("NO_RCTX_AVAIL! ");
315
				goto cont_ep2;
316
			}
317
			rctx->tot_len = 0;
318
		}
319
		DEBUGIO("RCTX=%u ", req_ctx_num(rctx));
320

    
321
		if (rctx->size - rctx->tot_len < pkt_size) {
322
			DEBUGIO("RCTX too small, truncating !!!\n");
323
			pkt_size = rctx->size - rctx->tot_len;
324
		}
325

    
326
		for (i = 0; i < pkt_size; i++)
327
			rctx->data[rctx->tot_len++] = pUDP->UDP_FDR[1];
328

    
329
		pUDP->UDP_CSR[1] &= ~cur_rcv_bank;
330

    
331
		/* toggle current receive bank */
332
		if (cur_rcv_bank == AT91C_UDP_RX_DATA_BK0)
333
			cur_rcv_bank = AT91C_UDP_RX_DATA_BK1;
334
		else
335
			cur_rcv_bank = AT91C_UDP_RX_DATA_BK0;
336
		upcd.cur_rcv_bank = cur_rcv_bank;
337

    
338
		DEBUGIO("rctxdump(%s) ", hexdump(rctx->data, rctx->tot_len));
339

    
340
		/* if this is the last packet in transfer, hand rctx up the
341
		 * stack */
342
		if (pkt_size < AT91C_EP_IN_SIZE) {
343
			DEBUGIO("RCTX_rx_done ");
344
			req_ctx_set_state(rctx, RCTX_STATE_UDP_RCV_DONE);
345
			upcd.ep[1].incomplete.rctx = NULL;
346
		} else {
347
			DEBUGIO("RCTX_rx_cont ");
348
			upcd.ep[1].incomplete.rctx = rctx;
349
		}
350
	}
351
cont_ep2:
352
	if (isr & AT91C_UDP_EPINT2) {
353
		csr = pUDP->UDP_CSR[2];
354
		DEBUGI("EP2INT(In, CSR=0x%08x) ", csr);
355
		if (csr & AT91C_UDP_TXCOMP) {
356
			DEBUGII("ACK_TX_COMP ");
357
			/* acknowledge TX completion */
358
			pUDP->UDP_CSR[2] &= ~AT91C_UDP_TXCOMP;
359
			while (pUDP->UDP_CSR[2] & AT91C_UDP_TXCOMP) ;
360

    
361
			/* if we already have another packet in DPR, send it */
362
			if (atomic_dec_return(&upcd.ep[2].pkts_in_transit) == 1)
363
				pUDP->UDP_CSR[2] |= AT91C_UDP_TXPKTRDY;
364

    
365
			udp_refill_ep(2);
366
		}
367
	}
368
	if (isr & AT91C_UDP_EPINT3) {
369
		csr = pUDP->UDP_CSR[3];
370
		DEBUGII("EP3INT(Interrupt, CSR=0x%08x) ", csr);
371
		/* Transmit has completed, re-fill from pending rcts for EP3 */
372
		if (csr & AT91C_UDP_TXCOMP) {
373
			pUDP->UDP_CSR[3] &= ~AT91C_UDP_TXCOMP;
374
			while (pUDP->UDP_CSR[3] & AT91C_UDP_TXCOMP) ;
375

    
376
			/* if we already have another packet in DPR, send it */
377
			if (atomic_dec_return(&upcd.ep[3].pkts_in_transit) == 1)
378
				pUDP->UDP_CSR[3] |= AT91C_UDP_TXPKTRDY;
379

    
380
			udp_refill_ep(3);
381
		}
382
	}
383
	if (isr & AT91C_UDP_RXSUSP) {
384
		pUDP->UDP_ICR = AT91C_UDP_RXSUSP;
385
		DEBUGI("RXSUSP ");
386
#ifdef CONFIG_USB_SUSPEND
387
		upcd.state = USB_STATE_SUSPENDED;
388
		/* FIXME: implement suspend/resume correctly. This
389
		 * involves saving the pre-suspend state, and calling back
390
		 * into the main application program to ask it to power down
391
		 * all peripherals, switching to slow clock, ... */
392
#endif
393
	}
394
	if (isr & AT91C_UDP_RXRSM) {
395
		pUDP->UDP_ICR = AT91C_UDP_RXRSM;
396
		DEBUGI("RXRSM ");
397
#ifdef CONFIG_USB_SUSPEND
398
		if (upcd.state == USB_STATE_SUSPENDED)
399
			upcd.state = USB_STATE_CONFIGURED;
400
		/* FIXME: implement suspend/resume */
401
#endif
402
	}
403
	if (isr & AT91C_UDP_EXTRSM) {
404
		pUDP->UDP_ICR = AT91C_UDP_EXTRSM;
405
		DEBUGI("EXTRSM ");
406
		/* FIXME: implement suspend/resume */
407
	}
408
	if (isr & AT91C_UDP_SOFINT) {
409
		pUDP->UDP_ICR = AT91C_UDP_SOFINT;
410
		DEBUGI("SOFINT ");
411
	}
412
	if (isr & AT91C_UDP_WAKEUP) {
413
		pUDP->UDP_ICR = AT91C_UDP_WAKEUP;
414
		DEBUGI("WAKEUP ");
415
	}
416
out:
417
	DEBUGI("END\r\n");
418
	AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_UDP);
419
}
420

    
421
void udp_pullup_on(void)
422
{
423
#ifdef PCD
424
	AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
425
#endif
426
	AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUPv4);
427
}
428

    
429
void udp_pullup_off(void)
430
{
431
#ifdef PCD
432
	AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
433
#endif
434
	AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUPv4);
435
}
436

    
437
/* Open USB Device Port  */
438
void udp_open(void)
439
{
440
	DEBUGPCRF("entering");
441
	udp_init();
442
	upcd.pUdp = AT91C_BASE_UDP;
443
	upcd.cur_config = 0;
444
	upcd.cur_rcv_bank = AT91C_UDP_RX_DATA_BK0;
445
	/* This should start with USB_STATE_NOTATTACHED, but we're a pure
446
	 * bus powered device and thus start with powered */
447
	upcd.state = USB_STATE_POWERED;
448

    
449
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_UDP,
450
			      OPENPCD_IRQ_PRIO_UDP,
451
			      AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &udp_irq);
452
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_UDP);
453

    
454
	/* End-of-Bus-Reset is always enabled */
455

    
456
	/* Set the Pull up resistor */
457
	udp_pullup_on();
458
}
459

    
460
void udp_reset(void)
461
{
462
	volatile int i;
463

    
464
	udp_pullup_off();
465
	for (i = 0; i < 0xffff; i++)
466
		;
467
	udp_pullup_on();
468
}
469

    
470
/* Handle requests on the USB Control Endpoint */
471
static void udp_ep0_handler(void)
472
{
473
	AT91PS_UDP pUDP = upcd.pUdp;
474
	uint8_t bmRequestType, bRequest;
475
	uint16_t wValue, wIndex, wLength, wStatus;
476
	uint32_t csr = pUDP->UDP_CSR[0];
477

    
478
	DEBUGE("CSR=0x%04x ", csr);
479

    
480
	if (csr & AT91C_UDP_STALLSENT) {
481
		DEBUGE("ACK_STALLSENT ");
482
		pUDP->UDP_CSR[0] = ~AT91C_UDP_STALLSENT;
483
	}
484

    
485
	if (csr & AT91C_UDP_RX_DATA_BK0) {
486
		DEBUGE("ACK_BANK0 ");
487
		pUDP->UDP_CSR[0] &= ~AT91C_UDP_RX_DATA_BK0;
488
	}
489

    
490
	if (!(csr & AT91C_UDP_RXSETUP)) {
491
		DEBUGE("no setup packet ");
492
		return;
493
	}
494

    
495
	DEBUGE("len=%d ", csr >> 16);
496
	if (csr >> 16  == 0) {
497
		DEBUGE("empty packet ");
498
		return;
499
	}
500

    
501
	bmRequestType = pUDP->UDP_FDR[0];
502
	bRequest = pUDP->UDP_FDR[0];
503
	wValue = (pUDP->UDP_FDR[0] & 0xFF);
504
	wValue |= (pUDP->UDP_FDR[0] << 8);
505
	wIndex = (pUDP->UDP_FDR[0] & 0xFF);
506
	wIndex |= (pUDP->UDP_FDR[0] << 8);
507
	wLength = (pUDP->UDP_FDR[0] & 0xFF);
508
	wLength |= (pUDP->UDP_FDR[0] << 8);
509

    
510
	DEBUGE("bmRequestType=0x%2x ", bmRequestType);
511

    
512
	if (bmRequestType & 0x80) {
513
		DEBUGE("DATA_IN=1 ");
514
		pUDP->UDP_CSR[0] |= AT91C_UDP_DIR;
515
		while (!(pUDP->UDP_CSR[0] & AT91C_UDP_DIR)) ;
516
	}
517
	pUDP->UDP_CSR[0] &= ~AT91C_UDP_RXSETUP;
518
	while ((pUDP->UDP_CSR[0] & AT91C_UDP_RXSETUP)) ;
519

    
520
	DEBUGE("dfu_state = %u ", *dfu->dfu_state);
521
	/* Handle supported standard device request Cf Table 9-3 in USB
522
	 * speciication Rev 1.1 */
523
	switch ((bRequest << 8) | bmRequestType) {
524
		uint8_t desc_type, desc_index;
525
	case STD_GET_DESCRIPTOR:
526
		DEBUGE("GET_DESCRIPTOR(wValue=0x%04x, wIndex=0x%04x) ",
527
			wValue, wIndex);
528
		desc_type = wValue >> 8;
529
		desc_index = wValue & 0xff;
530
		switch (desc_type) {
531
		case USB_DT_DEVICE:
532
			/* Return Device Descriptor */
533
#ifdef CONFIG_DFU
534
			if (*dfu->dfu_state != DFU_STATE_appIDLE)
535
				udp_ep0_send_data((const char *) 
536
						  dfu->dfu_dev_descriptor,
537
						  dfu->dfu_dev_descriptor->bLength,
538
						  wLength);
539
			else
540
#endif
541
			udp_ep0_send_data((const char *) &dev_descriptor,
542
					  sizeof(dev_descriptor), wLength);
543
			break;
544
		case USB_DT_CONFIG:
545
			/* Return Configuration Descriptor */
546
#ifdef CONFIG_DFU
547
			if (*dfu->dfu_state != DFU_STATE_appIDLE)
548
				udp_ep0_send_data((const char *)
549
						  dfu->dfu_cfg_descriptor,
550
						  dfu->dfu_cfg_descriptor->ucfg.wTotalLength,
551
						  wLength);
552
			else
553
#endif
554
			udp_ep0_send_data((const char *) &cfg_descriptor,
555
					   sizeof(cfg_descriptor), wLength);
556
			break;
557
		case USB_DT_STRING:
558
#ifdef CONFIG_USB_STRING
559
			/* Return String descriptor */
560
			if (desc_index > ARRAY_SIZE(usb_strings))
561
				goto out_stall;
562
			DEBUGE("bLength=%u, wLength=%u\n", 
563
				usb_strings[desc_index]->bLength, wLength);
564
			udp_ep0_send_data((const char *) usb_strings[desc_index],
565
					  usb_strings[desc_index]->bLength,
566
					  wLength);
567
#else
568
			goto out_stall;
569
#endif
570
			break;
571
		case USB_DT_CS_DEVICE:
572
			/* Return Function descriptor */
573
			udp_ep0_send_data((const char *) &dfu->dfu_cfg_descriptor->func_dfu,
574
					  sizeof(dfu->dfu_cfg_descriptor->func_dfu), wLength);
575
			break;
576
		case USB_DT_INTERFACE:
577
			/* Return Interface descriptor */
578
			if (desc_index > cfg_descriptor.ucfg.bNumInterfaces)
579
				goto out_stall;
580
			switch (desc_index) {
581
			case 0:
582
				udp_ep0_send_data((const char *)
583
						&cfg_descriptor.uif,
584
						sizeof(cfg_descriptor.uif),
585
						wLength);
586
				break;
587
	#ifdef CONFIG_DFU
588
			case 1:
589
				udp_ep0_send_data((const char *)
590
						&cfg_descriptor.uif_dfu[0],
591
						sizeof(cfg_descriptor.uif_dfu[0]),
592
						wLength);
593
				break;
594
			case 2:
595
				udp_ep0_send_data((const char *)
596
						&cfg_descriptor.uif_dfu[1],
597
						sizeof(cfg_descriptor.uif_dfu[1]),
598
						wLength);
599
				break;
600
			case 3:
601
				udp_ep0_send_data((const char *)
602
						&cfg_descriptor.uif_dfu[2],
603
						sizeof(cfg_descriptor.uif_dfu[2]),
604
						wLength);
605
				break;
606
	#endif
607
			default:
608
				goto out_stall;
609
				break;
610
			}
611
			break;
612
		default:
613
			goto out_stall;
614
			break;
615
		}
616
		break;
617
	case STD_SET_ADDRESS:
618
		DEBUGE("SET_ADDRESS ");
619
		if (wValue > 127)
620
			goto out_stall;
621
		
622
		switch (upcd.state) {
623
		case USB_STATE_DEFAULT:
624
			udp_ep0_send_zlp();
625
			if (wValue == 0) {
626
				/* do nothing */
627
			} else {
628
				pUDP->UDP_FADDR = (AT91C_UDP_FEN | wValue);
629
				pUDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
630
				upcd.state = USB_STATE_ADDRESS;
631
			}
632
			break;
633
		case USB_STATE_ADDRESS:
634
			udp_ep0_send_zlp();
635
			if (wValue == 0) {
636
				upcd.state = USB_STATE_DEFAULT;
637
			} else {
638
				pUDP->UDP_FADDR = (AT91C_UDP_FEN | wValue);
639
			}
640
			break;
641
		default:
642
			goto out_stall;
643
			break;
644
		}
645
		break;
646
	case STD_SET_CONFIGURATION:
647
		DEBUGE("SET_CONFIG ");
648
		if (upcd.state != USB_STATE_ADDRESS &&
649
		    upcd.state != USB_STATE_CONFIGURED) {
650
		    	goto out_stall;
651
		}
652
		if ((wValue & 0xff) == 0) {
653
			DEBUGE("VALUE==0 ");
654
			upcd.state = USB_STATE_ADDRESS;
655
			pUDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
656
			pUDP->UDP_CSR[1] = 0;
657
			pUDP->UDP_CSR[2] = 0;
658
			pUDP->UDP_CSR[3] = 0;
659
		} else if ((wValue & 0xff) <=
660
					dev_descriptor.bNumConfigurations) {
661
			DEBUGE("VALUE!=0 ");
662
			upcd.state = USB_STATE_CONFIGURED;
663
			pUDP->UDP_GLBSTATE = AT91C_UDP_CONFG;
664
			pUDP->UDP_CSR[1] = AT91C_UDP_EPEDS |
665
					   AT91C_UDP_EPTYPE_BULK_OUT;
666
			pUDP->UDP_CSR[2] = AT91C_UDP_EPEDS |
667
					   AT91C_UDP_EPTYPE_BULK_IN;
668
			pUDP->UDP_CSR[3] = AT91C_UDP_EPEDS |
669
					   AT91C_UDP_EPTYPE_INT_IN;
670
		} else {
671
			/* invalid configuration */
672
			goto out_stall;
673
			break;
674
		}
675
		upcd.cur_config = wValue;
676
		udp_ep0_send_zlp();
677
		pUDP->UDP_IER = (AT91C_UDP_EPINT0 | AT91C_UDP_EPINT1 |
678
				 AT91C_UDP_EPINT2 | AT91C_UDP_EPINT3);
679
		break;
680
	case STD_GET_CONFIGURATION:
681
		DEBUGE("GET_CONFIG ");
682
		switch (upcd.state) {
683
		case USB_STATE_ADDRESS:
684
		case USB_STATE_CONFIGURED:
685
			/* Table 9.4 wLength One */
686
			udp_ep0_send_data((char *)&(upcd.cur_config),
687
					   sizeof(upcd.cur_config), 1);
688
			break;
689
		default:
690
			goto out_stall;
691
			break;
692
		}
693
		break;
694
	case STD_GET_INTERFACE:
695
		DEBUGE("GET_INTERFACE ");
696
		if (upcd.state != USB_STATE_CONFIGURED)
697
			goto out_stall;
698
		/* Table 9.4 wLength One */
699
		udp_ep0_send_data((char *)&(upcd.cur_altsett),
700
				  sizeof(upcd.cur_altsett), 1);
701
		break;
702
	case STD_GET_STATUS_ZERO:
703
		DEBUGE("GET_STATUS_ZERO ");
704
		wStatus = 0;
705
		/* Table 9.4 wLength Two */
706
		udp_ep0_send_data((char *)&wStatus, sizeof(wStatus), 2);
707
		break;
708
	case STD_GET_STATUS_INTERFACE:
709
		DEBUGE("GET_STATUS_INTERFACE ");
710
		if (upcd.state == USB_STATE_DEFAULT ||
711
		    (upcd.state == USB_STATE_ADDRESS && wIndex != 0))
712
			goto out_stall;
713
		wStatus = 0;
714
		/* Table 9.4 wLength Two */
715
		udp_ep0_send_data((char *)&wStatus, sizeof(wStatus), 2);
716
		break;
717
	case STD_GET_STATUS_ENDPOINT:
718
		DEBUGE("GET_STATUS_ENDPOINT(EPidx=%u) ", wIndex&0x0f);
719
		if (upcd.state == USB_STATE_DEFAULT ||
720
		    (upcd.state == USB_STATE_ADDRESS && wIndex != 0))
721
			goto out_stall;
722
		wStatus = 0;
723
		wIndex &= 0x0F;
724
		if ((pUDP->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= 3)) {
725
			wStatus =
726
			    (pUDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
727
			/* Table 9.4 wLength Two */
728
			udp_ep0_send_data((char *)&wStatus, sizeof(wStatus), 2);
729
		} else if ((pUDP->UDP_GLBSTATE & AT91C_UDP_FADDEN)
730
			   && (wIndex == 0)) {
731
			wStatus =
732
			    (pUDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
733
			/* Table 9.4 wLength Two */
734
			udp_ep0_send_data((char *)&wStatus, sizeof(wStatus), 2);
735
		} else
736
			goto out_stall;
737
		break;
738
	case STD_SET_FEATURE_ZERO:
739
		DEBUGE("SET_FEATURE_ZERO ");
740
		if (upcd.state == USB_STATE_ADDRESS &&
741
		    (wIndex & 0xff) != 0)
742
			goto out_stall;
743
		/* FIXME: implement this */
744
		goto out_stall;
745
		break;
746
	case STD_SET_FEATURE_INTERFACE:
747
		DEBUGE("SET_FEATURE_INTERFACE ");
748
		if (upcd.state == USB_STATE_ADDRESS &&
749
		    (wIndex & 0xff) != 0)
750
			goto out_stall;
751
		udp_ep0_send_zlp();
752
		break;
753
	case STD_SET_FEATURE_ENDPOINT:
754
		DEBUGE("SET_FEATURE_ENDPOINT ");
755
		if (upcd.state == USB_STATE_ADDRESS &&
756
		    (wIndex & 0xff) != 0)
757
			goto out_stall;
758
		if (wValue != USB_ENDPOINT_HALT)
759
			goto out_stall;
760
		udp_ep0_send_zlp();
761
		wIndex &= 0x0F;
762
		if ((wValue == 0) && wIndex && (wIndex <= 3)) {
763
			pUDP->UDP_CSR[wIndex] = 0;
764
			udp_ep0_send_zlp();
765
		} else
766
			goto out_stall;
767
		break;
768
	case STD_CLEAR_FEATURE_ZERO:
769
		DEBUGE("CLEAR_FEATURE_ZERO ");
770
		goto out_stall;
771
		break;
772
	case STD_CLEAR_FEATURE_INTERFACE:
773
		DEBUGP("CLEAR_FEATURE_INTERFACE ");
774
		udp_ep0_send_zlp();
775
		break;
776
	case STD_CLEAR_FEATURE_ENDPOINT:
777
		DEBUGE("CLEAR_FEATURE_ENDPOINT(EPidx=%u) ", wIndex & 0x0f);
778
		if (wValue != USB_ENDPOINT_HALT)
779
			goto out_stall;
780
		wIndex &= 0x0F;
781
		if ((wValue == 0) && wIndex && (wIndex <= 3)) {
782
			reset_ep(wIndex);
783
			udp_ep0_send_zlp();
784
		} else
785
			goto out_stall;
786
		break;
787
	case STD_SET_INTERFACE:
788
		DEBUGE("SET INTERFACE ");
789
		if (upcd.state != USB_STATE_CONFIGURED)
790
			goto out_stall;
791
		if (wIndex > cfg_descriptor.ucfg.bNumInterfaces)
792
			goto out_stall;
793
		upcd.cur_interface = wIndex;
794
		upcd.cur_altsett = wValue;
795
		/* USB spec mandates that if we only support one altsetting in
796
		 * the given interface, we shall respond with STALL in the
797
		 * status stage */
798
		udp_ep0_send_stall();
799
		break;
800
	default:
801
		DEBUGE("DEFAULT(req=0x%02x, type=0x%02x) ", 
802
			bRequest, bmRequestType);
803
#ifdef CONFIG_DFU
804
		if ((bmRequestType & 0x3f) == USB_TYPE_DFU) {
805
			dfu->dfu_ep0_handler(bmRequestType, bRequest, wValue,
806
					     wLength);
807
		} else
808
#endif
809
		goto out_stall;
810
		break;
811
	}
812
	return;
813
out_stall:
814
	DEBUGE("STALL!! ");
815
	udp_ep0_send_stall();
816
}
817

    
(13-13/40)
Add picture from clipboard (Maximum size: 48.8 MB)