Project

General

Profile

Download (26.9 KB) Statistics
| Branch: | Tag: | Revision:
1
/* USB Device Firmware Update Implementation for OpenPCD
2
 * (C) 2006-2011 by Harald Welte <hwelte@hmw-consulting.de>
3
 *
4
 * This ought to be compliant to the USB DFU Spec 1.0 as available from
5
 * http://www.usb.org/developers/devclass_docs/usbdfu10.pdf
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by 
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  (at your option) any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program; if not, write to the Free Software
19
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 *
21
 */
22

    
23
#include <errno.h>
24
#include <usb_ch9.h>
25
#include <usb_dfu.h>
26
#include <board.h>
27
#include <lib_AT91SAM7.h>
28

    
29
#include <usb_strings_dfu.h>
30

    
31
#include <dfu/dfu.h>
32
#include <dfu/dbgu.h>
33
#include <os/flash.h>
34
#include <os/pcd_enumerate.h>
35
#include "../openpcd.h"
36

    
37
#include <compile.h>
38

    
39
#define SAM7DFU_SIZE	0x4000
40
#define SAM7DFU_RAM_SIZE	0x2000
41

    
42
/* If debug is enabled, we need to access debug functions from flash
43
 * and therefore have to omit flashing */
44
//#define DEBUG_DFU_NOFLASH
45

    
46
#ifdef DEBUG
47
#define DEBUG_DFU_EP0
48
//#define DEBUG_DFU_RECV
49
#endif
50

    
51
#ifdef DEBUG_DFU_EP0
52
#define DEBUGE DEBUGP
53
#else
54
#define DEBUGE(x, args ...)
55
#endif
56

    
57
#ifdef DEBUG_DFU_RECV
58
#define DEBUGR DEBUGP
59
#else
60
#define DEBUGR(x, args ...)
61
#endif
62

    
63
#define RET_NOTHING	0
64
#define RET_ZLP		1
65
#define RET_STALL	2
66

    
67
#define led1on()	AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED1)
68
#define led1off()	AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED1)
69

    
70
#define led2on()	AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2)
71
#define led2off()	AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2)
72

    
73
static int past_manifest = 0;
74
static int switch_to_ram = 0; /* IRQ handler requests main to jump to RAM */
75
static uint16_t usb_if_nr = 0;	/* last SET_INTERFACE */
76
static uint16_t usb_if_alt_nr = 0; /* last SET_INTERFACE AltSetting */
77
static uint16_t usb_if_alt_nr_dnload = 0; /* AltSetting during last dnload */
78

    
79
static void __dfufunc udp_init(void)
80
{
81
	/* Set the PLL USB Divider */
82
	AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1;
83

    
84
	/* Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock */
85
	AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
86
	AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
87

    
88
	/* Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the
89
	 * corresponding PIO Set in PIO mode and Configure in Output */
90
#if defined(PCD)
91
	AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
92
#endif
93
	AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUPv4);
94
}
95

    
96
static void __dfufunc udp_ep0_send_zlp(void);
97

    
98
/* Send Data through the control endpoint */
99
static void __dfufunc udp_ep0_send_data(const char *pData, uint32_t length,
100
					uint32_t window_length)
101
{
102
	AT91PS_UDP pUdp = AT91C_BASE_UDP;
103
	uint32_t cpt = 0, len_remain;
104
	AT91_REG csr;
105

    
106
	len_remain = MIN(length, window_length);
107
	DEBUGE("send_data: %u/%u bytes ", length, window_length);
108

    
109
	do {
110
		cpt = MIN(len_remain, 8);
111
		len_remain -= cpt;
112

    
113
		while (cpt--)
114
			pUdp->UDP_FDR[0] = *pData++;
115

    
116
		if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) {
117
			pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);
118
			while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) ;
119
		}
120

    
121
		pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;
122
		do {
123
			csr = pUdp->UDP_CSR[0];
124

    
125
			/* Data IN stage has been stopped by a status OUT */
126
			if (csr & AT91C_UDP_RX_DATA_BK0) {
127
				pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);
128
				DEBUGE("stopped by status out ");
129
				return;
130
			}
131
		} while (!(csr & AT91C_UDP_TXCOMP));
132

    
133
	} while (len_remain);
134

    
135
	if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) {
136
		pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);
137
		while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) ;
138
	}
139

    
140
	if ((length % 8) == 0 && length < window_length) {
141
		/* if the length is a multiple of the EP size, we need
142
		 * to send another ZLP (zero-length packet) to tell the
143
		 * host the transfer has completed.  */
144
		DEBUGE("set_txpktrdy_zlp ");
145
		udp_ep0_send_zlp();
146
	}
147
}
148

    
149
/* receive data from EP0 */
150
static int __dfufunc udp_ep0_recv_data(uint8_t *data, uint16_t len)
151
{
152
	AT91PS_UDP pUdp = AT91C_BASE_UDP;
153
	AT91_REG csr;
154
	uint16_t i, num_rcv;
155
	uint32_t num_rcv_total = 0;
156

    
157
	do {
158
		/* FIXME: do we need to check whether we've been interrupted
159
		 * by a RX SETUP stage? */
160
		do {
161
			csr = pUdp->UDP_CSR[0];
162
			DEBUGR("CSR=%08x ", csr);
163
		} while (!(csr & AT91C_UDP_RX_DATA_BK0)) ;
164
	
165
		num_rcv = pUdp->UDP_CSR[0] >> 16;
166

    
167
		/* make sure we don't read more than requested */
168
		if (num_rcv_total + num_rcv > len)
169
			num_rcv = num_rcv_total - len;
170

    
171
		DEBUGR("num_rcv = %u ", num_rcv);
172
		for (i = 0; i < num_rcv; i++)
173
			*data++ = pUdp->UDP_FDR[0];
174
		pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);
175

    
176
		num_rcv_total += num_rcv;
177

    
178
		/* we need to continue to pull data until we either receive 
179
		 * a packet < endpoint size or == 0 */
180
	} while (num_rcv == 8 && num_rcv_total < len);
181

    
182
	DEBUGE("ep0_rcv_returning(%u total) ", num_rcv_total);
183

    
184
	return num_rcv_total;
185
}
186

    
187
/* Send zero length packet through the control endpoint */
188
static void __dfufunc udp_ep0_send_zlp(void)
189
{
190
	AT91PS_UDP pUdp = AT91C_BASE_UDP;
191
	pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;
192
	while (!(pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP)) ;
193
	pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);
194
	while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) ;
195
}
196

    
197
/* Stall the control endpoint */
198
static void __dfufunc udp_ep0_send_stall(void)
199
{
200
	AT91PS_UDP pUdp = AT91C_BASE_UDP;
201
	pUdp->UDP_CSR[0] |= AT91C_UDP_FORCESTALL;
202
	while (!(pUdp->UDP_CSR[0] & AT91C_UDP_ISOERROR)) ;
203
	pUdp->UDP_CSR[0] &= ~(AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR);
204
	while (pUdp->UDP_CSR[0] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR)) ;
205
}
206

    
207

    
208
static int first_download = 1;
209
static uint8_t *ptr, *ptr_max;
210
static __dfudata uint8_t dfu_status;
211
__dfudata uint32_t dfu_state = DFU_STATE_appIDLE;
212
static uint32_t pagebuf32[AT91C_IFLASH_PAGE_SIZE/4];
213

    
214
static void chk_first_dnload_set_ptr(void)
215
{
216
	if (!first_download)
217
		return;
218

    
219
	switch (usb_if_alt_nr) {
220
	case 0:
221
		ptr = (uint8_t *) AT91C_IFLASH + SAM7DFU_SIZE;
222
		ptr_max = AT91C_IFLASH + AT91C_IFLASH_SIZE - ENVIRONMENT_SIZE;
223
		break;
224
	case 1:
225
		ptr = (uint8_t *) AT91C_IFLASH;
226
		ptr_max = AT91C_IFLASH + SAM7DFU_SIZE;
227
		break;
228
	case 2:
229
		ptr = (uint8_t *) AT91C_ISRAM + SAM7DFU_RAM_SIZE;
230
		ptr_max = AT91C_ISRAM + AT91C_ISRAM_SIZE;
231
		break;
232
	}
233
	first_download = 0;
234
}
235

    
236
static int __dfufunc handle_dnload_flash(uint16_t __unused val, uint16_t len)
237
{
238
	volatile uint32_t *p;
239
	uint8_t *pagebuf = (uint8_t *) pagebuf32;
240
	int i;
241

    
242
	DEBUGE("download ");
243

    
244
	if (len > AT91C_IFLASH_PAGE_SIZE) {
245
		/* Too big. Not that we'd really care, but it's a
246
		 * DFU protocol violation */
247
		DEBUGP("length exceeds flash page size ");
248
	    	dfu_state = DFU_STATE_dfuERROR;
249
		dfu_status = DFU_STATUS_errADDRESS;
250
		return RET_STALL;
251
	}
252
	if (len & 0x3) {
253
		/* reject non-four-byte-aligned writes */
254
		DEBUGP("not four-byte-aligned length ");
255
		dfu_state = DFU_STATE_dfuERROR;
256
		dfu_status = DFU_STATUS_errADDRESS;
257
		return RET_STALL;
258
	}
259
	chk_first_dnload_set_ptr();
260
	p = (volatile uint32_t *)ptr;
261

    
262
	if (len == 0) {
263
		DEBUGP("zero-size write -> MANIFEST_SYNC ");
264
		if (((unsigned long)p % AT91C_IFLASH_PAGE_SIZE) != 0)
265
			flash_page(p);
266
		dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
267
		first_download = 1;
268
		return RET_ZLP;
269
	}
270

    
271
	/* check if we would exceed end of memory */
272
	if (ptr + len > ptr_max) {
273
		DEBUGP("end of write exceeds flash end ");
274
		dfu_state = DFU_STATE_dfuERROR;
275
		dfu_status = DFU_STATUS_errADDRESS;
276
		return RET_STALL;
277
	}
278

    
279
	DEBUGP("try_to_recv=%u ", len);
280
	udp_ep0_recv_data(pagebuf, len);
281

    
282
	DEBUGR(hexdump(pagebuf, len));
283

    
284
#ifndef DEBUG_DFU_NOFLASH
285
	DEBUGP("copying ");
286
	/* we can only access the write buffer with correctly aligned
287
	 * 32bit writes ! */
288
	for (i = 0; i < len/4; i++) {
289
		*p++ = pagebuf32[i];
290
		/* If we have filled a page buffer, flash it */
291
		if (((unsigned long)p % AT91C_IFLASH_PAGE_SIZE) == 0) {
292
			DEBUGP("page_full  ");
293
			flash_page(p-1);
294
		}
295
	}
296
	ptr = (uint8_t *) p;
297
#endif
298

    
299
	return RET_ZLP;
300
}
301

    
302
static int __dfufunc handle_dnload_ram(uint16_t __unused val, uint16_t len)
303
{
304
	DEBUGE("download ");
305

    
306
	if (len > AT91C_IFLASH_PAGE_SIZE) {
307
		/* Too big. Not that we'd really care, but it's a
308
		 * DFU protocol violation */
309
		DEBUGP("length exceeds flash page size ");
310
		dfu_state = DFU_STATE_dfuERROR;
311
		dfu_status = DFU_STATUS_errADDRESS;
312
		return RET_STALL;
313
	}
314
	chk_first_dnload_set_ptr();
315

    
316
	if (len == 0) {
317
		DEBUGP("zero-size write -> MANIFEST_SYNC ");
318
		dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
319
		first_download = 1;
320
		return RET_ZLP;
321
	}
322

    
323
	/* check if we would exceed end of memory */
324
	if (ptr + len >= ptr_max) {
325
		DEBUGP("end of write exceeds RAM end ");
326
		dfu_state = DFU_STATE_dfuERROR;
327
		dfu_status = DFU_STATUS_errADDRESS;
328
		return RET_STALL;
329
	}
330

    
331
	/* drectly copy into RAM */
332
	DEBUGP("try_to_recv=%u ", len);
333
	udp_ep0_recv_data(ptr, len);
334

    
335
	DEBUGR(hexdump(ptr, len));
336

    
337
	ptr += len;
338

    
339
	return RET_ZLP;
340
}
341

    
342
static int __dfufunc handle_dnload(uint16_t val, uint16_t len)
343
{
344
	usb_if_alt_nr_dnload = usb_if_alt_nr;
345
	switch (usb_if_alt_nr) {
346
	case 2:
347
		return handle_dnload_ram(val, len);
348
	default:
349
		return handle_dnload_flash(val, len);
350
	}
351
}
352

    
353
#define AT91C_IFLASH_END ((uint8_t *)AT91C_IFLASH + AT91C_IFLASH_SIZE)
354
static __dfufunc int handle_upload(uint16_t __unused val, uint16_t len)
355
{
356
	DEBUGE("upload ");
357
	if (len > AT91C_IFLASH_PAGE_SIZE) {
358
		/* Too big */
359
		dfu_state = DFU_STATE_dfuERROR;
360
		dfu_status = DFU_STATUS_errADDRESS;
361
		udp_ep0_send_stall();
362
		return -EINVAL;
363
	}
364
	chk_first_dnload_set_ptr();
365

    
366
	if (ptr + len > AT91C_IFLASH_END) {
367
		len = AT91C_IFLASH_END - (uint8_t *)ptr;
368
		first_download = 1;
369
	}
370

    
371
	udp_ep0_send_data((char *)ptr, len, len);
372
	ptr+= len;
373

    
374
	return len;
375
}
376

    
377
static __dfufunc void handle_getstatus(void)
378
{
379
	struct dfu_status dstat;
380
	uint32_t fsr = AT91F_MC_EFC_GetStatus(AT91C_BASE_MC);
381

    
382
	DEBUGE("getstatus(fsr=0x%08x) ", fsr);
383

    
384
	switch (dfu_state) {
385
	case DFU_STATE_dfuDNLOAD_SYNC:
386
	case DFU_STATE_dfuDNBUSY:
387
		if (fsr & AT91C_MC_PROGE) {
388
			DEBUGE("errPROG ");
389
			dfu_status = DFU_STATUS_errPROG;
390
			dfu_state = DFU_STATE_dfuERROR;
391
		} else if (fsr & AT91C_MC_LOCKE) {
392
			DEBUGE("errWRITE ");
393
			dfu_status = DFU_STATUS_errWRITE;
394
			dfu_state = DFU_STATE_dfuERROR;
395
		} else if (fsr & AT91C_MC_FRDY) {
396
			DEBUGE("DNLOAD_IDLE ");
397
			dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
398
		} else {
399
			DEBUGE("DNBUSY ");
400
			dfu_state = DFU_STATE_dfuDNBUSY;
401
		}
402
		break;
403
	case DFU_STATE_dfuMANIFEST_SYNC:
404
		dfu_state = DFU_STATE_dfuMANIFEST;
405
		break;
406
	}
407

    
408
	/* send status response */
409
	dstat.bStatus = dfu_status;
410
	dstat.bState = dfu_state;
411
	dstat.iString = 0;
412
	/* FIXME: set dstat.bwPollTimeout */
413

    
414
	udp_ep0_send_data((char *)&dstat, sizeof(dstat), sizeof(dstat));
415
}
416

    
417
static void __dfufunc handle_getstate(void)
418
{
419
	uint8_t u8 = dfu_state;
420
	DEBUGE("getstate ");
421

    
422
	udp_ep0_send_data((char *)&u8, sizeof(u8), sizeof(u8));
423
}
424

    
425
/* callback function for DFU requests */
426
int __dfufunc dfu_ep0_handler(uint8_t __unused req_type, uint8_t req,
427
		    uint16_t val, uint16_t len)
428
{
429
	int rc, ret = RET_NOTHING;
430

    
431
	DEBUGE("old_state = %u ", dfu_state);
432

    
433
	switch (dfu_state) {
434
	case DFU_STATE_appIDLE:
435
		switch (req) {
436
		case USB_REQ_DFU_GETSTATUS:
437
			handle_getstatus();
438
			break;
439
		case USB_REQ_DFU_GETSTATE:
440
			handle_getstate();
441
			break;
442
		case USB_REQ_DFU_DETACH:
443
			dfu_state = DFU_STATE_appDETACH;
444
			ret = RET_ZLP;
445
			goto out;
446
			break;
447
		default:
448
			ret = RET_STALL;
449
		}
450
		break;
451
	case DFU_STATE_appDETACH:
452
		switch (req) {
453
		case USB_REQ_DFU_GETSTATUS:
454
			handle_getstatus();
455
			break;
456
		case USB_REQ_DFU_GETSTATE:
457
			handle_getstate();
458
			break;
459
		default:
460
			dfu_state = DFU_STATE_appIDLE;
461
			ret = RET_STALL;
462
			goto out;
463
			break;
464
		}
465
		/* FIXME: implement timer to return to appIDLE */
466
		break;
467
	case DFU_STATE_dfuIDLE:
468
		switch (req) {
469
		case USB_REQ_DFU_DNLOAD:
470
			if (len == 0) {
471
				dfu_state = DFU_STATE_dfuERROR;
472
				ret = RET_STALL;
473
				goto out;
474
			}
475
			dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
476
			ptr = (uint8_t *) AT91C_IFLASH + SAM7DFU_SIZE;
477
			ret = handle_dnload(val, len);
478
			break;
479
		case USB_REQ_DFU_UPLOAD:
480
			ptr = (uint8_t *) AT91C_IFLASH + SAM7DFU_SIZE;
481
			dfu_state = DFU_STATE_dfuUPLOAD_IDLE;
482
			handle_upload(val, len);
483
			break;
484
		case USB_REQ_DFU_ABORT:
485
			/* no zlp? */
486
			ret = RET_ZLP;
487
			break;
488
		case USB_REQ_DFU_GETSTATUS:
489
			handle_getstatus();
490
			break;
491
		case USB_REQ_DFU_GETSTATE:
492
			handle_getstate();
493
			break;
494
		default:
495
			dfu_state = DFU_STATE_dfuERROR;
496
			ret = RET_STALL;
497
			goto out;
498
			break;
499
		}
500
		break;
501
	case DFU_STATE_dfuDNLOAD_SYNC:
502
		switch (req) {
503
		case USB_REQ_DFU_GETSTATUS:
504
			handle_getstatus();
505
			/* FIXME: state transition depending on block completeness */
506
			break;
507
		case USB_REQ_DFU_GETSTATE:
508
			handle_getstate();
509
			break;
510
		default:
511
			dfu_state = DFU_STATE_dfuERROR;
512
			ret = RET_STALL;
513
			goto out;
514
		}
515
		break;
516
	case DFU_STATE_dfuDNBUSY:
517
		switch (req) {
518
		case USB_REQ_DFU_GETSTATUS:
519
			/* FIXME: only accept getstatus if bwPollTimeout
520
			 * has elapsed */
521
			handle_getstatus();
522
			break;
523
		default:
524
			dfu_state = DFU_STATE_dfuERROR;
525
			ret = RET_STALL;
526
			goto out;
527
		}
528
		break;
529
	case DFU_STATE_dfuDNLOAD_IDLE:
530
		switch (req) {
531
		case USB_REQ_DFU_DNLOAD:
532
			dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
533
			ret = handle_dnload(val, len);
534
			break;
535
		case USB_REQ_DFU_ABORT:
536
			dfu_state = DFU_STATE_dfuIDLE;
537
			ret = RET_ZLP;
538
			break;
539
		case USB_REQ_DFU_GETSTATUS:
540
			handle_getstatus();
541
			break;
542
		case USB_REQ_DFU_GETSTATE:
543
			handle_getstate();
544
			break;
545
		default:
546
			dfu_state = DFU_STATE_dfuERROR;
547
			ret = RET_STALL;
548
			break;
549
		}
550
		break;
551
	case DFU_STATE_dfuMANIFEST_SYNC:
552
		switch (req) {
553
		case USB_REQ_DFU_GETSTATUS:
554
			handle_getstatus();
555
			break;
556
		case USB_REQ_DFU_GETSTATE:
557
			handle_getstate();
558
			break;
559
		default:
560
			dfu_state = DFU_STATE_dfuERROR;
561
			ret = RET_STALL;
562
			break;
563
		}
564
		break;
565
	case DFU_STATE_dfuMANIFEST:
566
		switch (req) {
567
		case USB_REQ_DFU_GETSTATUS:
568
			/* we don't want to change to WAIT_RST, as it
569
			 * would mean that we can not support another
570
			 * DFU transaction before doing the actual
571
			 * reset.  Instead, we switch to idle and note
572
			 * that we've already been through MANIFST in
573
			 * the global variable 'past_manifest'.
574
			 */
575
			//dfu_state = DFU_STATE_dfuMANIFEST_WAIT_RST;
576
			dfu_state = DFU_STATE_dfuIDLE;
577
			past_manifest = 1;
578
			handle_getstatus();
579
			break;
580
		case USB_REQ_DFU_GETSTATE:
581
			handle_getstate();
582
			break;
583
		default:
584
			dfu_state = DFU_STATE_dfuERROR;
585
			ret = RET_STALL;
586
			break;
587
		}
588
		break;
589
	case DFU_STATE_dfuMANIFEST_WAIT_RST:
590
		/* we should never go here */
591
		break;
592
	case DFU_STATE_dfuUPLOAD_IDLE:
593
		switch (req) {
594
		case USB_REQ_DFU_UPLOAD:
595
			/* state transition if less data then requested */
596
			rc = handle_upload(val, len);
597
			if (rc >= 0 && rc < len)
598
				dfu_state = DFU_STATE_dfuIDLE;
599
			break;
600
		case USB_REQ_DFU_ABORT:
601
			dfu_state = DFU_STATE_dfuIDLE;
602
			/* no zlp? */
603
			ret = RET_ZLP;
604
			break;
605
		case USB_REQ_DFU_GETSTATUS:
606
			handle_getstatus();
607
			break;
608
		case USB_REQ_DFU_GETSTATE:
609
			handle_getstate();
610
			break;
611
		default:
612
			dfu_state = DFU_STATE_dfuERROR;
613
			ret = RET_STALL;
614
			break;
615
		}
616
		break;
617
	case DFU_STATE_dfuERROR:
618
		switch (req) {
619
		case USB_REQ_DFU_GETSTATUS:
620
			handle_getstatus();
621
			break;
622
		case USB_REQ_DFU_GETSTATE:
623
			handle_getstate();
624
			break;
625
		case USB_REQ_DFU_CLRSTATUS:
626
			dfu_state = DFU_STATE_dfuIDLE;
627
			dfu_status = DFU_STATUS_OK;
628
			/* no zlp? */
629
			ret = RET_ZLP;
630
			break;
631
		default:
632
			dfu_state = DFU_STATE_dfuERROR;
633
			ret = RET_STALL;
634
			break;
635
		}
636
		break;
637
	}
638

    
639
out:
640
	DEBUGE("new_state = %u\r\n", dfu_state);
641

    
642
	switch (ret) {
643
	case RET_NOTHING:
644
		break;
645
	case RET_ZLP:
646
		udp_ep0_send_zlp();
647
		break;
648
	case RET_STALL:
649
		udp_ep0_send_stall();
650
		break;
651
	}
652
	return 0;
653
}
654

    
655
static uint8_t cur_config;
656

    
657
/* USB DFU Device descriptor in DFU mode */
658
__dfustruct const struct usb_device_descriptor dfu_dev_descriptor = {
659
	.bLength		= USB_DT_DEVICE_SIZE,
660
	.bDescriptorType	= USB_DT_DEVICE,
661
	.bcdUSB			= 0x0100,
662
	.bDeviceClass		= 0x00,
663
	.bDeviceSubClass	= 0x00,
664
	.bDeviceProtocol	= 0x00,
665
	.bMaxPacketSize0	= 8,
666
	.idVendor		= USB_VENDOR_ID,
667
	.idProduct		= USB_PRODUCT_ID,
668
	.bcdDevice		= 0x0000,
669
#ifdef CONFIG_USB_STRING
670
	.iManufacturer		= 1,
671
	.iProduct		= 2,
672
#else
673
	.iManufacturer		= 0,
674
	.iProduct		= 0,
675
#endif
676
	.iSerialNumber		= 0x00,
677
	.bNumConfigurations	= 0x01,
678
};
679

    
680
/* USB DFU Config descriptor in DFU mode */
681
__dfustruct const struct _dfu_desc dfu_cfg_descriptor = {
682
	.ucfg = {
683
		.bLength = USB_DT_CONFIG_SIZE,
684
		.bDescriptorType = USB_DT_CONFIG,
685
		.wTotalLength = USB_DT_CONFIG_SIZE + 
686
				3* USB_DT_INTERFACE_SIZE +
687
				USB_DT_DFU_SIZE,
688
		.bNumInterfaces = 1,
689
		.bConfigurationValue = 1,
690
#ifdef CONFIG_USB_STRING
691
		.iConfiguration = 3,
692
#else
693
		.iConfiguration = 0,
694
#endif
695
		.bmAttributes = USB_CONFIG_ATT_ONE,
696
		.bMaxPower = 100,
697
		},
698
	.uif[0] = {
699
		.bLength		= USB_DT_INTERFACE_SIZE,
700
		.bDescriptorType	= USB_DT_INTERFACE,
701
		.bInterfaceNumber	= 0x00,
702
		.bAlternateSetting	= 0x00,
703
		.bNumEndpoints		= 0x00,
704
		.bInterfaceClass	= 0xfe,
705
		.bInterfaceSubClass	= 0x01,
706
		.bInterfaceProtocol	= 0x02,
707
#ifdef CONFIG_USB_STRING
708
		.iInterface		= 4,
709
#else
710
		.iInterface		= 0,
711
#endif
712
		}, 
713
	.uif[1] = {
714
		.bLength		= USB_DT_INTERFACE_SIZE,
715
		.bDescriptorType	= USB_DT_INTERFACE,
716
		.bInterfaceNumber	= 0x00,
717
		.bAlternateSetting	= 0x01,
718
		.bNumEndpoints		= 0x00,
719
		.bInterfaceClass	= 0xfe,
720
		.bInterfaceSubClass	= 0x01,
721
		.bInterfaceProtocol	= 0x02,
722
#ifdef CONFIG_USB_STRING
723
		.iInterface		= 5,
724
#else
725
		.iInterface		= 0,
726
#endif
727
		}, 
728
	.uif[2] = {
729
		.bLength		= USB_DT_INTERFACE_SIZE,
730
		.bDescriptorType	= USB_DT_INTERFACE,
731
		.bInterfaceNumber	= 0x00,
732
		.bAlternateSetting	= 0x02,
733
		.bNumEndpoints		= 0x00,
734
		.bInterfaceClass	= 0xfe,
735
		.bInterfaceSubClass	= 0x01,
736
		.bInterfaceProtocol	= 0x02,
737
#ifdef CONFIG_USB_STRING
738
		.iInterface		= 6,
739
#else
740
		.iInterface		= 0,
741
#endif
742
		},
743

    
744
	.func_dfu = DFU_FUNC_DESC,
745
};
746

    
747

    
748
/* minimal USB EP0 handler in DFU mode */
749
static __dfufunc void dfu_udp_ep0_handler(void)
750
{
751
	AT91PS_UDP pUDP = AT91C_BASE_UDP;
752
	uint8_t bmRequestType, bRequest;
753
	uint16_t wValue, wIndex, wLength, wStatus;
754
	uint32_t csr = pUDP->UDP_CSR[0];
755

    
756
	DEBUGE("CSR=0x%04x ", csr);
757

    
758
	if (csr & AT91C_UDP_STALLSENT) {
759
		DEBUGE("ACK_STALLSENT ");
760
		pUDP->UDP_CSR[0] = ~AT91C_UDP_STALLSENT;
761
	}
762

    
763
	if (csr & AT91C_UDP_RX_DATA_BK0) {
764
		DEBUGE("ACK_BANK0 ");
765
		pUDP->UDP_CSR[0] &= ~AT91C_UDP_RX_DATA_BK0;
766
	}
767

    
768
	if (!(csr & AT91C_UDP_RXSETUP)) {
769
		DEBUGE("no setup packet\r\n");
770
		return;
771
	}
772

    
773
	DEBUGE("len=%d ", csr >> 16);
774
	if (csr >> 16  == 0) {
775
		DEBUGE("empty packet\r\n");
776
		return;
777
	}
778

    
779
	bmRequestType = pUDP->UDP_FDR[0];
780
	bRequest = pUDP->UDP_FDR[0];
781
	wValue = (pUDP->UDP_FDR[0] & 0xFF);
782
	wValue |= (pUDP->UDP_FDR[0] << 8);
783
	wIndex = (pUDP->UDP_FDR[0] & 0xFF);
784
	wIndex |= (pUDP->UDP_FDR[0] << 8);
785
	wLength = (pUDP->UDP_FDR[0] & 0xFF);
786
	wLength |= (pUDP->UDP_FDR[0] << 8);
787

    
788
	DEBUGE("bmRequestType=0x%2x ", bmRequestType);
789

    
790
	if (bmRequestType & 0x80) {
791
		DEBUGE("DATA_IN=1 ");
792
		pUDP->UDP_CSR[0] |= AT91C_UDP_DIR;
793
		while (!(pUDP->UDP_CSR[0] & AT91C_UDP_DIR)) ;
794
	}
795
	pUDP->UDP_CSR[0] &= ~AT91C_UDP_RXSETUP;
796
	while ((pUDP->UDP_CSR[0] & AT91C_UDP_RXSETUP)) ;
797

    
798
	/* Handle supported standard device request Cf Table 9-3 in USB
799
	 * speciication Rev 1.1 */
800
	switch ((bRequest << 8) | bmRequestType) {
801
		uint8_t desc_type, desc_index;
802
	case STD_GET_DESCRIPTOR:
803
		DEBUGE("GET_DESCRIPTOR ");
804
		desc_type = wValue >> 8;
805
		desc_index = wValue & 0xff;
806
		switch (desc_type) {
807
		case USB_DT_DEVICE:
808
			/* Return Device Descriptor */
809
			udp_ep0_send_data((const char *) 
810
					  &dfu_dev_descriptor,
811
					  sizeof(dfu_dev_descriptor), wLength);
812
			break;
813
		case USB_DT_CONFIG:
814
			/* Return Configuration Descriptor */
815
			udp_ep0_send_data((const char *)
816
					  &dfu_cfg_descriptor,
817
					  sizeof(dfu_cfg_descriptor), wLength);
818
			break;
819
		case USB_DT_STRING:
820
			/* Return String Descriptor */
821
			if (desc_index > ARRAY_SIZE(usb_strings)) {
822
				udp_ep0_send_stall();
823
				break;
824
			}
825
			DEBUGE("bLength=%u, wLength=%u ", 
826
				usb_strings[desc_index]->bLength, wLength);
827
			udp_ep0_send_data((const char *) usb_strings[desc_index],
828
					  usb_strings[desc_index]->bLength, wLength);
829
			break;
830
		case USB_DT_CS_DEVICE:
831
			/* Return Function descriptor */
832
			udp_ep0_send_data((const char *) &dfu_cfg_descriptor.func_dfu,
833
					  sizeof(dfu_cfg_descriptor.func_dfu), wLength);
834
			break;
835
		default:
836
			udp_ep0_send_stall();
837
			break;
838
		}
839
		break;
840
	case STD_SET_ADDRESS:
841
		DEBUGE("SET_ADDRESS ");
842
		udp_ep0_send_zlp();
843
		pUDP->UDP_FADDR = (AT91C_UDP_FEN | wValue);
844
		pUDP->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;
845
		break;
846
	case STD_SET_CONFIGURATION:
847
		DEBUGE("SET_CONFIG ");
848
		if (wValue) {
849
			DEBUGE("VALUE!=0 ");
850
		}
851
	
852
		cur_config = wValue;
853
		udp_ep0_send_zlp();
854
		pUDP->UDP_GLBSTATE =
855
		    (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;
856
		pUDP->UDP_CSR[1] =
857
		    (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) :
858
		    0;
859
		pUDP->UDP_CSR[2] =
860
		    (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;
861
		pUDP->UDP_CSR[3] =
862
		    (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;
863
		pUDP->UDP_IER = (AT91C_UDP_EPINT0|AT91C_UDP_EPINT1|
864
				 AT91C_UDP_EPINT2|AT91C_UDP_EPINT3);
865
		break;
866
	case STD_GET_CONFIGURATION:
867
		DEBUGE("GET_CONFIG ");
868
		/* Table 9.4 wLength One */
869
		udp_ep0_send_data((char *)&(cur_config), sizeof(cur_config), 1);
870
		break;
871
	case STD_GET_STATUS_ZERO:
872
		DEBUGE("GET_STATUS_ZERO ");
873
		wStatus = 0;
874
		/* Table 9.4 wLength Two */
875
		udp_ep0_send_data((char *)&wStatus, sizeof(wStatus), 2);
876
		break;
877
	case STD_GET_STATUS_INTERFACE:
878
		DEBUGE("GET_STATUS_INTERFACE ");
879
		wStatus = 0;
880
		/* Table 9.4 wLength Two */
881
		udp_ep0_send_data((char *)&wStatus, sizeof(wStatus), 2);
882
		break;
883
	case STD_GET_STATUS_ENDPOINT:
884
		DEBUGE("GET_STATUS_ENDPOINT(EPidx=%u) ", wIndex&0x0f);
885
		wStatus = 0;
886
		wIndex &= 0x0F;
887
		if ((pUDP->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex == 0)) {
888
			wStatus =
889
			    (pUDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
890
			/* Table 9.4 wLength Two */
891
			udp_ep0_send_data((char *)&wStatus, sizeof(wStatus), 2);
892
		} else if ((pUDP->UDP_GLBSTATE & AT91C_UDP_FADDEN)
893
			   && (wIndex == 0)) {
894
			wStatus =
895
			    (pUDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
896
			/* Table 9.4 wLength Two */
897
			udp_ep0_send_data((char *)&wStatus, sizeof(wStatus), 2);
898
		} else
899
			udp_ep0_send_stall();
900
		break;
901
	case STD_SET_FEATURE_ZERO:
902
		DEBUGE("SET_FEATURE_ZERO ");
903
		udp_ep0_send_stall();
904
		break;
905
	case STD_SET_FEATURE_INTERFACE:
906
		DEBUGE("SET_FEATURE_INTERFACE ");
907
		udp_ep0_send_zlp();
908
		break;
909
	case STD_SET_FEATURE_ENDPOINT:
910
		DEBUGE("SET_FEATURE_ENDPOINT ");
911
		udp_ep0_send_stall();
912
		break;
913
	case STD_CLEAR_FEATURE_ZERO:
914
		DEBUGE("CLEAR_FEATURE_ZERO ");
915
		udp_ep0_send_stall();
916
		break;
917
	case STD_CLEAR_FEATURE_INTERFACE:
918
		DEBUGE("CLEAR_FEATURE_INTERFACE ");
919
		udp_ep0_send_zlp();
920
		break;
921
	case STD_CLEAR_FEATURE_ENDPOINT:
922
		DEBUGE("CLEAR_FEATURE_ENDPOINT(EPidx=%u) ", wIndex & 0x0f);
923
		udp_ep0_send_stall();
924
		break;
925
	case STD_SET_INTERFACE:
926
		DEBUGE("SET INTERFACE(if=%d, alt=%d) ", wIndex, wValue);
927
		/* store the interface number somewhere, once
928
		 * we need to support DFU flashing DFU */
929
		usb_if_alt_nr = wValue;
930
		usb_if_nr = wIndex;
931
		udp_ep0_send_zlp();
932
		break;
933
	default:
934
		DEBUGE("DEFAULT(req=0x%02x, type=0x%02x) ",
935
			bRequest, bmRequestType);
936
		if ((bmRequestType & 0x3f) == USB_TYPE_DFU) {
937
			dfu_ep0_handler(bmRequestType, bRequest,
938
					wValue, wLength);
939
		} else
940
			udp_ep0_send_stall();
941
		break;
942
	}
943
	DEBUGE("\r\n");
944
}
945

    
946
/* minimal USB IRQ handler in DFU mode */
947
static __dfufunc void dfu_udp_irq(void)
948
{
949
	AT91PS_UDP pUDP = AT91C_BASE_UDP;
950
	AT91_REG isr = pUDP->UDP_ISR;
951
	led1on();
952

    
953
	if (isr & AT91C_UDP_ENDBUSRES) {
954
		led2on();
955
		pUDP->UDP_IER = AT91C_UDP_EPINT0;
956
		/* reset all endpoints */
957
		pUDP->UDP_RSTEP = (unsigned int)-1;
958
		pUDP->UDP_RSTEP = 0;
959
		/* Enable the function */
960
		pUDP->UDP_FADDR = AT91C_UDP_FEN;
961
		/* Configure endpoint 0 */
962
		pUDP->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
963
		cur_config = 0;
964

    
965
		if (dfu_state == DFU_STATE_dfuMANIFEST_WAIT_RST ||
966
		    dfu_state == DFU_STATE_dfuMANIFEST ||
967
		    past_manifest) {
968
			AT91F_DBGU_Printk("sam7dfu: switching to APP mode\r\n");
969
			switch (usb_if_alt_nr_dnload) {
970
			case 2:
971
				switch_to_ram = 1;
972
				break;
973
			default:
974
				/* reset back into the main application */
975
				AT91F_RSTSoftReset(AT91C_BASE_RSTC,
976
							  AT91C_RSTC_PROCRST|
977
					   		  AT91C_RSTC_PERRST|
978
							  AT91C_RSTC_EXTRST);
979
				break;
980
			}
981
		}
982
	}
983

    
984
	if (isr & AT91C_UDP_EPINT0)
985
		dfu_udp_ep0_handler();
986

    
987
	/* clear all interrupts */
988
	pUDP->UDP_ICR = isr;
989

    
990
	AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_UDP);
991

    
992
	led1off();
993
}
994

    
995
/* this is only called once before DFU mode, no __dfufunc required */
996
static __noreturn void dfu_switch(void)
997
{
998
	DEBUGE("\r\nsam7dfu: switching to DFU mode\r\n");
999

    
1000
	dfu_state = DFU_STATE_appDETACH;
1001
	AT91F_RSTSoftReset(AT91C_BASE_RSTC, AT91C_RSTC_PROCRST|
1002
			   AT91C_RSTC_PERRST|AT91C_RSTC_EXTRST);
1003

    
1004
	/* We should never reach here, but anyway avoid returning to the
1005
	 * caller since he doesn't expect us to do so */
1006
	while (1) ;
1007
}
1008

    
1009
void __dfufunc dfu_main(void)
1010
{
1011
	AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED1);
1012
	AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2);
1013
	led1off();
1014
	led2off();
1015

    
1016
	AT91F_DBGU_Init();
1017
	AT91F_DBGU_Printk("\n\r\n\rsam7dfu - AT91SAM7 USB DFU bootloader\n\r"
1018
		 "(C) 2006-2011 by Harald Welte <hwelte@hmw-consulting.de>\n\r"
1019
		 "This software is FREE SOFTWARE licensed under GNU GPL\n\r");
1020
	AT91F_DBGU_Printk("Version " COMPILE_SVNREV 
1021
			  " compiled " COMPILE_DATE 
1022
			  " by " COMPILE_BY "\n\r\n\r");
1023

    
1024
	udp_init();
1025

    
1026
	dfu_state = DFU_STATE_dfuIDLE;
1027

    
1028
	/* This implements 
1029
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_UDP,
1030
			      OPENPCD_IRQ_PRIO_UDP,
1031
			      AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, dfu_udp_irq);
1032
	*/
1033
	AT91PS_AIC pAic = AT91C_BASE_AIC;
1034
	pAic->AIC_IDCR = 1 << AT91C_ID_UDP;
1035
	pAic->AIC_SVR[AT91C_ID_UDP] = (unsigned int) &dfu_udp_irq;
1036
	pAic->AIC_SMR[AT91C_ID_UDP] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 
1037
					OPENPCD_IRQ_PRIO_UDP;
1038
	pAic->AIC_ICCR = 1 << AT91C_ID_UDP;
1039

    
1040
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_UDP);
1041

    
1042
	/* End-of-Bus-Reset is always enabled */
1043

    
1044
	/* Clear for set the Pull up resistor */
1045
#if defined(PCD)
1046
	AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
1047
#endif
1048
	AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUPv4);
1049

    
1050
	flash_init();
1051

    
1052
	AT91F_DBGU_Printk("You may now start the DFU up/download process\r\n");
1053
	/* do nothing, since all of DFU is interrupt driven */
1054
	int i = 0;
1055
	while (1) {
1056
	    /* Occasionally reset watchdog */
1057
	    i = (i+1) % 10000;
1058
	    if( i== 0) {
1059
		AT91F_WDTRestart(AT91C_BASE_WDTC);
1060
	    }
1061
	    if (switch_to_ram) {
1062
		void (*ram_app_entry)(void);
1063
		int j;
1064
		for (j = 0; j < 32; j++)
1065
			AT91F_AIC_DisableIt(AT91C_BASE_AIC, j);
1066
		/* jump into RAM */
1067
		AT91F_DBGU_Printk("JUMP TO RAM\r\n");
1068
		ram_app_entry = AT91C_ISRAM + SAM7DFU_RAM_SIZE;
1069
		ram_app_entry();
1070
	    }
1071
	}
1072
}
1073

    
1074
const struct dfuapi __dfufunctab dfu_api = {
1075
	.udp_init		= &udp_init,
1076
	.ep0_send_data		= &udp_ep0_send_data,
1077
	.ep0_send_zlp		= &udp_ep0_send_zlp,
1078
	.ep0_send_stall		= &udp_ep0_send_stall,
1079
	.dfu_ep0_handler	= &dfu_ep0_handler,
1080
	.dfu_switch		= &dfu_switch,
1081
	.dfu_state		= &dfu_state,
1082
	.dfu_dev_descriptor	= &dfu_dev_descriptor,
1083
	.dfu_cfg_descriptor	= &dfu_cfg_descriptor,
1084
};
1085

    
1086
/* just for testing */
1087
int foo = 12345;
(3-3/4)
Add picture from clipboard (Maximum size: 48.8 MB)