Project

General

Profile

Download (21.6 KB) Statistics
| Branch: | Tag: | Revision:
1 1bc85442 (no author)
/* AT91SAM7 USB interface code for OpenPCD 
2
 * (C) 2006 by Harald Welte <laforge@gnumonks.org>
3
 *
4 32985a29 laforge
 *  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 1bc85442 (no author)
 * 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 f57b548d (no author)
30 fa5c8c7c (no author)
#include <errno.h>
31 9164ed93 (no author)
#include <usb_ch9.h>
32 1bc85442 (no author)
#include <sys/types.h>
33
#include <asm/atomic.h>
34 9164ed93 (no author)
#include <lib_AT91SAM7.h>
35
#include <openpcd.h>
36 174bf894 (no author)
37 89c40594 laforge
#include <usb_strings_app.h>
38 5872753e laforge
39 520784c7 (no author)
#include <os/pcd_enumerate.h>
40
#include <os/req_ctx.h>
41 a97e460b laforge
#include <dfu/dfu.h>
42 520784c7 (no author)
#include "../openpcd.h"
43
#include <os/dbgu.h>
44 f57b548d (no author)
45 28eb4a57 laforge
#include "../config.h"
46
47 706ffa9f laforge
//#define DEBUG_UDP_IRQ
48 a914cae2 laforge
//#define DEBUG_UDP_IRQ_IN
49 706ffa9f laforge
//#define DEBUG_UDP_IRQ_OUT
50 f2349ebe Harald Welte
//#define DEBUG_UDP_EP0
51 43d61cf0 (no author)
52 706ffa9f laforge
#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 2858e795 (no author)
58 706ffa9f laforge
#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 28eb4a57 laforge
#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 706ffa9f laforge
76
#define CONFIG_DFU
77 1bc85442 (no author)
78 b0317c72 (no author)
#ifdef CONFIG_DFU
79
static const struct dfuapi *dfu = DFU_API_LOCATION;
80 a97e460b laforge
#define udp_init		dfu->udp_init
81 dd88fde8 Harald Welte
#define udp_ep0_send_data	dfu->ep0_send_data
82 b0317c72 (no author)
#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 1bc85442 (no author)
88 4dc2cb5b laforge
#ifdef CONFIG_USB_HID
89
#include "usb_descriptors_hid.h"
90 28eb4a57 laforge
#else
91 4dc2cb5b laforge
#include "usb_descriptors_openpcd.h"
92 28eb4a57 laforge
#endif
93 f57b548d (no author)
94 4dc2cb5b laforge
static struct udp_pcd upcd;
95 f57b548d (no author)
96 706ffa9f laforge
struct epstate {
97 373c172a Harald Welte
	uint32_t state_busy;
98
	uint32_t state_pending;
99 706ffa9f laforge
};
100
101
static const struct epstate epstate[] = {
102 3b7035dc Min Xu
	[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 706ffa9f laforge
	[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 9f45ae4e laforge
	while ((rctx = req_ctx_find_get(0, epstate[ep].state_busy,
121
				       RCTX_STATE_FREE))) {}
122 e9902c56 laforge
	/* free all currently pending contexts */
123 9f45ae4e laforge
	while ((rctx = req_ctx_find_get(0, epstate[ep].state_pending,
124
				       RCTX_STATE_FREE))) {}
125 706ffa9f laforge
126
	pUDP->UDP_RSTEP |= (1 << ep);
127
	pUDP->UDP_RSTEP &= ~(1 << ep);
128 4b98ba5d Min Xu
	pUDP->UDP_CSR[ep] = AT91C_UDP_EPEDS;
129 706ffa9f laforge
130
	upcd.ep[ep].incomplete.rctx = NULL;
131
}
132 f57b548d (no author)
133 caf50003 (no author)
static void udp_ep0_handler(void);
134 a5a204c6 (no author)
135 fa5c8c7c (no author)
void udp_unthrottle(void)
136
{
137 1bc85442 (no author)
	AT91PS_UDP pUDP = upcd.pUdp;
138 fa5c8c7c (no author)
	pUDP->UDP_IER = AT91C_UDP_EPINT1;
139
}
140
141 e39637e1 Min Xu
int udp_refill_ep(int ep)
142 fa5c8c7c (no author)
{
143 373c172a Harald Welte
	uint16_t i;
144 1bc85442 (no author)
	AT91PS_UDP pUDP = upcd.pUdp;
145 514b0f72 laforge
	struct req_ctx *rctx;
146
	unsigned int start, end;
147 fa5c8c7c (no author)
148 514b0f72 laforge
	/* If we're not configured by the host yet, there is no point
149
	 * in trying to send data to it... */
150 706ffa9f laforge
	if (!upcd.cur_config) {
151 cc0a7ad6 (no author)
		return -ENXIO;
152 706ffa9f laforge
	}
153 cc0a7ad6 (no author)
	
154 514b0f72 laforge
	/* If there are already two packets in transit, the DPR of
155
	 * the SAM7 UDC doesn't have space for more data */
156 e39637e1 Min Xu
	if (atomic_read(&upcd.ep[ep].pkts_in_transit) == 2)
157 fa5c8c7c (no author)
		return -EBUSY;
158 e39637e1 Min Xu
159
	/* disable endpoint interrup */
160
	pUDP->UDP_IDR |= 1 << ep;
161 514b0f72 laforge
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 706ffa9f laforge
		rctx = req_ctx_find_get(0, epstate[ep].state_pending, 
170
					epstate[ep].state_busy);
171 e39637e1 Min Xu
		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 514b0f72 laforge
			return 0;
181 e39637e1 Min Xu
		}
182 3cd467a8 Min Xu
		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 e39637e1 Min Xu
			 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 514b0f72 laforge
		start = 0;
189 706ffa9f laforge
190
		upcd.ep[ep].incomplete.bytes_sent = 0;
191 514b0f72 laforge
	}
192
193
	if (rctx->tot_len - start <= AT91C_EP_IN_SIZE)
194
		end = rctx->tot_len;
195
	else
196 706ffa9f laforge
		end = start + AT91C_EP_IN_SIZE;
197 514b0f72 laforge
198 fa5c8c7c (no author)
	/* fill FIFO/DPR */
199 514b0f72 laforge
	for (i = start; i < end; i++) 
200
		pUDP->UDP_FDR[ep] = rctx->data[i];
201 fa5c8c7c (no author)
202 cc0a7ad6 (no author)
	if (atomic_inc_return(&upcd.ep[ep].pkts_in_transit) == 1) {
203
		/* not been transmitting before, start transmit */
204 fa5c8c7c (no author)
		pUDP->UDP_CSR[ep] |= AT91C_UDP_TXPKTRDY;
205
	}
206 cc0a7ad6 (no author)
207 e39637e1 Min Xu
	if (end == rctx->tot_len) {
208 706ffa9f laforge
		/* 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 e39637e1 Min Xu
	         */
222 706ffa9f laforge
		upcd.ep[ep].incomplete.rctx = rctx;
223
		upcd.ep[ep].incomplete.bytes_sent += end - start;
224
	}
225 fa5c8c7c (no author)
226 e39637e1 Min Xu
	/* re-enable endpoint interrupt */
227
	pUDP->UDP_IER |= 1 << ep;
228 fa5c8c7c (no author)
229 e39637e1 Min Xu
	return 1;
230 706ffa9f laforge
}
231 2858e795 (no author)
232 0d69fadb laforge
static void udp_irq(void)
233 f7d6875c (no author)
{
234 373c172a Harald Welte
	uint32_t csr;
235 1bc85442 (no author)
	AT91PS_UDP pUDP = upcd.pUdp;
236 f7d6875c (no author)
	AT91_REG isr = pUDP->UDP_ISR;
237
238 9f45ae4e laforge
	DEBUGI("udp_irq(imr=0x%04x, isr=0x%04x, state=%d): ", 
239
		pUDP->UDP_IMR, isr, upcd.state);
240 a5a204c6 (no author)
241 f7d6875c (no author)
	if (isr & AT91C_UDP_ENDBUSRES) {
242 2858e795 (no author)
		DEBUGI("ENDBUSRES ");
243 f7d6875c (no author)
		pUDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
244 a5a204c6 (no author)
		pUDP->UDP_IER = AT91C_UDP_EPINT0;
245 4b98ba5d Min Xu
		reset_ep(0);
246
		reset_ep(1);
247
		reset_ep(2);
248
		reset_ep(3);
249
250 1bc85442 (no author)
		/* Enable the function */
251 f7d6875c (no author)
		pUDP->UDP_FADDR = AT91C_UDP_FEN;
252 4b98ba5d Min Xu
253 1bc85442 (no author)
		/* Configure endpoint 0 */
254 f7d6875c (no author)
		pUDP->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
255 1bc85442 (no author)
		upcd.cur_config = 0;
256 9f45ae4e laforge
		upcd.state = USB_STATE_DEFAULT;
257 43d61cf0 (no author)
		
258 b0317c72 (no author)
#ifdef CONFIG_DFU
259
		if (*dfu->dfu_state == DFU_STATE_appDETACH) {
260 9f45ae4e laforge
			DEBUGI("DFU_SWITCH ");
261 43d61cf0 (no author)
			/* now we need to switch to DFU mode */
262 b0317c72 (no author)
			dfu->dfu_switch();
263 706ffa9f laforge
			goto out;
264 43d61cf0 (no author)
		}
265 b0317c72 (no author)
#endif
266 f7d6875c (no author)
	}
267
268
	if (isr & AT91C_UDP_EPINT0) {
269 2858e795 (no author)
		DEBUGI("EP0INT(Control) ");
270 caf50003 (no author)
		udp_ep0_handler();
271 f7d6875c (no author)
	}
272
	if (isr & AT91C_UDP_EPINT1) {
273 373c172a Harald Welte
		uint32_t cur_rcv_bank = upcd.cur_rcv_bank;
274
		uint16_t i, pkt_size;
275 706ffa9f laforge
		struct req_ctx *rctx;
276
277 a5a204c6 (no author)
		csr = pUDP->UDP_CSR[1];
278 706ffa9f laforge
		pkt_size = csr >> 16;
279
280 2858e795 (no author)
		DEBUGI("EP1INT(Out, CSR=0x%08x) ", csr);
281 5f148f59 (no author)
		if (cur_rcv_bank == AT91C_UDP_RX_DATA_BK1)
282 706ffa9f laforge
			DEBUGIO("cur_bank=1 ");
283 5f148f59 (no author)
		else if (cur_rcv_bank == AT91C_UDP_RX_DATA_BK0)
284 706ffa9f laforge
			DEBUGIO("cur_bank=0 ");
285 5f148f59 (no author)
		else
286 706ffa9f laforge
			DEBUGIO("cur_bank INVALID ");
287 5f148f59 (no author)
288
		if (csr & AT91C_UDP_RX_DATA_BK1)
289 706ffa9f laforge
			DEBUGIO("BANK1 ");
290 5f148f59 (no author)
		if (csr & AT91C_UDP_RX_DATA_BK0)
291 706ffa9f laforge
			DEBUGIO("BANK0 ");
292 a5a204c6 (no author)
293 706ffa9f laforge
		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 514b0f72 laforge
						 RCTX_STATE_UDP_RCV_BUSY);
310 5f148f59 (no author)
311 706ffa9f laforge
			if (!rctx) {
312 fa5c8c7c (no author)
				/* disable interrupts for now */
313
				pUDP->UDP_IDR = AT91C_UDP_EPINT1;
314
				DEBUGP("NO_RCTX_AVAIL! ");
315 706ffa9f laforge
				goto cont_ep2;
316 fa5c8c7c (no author)
			}
317 706ffa9f laforge
			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 a5a204c6 (no author)
		}
350 f7d6875c (no author)
	}
351 706ffa9f laforge
cont_ep2:
352 f7d6875c (no author)
	if (isr & AT91C_UDP_EPINT2) {
353 a5a204c6 (no author)
		csr = pUDP->UDP_CSR[2];
354 2858e795 (no author)
		DEBUGI("EP2INT(In, CSR=0x%08x) ", csr);
355 fa5c8c7c (no author)
		if (csr & AT91C_UDP_TXCOMP) {
356 706ffa9f laforge
			DEBUGII("ACK_TX_COMP ");
357 fa5c8c7c (no author)
			/* 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 1bc85442 (no author)
			if (atomic_dec_return(&upcd.ep[2].pkts_in_transit) == 1)
363 fa5c8c7c (no author)
				pUDP->UDP_CSR[2] |= AT91C_UDP_TXPKTRDY;
364
365 e39637e1 Min Xu
			udp_refill_ep(2);
366 fa5c8c7c (no author)
		}
367 f7d6875c (no author)
	}
368 a5a204c6 (no author)
	if (isr & AT91C_UDP_EPINT3) {
369
		csr = pUDP->UDP_CSR[3];
370 706ffa9f laforge
		DEBUGII("EP3INT(Interrupt, CSR=0x%08x) ", csr);
371 fa5c8c7c (no author)
		/* Transmit has completed, re-fill from pending rcts for EP3 */
372 514b0f72 laforge
		if (csr & AT91C_UDP_TXCOMP) {
373
			pUDP->UDP_CSR[3] &= ~AT91C_UDP_TXCOMP;
374
			while (pUDP->UDP_CSR[3] & AT91C_UDP_TXCOMP) ;
375 a5a204c6 (no author)
376 514b0f72 laforge
			/* 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 e39637e1 Min Xu
			udp_refill_ep(3);
381 514b0f72 laforge
		}
382
	}
383 a5a204c6 (no author)
	if (isr & AT91C_UDP_RXSUSP) {
384
		pUDP->UDP_ICR = AT91C_UDP_RXSUSP;
385 2858e795 (no author)
		DEBUGI("RXSUSP ");
386 7d1d85c0 laforge
#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 a5a204c6 (no author)
	}
394
	if (isr & AT91C_UDP_RXRSM) {
395
		pUDP->UDP_ICR = AT91C_UDP_RXRSM;
396 2858e795 (no author)
		DEBUGI("RXRSM ");
397 7d1d85c0 laforge
#ifdef CONFIG_USB_SUSPEND
398
		if (upcd.state == USB_STATE_SUSPENDED)
399
			upcd.state = USB_STATE_CONFIGURED;
400 fa5c8c7c (no author)
		/* FIXME: implement suspend/resume */
401 7d1d85c0 laforge
#endif
402 a5a204c6 (no author)
	}
403
	if (isr & AT91C_UDP_EXTRSM) {
404
		pUDP->UDP_ICR = AT91C_UDP_EXTRSM;
405 2858e795 (no author)
		DEBUGI("EXTRSM ");
406 fa5c8c7c (no author)
		/* FIXME: implement suspend/resume */
407 a5a204c6 (no author)
	}
408
	if (isr & AT91C_UDP_SOFINT) {
409
		pUDP->UDP_ICR = AT91C_UDP_SOFINT;
410 2858e795 (no author)
		DEBUGI("SOFINT ");
411 a5a204c6 (no author)
	}
412
	if (isr & AT91C_UDP_WAKEUP) {
413
		pUDP->UDP_ICR = AT91C_UDP_WAKEUP;
414 2858e795 (no author)
		DEBUGI("WAKEUP ");
415 a5a204c6 (no author)
	}
416 706ffa9f laforge
out:
417 2858e795 (no author)
	DEBUGI("END\r\n");
418 9d0d7022 (no author)
	AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_UDP);
419 f7d6875c (no author)
}
420 f57b548d (no author)
421 d1dd3611 laforge
void udp_pullup_on(void)
422
{
423 28eb4a57 laforge
#ifdef PCD
424 6c6b1878 laforge
	AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
425 28eb4a57 laforge
#endif
426 6c6b1878 laforge
	AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUPv4);
427 d1dd3611 laforge
}
428
429
void udp_pullup_off(void)
430
{
431 28eb4a57 laforge
#ifdef PCD
432 6c6b1878 laforge
	AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUP);
433 28eb4a57 laforge
#endif
434 6c6b1878 laforge
	AT91F_PIO_SetOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUPv4);
435 d1dd3611 laforge
}
436
437 caf50003 (no author)
/* Open USB Device Port  */
438 b0317c72 (no author)
void udp_open(void)
439 f57b548d (no author)
{
440 caf50003 (no author)
	DEBUGPCRF("entering");
441 a97e460b laforge
	udp_init();
442 b0317c72 (no author)
	upcd.pUdp = AT91C_BASE_UDP;
443 1bc85442 (no author)
	upcd.cur_config = 0;
444
	upcd.cur_rcv_bank = AT91C_UDP_RX_DATA_BK0;
445 9f45ae4e laforge
	/* 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 b0317c72 (no author)
449 327d426e (no author)
	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_UDP,
450
			      OPENPCD_IRQ_PRIO_UDP,
451 9f45ae4e laforge
			      AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &udp_irq);
452 f7d6875c (no author)
	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_UDP);
453
454
	/* End-of-Bus-Reset is always enabled */
455
456 84f258ce (no author)
	/* Set the Pull up resistor */
457 d1dd3611 laforge
	udp_pullup_on();
458 caf50003 (no author)
}
459 f57b548d (no author)
460 43d61cf0 (no author)
void udp_reset(void)
461 f57b548d (no author)
{
462 43d61cf0 (no author)
	volatile int i;
463 f57b548d (no author)
464 d1dd3611 laforge
	udp_pullup_off();
465 43d61cf0 (no author)
	for (i = 0; i < 0xffff; i++)
466
		;
467 d1dd3611 laforge
	udp_pullup_on();
468 f57b548d (no author)
}
469
470 caf50003 (no author)
/* Handle requests on the USB Control Endpoint */
471
static void udp_ep0_handler(void)
472 f57b548d (no author)
{
473 1bc85442 (no author)
	AT91PS_UDP pUDP = upcd.pUdp;
474 373c172a Harald Welte
	uint8_t bmRequestType, bRequest;
475
	uint16_t wValue, wIndex, wLength, wStatus;
476
	uint32_t csr = pUDP->UDP_CSR[0];
477 fa5c8c7c (no author)
478 cc0a7ad6 (no author)
	DEBUGE("CSR=0x%04x ", csr);
479 f57b548d (no author)
480 fa5c8c7c (no author)
	if (csr & AT91C_UDP_STALLSENT) {
481 cc0a7ad6 (no author)
		DEBUGE("ACK_STALLSENT ");
482 fa5c8c7c (no author)
		pUDP->UDP_CSR[0] = ~AT91C_UDP_STALLSENT;
483
	}
484
485
	if (csr & AT91C_UDP_RX_DATA_BK0) {
486 cc0a7ad6 (no author)
		DEBUGE("ACK_BANK0 ");
487 0ba41a67 (no author)
		pUDP->UDP_CSR[0] &= ~AT91C_UDP_RX_DATA_BK0;
488 fa5c8c7c (no author)
	}
489
490
	if (!(csr & AT91C_UDP_RXSETUP)) {
491 cc0a7ad6 (no author)
		DEBUGE("no setup packet ");
492
		return;
493
	}
494
495
	DEBUGE("len=%d ", csr >> 16);
496
	if (csr >> 16  == 0) {
497
		DEBUGE("empty packet ");
498 f57b548d (no author)
		return;
499 a5a204c6 (no author)
	}
500 f57b548d (no author)
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 cc0a7ad6 (no author)
	DEBUGE("bmRequestType=0x%2x ", bmRequestType);
511
512 f57b548d (no author)
	if (bmRequestType & 0x80) {
513 cc0a7ad6 (no author)
		DEBUGE("DATA_IN=1 ");
514 f57b548d (no author)
		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 514b0f72 laforge
	DEBUGE("dfu_state = %u ", *dfu->dfu_state);
521 1bc85442 (no author)
	/* Handle supported standard device request Cf Table 9-3 in USB
522 cc0a7ad6 (no author)
	 * speciication Rev 1.1 */
523 f57b548d (no author)
	switch ((bRequest << 8) | bmRequestType) {
524 373c172a Harald Welte
		uint8_t desc_type, desc_index;
525 f57b548d (no author)
	case STD_GET_DESCRIPTOR:
526 9f45ae4e laforge
		DEBUGE("GET_DESCRIPTOR(wValue=0x%04x, wIndex=0x%04x) ",
527
			wValue, wIndex);
528 5872753e laforge
		desc_type = wValue >> 8;
529
		desc_index = wValue & 0xff;
530
		switch (desc_type) {
531
		case USB_DT_DEVICE:
532 43d61cf0 (no author)
			/* Return Device Descriptor */
533
#ifdef CONFIG_DFU
534 b0317c72 (no author)
			if (*dfu->dfu_state != DFU_STATE_appIDLE)
535 43d61cf0 (no author)
				udp_ep0_send_data((const char *) 
536 b0317c72 (no author)
						  dfu->dfu_dev_descriptor,
537 ebf16b4d Holger Hans Peter Freyther
						  dfu->dfu_dev_descriptor->bLength,
538
						  wLength);
539 43d61cf0 (no author)
			else
540
#endif
541
			udp_ep0_send_data((const char *) &dev_descriptor,
542 ebf16b4d Holger Hans Peter Freyther
					  sizeof(dev_descriptor), wLength);
543 5872753e laforge
			break;
544
		case USB_DT_CONFIG:
545 43d61cf0 (no author)
			/* Return Configuration Descriptor */
546
#ifdef CONFIG_DFU
547 b0317c72 (no author)
			if (*dfu->dfu_state != DFU_STATE_appIDLE)
548 43d61cf0 (no author)
				udp_ep0_send_data((const char *)
549 b0317c72 (no author)
						  dfu->dfu_cfg_descriptor,
550 ebf16b4d Holger Hans Peter Freyther
						  dfu->dfu_cfg_descriptor->ucfg.wTotalLength,
551
						  wLength);
552 43d61cf0 (no author)
			else
553
#endif
554
			udp_ep0_send_data((const char *) &cfg_descriptor,
555 ebf16b4d Holger Hans Peter Freyther
					   sizeof(cfg_descriptor), wLength);
556 5872753e laforge
			break;
557
		case USB_DT_STRING:
558 28eb4a57 laforge
#ifdef CONFIG_USB_STRING
559 43d61cf0 (no author)
			/* Return String descriptor */
560 9f45ae4e laforge
			if (desc_index > ARRAY_SIZE(usb_strings))
561
				goto out_stall;
562
			DEBUGE("bLength=%u, wLength=%u\n", 
563 5872753e laforge
				usb_strings[desc_index]->bLength, wLength);
564
			udp_ep0_send_data((const char *) usb_strings[desc_index],
565 ebf16b4d Holger Hans Peter Freyther
					  usb_strings[desc_index]->bLength,
566
					  wLength);
567 28eb4a57 laforge
#else
568
			goto out_stall;
569
#endif
570 5872753e laforge
			break;
571
		case USB_DT_CS_DEVICE:
572 514b0f72 laforge
			/* Return Function descriptor */
573
			udp_ep0_send_data((const char *) &dfu->dfu_cfg_descriptor->func_dfu,
574 ebf16b4d Holger Hans Peter Freyther
					  sizeof(dfu->dfu_cfg_descriptor->func_dfu), wLength);
575 d9c44227 laforge
			break;
576 9f45ae4e laforge
		case USB_DT_INTERFACE:
577 43d61cf0 (no author)
			/* Return Interface descriptor */
578 9f45ae4e laforge
			if (desc_index > cfg_descriptor.ucfg.bNumInterfaces)
579
				goto out_stall;
580
			switch (desc_index) {
581
			case 0:
582 d9c44227 laforge
				udp_ep0_send_data((const char *)
583
						&cfg_descriptor.uif,
584 ebf16b4d Holger Hans Peter Freyther
						sizeof(cfg_descriptor.uif),
585
						wLength);
586 9f45ae4e laforge
				break;
587 d9c44227 laforge
	#ifdef CONFIG_DFU
588 9f45ae4e laforge
			case 1:
589 d9c44227 laforge
				udp_ep0_send_data((const char *)
590
						&cfg_descriptor.uif_dfu[0],
591 ebf16b4d Holger Hans Peter Freyther
						sizeof(cfg_descriptor.uif_dfu[0]),
592
						wLength);
593 9f45ae4e laforge
				break;
594
			case 2:
595 d9c44227 laforge
				udp_ep0_send_data((const char *)
596
						&cfg_descriptor.uif_dfu[1],
597 ebf16b4d Holger Hans Peter Freyther
						sizeof(cfg_descriptor.uif_dfu[1]),
598
						wLength);
599 9f45ae4e laforge
				break;
600 7d31d475 Harald Welte
			case 3:
601
				udp_ep0_send_data((const char *)
602
						&cfg_descriptor.uif_dfu[2],
603 ebf16b4d Holger Hans Peter Freyther
						sizeof(cfg_descriptor.uif_dfu[2]),
604
						wLength);
605 7d31d475 Harald Welte
				break;
606 d9c44227 laforge
	#endif
607 9f45ae4e laforge
			default:
608
				goto out_stall;
609
				break;
610
			}
611 5872753e laforge
			break;
612
		default:
613 9f45ae4e laforge
			goto out_stall;
614 d9c44227 laforge
			break;
615 5872753e laforge
		}
616 f57b548d (no author)
		break;
617
	case STD_SET_ADDRESS:
618 cc0a7ad6 (no author)
		DEBUGE("SET_ADDRESS ");
619 d9c44227 laforge
		if (wValue > 127)
620 9f45ae4e laforge
			goto out_stall;
621 d9c44227 laforge
		
622 9f45ae4e laforge
		switch (upcd.state) {
623
		case USB_STATE_DEFAULT:
624 d9c44227 laforge
			udp_ep0_send_zlp();
625 9f45ae4e laforge
			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 d9c44227 laforge
			udp_ep0_send_zlp();
635 9f45ae4e laforge
			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 f57b548d (no author)
		break;
646
	case STD_SET_CONFIGURATION:
647 cc0a7ad6 (no author)
		DEBUGE("SET_CONFIG ");
648 9f45ae4e laforge
		if (upcd.state != USB_STATE_ADDRESS &&
649
		    upcd.state != USB_STATE_CONFIGURED) {
650 d9c44227 laforge
		    	goto out_stall;
651 9f45ae4e laforge
		}
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 d9c44227 laforge
		} else if ((wValue & 0xff) <=
660 9f45ae4e laforge
					dev_descriptor.bNumConfigurations) {
661 cc0a7ad6 (no author)
			DEBUGE("VALUE!=0 ");
662 9f45ae4e laforge
			upcd.state = USB_STATE_CONFIGURED;
663
			pUDP->UDP_GLBSTATE = AT91C_UDP_CONFG;
664 d9c44227 laforge
			pUDP->UDP_CSR[1] = AT91C_UDP_EPEDS |
665 9f45ae4e laforge
					   AT91C_UDP_EPTYPE_BULK_OUT;
666 d9c44227 laforge
			pUDP->UDP_CSR[2] = AT91C_UDP_EPEDS |
667 9f45ae4e laforge
					   AT91C_UDP_EPTYPE_BULK_IN;
668 d9c44227 laforge
			pUDP->UDP_CSR[3] = AT91C_UDP_EPEDS |
669 9f45ae4e laforge
					   AT91C_UDP_EPTYPE_INT_IN;
670
		} else {
671
			/* invalid configuration */
672
			goto out_stall;
673
			break;
674
		}
675 1bc85442 (no author)
		upcd.cur_config = wValue;
676 43d61cf0 (no author)
		udp_ep0_send_zlp();
677 d9c44227 laforge
		pUDP->UDP_IER = (AT91C_UDP_EPINT0 | AT91C_UDP_EPINT1 |
678
				 AT91C_UDP_EPINT2 | AT91C_UDP_EPINT3);
679 f57b548d (no author)
		break;
680
	case STD_GET_CONFIGURATION:
681 cc0a7ad6 (no author)
		DEBUGE("GET_CONFIG ");
682 9f45ae4e laforge
		switch (upcd.state) {
683
		case USB_STATE_ADDRESS:
684
		case USB_STATE_CONFIGURED:
685 ebf16b4d Holger Hans Peter Freyther
			/* Table 9.4 wLength One */
686 9f45ae4e laforge
			udp_ep0_send_data((char *)&(upcd.cur_config),
687 ebf16b4d Holger Hans Peter Freyther
					   sizeof(upcd.cur_config), 1);
688 9f45ae4e laforge
			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 ebf16b4d Holger Hans Peter Freyther
		/* Table 9.4 wLength One */
699 9f45ae4e laforge
		udp_ep0_send_data((char *)&(upcd.cur_altsett),
700 ebf16b4d Holger Hans Peter Freyther
				  sizeof(upcd.cur_altsett), 1);
701 f57b548d (no author)
		break;
702
	case STD_GET_STATUS_ZERO:
703 cc0a7ad6 (no author)
		DEBUGE("GET_STATUS_ZERO ");
704 f57b548d (no author)
		wStatus = 0;
705 ebf16b4d Holger Hans Peter Freyther
		/* Table 9.4 wLength Two */
706
		udp_ep0_send_data((char *)&wStatus, sizeof(wStatus), 2);
707 f57b548d (no author)
		break;
708
	case STD_GET_STATUS_INTERFACE:
709 cc0a7ad6 (no author)
		DEBUGE("GET_STATUS_INTERFACE ");
710 9f45ae4e laforge
		if (upcd.state == USB_STATE_DEFAULT ||
711
		    (upcd.state == USB_STATE_ADDRESS && wIndex != 0))
712 d9c44227 laforge
			goto out_stall;
713 f57b548d (no author)
		wStatus = 0;
714 ebf16b4d Holger Hans Peter Freyther
		/* Table 9.4 wLength Two */
715
		udp_ep0_send_data((char *)&wStatus, sizeof(wStatus), 2);
716 f57b548d (no author)
		break;
717
	case STD_GET_STATUS_ENDPOINT:
718 cc0a7ad6 (no author)
		DEBUGE("GET_STATUS_ENDPOINT(EPidx=%u) ", wIndex&0x0f);
719 9f45ae4e laforge
		if (upcd.state == USB_STATE_DEFAULT ||
720
		    (upcd.state == USB_STATE_ADDRESS && wIndex != 0))
721 d9c44227 laforge
			goto out_stall;
722 f57b548d (no author)
		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 ebf16b4d Holger Hans Peter Freyther
			/* Table 9.4 wLength Two */
728
			udp_ep0_send_data((char *)&wStatus, sizeof(wStatus), 2);
729 f57b548d (no author)
		} else if ((pUDP->UDP_GLBSTATE & AT91C_UDP_FADDEN)
730
			   && (wIndex == 0)) {
731
			wStatus =
732
			    (pUDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
733 ebf16b4d Holger Hans Peter Freyther
			/* Table 9.4 wLength Two */
734
			udp_ep0_send_data((char *)&wStatus, sizeof(wStatus), 2);
735 f57b548d (no author)
		} else
736 9f45ae4e laforge
			goto out_stall;
737 f57b548d (no author)
		break;
738
	case STD_SET_FEATURE_ZERO:
739 cc0a7ad6 (no author)
		DEBUGE("SET_FEATURE_ZERO ");
740 9f45ae4e laforge
		if (upcd.state == USB_STATE_ADDRESS &&
741
		    (wIndex & 0xff) != 0)
742
			goto out_stall;
743
		/* FIXME: implement this */
744
		goto out_stall;
745 f57b548d (no author)
		break;
746
	case STD_SET_FEATURE_INTERFACE:
747 cc0a7ad6 (no author)
		DEBUGE("SET_FEATURE_INTERFACE ");
748 9f45ae4e laforge
		if (upcd.state == USB_STATE_ADDRESS &&
749
		    (wIndex & 0xff) != 0)
750
			goto out_stall;
751 43d61cf0 (no author)
		udp_ep0_send_zlp();
752 f57b548d (no author)
		break;
753
	case STD_SET_FEATURE_ENDPOINT:
754 cc0a7ad6 (no author)
		DEBUGE("SET_FEATURE_ENDPOINT ");
755 9f45ae4e laforge
		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 43d61cf0 (no author)
		udp_ep0_send_zlp();
761 f57b548d (no author)
		wIndex &= 0x0F;
762
		if ((wValue == 0) && wIndex && (wIndex <= 3)) {
763
			pUDP->UDP_CSR[wIndex] = 0;
764 43d61cf0 (no author)
			udp_ep0_send_zlp();
765 f57b548d (no author)
		} else
766 9f45ae4e laforge
			goto out_stall;
767 f57b548d (no author)
		break;
768
	case STD_CLEAR_FEATURE_ZERO:
769 cc0a7ad6 (no author)
		DEBUGE("CLEAR_FEATURE_ZERO ");
770 9f45ae4e laforge
		goto out_stall;
771 f57b548d (no author)
		break;
772
	case STD_CLEAR_FEATURE_INTERFACE:
773 a5a204c6 (no author)
		DEBUGP("CLEAR_FEATURE_INTERFACE ");
774 43d61cf0 (no author)
		udp_ep0_send_zlp();
775 f57b548d (no author)
		break;
776
	case STD_CLEAR_FEATURE_ENDPOINT:
777 cc0a7ad6 (no author)
		DEBUGE("CLEAR_FEATURE_ENDPOINT(EPidx=%u) ", wIndex & 0x0f);
778 9f45ae4e laforge
		if (wValue != USB_ENDPOINT_HALT)
779
			goto out_stall;
780 f57b548d (no author)
		wIndex &= 0x0F;
781
		if ((wValue == 0) && wIndex && (wIndex <= 3)) {
782 706ffa9f laforge
			reset_ep(wIndex);
783 43d61cf0 (no author)
			udp_ep0_send_zlp();
784 f57b548d (no author)
		} else
785 9f45ae4e laforge
			goto out_stall;
786 f57b548d (no author)
		break;
787 5f148f59 (no author)
	case STD_SET_INTERFACE:
788 cc0a7ad6 (no author)
		DEBUGE("SET INTERFACE ");
789 9f45ae4e laforge
		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 d9c44227 laforge
		/* USB spec mandates that if we only support one altsetting in
796 28eb4a57 laforge
		 * the given interface, we shall respond with STALL in the
797
		 * status stage */
798 d9c44227 laforge
		udp_ep0_send_stall();
799 5f148f59 (no author)
		break;
800 f57b548d (no author)
	default:
801 706ffa9f laforge
		DEBUGE("DEFAULT(req=0x%02x, type=0x%02x) ", 
802
			bRequest, bmRequestType);
803 43d61cf0 (no author)
#ifdef CONFIG_DFU
804
		if ((bmRequestType & 0x3f) == USB_TYPE_DFU) {
805 706ffa9f laforge
			dfu->dfu_ep0_handler(bmRequestType, bRequest, wValue,
806
					     wLength);
807 43d61cf0 (no author)
		} else
808
#endif
809 9f45ae4e laforge
		goto out_stall;
810 f57b548d (no author)
		break;
811
	}
812 9f45ae4e laforge
	return;
813
out_stall:
814
	DEBUGE("STALL!! ");
815
	udp_ep0_send_stall();
816 f57b548d (no author)
}
Add picture from clipboard (Maximum size: 48.8 MB)