summaryrefslogtreecommitdiffstats
path: root/gen.c
diff options
context:
space:
mode:
authorPaul Kocialkowski <contact@paulk.fr>2014-08-07 13:12:15 +0200
committerPaul Kocialkowski <contact@paulk.fr>2014-08-07 13:12:15 +0200
commita7ff1df1869ce543171a6ee92cbf821647b1bf7d (patch)
tree659e315b3d609f0f9e661d4de21b52077e6e2b81 /gen.c
parentc8408cd2c116b0b99a399282032b6607a1318b84 (diff)
downloadhardware_ril_samsung-ril-a7ff1df1869ce543171a6ee92cbf821647b1bf7d.zip
hardware_ril_samsung-ril-a7ff1df1869ce543171a6ee92cbf821647b1bf7d.tar.gz
hardware_ril_samsung-ril-a7ff1df1869ce543171a6ee92cbf821647b1bf7d.tar.bz2
Samsung-RIL rewrite: harder, better, probably not faster but definitely stronger
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
Diffstat (limited to 'gen.c')
-rw-r--r--gen.c275
1 files changed, 180 insertions, 95 deletions
diff --git a/gen.c b/gen.c
index 596560c..8bfdb13 100644
--- a/gen.c
+++ b/gen.c
@@ -1,7 +1,7 @@
/*
* This file is part of Samsung-RIL.
*
- * Copyright (C) 2011-2013 Paul Kocialkowski <contact@paulk.fr>
+ * Copyright (C) 2011-2014 Paul Kocialkowski <contact@paulk.fr>
*
* Samsung-RIL is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,178 +17,263 @@
* along with Samsung-RIL. If not, see <http://www.gnu.org/licenses/>.
*/
-#define LOG_TAG "RIL-GEN"
-#include <utils/Log.h>
+#include <stdlib.h>
-#include "samsung-ril.h"
-#include "util.h"
+#define LOG_TAG "RIL"
+#include <utils/Log.h>
-/*
- * IPC_GEN_PHONE_RES has shared aseq (in the header), group, index and type (in the data)
- * with the original request it responds to.
- * On this implementation, we just check aseq and command (group and index).
- * aseq permits to identify the queued request and do what's wanted.
- * It can be either call a function with the struct ipc_message_info,
- * complete the request to RILJ (with or without an error),
- * return to RILJ if there is an error in this response.
- *
- * It would have been possible to deal with group, index and type only and use
- * callback functions. Though, what is currently being used is more a "standard"
- * error catch system, that requires less code (no particular function), while
- * it also permits using custom functions, when IPC_GEN_PHONE_RES code is
- * request-specific.
- *
- * On a custom function, don't forget to get a clean new aseq if you're going to
- * send some data to the modem, just liek this:
- * aseq = ril_request_reg_id(ril_request_get_token(info->aseq));
- *
- * Please use the GEN_PHONE_RES engine as often as possible!
- */
+#include <samsung-ril.h>
+#include <utils.h>
-/*
- * GEN expects functions
- */
-
-int ipc_gen_phone_res_expect_register(unsigned char aseq, unsigned short command,
- void (*func)(struct ipc_message_info *info), int complete, int abort)
+int ipc_gen_phone_res_expect_register(struct ril_client *client,
+ unsigned char aseq, unsigned short command,
+ int (*callback)(struct ipc_message *message),
+ int complete, int abort)
{
- struct ipc_gen_phone_res_expect_info *expect;
+ struct ipc_gen_phone_res_expect *expect;
+ struct ipc_fmt_data *data;
struct list_head *list_end;
struct list_head *list;
- expect = calloc(1, sizeof(struct ipc_gen_phone_res_expect_info));
- if (expect == NULL)
+ if (client == NULL || client->data == NULL)
return -1;
+ data = (struct ipc_fmt_data *) client->data;
+
+ RIL_CLIENT_LOCK(client);
+
+ expect = calloc(1, sizeof(struct ipc_gen_phone_res_expect));
expect->aseq = aseq;
expect->command = command;
- expect->func = func;
+ expect->callback = callback;
expect->complete = complete;
expect->abort = abort;
- list_end = ril_data.generic_responses;
+ list_end = data->gen_phone_res_expect;
while (list_end != NULL && list_end->next != NULL)
list_end = list_end->next;
- list = list_head_alloc((void *) expect, list_end, NULL);
+ list = list_head_alloc(list_end, NULL, (void *) expect);
+
+ if (data->gen_phone_res_expect == NULL)
+ data->gen_phone_res_expect = list;
- if (ril_data.generic_responses == NULL)
- ril_data.generic_responses = list;
+ RIL_CLIENT_UNLOCK(client);
return 0;
}
-void ipc_gen_phone_res_expect_unregister(struct ipc_gen_phone_res_expect_info *expect)
+int ipc_gen_phone_res_expect_unregister(struct ril_client *client,
+ struct ipc_gen_phone_res_expect *expect)
{
+ struct ipc_fmt_data *data;
struct list_head *list;
- if (expect == NULL)
- return;
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ data = (struct ipc_fmt_data *) client->data;
+
+ RIL_CLIENT_LOCK(client);
- list = ril_data.generic_responses;
+ list = data->gen_phone_res_expect;
while (list != NULL) {
if (list->data == (void *) expect) {
- memset(expect, 0, sizeof(struct ipc_gen_phone_res_expect_info));
+ memset(expect, 0, sizeof(struct ipc_gen_phone_res_expect));
free(expect);
- if (list == ril_data.generic_responses)
- ril_data.generic_responses = list->next;
+ if (list == data->gen_phone_res_expect)
+ data->gen_phone_res_expect = list->next;
list_head_free(list);
break;
}
+
list_continue:
list = list->next;
}
+
+ RIL_CLIENT_UNLOCK(client);
+
+ return 0;
}
-struct ipc_gen_phone_res_expect_info *ipc_gen_phone_res_expect_info_find_aseq(unsigned char aseq)
+int ipc_gen_phone_res_expect_flush(struct ril_client *client)
{
- struct ipc_gen_phone_res_expect_info *expect;
+ struct ipc_gen_phone_res_expect *expect;
+ struct ipc_fmt_data *data;
struct list_head *list;
+ struct list_head *list_next;
+
+ if (client == NULL || client->data == NULL)
+ return -1;
+
+ data = (struct ipc_fmt_data *) client->data;
+
+ RIL_CLIENT_LOCK(client);
+
+ list = data->gen_phone_res_expect;
+ while (list != NULL) {
+ if (list->data != NULL) {
+ expect = (struct ipc_gen_phone_res_expect *) list->data;
+ memset(expect, 0, sizeof(struct ipc_gen_phone_res_expect));
+ free(expect);
+ }
+
+ if (list == data->gen_phone_res_expect)
+ data->gen_phone_res_expect = list->next;
+
+ list_next = list->next;
+
+ list_head_free(list);
+
+list_continue:
+ list = list_next;
+ }
+
+ RIL_CLIENT_UNLOCK(client);
+
+ return 0;
+}
+
+struct ipc_gen_phone_res_expect *ipc_gen_phone_res_expect_find_aseq(struct ril_client *client,
+ unsigned char aseq)
+{
+ struct ipc_gen_phone_res_expect *expect;
+ struct ipc_fmt_data *data;
+ struct list_head *list;
+
+ if (client == NULL || client->data == NULL)
+ return NULL;
+
+ data = (struct ipc_fmt_data *) client->data;
- list = ril_data.generic_responses;
+ RIL_CLIENT_LOCK(client);
+
+ list = data->gen_phone_res_expect;
while (list != NULL) {
- expect = (struct ipc_gen_phone_res_expect_info *) list->data;
- if (expect == NULL)
+ if (list->data == NULL)
goto list_continue;
- if (expect->aseq == aseq)
+ expect = (struct ipc_gen_phone_res_expect *) list->data;
+
+ if (expect->aseq == aseq) {
+ RIL_CLIENT_UNLOCK(client);
return expect;
+ }
list_continue:
list = list->next;
}
+ RIL_CLIENT_UNLOCK(client);
+
return NULL;
}
-int ipc_gen_phone_res_expect_to_func(unsigned char aseq, unsigned short command,
- void (*func)(struct ipc_message_info *info))
+int ipc_gen_phone_res_expect_callback(unsigned char aseq, unsigned short command,
+ int (*callback)(struct ipc_message *message))
{
- return ipc_gen_phone_res_expect_register(aseq, command, func, 0, 0);
+ struct ril_client *client;
+ int rc;
+
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL)
+ return -1;
+
+ rc = ipc_gen_phone_res_expect_register(client, aseq, command, callback, 0, 0);
+ if (rc < 0)
+ return -1;
+
+ return 0;
}
-int ipc_gen_phone_res_expect_to_complete(unsigned char aseq, unsigned short command)
+int ipc_gen_phone_res_expect_complete(unsigned char aseq, unsigned short command)
{
- return ipc_gen_phone_res_expect_register(aseq, command, NULL, 1, 0);
+ struct ril_client *client;
+ int rc;
+
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL)
+ return -1;
+
+ rc = ipc_gen_phone_res_expect_register(client, aseq, command, NULL, 1, 0);
+ if (rc < 0)
+ return -1;
+
+ return 0;
}
-int ipc_gen_phone_res_expect_to_abort(unsigned char aseq, unsigned short command)
+int ipc_gen_phone_res_expect_abort(unsigned char aseq, unsigned short command)
{
- return ipc_gen_phone_res_expect_register(aseq, command, NULL, 0, 1);
-}
+ struct ril_client *client;
+ int rc;
-/*
- * GEN dequeue function
- */
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL)
+ return -1;
+
+ rc = ipc_gen_phone_res_expect_register(client, aseq, command, NULL, 0, 1);
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
-void ipc_gen_phone_res(struct ipc_message_info *info)
+int ipc_gen_phone_res(struct ipc_message *message)
{
- struct ipc_gen_phone_res_expect_info *expect;
- struct ipc_gen_phone_res *phone_res;
- RIL_Errno e;
+ struct ipc_gen_phone_res_expect *expect;
+ struct ipc_gen_phone_res_data *data;
+ struct ril_client *client;
+ RIL_Errno error;
int rc;
- if (info->data == NULL || info->length < sizeof(struct ipc_gen_phone_res))
- return;
+ if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_gen_phone_res_data))
+ return -1;
+
+ client = ril_client_find_id(RIL_CLIENT_IPC_FMT);
+ if (client == NULL)
+ return -1;
- phone_res = (struct ipc_gen_phone_res *) info->data;
- expect = ipc_gen_phone_res_expect_info_find_aseq(info->aseq);
+ data = (struct ipc_gen_phone_res_data *) message->data;
+ expect = ipc_gen_phone_res_expect_find_aseq(client, message->aseq);
if (expect == NULL) {
- RIL_LOGD("aseq: 0x%x not found in the IPC_GEN_PHONE_RES queue", info->aseq);
- return;
+ RIL_LOGD("Ignoring generic response for command %s", ipc_command_string(IPC_COMMAND(data->group, data->index)));
+ return 0;
}
- RIL_LOGD("aseq: 0x%x found in the IPC_GEN_PHONE_RES queue!", info->aseq);
-
- if (expect->command != IPC_COMMAND(phone_res)) {
- RIL_LOGE("IPC_GEN_PHONE_RES aseq (0x%x) doesn't match the queued one with command (0x%x)",
- expect->aseq, expect->command);
-
- if (expect->func != NULL) {
- RIL_LOGE("Not safe to run the custom function, reporting generic failure");
- ril_request_complete(ril_request_get_token(expect->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
- goto unregister;
- }
+ if (IPC_COMMAND(data->group, data->index) != expect->command) {
+ RIL_LOGE("Generic response commands mismatch: %s/%s", ipc_command_string(IPC_COMMAND(data->group, data->index)), ipc_command_string(expect->command));
+ goto error;
}
- if (expect->func != NULL) {
- expect->func(info);
- goto unregister;
+ RIL_LOGD("Generic response was expected");
+
+ if (expect->callback != NULL) {
+ rc = expect->callback(message);
+ goto complete;
}
- rc = ipc_gen_phone_res_check(phone_res);
+ rc = ipc_gen_phone_res_check(data);
if (rc < 0)
- e = RIL_E_GENERIC_FAILURE;
+ error = RIL_E_GENERIC_FAILURE;
else
- e = RIL_E_SUCCESS;
+ error = RIL_E_SUCCESS;
+
+ if (expect->complete || (expect->abort && error == RIL_E_GENERIC_FAILURE))
+ ril_request_complete(ipc_fmt_request_token(message->aseq), error, NULL, 0);
+
+ rc = 0;
+ goto complete;
+
+error:
+ rc = -1;
- if (expect->complete || (expect->abort && e == RIL_E_GENERIC_FAILURE))
- ril_request_complete(ril_request_get_token(expect->aseq), e, NULL, 0);
+complete:
+ if (expect != NULL)
+ ipc_gen_phone_res_expect_unregister(client, expect);
-unregister:
- ipc_gen_phone_res_expect_unregister(expect);
+ return rc;
}