fw/e1-tracer: Additional USB configuration for "osmo-e1d compatible mode"
This adds a second USB configuration to the e1-tracer firmware. This configuration is closer to the USB configuration of an icE1usb and hence paves the way for using osmo-e1d with the tracer. The main conceptual difference between the existing "legacy" configuration and this new "e1d compatible" configuration is to have two USB interfaces, one for each direction of the traced E1 interface. Each interface has its own separate two altsettings, one for the disabled and one for the enabled state. Unmodified osmo-e1d will not work straight away with this, as it expects ISO OUT and ISU Feedback endpoints, which a pure rx-only tracing device of course doesn't have. Related: OS#5733 Change-Id: I97062b9f12317b1b9b3855409c2380108cb921ff
This commit is contained in:
parent
fced9a7147
commit
65324160a7
|
@ -13,10 +13,9 @@
|
|||
#define num_elem(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
|
||||
/* Legacy Configuration */
|
||||
static const struct {
|
||||
/* Configuration */
|
||||
struct usb_conf_desc conf;
|
||||
|
||||
/* E1 */
|
||||
struct {
|
||||
struct {
|
||||
|
@ -30,7 +29,6 @@ static const struct {
|
|||
struct usb_ep_desc ep_data_in1;
|
||||
} __attribute__ ((packed)) on;
|
||||
} __attribute__ ((packed)) e1;
|
||||
|
||||
/* DFU Runtime */
|
||||
struct {
|
||||
struct usb_intf_desc intf;
|
||||
|
@ -130,8 +128,161 @@ static const struct {
|
|||
},
|
||||
};
|
||||
|
||||
/* "icE1usb" compatible Configuration */
|
||||
static const struct {
|
||||
struct usb_conf_desc conf;
|
||||
/* Interface / Direction A */
|
||||
struct {
|
||||
struct {
|
||||
struct usb_intf_desc intf;
|
||||
struct usb_ep_desc ep_data_in0;
|
||||
} __attribute__ ((packed)) off;
|
||||
struct {
|
||||
struct usb_intf_desc intf;
|
||||
struct usb_ep_desc ep_data_in0;
|
||||
} __attribute__ ((packed)) on;
|
||||
} __attribute__ ((packed)) a;
|
||||
/* Interface / Direction B */
|
||||
struct {
|
||||
struct {
|
||||
struct usb_intf_desc intf;
|
||||
struct usb_ep_desc ep_data_in1;
|
||||
} __attribute__ ((packed)) off;
|
||||
struct {
|
||||
struct usb_intf_desc intf;
|
||||
struct usb_ep_desc ep_data_in1;
|
||||
} __attribute__ ((packed)) on;
|
||||
} __attribute__ ((packed)) b;
|
||||
/* DFU Runtime */
|
||||
struct {
|
||||
struct usb_intf_desc intf;
|
||||
struct usb_dfu_func_desc func;
|
||||
} __attribute__ ((packed)) dfu;
|
||||
} __attribute__ ((packed)) _app_conf_desc_e1d = {
|
||||
.conf = {
|
||||
.bLength = sizeof(struct usb_conf_desc),
|
||||
.bDescriptorType = USB_DT_CONF,
|
||||
.wTotalLength = sizeof(_app_conf_desc_e1d),
|
||||
.bNumInterfaces = 3,
|
||||
.bConfigurationValue = 2,
|
||||
.iConfiguration = 7,
|
||||
.bmAttributes = 0x80,
|
||||
.bMaxPower = 0x32, /* 100 mA */
|
||||
},
|
||||
.a = {
|
||||
.off = {
|
||||
.intf = {
|
||||
.bLength = sizeof(struct usb_intf_desc),
|
||||
.bDescriptorType = USB_DT_INTF,
|
||||
.bInterfaceNumber = 0,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 1,
|
||||
.bInterfaceClass = 0xff,
|
||||
.bInterfaceSubClass = 0xe1,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.iInterface = 8,
|
||||
},
|
||||
.ep_data_in0 = {
|
||||
.bLength = sizeof(struct usb_ep_desc),
|
||||
.bDescriptorType = USB_DT_EP,
|
||||
.bEndpointAddress = 0x81,
|
||||
.bmAttributes = 0x05,
|
||||
.wMaxPacketSize = 0,
|
||||
.bInterval = 1,
|
||||
},
|
||||
},
|
||||
.on = {
|
||||
.intf = {
|
||||
.bLength = sizeof(struct usb_intf_desc),
|
||||
.bDescriptorType = USB_DT_INTF,
|
||||
.bInterfaceNumber = 0,
|
||||
.bAlternateSetting = 1,
|
||||
.bNumEndpoints = 1,
|
||||
.bInterfaceClass = 0xff,
|
||||
.bInterfaceSubClass = 0xe1,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.iInterface = 8,
|
||||
},
|
||||
.ep_data_in0 = {
|
||||
.bLength = sizeof(struct usb_ep_desc),
|
||||
.bDescriptorType = USB_DT_EP,
|
||||
.bEndpointAddress = 0x81,
|
||||
.bmAttributes = 0x05,
|
||||
.wMaxPacketSize = 388,
|
||||
.bInterval = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.b = {
|
||||
.off = {
|
||||
.intf = {
|
||||
.bLength = sizeof(struct usb_intf_desc),
|
||||
.bDescriptorType = USB_DT_INTF,
|
||||
.bInterfaceNumber = 1,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 1,
|
||||
.bInterfaceClass = 0xff,
|
||||
.bInterfaceSubClass = 0xe1,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.iInterface = 9,
|
||||
},
|
||||
.ep_data_in1 = {
|
||||
.bLength = sizeof(struct usb_ep_desc),
|
||||
.bDescriptorType = USB_DT_EP,
|
||||
.bEndpointAddress = 0x82,
|
||||
.bmAttributes = 0x05,
|
||||
.wMaxPacketSize = 0,
|
||||
.bInterval = 1,
|
||||
},
|
||||
},
|
||||
.on = {
|
||||
.intf = {
|
||||
.bLength = sizeof(struct usb_intf_desc),
|
||||
.bDescriptorType = USB_DT_INTF,
|
||||
.bInterfaceNumber = 1,
|
||||
.bAlternateSetting = 1,
|
||||
.bNumEndpoints = 1,
|
||||
.bInterfaceClass = 0xff,
|
||||
.bInterfaceSubClass = 0xe1,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.iInterface = 9,
|
||||
},
|
||||
.ep_data_in1 = {
|
||||
.bLength = sizeof(struct usb_ep_desc),
|
||||
.bDescriptorType = USB_DT_EP,
|
||||
.bEndpointAddress = 0x82,
|
||||
.bmAttributes = 0x05,
|
||||
.wMaxPacketSize = 388,
|
||||
.bInterval = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.dfu = {
|
||||
.intf = {
|
||||
.bLength = sizeof(struct usb_intf_desc),
|
||||
.bDescriptorType = USB_DT_INTF,
|
||||
.bInterfaceNumber = 2,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 0,
|
||||
.bInterfaceClass = 0xfe,
|
||||
.bInterfaceSubClass = 0x01,
|
||||
.bInterfaceProtocol = 0x01,
|
||||
.iInterface = 6,
|
||||
},
|
||||
.func = {
|
||||
.bLength = sizeof(struct usb_dfu_func_desc),
|
||||
.bDescriptorType = USB_DFU_DT_FUNC,
|
||||
.bmAttributes = 0x0d,
|
||||
.wDetachTimeOut = 1000,
|
||||
.wTransferSize = 4096,
|
||||
.bcdDFUVersion = 0x0101,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct usb_conf_desc * const _conf_desc_array[] = {
|
||||
&_app_conf_desc.conf,
|
||||
&_app_conf_desc_e1d.conf,
|
||||
};
|
||||
|
||||
static const struct usb_dev_desc _dev_desc = {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* usb_e1.c
|
||||
*
|
||||
* Copyright (C) 2019-2020 Sylvain Munaut <tnt@246tNt.com>
|
||||
* Copyright (C) 2022 Harald Welte <laforge@osmocom.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
|
@ -17,7 +18,7 @@
|
|||
#include "misc.h"
|
||||
|
||||
struct {
|
||||
bool running;
|
||||
bool running[2];
|
||||
int in_bdi[2];
|
||||
} g_usb_e1;
|
||||
|
||||
|
@ -35,12 +36,12 @@ usb_e1_run(void)
|
|||
int chan;
|
||||
int bdi;
|
||||
|
||||
if (!g_usb_e1.running)
|
||||
return;
|
||||
|
||||
/* EP[1-2] IN */
|
||||
for (chan=0; chan<2; chan++)
|
||||
{
|
||||
if (!g_usb_e1.running[chan])
|
||||
continue;
|
||||
|
||||
bdi = g_usb_e1.in_bdi[chan];
|
||||
|
||||
while ((usb_ep_regs[1+chan].in.bd[bdi].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA)
|
||||
|
@ -112,12 +113,17 @@ _find_intf(const struct usb_conf_desc *conf, uint8_t idx)
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct usb_conf_desc *last_conf;
|
||||
|
||||
enum usb_fnd_resp
|
||||
_e1_set_conf(const struct usb_conf_desc *conf)
|
||||
{
|
||||
const struct usb_intf_desc *intf;
|
||||
|
||||
printf("e1 set_conf %08x\n", conf);
|
||||
|
||||
last_conf = conf;
|
||||
if (!conf)
|
||||
return USB_FND_SUCCESS;
|
||||
|
||||
|
@ -133,81 +139,123 @@ _e1_set_conf(const struct usb_conf_desc *conf)
|
|||
return USB_FND_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
disable_chan(uint8_t chan)
|
||||
{
|
||||
/* Already stopped ? */
|
||||
if (!g_usb_e1.running[chan])
|
||||
return;
|
||||
|
||||
/* Update state */
|
||||
g_usb_e1.running[chan] = false;
|
||||
|
||||
/* Stop E1 */
|
||||
e1_stop_one(chan);
|
||||
|
||||
/* Disable end-points */
|
||||
usb_ep_regs[chan+1].in.status = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
enable_chan(uint8_t chan)
|
||||
{
|
||||
/* Already running ? */
|
||||
if (g_usb_e1.running[chan])
|
||||
return;
|
||||
|
||||
/* Update state */
|
||||
g_usb_e1.running[chan] = true;
|
||||
|
||||
/* Reset buffer pointers */
|
||||
g_usb_e1.in_bdi[chan] = 0;
|
||||
|
||||
/* Configure EP1 IN / EP2 IN */
|
||||
usb_ep_regs[chan+1].in.status = USB_EP_TYPE_ISOC | USB_EP_BD_DUAL; /* Type=Isochronous, dual buffered */
|
||||
|
||||
/* EP1 IN: Prepare two buffers */
|
||||
usb_ep_regs[chan+1].in.bd[0].ptr = 256 + (chan * 2 + 0) * 388;
|
||||
usb_ep_regs[chan+1].in.bd[0].csr = 0;
|
||||
|
||||
usb_ep_regs[chan+1].in.bd[1].ptr = 256 + (chan * 2 + 1) * 388;
|
||||
usb_ep_regs[chan+1].in.bd[1].csr = 0;
|
||||
|
||||
/* Start E1 */
|
||||
e1_start_one(chan);
|
||||
}
|
||||
|
||||
enum usb_fnd_resp
|
||||
_e1_set_intf(const struct usb_intf_desc *base, const struct usb_intf_desc *sel)
|
||||
{
|
||||
if (base->bInterfaceNumber != 0)
|
||||
return USB_FND_CONTINUE;
|
||||
if (!last_conf || last_conf->bConfigurationValue == 1) {
|
||||
/* Legacy Configuration */
|
||||
|
||||
if (sel->bAlternateSetting == 0)
|
||||
{
|
||||
/* Already stopped ? */
|
||||
if (!g_usb_e1.running)
|
||||
return USB_FND_SUCCESS;
|
||||
if (base->bInterfaceNumber != 0)
|
||||
return USB_FND_CONTINUE;
|
||||
|
||||
/* Update state */
|
||||
g_usb_e1.running = false;
|
||||
if (sel->bAlternateSetting == 0)
|
||||
{
|
||||
disable_chan(0);
|
||||
disable_chan(1);
|
||||
}
|
||||
else if (sel->bAlternateSetting == 1)
|
||||
{
|
||||
enable_chan(0);
|
||||
enable_chan(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unknown */
|
||||
return USB_FND_ERROR;
|
||||
}
|
||||
} else if (last_conf && last_conf->bConfigurationValue == 2) {
|
||||
/* e1d compatible configuration */
|
||||
|
||||
/* Stop E1 */
|
||||
e1_stop_one(0);
|
||||
e1_stop_one(1);
|
||||
|
||||
/* Disable end-points */
|
||||
usb_ep_regs[1].in.status = 0;
|
||||
usb_ep_regs[2].in.status = 0;
|
||||
}
|
||||
else if (sel->bAlternateSetting == 1)
|
||||
{
|
||||
/* Already running ? */
|
||||
if (g_usb_e1.running)
|
||||
return USB_FND_SUCCESS;
|
||||
|
||||
/* Update state */
|
||||
g_usb_e1.running = true;
|
||||
|
||||
/* Reset buffer pointers */
|
||||
g_usb_e1.in_bdi[0] = 0;
|
||||
g_usb_e1.in_bdi[1] = 0;
|
||||
|
||||
/* Configure EP1 IN / EP2 IN */
|
||||
usb_ep_regs[1].in.status = USB_EP_TYPE_ISOC | USB_EP_BD_DUAL; /* Type=Isochronous, dual buffered */
|
||||
usb_ep_regs[2].in.status = USB_EP_TYPE_ISOC | USB_EP_BD_DUAL; /* Type=Isochronous, dual buffered */
|
||||
|
||||
/* EP1 IN: Prepare two buffers */
|
||||
usb_ep_regs[1].in.bd[0].ptr = 256 + 0 * 388;
|
||||
usb_ep_regs[1].in.bd[0].csr = 0;
|
||||
|
||||
usb_ep_regs[1].in.bd[1].ptr = 256 + 1 * 388;
|
||||
usb_ep_regs[1].in.bd[1].csr = 0;
|
||||
|
||||
/* EP2 IN: Prepare two buffers */
|
||||
usb_ep_regs[2].in.bd[0].ptr = 256 + 2 * 388;
|
||||
usb_ep_regs[2].in.bd[0].csr = 0;
|
||||
|
||||
usb_ep_regs[2].in.bd[1].ptr = 256 + 3 * 388;
|
||||
usb_ep_regs[2].in.bd[1].csr = 0;
|
||||
|
||||
/* Start E1 */
|
||||
e1_start_one(0);
|
||||
e1_start_one(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unknown */
|
||||
switch (base->bInterfaceNumber) {
|
||||
case 0:
|
||||
case 1:
|
||||
switch (sel->bAlternateSetting) {
|
||||
case 0:
|
||||
disable_chan(base->bInterfaceNumber);
|
||||
break;
|
||||
case 1:
|
||||
enable_chan(base->bInterfaceNumber);
|
||||
break;
|
||||
default:
|
||||
/* Unknown */
|
||||
return USB_FND_ERROR;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return USB_FND_CONTINUE;
|
||||
}
|
||||
} else {
|
||||
return USB_FND_ERROR;
|
||||
}
|
||||
|
||||
|
||||
return USB_FND_SUCCESS;
|
||||
}
|
||||
|
||||
enum usb_fnd_resp
|
||||
_e1_get_intf(const struct usb_intf_desc *base, uint8_t *alt)
|
||||
{
|
||||
if (base->bInterfaceNumber != 0)
|
||||
return USB_FND_CONTINUE;
|
||||
if (!last_conf || last_conf->bConfigurationValue == 1) {
|
||||
/* Legacy configuration */
|
||||
if (base->bInterfaceNumber != 0)
|
||||
return USB_FND_CONTINUE;
|
||||
|
||||
*alt = g_usb_e1.running ? 1 : 0;
|
||||
*alt = g_usb_e1.running[0] && g_usb_e1.running[1] ? 1 : 0;
|
||||
} else if (last_conf && last_conf->bConfigurationValue == 2) {
|
||||
/* e1d compatible configuration */
|
||||
switch (base->bInterfaceNumber) {
|
||||
case 0:
|
||||
case 1:
|
||||
*alt = g_usb_e1.running[base->bInterfaceNumber] ? 1 : 0;
|
||||
break;
|
||||
default:
|
||||
return USB_FND_CONTINUE;
|
||||
}
|
||||
} else
|
||||
return USB_FND_CONTINUE;
|
||||
|
||||
return USB_FND_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
0000000000000000
|
||||
osmocom
|
||||
e1-tracer
|
||||
Main
|
||||
Legacy
|
||||
E1
|
||||
DFU runtime
|
||||
osmo-e1d compatible
|
||||
E1 Direction A
|
||||
E1 Direction B
|
||||
|
|
Loading…
Reference in New Issue