lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 1 | // Copyright lowRISC contributors. |
| 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 3 | // SPDX-License-Identifier: Apache-2.0 |
| 4 | |
Miguel Young de la Sota | f225d99 | 2019-12-17 10:19:22 -0600 | [diff] [blame] | 5 | #include "sw/device/lib/usb_simpleserial.h" |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 6 | |
Miguel Young de la Sota | f225d99 | 2019-12-17 10:19:22 -0600 | [diff] [blame] | 7 | #include "sw/device/lib/usbdev.h" |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 8 | |
| 9 | #define MAX_GATHER 16 |
| 10 | |
| 11 | static void ss_rx(void *ssctx_v, usbbufid_t buf, int size, int setup) { |
| 12 | usb_ss_ctx_t *ssctx = (usb_ss_ctx_t *)ssctx_v; |
| 13 | void *ctx = ssctx->ctx; |
| 14 | volatile uint8_t *bp = (volatile uint8_t *)usbdev_buf_idtoaddr(ctx, buf); |
| 15 | |
| 16 | if (size > BUF_LENGTH) { |
| 17 | size = BUF_LENGTH; |
| 18 | } |
| 19 | |
| 20 | while (size--) { |
| 21 | ssctx->got_byte(*bp++); |
| 22 | } |
| 23 | } |
| 24 | |
| 25 | // Called periodically by the main loop to ensure characters don't |
| 26 | // stick around too long |
| 27 | static void ss_flush(void *ssctx_v) { |
| 28 | usb_ss_ctx_t *ssctx = (usb_ss_ctx_t *)ssctx_v; |
| 29 | void *ctx = ssctx->ctx; |
| 30 | volatile uint32_t *bp_w; |
| 31 | if ((ssctx->cur_buf == -1) || (ssctx->cur_cpos <= 0)) { |
| 32 | return; |
| 33 | } |
| 34 | if ((ssctx->cur_cpos & 0x3) != 0) { |
| 35 | // unwritten data to copy over |
| 36 | bp_w = usbdev_buf_idtoaddr(ctx, ssctx->cur_buf); |
| 37 | // no -1 here because cpos is in the word we are writing |
| 38 | bp_w[(ssctx->cur_cpos / 4)] = ssctx->chold.data_w; |
| 39 | } |
| 40 | usbdev_sendbuf_byid(ctx, ssctx->cur_buf, ssctx->cur_cpos, ssctx->ep); |
| 41 | ssctx->cur_buf = -1; // given it to the hardware |
| 42 | } |
| 43 | |
| 44 | // Simple send byte will gather data for a while and send |
| 45 | void usb_simpleserial_send_byte(usb_ss_ctx_t *ssctx, uint8_t c) { |
| 46 | volatile uint32_t *bp_w; |
| 47 | if (ssctx->cur_buf == -1) { |
| 48 | ssctx->cur_buf = usbdev_buf_allocate_byid(ssctx->ctx); |
| 49 | ssctx->cur_cpos = 0; |
| 50 | } |
| 51 | // Abort if completely out of buffers and allocation returned -1 |
| 52 | if (ssctx->cur_buf < 0) { |
| 53 | return; |
| 54 | } |
| 55 | ssctx->chold.data_b[ssctx->cur_cpos++ & 0x3] = c; |
| 56 | if ((ssctx->cur_cpos & 0x3) == 0) { |
| 57 | // just wrote last byte in word |
| 58 | bp_w = usbdev_buf_idtoaddr(ssctx->ctx, ssctx->cur_buf); |
| 59 | // -1 here because cpos already incremented to next word |
| 60 | bp_w[(ssctx->cur_cpos / 4) - 1] = ssctx->chold.data_w; |
| 61 | if (ssctx->cur_cpos >= MAX_GATHER) { |
| 62 | usbdev_sendbuf_byid(ssctx->ctx, ssctx->cur_buf, ssctx->cur_cpos, |
| 63 | ssctx->ep); |
| 64 | ssctx->cur_buf = -1; // given it to the hardware |
| 65 | } |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | void usb_simpleserial_init(usb_ss_ctx_t *ssctx, usbdev_ctx_t *ctx, int ep, |
| 70 | void (*got_byte)(uint8_t)) { |
Stefan Lippuner | 3a10e76 | 2020-01-09 16:06:42 +0100 | [diff] [blame] | 71 | usbdev_endpoint_setup(ctx, ep, 1, ssctx, NULL, ss_rx, ss_flush, NULL); |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 72 | ssctx->ctx = ctx; |
| 73 | ssctx->ep = ep; |
| 74 | ssctx->got_byte = got_byte; |
| 75 | ssctx->cur_buf = -1; |
| 76 | } |