diff options
author | Tony Garnock-Jones <tonyg@leastfixedpoint.com> | 2020-09-29 22:03:07 +0200 |
---|---|---|
committer | Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> | 2022-09-08 18:09:20 +0200 |
commit | 6fcec3c5827efce6d46240d35ca8b623874c5e7a (patch) | |
tree | 38e9b87d8aad5b4f2da93d3f984e9f0ed9555063 | |
parent | 91ac87c54b942977bec90d44329d4146dac2435f (diff) | |
download | hardware_replicant_libsamsung-ipc-6fcec3c5827efce6d46240d35ca8b623874c5e7a.tar.gz hardware_replicant_libsamsung-ipc-6fcec3c5827efce6d46240d35ca8b623874c5e7a.tar.bz2 hardware_replicant_libsamsung-ipc-6fcec3c5827efce6d46240d35ca8b623874c5e7a.zip |
ipc-modem: Add support for RFSpatches-todo/ipc-modem-rfs-from-Tony-Garnock-Jones-v3-rebase
Cornucopia isn't maintained anymore and depended on
libsamsung-ipc's Vala bindings which have been removed by
commit ff8032e4c25f ("Deprecated and unmaintained vapi removal").
So beside using oFono patches to or libsamsung-ril through
libhybris, tools like ipc-modem, ipc-test are pretty much
the only way to test modems under GNU/Linux, and being able
to test the RFS support is useful.
In addition herolte (a Galaxy S7 variant), has a check
in its kernel that prevents ipc-modem to work if the RFS
channel is not opened[1]:
static bool rild_ready(struct link_device *ld)
{
[...]
fmt_iod = link_get_iod_with_channel(ld,
SIPC5_CH_ID_FMT_0);
if (!fmt_iod) {
mif_err("%s: No FMT io_device\n", ld->name);
return false;
}
rfs_iod = link_get_iod_with_channel(ld, SIPC5_CH_ID_RFS_0);
if (!rfs_iod) {
mif_err("%s: No RFS io_device\n", ld->name);
return false;
}
[...]
}
So when adding support for such devices, being able use ipc-modem
to easily test if it works is also very useful.
[1]drivers/misc/modem_v1/link_device_shmem.c from
https://github.com/ivanmeler/android_kernel_samsung_herolte
with the lineage-17.0 branch
Signed-off-by: Tony Garnock-Jones <tonyg@leastfixedpoint.com>
GNUtoo: rewrote the commit message, whitespace fixes.
Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
=======================================================================
=======================================================================
=======================================================================
TODO:
=====
- Finish addressing all the review concerns
- Send it for review again (if possible involve Tony for testing +
review)
Review things to address:
========================
> + return 0;
Thanks a lot: That check wasn't there before as we had that instead:
> rc = ipc_client_poll(client, NULL, NULL);
> if (rc < 0)
> continue;
So here when rc was 0, it would then run that:
> rc = ipc_client_recv(client, &resp);
> if (rc < 0) {
> [...]
> break;
> }
This is because for some devices this will call
xmm626_kernel_smdk4412_fmt_recv that has the following:
> rc = client->handlers->read(client, client->handlers->transport_data,
> buffer, length);
> if (rc < (int) sizeof(struct ipc_fmt_header)) {
> [...]
> goto error;
> }
And client->handlers->read can be xmm626_kernel_smdk4412_read which
just wraps a read call. And read can return 0 if there is nothing to
read yet.
So if I understood correctly, we could have read too soon, and that
would make ipc-modem stop due to an error.
In any case it's also best to create a separate patch to fix that
before this patch as if there is any regression we could easily pinpoint
that to this exact change.
Do you want me to do this patch? or do you want to do it?
%<------------------------------------------------------------------->%
> + if (resp.data != NULL)
> + free(resp.data);
> +
> + return 1;
> +}
If you switch the name of that function to modem_read, you could just
return rc (including when there is a timeout). This way it would look
like the semantics of the read() function. As read also return -1 in
case of errors that would look way better.
%<------------------------------------------------------------------->%
> +void modem_read_loop(struct ipc_client *client_fmt, struct
> ipc_client *client_rfs) +{
> while (1) {
> usleep(3000);
>
> - rc = ipc_client_poll(client, NULL, NULL);
> - if (rc < 0)
> - continue;
> -
> - rc = ipc_client_recv(client, &resp);
> - if (rc < 0) {
> - printf("[E] "
> - "Can't RECV from modem: please run
> this again"
> - "\n");
> - break;
> - }
> -
> - modem_response_handle(client, &resp);
> -
> - if (resp.data != NULL)
> - free(resp.data);
> + switch (modem_poll_client(client_fmt, "FMT")) {
> + case -1:
> + return;
This changes the program behavior here: before we had that:
> int modem_read_loop(struct ipc_client *client)> {
> [...]
> while (1) {
> usleep(3000);
>
> rc = ipc_client_poll(client, NULL, NULL);
> if (rc < 0)
> continue;
> [...]
> } [...]
> }
So when the modem crashed for instance, you would simply continue
trying to read ipc messages. While there are no comments that
indicates why it was done like that, in libsamsung-ril we just restart
to bootstrap the modem again when that happens: for instance in
xmm626_kernel_smdk4412_poll we have:
> rc = select(fd_max + 1, &set, NULL, NULL, timeout);
>
> if (FD_ISSET(fd, &set)) {
> status = ioctl(fd, IOCTL_MODEM_STATUS, 0);
> if (status != STATE_ONLINE && status != STATE_BOOTING)
> return -1;
> }
> [...]
> return rc;
So it's probably safe to assume that the modem is crashed if the is
return code is -1 as it's not booting.
It would probably be best to split that change somehow, as it could
help bisecting the issue in case of problems with that change.
For instance the patch to fix that could be applied before this patch
and look like that:
> int modem_read_loop(struct ipc_client *client)
> {
> [...]
> while (1) {
> usleep(3000);
>
> rc = ipc_client_poll(client, NULL, NULL);
> if (rc < 0)
> - continue;
> + return rc;
> [...]
> } [...]
>}
Do you want me to do it or do you prefer doing it?
%<------------------------------------------------------------------->%
> + case 0:
> + if (client_rfs != NULL) {
> + switch
> (modem_poll_client(client_rfs, "RFS")) {
The issue here is that if the IPC channel always has some data, the RFS
modem poll is never run.
The issue is that, as I understand the following won't work:
> switch (modem_poll_client(client_fmt, "FMT")) {
> case -1:
> return;
> case 0:
> /* Fall through */
> default:
> break;
> }
> switch (modem_poll_client(client_rfs, "RFS")) {
> case -1:
> return;
> case 0:
> /* Fall through */
> default:
> break;
> }
> void modem_log_handler(__attribute__((unused)) void *user_data,
> @@ -476,20 +508,24 @@ void print_help(void)
> printf("\tpower-off power off the modem\n");
> printf("arguments:\n");
> printf("\t--debug enable debug messages\n");
> + printf("\t--rfs enable RFS client in
> addition to FMT client\n"); printf("\t--pin=[PIN] provide
> SIM card PIN\n"); }
>
> int main(int argc, char *argv[])
> {
> - struct ipc_client *client_fmt;
> + struct ipc_client *client_fmt = 0;
> + struct ipc_client *client_rfs = 0;
> int c = 0;
> int opt_i = 0;
> int rc = -1;
> int debug = 0;
> + int rfs = 0;
>
> struct option opt_l[] = {
> {"help", no_argument, 0, 0 },
> {"debug", no_argument, 0, 0 },
> + {"rfs", no_argument, 0, 0 },
> {"pin", required_argument, 0, 0 },
> {0, 0, 0, 0 }
> };
> @@ -512,6 +548,9 @@ int main(int argc, char *argv[])
> } else if (strcmp(opt_l[opt_i].name,
> "debug") == 0) { debug = 1;
> printf("[I] Debug enabled\n");
> + } else if (strcmp(opt_l[opt_i].name, "rfs")
> == 0) {
> + rfs = 1;
> + printf("[I] RFS enabled\n");
> } else if (strcmp(opt_l[opt_i].name, "pin")
> == 0) { if (optarg) {
> if (strlen(optarg) < 8) {
> @@ -536,12 +575,30 @@ int main(int argc, char *argv[])
> goto modem_quit;
> }
>
> + if (rfs) {
> + client_rfs = ipc_client_create(IPC_CLIENT_TYPE_RFS);
> + if (client_rfs == 0) {
> + printf("[E] Could not create RFS client;
> aborting ...\n");
> + goto modem_quit;
> + }
> + } else {
> + client_rfs = 0;
> + }
> +
> if (debug == 0) {
> ipc_client_log_callback_register(client_fmt,
> modem_log_handler_quiet,
> NULL);
> + if (rfs) {
> + ipc_client_log_callback_register(client_rfs,
> +
> modem_log_handler_quiet, NULL);
> + }
> } else {
> ipc_client_log_callback_register(client_fmt,
> modem_log_handler, NULL);
> + if (rfs) {
> + ipc_client_log_callback_register(client_rfs,
> modem_log_handler,
> + NULL);
> + }
> }
>
> while (optind < argc) {
> @@ -561,18 +618,34 @@ int main(int argc, char *argv[])
> printf("[E] Something went wrong "
> "while bootstrapping
> modem\n"); } else if (strncmp(argv[optind], "start", 5) == 0) {
> - printf("[0] Starting modem on FMT client\n");
> + printf("[0] Starting modem FMT client\n");
> rc = modem_start(client_fmt);
> if (rc < 0) {
> - printf("[E] Something went wrong\n");
> + printf("[E] Something went wrong
> starting FMT client\n"); modem_stop(client_fmt);
> return 1;
> }
>
> - printf("[1] Starting modem_read_loop on FMT
> client\n");
> - modem_read_loop(client_fmt);
> + if (rfs) {
> + printf("[1] Starting modem RFS
> client\n");
> + ipc_client_data_create(client_rfs);
> + rc = ipc_client_open(client_rfs);
> + if (rc < 0) {
> + printf("[E] Something went
> wrong starting RFS client\n");
> + ipc_client_close(client_rfs);
> + modem_stop(client_fmt);
> + return 1;
> + }
> + } else {
> + printf("[1] Skipping modem RFS
> client start\n");
If you use thread and chose not to enable RFS by default for some good
reason, it would be a good idea to add a print here as it's probably
easy to forget to add --rfs to the command line. It also shows up in
logs so the information will appear when copy/pasting logs to get some
help.
However for someone that didn't read that code, that could be
interpreted as an error. To make it more clear you could do something
like that for instance:
> printf("[1] --rfs not selected, "
> "skipping modem RFS client start\n");
Here it explains why it's skipping the RFS client start.
Another option would be to enable the RFS handling by default. If there
are no downsides here that option would be way better. Otherwise people
that have a Galaxy S7 with the herolte codename, and potentially other
devices they want to add support for will not necessarily know that
--rfs is really required. They could also forget to add it during some
tests and draw wrong conclusions.
Still, it should probably be safe to enable it by default as we don't
write to the nv_data.bin
This won't be perfect as ipc-test doesn't have RFS support, but in the
worst case people might try both tools and assume that for some unknown
reason ipc-test doesn't work while ipc-modem does.
> + }
> +
> + printf("[2] Starting modem_read_loop on FMT
> client\n");
> + modem_read_loop(client_fmt, client_rfs);
>
> modem_stop(client_fmt);
> + if (client_rfs != 0)
> + ipc_client_close(client_rfs);
That could be moved in modem_stop:
- That code is also repeated when "Something went wrong starting RFS
client".
- It's not very consistent to have ipc_client_close(client) in
modem_stop for the ipc_client but have the same for the RFS client
outside of that function.
- The function name (modem_stop) implies that it's generic
Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
-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, |