diff options
author | Harald Welte <laforge@osmocom.org> | 2020-02-22 16:45:05 +0100 |
---|---|---|
committer | Harald Welte <laforge@osmocom.org> | 2020-05-25 23:00:20 +0200 |
commit | 859f1b0974daee3dd5e4a650f7077148d9d61cf5 (patch) | |
tree | eb7e42c8c5d4c92cfb2468818dd92095b8da5e13 | |
parent | 4e73aaeba8fe30db1e8a385aadb425d43b4e2414 (diff) |
Introduce support for asynchronous USB transmission
libosmo-simtrace2 traditionally had only supported blocking, synchronous
I/O, while other osmocom programs such as remsim-client used
asynchronous USB I/O.
Using async USB I/O for IRQ + IN transfers while using blocking I/O for
OUT transfers doesn't seem to work reliably, so we have to offer a way
to perform the OUT transfers generated within libosmo-simtrace2 in async
mode.
Change-Id: Ib8939bdb7f533cd20a34a30a97f12b782b9816c2
-rw-r--r-- | TODO-RELEASE | 10 | ||||
-rw-r--r-- | host/include/osmocom/simtrace2/simtrace2_api.h | 4 | ||||
-rw-r--r-- | host/lib/simtrace2_api.c | 78 |
3 files changed, 77 insertions, 15 deletions
diff --git a/TODO-RELEASE b/TODO-RELEASE new file mode 100644 index 0000000..5da461b --- /dev/null +++ b/TODO-RELEASE @@ -0,0 +1,10 @@ +# When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install +# according to https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release +# In short: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info +# LIBVERSION=c:r:a +# If the library source code has changed at all since the last update, then increment revision: c:r + 1:a. +# If any interfaces have been added, removed, or changed since the last update: c + 1:0:0. +# If any interfaces have been added since the last public release: c:r:a + 1. +# If any interfaces have been removed or changed since the last public release: c:r:0. +#library what description / commit summary line +simtrace2 API/ABI change osmo_st2_transport new member diff --git a/host/include/osmocom/simtrace2/simtrace2_api.h b/host/include/osmocom/simtrace2/simtrace2_api.h index aa1637d..d658d16 100644 --- a/host/include/osmocom/simtrace2/simtrace2_api.h +++ b/host/include/osmocom/simtrace2/simtrace2_api.h @@ -12,6 +12,8 @@ struct osmo_st2_transport { uint8_t out; uint8_t irq_in; } usb_ep; + /* use non-blocking / asynchronous libusb I/O */ + bool usb_async; /* UDP */ int udp_fd; @@ -39,8 +41,6 @@ struct osmo_st2_cardem_inst { void *priv; }; -int osmo_st2_transp_tx_msg(struct osmo_st2_transport *transp, struct msgb *msg); - int osmo_st2_slot_tx_msg(struct osmo_st2_slot *slot, struct msgb *msg, uint8_t msg_class, uint8_t msg_type); diff --git a/host/lib/simtrace2_api.c b/host/lib/simtrace2_api.c index b3e4e38..4e16fd1 100644 --- a/host/lib/simtrace2_api.c +++ b/host/lib/simtrace2_api.c @@ -57,23 +57,60 @@ static struct msgb *st_msgb_alloc(void) return msgb_alloc_headroom(1024+32, 32, "SIMtrace"); } -/*! \brief Transmit a given command to the SIMtrace2 device */ -int osmo_st2_transp_tx_msg(struct osmo_st2_transport *transp, struct msgb *msg) + +static void usb_out_xfer_cb(struct libusb_transfer *xfer) { - int rc; + struct msgb *msg = xfer->user_data; + + switch (xfer->status) { + case LIBUSB_TRANSFER_COMPLETED: + break; + case LIBUSB_TRANSFER_NO_DEVICE: + fprintf(stderr, "USB device disappeared\n"); + exit(1); + break; + default: + fprintf(stderr, "USB OUT transfer failed, status=%u\n", xfer->status); + exit(1); + break; + } - printf("<- %s\n", msgb_hexdump(msg)); + msgb_free(msg); + libusb_free_transfer(xfer); +} - if (transp->udp_fd < 0) { - int xfer_len; - rc = libusb_bulk_transfer(transp->usb_devh, transp->usb_ep.out, - msgb_data(msg), msgb_length(msg), - &xfer_len, 100000); - } else { - rc = write(transp->udp_fd, msgb_data(msg), msgb_length(msg)); - } +static int st2_transp_tx_msg_usb_async(struct osmo_st2_transport *transp, struct msgb *msg) +{ + struct libusb_transfer *xfer; + int rc; + + xfer = libusb_alloc_transfer(0); + OSMO_ASSERT(xfer); + xfer->dev_handle = transp->usb_devh; + xfer->flags = 0; + xfer->type = LIBUSB_TRANSFER_TYPE_BULK; + xfer->endpoint = transp->usb_ep.out; + xfer->timeout = 100000; + xfer->user_data = msg; + xfer->length = msgb_length(msg); + xfer->buffer = msgb_data(msg); + xfer->callback = usb_out_xfer_cb; + + rc = libusb_submit_transfer(xfer); + OSMO_ASSERT(rc == 0); + return rc; +} + +/*! \brief Transmit a given command to the SIMtrace2 device */ +static int st2_transp_tx_msg_usb_sync(struct osmo_st2_transport *transp, struct msgb *msg) +{ + int rc; + int xfer_len; + rc = libusb_bulk_transfer(transp->usb_devh, transp->usb_ep.out, + msgb_data(msg), msgb_length(msg), + &xfer_len, 100000); msgb_free(msg); return rc; } @@ -98,9 +135,24 @@ static struct simtrace_msg_hdr *st_push_hdr(struct msgb *msg, uint8_t msg_class, int osmo_st2_slot_tx_msg(struct osmo_st2_slot *slot, struct msgb *msg, uint8_t msg_class, uint8_t msg_type) { + struct osmo_st2_transport *transp = slot->transp; + int rc; + + OSMO_ASSERT(transp); + st_push_hdr(msg, msg_class, msg_type, slot->slot_nr); + printf("SIMtrace <- %s\n", msgb_hexdump(msg)); - return osmo_st2_transp_tx_msg(slot->transp, msg); + if (transp->udp_fd < 0) { + if (transp->usb_async) + rc = st2_transp_tx_msg_usb_async(transp, msg); + else + rc = st2_transp_tx_msg_usb_sync(transp, msg); + } else { + rc = write(transp->udp_fd, msgb_data(msg), msgb_length(msg)); + msgb_free(msg); + } + return rc; } /*********************************************************************** |