remote-sim host tools: Auto-discover the endpoint addresses

We now auto-discover the end-point addresses based on the interface
descriptor.  The user can also use the new "--interface" command line
argument to set a non-zero intrerface.  In combination, this should
enable support for the remote-sim functionality on the second UART
on OWHW.
This commit is contained in:
Harald Welte 2016-03-19 21:28:09 +01:00
parent 095ac6cbe2
commit 236caf68eb
6 changed files with 124 additions and 27 deletions

View File

@ -2,10 +2,10 @@ LDFLAGS=`pkg-config --libs libusb-1.0 libosmocore` -losmocore
all: simtrace2-remsim simtrace2-remsim-usb2udp
simtrace2-remsim: simtrace2-remsim.o apdu_dispatch.o
simtrace2-remsim: simtrace2-remsim.o apdu_dispatch.o simtrace2-discovery.o
$(CC) -o $@ $^ $(LDFLAGS) -losmosim
simtrace2-remsim-usb2udp: usb2udp.o
simtrace2-remsim-usb2udp: usb2udp.o simtrace2-discovery.o
$(CC) -o $@ $^ $(LDFLAGS)
%.o: %.c

View File

@ -4,10 +4,4 @@
#define SIMTRACE_USB_VENDOR 0x1d50
#define SIMTRACE_USB_PRODUCT 0x60e3
/* FIXME: automatically determine those values based on the usb config /
* interface descriptors */
#define SIMTRACE_OUT_EP 0x04
#define SIMTRACE_IN_EP 0x85
#define SIMTRACE_INT_EP 0x86
#endif

View File

@ -0,0 +1,75 @@
#include <stdint.h>
#include <libusb.h>
/*! \brief obtain the endpoint addresses for a given USB interface */
int get_usb_ep_addrs(libusb_device_handle *devh, unsigned int if_num,
uint8_t *out, uint8_t *in, uint8_t *irq)
{
libusb_device *dev = libusb_get_device(devh);
struct libusb_config_descriptor *cdesc;
const struct libusb_interface_descriptor *idesc;
const struct libusb_interface *iface;
int rc, l;
rc = libusb_get_active_config_descriptor(dev, &cdesc);
if (rc < 0)
return rc;
iface = &cdesc->interface[if_num];
/* FIXME: we assume there's no altsetting */
idesc = &iface->altsetting[0];
for (l = 0; l < idesc->bNumEndpoints; l++) {
const struct libusb_endpoint_descriptor *edesc = &idesc->endpoint[l];
switch (edesc->bmAttributes & 3) {
case LIBUSB_TRANSFER_TYPE_BULK:
if (edesc->bEndpointAddress & 0x80) {
if (in)
*in = edesc->bEndpointAddress;
} else {
if (out)
*out = edesc->bEndpointAddress;
}
break;
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
if (irq)
*irq = edesc->bEndpointAddress;
break;
default:
break;
}
}
return 0;
}
#if 0
struct libusb_device_descriptor ddesc;
int rc, i, j, k;
rc = libusb_get_device_descriptor(devh, &ddesc);
if (rc < 0)
return;
for (i = 0; i < ddesc.bNumConfigurations; i++) {
struct libusb_config_descriptor *cdesc;
rc = libusb_get_config_descriptor(devh, i, &cdesc);
if (rc < 0)
return;
for (j = 0; j < cdesc->bNumInterfaces; j++) {
const struct libusb_interface *iface = cdesc->interface[j];
for (k = 0; k < iface->num_altsetting; k++) {
const struct libusb_interface_descriptor *idesc = iface->altsetting[k];
/* make sure this is the interface we're looking for */
if (idesc->bInterfaceClass != 0xFF ||
idesc->bInterfaceSubClass != if_class ||
idsec->bInterfaceProtocol != if_proto)
continue;
/* FIXME */
}
}
libusb_free_config_descriptor(cdesc);
}
#endif

View File

@ -0,0 +1,7 @@
#pragma once
#include <stdint.h>
#include <libusb.h>
int get_usb_ep_addrs(libusb_device_handle *devh, unsigned int if_num,
uint8_t *out, uint8_t *in, uint8_t *irq);

View File

@ -37,6 +37,7 @@
#include "simtrace.h"
#include "cardemu_prot.h"
#include "apdu_dispatch.h"
#include "simtrace2-discovery.h"
#include <osmocom/core/gsmtap.h>
#include <osmocom/core/gsmtap_util.h>
@ -48,6 +49,8 @@
static struct gsmtap_inst *g_gti;
struct libusb_device_handle *g_devh;
const struct osim_cla_ins_card_profile *g_prof;
static uint8_t g_in_ep;
static uint8_t g_out_ep;
static int g_udp_fd = -1;
static struct osim_chan_hdl *g_chan;
@ -99,7 +102,7 @@ static int tx_to_dev(uint8_t *buf, unsigned int len)
printf("<- %s\n", osmo_hexdump(buf, len));
if (g_udp_fd < 0) {
return libusb_bulk_transfer(g_devh, SIMTRACE_OUT_EP, buf, len,
return libusb_bulk_transfer(g_devh, g_out_ep, buf, len,
&xfer_len, 100000);
} else {
return write(g_udp_fd, buf, len);
@ -331,7 +334,7 @@ static void run_mainloop(void)
while (1) {
/* read data from SIMtrace2 device (local or via USB) */
if (g_udp_fd < 0) {
rc = libusb_bulk_transfer(g_devh, SIMTRACE_IN_EP, buf, sizeof(buf), &xfer_len, 100000);
rc = libusb_bulk_transfer(g_devh, g_in_ep, buf, sizeof(buf), &xfer_len, 100000);
if (rc < 0 && rc != LIBUSB_ERROR_TIMEOUT) {
fprintf(stderr, "BULK IN transfer error; rc=%d\n", rc);
return;
@ -362,6 +365,7 @@ int main(int argc, char **argv)
int skip_atr = 0;
int keep_running = 0;
int remote_udp_port = 52342;
int if_num = 0;
char *remote_udp_host = NULL;
struct osim_reader_hdl *reader;
struct osim_card_hdl *card;
@ -371,7 +375,7 @@ int main(int argc, char **argv)
while (1) {
int option_index = 0;
c = getopt_long(argc, argv, "r:p:hi:ak", opts, &option_index);
c = getopt_long(argc, argv, "r:p:hi:I:ak", opts, &option_index);
if (c == -1)
break;
switch (c) {
@ -388,6 +392,9 @@ int main(int argc, char **argv)
case 'i':
gsmtap_host = optarg;
break;
case 'I':
if_num = atoi(optarg);
break;
case 'a':
skip_atr = 1;
break;
@ -407,7 +414,7 @@ int main(int argc, char **argv)
}
} else {
g_udp_fd = osmo_sock_init(AF_INET, SOCK_DGRAM, IPPROTO_UDP, remote_udp_host,
remote_udp_port, OSMO_SOCK_F_CONNECT);
remote_udp_port+if_num, OSMO_SOCK_F_CONNECT);
if (g_udp_fd < 0) {
fprintf(stderr, "error binding UDP port\n");
goto do_exit;
@ -447,9 +454,15 @@ int main(int argc, char **argv)
goto close_exit;
}
rc = libusb_claim_interface(g_devh, 0);
rc = libusb_claim_interface(g_devh, if_num);
if (rc < 0) {
fprintf(stderr, "can't claim interface; rc=%d\n", rc);
fprintf(stderr, "can't claim interface %d; rc=%d\n", if_num, rc);
goto close_exit;
}
rc = get_usb_ep_addrs(g_devh, if_num, &g_out_ep, &g_in_ep, NULL);
if (rc < 0) {
fprintf(stderr, "can't obtain EP addrs; rc=%d\n", rc);
goto close_exit;
}
}

View File

@ -38,6 +38,7 @@
#include "simtrace.h"
#include "cardemu_prot.h"
#include "apdu_dispatch.h"
#include "simtrace2-discovery.h"
#include <osmocom/core/utils.h>
#include <osmocom/core/socket.h>
@ -56,6 +57,7 @@ static void print_welcome(void)
static void print_help(void)
{
printf( "\t-h\t--help\n"
"\t-i\t--interface <0-255>\n"
"\n"
);
}
@ -76,8 +78,7 @@ static void usb_in_xfer_cb(struct libusb_transfer *xfer)
xfer->endpoint, xfer->status, xfer->flags, xfer->type, xfer->length, xfer->actual_length);
switch (xfer->status) {
case LIBUSB_TRANSFER_COMPLETED:
switch (xfer->endpoint) {
case SIMTRACE_IN_EP:
if (xfer->endpoint == g_buf_in.ep) {
/* process the data */
printf("read %d bytes from SIMTRACE, forwarding to UDP\n", xfer->actual_length);
rc = sendto(g_udp_ofd.fd, xfer->buffer, xfer->actual_length, 0, (struct sockaddr *)&g_sa_remote, sizeof(g_sa_remote));
@ -86,11 +87,9 @@ static void usb_in_xfer_cb(struct libusb_transfer *xfer)
}
/* and re-submit the URB */
libusb_submit_transfer(xfer);
break;
case SIMTRACE_OUT_EP:
} else if (xfer->endpoint == g_buf_out.ep) {
/* re-enable reading from the UDP side */
g_udp_ofd.when |= BSC_FD_READ;
break;
}
break;
default:
@ -99,9 +98,8 @@ static void usb_in_xfer_cb(struct libusb_transfer *xfer)
}
}
static void init_ep_buf(int ep, struct ep_buf *epb)
static void init_ep_buf(struct ep_buf *epb)
{
epb->ep = ep;
if (!epb->xfer)
epb->xfer = libusb_alloc_transfer(0);
@ -208,6 +206,7 @@ int main(int argc, char **argv)
int c, ret = 1;
char *remote_host = NULL;
int local_udp_port = 52342;
unsigned int if_num = 0;
print_welcome();
@ -215,17 +214,21 @@ int main(int argc, char **argv)
int option_index = 0;
static const struct option opts[] = {
{ "udp-port", 1, 0, 'u' },
{ "interface", 1, 0, 'I' },
{ "help", 0, 0, 'h' },
{ NULL, 0, 0, 0 }
};
c = getopt_long(argc, argv, "u:p:h", opts, &option_index);
c = getopt_long(argc, argv, "u:I:h", opts, &option_index);
if (c == -1)
break;
switch (c) {
case 'u':
local_udp_port = atoi(optarg);
break;
case 'I':
if_num = atoi(optarg);
break;
case 'h':
print_help();
exit(0);
@ -247,20 +250,25 @@ int main(int argc, char **argv)
goto close_exit;
}
rc = libusb_claim_interface(g_devh, 0);
rc = libusb_claim_interface(g_devh, if_num);
if (rc < 0) {
fprintf(stderr, "can't claim interface; rc=%d\n", rc);
fprintf(stderr, "can't claim interface %u; rc=%d\n", if_num, rc);
goto close_exit;
}
/* open UDP socket, register with select handling and mark it
* readable */
g_udp_ofd.cb = ofd_udp_cb;
osmo_sock_init_ofd(&g_udp_ofd, AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, local_udp_port, OSMO_SOCK_F_BIND);
osmo_sock_init_ofd(&g_udp_ofd, AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, local_udp_port + if_num, OSMO_SOCK_F_BIND);
rc = get_usb_ep_addrs(g_devh, if_num, &g_buf_out.ep, &g_buf_in.ep, NULL);
if (rc < 0) {
fprintf(stderr, "couldn't find enpdoint addresses; rc=%d\n", rc);
goto close_exit;
}
/* initialize USB buffers / transfers */
init_ep_buf(SIMTRACE_OUT_EP, &g_buf_out);
init_ep_buf(SIMTRACE_IN_EP, &g_buf_in);
init_ep_buf(&g_buf_out);
init_ep_buf(&g_buf_in);
/* submit the first transfer for the IN endpoint */
libusb_submit_transfer(g_buf_in.xfer);