diff usb.c @ 31:4e417d84365e

- Rename some more functions to be consistent. - Add some delays when talking to the 'D12 - probably not needed. - Add some comments at the top of each function. - Log endpoint errors. - Whitespace changes. - Remove exact_Bytes crap. - Many other changes I have made in an attempt to get it to work consistently (but no luck yet).
author darius
date Mon, 10 Apr 2006 17:27:48 +0930
parents 350e8655cbb7
children fed32b382de2
line wrap: on
line diff
--- a/usb.c	Mon Apr 10 17:23:51 2006 +0930
+++ b/usb.c	Mon Apr 10 17:27:48 2006 +0930
@@ -6,13 +6,19 @@
 #include <util/delay.h>
 
 #include "usb.h"
+#include "1wire.h"
 
-#define EP0_SIZE 16
+/* Maximum FIFO sizes for each endpoint */
+#define EP0_FIFO_SZ 16
+#define EP1_FIFO_SZ 16
+#define EP2_FIFO_SZ 64
 
+/* PDIUSBD12 mode */
 #define D12_MODE_0	0x14	/* Endpoint config = 0, SoftConnect = 1, IRQ Mode = 1,
 				 * Clock running = 0, No Lazy Clock = 0 
 				 */
 #define D12_MODE_1	0x02	/* SOF mode = 0, Set-to-one = 0, Clock div = 2 (16Mhz) */
+
 /* Debugging stuff */
 void		uart_putsP(const char *addr);
 void		uart_puts(const char *addr);
@@ -20,21 +26,30 @@
 void		uart_puts_dec(uint8_t a, uint8_t l);
 void		uart_puts_hex(uint8_t a);
 
+void		parsebuf(uint8_t *buffer, uint8_t ep);
+
 /* USB administrivia */
 uint8_t deviceaddress;
 uint8_t deviceconfigured;
 
-/* End point buffer points and such */
-const uint8_t *pSendBuffer;
-uint8_t BytesToSend;
-static uint8_t send_Bytes;
-static uint8_t exact_Bytes;
+/* Endpoint buffers and such */
+/* EP0 in */
+static const uint8_t *sendbuffer0;
+static uint8_t sendbytes0;
+
+/* EP0 out */
+/* This is unbuffered as we don't handle packets > EP0_FIFO_SZ */
 
-static const uint8_t *pSendBuffer2;
-static uint8_t BytesToSend2;
+/* EP1 */
+/* Unbuffered as yet */
+static uint8_t packet1[270];
+static uint16_t packetlen1;
 
-/* Data packet buffer */
-static uint8_t send_packet2;
+/* EP2 in */
+static const uint8_t *sendbuffer2;
+static uint8_t sendbytes2;
+
+/* EP2 out */
 static uint8_t packet2[270];
 static uint16_t packetlen2;
 
@@ -49,8 +64,8 @@
     0,					/* bDeviceClass */
     0,					/* bDeviceSubclass */
     0,					/* bDeviceProtocol */
-    EP0_SIZE,				/* bMaxPacketSize in Bytes */
-    0x4753,				/* idVendor (inofficial GS) */
+    EP0_FIFO_SZ,			/* bMaxPacketSize in Bytes */
+    0x4753,				/* idVendor (unofficial GS) */
     0x0001,				/* idProduct */
     0x0100,				/* bcdDevice */
     1,					/* iManufacturer String Index */
@@ -76,7 +91,7 @@
 	0,					/* bInterface Number */
 	0,					/* bAlternateSetting */
 	2,					/* bNumEndpoints */
-	0xFF,					/* bInterfaceClass (Vendor specific) */
+	0xff,					/* bInterfaceClass (Vendor specific) */
 	0x02,					/* bInterfaceSubClass */
 	0x00,					/* bInterfaceProtocol */
 	0					/* iInterface String Index */
@@ -103,7 +118,7 @@
 	1,					/* bInterface Number */
 	0,					/* bAlternateSetting */
 	2,					/* bNumEndpoints */
-	0xFF,					/* bInterfaceClass (Vendor specific) */
+	0xff,					/* bInterfaceClass (Vendor specific) */
 	0x02,					/* bInterfaceSubClass */
 	0x00,					/* bInterfaceProtocol */
 	0					/* iInterface String Index */
@@ -167,10 +182,17 @@
  * A0       <=      PB3 (0 = data, 1 = cmd)
  * SUSPEND  <=>     PB4
  */
+
+/*******************************************************************************
+** d12_get_data
+**
+** Read a data byte
+*/
 uint8_t
 d12_get_data(void) {
     uint8_t data;
 
+    _delay_us(1);
     PORTB &= ~_BV(PB3);	/* Data phase */
     DDRA = 0x00;	/* Set to input */
     PORTB &= ~_BV(PB1);	/* Pull RD_N low */
@@ -179,11 +201,18 @@
     PORTB &= ~_BV(PB1);
     data = PINA;	/* Read the data */
     PORTB |= _BV(PB1);	/* Pull RD_N high */
+
     return(data);
 }
 
+/*******************************************************************************
+** d12_set_data
+**
+** Write a data byte
+*/
 void
-set_d12_data(uint8_t data) {
+d12_set_data(uint8_t data) {
+    _delay_us(1);
     PORTB &= ~_BV(PB3);	/* Data phase */
     DDRA = 0xff;	/* Set to output */
     PORTA = data;	/* Put the data on the bus */
@@ -198,8 +227,14 @@
     DDRA = 0x00;	/* Back to input */
 }
 
+/*******************************************************************************
+** d12_set_cmd
+**
+** Start a command
+*/
 void
-set_d12_cmd(uint8_t cmd) {
+d12_set_cmd(uint8_t cmd) {
+    _delay_us(1);
     PORTB |= _BV(PB3);	/* Command phase */
     DDRA = 0xff;	/* Set to output */
     PORTA = cmd;	/* Put the data on the bus */
@@ -214,23 +249,33 @@
     DDRA = 0x00;	/* Back to input */
 }
 
+/*******************************************************************************
+** d12_write_cmd
+**
+** Issue a command with associated data
+*/
 void 
 d12_write_cmd(uint8_t command, const uint8_t *buffer, uint8_t count) {
     uint8_t i;
 
-    set_d12_cmd(command);
+    d12_set_cmd(command);
     if (count) {
 	for (i = 0; i < count; i++) {
-	    set_d12_data(buffer[i]);
+	    d12_set_data(buffer[i]);
 	}
     }
 }
 
+/*******************************************************************************
+** d12_read_cmd
+**
+** Issue a command and read back the data
+*/
 void 
 d12_read_cmd(uint8_t command, uint8_t *buffer, uint8_t count) {
     uint8_t i;
 
-    set_d12_cmd(command);
+    d12_set_cmd(command);
     if (count) {
 	for (i = 0; i < count; i++) {
 	    buffer[i] = d12_get_data();
@@ -238,7 +283,11 @@
     }
 }
 
-/* Set up the PDIUSBD12 */
+/*******************************************************************************
+** usb_init
+**
+** Configure the PDIUSBD12
+*/
 void
 usb_init(void) {
     uint8_t	buffer[2];
@@ -270,7 +319,11 @@
     d12_write_cmd(D12_SET_DMA, buffer, 1);
 }
 
-/* Process an interrupt */
+/*******************************************************************************
+** usb_intr
+**
+** Process any pending interrupts
+*/
 void
 usb_intr(void) {
     uint8_t	irq[2];
@@ -294,37 +347,92 @@
 	
     if (irq[0] & D12_INT_EP0_IN) {
 	d12_read_cmd(D12_READ_LAST_TRANSACTION + D12_ENDPOINT_EP0_IN, buffer, 1);
+	if ((buffer[0] & D12_LAST_TRAN_ERRMSK) != 0) {
+	    uart_putsP(PSTR("EP0_IN error "));
+	    uart_puts_hex((buffer[0] & D12_LAST_TRAN_ERRMSK) >> 1);
+	    uart_putsP(PSTR("\n\r"));
+	}
 
 	/* Handle any outgoing data for EP0 */
-	d12_write_buffer_ep0();
+	d12_send_data_ep0();
     }
     
     /* Handle configuration and misc stuff */
     if (irq[0] & D12_INT_EP0_OUT) {
-	d12_ep0_irq();
+	d12_read_cmd(D12_READ_LAST_TRANSACTION + D12_ENDPOINT_EP0_OUT, buffer, 1);
+	if ((buffer[0] & D12_LAST_TRAN_ERRMSK) != 0) {
+	    uart_putsP(PSTR("EP0_OUT error "));
+	    uart_puts_hex((buffer[0] & D12_LAST_TRAN_ERRMSK) >> 1);
+	    uart_putsP(PSTR("\n\r"));
+	}
+
+	if (buffer[0] & D12_LAST_TRAN_SETUP)
+	    d12_handle_setup();
+	else {
+	    /* Data packet */
+	}
     }
     
     /* EPx_IN is when the host has had a packet of data and is expecting more */
     if (irq[0] & D12_INT_EP1_IN) {
-	/* XXX: Not yet implemented */
+	d12_read_cmd(D12_READ_LAST_TRANSACTION + D12_ENDPOINT_EP1_IN, buffer, 1);
+	if ((buffer[0] & D12_LAST_TRAN_ERRMSK) != 0) {
+	    uart_putsP(PSTR("EP1_IN error "));
+	    uart_puts_hex((buffer[0] & D12_LAST_TRAN_ERRMSK) >> 1);
+	    uart_putsP(PSTR("\n\r"));
+	}
+	    
+	/* Select endpoint */
+	d12_read_cmd(D12_ENDPOINT_EP1_IN, buffer, 1);
+
+	if (buffer[0] & 0x01)
+	    uart_putsP(PSTR("EP1_IN is full\n\r"));
+	
+	if (buffer[0] & 0x02)
+	    uart_putsP(PSTR("EP1_IN is stalled\n\r"));
+
+	d12_write_endpt(D12_ENDPOINT_EP1_IN, NULL, 0);
     }
     
     /* EPx_OUT is when we have gotten a packet from the host */
     if (irq[0] & D12_INT_EP1_OUT) {
-	/* XXX: Not yet implemented */
+	d12_read_cmd(D12_READ_LAST_TRANSACTION + D12_ENDPOINT_EP1_OUT, buffer, 1);
+	if ((buffer[0] & D12_LAST_TRAN_ERRMSK) != 0) {
+	    uart_putsP(PSTR("EP1_OUT error "));
+	    uart_puts_hex((buffer[0] & D12_LAST_TRAN_ERRMSK) >> 1);
+	    uart_putsP(PSTR("\n\r"));
+	}
+
+	d12_receive_data_ep1();
     }
 
-    if (irq[0] & D12_INT_EP2_IN) {
+    if (irq[0] & D12_INT_EP2_IN) {	
 	d12_read_cmd(D12_READ_LAST_TRANSACTION + D12_ENDPOINT_EP2_IN, buffer, 1);
+	if ((buffer[0] & D12_LAST_TRAN_ERRMSK) != 0) {
+	    uart_putsP(PSTR("EP2_IN error "));
+	    uart_puts_hex((buffer[0] & D12_LAST_TRAN_ERRMSK) >> 1);
+	    uart_putsP(PSTR("\n\r"));
+	}
+
 	d12_send_data_ep2();
     }
     
     if (irq[0] & D12_INT_EP2_OUT) {
 	d12_read_cmd(D12_READ_LAST_TRANSACTION + D12_ENDPOINT_EP2_OUT, buffer, 1);
+	if ((buffer[0] & D12_LAST_TRAN_ERRMSK) != 0) {
+	    uart_putsP(PSTR("EP2_OUT error "));
+	    uart_puts_hex((buffer[0] & D12_LAST_TRAN_ERRMSK) >> 1);
+	    uart_putsP(PSTR("\n\r"));
+	}
 	d12_receive_data_ep2();
     }
 }
 
+/*******************************************************************************
+** usb_gendata
+**
+** Fake up some data for testing purposes
+*/
 void
 usb_gendata(void) {
     packet2[0] = 'a';
@@ -332,358 +440,386 @@
     packet2[2] = 'c';
     packet2[3] = '\n';
     packet2[4] = '\r';
-    BytesToSend2 = 5;
-    pSendBuffer2 = (uint8_t *)&packet2[0];
-    send_packet2 = 1;
+    sendbytes2 = 5;
+    sendbuffer2 = (uint8_t *)&packet2[0];
 
     /* Kick off the data transfer */
     d12_send_data_ep2();
 }
 
+/*******************************************************************************
+** d12_handle_setup
+**
+** Handle setup packet stuff for endpoint 0
+*/
 void
-d12_ep0_irq(void) {
+d12_handle_setup(void) {
     uint8_t		buffer[2];
     USB_SETUP_REQUEST	setuppkt;
 
-    d12_read_cmd(D12_READ_LAST_TRANSACTION + D12_ENDPOINT_EP0_OUT, buffer, 1);
-
-    if (buffer[0] & D12_LAST_TRAN_SETUP) {
-	/* Read the setup packet */
-	d12_read_endpt(D12_ENDPOINT_EP0_OUT, (uint8_t *)&setuppkt);
+    /* Read the setup packet */
+    d12_read_endpt(D12_ENDPOINT_EP0_OUT, (uint8_t *)&setuppkt);
+    
+    /* Ack the packet to EP0_OUT */
+    d12_write_cmd(D12_ENDPOINT_EP0_OUT, NULL, 0);
+    d12_write_cmd(D12_ACK_SETUP, NULL, 0);
+    d12_write_cmd(D12_CLEAR_BUFFER, NULL, 0);
 	
-	/* Ack the packet to EP0_OUT */
-	d12_write_cmd(D12_ENDPOINT_EP0_OUT, NULL, 0);
-	d12_write_cmd(D12_ACK_SETUP, NULL, 0);
-	d12_write_cmd(D12_CLEAR_BUFFER, NULL, 0);
-	
-	/* Ack the packet to EP0_IN */
-	d12_write_cmd(D12_ENDPOINT_EP0_IN, NULL, 0);
-	d12_write_cmd(D12_ACK_SETUP, NULL, 0);
-	
-	/* It's a new xfer, so forget about any old one */
-	send_Bytes = 0;
+    /* Ack the packet to EP0_IN */
+    d12_write_cmd(D12_ENDPOINT_EP0_IN, NULL, 0);
+    d12_write_cmd(D12_ACK_SETUP, NULL, 0);
 	
-	/* Parse request type */
-	switch (setuppkt.bmRequestType & 0x7f) {
-	    case STANDARD_DEVICE_REQUEST:
-		switch (setuppkt.bRequest) {
-		    case GET_STATUS:
-			/* Get status request should return remote
-			 * wakeup and self powered status
-			 */
-			buffer[0] = 0x01;
-			buffer[1] = 0x00;
-			d12_write_endpt(D12_ENDPOINT_EP0_IN, buffer, 2);
-			break;
-		    case CLEAR_FEATURE:
-		    case SET_FEATURE:
-			/* We don't support DEVICE_REMOTE_WAKEUP or
-			 * TEST_MODE
-			 */
-			d12_stallctrlendpt();
-			break;
+    /* Parse request type */
+    switch (setuppkt.bmRequestType & 0x7f) {
+	case STANDARD_DEVICE_REQUEST:
+	    switch (setuppkt.bRequest) {
+		case GET_STATUS:
+		    /* Get status request should return remote
+		     * wakeup and self powered status
+		     */
+		    buffer[0] = 0x01;
+		    buffer[1] = 0x00;
+		    d12_write_endpt(D12_ENDPOINT_EP0_IN, buffer, 2);
+		    break;
+		case CLEAR_FEATURE:
+		case SET_FEATURE:
+		    /* We don't support DEVICE_REMOTE_WAKEUP or
+		     * TEST_MODE
+		     */
+
+		    d12_stallendpt(D12_ENDPOINT_EP0_IN);
+		    d12_stallendpt(D12_ENDPOINT_EP0_OUT);
+		    break;
 			
-		    case SET_ADDRESS:
-			deviceaddress = setuppkt.wValue | 0x80;
-			d12_write_cmd(D12_SET_ADDRESS_ENABLE, &deviceaddress, 1);
-			d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0);
-			break;
+		case SET_ADDRESS:
+		    deviceaddress = setuppkt.wValue | 0x80;
+		    d12_write_cmd(D12_SET_ADDRESS_ENABLE, &deviceaddress, 1);
+		    d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0);
+		    break;
 
-		    case GET_DESCRIPTOR:	
-			d12_getdescriptor(&setuppkt);
-			break;
+		case GET_DESCRIPTOR:	
+		    d12_getdescriptor(&setuppkt);
+		    break;
 			
-		    case GET_CONFIGURATION:
-			d12_write_endpt(D12_ENDPOINT_EP0_IN, &deviceconfigured, 1);
-			break;
+		case GET_CONFIGURATION:
+		    d12_write_endpt(D12_ENDPOINT_EP0_IN, &deviceconfigured, 1);
+		    break;
 			
-		    case SET_CONFIGURATION:
-			deviceconfigured = setuppkt.wValue & 0xff;
-			d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0);
-			break;
+		case SET_CONFIGURATION:
+		    deviceconfigured = setuppkt.wValue & 0xff;
+		    d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0);
+		    break;
 			
 
-		    case SET_DESCRIPTOR:
-		    default:
-			/* Unsupported, stall */
-			d12_stallctrlendpt();
-			break;
-		}
-		break;
-		
-	    case STANDARD_INTERFACE_REQUEST:
-		switch (setuppkt.bRequest) {
-		    case GET_STATUS:
-			/* Should return 0, 0 (reserved) */
-			buffer[0] = 0x00;
-			buffer[1] = 0x00;
-			d12_write_endpt(D12_ENDPOINT_EP0_IN, buffer, 2);
-			break;
-			
-		    case SET_INTERFACE:
-			if (setuppkt.wIndex == 0 && setuppkt.wValue == 0)
-			    d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0);
-			else
-			    d12_stallctrlendpt();
-			break;
-
-		    case GET_INTERFACE:
-			/* Can only handle interface 0 ... */
-			if (setuppkt.wIndex == 0) {
-			    buffer[0] = 0;
-			    d12_write_endpt(D12_ENDPOINT_EP0_IN, buffer, 1);
-			    break;
-			}
-			/* .. otherwise fall through to error */
-
-		    case CLEAR_FEATURE:
-		    case SET_FEATURE:
-		    default:
-			d12_stallctrlendpt();
-			break;
-		}
-		break;
+		case SET_DESCRIPTOR:
+		default:
+		    /* Unsupported, stall */
+		    d12_stallendpt(D12_ENDPOINT_EP0_IN);
+		    d12_stallendpt(D12_ENDPOINT_EP0_OUT);
+		    break;
+	    }
+	    break;
 		
-	    case STANDARD_ENDPOINT_REQUEST:
-		switch (setuppkt.bRequest) {
-		    case CLEAR_FEATURE:
-		    case SET_FEATURE:
-			/* Halt(stall) is required to be implemented on
-			 * interrupt and bulk endpoints.
-			 */
-			if (setuppkt.wValue == ENDPOINT_HALT) {
-			    if (setuppkt.bRequest == CLEAR_FEATURE)
-				buffer[0] = 0x00;
-			    else
-				buffer[0] = 0x01;
-			    switch (setuppkt.wIndex & 0xFF) {
-				case 0x01:
-				    d12_write_cmd(D12_SET_ENDPOINT_STATUS + \
-						  D12_ENDPOINT_EP1_OUT, buffer, 1);
-				    break;
-				case 0x81:
-				    d12_write_cmd(D12_SET_ENDPOINT_STATUS + \
-						  D12_ENDPOINT_EP1_IN, buffer, 1);
-				    break;
-				case 0x02:
-				    d12_write_cmd(D12_SET_ENDPOINT_STATUS + \
-						  D12_ENDPOINT_EP2_OUT, buffer, 1);
-				    break;
-				case 0x82:
-				    d12_write_cmd(D12_SET_ENDPOINT_STATUS + \
-						  D12_ENDPOINT_EP2_IN, buffer, 1);
-				    break;
-				default:	/* Invalid Endpoint -
-						 * RequestError */
-				    d12_stallctrlendpt();
-				    break;
-			    }
-			    d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0);
-			} else {
-			    /*
-			     * No other Features for Endpoint -
-			     * Request Error
-			     */
-			    d12_stallctrlendpt();
-			}
+	case STANDARD_INTERFACE_REQUEST:
+	    switch (setuppkt.bRequest) {
+		case GET_STATUS:
+		    /* Should return 0, 0 (reserved) */
+		    buffer[0] = 0x00;
+		    buffer[1] = 0x00;
+		    d12_write_endpt(D12_ENDPOINT_EP0_IN, buffer, 2);
+		    break;
+			
+		case SET_INTERFACE:
+		    if (setuppkt.wIndex == 0 && setuppkt.wValue == 0)
+			d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0);
+		    else {			    
+			d12_stallendpt(D12_ENDPOINT_EP0_IN);
+			d12_stallendpt(D12_ENDPOINT_EP0_OUT);
+		    }
+			
+		    break;
+
+		case GET_INTERFACE:
+		    /* Can only handle interface 0 ... */
+		    if (setuppkt.wIndex == 0) {
+			buffer[0] = 0;
+			d12_write_endpt(D12_ENDPOINT_EP0_IN, buffer, 1);
 			break;
+		    }
+		    /* .. otherwise fall through to error */
 
-		    case GET_STATUS:
-			/*
-			 * Get Status Request to Endpoint should
-			 * return Halt Status in D0 for Interrupt and Bulk
-			 */
+		case CLEAR_FEATURE:
+		case SET_FEATURE:
+		default:
+		    d12_stallendpt(D12_ENDPOINT_EP0_IN);
+		    d12_stallendpt(D12_ENDPOINT_EP0_OUT);
+		    break;
+	    }
+	    break;
+		
+	case STANDARD_ENDPOINT_REQUEST:
+	    switch (setuppkt.bRequest) {
+		case CLEAR_FEATURE:
+		case SET_FEATURE:
+		    /* Halt(stall) is required to be implemented on
+		     * interrupt and bulk endpoints.
+		     */
+		    if (setuppkt.wValue == ENDPOINT_HALT) {
+			if (setuppkt.bRequest == CLEAR_FEATURE)
+			    buffer[0] = 0x00;
+			else
+			    buffer[0] = 0x01;
 			switch (setuppkt.wIndex & 0xFF) {
 			    case 0x01:
-				d12_read_cmd(D12_READ_ENDPOINT_STATUS + \
-					       D12_ENDPOINT_EP1_OUT, buffer, 1);
+				d12_write_cmd(D12_SET_ENDPOINT_STATUS + \
+					      D12_ENDPOINT_EP1_OUT, buffer, 1);
 				break;
 			    case 0x81:
-				d12_read_cmd(D12_READ_ENDPOINT_STATUS + \
-					       D12_ENDPOINT_EP1_IN, buffer, 1);
+				d12_write_cmd(D12_SET_ENDPOINT_STATUS + \
+					      D12_ENDPOINT_EP1_IN, buffer, 1);
 				break;
 			    case 0x02:
-				d12_read_cmd(D12_READ_ENDPOINT_STATUS + \
-					       D12_ENDPOINT_EP2_OUT, buffer, 1);
+				d12_write_cmd(D12_SET_ENDPOINT_STATUS + \
+					      D12_ENDPOINT_EP2_OUT, buffer, 1);
 				break;
 			    case 0x82:
-				d12_read_cmd(D12_READ_ENDPOINT_STATUS + \
-					       D12_ENDPOINT_EP2_IN, buffer, 1);
+				d12_write_cmd(D12_SET_ENDPOINT_STATUS + \
+					      D12_ENDPOINT_EP2_IN, buffer, 1);
 				break;
 			    default:	/* Invalid Endpoint -
-					 * RequestError */
-				d12_stallctrlendpt();
+					 * RequestError */	
+				d12_stallendpt(D12_ENDPOINT_EP0_IN);
+				d12_stallendpt(D12_ENDPOINT_EP0_OUT);
 				break;
 			}
-			if (buffer[0] & 0x08)
-			    buffer[0] = 0x01;
-			else
-			    buffer[0] = 0x00;
-			buffer[1] = 0x00;
-			d12_write_endpt(D12_ENDPOINT_EP0_IN, buffer, 2);
-			break;
-
-		    default:
-			/* Unsupported - Request Error - Stall */
-			d12_stallctrlendpt();
-			break;
-		}
-		break;
-	    case VENDOR_DEVICE_REQUEST:
-	    case VENDOR_ENDPOINT_REQUEST:
-		switch (setuppkt.bRequest) {
-		    case VENDOR_RESET:
 			d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0);
-			_delay_us(1000);
-			/* disconnect from USB */
-			buffer[0] = D12_MODE_0 & 0xef;
-			buffer[1] = D12_MODE_1;
-			d12_write_cmd(D12_SET_MODE, buffer, 2);
-			_delay_us(1000);
-			cli();
-			reset();
-			/* NOT REACHED */
-			break;
-		    case VENDOR_UPDATE:
-			d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0);
-			_delay_us(1000);
-			/* disconnect from USB */
-			buffer[0] = D12_MODE_0 & 0xef;
-			buffer[1] = D12_MODE_1;
-			d12_write_cmd(D12_SET_MODE, buffer, 2);
-			_delay_us(1000);
-			cli();
-			bootloader();
-			/* NOT REACHED */
-			break;
-		    default:
-			d12_stallctrlendpt();
-			break;
-		}
-		break;
-	    case VENDOR_INTERFACE_REQUEST:
-		switch (setuppkt.bRequest) {
-		    default:
-			d12_stallctrlendpt();
-			break;
-		}
-		break;
-	    default:
-		d12_stallctrlendpt();
-		break;
-	}
-    } else {
-	/* This is a Data Packet */
-    }
-		
-}
-
-/* Reset the micro */
-static void
-reset(void) {
-    MCUCR = _BV(IVCE);
-    MCUCR = 0;
-    WDTCR = _BV(WDE);
-    for (;;)
-	;
-}
-
-void 
-d12_getdescriptor(USB_SETUP_REQUEST *setuppkt) {
-    switch ((setuppkt->wValue & 0xff00) >> 8) {
-	case TYPE_DEVICE_DESCRIPTOR:
-	    pSendBuffer = (const uint8_t *)&DeviceDescriptor;
-	    BytesToSend = DeviceDescriptor.bLength;
-	    send_Bytes = 1;
-	    if (BytesToSend >= setuppkt->wLength) {
-		BytesToSend = setuppkt->wLength;
-		exact_Bytes = 1;
-	    } else {
-		exact_Bytes = 0;
-	    }
-	    d12_write_buffer_ep0();
-	    break;
-
-	case TYPE_CONFIGURATION_DESCRIPTOR:
-	    pSendBuffer = (const uint8_t *)&ConfigurationDescriptor;
-	    BytesToSend = sizeof(ConfigurationDescriptor);
-	    send_Bytes = 1;
-	    if (BytesToSend >= setuppkt->wLength) {
-		BytesToSend = setuppkt->wLength;
-		exact_Bytes = 1;
-	    } else {
-		exact_Bytes = 0;
-	    }
-	    d12_write_buffer_ep0();
-	    break;
-
-	case TYPE_STRING_DESCRIPTOR:
-	    switch (setuppkt->wValue & 0xFF) {
-
-		case 0:
-		    pSendBuffer = (const uint8_t *)&LANGID_Descriptor;
-		    BytesToSend = LANGID_Descriptor.bLength;
+		    } else {
+			/*
+			 * No other Features for Endpoint -
+			 * Request Error
+			 */
+			d12_stallendpt(D12_ENDPOINT_EP0_IN);
+			d12_stallendpt(D12_ENDPOINT_EP0_OUT);
+		    }
 		    break;
 
-		case 1:
-		    pSendBuffer = (const uint8_t *)&Manufacturer_Descriptor;
-		    BytesToSend = Manufacturer_Descriptor.bLength;
-		    break;
-
-		case 2:
-		    pSendBuffer = (const uint8_t *)&Product_Descriptor;
-		    BytesToSend = Product_Descriptor.bLength;
-		    break;
-
-		case 3:
-		    pSendBuffer = (const uint8_t *)&Serial_Descriptor;
-		    BytesToSend = Serial_Descriptor.bLength;
+		case GET_STATUS:
+		    /*
+		     * Get Status Request to Endpoint should
+		     * return Halt Status in D0 for Interrupt and Bulk
+		     */
+		    switch (setuppkt.wIndex & 0xFF) {
+			case 0x01:
+			    d12_read_cmd(D12_READ_ENDPOINT_STATUS + \
+					 D12_ENDPOINT_EP1_OUT, buffer, 1);
+			    break;
+			case 0x81:
+			    d12_read_cmd(D12_READ_ENDPOINT_STATUS + \
+					 D12_ENDPOINT_EP1_IN, buffer, 1);
+			    break;
+			case 0x02:
+			    d12_read_cmd(D12_READ_ENDPOINT_STATUS + \
+					 D12_ENDPOINT_EP2_OUT, buffer, 1);
+			    break;
+			case 0x82:
+			    d12_read_cmd(D12_READ_ENDPOINT_STATUS + \
+					 D12_ENDPOINT_EP2_IN, buffer, 1);
+			    break;
+			default:	/* Invalid Endpoint -
+					 * RequestError */
+			    d12_stallendpt(D12_ENDPOINT_EP0_IN);
+			    d12_stallendpt(D12_ENDPOINT_EP0_OUT);
+			    break;
+		    }
+		    if (buffer[0] & 0x08)
+			buffer[0] = 0x01;
+		    else
+			buffer[0] = 0x00;
+		    buffer[1] = 0x00;
+		    d12_write_endpt(D12_ENDPOINT_EP0_IN, buffer, 2);
 		    break;
 
 		default:
-		    pSendBuffer = NULL;
-		    BytesToSend = 0;
+		    /* Unsupported - Request Error - Stall */
+		    d12_stallendpt(D12_ENDPOINT_EP0_IN);
+		    d12_stallendpt(D12_ENDPOINT_EP0_OUT);
+		    break;
 	    }
-	    send_Bytes = 1;
-	    if (BytesToSend >= setuppkt->wLength) {
-		BytesToSend = setuppkt->wLength;
-		exact_Bytes = 1;
-	    } else {
-		exact_Bytes = 0;
+	    break;
+	case VENDOR_DEVICE_REQUEST:
+	case VENDOR_ENDPOINT_REQUEST:
+	    switch (setuppkt.bRequest) {
+		case VENDOR_RESET:
+		    d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0);
+		    _delay_us(1000);
+		    /* disconnect from USB */
+		    buffer[0] = D12_MODE_0 & 0xef;
+		    buffer[1] = D12_MODE_1;
+		    d12_write_cmd(D12_SET_MODE, buffer, 2);
+		    _delay_us(1000);
+		    cli();
+		    reset();
+		    /* NOT REACHED */
+		    break;
+
+		case VENDOR_UPDATE:
+		    d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0);
+		    _delay_us(1000);
+		    /* disconnect from USB */
+		    buffer[0] = D12_MODE_0 & 0xef;
+		    buffer[1] = D12_MODE_1;
+		    d12_write_cmd(D12_SET_MODE, buffer, 2);
+		    _delay_us(1000);
+		    cli();
+		    bootloader();
+		    /* NOT REACHED */
+		    break;
+
+		default:
+		    d12_stallendpt(D12_ENDPOINT_EP0_IN);
+		    d12_stallendpt(D12_ENDPOINT_EP0_OUT);
+		    break;
 	    }
-	    d12_write_buffer_ep0();
+	    break;
+	case VENDOR_INTERFACE_REQUEST:
+	    switch (setuppkt.bRequest) {
+		default:
+		    d12_stallendpt(D12_ENDPOINT_EP0_IN);
+		    d12_stallendpt(D12_ENDPOINT_EP0_OUT);
+		    break;
+	    }
 	    break;
 	default:
-	    d12_stallctrlendpt();
+	    d12_stallendpt(D12_ENDPOINT_EP0_IN);
+	    d12_stallendpt(D12_ENDPOINT_EP0_OUT);
 	    break;
     }
 }
 
 
+/*******************************************************************************
+** reset
+**
+** Reset the micro by triggering the watchdog timer.
+**
+*/
+static void
+reset(void) {
+    uart_putsP(PSTR("Resetting!\n\r"));
+    _delay_us(1000);
+    
+    /* Disable the interrupts */
+    MCUCR = _BV(IVCE);
+    MCUCR = 0;
+
+    /* Enable watchdog, smallest prescaler */
+    WDTCR = _BV(WDE);
+
+    /* Wait for oblivion! */
+    for (;;)
+	;
+}
+
+/*******************************************************************************
+** d12_getdescriptor
+**
+** Handle returning the various descriptor to the host
+**
+** Note: that we need to truncate the request because the host first
+** requests the first 2 bytes to find out then size, then requests the
+** rest.
+*/
 void 
-d12_stallctrlendpt(void) {
-    uint8_t   Buffer[] = {0x01};
-    /*
-     * 9.2.7 RequestError - return STALL PID in response to next DATA
-     * Stage Transaction
-     */
-    d12_write_cmd(D12_SET_ENDPOINT_STATUS + D12_ENDPOINT_EP0_IN, Buffer, 1);
-    /* or in the status stage of the message. */
-    d12_write_cmd(D12_SET_ENDPOINT_STATUS + D12_ENDPOINT_EP0_OUT, Buffer, 1);
+d12_getdescriptor(USB_SETUP_REQUEST *setuppkt) {
+    switch ((setuppkt->wValue & 0xff00) >> 8) {
+	case TYPE_DEVICE_DESCRIPTOR:
+	    sendbuffer0 = (const uint8_t *)&DeviceDescriptor;
+	    sendbytes0 = DeviceDescriptor.bLength;
+	    if (sendbytes0 >= setuppkt->wLength)
+		sendbytes0 = setuppkt->wLength;
+
+	    d12_send_data_ep0();
+	    break;
+
+	case TYPE_CONFIGURATION_DESCRIPTOR:
+	    sendbuffer0 = (const uint8_t *)&ConfigurationDescriptor;
+	    sendbytes0 = sizeof(ConfigurationDescriptor);
+	    if (sendbytes0 >= setuppkt->wLength)
+		sendbytes0 = setuppkt->wLength;
+
+	    d12_send_data_ep0();
+	    break;
+
+	case TYPE_STRING_DESCRIPTOR:
+	    switch (setuppkt->wValue & 0xFF) {
+		case 0:
+		    sendbuffer0 = (const uint8_t *)&LANGID_Descriptor;
+		    sendbytes0 = LANGID_Descriptor.bLength;
+		    break;
+
+		case 1:
+		    sendbuffer0 = (const uint8_t *)&Manufacturer_Descriptor;
+		    sendbytes0 = Manufacturer_Descriptor.bLength;
+		    break;
+
+		case 2:
+		    sendbuffer0 = (const uint8_t *)&Product_Descriptor;
+		    sendbytes0 = Product_Descriptor.bLength;
+		    break;
+
+		case 3:
+		    sendbuffer0 = (const uint8_t *)&Serial_Descriptor;
+		    sendbytes0 = Serial_Descriptor.bLength;
+		    break;
+
+		default:
+		    sendbuffer0 = NULL;
+		    sendbytes0 = 0;
+	    }
+	    if (sendbytes0 >= setuppkt->wLength)
+		sendbytes0 = setuppkt->wLength;
+
+	    d12_send_data_ep0();
+	    break;
+
+	default:
+	    d12_stallendpt(D12_ENDPOINT_EP0_IN);
+	    d12_stallendpt(D12_ENDPOINT_EP0_OUT);
+	    break;
+    }
+}
+
+/*******************************************************************************
+** d12_stallendpt
+**
+** Stall the nominated endpoint.
+**
+*/
+void 
+d12_stallendpt(uint8_t ep) {
+    uint8_t   buffer[] = {0x01};
+
+    d12_write_cmd(D12_SET_ENDPOINT_STATUS + ep, buffer, 1);
 }
     
+/*******************************************************************************
+** d12_read_cmd
+**
+** Read data from the nominated endpoint if it's full.
+**
+*/
 uint8_t
 d12_read_endpt(uint8_t endpt, uint8_t *buffer) {
-    uint8_t d12header[2];
-    uint8_t status = 0;
-    uint8_t i;
+    uint8_t d12header[2], status, i;
 
+    d12header[1] = 0;
+    
     /* Select Endpoint */
     d12_read_cmd(endpt, &status, 1);
 
-    /* Check if Buffer is Full */
+    /* Check if buffer is Full */
     if (status & 0x01) {
-	set_d12_cmd(D12_READ_BUFFER);
+	d12_set_cmd(D12_READ_BUFFER);
 	d12header[0] = d12_get_data();
 	d12header[1] = d12_get_data();
 	if (d12header[1]) {
@@ -697,123 +833,226 @@
     return d12header[1];
 }
 
+/*******************************************************************************
+** d12_read_cmd
+**
+** Write data to the nominated endpoint.
+**
+*/
 void 
 d12_write_endpt(uint8_t endpt, const uint8_t *buffer, uint8_t bytes) {
-    uint8_t status = 0;
-    uint8_t i;
+    uint8_t status, i;
 
     /* Select Endpoint */
     d12_read_cmd(endpt, &status, 1);
-    /* Write Header */
-    set_d12_cmd(D12_WRITE_BUFFER);
-    set_d12_data(0x00);
-    set_d12_data(bytes);
-    /* Write Packet */
-    if (bytes) {
-	for (i = 0; i < bytes; i++) {
-	    set_d12_data(buffer[i]);
-	}
-    }
-    /* Validate Buffer */
-    d12_write_cmd(D12_VALIDATE_BUFFER, NULL, 0);
-}
-
-void 
-d12_write_buffer_ep0(void) {
-    uint8_t BufferStatus = 1;
-    
-    if (send_Bytes == 0) {
-	return;
-    }
-	
-    /* Read Buffer Full Status */
-    d12_read_cmd(D12_ENDPOINT_EP0_IN, &BufferStatus, 1);
-    if (BufferStatus != 0) {/* Buffer Full */
+    if ((status & 0x01) != 0) {
+	uart_putsP(PSTR("Endpoint "));
+	uart_puts_dec(endpt / 2, 0);
+	uart_putsP(PSTR(" IN is full..\n\r"));
 	return;
     }
     
-    if (BytesToSend == 0) {
-	/*
-	 * If BytesToSend is Zero and we get called again, assume
-	 * buffer is smaller
-	 * than Setup Request Size and indicate end by sending Zero
-	 * Length packet
-	 */
-	d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0);
-	send_Bytes = 0;
-    } else if (BytesToSend >= EP0_SIZE) {	
-	/* Write another EP0_SIZE Bytes to buffer and send */
-	d12_write_endpt(D12_ENDPOINT_EP0_IN, pSendBuffer, EP0_SIZE);
-	pSendBuffer += EP0_SIZE;
-	BytesToSend -= EP0_SIZE;
-	if (BytesToSend == 0 && exact_Bytes) {
-	    send_Bytes = 0;
-	}
+    /* Write Header */
+    d12_set_cmd(D12_WRITE_BUFFER);
+    d12_set_data(0x00);
+    d12_set_data(bytes);
+    /* Write Packet */
+    if (bytes) {
+	for (i = 0; i < bytes; i++)
+	    d12_set_data(buffer[i]);
+    }
+    /* Validate buffer */
+    d12_write_cmd(D12_VALIDATE_BUFFER, NULL, 0);
+}
+
+/*******************************************************************************
+** d12_send_data_ep0
+**
+** Send the next FIFOs worth of data to the endpoint and update the
+** pointer and counters.
+**
+** d12_send_data_epX should be collapsed together but it's more
+** complex than it looks.
+**
+*/
+void 
+d12_send_data_ep0(void) {
+    uint8_t status;
+
+    /* Select endpoint */
+    d12_read_cmd(D12_ENDPOINT_EP0_IN, &status, 1);
+
+    if (status & 0x01)	/* Bail if the buffer is full */
+	return;
+    
+    if (sendbytes0 == 0) {
+	/* Nothing to do */
+    } else if (sendbytes0 >= EP0_FIFO_SZ) {
+	/* Write another EP0_FIFO_SZ Bytes to buffer and send */
+	d12_write_endpt(D12_ENDPOINT_EP0_IN, sendbuffer0, EP0_FIFO_SZ);
+	sendbuffer0 += EP0_FIFO_SZ;
+	sendbytes0 -= EP0_FIFO_SZ;
+    } else {
+	/* Buffer must have less than EP0_FIFO_SZ bytes left */
+	d12_write_endpt(D12_ENDPOINT_EP0_IN, sendbuffer0, sendbytes0);
+	sendbytes0 = 0;
+    }
+}
+
+/*******************************************************************************
+** d12_send_data_ep2
+**
+** Send the next FIFOs worth of data to the endpoint and update the
+** pointer and counters.
+**
+*/
+void
+d12_send_data_ep2(void) {
+    uint8_t status;
+
+    /* Select endpoint */
+    d12_read_cmd(D12_ENDPOINT_EP2_IN, &status, 1);
+
+    if (status & 0x01)   /* Bail if the buffer is full */
+	return;
+
+    if (sendbytes2 == 0) {
+	/* Nothing to do */
+    } else if (sendbytes2 >= EP2_FIFO_SZ) {
+	/* Write another EP2_FIFO_SZ Bytes to buffer and send */
+	d12_write_endpt(D12_ENDPOINT_EP2_IN, sendbuffer2, EP2_FIFO_SZ);
+	sendbuffer2 += EP2_FIFO_SZ;
+	sendbytes2 -= EP2_FIFO_SZ;
     } else {
-	/* Buffer must have less than EP0_SIZE bytes left */	
-	d12_write_endpt(D12_ENDPOINT_EP0_IN, pSendBuffer, BytesToSend);
+	/* Buffer must have less than EP2_FIFO_SZ bytes left */
+	d12_write_endpt(D12_ENDPOINT_EP2_IN, sendbuffer2, sendbytes2);
+	sendbytes2 = 0;
+    }
+}
+
+/*******************************************************************************
+** d12_receive_data_ep2
+**
+** Get the next FIFOs worth of data from the endpoint
+**
+*/
+void
+d12_receive_data_ep2(void) {
+    uint8_t d12header[2], bytes, i, status;
+    
+    /* Select Endpoint */
+    d12_read_cmd(D12_ENDPOINT_EP2_OUT, &status, 1);
+
+    if (!(status & 0x01))	/* Bail if the buffer is empty */
+	return;
+    
+    /* Read header */
+    d12_set_cmd(D12_READ_BUFFER);
+    d12header[0] = d12_get_data();
+    d12header[1] = d12_get_data();
+    bytes = d12header[1];
+
+    packetlen2 = 0;
+    
+    for (i = 0; i < bytes; i++)
+	packet2[i] = d12_get_data();
+
+    packetlen2 += bytes;
+
+    /* Allow new packets to be accepted */
+    d12_write_cmd(D12_CLEAR_BUFFER, NULL, 0);
+
+    uart_putsP(PSTR("Got "));
+    uart_puts_dec(bytes, 0);
+    uart_putsP(PSTR(" bytes from the host\n\r"));
 	
-	BytesToSend = 0;
-	send_Bytes = 0;
-    }
+    parsebuf(packet2, D12_ENDPOINT_EP2_IN);
+    
+}
+
+/*******************************************************************************
+** d12_receive_data_ep1
+**
+** Get the next FIFOs worth of data from the endpoint
+**
+*/
+void
+d12_receive_data_ep1(void) {
+    uint8_t d12header[2], bytes, i, status;
+    
+    /* Select Endpoint */
+    d12_read_cmd(D12_ENDPOINT_EP1_OUT, &status, 1);
+
+    /* Check if Buffer is Full */
+    if (!(status & 0x01))
+	return;
+    
+    /* Read header */
+    d12_set_cmd(D12_READ_BUFFER);
+    d12header[0] = d12_get_data();
+    d12header[1] = d12_get_data();
+    bytes = d12header[1];
+
+    packetlen1 = 0;
+    
+    for (i = 0; i < bytes; i++)
+	packet1[i] = d12_get_data();
+
+    packetlen1 += bytes;
+
+    uart_putsP(PSTR("Got "));
+    uart_puts_dec(bytes, 0);
+    uart_putsP(PSTR(" bytes from the host\n\r"));
+	
+    /* Allow new packets to be accepted */
+    d12_write_cmd(D12_CLEAR_BUFFER, NULL, 0);
+
+    parsebuf(packet1, D12_ENDPOINT_EP1_IN);
 }
 
 void
-d12_send_data_ep2(void) {
-    uint8_t BufferStatus = 1;
+parsebuf(uint8_t *buffer, uint8_t ep) {
+    int		i;
+
+    switch (buffer[0]) {
+	case 0x00:
+	    uart_putsP(PSTR("OWTouchReset()\n\r"));
+	    (int8_t)buffer[0] = OWTouchReset();
+	    d12_write_endpt(ep, buffer, 1);
+	    break;
+		
+	case 0x01:
+	    uart_putsP(PSTR("OWFirst()\n\r"));
+	    (int8_t)buffer[0] = OWFirst(&buffer[1], 1, 0);
+	    for (i = 0; i < 9; i++) {
+		uart_puts_hex(buffer[i + 1]);
+		uart_putsP(PSTR(" "));
+	    }
+	    uart_putsP(PSTR("\n\r"));
+	    d12_write_endpt(ep, buffer, 9);
+	    break;
 
-    /* Read Buffer Full Status */
-    d12_read_cmd(D12_ENDPOINT_EP2_IN, &BufferStatus, 1);
-    if (BufferStatus == 0) {   /* Buffer Empty */
-	if (BytesToSend2 == 0) {
-	    /* Nothing to do */
-	    send_packet2 = 0;
-	} else if (BytesToSend2 >= 64) {
-	    /* Write another 64 Bytes to buffer and send */
-	    d12_write_endpt(D12_ENDPOINT_EP2_IN, pSendBuffer2, 64);
-	    pSendBuffer2 += 64;
-	    BytesToSend2 -= 64;
-	} else {
-	    /* Buffer must have less than 64 bytes left */
-	    d12_write_endpt(D12_ENDPOINT_EP2_IN, pSendBuffer2, BytesToSend2);
-	    BytesToSend2 = 0;
-	    send_packet2 = 0;
-	}
+	case 0x02:
+	    uart_putsP(PSTR("OWNext()\n\r"));
+	    (int8_t)buffer[0] = OWNext(&buffer[1], 1, 0);
+	    d12_write_endpt(ep, buffer, 9);
+	    break;
+
+	case 0x03:
+	    uart_putsP(PSTR(" bytes, asked to do temperature conversion for "));
+	    for (i = 0; i < 8; i++) {
+		uart_puts_hex(buffer[i + 1]);
+		if (i != 7)
+		    uart_putsP(PSTR(":"));
+	    }
+
+	    uart_putsP(PSTR("\n\r"));
+	    d12_write_endpt(ep, buffer, 9);
+		
+	    break;
+		
+	default:
+	    uart_putsP(PSTR("Unknown command on endpoint 1\n\r"));
+	    break;
     }
 }
-
-void
-d12_receive_data_ep2(void) {
-    uint8_t D12Header[2];
-    uint8_t bytes;
-    uint8_t BufferStatus = 0;
-    uint8_t i;
-
-    /* Select Endpoint */
-    d12_read_cmd(D12_ENDPOINT_EP2_OUT, &BufferStatus, 1);
-    /* Check if Buffer is Full */
-    if (BufferStatus & 0x01) {
-	/* Read header */
-	set_d12_cmd(D12_READ_BUFFER);
-	D12Header[0] = d12_get_data();
-	D12Header[1] = d12_get_data();
-	bytes = D12Header[1];
-	/* TODO check if the packet is not too long */
-	uart_putsP(PSTR("Got data\n\r"));
-	for (i = 0; i < bytes; i++) {
-	    packet2[packetlen2 + i] = d12_get_data();
-	    uart_puts_hex(packet2[packetlen2 + i]);
-	    uart_putsP(PSTR(" "));
-	}
-	uart_putsP(PSTR("\n\r"));
-	packetlen2 += bytes;
-	/* Allow new packets to be accepted */
-	d12_write_cmd(D12_CLEAR_BUFFER, NULL, 0);
-	if (bytes == 0 || bytes < 64) { /* request complete */
-	    pSendBuffer2 = packet2;
-	    send_packet2 = 1;
-	    packetlen2 = 0;
-	    d12_send_data_ep2();
-	}
-    }
-}