host: split the transport layer from card emulation

We want to be able to use some code irrespective of the application
(emulation, tracing, ...), so let's split the transport struct out of
the cardem_instance.
This commit is contained in:
Harald Welte 2017-05-09 15:11:53 +02:00
parent 296c401275
commit 08b77ba9ee
1 changed files with 42 additions and 30 deletions

View File

@ -51,16 +51,24 @@
static struct gsmtap_inst *g_gti; static struct gsmtap_inst *g_gti;
struct cardem_inst { /* transport to a SIMtrace device */
static struct st_transport {
/* USB */
struct libusb_device_handle *usb_devh; struct libusb_device_handle *usb_devh;
struct { struct {
uint8_t in; uint8_t in;
uint8_t out; uint8_t out;
uint8_t irq_in; uint8_t irq_in;
} usb_ep; } usb_ep;
const struct osim_cla_ins_card_profile *card_prof;
/* UDP */
int udp_fd; int udp_fd;
};
/* One istance of card emulation */
struct cardem_inst {
struct st_transport transp;
const struct osim_cla_ins_card_profile *card_prof;
struct osim_chan_hdl *chan; struct osim_chan_hdl *chan;
}; };
@ -111,19 +119,20 @@ static void apdu_out_cb(uint8_t *buf, unsigned int len, void *user_data)
#endif #endif
/*! \brief Transmit a given command to the SIMtrace2 device */ /*! \brief Transmit a given command to the SIMtrace2 device */
static int st_tx_msgb_to_dev(struct cardem_inst *ci, struct msgb *msg) static int st_transp_tx_msg(struct st_transport *transp, struct msgb *msg)
{ {
int rc; int rc;
printf("<- %s\n", msgb_hexdump(msg)); printf("<- %s\n", msgb_hexdump(msg));
if (ci->udp_fd < 0) { if (transp->udp_fd < 0) {
unsigned int xfer_len; unsigned int xfer_len;
rc = libusb_bulk_transfer(ci->usb_devh, ci->usb_ep.out, msgb_data(msg), rc = libusb_bulk_transfer(transp->usb_devh, transp->usb_ep.out,
msgb_length(msg), &xfer_len, 100000); msgb_data(msg), msgb_length(msg),
&xfer_len, 100000);
} else { } else {
rc = write(ci->udp_fd, msgb_data(msg), msgb_length(msg)); rc = write(transp->udp_fd, msgb_data(msg), msgb_length(msg));
} }
msgb_free(msg); msgb_free(msg);
@ -158,7 +167,7 @@ static int cardem_request_card_insert(struct cardem_inst *ci, bool inserted)
st_push_hdr(msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_CARDINSERT); st_push_hdr(msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_CARDINSERT);
return st_tx_msgb_to_dev(ci, msg); return st_transp_tx_msg(&ci->transp, msg);
} }
/*! \brief Request the SIMtrace2 to transmit a Procedure Byte, then Rx */ /*! \brief Request the SIMtrace2 to transmit a Procedure Byte, then Rx */
@ -178,7 +187,7 @@ static int cardem_request_pb_and_rx(struct cardem_inst *ci, uint8_t pb, uint8_t
st_push_hdr(msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA); st_push_hdr(msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA);
return st_tx_msgb_to_dev(ci, msg); return st_transp_tx_msg(&ci->transp, msg);
} }
/*! \brief Request the SIMtrace2 to transmit a Procedure Byte, then Tx */ /*! \brief Request the SIMtrace2 to transmit a Procedure Byte, then Tx */
@ -205,7 +214,7 @@ static int cardem_request_pb_and_tx(struct cardem_inst *ci, uint8_t pb,
st_push_hdr(msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA); st_push_hdr(msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA);
return st_tx_msgb_to_dev(ci, msg); return st_transp_tx_msg(&ci->transp, msg);
} }
/*! \brief Request the SIMtrace2 to send a Status Word */ /*! \brief Request the SIMtrace2 to send a Status Word */
@ -228,7 +237,7 @@ static int cardem_request_sw_tx(struct cardem_inst *ci, const uint8_t *sw)
st_push_hdr(msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA); st_push_hdr(msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA);
return st_tx_msgb_to_dev(ci, msg); return st_transp_tx_msg(&ci->transp, msg);
} }
static void atr_update_csum(uint8_t *atr, unsigned int atr_len) static void atr_update_csum(uint8_t *atr, unsigned int atr_len)
@ -259,7 +268,7 @@ static int cardem_request_set_atr(struct cardem_inst *ci, const uint8_t *atr, un
st_push_hdr(msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_SET_ATR); st_push_hdr(msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_SET_ATR);
return st_tx_msgb_to_dev(ci, msg); return st_transp_tx_msg(&ci->transp, msg);
} }
@ -430,6 +439,7 @@ static const struct option opts[] = {
static void run_mainloop(struct cardem_inst *ci) static void run_mainloop(struct cardem_inst *ci)
{ {
struct st_transport *transp = &ci->transp;
unsigned int msg_count, byte_count = 0; unsigned int msg_count, byte_count = 0;
uint8_t buf[16*265]; uint8_t buf[16*265];
int xfer_len; int xfer_len;
@ -439,15 +449,15 @@ static void run_mainloop(struct cardem_inst *ci)
while (1) { while (1) {
/* read data from SIMtrace2 device (local or via USB) */ /* read data from SIMtrace2 device (local or via USB) */
if (ci->udp_fd < 0) { if (transp->udp_fd < 0) {
rc = libusb_bulk_transfer(ci->usb_devh, ci->usb_ep.in, rc = libusb_bulk_transfer(transp->usb_devh, transp->usb_ep.in,
buf, sizeof(buf), &xfer_len, 100000); buf, sizeof(buf), &xfer_len, 100000);
if (rc < 0 && rc != LIBUSB_ERROR_TIMEOUT) { if (rc < 0 && rc != LIBUSB_ERROR_TIMEOUT) {
fprintf(stderr, "BULK IN transfer error; rc=%d\n", rc); fprintf(stderr, "BULK IN transfer error; rc=%d\n", rc);
return; return;
} }
} else { } else {
rc = read(ci->udp_fd, buf, sizeof(buf)); rc = read(transp->udp_fd, buf, sizeof(buf));
if (rc <= 0) { if (rc <= 0) {
fprintf(stderr, "shor read from UDP\n"); fprintf(stderr, "shor read from UDP\n");
return; return;
@ -480,6 +490,7 @@ static void signal_handler(int signal)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct st_transport *transp = &ci->transp;
char *gsmtap_host = "127.0.0.1"; char *gsmtap_host = "127.0.0.1";
int rc; int rc;
int c, ret = 1; int c, ret = 1;
@ -547,7 +558,7 @@ int main(int argc, char **argv)
} }
memset(ci, 0, sizeof(*ci)); memset(ci, 0, sizeof(*ci));
ci->udp_fd = -1; transp->udp_fd = -1;
ci->card_prof = &osim_uicc_sim_cic_profile; ci->card_prof = &osim_uicc_sim_cic_profile;
@ -558,9 +569,10 @@ int main(int argc, char **argv)
goto do_exit; goto do_exit;
} }
} else { } else {
ci->udp_fd = osmo_sock_init(AF_INET, SOCK_DGRAM, IPPROTO_UDP, remote_udp_host, transp->udp_fd = osmo_sock_init(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
remote_udp_port+if_num, OSMO_SOCK_F_CONNECT); remote_udp_host, remote_udp_port+if_num,
if (ci->udp_fd < 0) { OSMO_SOCK_F_CONNECT);
if (transp->udp_fd < 0) {
fprintf(stderr, "error binding UDP port\n"); fprintf(stderr, "error binding UDP port\n");
goto do_exit; goto do_exit;
} }
@ -594,7 +606,7 @@ int main(int argc, char **argv)
signal(SIGINT, &signal_handler); signal(SIGINT, &signal_handler);
do { do {
if (ci->udp_fd < 0) { if (transp->udp_fd < 0) {
struct usb_interface_match _ifm, *ifm = &_ifm; struct usb_interface_match _ifm, *ifm = &_ifm;
ifm->vendor = vendor_id; ifm->vendor = vendor_id;
ifm->product = product_id; ifm->product = product_id;
@ -602,20 +614,20 @@ int main(int argc, char **argv)
ifm->interface = if_num; ifm->interface = if_num;
ifm->altsetting = altsetting; ifm->altsetting = altsetting;
ifm->addr = addr; ifm->addr = addr;
ci->usb_devh = usb_open_claim_interface(NULL, ifm); transp->usb_devh = usb_open_claim_interface(NULL, ifm);
if (!ci->usb_devh) { if (!transp->usb_devh) {
fprintf(stderr, "can't open USB device\n"); fprintf(stderr, "can't open USB device\n");
goto close_exit; goto close_exit;
} }
rc = libusb_claim_interface(ci->usb_devh, if_num); rc = libusb_claim_interface(transp->usb_devh, if_num);
if (rc < 0) { if (rc < 0) {
fprintf(stderr, "can't claim interface %d; rc=%d\n", if_num, rc); fprintf(stderr, "can't claim interface %d; rc=%d\n", if_num, rc);
goto close_exit; goto close_exit;
} }
rc = get_usb_ep_addrs(ci->usb_devh, if_num, &ci->usb_ep.out, rc = get_usb_ep_addrs(transp->usb_devh, if_num, &transp->usb_ep.out,
&ci->usb_ep.in, &ci->usb_ep.irq_in); &transp->usb_ep.in, &transp->usb_ep.irq_in);
if (rc < 0) { if (rc < 0) {
fprintf(stderr, "can't obtain EP addrs; rc=%d\n", rc); fprintf(stderr, "can't obtain EP addrs; rc=%d\n", rc);
goto close_exit; goto close_exit;
@ -632,17 +644,17 @@ int main(int argc, char **argv)
run_mainloop(ci); run_mainloop(ci);
ret = 0; ret = 0;
if (ci->udp_fd < 0) if (transp->udp_fd < 0)
libusb_release_interface(ci->usb_devh, 0); libusb_release_interface(transp->usb_devh, 0);
close_exit: close_exit:
if (ci->usb_devh) if (transp->usb_devh)
libusb_close(ci->usb_devh); libusb_close(transp->usb_devh);
if (keep_running) if (keep_running)
sleep(1); sleep(1);
} while (keep_running); } while (keep_running);
release_exit: release_exit:
if (ci->udp_fd < 0) if (transp->udp_fd < 0)
libusb_exit(NULL); libusb_exit(NULL);
do_exit: do_exit:
return ret; return ret;