Browse Source

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
changes/74/18474/1
Harald Welte 2 years ago
parent
commit
859f1b0974
  1. 10
      TODO-RELEASE
  2. 4
      host/include/osmocom/simtrace2/simtrace2_api.h
  3. 78
      host/lib/simtrace2_api.c

10
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

4
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);

78
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;
}
/***********************************************************************

Loading…
Cancel
Save