blob: 328ff3f2161d6f30207dbafef3921ff488c1ce5b [file] [log] [blame]
Sylvain Munautbc9f5c42020-09-14 10:22:29 +02001/*
2 * usb_e1.c
3 *
4 * Copyright (C) 2019-2020 Sylvain Munaut <tnt@246tNt.com>
5 * SPDX-License-Identifier: GPL-3.0-or-later
6 */
7
8#include <stdint.h>
9#include <stdbool.h>
10#include <string.h>
11
12#include <no2usb/usb_hw.h>
13#include <no2usb/usb_priv.h>
14
15#include "console.h"
Harald Welte2df1f802020-12-14 17:46:53 +010016#include "e1.h"
Sylvain Munautff44f142022-01-03 20:34:23 +010017#include "misc.h"
18#include "usb_desc_ids.h"
Sylvain Munaut41c98b62022-01-05 21:11:35 +010019#include "utils.h"
Harald Welte9469e042020-12-15 23:09:40 +010020
21#include "ice1usb_proto.h"
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020022
Sylvain Munaut41c98b62022-01-05 21:11:35 +010023struct usb_e1_state {
Harald Welte30fc5602020-12-14 15:56:28 +010024 bool running; /* are we running (transceiving USB data)? */
25 int out_bdi; /* buffer descriptor index for OUT EP */
26 int in_bdi; /* buffer descriptor index for IN EP */
Harald Welte9469e042020-12-15 23:09:40 +010027 struct ice1usb_tx_config tx_cfg;
28 struct ice1usb_rx_config rx_cfg;
Harald Welte805f2cf2020-12-14 17:31:03 +010029 struct e1_error_count last_err;
Sylvain Munaut41c98b62022-01-05 21:11:35 +010030};
31
Sylvain Munautdb0b8102022-09-01 18:43:41 +020032static struct usb_e1_state g_usb_e1[NUM_E1_PORTS];
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020033
Harald Welte9469e042020-12-15 23:09:40 +010034/* default configuration at power-up */
35static const struct ice1usb_tx_config tx_cfg_default = {
36 .mode = ICE1USB_TX_MODE_TS0_CRC4_E,
37 .timing = ICE1USB_TX_TIME_SRC_LOCAL,
38 .ext_loopback = ICE1USB_TX_EXT_LOOPBACK_OFF,
39 .alarm = 0,
40};
41
42static const struct ice1usb_rx_config rx_cfg_default = {
43 .mode = ICE1USB_RX_MODE_MULTIFRAME,
44};
45
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020046
Sylvain Munautff44f142022-01-03 20:34:23 +010047static volatile struct usb_ep *
48_get_ep_regs(uint8_t ep)
49{
50 return (ep & 0x80) ? &usb_ep_regs[ep & 0x1f].in : &usb_ep_regs[ep & 0x1f].out;
51}
52
Sylvain Munaut41c98b62022-01-05 21:11:35 +010053static struct usb_e1_state *
54_get_state(int port)
55{
Sylvain Munautdb0b8102022-09-01 18:43:41 +020056 if ((port < 0) || (port >= NUM_E1_PORTS))
Sylvain Munaut41c98b62022-01-05 21:11:35 +010057 panic("_get_state invalid port %d", port);
58 return &g_usb_e1[port];
59}
60
61static int
62_ifnum2port(uint8_t bInterfaceNumber)
63{
64 switch (bInterfaceNumber) {
65 case USB_INTF_E1(0): return 0;
Sylvain Munautdb0b8102022-09-01 18:43:41 +020066#if NUM_E1_PORTS >= 2
Sylvain Munaut41c98b62022-01-05 21:11:35 +010067 case USB_INTF_E1(1): return 1;
Sylvain Munautdb0b8102022-09-01 18:43:41 +020068#endif
Sylvain Munaut41c98b62022-01-05 21:11:35 +010069 default:
70 /* Don't panic since this will be handled as USB STALL */
71 return -1;
72 }
73}
74
75
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020076static void
Sylvain Munaut41c98b62022-01-05 21:11:35 +010077_usb_fill_feedback_ep(int port)
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020078{
Sylvain Munaut2de84f82022-01-06 08:12:04 +010079 volatile struct usb_ep *ep_regs = _get_ep_regs(USB_EP_E1_FB(port));
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020080
Sylvain Munaut2de84f82022-01-06 08:12:04 +010081 /* Always ensure we're ready to send */
82 if ((ep_regs->bd[0].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA)
83 {
84 uint32_t val = 8192;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020085
Sylvain Munaut2de84f82022-01-06 08:12:04 +010086 /* Add instant bias depending on TX fifo level */
87 unsigned int level = e1_tx_level(port);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020088
Sylvain Munaut2de84f82022-01-06 08:12:04 +010089 if (level < (4 * 16))
90 val += 256;
91 else if (level > (6 * 16))
92 val -= 256;
93
94 /* Fill buffer and submit it */
95 usb_data_write(ep_regs->bd[0].ptr, &val, 4);
96 ep_regs->bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(3);
97 }
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020098}
99
Harald Welte1b89f3b2022-01-13 10:03:42 +0100100static void
101_fill_irq_err(struct ice1usb_irq_err *out, const struct e1_error_count *cur_err)
102{
103 out->crc = cur_err->crc;
104 out->align = cur_err->align;
105 out->ovfl = cur_err->ovfl;
106 out->unfl = cur_err->unfl;
107 out->flags = cur_err->flags;
108}
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200109
Sylvain Munautc9c22a62022-01-12 11:47:08 +0100110static void
111_usb_e1_run(int port)
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200112{
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100113 struct usb_e1_state *usb_e1 = _get_state(port);
Sylvain Munautff44f142022-01-03 20:34:23 +0100114 volatile struct usb_ep *ep_regs;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200115 int bdi;
116
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100117 if (!usb_e1->running)
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200118 return;
119
Sylvain Munautff44f142022-01-03 20:34:23 +0100120 /* Interrupt endpoint */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100121 ep_regs = _get_ep_regs(USB_EP_E1_INT(port));
Sylvain Munautff44f142022-01-03 20:34:23 +0100122
123 if ((ep_regs->bd[0].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA) {
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100124 const struct e1_error_count *cur_err = e1_get_error_count(port);
125 if (memcmp(cur_err, &usb_e1->last_err, sizeof(*cur_err))) {
Harald Welte1b89f3b2022-01-13 10:03:42 +0100126 struct ice1usb_irq errmsg;
127 errmsg.type = ICE1USB_IRQ_T_ERRCNT;
128 _fill_irq_err(&errmsg.u.errors, cur_err);
Harald Welte805f2cf2020-12-14 17:31:03 +0100129 printf("E");
Sylvain Munautff44f142022-01-03 20:34:23 +0100130 usb_data_write(ep_regs->bd[0].ptr, &errmsg, sizeof(errmsg));
131 ep_regs->bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(sizeof(errmsg));
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100132 usb_e1->last_err = *cur_err;
Harald Welte805f2cf2020-12-14 17:31:03 +0100133 }
134 }
135
Sylvain Munautff44f142022-01-03 20:34:23 +0100136 /* Data IN endpoint */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100137 ep_regs = _get_ep_regs(USB_EP_E1_IN(port));
138 bdi = usb_e1->in_bdi;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200139
Sylvain Munautff44f142022-01-03 20:34:23 +0100140 while ((ep_regs->bd[bdi].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA)
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200141 {
Sylvain Munautff44f142022-01-03 20:34:23 +0100142 uint32_t ptr = ep_regs->bd[bdi].ptr;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200143 uint32_t hdr;
Harald Welte2df1f802020-12-14 17:46:53 +0100144 unsigned int pos;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200145
146 /* Error check */
Sylvain Munautff44f142022-01-03 20:34:23 +0100147 if ((ep_regs->bd[bdi].csr & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_ERR)
148 puts("Err EP IN\n");
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200149
150 /* Get some data from E1 */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100151 int n = e1_rx_level(port);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200152
Sylvain Munaut1d987092022-01-05 21:04:09 +0100153 if (n > 32)
154 n = 9;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200155 else if (n > 8)
156 n = 8;
157 else if (!n)
158 break;
159
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100160 n = e1_rx_need_data(port, (ptr >> 2) + 1, n, &pos);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200161
Harald Welte2df1f802020-12-14 17:46:53 +0100162 /* Write header: currently version and pos (mfr/fr number) */
163 hdr = (0 << 28) | (pos & 0xff);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200164 usb_data_write(ptr, &hdr, 4);
165
166 /* Resubmit */
Sylvain Munautff44f142022-01-03 20:34:23 +0100167 ep_regs->bd[bdi].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN((n * 32) + 4);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200168
169 /* Next BDI */
170 bdi ^= 1;
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100171 usb_e1->in_bdi = bdi;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200172 }
173
Sylvain Munautff44f142022-01-03 20:34:23 +0100174 /* Data OUT endpoint */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100175 ep_regs = _get_ep_regs(USB_EP_E1_OUT(port));
176 bdi = usb_e1->out_bdi;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200177
Sylvain Munautff44f142022-01-03 20:34:23 +0100178 while ((ep_regs->bd[bdi].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA)
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200179 {
Sylvain Munautff44f142022-01-03 20:34:23 +0100180 uint32_t ptr = ep_regs->bd[bdi].ptr;
181 uint32_t csr = ep_regs->bd[bdi].csr;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200182 uint32_t hdr;
183
184 /* Error check */
185 if ((csr & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_ERR) {
Sylvain Munautff44f142022-01-03 20:34:23 +0100186 puts("Err EP OUT\n");
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200187 goto refill;
188 }
189
190 /* Grab header */
191 usb_data_read(&hdr, ptr, 4);
192
193 /* Empty data into the FIFO */
Sylvain Munautd108dfb2022-01-03 21:11:05 +0100194 int n = ((int)(csr & USB_BD_LEN_MSK) - 6) / 32;
195 if (n > 0)
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100196 e1_tx_feed_data(port, (ptr >> 2) + 1, n);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200197
198refill:
199 /* Refill it */
Sylvain Munaut1d987092022-01-05 21:04:09 +0100200 ep_regs->bd[bdi].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(292);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200201
202 /* Next BDI */
203 bdi ^= 1;
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100204 usb_e1->out_bdi = bdi;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200205 }
206
Sylvain Munautff44f142022-01-03 20:34:23 +0100207 /* Feedback endpoint */
Sylvain Munaut2de84f82022-01-06 08:12:04 +0100208 _usb_fill_feedback_ep(port);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200209}
210
Sylvain Munautc9c22a62022-01-12 11:47:08 +0100211void
212usb_e1_poll(void)
213{
Sylvain Munautdb0b8102022-09-01 18:43:41 +0200214 for (int i=0; i<NUM_E1_PORTS; i++) {
Sylvain Munautc9c22a62022-01-12 11:47:08 +0100215 e1_poll(i);
216 _usb_e1_run(i);
217 }
218}
219
220
Harald Weltec8271852020-12-14 13:48:09 +0100221static enum usb_fnd_resp
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200222_e1_set_conf(const struct usb_conf_desc *conf)
223{
224 const struct usb_intf_desc *intf;
225
226 printf("e1 set_conf %08x\n", conf);
227 if (!conf)
228 return USB_FND_SUCCESS;
229
Sylvain Munautdb0b8102022-09-01 18:43:41 +0200230 for (int port=0; port<NUM_E1_PORTS; port++)
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100231 {
232 intf = usb_desc_find_intf(conf, USB_INTF_E1(port), 0, NULL);
233 if (!intf)
234 return USB_FND_ERROR;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200235
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100236 printf("e1 set_conf[%d] %08x\n", port, intf);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200237
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100238 usb_ep_boot(intf, USB_EP_E1_IN(port), true);
239 usb_ep_boot(intf, USB_EP_E1_OUT(port), true);
240 usb_ep_boot(intf, USB_EP_E1_FB(port), false);
241 usb_ep_boot(intf, USB_EP_E1_INT(port), false);
242 }
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200243
244 return USB_FND_SUCCESS;
245}
246
Sylvain Munautace09322022-01-10 12:41:49 +0100247static uint32_t
248_tx_config_reg(const struct ice1usb_tx_config *cfg)
Harald Welte9469e042020-12-15 23:09:40 +0100249{
Sylvain Munautace09322022-01-10 12:41:49 +0100250 return ((cfg->mode & 3) << 1) |
Sylvain Munaut3da51512022-01-03 22:12:59 +0100251 ((cfg->timing & 1) << 3) |
252 ((cfg->alarm & 1) << 4) |
Sylvain Munautace09322022-01-10 12:41:49 +0100253 ((cfg->ext_loopback & 3) << 5);
Harald Welte9469e042020-12-15 23:09:40 +0100254}
255
Sylvain Munautace09322022-01-10 12:41:49 +0100256static uint32_t
257_rx_config_reg(const struct ice1usb_rx_config *cfg)
Harald Welte9469e042020-12-15 23:09:40 +0100258{
Sylvain Munautace09322022-01-10 12:41:49 +0100259 return (cfg->mode << 1);
Harald Welte9469e042020-12-15 23:09:40 +0100260}
261
Harald Weltec8271852020-12-14 13:48:09 +0100262static enum usb_fnd_resp
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200263_e1_set_intf(const struct usb_intf_desc *base, const struct usb_intf_desc *sel)
264{
Sylvain Munautff44f142022-01-03 20:34:23 +0100265 volatile struct usb_ep *ep_regs;
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100266 struct usb_e1_state *usb_e1;
267 int port;
Sylvain Munautff44f142022-01-03 20:34:23 +0100268
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100269 /* Is it for E1 interface ? */
Sylvain Munautff44f142022-01-03 20:34:23 +0100270 if ((base->bInterfaceClass != 0xff) || (base->bInterfaceSubClass != 0xe1))
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200271 return USB_FND_CONTINUE;
272
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100273 /* Get matching port (if any) */
274 port = _ifnum2port(base->bInterfaceNumber);
275 if (port < 0)
276 return USB_FND_ERROR;
277
278 usb_e1 = _get_state(port);
279
280 /* Valid setting ? */
Sylvain Munaut96744362022-01-03 17:03:26 +0100281 if (sel->bAlternateSetting > 1)
282 return USB_FND_ERROR;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200283
Sylvain Munaut96744362022-01-03 17:03:26 +0100284 /* Don't do anything if no change */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100285 if (usb_e1->running == (sel->bAlternateSetting != 0))
Sylvain Munaut96744362022-01-03 17:03:26 +0100286 return USB_FND_SUCCESS;
287
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100288 usb_e1->running = (sel->bAlternateSetting != 0);
Sylvain Munaut96744362022-01-03 17:03:26 +0100289
290 /* Reconfigure the endpoints */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100291 usb_ep_reconf(sel, USB_EP_E1_IN(port));
292 usb_ep_reconf(sel, USB_EP_E1_OUT(port));
293 usb_ep_reconf(sel, USB_EP_E1_FB(port));
294 usb_ep_reconf(sel, USB_EP_E1_INT(port));
Sylvain Munaut96744362022-01-03 17:03:26 +0100295
296 /* Update E1 and USB state */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100297 switch (usb_e1->running) {
Sylvain Munaut96744362022-01-03 17:03:26 +0100298 case false:
299 /* Disable E1 rx/tx */
Sylvain Munaut0cc16132022-01-10 13:26:15 +0100300 e1_stop(port);
Harald Weltee6b0fe82020-12-17 22:22:05 +0100301 break;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200302
Sylvain Munaut96744362022-01-03 17:03:26 +0100303 case true:
304 /* Reset and Re-Enable E1 */
Sylvain Munaut0cc16132022-01-10 13:26:15 +0100305 e1_start(port);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200306
Sylvain Munaut96744362022-01-03 17:03:26 +0100307 /* Reset BDI */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100308 usb_e1->in_bdi = 0;
309 usb_e1->out_bdi = 0;
Harald Weltee6b0fe82020-12-17 22:22:05 +0100310
Sylvain Munautff44f142022-01-03 20:34:23 +0100311 /* EP OUT: Queue two buffers */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100312 ep_regs = _get_ep_regs(USB_EP_E1_OUT(port));
Sylvain Munaut1d987092022-01-05 21:04:09 +0100313 ep_regs->bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(292);
314 ep_regs->bd[1].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(292);
Harald Weltee6b0fe82020-12-17 22:22:05 +0100315
Harald Weltee6b0fe82020-12-17 22:22:05 +0100316 break;
Harald Weltee6b0fe82020-12-17 22:22:05 +0100317 }
Harald Welte805f2cf2020-12-14 17:31:03 +0100318
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200319 return USB_FND_SUCCESS;
320}
321
Harald Weltec8271852020-12-14 13:48:09 +0100322static enum usb_fnd_resp
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200323_e1_get_intf(const struct usb_intf_desc *base, uint8_t *alt)
324{
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100325 struct usb_e1_state *usb_e1;
326 int port;
327
328 /* Is it for E1 interface ? */
Sylvain Munautff44f142022-01-03 20:34:23 +0100329 if ((base->bInterfaceClass != 0xff) || (base->bInterfaceSubClass != 0xe1))
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200330 return USB_FND_CONTINUE;
331
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100332 /* Get matching port (if any) */
333 port = _ifnum2port(base->bInterfaceNumber);
334 if (port < 0)
335 return USB_FND_ERROR;
336
337 usb_e1 = _get_state(port);
338
339 /* Return current alt-setting */
340 *alt = usb_e1->running ? 1 : 0;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200341
342 return USB_FND_SUCCESS;
343}
344
Harald Welte9469e042020-12-15 23:09:40 +0100345static bool
346_set_tx_mode_done(struct usb_xfer *xfer)
347{
348 const struct ice1usb_tx_config *cfg = (const struct ice1usb_tx_config *) xfer->data;
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100349 struct usb_ctrl_req *req = xfer->cb_ctx;
350 int port = _ifnum2port(req->wIndex);
351 struct usb_e1_state *usb_e1 = _get_state(port);
352 printf("set_tx_mode[%d] %02x%02x%02x%02x\r\n", port,
Harald Welte9469e042020-12-15 23:09:40 +0100353 xfer->data[0], xfer->data[1], xfer->data[2], xfer->data[3]);
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100354 usb_e1->tx_cfg = *cfg;
Sylvain Munautace09322022-01-10 12:41:49 +0100355 e1_tx_config(port, _tx_config_reg(cfg));
Harald Welte9469e042020-12-15 23:09:40 +0100356 return true;
357}
358
359static bool
360_set_rx_mode_done(struct usb_xfer *xfer)
361{
362 const struct ice1usb_rx_config *cfg = (const struct ice1usb_rx_config *) xfer->data;
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100363 struct usb_ctrl_req *req = xfer->cb_ctx;
364 int port = _ifnum2port(req->wIndex);
365 struct usb_e1_state *usb_e1 = _get_state(port);
366 printf("set_rx_mode[%d] %02x\r\n", port, xfer->data[0]);
367 usb_e1->rx_cfg = *cfg;
Sylvain Munautace09322022-01-10 12:41:49 +0100368 e1_rx_config(port, _rx_config_reg(cfg));
Harald Welte9469e042020-12-15 23:09:40 +0100369 return true;
370}
371
Harald Welte9469e042020-12-15 23:09:40 +0100372static enum usb_fnd_resp
Sylvain Munautcaf8cf92022-01-12 13:35:12 +0100373_e1_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer)
Harald Welte9469e042020-12-15 23:09:40 +0100374{
Harald Welte1b89f3b2022-01-13 10:03:42 +0100375 const struct e1_error_count *cur_err;
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100376 struct usb_e1_state *usb_e1;
377 int port;
Harald Welte9469e042020-12-15 23:09:40 +0100378
Sylvain Munautcaf8cf92022-01-12 13:35:12 +0100379 /* Check it's for an E1 interface */
380 if (USB_REQ_TYPE_RCPT(req) != (USB_REQ_TYPE_VENDOR | USB_REQ_RCPT_INTF))
381 return USB_FND_CONTINUE;
382
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100383 /* Get matching port (if any) */
384 port = _ifnum2port(req->wIndex);
385 if (port < 0)
386 return USB_FND_CONTINUE;
387
388 usb_e1 = _get_state(port);
389
390 /* Process request */
Harald Welte9469e042020-12-15 23:09:40 +0100391 switch (req->bRequest) {
392 case ICE1USB_INTF_GET_CAPABILITIES:
393 /* no optional capabilities yet */
394 xfer->len = 0;
395 break;
396 case ICE1USB_INTF_SET_TX_CFG:
397 if (req->wLength < sizeof(struct ice1usb_tx_config))
398 return USB_FND_ERROR;
399 xfer->cb_done = _set_tx_mode_done;
400 xfer->cb_ctx = req;
401 xfer->len = sizeof(struct ice1usb_tx_config);
402 break;
403 case ICE1USB_INTF_GET_TX_CFG:
404 if (req->wLength < sizeof(struct ice1usb_tx_config))
405 return USB_FND_ERROR;
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100406 memcpy(xfer->data, &usb_e1->tx_cfg, sizeof(struct ice1usb_tx_config));
Harald Welte9469e042020-12-15 23:09:40 +0100407 xfer->len = sizeof(struct ice1usb_tx_config);
408 break;
409 case ICE1USB_INTF_SET_RX_CFG:
410 if (req->wLength < sizeof(struct ice1usb_rx_config))
411 return USB_FND_ERROR;
412 xfer->cb_done = _set_rx_mode_done;
413 xfer->cb_ctx = req;
414 xfer->len = sizeof(struct ice1usb_rx_config);
415 break;
416 case ICE1USB_INTF_GET_RX_CFG:
417 if (req->wLength < sizeof(struct ice1usb_rx_config))
418 return USB_FND_ERROR;
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100419 memcpy(xfer->data, &usb_e1->rx_cfg, sizeof(struct ice1usb_rx_config));
Harald Welte9469e042020-12-15 23:09:40 +0100420 xfer->len = sizeof(struct ice1usb_rx_config);
421 break;
Harald Welte1b89f3b2022-01-13 10:03:42 +0100422 case ICE1USB_INTF_GET_ERRORS:
423 if (req->wLength < sizeof(struct ice1usb_irq_err))
424 return USB_FND_ERROR;
425 cur_err = e1_get_error_count(port);
426 _fill_irq_err((struct ice1usb_irq_err *)xfer->data, cur_err);
427 xfer->len = sizeof(struct ice1usb_irq_err);
428 break;
Harald Welte9469e042020-12-15 23:09:40 +0100429 default:
430 return USB_FND_ERROR;
431 }
432
433 return USB_FND_SUCCESS;
434}
435
Harald Welte9469e042020-12-15 23:09:40 +0100436
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200437static struct usb_fn_drv _e1_drv = {
438 .set_conf = _e1_set_conf,
439 .set_intf = _e1_set_intf,
440 .get_intf = _e1_get_intf,
Harald Welte9469e042020-12-15 23:09:40 +0100441 .ctrl_req = _e1_ctrl_req,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200442};
443
444void
445usb_e1_init(void)
446{
Sylvain Munaut0cc16132022-01-10 13:26:15 +0100447 uint32_t rx_cr = _rx_config_reg(&rx_cfg_default);
448 uint32_t tx_cr = _tx_config_reg(&tx_cfg_default);
449
Sylvain Munautdb0b8102022-09-01 18:43:41 +0200450 for (int i=0; i<NUM_E1_PORTS; i++) {
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100451 struct usb_e1_state *usb_e1 = _get_state(i);
452 memset(usb_e1, 0x00, sizeof(struct usb_e1_state));
453 usb_e1->tx_cfg = tx_cfg_default;
454 usb_e1->rx_cfg = rx_cfg_default;
Sylvain Munaut0cc16132022-01-10 13:26:15 +0100455 e1_init(i, rx_cr, tx_cr);
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100456 }
457
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200458 usb_register_function_driver(&_e1_drv);
459}