FreeCalypso > hg > freecalypso-tools
view rvinterf/asyncshell/tchcmd.c @ 951:297c7d5b57a2
doc/Rvinterf-logs: new document
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 07 Jun 2023 07:52:55 +0000 |
parents | 2e6764022292 |
children |
line wrap: on
line source
/* * Commands for manipulating the experimental TCH rerouting feature * of FreeCalypso GSM firmware */ #include <sys/types.h> #include <stdio.h> #include <string.h> #include <strings.h> #include <stdlib.h> #include "pktmux.h" #include "limits.h" #include "tch_feature.h" #include "exitcodes.h" extern u_char rvi_msg[]; extern int rvi_msg_len; static int tch_rawdump_mode; send_tch_config_req(config) { u_char sendpkt[3]; sendpkt[0] = RVT_TCH_HEADER; sendpkt[1] = TCH_CONFIG_REQ; sendpkt[2] = config; /* send it! */ send_pkt_to_target(sendpkt, 3); return(0); } cmd_tchdl_common(argc, argv) char **argv; { int config; if (!strcmp(argv[0], "enable") || !strcmp(argv[0], "on") || !strcmp(argv[0], "1")) config = 1; else if (!strcmp(argv[0], "disable") || !strcmp(argv[0], "off") || !strcmp(argv[0], "0")) config = 0; else { printf("error: boolean argument required\n"); return(ERROR_USAGE); } return send_tch_config_req(config); } void cmd_tchdl_interactive(argstr) char *argstr; { char *argv[2]; int argc, rc; rc = parse_interactive_command_into_argv(argstr, argv, 1, 1, &argc); if (rc < 0) return; tch_rx_control(1); cmd_tchdl_common(argc, argv); } cmd_tchdl_oneshot(argc, argv) char **argv; { return cmd_tchdl_common(argc - 1, argv + 1); } static void tch_rawdump() { char buf[MAX_PKT_FROM_TARGET*3+5], *dp; u_char *cp, *endp; cp = rvi_msg + 2; endp = rvi_msg + rvi_msg_len; strcpy(buf, "TCH:"); dp = buf + 4; while (cp < endp) { sprintf(dp, " %02X", *cp++); dp += 3; } *dp = '\0'; async_msg_output(buf); } void tch_packet_rx() { char buf[128], *mode_kw; int expect_pktlen, databytes; if (tch_rawdump_mode) { tch_rawdump(); return; } if (rvi_msg_len < 3) { inv: async_msg_output("Error: invalid TCH packet received"); return; } switch (rvi_msg[2]) { case TCH_CONFIG_CONF: if (rvi_msg_len != 4) goto inv; if (rvi_msg[3] & 0xFE) goto inv; sprintf(buf, "TCH_CONFIG_CONF: DL forwarding is %s", rvi_msg[3] ? "enabled" : "disabled"); async_msg_output(buf); return; case TCH_ULBITS_CONF: if (rvi_msg_len != 3) goto inv; tch_ulbits_conf(); return; case TCH_DLBITS_OLD_IND: if (rvi_msg_len != 43) goto inv; tch_dlbits_old_handler(); return; case TCH_DLBITS_NEW_IND: if (rvi_msg_len < 4) goto inv; switch (rvi_msg[3]) { case TCH_FS_MODE: mode_kw = "FR"; expect_pktlen = 45; databytes = 33; break; case TCH_HS_MODE: mode_kw = "HR"; expect_pktlen = 27; databytes = 15; break; case TCH_EFR_MODE: mode_kw = "EFR"; expect_pktlen = 45; databytes = 33; break; default: goto inv; } if (rvi_msg_len != expect_pktlen) goto inv; tch_dlbits_new_handler(mode_kw, databytes); return; default: goto inv; } } static void cmd_tch_dumpraw(argc, argv) char **argv; { if (argc < 2) { printf("error: too few arguments\n"); return; } if (!strcmp(argv[1], "enable") || !strcmp(argv[1], "on") || !strcmp(argv[1], "1")) tch_rawdump_mode = 1; else if (!strcmp(argv[1], "disable") || !strcmp(argv[1], "off") || !strcmp(argv[1], "0")) tch_rawdump_mode = 0; else printf("error: boolean argument required\n"); } static void cmd_tch_status(argc, argv) char **argv; { if (argc > 1) { printf("error: too many arguments\n"); return; } show_tch_record_status(); show_tch_play_status(); printf("TCH raw dump mode is %s\n", tch_rawdump_mode ? "enabled" : "disabled"); } void cmd_tch_dispatch(argstr) char *argstr; { char *argv[3]; int argc, rc; rc = parse_interactive_command_into_argv(argstr, argv, 1, 2, &argc); if (rc < 0) return; if (!strcmp(argv[0], "dump-raw")) { cmd_tch_dumpraw(argc, argv); return; } if (!strcmp(argv[0], "play")) { cmd_tch_play(argc, argv); return; } if (!strcmp(argv[0], "record")) { cmd_tch_record(argc, argv); return; } if (!strcmp(argv[0], "status")) { cmd_tch_status(argc, argv); return; } printf("error: invalid tch subcommand\n"); }