blob: 6d0d3cfde5ba513cca5edb1f4991315fe19d4031 [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
32static struct usb_e1_state g_usb_e1[2];
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{
56 if ((port < 0) || (port > 1))
57 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;
66 case USB_INTF_E1(1): return 1;
67 default:
68 /* Don't panic since this will be handled as USB STALL */
69 return -1;
70 }
71}
72
73
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020074static void
Sylvain Munaut41c98b62022-01-05 21:11:35 +010075_usb_fill_feedback_ep(int port)
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020076{
Sylvain Munaut2de84f82022-01-06 08:12:04 +010077 volatile struct usb_ep *ep_regs = _get_ep_regs(USB_EP_E1_FB(port));
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020078
Sylvain Munaut2de84f82022-01-06 08:12:04 +010079 /* Always ensure we're ready to send */
80 if ((ep_regs->bd[0].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA)
81 {
82 uint32_t val = 8192;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020083
Sylvain Munaut2de84f82022-01-06 08:12:04 +010084 /* Add instant bias depending on TX fifo level */
85 unsigned int level = e1_tx_level(port);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020086
Sylvain Munaut2de84f82022-01-06 08:12:04 +010087 if (level < (4 * 16))
88 val += 256;
89 else if (level > (6 * 16))
90 val -= 256;
91
92 /* Fill buffer and submit it */
93 usb_data_write(ep_regs->bd[0].ptr, &val, 4);
94 ep_regs->bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(3);
95 }
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020096}
97
98
Sylvain Munautc9c22a62022-01-12 11:47:08 +010099static void
100_usb_e1_run(int port)
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200101{
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100102 struct usb_e1_state *usb_e1 = _get_state(port);
Sylvain Munautff44f142022-01-03 20:34:23 +0100103 volatile struct usb_ep *ep_regs;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200104 int bdi;
105
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100106 if (!usb_e1->running)
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200107 return;
108
Sylvain Munautff44f142022-01-03 20:34:23 +0100109 /* Interrupt endpoint */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100110 ep_regs = _get_ep_regs(USB_EP_E1_INT(port));
Sylvain Munautff44f142022-01-03 20:34:23 +0100111
112 if ((ep_regs->bd[0].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA) {
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100113 const struct e1_error_count *cur_err = e1_get_error_count(port);
114 if (memcmp(cur_err, &usb_e1->last_err, sizeof(*cur_err))) {
Harald Welte805f2cf2020-12-14 17:31:03 +0100115 struct ice1usb_irq errmsg = {
116 .type = ICE1USB_IRQ_T_ERRCNT,
117 .u = {
118 .errors = {
119 .crc = cur_err->crc,
120 .align = cur_err->align,
121 .ovfl = cur_err->ovfl,
122 .unfl = cur_err->unfl,
123 .flags = cur_err->flags,
124 }
125 }
126 };
127 printf("E");
Sylvain Munautff44f142022-01-03 20:34:23 +0100128 usb_data_write(ep_regs->bd[0].ptr, &errmsg, sizeof(errmsg));
129 ep_regs->bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(sizeof(errmsg));
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100130 usb_e1->last_err = *cur_err;
Harald Welte805f2cf2020-12-14 17:31:03 +0100131 }
132 }
133
Sylvain Munautff44f142022-01-03 20:34:23 +0100134 /* Data IN endpoint */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100135 ep_regs = _get_ep_regs(USB_EP_E1_IN(port));
136 bdi = usb_e1->in_bdi;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200137
Sylvain Munautff44f142022-01-03 20:34:23 +0100138 while ((ep_regs->bd[bdi].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA)
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200139 {
Sylvain Munautff44f142022-01-03 20:34:23 +0100140 uint32_t ptr = ep_regs->bd[bdi].ptr;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200141 uint32_t hdr;
Harald Welte2df1f802020-12-14 17:46:53 +0100142 unsigned int pos;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200143
144 /* Error check */
Sylvain Munautff44f142022-01-03 20:34:23 +0100145 if ((ep_regs->bd[bdi].csr & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_ERR)
146 puts("Err EP IN\n");
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200147
148 /* Get some data from E1 */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100149 int n = e1_rx_level(port);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200150
Sylvain Munaut1d987092022-01-05 21:04:09 +0100151 if (n > 32)
152 n = 9;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200153 else if (n > 8)
154 n = 8;
155 else if (!n)
156 break;
157
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100158 n = e1_rx_need_data(port, (ptr >> 2) + 1, n, &pos);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200159
Harald Welte2df1f802020-12-14 17:46:53 +0100160 /* Write header: currently version and pos (mfr/fr number) */
161 hdr = (0 << 28) | (pos & 0xff);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200162 usb_data_write(ptr, &hdr, 4);
163
164 /* Resubmit */
Sylvain Munautff44f142022-01-03 20:34:23 +0100165 ep_regs->bd[bdi].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN((n * 32) + 4);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200166
167 /* Next BDI */
168 bdi ^= 1;
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100169 usb_e1->in_bdi = bdi;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200170 }
171
Sylvain Munautff44f142022-01-03 20:34:23 +0100172 /* Data OUT endpoint */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100173 ep_regs = _get_ep_regs(USB_EP_E1_OUT(port));
174 bdi = usb_e1->out_bdi;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200175
Sylvain Munautff44f142022-01-03 20:34:23 +0100176 while ((ep_regs->bd[bdi].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA)
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200177 {
Sylvain Munautff44f142022-01-03 20:34:23 +0100178 uint32_t ptr = ep_regs->bd[bdi].ptr;
179 uint32_t csr = ep_regs->bd[bdi].csr;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200180 uint32_t hdr;
181
182 /* Error check */
183 if ((csr & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_ERR) {
Sylvain Munautff44f142022-01-03 20:34:23 +0100184 puts("Err EP OUT\n");
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200185 goto refill;
186 }
187
188 /* Grab header */
189 usb_data_read(&hdr, ptr, 4);
190
191 /* Empty data into the FIFO */
Sylvain Munautd108dfb2022-01-03 21:11:05 +0100192 int n = ((int)(csr & USB_BD_LEN_MSK) - 6) / 32;
193 if (n > 0)
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100194 e1_tx_feed_data(port, (ptr >> 2) + 1, n);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200195
196refill:
197 /* Refill it */
Sylvain Munaut1d987092022-01-05 21:04:09 +0100198 ep_regs->bd[bdi].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(292);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200199
200 /* Next BDI */
201 bdi ^= 1;
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100202 usb_e1->out_bdi = bdi;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200203
204 static int x = 0;
205 if ((x++ & 0xff) == 0xff)
206 puts(".");
207 }
208
Sylvain Munautff44f142022-01-03 20:34:23 +0100209 /* Feedback endpoint */
Sylvain Munaut2de84f82022-01-06 08:12:04 +0100210 _usb_fill_feedback_ep(port);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200211}
212
Sylvain Munautc9c22a62022-01-12 11:47:08 +0100213void
214usb_e1_poll(void)
215{
216 for (int i=0; i<2; i++) {
217 e1_poll(i);
218 _usb_e1_run(i);
219 }
220}
221
222
Harald Weltec8271852020-12-14 13:48:09 +0100223static enum usb_fnd_resp
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200224_e1_set_conf(const struct usb_conf_desc *conf)
225{
226 const struct usb_intf_desc *intf;
227
228 printf("e1 set_conf %08x\n", conf);
229 if (!conf)
230 return USB_FND_SUCCESS;
231
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100232 for (int port=0; port<2; port++)
233 {
234 intf = usb_desc_find_intf(conf, USB_INTF_E1(port), 0, NULL);
235 if (!intf)
236 return USB_FND_ERROR;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200237
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100238 printf("e1 set_conf[%d] %08x\n", port, intf);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200239
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100240 usb_ep_boot(intf, USB_EP_E1_IN(port), true);
241 usb_ep_boot(intf, USB_EP_E1_OUT(port), true);
242 usb_ep_boot(intf, USB_EP_E1_FB(port), false);
243 usb_ep_boot(intf, USB_EP_E1_INT(port), false);
244 }
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200245
246 return USB_FND_SUCCESS;
247}
248
Sylvain Munautace09322022-01-10 12:41:49 +0100249static uint32_t
250_tx_config_reg(const struct ice1usb_tx_config *cfg)
Harald Welte9469e042020-12-15 23:09:40 +0100251{
Sylvain Munautace09322022-01-10 12:41:49 +0100252 return ((cfg->mode & 3) << 1) |
Sylvain Munaut3da51512022-01-03 22:12:59 +0100253 ((cfg->timing & 1) << 3) |
254 ((cfg->alarm & 1) << 4) |
Sylvain Munautace09322022-01-10 12:41:49 +0100255 ((cfg->ext_loopback & 3) << 5);
Harald Welte9469e042020-12-15 23:09:40 +0100256}
257
Sylvain Munautace09322022-01-10 12:41:49 +0100258static uint32_t
259_rx_config_reg(const struct ice1usb_rx_config *cfg)
Harald Welte9469e042020-12-15 23:09:40 +0100260{
Sylvain Munautace09322022-01-10 12:41:49 +0100261 return (cfg->mode << 1);
Harald Welte9469e042020-12-15 23:09:40 +0100262}
263
Harald Weltec8271852020-12-14 13:48:09 +0100264static enum usb_fnd_resp
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200265_e1_set_intf(const struct usb_intf_desc *base, const struct usb_intf_desc *sel)
266{
Sylvain Munautff44f142022-01-03 20:34:23 +0100267 volatile struct usb_ep *ep_regs;
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100268 struct usb_e1_state *usb_e1;
269 int port;
Sylvain Munautff44f142022-01-03 20:34:23 +0100270
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100271 /* Is it for E1 interface ? */
Sylvain Munautff44f142022-01-03 20:34:23 +0100272 if ((base->bInterfaceClass != 0xff) || (base->bInterfaceSubClass != 0xe1))
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200273 return USB_FND_CONTINUE;
274
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100275 /* Get matching port (if any) */
276 port = _ifnum2port(base->bInterfaceNumber);
277 if (port < 0)
278 return USB_FND_ERROR;
279
280 usb_e1 = _get_state(port);
281
282 /* Valid setting ? */
Sylvain Munaut96744362022-01-03 17:03:26 +0100283 if (sel->bAlternateSetting > 1)
284 return USB_FND_ERROR;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200285
Sylvain Munaut96744362022-01-03 17:03:26 +0100286 /* Don't do anything if no change */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100287 if (usb_e1->running == (sel->bAlternateSetting != 0))
Sylvain Munaut96744362022-01-03 17:03:26 +0100288 return USB_FND_SUCCESS;
289
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100290 usb_e1->running = (sel->bAlternateSetting != 0);
Sylvain Munaut96744362022-01-03 17:03:26 +0100291
292 /* Reconfigure the endpoints */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100293 usb_ep_reconf(sel, USB_EP_E1_IN(port));
294 usb_ep_reconf(sel, USB_EP_E1_OUT(port));
295 usb_ep_reconf(sel, USB_EP_E1_FB(port));
296 usb_ep_reconf(sel, USB_EP_E1_INT(port));
Sylvain Munaut96744362022-01-03 17:03:26 +0100297
298 /* Update E1 and USB state */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100299 switch (usb_e1->running) {
Sylvain Munaut96744362022-01-03 17:03:26 +0100300 case false:
301 /* Disable E1 rx/tx */
Sylvain Munaut0cc16132022-01-10 13:26:15 +0100302 e1_stop(port);
Harald Weltee6b0fe82020-12-17 22:22:05 +0100303 break;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200304
Sylvain Munaut96744362022-01-03 17:03:26 +0100305 case true:
306 /* Reset and Re-Enable E1 */
Sylvain Munaut0cc16132022-01-10 13:26:15 +0100307 e1_start(port);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200308
Sylvain Munaut96744362022-01-03 17:03:26 +0100309 /* Reset BDI */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100310 usb_e1->in_bdi = 0;
311 usb_e1->out_bdi = 0;
Harald Weltee6b0fe82020-12-17 22:22:05 +0100312
Sylvain Munautff44f142022-01-03 20:34:23 +0100313 /* EP OUT: Queue two buffers */
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100314 ep_regs = _get_ep_regs(USB_EP_E1_OUT(port));
Sylvain Munaut1d987092022-01-05 21:04:09 +0100315 ep_regs->bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(292);
316 ep_regs->bd[1].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(292);
Harald Weltee6b0fe82020-12-17 22:22:05 +0100317
Harald Weltee6b0fe82020-12-17 22:22:05 +0100318 break;
Harald Weltee6b0fe82020-12-17 22:22:05 +0100319 }
Harald Welte805f2cf2020-12-14 17:31:03 +0100320
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200321 return USB_FND_SUCCESS;
322}
323
Harald Weltec8271852020-12-14 13:48:09 +0100324static enum usb_fnd_resp
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200325_e1_get_intf(const struct usb_intf_desc *base, uint8_t *alt)
326{
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100327 struct usb_e1_state *usb_e1;
328 int port;
329
330 /* Is it for E1 interface ? */
Sylvain Munautff44f142022-01-03 20:34:23 +0100331 if ((base->bInterfaceClass != 0xff) || (base->bInterfaceSubClass != 0xe1))
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200332 return USB_FND_CONTINUE;
333
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100334 /* Get matching port (if any) */
335 port = _ifnum2port(base->bInterfaceNumber);
336 if (port < 0)
337 return USB_FND_ERROR;
338
339 usb_e1 = _get_state(port);
340
341 /* Return current alt-setting */
342 *alt = usb_e1->running ? 1 : 0;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200343
344 return USB_FND_SUCCESS;
345}
346
Harald Welte9469e042020-12-15 23:09:40 +0100347static bool
348_set_tx_mode_done(struct usb_xfer *xfer)
349{
350 const struct ice1usb_tx_config *cfg = (const struct ice1usb_tx_config *) xfer->data;
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100351 struct usb_ctrl_req *req = xfer->cb_ctx;
352 int port = _ifnum2port(req->wIndex);
353 struct usb_e1_state *usb_e1 = _get_state(port);
354 printf("set_tx_mode[%d] %02x%02x%02x%02x\r\n", port,
Harald Welte9469e042020-12-15 23:09:40 +0100355 xfer->data[0], xfer->data[1], xfer->data[2], xfer->data[3]);
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100356 usb_e1->tx_cfg = *cfg;
Sylvain Munautace09322022-01-10 12:41:49 +0100357 e1_tx_config(port, _tx_config_reg(cfg));
Harald Welte9469e042020-12-15 23:09:40 +0100358 return true;
359}
360
361static bool
362_set_rx_mode_done(struct usb_xfer *xfer)
363{
364 const struct ice1usb_rx_config *cfg = (const struct ice1usb_rx_config *) xfer->data;
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100365 struct usb_ctrl_req *req = xfer->cb_ctx;
366 int port = _ifnum2port(req->wIndex);
367 struct usb_e1_state *usb_e1 = _get_state(port);
368 printf("set_rx_mode[%d] %02x\r\n", port, xfer->data[0]);
369 usb_e1->rx_cfg = *cfg;
Sylvain Munautace09322022-01-10 12:41:49 +0100370 e1_rx_config(port, _rx_config_reg(cfg));
Harald Welte9469e042020-12-15 23:09:40 +0100371 return true;
372}
373
Harald Welte9469e042020-12-15 23:09:40 +0100374static enum usb_fnd_resp
Sylvain Munautcaf8cf92022-01-12 13:35:12 +0100375_e1_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer)
Harald Welte9469e042020-12-15 23:09:40 +0100376{
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100377 struct usb_e1_state *usb_e1;
378 int port;
Harald Welte9469e042020-12-15 23:09:40 +0100379
Sylvain Munautcaf8cf92022-01-12 13:35:12 +0100380 /* Check it's for an E1 interface */
381 if (USB_REQ_TYPE_RCPT(req) != (USB_REQ_TYPE_VENDOR | USB_REQ_RCPT_INTF))
382 return USB_FND_CONTINUE;
383
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100384 /* Get matching port (if any) */
385 port = _ifnum2port(req->wIndex);
386 if (port < 0)
387 return USB_FND_CONTINUE;
388
389 usb_e1 = _get_state(port);
390
391 /* Process request */
Harald Welte9469e042020-12-15 23:09:40 +0100392 switch (req->bRequest) {
393 case ICE1USB_INTF_GET_CAPABILITIES:
394 /* no optional capabilities yet */
395 xfer->len = 0;
396 break;
397 case ICE1USB_INTF_SET_TX_CFG:
398 if (req->wLength < sizeof(struct ice1usb_tx_config))
399 return USB_FND_ERROR;
400 xfer->cb_done = _set_tx_mode_done;
401 xfer->cb_ctx = req;
402 xfer->len = sizeof(struct ice1usb_tx_config);
403 break;
404 case ICE1USB_INTF_GET_TX_CFG:
405 if (req->wLength < sizeof(struct ice1usb_tx_config))
406 return USB_FND_ERROR;
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100407 memcpy(xfer->data, &usb_e1->tx_cfg, sizeof(struct ice1usb_tx_config));
Harald Welte9469e042020-12-15 23:09:40 +0100408 xfer->len = sizeof(struct ice1usb_tx_config);
409 break;
410 case ICE1USB_INTF_SET_RX_CFG:
411 if (req->wLength < sizeof(struct ice1usb_rx_config))
412 return USB_FND_ERROR;
413 xfer->cb_done = _set_rx_mode_done;
414 xfer->cb_ctx = req;
415 xfer->len = sizeof(struct ice1usb_rx_config);
416 break;
417 case ICE1USB_INTF_GET_RX_CFG:
418 if (req->wLength < sizeof(struct ice1usb_rx_config))
419 return USB_FND_ERROR;
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100420 memcpy(xfer->data, &usb_e1->rx_cfg, sizeof(struct ice1usb_rx_config));
Harald Welte9469e042020-12-15 23:09:40 +0100421 xfer->len = sizeof(struct ice1usb_rx_config);
422 break;
423 default:
424 return USB_FND_ERROR;
425 }
426
427 return USB_FND_SUCCESS;
428}
429
Harald Welte9469e042020-12-15 23:09:40 +0100430
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200431static struct usb_fn_drv _e1_drv = {
432 .set_conf = _e1_set_conf,
433 .set_intf = _e1_set_intf,
434 .get_intf = _e1_get_intf,
Harald Welte9469e042020-12-15 23:09:40 +0100435 .ctrl_req = _e1_ctrl_req,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200436};
437
438void
439usb_e1_init(void)
440{
Sylvain Munaut0cc16132022-01-10 13:26:15 +0100441 uint32_t rx_cr = _rx_config_reg(&rx_cfg_default);
442 uint32_t tx_cr = _tx_config_reg(&tx_cfg_default);
443
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100444 for (int i=0; i<2; i++) {
445 struct usb_e1_state *usb_e1 = _get_state(i);
446 memset(usb_e1, 0x00, sizeof(struct usb_e1_state));
447 usb_e1->tx_cfg = tx_cfg_default;
448 usb_e1->rx_cfg = rx_cfg_default;
Sylvain Munaut0cc16132022-01-10 13:26:15 +0100449 e1_init(i, rx_cr, tx_cr);
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100450 }
451
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200452 usb_register_function_driver(&_e1_drv);
453}