X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=src%2Flpc%2Fao_usb_lpc.c;h=594114b62ed856a8b4babc8f9ccf47f3597d9624;hp=af304b8afdd0653ebedf141ceac1d7dda194b193;hb=0686a7b8aec524d81bda4c572549a3a068ce0eed;hpb=41a0604ad1ea1a03e2db7d41731dbadf466b45db diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index af304b8a..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 @@ -106,7 +107,7 @@ static uint8_t ao_usb_in_pending; /* Marks when an OUT packet has been received by the hardware * but not pulled to the shadow buffer. */ -uint8_t ao_usb_out_avail; +static uint8_t ao_usb_out_avail; uint8_t ao_usb_running; static uint8_t ao_usb_configuration; @@ -232,15 +233,15 @@ ao_usb_ep0_in(void) } static inline vuint32_t * -ao_usb_epn_out(uint8_t n) +ao_usb_epn_out(uint8_t n, uint8_t i) { - return &lpc_usb_endpoint.epn[n-1].out[0]; + return &lpc_usb_endpoint.epn[n-1].out[i]; } static inline vuint32_t * -ao_usb_epn_in(uint8_t n) +ao_usb_epn_in(uint8_t n, uint8_t i) { - return &lpc_usb_endpoint.epn[n-1].in[0]; + return &lpc_usb_endpoint.epn[n-1].in[i]; } #if UNUSED @@ -254,28 +255,25 @@ ao_usb_set_epn_in(uint8_t n, uint8_t *addr, uint16_t nbytes) static void ao_usb_set_epn_out(uint8_t n, uint8_t *addr, uint16_t nbytes) { - ao_usb_set_ep(ao_usb_epn_out(n), addr, nbytes); + ao_usb_set_ep(ao_usb_epn_out(n, 0), addr, nbytes); } static inline uint16_t ao_usb_epn_out_count(uint8_t n) { - return ao_usb_ep_count(ao_usb_epn_out(n)); + return ao_usb_ep_count(ao_usb_epn_out(n, 0)); } static inline uint16_t ao_usb_epn_in_count(uint8_t n) { - return ao_usb_ep_count(ao_usb_epn_in(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 @@ -292,28 +290,24 @@ ao_usb_disable_ep(vuint32_t *ep) } static void -ao_usb_enable_epn(uint8_t n, uint16_t out_bytes, uint16_t out_set_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), out_bytes, out_set_bytes); - if (out_addr) - *out_addr = addr; - ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].out[1]); + 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), in_bytes, 0); - if (in_addr) - *in_addr = addr; - ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].in[1]); + ao_usb_enable_ep(ao_usb_epn_in(n, 0), in_addr, 0); + ao_usb_disable_ep(ao_usb_epn_in(n, 1)); } static void ao_usb_disable_epn(uint8_t n) { - ao_usb_disable_ep(ao_usb_epn_out(n)); - ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].out[1]); - ao_usb_disable_ep(ao_usb_epn_in(n)); - ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].in[1]); + ao_usb_disable_ep(ao_usb_epn_out(n, 0)); + ao_usb_disable_ep(ao_usb_epn_out(n, 1)); + ao_usb_disable_ep(ao_usb_epn_in(n, 0)); + ao_usb_disable_ep(ao_usb_epn_in(n, 1)); } static void @@ -321,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 @@ -335,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++) @@ -359,19 +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, 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 * 2, AO_USB_OUT_SIZE, &ao_usb_out_rx_buffer[0], 0, NULL); - ao_usb_out_rx_buffer[1] = ao_usb_out_rx_buffer[0] + AO_USB_OUT_SIZE; - ao_usb_out_rx_cur = 0; + 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, 0, NULL, AO_USB_IN_SIZE * 2, &ao_usb_in_tx_buffer[0]); - ao_usb_in_tx_buffer[1] = ao_usb_in_tx_buffer[0] + AO_USB_IN_SIZE; + 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 */ @@ -468,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; @@ -487,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; } @@ -531,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); @@ -718,7 +729,7 @@ _ao_usb_in_send(void) ao_usb_in_pending = 1; if (ao_usb_tx_count != AO_USB_IN_SIZE) ao_usb_in_flushed = 1; - ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP), ao_usb_in_tx_buffer[ao_usb_in_tx_cur], 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"); @@ -784,45 +795,6 @@ ao_usb_putchar(char c) ao_arch_release_interrupts(); } -#if HAS_AO_USB_WRITE -void * -ao_usb_alloc(uint16_t len) -{ - return ao_usb_alloc_sram(len); -} - -void -ao_usb_write(void *block, int len) -{ - uint8_t *b = block; - int this_time; - - if (!ao_usb_running) - return; - - if (!ao_usb_in_flushed) - ao_usb_flush(); - - while (len) { - ao_usb_in_flushed = 0; - this_time = AO_USB_IN_SIZE; - if (this_time > len) - this_time = len; - - ao_arch_block_interrupts(); - while (ao_usb_in_pending) - ao_sleep(&ao_usb_in_pending); - ao_usb_in_pending = 1; - if (this_time != AO_USB_IN_SIZE) - ao_usb_in_flushed = 1; - ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP), b, this_time); - ao_arch_release_interrupts(); - b += this_time; - len -= this_time; - } -} -#endif - static void _ao_usb_out_recv(void) { @@ -885,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; @@ -989,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 } @@ -1020,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 } }; @@ -1030,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"); @@ -1084,7 +1070,7 @@ static void _dbg(int line, char *msg, uint32_t value) dbg[dbg_i].primask = primask; #if TX_DBG dbg[dbg_i].in_count = in_count; - dbg[dbg_i].in_ep = *ao_usb_epn_in(AO_USB_IN_EP); + dbg[dbg_i].in_ep = *ao_usb_epn_in(AO_USB_IN_EP, 0); dbg[dbg_i].in_pending = ao_usb_in_pending; dbg[dbg_i].tx_count = ao_usb_tx_count; dbg[dbg_i].in_flushed = ao_usb_in_flushed; @@ -1093,7 +1079,7 @@ static void _dbg(int line, char *msg, uint32_t value) dbg[dbg_i].rx_count = ao_usb_rx_count; dbg[dbg_i].rx_pos = ao_usb_rx_pos; dbg[dbg_i].out_avail = ao_usb_out_avail; - dbg[dbg_i].out_ep = *ao_usb_epn_out(AO_USB_OUT_EP); + dbg[dbg_i].out_ep = *ao_usb_epn_out(AO_USB_OUT_EP, 0); #endif if (++dbg_i == NUM_USB_DBG) dbg_i = 0;