Christina Quast | 2b8a18b | 2015-04-12 09:31:36 +0200 | [diff] [blame] | 1 | #include "board.h" |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 2 | #include "req_ctx.h" |
Harald Welte | 54cb3d0 | 2016-02-29 14:12:40 +0100 | [diff] [blame] | 3 | #include "linuxlist.h" |
| 4 | |
| 5 | static volatile uint32_t usbep_in_progress[BOARD_USB_NUMENDPOINTS]; |
Christina Quast | 2b8a18b | 2015-04-12 09:31:36 +0200 | [diff] [blame] | 6 | |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 7 | /* call-back after (successful?) transfer of a buffer */ |
| 8 | static void usb_write_cb(uint8_t *arg, uint8_t status, uint32_t transferred, |
| 9 | uint32_t remaining) |
Christina Quast | 2b8a18b | 2015-04-12 09:31:36 +0200 | [diff] [blame] | 10 | { |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 11 | struct req_ctx *rctx = (struct req_ctx *) arg; |
| 12 | |
Harald Welte | a0cf200 | 2016-03-02 10:35:51 +0100 | [diff] [blame] | 13 | TRACE_DEBUG("%s (EP=%u)\r\n", __func__, rctx->ep); |
| 14 | |
| 15 | __disable_irq(); |
| 16 | usbep_in_progress[rctx->ep]--; |
| 17 | __enable_irq(); |
| 18 | TRACE_DEBUG("%u: in_progress=%d\n", rctx->ep, usbep_in_progress[rctx->ep]); |
Harald Welte | 54cb3d0 | 2016-02-29 14:12:40 +0100 | [diff] [blame] | 19 | |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 20 | if (status != USBD_STATUS_SUCCESS) |
| 21 | TRACE_ERROR("%s error, status=%d\n", __func__, status); |
| 22 | |
| 23 | /* release request contxt to pool */ |
| 24 | req_ctx_set_state(rctx, RCTX_S_FREE); |
Christina Quast | 2b8a18b | 2015-04-12 09:31:36 +0200 | [diff] [blame] | 25 | } |
| 26 | |
Harald Welte | 54cb3d0 | 2016-02-29 14:12:40 +0100 | [diff] [blame] | 27 | int usb_refill_to_host(struct llist_head *queue, uint32_t ep) |
Christina Quast | 2b8a18b | 2015-04-12 09:31:36 +0200 | [diff] [blame] | 28 | { |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 29 | struct req_ctx *rctx; |
| 30 | int rc; |
Christina Quast | 2b8a18b | 2015-04-12 09:31:36 +0200 | [diff] [blame] | 31 | |
Harald Welte | a0cf200 | 2016-03-02 10:35:51 +0100 | [diff] [blame] | 32 | __disable_irq(); |
| 33 | if (usbep_in_progress[ep]) { |
| 34 | __enable_irq(); |
Harald Welte | 54cb3d0 | 2016-02-29 14:12:40 +0100 | [diff] [blame] | 35 | return 0; |
Harald Welte | a0cf200 | 2016-03-02 10:35:51 +0100 | [diff] [blame] | 36 | } |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 37 | |
Harald Welte | a0cf200 | 2016-03-02 10:35:51 +0100 | [diff] [blame] | 38 | if (llist_empty(queue)) { |
| 39 | __enable_irq(); |
Harald Welte | 54cb3d0 | 2016-02-29 14:12:40 +0100 | [diff] [blame] | 40 | return 0; |
Harald Welte | a0cf200 | 2016-03-02 10:35:51 +0100 | [diff] [blame] | 41 | } |
| 42 | |
| 43 | usbep_in_progress[ep]++; |
Harald Welte | 54cb3d0 | 2016-02-29 14:12:40 +0100 | [diff] [blame] | 44 | |
| 45 | rctx = llist_entry(queue->next, struct req_ctx, list); |
| 46 | llist_del(&rctx->list); |
| 47 | |
Harald Welte | a0cf200 | 2016-03-02 10:35:51 +0100 | [diff] [blame] | 48 | __enable_irq(); |
| 49 | |
| 50 | TRACE_DEBUG("%u: in_progress=%d\n", ep, usbep_in_progress[ep]); |
| 51 | TRACE_DEBUG("%s (EP=%u)\r\n", __func__, ep); |
| 52 | |
Harald Welte | 54cb3d0 | 2016-02-29 14:12:40 +0100 | [diff] [blame] | 53 | req_ctx_set_state(rctx, RCTX_S_USB_TX_BUSY); |
| 54 | rctx->ep = ep; |
| 55 | |
| 56 | rc = USBD_Write(ep, rctx->data, rctx->tot_len, |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 57 | (TransferCallback) &usb_write_cb, rctx); |
| 58 | if (rc != USBD_STATUS_SUCCESS) { |
Harald Welte | 2ad0ca1 | 2016-02-29 10:07:16 +0100 | [diff] [blame] | 59 | TRACE_ERROR("%s error %x\n", __func__, rc); |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 60 | req_ctx_set_state(rctx, RCTX_S_USB_TX_PENDING); |
Harald Welte | a0cf200 | 2016-03-02 10:35:51 +0100 | [diff] [blame] | 61 | __disable_irq(); |
| 62 | usbep_in_progress[ep]--; |
| 63 | __enable_irq(); |
| 64 | TRACE_DEBUG("%u: in_progress=%d\n", ep, usbep_in_progress[ep]); |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 65 | return 0; |
| 66 | } |
| 67 | |
| 68 | return 1; |
Christina Quast | 2b8a18b | 2015-04-12 09:31:36 +0200 | [diff] [blame] | 69 | } |
| 70 | |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 71 | static void usb_read_cb(uint8_t *arg, uint8_t status, uint32_t transferred, |
| 72 | uint32_t remaining) |
Christina Quast | 2b8a18b | 2015-04-12 09:31:36 +0200 | [diff] [blame] | 73 | { |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 74 | struct req_ctx *rctx = (struct req_ctx *) arg; |
Harald Welte | 54cb3d0 | 2016-02-29 14:12:40 +0100 | [diff] [blame] | 75 | struct llist_head *queue = (struct llist_head *) usbep_in_progress[rctx->ep]; |
| 76 | |
Harald Welte | a0cf200 | 2016-03-02 10:35:51 +0100 | [diff] [blame] | 77 | TRACE_DEBUG("%s (EP=%u)\r\n", __func__, rctx->ep); |
| 78 | |
Harald Welte | 54cb3d0 | 2016-02-29 14:12:40 +0100 | [diff] [blame] | 79 | usbep_in_progress[rctx->ep] = 0; |
Christina Quast | 2b8a18b | 2015-04-12 09:31:36 +0200 | [diff] [blame] | 80 | |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 81 | if (status != USBD_STATUS_SUCCESS) { |
| 82 | TRACE_ERROR("%s error, status=%d\n", __func__, status); |
| 83 | /* release request contxt to pool */ |
| 84 | req_ctx_put(rctx); |
| 85 | return; |
| 86 | } |
Harald Welte | ebb80ed | 2016-03-02 13:56:59 +0100 | [diff] [blame] | 87 | req_ctx_set_state(rctx, RCTX_S_MAIN_PROCESSING); |
Harald Welte | 54cb3d0 | 2016-02-29 14:12:40 +0100 | [diff] [blame] | 88 | llist_add_tail(&rctx->list, queue); |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 89 | } |
| 90 | |
Harald Welte | 54cb3d0 | 2016-02-29 14:12:40 +0100 | [diff] [blame] | 91 | int usb_refill_from_host(struct llist_head *queue, int ep) |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 92 | { |
| 93 | struct req_ctx *rctx; |
| 94 | int rc; |
| 95 | |
Harald Welte | 54cb3d0 | 2016-02-29 14:12:40 +0100 | [diff] [blame] | 96 | if (usbep_in_progress[ep]) |
| 97 | return 0; |
| 98 | |
Harald Welte | a0cf200 | 2016-03-02 10:35:51 +0100 | [diff] [blame] | 99 | TRACE_DEBUG("%s (EP=%u)\r\n", __func__, ep); |
| 100 | |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 101 | rctx = req_ctx_find_get(0, RCTX_S_FREE, RCTX_S_USB_RX_BUSY); |
Harald Welte | 54cb3d0 | 2016-02-29 14:12:40 +0100 | [diff] [blame] | 102 | rctx->ep = ep; |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 103 | |
| 104 | rc = USBD_Read(ep, rctx->data, rctx->size, |
| 105 | (TransferCallback) &usb_read_cb, rctx); |
| 106 | |
| 107 | if (rc != USBD_STATUS_SUCCESS) { |
Harald Welte | 2ad0ca1 | 2016-02-29 10:07:16 +0100 | [diff] [blame] | 108 | TRACE_ERROR("%s error %x\n", __func__, rc); |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 109 | req_ctx_put(rctx); |
Harald Welte | 54cb3d0 | 2016-02-29 14:12:40 +0100 | [diff] [blame] | 110 | return 0; |
Harald Welte | 2a6d3af | 2016-02-28 19:29:14 +0100 | [diff] [blame] | 111 | } |
| 112 | |
Harald Welte | 54cb3d0 | 2016-02-29 14:12:40 +0100 | [diff] [blame] | 113 | usbep_in_progress[ep] = (uint32_t) queue; |
| 114 | |
| 115 | return 1; |
Christina Quast | 2b8a18b | 2015-04-12 09:31:36 +0200 | [diff] [blame] | 116 | } |