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>