X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=src%2Flpc%2Fao_usb_lpc.c;h=594114b62ed856a8b4babc8f9ccf47f3597d9624;hp=78fbac3985ea848e3a519c2c977562c193ab3774;hb=0686a7b8aec524d81bda4c572549a3a068ce0eed;hpb=0671b3c8c24c9f33be77a10315c4669f33c516d7 diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 78fbac39..594114b6 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -3,7 +3,8 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -80,14 +81,12 @@ static uint8_t *ao_usb_ep0_setup_buffer; static uint8_t *ao_usb_ep0_rx_buffer; /* Pointer to bulk data tx/rx buffers in USB memory */ -static uint8_t *ao_usb_in_tx_buffer; -static uint8_t *ao_usb_out_rx_buffer; - -/* Our data buffers */ -static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE]; +static uint8_t *ao_usb_in_tx_buffer[2]; +static uint8_t ao_usb_in_tx_cur; static uint8_t ao_usb_tx_count; -static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; +static uint8_t *ao_usb_out_rx_buffer[2]; +static uint8_t ao_usb_out_rx_cur; static uint8_t ao_usb_rx_count, ao_usb_rx_pos; extern struct lpc_usb_endpoint lpc_usb_endpoint; @@ -271,13 +270,10 @@ ao_usb_epn_in_count(uint8_t n) return ao_usb_ep_count(ao_usb_epn_in(n, 0)); } -static uint8_t * -ao_usb_enable_ep(vuint32_t *ep, uint16_t nbytes, uint16_t set_nbytes) +static void +ao_usb_enable_ep(vuint32_t *ep, uint8_t *addr, uint16_t set_nbytes) { - uint8_t *addr = ao_usb_alloc_sram(nbytes); - ao_usb_set_ep(ep, addr, set_nbytes); - return addr; } static void @@ -294,18 +290,14 @@ ao_usb_disable_ep(vuint32_t *ep) } static void -ao_usb_enable_epn(uint8_t n, uint16_t out_bytes, uint8_t **out_addr, uint16_t in_bytes, uint8_t **in_addr) +ao_usb_enable_epn(uint8_t n, + uint16_t out_bytes, uint8_t *out_addr, + uint8_t *in_addr) { - uint8_t *addr; - - addr = ao_usb_enable_ep(ao_usb_epn_out(n, 0), out_bytes, out_bytes); - if (out_addr) - *out_addr = addr; + ao_usb_enable_ep(ao_usb_epn_out(n, 0), out_addr, out_bytes); ao_usb_disable_ep(ao_usb_epn_out(n, 1)); - addr = ao_usb_enable_ep(ao_usb_epn_in(n, 0), in_bytes, 0); - if (in_addr) - *in_addr = addr; + ao_usb_enable_ep(ao_usb_epn_in(n, 0), in_addr, 0); ao_usb_disable_ep(ao_usb_epn_in(n, 1)); } @@ -323,6 +315,14 @@ ao_usb_reset(void) { ao_usb_set_address(0); ao_usb_configuration = 0; + + ao_usb_ep0_state = AO_USB_EP0_IDLE; + ao_usb_ep0_in_data = NULL; + ao_usb_ep0_in_len = 0; + ao_usb_ep0_in_max = 0; + + ao_usb_ep0_out_data = NULL; + ao_usb_ep0_out_len = 0; } static void @@ -337,17 +337,14 @@ ao_usb_set_ep0(void) lpc_usb.intstat = 0xc00003ff; - ao_usb_sram = lpc_usb_sram; - lpc_usb.epliststart = (uint32_t) (intptr_t) &lpc_usb_endpoint; lpc_usb.databufstart = ((uint32_t) (intptr_t) ao_usb_sram) & 0xffc00000; /* Set up EP 0 - a Control end point with 32 bytes of in and out buffers */ - ao_usb_ep0_rx_buffer = ao_usb_enable_ep(ao_usb_ep0_out(), AO_USB_CONTROL_SIZE, AO_USB_CONTROL_SIZE); - ao_usb_ep0_setup_buffer = ao_usb_alloc_sram(AO_USB_CONTROL_SIZE); + ao_usb_enable_ep(ao_usb_ep0_out(), ao_usb_ep0_rx_buffer, AO_USB_CONTROL_SIZE); lpc_usb_endpoint.setup = ao_usb_sram_offset(ao_usb_ep0_setup_buffer); - ao_usb_ep0_tx_buffer = ao_usb_enable_ep(ao_usb_ep0_in(), AO_USB_CONTROL_SIZE, 0); + ao_usb_enable_ep(ao_usb_ep0_in(), ao_usb_ep0_tx_buffer, 0); /* Clear all of the other endpoints */ for (e = 1; e <= 4; e++) @@ -361,15 +358,29 @@ ao_usb_set_configuration(void) debug ("ao_usb_set_configuration\n"); /* Set up the INT end point */ - ao_usb_enable_epn(AO_USB_INT_EP, 0, NULL, 0, NULL); - + ao_usb_enable_epn(AO_USB_INT_EP, 0, NULL, NULL); + /* Set up the OUT end point */ - ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE, &ao_usb_out_rx_buffer, 0, NULL); + ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE, ao_usb_out_rx_buffer[0], NULL); + + /* Set the current RX pointer to the *other* buffer so that when buffer 0 gets + * data, we'll switch to it and pull bytes from there + */ + ao_usb_out_rx_cur = 1; /* Set up the IN end point */ - ao_usb_enable_epn(AO_USB_IN_EP, 0, NULL, AO_USB_IN_SIZE, &ao_usb_in_tx_buffer); + ao_usb_enable_epn(AO_USB_IN_EP, 0, NULL, ao_usb_in_tx_buffer[0]); + ao_usb_in_tx_cur = 0; + + ao_usb_in_flushed = 0; + ao_usb_in_pending = 0; + ao_wakeup(&ao_usb_in_pending); + + ao_usb_out_avail = 0; + ao_usb_configuration = 0; ao_usb_running = 1; + ao_wakeup(&ao_usb_running); } /* Send an IN data packet */ @@ -466,12 +477,12 @@ ao_usb_ep0_in_start(uint16_t max) ao_usb_ep0_flush(); } -static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; +struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; /* Walk through the list of descriptors and find a match */ static void -ao_usb_get_descriptor(uint16_t value) +ao_usb_get_descriptor(uint16_t value, uint16_t length) { const uint8_t *descriptor; uint8_t type = value >> 8; @@ -485,6 +496,8 @@ ao_usb_get_descriptor(uint16_t value) len = descriptor[2]; else len = descriptor[0]; + if (len > length) + len = length; ao_usb_ep0_in_set(descriptor, len); break; } @@ -529,7 +542,7 @@ ao_usb_ep0_setup(void) break; case AO_USB_REQ_GET_DESCRIPTOR: debug ("get descriptor %d\n", ao_usb_setup.value); - ao_usb_get_descriptor(ao_usb_setup.value); + ao_usb_get_descriptor(ao_usb_setup.value, ao_usb_setup.length); break; case AO_USB_REQ_GET_CONFIGURATION: debug ("get configuration %d\n", ao_usb_configuration); @@ -716,8 +729,8 @@ _ao_usb_in_send(void) ao_usb_in_pending = 1; if (ao_usb_tx_count != AO_USB_IN_SIZE) ao_usb_in_flushed = 1; - memcpy(ao_usb_in_tx_buffer, ao_usb_tx_buffer, ao_usb_tx_count); - ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP, 0), ao_usb_in_tx_buffer, ao_usb_tx_count); + ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP, 0), ao_usb_in_tx_buffer[ao_usb_in_tx_cur], ao_usb_tx_count); + ao_usb_in_tx_cur = 1 - ao_usb_in_tx_cur; ao_usb_tx_count = 0; _tx_dbg0("in_send end"); } @@ -771,7 +784,7 @@ ao_usb_putchar(char c) _ao_usb_in_wait(); ao_usb_in_flushed = 0; - ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c; + ao_usb_in_tx_buffer[ao_usb_in_tx_cur][ao_usb_tx_count++] = (uint8_t) c; /* Send the packet when full */ if (ao_usb_tx_count == AO_USB_IN_SIZE) { @@ -792,13 +805,12 @@ _ao_usb_out_recv(void) _rx_dbg1("out_recv count", ao_usb_rx_count); debug ("recv %d\n", ao_usb_rx_count); - debug_data("Fill OUT len %d:", ao_usb_rx_count); - memcpy(ao_usb_rx_buffer, ao_usb_out_rx_buffer, ao_usb_rx_count); - debug_data("\n"); + debug_data("Fill OUT len %d\n", ao_usb_rx_count); ao_usb_rx_pos = 0; + ao_usb_out_rx_cur = 1 - ao_usb_out_rx_cur; /* ACK the packet */ - ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer, AO_USB_OUT_SIZE); + ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer[1-ao_usb_out_rx_cur], AO_USB_OUT_SIZE); } int @@ -823,7 +835,7 @@ _ao_usb_pollchar(void) } /* Pull a character out of the fifo */ - c = ao_usb_rx_buffer[ao_usb_rx_pos++]; + c = ao_usb_out_rx_buffer[ao_usb_out_rx_cur][ao_usb_rx_pos++]; return c; } @@ -845,7 +857,7 @@ ao_usb_disable(void) ao_arch_block_interrupts(); #if HAS_USB_PULLUP - ao_gpio_set(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 0); + ao_gpio_set(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, 0); #endif /* Disable interrupts */ lpc_usb.inten = 0; @@ -949,10 +961,21 @@ ao_usb_enable(void) for (t = 0; t < 1000; t++) ao_arch_nop(); + ao_usb_sram = lpc_usb_sram; + + ao_usb_ep0_rx_buffer = ao_usb_alloc_sram(AO_USB_CONTROL_SIZE); + ao_usb_ep0_tx_buffer = ao_usb_alloc_sram(AO_USB_CONTROL_SIZE); + ao_usb_ep0_setup_buffer = ao_usb_alloc_sram(AO_USB_CONTROL_SIZE); + + ao_usb_out_rx_buffer[0] = ao_usb_alloc_sram(AO_USB_OUT_SIZE); + ao_usb_out_rx_buffer[1] = ao_usb_alloc_sram(AO_USB_OUT_SIZE); + ao_usb_in_tx_buffer[0] = ao_usb_alloc_sram(AO_USB_IN_SIZE); + ao_usb_in_tx_buffer[1] = ao_usb_alloc_sram(AO_USB_IN_SIZE); + ao_usb_set_ep0(); #if HAS_USB_PULLUP - ao_gpio_set(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 1); + ao_gpio_set(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, 1); #endif } @@ -980,7 +1003,7 @@ ao_usb_irq(void) control_count, out_count, in_count, int_count, reset_count); } -__code struct ao_cmds ao_usb_cmds[] = { +const struct ao_cmds ao_usb_cmds[] = { { ao_usb_irq, "I\0Show USB interrupt counts" }, { 0, NULL } }; @@ -990,9 +1013,12 @@ void ao_usb_init(void) { #if HAS_USB_PULLUP - ao_enable_output(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 0); -#endif + int i; + ao_enable_output(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, 0); + for (i = 0; i < 40000; i++) + ao_arch_nop(); +#endif ao_usb_enable(); debug ("ao_usb_init\n");