diff options
author | Harald Welte <laforge@gnumonks.org> | 2017-01-01 11:15:35 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2017-01-01 19:51:50 +0100 |
commit | dc2cafcd97be63232a1fc513013987064477cf86 (patch) | |
tree | ab663a1853c4feac9af8077c7d7273a32b3840a1 | |
parent | 9a3cd09fedec9701db9221f927d9c9281d9d194d (diff) |
restructuring: Introduce _transceive_ functions for Tx-then-Rx
-rw-r--r-- | src/Makefile | 2 | ||||
-rw-r--r-- | src/diag_cmd.c | 72 | ||||
-rw-r--r-- | src/diag_cmd.h | 14 | ||||
-rw-r--r-- | src/diag_dpl.c | 42 | ||||
-rw-r--r-- | src/diag_io.c | 83 | ||||
-rw-r--r-- | src/diag_io.h | 9 | ||||
-rw-r--r-- | src/diag_log.c | 7 | ||||
-rw-r--r-- | src/diag_msg.c | 7 | ||||
-rw-r--r-- | src/osmo-qcdiag-log.c | 43 | ||||
-rw-r--r-- | src/protocol/dpl.h | 2 |
10 files changed, 208 insertions, 73 deletions
diff --git a/src/Makefile b/src/Makefile index ecff5c5..525e784 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,7 +4,7 @@ all: osmo-qcdiag-log MODS_LOG = gprs_rlc.o gprs_mac.o diag_gsm.o diag_log.o diag_log_gsm.o diag_log_gprs.o diag_log_umts.o diag_log_qmi.o diag_dpl.o -osmo-qcdiag-log: diagchar_hdlc.o diag_io.o osmo-qcdiag-log.o diag_msg.o protocol.o $(MODS_LOG) +osmo-qcdiag-log: diagchar_hdlc.o diag_io.o osmo-qcdiag-log.o diag_msg.o protocol.o diag_cmd.o $(MODS_LOG) $(CC) $(CPPFLAGS) -o $@ $^ $(LIBS) clean: diff --git a/src/diag_cmd.c b/src/diag_cmd.c new file mode 100644 index 0000000..b1f4dc4 --- /dev/null +++ b/src/diag_cmd.c @@ -0,0 +1,72 @@ +/* + * (C) 2013-2016 by Harald Welte <laforge@gnumonks.org> + * + * originally based on earlier code from Dieter Spaar and Holger + * Freyther, though by now almost entirely rewritten. Nevertheless, + * thanks to Dieter and Holger! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "protocol/protocol.h" +#include "protocol/diagcmd.h" +#include "diag_cmd.h" +#include "diag_log.h" +#include "diag_msg.h" + + +/*********************************************************************** + * CMD Dispatch + ***********************************************************************/ + +static diag_cmd_handler *cmd_handlers[0xff]; + +/* called by individual modules to register their own decoders */ +void diag_cmd_reg_dispatch(const struct diag_cmd_dispatch_tbl *tbl, unsigned int size) +{ + unsigned int i; + for (i = 0; i < size; i++) { + printf("Registering CMD dispatch for 0x%02x\n", tbl[i].code); + cmd_handlers[tbl[i].code] = tbl[i].handler; + } +} + +int diag_process_msg(struct diag_instance *di, struct msgb *msg) +{ + uint8_t cmd = msg->l2h[0]; + + switch (cmd) { + case DIAG_LOG_F: + diag_log_handle(di, msg); + msgb_free(msg); + return 1; + case DIAG_EXT_MSG_F: + diag_rx_ext_msg_f(di, msg); + msgb_free(msg); + return 1; + default: + if (cmd_handlers[cmd]) { + (cmd_handlers[cmd])(di, msg); + msgb_free(msg); + return 1; + } else { + printf("Got %d bytes data of unknown payload type 0x%02x: %s\n", + msgb_length(msg), msg->l2h[0], + osmo_hexdump(msgb_data(msg), msgb_length(msg))); + return 0; + } + break; + } +} diff --git a/src/diag_cmd.h b/src/diag_cmd.h new file mode 100644 index 0000000..edeb863 --- /dev/null +++ b/src/diag_cmd.h @@ -0,0 +1,14 @@ +#pragma once + +#include <osmocom/core/msgb.h> +#include "diag_io.h" + +typedef void diag_cmd_handler(struct diag_instance *di, struct msgb *msg); + +struct diag_cmd_dispatch_tbl { + uint8_t code; + diag_cmd_handler *handler; +}; + +void diag_cmd_reg_dispatch(const struct diag_cmd_dispatch_tbl *tbl, unsigned int size); +int diag_process_msg(struct diag_instance *di, struct msgb *msg); diff --git a/src/diag_dpl.c b/src/diag_dpl.c index 72008dd..31bcff6 100644 --- a/src/diag_dpl.c +++ b/src/diag_dpl.c @@ -21,6 +21,7 @@ #include <osmocom/core/msgb.h> #include "diag_log.h" +#include "diag_io.h" #include "protocol/diagcmd.h" #include "protocol/diag_log_1x.h" #include "protocol/dpl.h" @@ -33,52 +34,61 @@ int diag_dpl_reset_logging(struct diag_instance *di) { - struct msb *msg = msgb_alloc_diag(); + struct msgb *msg = msgb_alloc_diag(); + struct msgb *rx; diag_push_subsys_hdr(msg, DIAG_SUBSYS_PS_DATA_LOGGING, DIAG_DPL_RESET_LOGGING); - diag_transmit_msgb(di, msg); - diag_read(di); + rx = diag_transceive_msg(di, msg); + /* FIXME */ + msgb_free(rx); return 0; } int diag_dpl_get_sup_if(struct diag_instance *di) { struct msgb *msg = msgb_alloc_diag(); + struct msgb *rx; diag_push_subsys_hdr(msg, DIAG_SUBSYS_PS_DATA_LOGGING, DIAG_DPL_GET_SUPPORTED_IFACES); - diag_transmit_msgb(di, msg); - diag_read(di); + rx = diag_transceive_msg(di, msg); + /* FIXME */ + msgb_free(rx); return 0; } int diag_dpl_get_if_desc(struct diag_instance *di, uint8_t iface_id) { struct msgb *msg = msgb_alloc_diag(); + struct msgb *rx; struct dpl_get_if_desc_req *gidr; gidr = (struct dpl_get_if_desc_req *) msgb_put(msg, sizeof(*gidr)); gidr->iface_id = iface_id; diag_push_subsys_hdr(msg, DIAG_SUBSYS_PS_DATA_LOGGING, DIAG_DPL_GET_SUPPORTED_IFACES); - diag_transmit_msgb(di, msg); - diag_read(di); + rx = diag_transceive_msg(di, msg); + /* FIXME */ + msgb_free(rx); return 0; } -int diag_dpl_set_if_log(struct diag_instance *di, uint8_t iface_id) +int diag_dpl_set_if_log(struct diag_instance *di, uint8_t iface_id, + uint32_t iid, uint32_t link_type) { struct msgb *msg = msgb_alloc_diag(); struct dpl_set_if_log_req *silr; + struct msgb *rx; - silr = (struct dpl_get_if_desc_req *) msgb_put(msg, sizeof(*silr)); + silr = (struct dpl_set_if_log_req *) msgb_put(msg, sizeof(*silr)); silr->iface_id = iface_id; silr->num_log_flags = 1; - msgb_put(msg, sizeof(silr->log_flags[0]); - silr->log_flags[0].iid = FIXME; - silr->log_flags[0].link_type = FIXME; + msgb_put(msg, sizeof(silr->log_flags[0])); + silr->log_flags[0].iid = iid; + silr->log_flags[0].link_type = link_type; - diag_transmit_msgb(di, msg); - diag_read(di); + rx = diag_transceive_msg(di, msg); + /* FIXME */ + msgb_free(rx); return 0; } @@ -91,8 +101,8 @@ static void handle_pcap_msg(struct log_hdr *lh, struct msgb *msg) struct dpl_hdr *dh = (struct dpl_hdr *) msgb_data(msg); printf("(fl=0x%02x, ifn=0x%02x, prot=0x%02x, inst=%u, seq=%u, seg=%u): %s", dh->iid.flags, dh->iid.if_name, dh->iid.protocol, - dh->iid.link_instance, dh->seeq_nr, sh->seg_num, - osmo_hexdump(dh->data, msgb_len(msg)-sizeof(*dh))); + dh->iid.link_instance, dh->seq_nr, dh->seg_num, + osmo_hexdump(dh->data, msgb_length(msg)-sizeof(*dh))); } static const struct diag_log_dispatch_tbl log_tbl[] = { diff --git a/src/diag_io.c b/src/diag_io.c index f4a7f88..b4313bb 100644 --- a/src/diag_io.c +++ b/src/diag_io.c @@ -25,8 +25,14 @@ #include "protocol/protocol.h" #include "diag_io.h" +#include "diag_cmd.h" #include "diagchar_hdlc.h" +struct msgb *msgb_alloc_diag(void) +{ + return msgb_alloc(DIAG_MAX_REQ_SIZE, "DIAG Tx"); +} + /* transmit a msgb containing a DIAG message over the given fd */ int diag_transmit_msgb(struct diag_instance *di, struct msgb *msg) { @@ -61,7 +67,7 @@ int diag_transmit_msgb(struct diag_instance *di, struct msgb *msg) /* transmit a message from a buffer (nto msgb) as DIAG over the given fd */ int diag_transmit_buf(struct diag_instance *di, const uint8_t *data, size_t data_len) { - struct msgb *msg = msgb_alloc(DIAG_MAX_REQ_SIZE, "DIAG Tx"); + struct msgb *msg = msgb_alloc_diag(); memcpy(msg->tail, data, data_len); msgb_put(msg, data_len); @@ -69,7 +75,7 @@ int diag_transmit_buf(struct diag_instance *di, const uint8_t *data, size_t data return diag_transmit_msgb(di, msg); } -int diag_read(struct diag_instance *di) +struct msgb *diag_read_msg(struct diag_instance *di) { uint8_t buf[DIAG_MAX_HDLC_BUF_SIZE]; struct diag_hdlc_decode_type hdlc_decode; @@ -78,9 +84,9 @@ int diag_read(struct diag_instance *di) /* read raw data into buffer */ rc = read(di->fd, buf, sizeof(buf)); - if (rc <= 0 ) { + if (rc <= 0) { fprintf(stderr, "Short read!\n"); - return -EIO; + exit(1); } if (!di->rx.msg) { @@ -102,7 +108,7 @@ int diag_read(struct diag_instance *di) fprintf(stderr, "Dropping packet. pkt_size: %d, max: %d\n", msgb_length(msg) + hdlc_decode.dest_idx, DIAG_MAX_REQ_SIZE); - return -EIO; + return NULL; } msgb_put(msg, hdlc_decode.dest_idx); @@ -112,22 +118,71 @@ int diag_read(struct diag_instance *di) rc = crc_check(msgb_data(msg), msgb_length(msg)); if (rc) { fprintf(stderr, "Bad CRC, dropping packet\n"); - msgb_free(msg); - return -EINVAL; + //msgb_free(msg); + //return NULL; } msgb_get(msg, HDLC_FOOTER_LEN); if (msgb_length(msg) < 1) { fprintf(stderr, "Message too short, len: %u\n", msgb_length(msg)); msgb_free(msg); - return -EINVAL; + return NULL; } - - if (di->rx.rcvmsg) - (di->rx.rcvmsg)(di, msg); - else - msgb_free(msg); + return msg; } - return 0; + return NULL; }; + +/* transmit a message, wait for response, return response */ +struct msgb *diag_transceive_msg(struct diag_instance *di, struct msgb *tx) +{ + struct msgb *rx; + int rc; + + /* transmit the tx message */ + diag_transmit_msgb(di, tx); + printf("Tx, waiting for Rx\n"); + + /* blocking loop and process incoming messages until there is + * one for which we don't have a parser registered, let's assume + * that this is our response */ + while (1) { + rx = diag_read_msg(di); + printf("Rx, handing off..."); + if (rx) { + rc = diag_process_msg(di, rx); + printf("rc = %d\n", rc); + if (rc == 0) + return rx; + } + } + return NULL; +} + +/* transmit a message, wait for response, then ignore response */ +void diag_transceive_msg_ign(struct diag_instance *di, struct msgb *tx) +{ + struct msgb *rx; + + rx = diag_transceive_msg(di, tx); + msgb_free(rx); +} + +/* transmit a message from a buffer, wait for response, return it */ +struct msgb *diag_transceive_buf(struct diag_instance *di, const uint8_t *data, size_t data_len) +{ + struct msgb *msg = msgb_alloc_diag(); + + memcpy(msg->tail, data, data_len); + msgb_put(msg, data_len); + + return diag_transceive_msg(di, msg); +} + +/* transmit a message from a buffer, wait for response, ignore it */ +void diag_transceive_buf_ign(struct diag_instance *di, const uint8_t *data, size_t data_len) +{ + struct msgb *rx = diag_transceive_buf(di, data, data_len); + msgb_free(rx); +} diff --git a/src/diag_io.h b/src/diag_io.h index c02ce82..953a089 100644 --- a/src/diag_io.h +++ b/src/diag_io.h @@ -8,13 +8,18 @@ struct diag_instance { int fd; struct { struct msgb *msg; - void (*rcvmsg)(struct diag_instance *di, struct msgb *msg); } rx; struct { } tx; struct gsmtap_inst *gsmtap; }; +struct msgb *msgb_alloc_diag(void); int diag_transmit_msgb(struct diag_instance *di, struct msgb *msg); int diag_transmit_buf(struct diag_instance *di, const uint8_t *data, size_t data_len); -int diag_read(struct diag_instance *di); +struct msgb *diag_read_msg(struct diag_instance *di); +int diag_process_msg(struct diag_instance *di, struct msgb *msg); +struct msgb *diag_transceive_msg(struct diag_instance *di, struct msgb *tx); +void diag_transceive_msg_ign(struct diag_instance *di, struct msgb *tx); +struct msgb *diag_transceive_buf(struct diag_instance *di, const uint8_t *data, size_t data_len); +void diag_transceive_buf_ign(struct diag_instance *di, const uint8_t *data, size_t data_len); diff --git a/src/diag_log.c b/src/diag_log.c index 55cc6aa..302787b 100644 --- a/src/diag_log.c +++ b/src/diag_log.c @@ -102,7 +102,7 @@ void diag_log_reg_dispatch(const struct diag_log_dispatch_tbl *tbl, unsigned int void diag_log_enable_all_supported_family(struct diag_instance *di, uint8_t family) { - struct msgb *msg; + struct msgb *msg, *rx; unsigned int i, size; unsigned int family_base = (family & 0xf) << 12; unsigned int max = 0; @@ -125,8 +125,9 @@ void diag_log_enable_all_supported_family(struct diag_instance *di, uint8_t fami log_config_set_mask_bit(msg, i-family_base); } - diag_transmit_msgb(di, msg); - diag_read(di); + rx = diag_transceive_msg(di, msg); + /* FIXME */ + msgb_free(rx); } void diag_log_enable_all_supported(struct diag_instance *di) diff --git a/src/diag_msg.c b/src/diag_msg.c index 1301ad0..f65a8f4 100644 --- a/src/diag_msg.c +++ b/src/diag_msg.c @@ -58,8 +58,11 @@ struct msgb *gen_msg_config_set_rt_mask(uint16_t ssid, uint32_t runtime_mask) int diag_msg_config_set_rt_mask(struct diag_instance *di, uint16_t ssid, uint32_t runtime_mask) { struct msgb *msg = gen_msg_config_set_rt_mask(ssid, runtime_mask); - diag_transmit_msgb(di, msg); - diag_read(di); + struct msgb *rx; + + rx = diag_transceive_msg(di, msg); + /* FIXME */ + msgb_free(rx); return 0; } diff --git a/src/osmo-qcdiag-log.c b/src/osmo-qcdiag-log.c index 33a9cb1..a867955 100644 --- a/src/osmo-qcdiag-log.c +++ b/src/osmo-qcdiag-log.c @@ -40,29 +40,10 @@ #include "diag_io.h" #include "diag_log.h" #include "diag_msg.h" +#include "diag_cmd.h" #include "protocol/protocol.h" #include "protocol/diagcmd.h" -/*********/ - -static void diag_process_msg(struct diag_instance *di, struct msgb *msg) -{ - switch (msg->l2h[0]) { - case DIAG_LOG_F: - diag_log_handle(di, msg); - break; - case DIAG_EXT_MSG_F: - diag_rx_ext_msg_f(di, msg); - break; - default: - printf("Got %d bytes data of unknown payload type 0x%02x: %s\n", - msgb_length(msg), msg->l2h[0], - osmo_hexdump(msgb_data(msg), msgb_length(msg))); - break; - } - msgb_free(msg); -} - static void do_configure(struct diag_instance *di) { static uint8_t timestamp[] = { DIAG_TS_F }; @@ -74,16 +55,13 @@ static void do_configure(struct diag_instance *di) }; /* TODO: introduce a wait for response kind of method */ - diag_transmit_buf(di, timestamp, sizeof(timestamp)); - diag_read(di); + diag_transceive_buf_ign(di, timestamp, sizeof(timestamp)); /* enable|disable the event report */ #if 0 - diag_transmit_buf(di, enable_evt_report, sizeof(enable_evt_report)); - diag_read(di); + diag_transceive_buf_ign(di, enable_evt_report, sizeof(enable_evt_report)); #else - diag_transmit_buf(di, disable_evt_report, sizeof(disable_evt_report)); - diag_read(di); + diag_transceive_buf_ign(di, disable_evt_report, sizeof(disable_evt_report)); #endif diag_msg_config_set_rt_mask(di, MSG_SSID_LINUX_DATA, 0xffffffff); diag_msg_config_set_rt_mask(di, 5012, 0xffffffff); @@ -115,8 +93,7 @@ static void do_configure(struct diag_instance *di) log_config_set_mask_bit(msg, LOG_EGPRS_MAC_UL_ACKNACK_C); log_config_set_mask_bit(msg, LOG_EGPRS_MAC_DL_ACKNACK_C); - diag_transmit_msgb(di, msg); - diag_read(di); + diag_tranceive_msgb(di, msg); printf("WCDMA\n"); msg = gen_log_config_set_mask(4, 1064); @@ -130,8 +107,7 @@ static void do_configure(struct diag_instance *di) log_config_set_mask_bit(msg, 0x128); log_config_set_mask_bit(msg, 0x129); - diag_transmit_msgb(di, msg); - diag_read(di); + diag_tranceive_msgb(di, msg); #else diag_log_enable_all_supported(di); #endif @@ -150,7 +126,6 @@ int main(int argc, char **argv) } memset(&di, 0, sizeof(di)); - di.rx.rcvmsg = &diag_process_msg; di.fd = osmo_serial_init(argv[1], 921600); if (di.fd < 0) return EXIT_FAILURE; @@ -162,9 +137,9 @@ int main(int argc, char **argv) while (1) { i++; - rc = diag_read(&di); - if (rc == -EIO) - break; + struct msgb *rx = diag_read_msg(&di); + if (rx) + diag_process_msg(&di, rx); #if 0 /* some packets need to be explicitly requested and * don't appear automatically */ diff --git a/src/protocol/dpl.h b/src/protocol/dpl.h index 065598a..3698728 100644 --- a/src/protocol/dpl.h +++ b/src/protocol/dpl.h @@ -66,7 +66,7 @@ struct dpl_set_if_log_req { struct { uint32_t iid; uint32_t link_type; - } log_flag[0]; + } log_flags[0]; }; /* header pre-fixed to actual packet payload; as generated by |