diff options
-rw-r--r-- | tools/ipc-modem.c | 319 |
1 files changed, 242 insertions, 77 deletions
diff --git a/tools/ipc-modem.c b/tools/ipc-modem.c index dad95fc..c09d0a8 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> @@ -58,9 +59,18 @@ enum command { }; struct cmdline_opts { - enum command command; + uint32_t 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; }; int seq_get(void) @@ -105,8 +115,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; @@ -364,7 +372,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: @@ -389,46 +398,79 @@ 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) { + printf("[E] 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) { + printf("[E] " + "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) { - printf("[E] " - "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(struct ipc_client *client) +void modem_dummy_read_loop(struct ipc_modem_client *modem_client) { - while (1) { - printf("[I] %s: looping\n", __FUNCTION__); + int rc = 0; + + while (true) { + printf("[I] %s: looping for the %s channel\n", + __FUNCTION__, + modem_client->name); sleep(1); } - return 0; + pthread_exit((void*)rc); } void modem_log_handler(__attribute__((unused)) void *user_data, @@ -459,34 +501,100 @@ void modem_log_handler_quiet(__attribute__((unused)) void *user_data, { } -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) { + printf("[E] 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) + printf("[2] Starting modem_dummy_read_loop on %s client\n", + modem_client->name); + else + printf("[2] Starting modem_read_loop on %s client\n", + modem_client->name); + + rc = pthread_attr_init(&modem_client->attr); + if (rc) { + printf("[E] %s pthread_attr_init failed with error %d\n", + modem_client->name, rc); + return rc; + } + + if (rc) { + printf("[E] %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) { + printf("[E] %s pthread_create failed with error %d\n", + modem_client->name, rc); + return rc; + } + + return rc; } void print_help(void) @@ -504,37 +612,55 @@ void print_help(void) "Test the ipc-modem program without talking to the modem.\n"); printf("\t--help print this help message\n"); printf("\t--pin=[PIN] provide SIM card PIN\n"); + printf("\t--rfs enable RFS client in addition to FMT client\n"); } -int handle_command(struct cmdline_opts *cmdline_opts) +int create_client(struct ipc_client **client, int client_type, + struct cmdline_opts *cmdline_opts) { - struct ipc_client *client_fmt; - int rc = 0; - if (cmdline_opts->dry_run) - client_fmt = ipc_client_create(IPC_CLIENT_TYPE_DUMMY); - else - client_fmt = ipc_client_create(IPC_CLIENT_TYPE_FMT); + client_type = IPC_CLIENT_TYPE_DUMMY; - if (client_fmt == 0) { - printf("[E] Could not create IPC client; aborting ...\n"); - goto modem_quit; + *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 == 0) { - ipc_client_log_callback_register(client_fmt, - modem_log_handler_quiet, NULL); - } else { - ipc_client_log_callback_register(client_fmt, modem_log_handler, + 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_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_fmt); + rc = ipc_client_power_on(modem_client_fmt->client); if (rc < 0) printf("[E] Something went wrong " "while powering modem on\n"); @@ -543,7 +669,7 @@ int handle_command(struct cmdline_opts *cmdline_opts) if (cmdline_opts->dry_run) break; - rc = ipc_client_power_off(client_fmt); + rc = ipc_client_power_off(modem_client_fmt->client); if (rc < 0) printf("[E] Something went wrong " "while powering modem off\n"); @@ -552,34 +678,61 @@ int handle_command(struct cmdline_opts *cmdline_opts) if (cmdline_opts->dry_run) break; - rc = ipc_client_boot(client_fmt); + rc = ipc_client_boot(modem_client_fmt->client); if (rc < 0) printf("[E] Something went wrong " "while bootstrapping modem\n"); break; case CMD_START: - if (cmdline_opts->dry_run) { - printf("[1] " - "Starting dummy modem_read_loop on %s client\n", - "FMT"); - modem_dummy_read_loop(client_fmt); - break; + + printf("[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) { + printf("[E] Something went wrong " + "starting FMT client\n"); + modem_stop(modem_client_fmt->client, modem_client_rfs->client); + return 1; + } + } + + if (cmdline_opts->rfs) { + printf("[1] Starting modem RFS thread\n"); + rc = modem_create_channel_thread(modem_client_rfs, + cmdline_opts); + if (rc) + return rc; + } else { + printf("[1] Skipping modem RFS client start\n"); } - printf("[0] Starting modem on FMT client\n"); + printf("[1] Starting modem FMT thread\n"); + rc = modem_create_channel_thread(modem_client_fmt, cmdline_opts); - rc = modem_start(client_fmt); - if (rc < 0) { - printf("[E] Something went wrong\n"); - modem_stop(client_fmt); - return 1; + while (true) { + int *thread_rc; + + printf("[I] checking threads\n"); + + if (0 && cmdline_opts->rfs) { + rc = pthread_join(modem_client_rfs->thread, (void**)&thread_rc); + if (rc != EINVAL) + printf("[E] %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) { + printf("[E] %s: pthread_join = %d\n", + modem_client_fmt->name, thread_rc); + } + sleep(1); } - printf("[1] Starting modem_read_loop on FMT client\n"); - modem_read_loop(client_fmt); - modem_stop(client_fmt); break; default: + printf("ERROR: unknown CMD %d\n", cmdline_opts->command); /* We should handle all commands */ printf("[E] %s: Unknown command %d\n", __FUNCTION__, cmdline_opts->command); @@ -588,8 +741,10 @@ int handle_command(struct cmdline_opts *cmdline_opts) } modem_quit: - if (client_fmt != 0) - ipc_client_destroy(client_fmt); + 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); return rc; } @@ -606,6 +761,8 @@ void print_cmdline_opts(struct cmdline_opts *cmdline_opts) int main(int argc, char *argv[]) { struct cmdline_opts cmdline_opts; + struct ipc_modem_client modem_client_fmt; + struct ipc_modem_client modem_client_rfs; int c = 0; int opt_i = 0; @@ -615,9 +772,12 @@ int main(int argc, char *argv[]) {"dry-run", no_argument, 0, 0 }, {"help", no_argument, 0, 0 }, {"pin", required_argument, 0, 0 }, + {"rfs", no_argument, 0, 0 }, {0, 0, 0, 0 } }; + 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) { @@ -666,6 +826,9 @@ int main(int argc, char *argv[]) printf("[E] SIM PIN 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"); } break; @@ -705,5 +868,7 @@ int main(int argc, char *argv[]) print_cmdline_opts(&cmdline_opts); - return handle_command(&cmdline_opts); + return handle_command(&cmdline_opts, + &modem_client_fmt, + &modem_client_rfs); } |