Mercurial > ~darius > hgwebdir.cgi > avr
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(); - } - } -}