summaryrefslogtreecommitdiff
path: root/src/gsmd/usock.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gsmd/usock.c')
-rw-r--r--src/gsmd/usock.c95
1 files changed, 75 insertions, 20 deletions
diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c
index 7c90c5d..925be75 100644
--- a/src/gsmd/usock.c
+++ b/src/gsmd/usock.c
@@ -39,32 +39,62 @@ static int usock_cmd_cb(struct gsmd_atcmd *cmd, void *ctx)
return 0;
}
-static int usock_rcv_pcmd(struct gsmd_user *gu, char *buf, int len)
+typedef int usock_msg_handler(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len);
+
+static int usock_rcv_passthrough(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len)
{
- struct gsmd_msg_hdr *gph = (struct gsmd_msg_hdr *)buf;
+ struct gsmd_atcmd *cmd;
+ cmd = atcmd_fill((char *)gph+sizeof(*gph), 255, &usock_cmd_cb, gu);
+ if (!cmd)
+ return -ENOMEM;
- if (gph->version != GSMD_PROTO_VERSION)
+ return atcmd_submit(gu->gsmd, cmd);
+}
+
+static int usock_rcv_event(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len)
+{
+ u_int32_t *evtmask = (u_int32_t *) ((char *)gph + sizeof(*gph));
+
+ if (len < sizeof(*gph) + sizeof(u_int32_t))
return -EINVAL;
- switch (gph->msg_type) {
- case GSMD_MSG_PASSTHROUGH:
- {
- struct gsmd_atcmd *cmd;
- cmd = atcmd_fill((char *)gph+sizeof(*gph),
- 255, &usock_cmd_cb, gu);
- if (!cmd)
- return -ENOMEM;
- return atcmd_submit(gu->gsmd, cmd);
- }
+ if (gph->msg_subtype != GSMD_EVENT_SUBSCRIPTIONS)
+ return -EINVAL;
+
+ gu->subscriptions = *evtmask;
+}
+
+static int usock_rcv_voicecall(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len)
+{
+ struct gsmd_atcmd *cmd;
+
+ switch (gph->msg_subtype) {
+ case GSMD_VOICECALL_DIAL:
+ /* FIXME */
break;
- case GSMD_PCMD_EVT_SUBSCRIPTIONS:
- {
- u_int32_t *evtmask = (u_int32_t *) (buf + sizeof(*gph));
- if (len < sizeof(*gph) + sizeof(u_int32_t))
- return -EINVAL;
+ case GSMD_VOICECALL_HANGUP:
+ cmd = atcmd_fill("ATH0", 5, &usock_cmd_cb, gu);
+ break;
+ default:
+ return -EINVAL;
+ }
- gu->subscriptions = *evtmask;
- }
+ return 0;
+}
+
+#define GSMD_PIN_MAXLEN 16
+
+static int usock_rcv_pin(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len)
+{
+ u_int8_t *pin = (u_int8_t *)gph + sizeof(*gph);
+ int pin_len = len - sizeof(*gph);
+ char pinbuf[GSMD_PIN_MAXLEN + 11]; /* `AT+CPIN=""\0' */
+
+ snprintf(pinbuf, sizeof(pinbuf), "AT+CPIN=\"%s\"", pin);
+
+ switch (gph->msg_subtype) {
+ case GSMD_PIN_INPUT:
+ /* FIXME */
break;
default:
return -EINVAL;
@@ -73,6 +103,31 @@ static int usock_rcv_pcmd(struct gsmd_user *gu, char *buf, int len)
return 0;
}
+static usock_msg_handler *pcmd_type_handlers[] = {
+ [GSMD_MSG_PASSTHROUGH] = &usock_rcv_passthrough,
+ [GSMD_MSG_EVENT] = &usock_rcv_event,
+ [GSMD_MSG_VOICECALL] = &usock_rcv_voicecall,
+ [GSMD_MSG_PIN] = &usock_rcv_pin,
+};
+
+static int usock_rcv_pcmd(struct gsmd_user *gu, char *buf, int len)
+{
+ struct gsmd_msg_hdr *gph = (struct gsmd_msg_hdr *)buf;
+ usock_msg_handler *umh;
+
+ if (gph->version != GSMD_PROTO_VERSION)
+ return -EINVAL;
+
+ if (gph->msg_type >= ARRAY_SIZE(pcmd_type_handlers))
+ return -EINVAL;
+
+ umh = pcmd_type_handlers[gph->msg_type];
+ if (!umh)
+ return -EINVAL;
+
+ return umh(gu, gph, len);
+}
+
/* callback for read/write on client (libgsmd) socket */
static int gsmd_usock_user_cb(int fd, unsigned int what, void *data)
{
personal git repositories of Harald Welte. Your mileage may vary