summaryrefslogtreecommitdiff
path: root/src/gsmd/usock.c
diff options
context:
space:
mode:
authorlaforge <laforge@99fdad57-331a-0410-800a-d7fa5415bdb3>2007-08-17 08:32:14 +0000
committerlaforge <laforge@99fdad57-331a-0410-800a-d7fa5415bdb3>2007-08-17 08:32:14 +0000
commit86c7ff07f100489d085efd6541b8c104a44209e0 (patch)
treec22d7172cec161430b130032f7b3ec8678d34afa /src/gsmd/usock.c
parent34fbfd275b710d3662eb490f6a59f58285892f70 (diff)
From: Andrzej Zaborowski <balrog@zabor.org>
Date: Tue, 31 Jul 2007 22:26:36 +0200 Subject: [PATCH] Operations on the preferred operators list. This makes use of the AT+CPOL variants to add / delete / list entries in the preferred operators list on the SIM. There's some inconsistency, similarly as with operator selection, in that we return operator names in long alphanumeric format but we take only operators in numeric format as parameters. Either the client will have to convert between the formats or we should always use for example the long alphanumeric format, or maybe do something else. git-svn-id: http://svn.openmoko.org/trunk/src/target/gsm@2725 99fdad57-331a-0410-800a-d7fa5415bdb3
Diffstat (limited to 'src/gsmd/usock.c')
-rw-r--r--src/gsmd/usock.c94
1 files changed, 91 insertions, 3 deletions
diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c
index 5224f92..0d9ec88 100644
--- a/src/gsmd/usock.c
+++ b/src/gsmd/usock.c
@@ -423,6 +423,10 @@ static int network_opers_parse(const char *str, struct gsmd_msg_oper out[])
{
int len = 0;
int stat, n;
+ char opname_longalpha[16 + 1];
+ char opname_shortalpha[8 + 1];
+ char opname_num[6 + 1];
+
if (strncmp(str, "+COPS: ", 7))
goto final;
str += 7;
@@ -434,12 +438,18 @@ static int network_opers_parse(const char *str, struct gsmd_msg_oper out[])
"(%i,\"%16[^\"]\","
"\"%8[^\"]\",\"%6[0-9]\")%n",
&stat,
- out->opname_longalpha,
- out->opname_shortalpha,
- out->opname_num,
+ opname_longalpha,
+ opname_shortalpha,
+ opname_num,
&n) < 4)
goto final;
out->stat = stat;
+ memcpy(out->opname_longalpha, opname_longalpha,
+ sizeof(out->opname_longalpha));
+ memcpy(out->opname_shortalpha, opname_shortalpha,
+ sizeof(out->opname_shortalpha));
+ memcpy(out->opname_num, opname_num,
+ sizeof(out->opname_num));
} else
if (sscanf(str,
"(%*i,\"%*[^\"]\","
@@ -480,6 +490,64 @@ static int network_opers_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
return 0;
}
+static int network_pref_opers_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = (struct gsmd_user *) ctx;
+ struct gsmd_ucmd *ucmd;
+ struct gsmd_msg_prefoper *entry;
+ int index;
+ char opname[17];
+
+ if (cmd->ret && cmd->ret != -255)
+ return 0;
+
+ if (sscanf(resp, "+CPOL: %i,0,\"%16[^\"]\"", &index, opname) < 2)
+ return -EINVAL;
+
+ ucmd = gsmd_ucmd_fill(sizeof(*entry), GSMD_MSG_NETWORK,
+ GSMD_NETWORK_PREF_LIST, cmd->id);
+ if (!ucmd)
+ return -ENOMEM;
+
+ entry = (struct gsmd_msg_prefoper *) ucmd->buf;
+ entry->index = index;
+ entry->is_last = (cmd->ret == 0);
+ memcpy(entry->opname_longalpha, opname,
+ sizeof(entry->opname_longalpha));
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int network_pref_num_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = (struct gsmd_user *) ctx;
+ struct gsmd_ucmd *ucmd;
+ int min_index, max_index, size;
+
+ if (cmd->ret)
+ return 0;
+
+ /* This is not a full general case, theoretically the range string
+ * can include commas and more dashes, but we have no full parser for
+ * ranges yet. */
+ if (sscanf(resp, "+CPOL: (%i-%i)", &min_index, &max_index) < 2)
+ return -EINVAL;
+
+ ucmd = gsmd_ucmd_fill(sizeof(int), GSMD_MSG_NETWORK,
+ GSMD_NETWORK_PREF_SPACE, cmd->id);
+ if (!ucmd)
+ return -ENOMEM;
+
+ size = max_index - min_index + 1;
+ memcpy(ucmd->buf, &size, sizeof(int));
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
static int usock_rcv_network(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
int len)
{
@@ -519,6 +587,26 @@ static int usock_rcv_network(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
case GSMD_NETWORK_OPER_LIST:
cmd = atcmd_fill("AT+COPS=?", 9+1, &network_opers_cb, gu, 0);
break;
+ case GSMD_NETWORK_PREF_LIST:
+ /* Set long alphanumeric format */
+ atcmd_submit(gu->gsmd, atcmd_fill("AT+CPOL=,0", 10 + 1,
+ &null_cmd_cb, gu, 0));
+ cmd = atcmd_fill("AT+CPOL?", 8 + 1,
+ &network_pref_opers_cb, gu, 0);
+ break;
+ case GSMD_NETWORK_PREF_DEL:
+ cmdlen = sprintf(buffer, "AT+CPOL=%i", *(int *) gph->data);
+ cmd = atcmd_fill(buffer, cmdlen + 1, &null_cmd_cb, gu, 0);
+ break;
+ case GSMD_NETWORK_PREF_ADD:
+ cmdlen = sprintf(buffer, "AT+CPOL=,2,\"%.*s\"",
+ sizeof(gsmd_oper_numeric), oper);
+ cmd = atcmd_fill(buffer, cmdlen + 1, &null_cmd_cb, gu, 0);
+ break;
+ case GSMD_NETWORK_PREF_SPACE:
+ cmd = atcmd_fill("AT+CPOL=?", 9 + 1,
+ &network_pref_num_cb, gu, 0);
+ break;
default:
return -EINVAL;
}
personal git repositories of Harald Welte. Your mileage may vary