This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
laforge gerrit-no-reply at lists.osmocom.orglaforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-e1d/+/21782 )
Change subject: Add support for icE1usb interrupt endpoint error reporting
......................................................................
Add support for icE1usb interrupt endpoint error reporting
Related: OS#4674
Change-Id: I5b0bf3cf40c623c17f2e88292e880b545c36b7b6
Depends: osmo-e1-hardware If157fde9d4ca05910b09537e19f37603c6d925f0
---
M src/Makefile.am
A src/ice1usb_proto.h
M src/usb.c
3 files changed, 192 insertions(+), 3 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-e1d refs/changes/82/21782/1
diff --git a/src/Makefile.am b/src/Makefile.am
index 6dd13ce..d9d8236 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,6 +21,7 @@
noinst_HEADERS = \
e1d.h \
+ ice1usb_proto.h \
log.h \
$(NULL)
diff --git a/src/ice1usb_proto.h b/src/ice1usb_proto.h
new file mode 100644
index 0000000..5f5f31c
--- /dev/null
+++ b/src/ice1usb_proto.h
@@ -0,0 +1,99 @@
+#pragma once
+
+/* Header file describing the USB protocol between the icE1usb firmware and the host
+ * software (currently really only osmo-e1d) */
+
+/***********************************************************************
+ * Control Endpoint / Device Requests
+ ***********************************************************************/
+
+/*! returns a bit-mask of optional device capabilities (see enum e1usb_dev_capability) */
+#define ICE1USB_DEV_GET_CAPABILITIES 0x01
+#define ICE1USB_DEV_GET_FW_BUILD 0x02
+
+enum e1usb_dev_capability {
+ /*! Does this board have a GPS-DO */
+ ICE1USB_DEV_CAP_GPSDO,
+};
+
+
+/* Interface Requests */
+
+/*! returns a bit-mask of optional device capabilities (see enum e1usb_intf_capability) */
+#define ICE1USB_INTF_GET_CAPABILITIES 0x01
+#define ICE1USB_INTF_SET_TX_CFG 0x02 /*!< struct ice1usb_tx_config */
+#define ICE1USB_INTF_GET_TX_CFG 0x03 /*!< struct ice1usb_tx_config */
+#define ICE1USB_INTF_SET_RX_CFG 0x04 /*!< struct ice1usb_rx_config */
+#define ICE1USB_INTF_GET_RX_CFG 0x05 /*!< struct ice1usb_rx_config */
+
+//enum e1usb_intf_capability { };
+
+enum ice1usb_tx_mode {
+ ICE1USB_TX_MODE_TRANSP = 0,
+ ICE1USB_TX_MODE_TS0 = 1,
+ ICE1USB_TX_MODE_TS0_CRC4 = 2,
+ ICE1USB_TX_MODE_TS0_CRC4_E = 3,
+};
+
+enum ice1usb_tx_timing {
+ ICE1USB_TX_TIME_SRC_LOCAL = 0,
+ ICE1USB_TX_TIME_SRC_REMOTE = 1,
+};
+
+enum ice1usb_tx_ext_loopback {
+ ICE1USB_TX_EXT_LOOPBACK_OFF = 0,
+ ICE1USB_TX_EXT_LOOPBACK_SAME = 1,
+ ICE1USB_TX_EXT_LOOPBACK_CROSS = 2,
+};
+
+/* ICE1USB_INTF_{GET,SET}_TX_CFG */
+struct ice1usb_tx_config {
+ uint8_t mode; /*!< enum ice1usb_tx_mode */
+ uint8_t timing; /*!< enum ice1usb_tx_timing */
+ uint8_t ext_loopback; /*!< enum ice1usb_tx_ext_loopback */
+ uint8_t alarm; /*!< 1 = transmit alarm; 0 = don't */
+} __attribute__((packed));
+
+
+enum ice1usb_rx_mode {
+ /*! transparent, unaligned bitstream */
+ ICE1USB_RX_MODE_TRANSP = 0,
+ /*! alignment to E1 frame */
+ ICE1USB_RX_MODE_FRAME = 2,
+ /*! alignment to E1 multiframe */
+ ICE1USB_RX_MODE_MULTIFRAME = 3,
+};
+
+/* ICE1USB_INTF_{GET,SET}_RX_CFG */
+struct ice1usb_rx_config {
+ uint8_t mode; /*!< enum ice1usb_rx_mode */
+} __attribute__((packed));
+
+
+/***********************************************************************
+ * Interrupt Endpoint
+ ***********************************************************************/
+
+enum ice1usb_irq_type {
+ ICE1USB_IRQQ_T_ERRCNT = 1,
+};
+
+/* Ensue ro keep those in sync with e1.h */
+#define ICE1USB_ERR_F_ALIGN_ERR 0x01
+#define ICE1USB_ERR_F_TICK_ERR 0x02
+
+struct ice1usb_irq_err {
+ /* 16-bit little-endian counters */
+ uint16_t crc;
+ uint16_t align;
+ uint16_t ovfl;
+ uint16_t unfl;
+ uint8_t flags;
+} __attribute__((packed));
+
+struct ice1usb_irq {
+ uint8_t type; /*!< enum ice1usb_irq_type */
+ union {
+ struct ice1usb_irq_err errors;
+ } u;
+} __attribute__((packed));
diff --git a/src/usb.c b/src/usb.c
index 7f7f5c6..3a35a20 100644
--- a/src/usb.c
+++ b/src/usb.c
@@ -36,6 +36,7 @@
#include "e1d.h"
#include "log.h"
+#include "ice1usb_proto.h"
#define USB_VID 0x1d50
@@ -57,6 +58,7 @@
uint8_t ep_in;
uint8_t ep_out;
uint8_t ep_fb;
+ uint8_t ep_int;
/* Max packet size */
int pkt_size;
@@ -66,6 +68,12 @@
struct e1_usb_flow *flow_out;
struct e1_usb_flow *flow_fb;
+ /* Interrupt */
+ struct {
+ uint8_t buf[10];
+ struct ice1usb_irq_err last_errcnt;
+ } irq;
+
/* Rate regulation */
uint32_t r_acc;
uint32_t r_sw;
@@ -98,8 +106,6 @@
struct e1_usb_flow_entry *entries;
};
-
-
// ---------------------------------------------------------------------------
// USB data transfer
// ---------------------------------------------------------------------------
@@ -275,6 +281,84 @@
return 0;
}
+static int resubmit_irq(struct e1_line *line);
+
+static void rx_interrupt_errcnt(struct e1_line *line, const struct ice1usb_irq_err *errcnt)
+{
+ struct e1_usb_line_data *ld = (struct e1_usb_line_data *) line->drv_data;
+ struct ice1usb_irq_err *last = &ld->irq.last_errcnt;
+
+ if (errcnt->crc != last->crc) {
+ LOGPLI(line, DE1D, LOGL_ERROR, "CRC error count %d (was %d)\n",
+ errcnt->crc, last->crc);
+ }
+
+ if (errcnt->align != last->align) {
+ LOGPLI(line, DE1D, LOGL_ERROR, "ALIGNMENT error count %d (was %d)\n",
+ errcnt->align, last->align);
+ }
+
+ if (errcnt->ovfl != last->ovfl) {
+ LOGPLI(line, DE1D, LOGL_ERROR, "OVERFLOW error count %d (was %d)\n",
+ errcnt->ovfl, last->ovfl);
+ }
+
+ if (errcnt->unfl != last->unfl) {
+ LOGPLI(line, DE1D, LOGL_ERROR, "UNDERFLOW error count %d (was %d)\n",
+ errcnt->unfl, last->unfl);
+ }
+
+ if ((errcnt->flags & ICE1USB_ERR_F_ALIGN_ERR) != (last->flags & ICE1USB_ERR_F_ALIGN_ERR)) {
+ LOGPLI(line, DE1D, LOGL_ERROR, "ALIGNMENT %s\n",
+ errcnt->flags & ICE1USB_ERR_F_ALIGN_ERR ? "LOST" : "REGAINED");
+ }
+
+ if ((errcnt->flags & ICE1USB_ERR_F_TICK_ERR) != (last->flags & ICE1USB_ERR_F_TICK_ERR)) {
+ LOGPLI(line, DE1D, LOGL_ERROR, "Rx Clock %s\n",
+ errcnt->flags & ICE1USB_ERR_F_TICK_ERR ? "LOST" : "REGAINED");
+ }
+
+ ld->irq.last_errcnt = *errcnt;
+}
+
+static void interrupt_ep_cb(struct libusb_transfer *xfer)
+{
+ struct e1_line *line = (struct e1_line *) xfer->user_data;
+ const struct ice1usb_irq *irq = (const struct ice1usb_irq *) xfer->buffer;
+
+ if (!xfer->actual_length) {
+ LOGPLI(line, DE1D, LOGL_ERROR, "Zero-Length Interrupt transfer\n");
+ goto out;
+ }
+
+ switch (irq->type) {
+ case ICE1USB_IRQQ_T_ERRCNT:
+ if (xfer->actual_length < sizeof(*irq)) {
+ LOGPLI(line, DE1D, LOGL_ERROR, "Short ERRCNT interrupt: %u<%zu\n",
+ xfer->actual_length, sizeof(*irq));
+ break;
+ }
+ rx_interrupt_errcnt(line, &irq->u.errors);
+ break;
+ default:
+ LOGPLI(line, DE1D, LOGL_INFO, "Unsupported interrupt 0x%02x\n", irq->type);
+ break;
+ }
+
+out:
+ resubmit_irq(line);
+}
+
+static int resubmit_irq(struct e1_line *line)
+{
+ struct e1_usb_line_data *ld = (struct e1_usb_line_data *) line->drv_data;
+ struct e1_usb_intf_data *id = (struct e1_usb_intf_data *) line->intf->drv_data;
+ struct libusb_transfer *xfr = libusb_alloc_transfer(0);
+
+ libusb_fill_interrupt_transfer(xfr, id->devh, ld->ep_int, ld->irq.buf, sizeof(ld->irq.buf),
+ interrupt_ep_cb, line, 0);
+ return libusb_submit_transfer(xfr);
+}
// ---------------------------------------------------------------------------
// Init / Probing
@@ -316,7 +400,7 @@
continue;
id = &cd->interface[i].altsetting[1];
- if ((id->bInterfaceClass != 0xff) || (id->bInterfaceSubClass != 0xe1) || (id->bNumEndpoints != 3))
+ if ((id->bInterfaceClass != 0xff) || (id->bInterfaceSubClass != 0xe1) || (id->bNumEndpoints < 3))
continue;
/* Get interface and set it up */
@@ -353,6 +437,8 @@
else if (line_data->pkt_size != id->endpoint[j].wMaxPacketSize)
LOGP(DE1D, LOGL_ERROR, "Inconsistent max packet size %d vs %d\n",
line_data->pkt_size, (int)id->endpoint[j].wMaxPacketSize);
+ } else if (id->endpoint[j].bmAttributes == 0x03) {
+ line_data->ep_int = id->endpoint[j].bEndpointAddress;
} else {
LOGP(DE1D, LOGL_ERROR, "Invalid EP %02x\n", id->endpoint[j].bEndpointAddress);
}
@@ -372,6 +458,9 @@
e1uf_start(line_data->flow_in);
e1uf_start(line_data->flow_out);
e1uf_start(line_data->flow_fb);
+
+ if (line_data->ep_int)
+ resubmit_irq(line);
}
return 0;
--
To view, visit https://gerrit.osmocom.org/c/osmo-e1d/+/21782
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-e1d
Gerrit-Branch: master
Gerrit-Change-Id: I5b0bf3cf40c623c17f2e88292e880b545c36b7b6
Gerrit-Change-Number: 21782
Gerrit-PatchSet: 1
Gerrit-Owner: laforge <laforge at osmocom.org>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20201217/912e72db/attachment.htm>