diff options
| author | laforge <laforge@6dc7ffe9-61d6-0310-9af1-9938baff3ed1> | 2006-09-20 11:44:10 +0000 | 
|---|---|---|
| committer | laforge <laforge@6dc7ffe9-61d6-0310-9af1-9938baff3ed1> | 2006-09-20 11:44:10 +0000 | 
| commit | 514b0f72f50b50b75ef855f008c888f29989d68e (patch) | |
| tree | 4a48031e2d2e95512ae3dc868301b5314c317081 /firmware/src/os | |
| parent | 20b657d7d20508b2a5fedf2e7a59a30e3d9a2fa4 (diff) | |
- Add OpenPICC register definition (and USB command handling)
- Add automatic generation of include/compile.h with svn revision and compiletime
- Add openpcd_compile_version structure to obtain version via USB
- Move LED commands into new CMD_CLS_GENERIC family
- Update TODO
- Add support for large (2048 byte) request contexts in addition to 64byte
- Shrink req_ctx size by collapsing rx and tx buffer into one
- move definition of DFU_API_LOCATION to header file
- Implement large req_ctx aware USB transmit / refill routines
- Implement TX refilling for IRQ Endpoint
- Print version information at startup time
- move some generic req_ctx processing into usb_handler.c
- Some further work on DFU (still not finished)
- Only use '-Os' for DFU, use '-O2' for application code
git-svn-id: https://svn.openpcd.org:2342/trunk@208 6dc7ffe9-61d6-0310-9af1-9938baff3ed1
Diffstat (limited to 'firmware/src/os')
| -rw-r--r-- | firmware/src/os/dbgu.c | 8 | ||||
| -rw-r--r-- | firmware/src/os/led.c | 21 | ||||
| -rw-r--r-- | firmware/src/os/main.c | 12 | ||||
| -rw-r--r-- | firmware/src/os/main.h | 1 | ||||
| -rw-r--r-- | firmware/src/os/pcd_enumerate.c | 93 | ||||
| -rw-r--r-- | firmware/src/os/pcd_enumerate.h | 7 | ||||
| -rw-r--r-- | firmware/src/os/pio_irq.c | 11 | ||||
| -rw-r--r-- | firmware/src/os/pwm.c | 7 | ||||
| -rw-r--r-- | firmware/src/os/req_ctx.c | 37 | ||||
| -rw-r--r-- | firmware/src/os/req_ctx.h | 16 | ||||
| -rw-r--r-- | firmware/src/os/usb_benchmark.c | 11 | ||||
| -rw-r--r-- | firmware/src/os/usb_handler.c | 42 | ||||
| -rw-r--r-- | firmware/src/os/usb_handler.h | 10 | ||||
| -rw-r--r-- | firmware/src/os/usbcmd_generic.c | 49 | ||||
| -rw-r--r-- | firmware/src/os/usbcmd_generic.h | 4 | 
15 files changed, 234 insertions, 95 deletions
| diff --git a/firmware/src/os/dbgu.c b/firmware/src/os/dbgu.c index f7c62e3..eed5546 100644 --- a/firmware/src/os/dbgu.c +++ b/firmware/src/os/dbgu.c @@ -139,7 +139,13 @@ void AT91F_DBGU_Init(void)  			      DBGU_irq_handler);  	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS); -	AT91F_DBGU_Printk +	AT91F_DBGU_Printk("\n\r"); +	AT91F_DBGU_Printk(opcd_version.svnrev); +	AT91F_DBGU_Printk(" "); +	AT91F_DBGU_Printk(opcd_version.date); +	AT91F_DBGU_Printk(" "); +	AT91F_DBGU_Printk(opcd_version.by); +	AT91F_DBGU_Printk("\n\r");  	    ("\n\r-I- OpenPCD test mode\n\r 0) Set Pull-up 1) Clear Pull-up "  	     "2) Toggle LED1 3) Toggle LED2 4) Test RC632\n\r"  	     "5) Read RxWait 6) Write RxWait 7) Dump RC632 Regs\n\r"); diff --git a/firmware/src/os/led.c b/firmware/src/os/led.c index 30353ac..96ffecc 100644 --- a/firmware/src/os/led.c +++ b/firmware/src/os/led.c @@ -73,31 +73,10 @@ int led_toggle(int led)  	return !on;  } -static int led_usb_rx(struct req_ctx *rctx) -{ -	struct openpcd_hdr *poh = (struct openpcd_hdr *) &rctx->rx.data[0]; -	int ret = 1; - -	switch (poh->cmd) { -	case OPENPCD_CMD_SET_LED: -		DEBUGP("SET LED(%u,%u) ", poh->reg, poh->val); -		led_switch(poh->reg, poh->val); -		break; -	default: -		DEBUGP("UNKNOWN "); -		ret = -EINVAL; -		break; -	} -	req_ctx_put(rctx); -	return 1; -} -  void led_init(void)  {  	AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED1);  	AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_LED2);  	led_switch(1, 0);  	led_switch(2, 0); - -	usb_hdlr_register(&led_usb_rx, OPENPCD_CMD_CLS_LED);  } diff --git a/firmware/src/os/main.c b/firmware/src/os/main.c index 3e05a7d..ce611bc 100644 --- a/firmware/src/os/main.c +++ b/firmware/src/os/main.c @@ -24,9 +24,18 @@  #include <os/led.h>  #include <os/main.h>  #include <os/power.h> +#include <os/usbcmd_generic.h>  #include <os/pcd_enumerate.h>  #include "../openpcd.h" +#include <compile.h> + +const struct openpcd_compile_version opcd_version = { +	.svnrev = COMPILE_SVNREV, +	.date = COMPILE_DATE, +	.by = COMPILE_BY, +}; +  int main(void)  {  	/* initialize LED and debug unit */ @@ -34,10 +43,13 @@ int main(void)  	AT91F_DBGU_Init();  	AT91F_PIOA_CfgPMC(); +  	/* call application specific init function */  	_init_func();  	/* initialize USB */ +	req_ctx_init(); +	usbcmd_gen_init();  	udp_open();  	// Enable User Reset and set its minimal assertion to 960 us diff --git a/firmware/src/os/main.h b/firmware/src/os/main.h index 1adc8f6..bd42341 100644 --- a/firmware/src/os/main.h +++ b/firmware/src/os/main.h @@ -5,4 +5,5 @@ extern void _init_func(void);  extern int _main_dbgu(char key);  extern void _main_func(void); +extern const struct openpcd_compile_version opcd_version;  #endif diff --git a/firmware/src/os/pcd_enumerate.c b/firmware/src/os/pcd_enumerate.c index 1f35b06..e3443a8 100644 --- a/firmware/src/os/pcd_enumerate.c +++ b/firmware/src/os/pcd_enumerate.c @@ -52,7 +52,6 @@  #define AT91C_EP_INT  3  #ifdef CONFIG_DFU -#define DFU_API_LOCATION	((const struct dfuapi *) 0x00100fd0)  static const struct dfuapi *dfu = DFU_API_LOCATION;  #define udp_init		dfu->udp_init  #define udp_ep0_send_data	dfu->ep0_send_data @@ -167,32 +166,64 @@ void udp_unthrottle(void)  	pUDP->UDP_IER = AT91C_UDP_EPINT1;  } -int udp_refill_ep(int ep, struct req_ctx *rctx) +int udp_refill_ep(int ep)  {  	u_int16_t i;  	AT91PS_UDP pUDP = upcd.pUdp; +	struct req_ctx *rctx; +	unsigned int start, end; +	/* If we're not configured by the host yet, there is no point +	 * in trying to send data to it... */  	if (!upcd.cur_config)  		return -ENXIO; -	if (rctx->tx.tot_len > AT91C_EP_IN_SIZE) { -		DEBUGPCRF("TOO LARGE!!!!!!!!!!!!!!!!!!!!!!!!!!! (%d > %d)", -			  rctx->tx.tot_len, AT91C_EP_IN_SIZE); -		return -EINVAL; -	} - +	/* If there are already two packets in transit, the DPR of +	 * the SAM7 UDC doesn't have space for more data */  	if (atomic_read(&upcd.ep[ep].pkts_in_transit) == 2)  		return -EBUSY; -		 + +	/* If we have an incompletely-transmitted req_ctx (>EP size), +	 * we need to transmit the rest and finish the transaction */ +	if (upcd.ep[ep].incomplete.rctx) { +		rctx = upcd.ep[ep].incomplete.rctx; +		start = upcd.ep[ep].incomplete.bytes_sent; +	} else { +		unsigned int state, state_busy; +		if (ep == 2) { +			state = RCTX_STATE_UDP_EP2_PENDING; +			state_busy = RCTX_STATE_UDP_EP2_BUSY; +		} else { +			state = RCTX_STATE_UDP_EP3_PENDING; +			state_busy = RCTX_STATE_UDP_EP3_BUSY; +		} + +		/* get pending rctx and start transmitting from zero */ +		rctx = req_ctx_find_get(0, state, state_busy); +		if (!rctx) +			return 0; +		start = 0; +	} + +	if (rctx->tot_len - start <= AT91C_EP_IN_SIZE) +		end = rctx->tot_len; +	else +		end = AT91C_EP_IN_SIZE; +  	/* fill FIFO/DPR */ -	for (i = 0; i < rctx->tx.tot_len; i++)  -		pUDP->UDP_FDR[ep] = rctx->tx.data[i]; +	for (i = start; i < end; i++)  +		pUDP->UDP_FDR[ep] = rctx->data[i];  	if (atomic_inc_return(&upcd.ep[ep].pkts_in_transit) == 1) {  		/* not been transmitting before, start transmit */  		pUDP->UDP_CSR[ep] |= AT91C_UDP_TXPKTRDY;  	} +	/* Increment the number of bytes sent in the current large +	 * context, if any */ +	if (start != 0) +		upcd.ep[ep].incomplete.bytes_sent += end-start; +  	/* return rctx to pool of free contexts */  	req_ctx_put(rctx); @@ -257,19 +288,21 @@ static void udp_irq(void)  		if (csr & cur_rcv_bank) {  			u_int16_t pkt_recv = 0;  			u_int16_t pkt_size = csr >> 16; -			struct req_ctx *rctx = req_ctx_find_get(RCTX_STATE_FREE, -								RCTX_STATE_UDP_RCV_BUSY); +			struct req_ctx *rctx =  +				req_ctx_find_get(0, RCTX_STATE_FREE, +						 RCTX_STATE_UDP_RCV_BUSY);  			if (rctx) { -				rctx->rx.tot_len = pkt_size; +				rctx->tot_len = pkt_size;  				while (pkt_size--) -					rctx->rx.data[pkt_recv++] = pUDP->UDP_FDR[1]; +					rctx->data[pkt_recv++] = pUDP->UDP_FDR[1];  				pUDP->UDP_CSR[1] &= ~cur_rcv_bank;  				if (cur_rcv_bank == AT91C_UDP_RX_DATA_BK0)  					cur_rcv_bank = AT91C_UDP_RX_DATA_BK1;  				else  					cur_rcv_bank = AT91C_UDP_RX_DATA_BK0;  				upcd.cur_rcv_bank = cur_rcv_bank; +				DEBUGI("rctxdump(%s) ", hexdump(rctx->data, rctx->tot_len));  				req_ctx_set_state(rctx, RCTX_STATE_UDP_RCV_DONE);  				DEBUGI("RCTX=%u ", req_ctx_num(rctx));  			} else { @@ -283,8 +316,6 @@ static void udp_irq(void)  		csr = pUDP->UDP_CSR[2];  		DEBUGI("EP2INT(In, CSR=0x%08x) ", csr);  		if (csr & AT91C_UDP_TXCOMP) { -			struct req_ctx *rctx; -  			DEBUGI("ACK_TX_COMP ");  			/* acknowledge TX completion */  			pUDP->UDP_CSR[2] &= ~AT91C_UDP_TXCOMP; @@ -294,21 +325,24 @@ static void udp_irq(void)  			if (atomic_dec_return(&upcd.ep[2].pkts_in_transit) == 1)  				pUDP->UDP_CSR[2] |= AT91C_UDP_TXPKTRDY; -			/* try to re-fill from pending rcts for EP2 */ -			rctx = req_ctx_find_get(RCTX_STATE_UDP_EP2_PENDING, -						RCTX_STATE_UDP_EP2_BUSY); -			if (rctx) -				udp_refill_ep(2, rctx); -			else -				DEBUGI("NO_RCTX_pending "); +			udp_refill_ep(2);  		}  	}  	if (isr & AT91C_UDP_EPINT3) {  		csr = pUDP->UDP_CSR[3];  		DEBUGI("EP3INT(Interrupt, CSR=0x%08x) ", csr);  		/* Transmit has completed, re-fill from pending rcts for EP3 */ -	} +		if (csr & AT91C_UDP_TXCOMP) { +			pUDP->UDP_CSR[3] &= ~AT91C_UDP_TXCOMP; +			while (pUDP->UDP_CSR[3] & AT91C_UDP_TXCOMP) ; +			/* if we already have another packet in DPR, send it */ +			if (atomic_dec_return(&upcd.ep[3].pkts_in_transit) == 1) +				pUDP->UDP_CSR[3] |= AT91C_UDP_TXPKTRDY; + +			udp_refill_ep(3); +		} +	}  	if (isr & AT91C_UDP_RXSUSP) {  		pUDP->UDP_ICR = AT91C_UDP_RXSUSP;  		DEBUGI("RXSUSP "); @@ -424,6 +458,7 @@ static void udp_ep0_handler(void)  	pUDP->UDP_CSR[0] &= ~AT91C_UDP_RXSETUP;  	while ((pUDP->UDP_CSR[0] & AT91C_UDP_RXSETUP)) ; +	DEBUGE("dfu_state = %u ", *dfu->dfu_state);  	/* Handle supported standard device request Cf Table 9-3 in USB  	 * speciication Rev 1.1 */  	switch ((bRequest << 8) | bmRequestType) { @@ -465,6 +500,10 @@ static void udp_ep0_handler(void)  				udp_ep0_send_stall();  				break;  			} +		} else if (wValue == 0x2100) { +			/* Return Function descriptor */ +			udp_ep0_send_data((const char *) &dfu->dfu_cfg_descriptor->func_dfu, +					  MIN(sizeof(dfu->dfu_cfg_descriptor->func_dfu), wLength));  #if 0  		} else if (wValue == 0x400) {  			/* Return Interface descriptor */ @@ -581,7 +620,7 @@ static void udp_ep0_handler(void)  				pUDP->UDP_RSTEP &= ~AT91C_UDP_EP2;  				/* free all currently transmitting contexts */ -				while (rctx = req_ctx_find_get(RCTX_STATE_UDP_EP2_BUSY, +				while (rctx = req_ctx_find_get(0, RCTX_STATE_UDP_EP2_BUSY,  							       RCTX_STATE_FREE)) {}  				atomic_set(&upcd.ep[wIndex].pkts_in_transit, 0);  			} @@ -593,7 +632,7 @@ static void udp_ep0_handler(void)  				pUDP->UDP_RSTEP &= ~AT91C_UDP_EP3;  				/* free all currently transmitting contexts */ -				while (rctx = req_ctx_find_get(RCTX_STATE_UDP_EP3_BUSY, +				while (rctx = req_ctx_find_get(0, RCTX_STATE_UDP_EP3_BUSY,  							       RCTX_STATE_FREE)) {}  				atomic_set(&upcd.ep[wIndex].pkts_in_transit, 0);  			} diff --git a/firmware/src/os/pcd_enumerate.h b/firmware/src/os/pcd_enumerate.h index 813243e..3b95de7 100644 --- a/firmware/src/os/pcd_enumerate.h +++ b/firmware/src/os/pcd_enumerate.h @@ -10,13 +10,16 @@  struct req_ctx;  extern void udp_open(void); -extern int udp_refill_ep(int ep, struct req_ctx *rctx); +extern int udp_refill_ep(int ep);  extern void udp_unthrottle(void);  extern void udp_reset(void);  struct ep_ctx {  	atomic_t pkts_in_transit; -	void *ctx; +	struct { +		struct req_ctx *rctx; +		unsigned int bytes_sent; +	} incomplete;  };  struct udp_pcd { diff --git a/firmware/src/os/pio_irq.c b/firmware/src/os/pio_irq.c index dfe818c..14f51c2 100644 --- a/firmware/src/os/pio_irq.c +++ b/firmware/src/os/pio_irq.c @@ -50,7 +50,7 @@ static void pio_irq_demux(void)  	if (send_usb && !pirqs.usb_throttled) {  		struct req_ctx *irq_rctx; -		irq_rctx = req_ctx_find_get(RCTX_STATE_FREE, +		irq_rctx = req_ctx_find_get(0, RCTX_STATE_FREE,  					    RCTX_STATE_PIOIRQ_BUSY);  		if (!irq_rctx) {  			/* we cannot disable the interrupt, since we have @@ -59,14 +59,14 @@ static void pio_irq_demux(void)  		} else {  			struct openpcd_hdr *opcdh;  			u_int32_t *regmask; -			opcdh = (struct openpcd_hdr *) &irq_rctx->tx.data[0]; -			regmask = (u_int32_t *) (&irq_rctx->tx.data[0] + sizeof(*opcdh)); +			opcdh = (struct openpcd_hdr *) irq_rctx->data; +			regmask = (u_int32_t *) (irq_rctx->data + sizeof(*opcdh));  			opcdh->cmd = OPENPCD_CMD_PIO_IRQ;  			opcdh->reg = 0x00;  			opcdh->flags = 0x00;  			opcdh->val = 0x00; -			irq_rctx->tx.tot_len = sizeof(*opcdh) + sizeof(u_int32_t); +			irq_rctx->tot_len = sizeof(*opcdh) + sizeof(u_int32_t);  			req_ctx_set_state(irq_rctx, RCTX_STATE_UDP_EP3_PENDING);  		}  	} @@ -116,8 +116,7 @@ void pio_irq_unregister(u_int32_t pio)  static int pio_irq_usb_in(struct req_ctx *rctx)  { -	struct openpcd_hdr *poh = (struct openpcd_hdr *) &rctx->rx.data[0]; -	struct openpcd_hdr *pih = (struct openpcd_hdr *) &rctx->tx.data[0]; +	struct openpcd_hdr *poh = (struct openpcd_hdr *) rctx->data;  	switch (poh->cmd) {  	case OPENPCD_CMD_PIO_IRQ: diff --git a/firmware/src/os/pwm.c b/firmware/src/os/pwm.c index 5c52ee6..285f4e7 100644 --- a/firmware/src/os/pwm.c +++ b/firmware/src/os/pwm.c @@ -119,8 +119,7 @@ void pwm_duty_set_percent(int channel, u_int16_t duty)  static int pwm_usb_in(struct req_ctx *rctx)  { -	struct openpcd_hdr *poh = (struct openpcd_hdr *) &rctx->rx.data[0]; -	/* struct openpcd_hdr *pih = (struct openpcd_hdr *) &rctx->tx.data[0]; */ +	struct openpcd_hdr *poh = (struct openpcd_hdr *) rctx->data;  	u_int32_t *freq;  	switch (poh->cmd) { @@ -137,7 +136,7 @@ static int pwm_usb_in(struct req_ctx *rctx)  		goto respond;  		break;  	case OPENPCD_CMD_PWM_FREQ_SET: -		if (rctx->rx.tot_len < sizeof(*poh)+4) +		if (rctx->tot_len < sizeof(*poh)+4)  			break;  		freq = (unsigned char *) poh + sizeof(*poh);  		pwm_freq_set(0, *freq); @@ -153,7 +152,7 @@ static int pwm_usb_in(struct req_ctx *rctx)  	return 0;  respond:  	req_ctx_set_state(rctx, RCTX_STATE_UDP_EP2_PENDING); -	udp_refill_ep(2, rctx); +	udp_refill_ep(2);  	return 1;  } diff --git a/firmware/src/os/req_ctx.c b/firmware/src/os/req_ctx.c index d118aca..fef7258 100644 --- a/firmware/src/os/req_ctx.c +++ b/firmware/src/os/req_ctx.c @@ -28,14 +28,32 @@  /* FIXME: locking, FIFO order processing */ +#define RCTX_SIZE_LARGE	2048 +#define RCTX_SIZE_SMALL	64 + +#define NUM_RCTX_SMALL 8 +#define NUM_RCTX_LARGE 3 + +#define NUM_REQ_CTX	(NUM_RCTX_SMALL+NUM_RCTX_LARGE) + +static u_int8_t rctx_data[NUM_RCTX_SMALL][RCTX_SIZE_SMALL]; +static u_int8_t rctx_data_large[NUM_RCTX_LARGE][RCTX_SIZE_LARGE]; +  static struct req_ctx req_ctx[NUM_REQ_CTX]; -struct req_ctx *req_ctx_find_get(unsigned long old_state, unsigned long new_state) +struct req_ctx *req_ctx_find_get(int large, +				 unsigned long old_state,  +				 unsigned long new_state)  {  	unsigned long flags;  	u_int8_t i; +	 +	if (large) +		i = NUM_RCTX_SMALL; +	else +		i = 0; -	for (i = 0; i < NUM_REQ_CTX; i++) { +	for (1; i < NUM_REQ_CTX; i++) {  		local_irq_save(flags);  		if (req_ctx[i].state == old_state) {  			req_ctx[i].state = new_state; @@ -67,3 +85,18 @@ void req_ctx_put(struct req_ctx *ctx)  {  	req_ctx_set_state(ctx, RCTX_STATE_FREE);  } + +void req_ctx_init(void) +{ +	int i; + +	for (i = 0; i < NUM_RCTX_SMALL; i++) { +		req_ctx[i].size = RCTX_SIZE_SMALL; +		req_ctx[i].data = rctx_data[i]; +	} + +	for (i = 0; i < NUM_RCTX_LARGE; i++) { +		req_ctx[i].size = RCTX_SIZE_LARGE; +		req_ctx[NUM_RCTX_SMALL+i].data = rctx_data_large[i]; +	} +} diff --git a/firmware/src/os/req_ctx.h b/firmware/src/os/req_ctx.h index 82a133f..b68fb66 100644 --- a/firmware/src/os/req_ctx.h +++ b/firmware/src/os/req_ctx.h @@ -9,18 +9,11 @@  #include <sys/types.h> -struct req_buf { -	u_int16_t hdr_len; -	u_int16_t tot_len; -	u_int8_t data[64]; -}; -  struct req_ctx { -	u_int16_t seq;		/* request sequence number */ -	u_int16_t flags;  	volatile u_int32_t state; -	struct req_buf rx; -	struct req_buf tx; +	u_int16_t size; +	u_int16_t tot_len; +	u_int8_t *data;  };  #define RCTX_STATE_FREE			0x00 @@ -39,8 +32,7 @@ struct req_ctx {  #define RCTX_STATE_PIOIRQ_BUSY		0x80 -#define NUM_REQ_CTX	8 -extern struct req_ctx *req_ctx_find_get(unsigned long old_state, unsigned long new_state); +extern struct req_ctx *req_ctx_find_get(int large, unsigned long old_state, unsigned long new_state);  extern struct req_ctx *req_ctx_find_busy(void);  extern void req_ctx_set_state(struct req_ctx *ctx, unsigned long new_state);  extern void req_ctx_put(struct req_ctx *ctx); diff --git a/firmware/src/os/usb_benchmark.c b/firmware/src/os/usb_benchmark.c index 1f890bf..bfc6b37 100644 --- a/firmware/src/os/usb_benchmark.c +++ b/firmware/src/os/usb_benchmark.c @@ -33,6 +33,8 @@ static void usbtest_tx_transfer(unsigned int num_pkts)  {  	unsigned int i; +#if 0 +#warning please reimplement refill userspecified rctx   	for (i = 0; i < num_pkts; i++) {  		/* send 16 packets of 64byte */  		while (udp_refill_ep(2, &dummy_rctx) < 0)  @@ -41,11 +43,12 @@ static void usbtest_tx_transfer(unsigned int num_pkts)  	/* send one packet of 0 byte */  	while (udp_refill_ep(2, &empty_rctx) < 0)   		; +#endif  }  static int usbtest_rx(struct req_ctx *rctx)  { -	struct openpcd_hdr *poh = (struct openpcd_hdr *) &rctx->rx.data[0]; +	struct openpcd_hdr *poh = (struct openpcd_hdr *) rctx->data;  	int i;  	switch (poh->cmd) { @@ -67,10 +70,10 @@ static int usbtest_rx(struct req_ctx *rctx)  void usbtest_init(void)  { -	dummy_rctx.tx.tot_len = 64; -	memset(dummy_rctx.tx.data, 0x23, 64); +	dummy_rctx.tot_len = 64; +	memset(dummy_rctx.data, 0x23, 64); -	empty_rctx.tx.tot_len = 0; +	empty_rctx.tot_len = 0;  	usb_hdlr_register(&usbtest_rx, OPENPCD_CMD_CLS_USBTEST);  } diff --git a/firmware/src/os/usb_handler.c b/firmware/src/os/usb_handler.c index 6c45e18..c3d4cfa 100644 --- a/firmware/src/os/usb_handler.c +++ b/firmware/src/os/usb_handler.c @@ -46,23 +46,33 @@ void usb_hdlr_unregister(u_int8_t class)  static int usb_in(struct req_ctx *rctx)  { -	struct openpcd_hdr *poh = (struct openpcd_hdr *) &rctx->rx.data[0]; -	struct openpcd_hdr *pih = (struct openpcd_hdr *) &rctx->tx.data[0]; +	struct openpcd_hdr *poh = (struct openpcd_hdr *) rctx->data;  	usb_cmd_fn *hdlr; +	int ret;  	DEBUGP("usb_in(cls=%d) ", OPENPCD_CMD_CLS(poh->cmd)); -	if (rctx->rx.tot_len < sizeof(*poh)) +	if (rctx->tot_len < sizeof(*poh))  		return -EINVAL; -	memcpy(pih, poh, sizeof(*poh)); -	rctx->tx.tot_len = sizeof(*poh); -  	hdlr = cmd_hdlrs[OPENPCD_CMD_CLS(poh->cmd)]; -	if (hdlr)  -		return (hdlr)(rctx); -	else -		DEBUGPCR("no handler for this class\n"); +	if (!hdlr) { +		DEBUGPCR("no handler for this class "); +		ret = USB_ERR(USB_ERR_CMD_UNKNOWN); +	} else +		ret = (hdlr)(rctx); +	 +	if (ret & USB_RET_ERR) { +		poh->val = ret & 0xff; +		poh->flags = OPENPCD_FLAG_ERROR; +	} +	if (ret & USB_RET_RESPOND) {  +		req_ctx_set_state(rctx, RCTX_STATE_UDP_EP2_PENDING); +		udp_refill_ep(2); +	} + +	DEBUGPCR(""); +	return (ret & USB_RET_ERR) ? 1 : 0;  }  /* Process all pending request contexts that want to Tx on either @@ -71,17 +81,17 @@ void usb_out_process(void)  {  	struct req_ctx *rctx; -	while (rctx = req_ctx_find_get(RCTX_STATE_UDP_EP3_PENDING, +	while (rctx = req_ctx_find_get(0, RCTX_STATE_UDP_EP3_PENDING,  				       RCTX_STATE_UDP_EP3_BUSY)) {  		DEBUGPCRF("EP3_BUSY for ctx %u", req_ctx_num(rctx)); -		if (udp_refill_ep(3, rctx) < 0) +		if (udp_refill_ep(3) < 0)  			req_ctx_set_state(rctx, RCTX_STATE_UDP_EP3_PENDING);  	} -	while (rctx = req_ctx_find_get(RCTX_STATE_UDP_EP2_PENDING, +	while (rctx = req_ctx_find_get(0, RCTX_STATE_UDP_EP2_PENDING,  				       RCTX_STATE_UDP_EP2_BUSY)) {  		DEBUGPCRF("EP2_BUSY for ctx %u", req_ctx_num(rctx)); -		if (udp_refill_ep(2, rctx) < 0) +		if (udp_refill_ep(2) < 0)  			req_ctx_set_state(rctx, RCTX_STATE_UDP_EP2_PENDING);  	}  } @@ -92,10 +102,10 @@ void usb_in_process(void)  {  	struct req_ctx *rctx; -	while (rctx = req_ctx_find_get(RCTX_STATE_UDP_RCV_DONE, +	while (rctx = req_ctx_find_get(0, RCTX_STATE_UDP_RCV_DONE,  				       RCTX_STATE_MAIN_PROCESSING)) {  	     	DEBUGPCRF("found used ctx %u: len=%u",  -			req_ctx_num(rctx), rctx->rx.tot_len); +			req_ctx_num(rctx), rctx->tot_len);  		usb_in(rctx);  	}  	udp_unthrottle(); diff --git a/firmware/src/os/usb_handler.h b/firmware/src/os/usb_handler.h index 3efcc1f..9d5ad48 100644 --- a/firmware/src/os/usb_handler.h +++ b/firmware/src/os/usb_handler.h @@ -6,6 +6,16 @@  #define MAX_PAYLOAD_LEN	(64 - sizeof(struct openpcd_hdr)) +#define USB_RET_RESPOND		(1 << 8) +#define USB_RET_ERR		(2 << 8) +#define USB_ERR(x)	(USB_RET_RESPOND|USB_RET_ERR|(x & 0xff)) + +enum usbapi_err { +	USB_ERR_NONE, +	USB_ERR_CMD_UNKNOWN, +	USB_ERR_CMD_NOT_IMPL, +}; +  typedef int usb_cmd_fn(struct req_ctx *rctx);  extern int usb_hdlr_register(usb_cmd_fn *hdlr, u_int8_t class); diff --git a/firmware/src/os/usbcmd_generic.c b/firmware/src/os/usbcmd_generic.c new file mode 100644 index 0000000..9dec14e --- /dev/null +++ b/firmware/src/os/usbcmd_generic.c @@ -0,0 +1,49 @@ +/* Some generel USB API commands, common between OpenPCD and OpenPICC + * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de> + */ + +#include <string.h> +#include <sys/types.h> +#include <openpcd.h> +#include <os/req_ctx.h> +#include <os/usb_handler.h> +#include <os/led.h> +#include <os/dbgu.h> +#include <os/main.h> + +static int gen_usb_rx(struct req_ctx *rctx) +{ +	struct openpcd_hdr *poh = (struct openpcd_hdr *) rctx->data; +	struct openpcd_compile_version *ver =  +			(struct openpcd_compile_version *) poh->data; +	int ret = 1; + +	rctx->tot_len = sizeof(*poh); + +	switch (poh->cmd) { +	case OPENPCD_CMD_GET_VERSION: +		DEBUGP("GET_VERSION "); +		memcpy(ver, &opcd_version, sizeof(*ver)); +		rctx->tot_len += sizeof(*ver); +		poh->flags |= OPENPCD_FLAG_RESPOND; +		break; +	case OPENPCD_CMD_SET_LED: +		DEBUGP("SET LED(%u,%u) ", poh->reg, poh->val); +		led_switch(poh->reg, poh->val); +		break; +	default: +		DEBUGP("UNKNOWN "); +		return USB_ERR(USB_ERR_CMD_UNKNOWN); +		break; +	} + +	if (poh->flags & OPENPCD_FLAG_RESPOND) +		return USB_RET_RESPOND; +	return 0; +} + +void usbcmd_gen_init(void) +{ +	usb_hdlr_register(&gen_usb_rx, OPENPCD_CMD_CLS_GENERIC); +} + diff --git a/firmware/src/os/usbcmd_generic.h b/firmware/src/os/usbcmd_generic.h new file mode 100644 index 0000000..0a7b8b7 --- /dev/null +++ b/firmware/src/os/usbcmd_generic.h @@ -0,0 +1,4 @@ +#ifndef _USBAPI_GENERIC_H +#define _USBAPI_GENERIC_H +extern void usbcmd_gen_init(void); +#endif | 
