diff options
-rw-r--r-- | tools/ipc-modem.c | 364 | ||||
-rw-r--r-- | tools/ipc-modem.h | 9 |
2 files changed, 285 insertions, 88 deletions
diff --git a/tools/ipc-modem.c b/tools/ipc-modem.c index 5977a7e..24d9806 100644 --- a/tools/ipc-modem.c +++ b/tools/ipc-modem.c @@ -19,6 +19,7 @@ */ #include <assert.h> +#include <errno.h> #include <fcntl.h> #include <getopt.h> #include <pthread.h> @@ -94,8 +95,6 @@ void modem_snd_audio_path_ctrl(struct ipc_client *client) IPC_TYPE_SET, (void *) &data, 1); } - - void modem_exec_call_out(struct ipc_client *client, char *num) { struct ipc_call_outgoing_data call_out; @@ -395,7 +394,8 @@ void modem_response_net(__attribute__((unused)) struct ipc_client *client, } } -void modem_response_handle(struct ipc_client *client, struct ipc_message *resp) +void modem_response_fmt_handle(struct ipc_client *client, + struct ipc_message *resp) { switch (IPC_GROUP(resp->command)) { case IPC_GROUP_NET: @@ -420,49 +420,85 @@ void modem_response_handle(struct ipc_client *client, struct ipc_message *resp) } } - -int modem_read_loop(struct ipc_client *client) +int modem_read(struct ipc_client *client, char const *channel_name) { struct ipc_message resp; + struct timeval timeout; int rc; memset(&resp, 0, sizeof(resp)); + timeout.tv_sec = 0; + timeout.tv_usec = 50000; + rc = ipc_client_poll(client, NULL, &timeout); + if (rc < 0) { + ipc_modem_log(client, + MODEM_LOG_ERROR, + "Poll of %s client failed\n", + channel_name); + return -1; + } + + if (rc == 0) { + /* timeout */ + return 0; + } + + rc = ipc_client_recv(client, &resp); + if (rc < 0) { + ipc_modem_log(client, + MODEM_LOG_ERROR, + "Can't RECV from %s channel: please run this again" + "\n", channel_name); + return -1; + } + + /* We have no RFS handler (yet) in ipc-modem */ + if (!strcmp(channel_name, "FMT")) + modem_response_fmt_handle(client, &resp); + + if (resp.data != NULL) + free(resp.data); + + return rc; +} + +void modem_read_loop(struct ipc_modem_client *modem_client) +{ + int rc; + while (1) { usleep(3000); - rc = ipc_client_poll(client, NULL, NULL); - if (rc < 0) - continue; + rc = modem_read(modem_client->client, modem_client->name); - rc = ipc_client_recv(client, &resp); - if (rc < 0) { - ipc_modem_log( - client, - MODEM_LOG_ERROR, - "Can't RECV from modem: please run this again" - "\n"); + switch (rc) { + case -1: + return; + case 0: + break; + default: break; } - - modem_response_handle(client, &resp); - - if (resp.data != NULL) - free(resp.data); } - return 0; + pthread_exit((void*)rc); } -int modem_dummy_read_loop(__attribute__((unused)) struct ipc_client *client) +void modem_dummy_read_loop(struct ipc_modem_client *modem_client) { + int rc = 0; + while (true) { - ipc_modem_log(client, - MODEM_LOG_INFO, "%s: looping\n", __func__); + ipc_modem_log(modem_client->client, + MODEM_LOG_INFO, + "%s: looping for the %s channel\n", + __func__, + modem_client->name); sleep(1); } - return 0; + pthread_exit((void*)rc); } void modem_log_handler(void *user_data, const char *msg) @@ -513,34 +549,110 @@ void ipc_modem_log(__attribute__((unused)) struct ipc_client *client, modem_log_handler(prefix, buffer); } -int modem_start(struct ipc_client *client) +int modem_start(struct ipc_client *client_fmt, struct ipc_client *client_rfs) { int rc = -1; - ipc_client_data_create(client); - rc = ipc_client_boot(client); - if (rc < 0) - return -1; + /* We need to boot the modem before opening the channels */ + ipc_client_data_create(client_fmt); + rc = ipc_client_boot(client_fmt); + if (rc < 0) + return -1; + usleep(300); + + /* Then we open the RFS channel as this should be done at the end + * of the boot, before opening the FMT channel as at least on + * one herolte kernel, the modem kernel drivers requires it. + */ + if (client_rfs) { + ipc_client_data_create(client_rfs); + rc = ipc_client_open(client_rfs); + if (rc < 0) { + ipc_modem_log(client_rfs, MODEM_LOG_ERROR, "Something went wrong " + "opening the RFS channel\n"); + return -1; + } + } - usleep(300); + /* Then we finally open the FMT channel */ + rc = ipc_client_open(client_fmt); + if (rc < 0) + return -1; - rc = ipc_client_open(client); - if (rc < 0) - return -1; + /* Some modem like aries have power_on callbacks that + * need to be called after booting the modem + */ + rc = ipc_client_power_on(client_fmt); + if (rc < 0) + return -1; - rc = ipc_client_power_on(client); - if (rc < 0) - return -1; + return 0; +} + +int modem_stop(struct ipc_client *client_fmt, struct ipc_client *client_rfs) +{ + if (client_rfs) + ipc_client_close(client_fmt); + + ipc_client_power_off(client_fmt); + ipc_client_close(client_fmt); return 0; } -int modem_stop(struct ipc_client *client) +int modem_create_channel_thread(struct ipc_modem_client *modem_client, + struct cmdline_opts *cmdline_opts) { - ipc_client_power_off(client); - ipc_client_close(client); + int rc; - return 0; + if (cmdline_opts->dry_run) + ipc_modem_log(modem_client->client, + "2", + "Starting modem_dummy_read_loop on %s client\n", + modem_client->name); + else + ipc_modem_log(modem_client->client, + "2", + "Starting modem_read_loop on %s client\n", + modem_client->name); + + rc = pthread_attr_init(&modem_client->attr); + if (rc) { + ipc_modem_log(modem_client->client, + "2", + "%s pthread_attr_init failed with error %d\n", + modem_client->name, rc); + return rc; + } + + if (rc) { + ipc_modem_log(modem_client->client, + MODEM_LOG_ERROR, + "%s pthread_attr_setdetachstate failed with error %d\n", + modem_client->name, rc); + return rc; + } + + if (cmdline_opts->dry_run) { + rc = pthread_create(&modem_client->thread, + &modem_client->attr, + (void *) modem_dummy_read_loop, + (void *) modem_client); + } + else + rc = pthread_create(&modem_client->thread, + &modem_client->attr, + (void *) modem_read_loop, + (void *) modem_client); + if (rc) { + ipc_modem_log(modem_client->client, + MODEM_LOG_ERROR, + "%s pthread_create failed with error %d\n", + modem_client->name, rc); + return rc; + } + + return rc; } void print_help(void) @@ -560,22 +672,59 @@ void print_help(void) "\t--help print this help message\n" "\t--log-target=[stdout|syslog] " "direct logs to stdout or syslog\n" - "\t--pin=[PIN] provide SIM card PIN\n"); + "\t--pin=[PIN] provide SIM card PIN\n" + "\t--rfs enable RFS client in addition to FMT client\n"); } -int handle_command(struct ipc_client *client, - struct cmdline_opts *cmdline_opts) +int create_client(struct ipc_client **client, int client_type, + struct cmdline_opts *cmdline_opts) +{ + if (cmdline_opts->dry_run) + client_type = IPC_CLIENT_TYPE_DUMMY; + + *client = ipc_client_create(client_type); + if (*client == 0) { + printf("[E] Could not create IPC %s client; aborting ...\n", + ipc_client_type_string(client_type)); + return -1; + } + + if (cmdline_opts->debug) + ipc_client_log_callback_register(*client, modem_log_handler, + NULL); + else + ipc_client_log_callback_register(*client, + modem_log_handler_quiet, NULL); + return 0; +} + +int handle_command(struct cmdline_opts *cmdline_opts, + struct ipc_client *dummy_client, + struct ipc_modem_client *modem_client_fmt, + struct ipc_modem_client *modem_client_rfs) { int rc = 0; + modem_client_fmt->name = "FMT"; + modem_client_rfs->name = "RFS"; + + rc = create_client(&modem_client_fmt->client, IPC_CLIENT_TYPE_FMT, + cmdline_opts); + if (rc) + goto modem_quit; + + if (cmdline_opts->rfs) + rc = create_client(&modem_client_rfs->client, IPC_CLIENT_TYPE_RFS, + cmdline_opts); + switch (cmdline_opts->command) { case CMD_POWER_ON: if (cmdline_opts->dry_run) break; - rc = ipc_client_power_on(client); + rc = ipc_client_power_on(modem_client_fmt->client); if (rc < 0) - ipc_modem_log(client, "[E]", + ipc_modem_log(dummy_client, "[E]", "[E] Something went wrong " "while powering modem on\n"); goto modem_quit; @@ -583,9 +732,9 @@ int handle_command(struct ipc_client *client, if (cmdline_opts->dry_run) break; - rc = ipc_client_power_off(client); + rc = ipc_client_power_off(modem_client_fmt->client); if (rc < 0) - ipc_modem_log(client, + ipc_modem_log(dummy_client, MODEM_LOG_ERROR, "Something went wrong " "while powering modem off\n"); @@ -594,45 +743,72 @@ int handle_command(struct ipc_client *client, if (cmdline_opts->dry_run) break; - rc = ipc_client_boot(client); + rc = ipc_client_boot(modem_client_fmt->client); if (rc < 0) - ipc_modem_log(client, + ipc_modem_log(dummy_client, MODEM_LOG_ERROR, "Something went wrong " "while bootstrapping modem\n"); break; case CMD_START: - if (cmdline_opts->dry_run) { - ipc_modem_log( - client, - "1", - "Starting dummy modem_read_loop on %s client\n", - "FMT"); - modem_dummy_read_loop(client); - break; + ipc_modem_log(modem_client_fmt->client, + "0", + "Starting modem FMT client\n"); + if (!cmdline_opts->dry_run) { + rc = modem_start(modem_client_fmt->client, modem_client_rfs->client); + if (rc < 0) { + ipc_modem_log(dummy_client, + MODEM_LOG_ERROR, + "Something went wrong " + "starting FMT client\n"); + modem_stop(modem_client_fmt->client, modem_client_rfs->client); + return 1; + } } - ipc_modem_log(client, - "0", "Starting modem on FMT client\n"); + if (cmdline_opts->rfs) { + ipc_modem_log(dummy_client, "1", "Starting modem RFS thread\n"); + rc = modem_create_channel_thread(modem_client_rfs, + cmdline_opts); + if (rc) + return rc; + } else { + ipc_modem_log(dummy_client, "1", "Skipping modem RFS client start\n"); + } - rc = modem_start(client); - if (rc < 0) { - ipc_modem_log(client, - MODEM_LOG_ERROR, - "Something went wrong\n"); - modem_stop(client); - return 1; + ipc_modem_log(dummy_client, "1", "Starting modem FMT thread\n"); + rc = modem_create_channel_thread(modem_client_fmt, cmdline_opts); + + while (true) { + int *thread_rc; + + ipc_modem_log(dummy_client, MODEM_LOG_INFO, "Checking threads\n"); + + if (0 && cmdline_opts->rfs) { + rc = pthread_join(modem_client_rfs->thread, (void**)&thread_rc); + if (rc != EINVAL) + ipc_modem_log(dummy_client, + MODEM_LOG_ERROR, + "%s Thread exited with error: %d\n", + modem_client_rfs->name, + *thread_rc); + } + + rc = pthread_join(modem_client_fmt->thread, (void**)&thread_rc); + if (!rc) { + ipc_modem_log(dummy_client, + MODEM_LOG_ERROR, + "%s: pthread_join = %d\n", + modem_client_fmt->name, + thread_rc); + } + sleep(1); } - ipc_modem_log(client, - "1", - "Starting modem_read_loop on FMT client\n"); - modem_read_loop(client); - modem_stop(client); break; default: /* We should handle all commands */ - ipc_modem_log(client, + ipc_modem_log(dummy_client, MODEM_LOG_ERROR, "%s: Unknown command %d\n", __func__, cmdline_opts->command); @@ -641,8 +817,12 @@ int handle_command(struct ipc_client *client, } modem_quit: - if (client != 0) - ipc_client_destroy(client); + if (modem_client_fmt->client != 0) + ipc_client_destroy(modem_client_fmt->client); + if (modem_client_rfs->client != 0) + ipc_client_destroy(modem_client_rfs->client); + if (dummy_client != 0) + ipc_client_destroy(dummy_client); return rc; } @@ -660,7 +840,9 @@ void print_cmdline_opts(struct ipc_client *client, int main(int argc, char *argv[]) { struct cmdline_opts cmdline_opts; - struct ipc_client *client; + struct ipc_client *dummy_client; + struct ipc_modem_client modem_client_fmt; + struct ipc_modem_client modem_client_rfs; int c = 0; int opt_i = 0; @@ -671,10 +853,13 @@ int main(int argc, char *argv[]) {"help", no_argument, 0, 0 }, {"log-target", required_argument, 0, 0 }, {"pin", required_argument, 0, 0 }, + {"rfs", no_argument, 0, 0 }, {0, 0, 0, 0 } }; - bzero((void *)&cmdline_opts, sizeof(cmdline_opts)); + bzero((void*)&modem_client_fmt, sizeof(modem_client_fmt)); + bzero((void*)&modem_client_rfs, sizeof(modem_client_rfs)); + bzero((void*)&cmdline_opts, sizeof(cmdline_opts)); if (argc < 2) { print_help(); @@ -698,6 +883,9 @@ int main(int argc, char *argv[]) "Call number is too long!\n"); return 1; } + } else if (strcmp(opt_l[opt_i].name, "rfs") == 0) { + cmdline_opts.rfs = true; + printf("[I] RFS enabled\n"); } } else if ((strcmp(opt_l[opt_i].name, "log-target") == 0)) { if (optarg && !strcmp(optarg, "syslog")) { @@ -728,22 +916,19 @@ int main(int argc, char *argv[]) } } - if (cmdline_opts.dry_run) - client = ipc_client_create(IPC_CLIENT_TYPE_DUMMY); - else - client = ipc_client_create(IPC_CLIENT_TYPE_FMT); + dummy_client = ipc_client_create(IPC_CLIENT_TYPE_DUMMY); - if (client == 0) { - printf("[E] Could not create IPC client; aborting ...\n"); + if (dummy_client == 0) { + printf("[E] Could not create dummy IPC client; aborting ...\n"); return 1; } if (cmdline_opts.debug == 0) - ipc_client_log_callback_register(client, + ipc_client_log_callback_register(dummy_client, modem_log_handler_quiet, NULL); else - ipc_client_log_callback_register(client, + ipc_client_log_callback_register(dummy_client, modem_log_handler, NULL); @@ -761,7 +946,7 @@ int main(int argc, char *argv[]) cmdline_opts.command = CMD_START; break; } else { - ipc_modem_log(client, + ipc_modem_log(dummy_client, MODEM_LOG_ERROR, "Unknown argument: '%s'\n", argv[optind]); @@ -781,7 +966,10 @@ int main(int argc, char *argv[]) return 1; } - print_cmdline_opts(client, &cmdline_opts); + print_cmdline_opts(dummy_client, &cmdline_opts); - return handle_command(client, &cmdline_opts); + return handle_command(&cmdline_opts, + dummy_client, + &modem_client_fmt, + &modem_client_rfs); } diff --git a/tools/ipc-modem.h b/tools/ipc-modem.h index 0b31d83..ef4bda5 100644 --- a/tools/ipc-modem.h +++ b/tools/ipc-modem.h @@ -46,6 +46,15 @@ struct cmdline_opts { enum command command; bool debug; bool dry_run; + bool rfs; +}; + +struct ipc_modem_client { + char *name; + pthread_t thread; + pthread_mutex_t mutex; + pthread_attr_t attr; + struct ipc_client *client; }; void ipc_modem_log(struct ipc_client *client, |