aboutsummaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2016-03-19 21:28:09 +0100
committerHarald Welte <laforge@gnumonks.org>2016-03-19 21:28:09 +0100
commit236caf68eb64ca70b7182dd75f052e670a54c4d4 (patch)
tree00422d8b176ab5b9080d33560ba4b88d42c0bf9d /host
parent095ac6cbe239e15773c494a077b990a5844cd44a (diff)
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.
Diffstat (limited to 'host')
-rw-r--r--host/Makefile4
-rw-r--r--host/simtrace.h6
-rw-r--r--host/simtrace2-discovery.c75
-rw-r--r--host/simtrace2-discovery.h7
-rw-r--r--host/simtrace2-remsim.c25
-rw-r--r--host/usb2udp.c34
6 files changed, 124 insertions, 27 deletions
diff --git a/host/Makefile b/host/Makefile
index 4f46c8f..09e45be 100644
--- a/host/Makefile
+++ b/host/Makefile
@@ -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
diff --git a/host/simtrace.h b/host/simtrace.h
index 0611f36..c4a20da 100644
--- a/host/simtrace.h
+++ b/host/simtrace.h
@@ -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
diff --git a/host/simtrace2-discovery.c b/host/simtrace2-discovery.c
new file mode 100644
index 0000000..38868fb
--- /dev/null
+++ b/host/simtrace2-discovery.c
@@ -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
diff --git a/host/simtrace2-discovery.h b/host/simtrace2-discovery.h
new file mode 100644
index 0000000..539b471
--- /dev/null
+++ b/host/simtrace2-discovery.h
@@ -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);
diff --git a/host/simtrace2-remsim.c b/host/simtrace2-remsim.c
index f22c341..1fd2fa7 100644
--- a/host/simtrace2-remsim.c
+++ b/host/simtrace2-remsim.c
@@ -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 %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 claim interface; rc=%d\n", rc);
+ fprintf(stderr, "can't obtain EP addrs; rc=%d\n", rc);
goto close_exit;
}
}
diff --git a/host/usb2udp.c b/host/usb2udp.c
index fcf508a..e33e371 100644
--- a/host/usb2udp.c
+++ b/host/usb2udp.c
@@ -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);