aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/ipc-modem.c319
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);
}