📄 sms_cb.c
字号:
/* gsmd SMS functions * * (C) 2006-2007 by OpenMoko, Inc. * Written by Harald Welte <laforge@openmoko.org> * All Rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <sys/socket.h>#include <sys/un.h>#include "gsmd.h"#include <gsmd/gsmd.h>#include <gsmd/usock.h>#include <gsmd/select.h>#include <gsmd/atcmd.h>#include <gsmd/usock.h>#include <gsmd/unsolicited.h>#include <gsmd/sms.h>#include <gsmd/talloc.h>#include <gsmd/extrsp.h>static const char *ts0705_memtype_name[] = { [GSM0705_MEMTYPE_NONE] = "NONE", [GSM0705_MEMTYPE_BROADCAST] = "BM", [GSM0705_MEMTYPE_ME_MESSAGE] = "ME", [GSM0705_MEMTYPE_MT] = "MT", [GSM0705_MEMTYPE_SIM] = "SM", [GSM0705_MEMTYPE_TA] = "TA", [GSM0705_MEMTYPE_SR] = "SR",};static inline int parse_memtype(char *memtype){ int i; for (i = 0; i < ARRAY_SIZE(ts0705_memtype_name); i++) { if (!strcmp(ts0705_memtype_name[i], memtype)) return i; } return GSM0705_MEMTYPE_NONE;}static int sms_list_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){ struct gsmd_user *gu = ctx; struct gsmd_sms_list msg; int i, idx, stat, len, cr; u_int8_t pdu[SMS_MAX_PDU_SIZE]; if (cmd->ret && cmd->ret != -255) return 0; /* TODO: Send a response */ /* FIXME: TEXT mode */ if ( sscanf(resp, "+CMGL: %i,%i,,%i\n%n", &idx, &stat, &len, &cr) < 3 && sscanf(resp, "+CMGL: %i,%i,\"%*[^\"]\",%i\n%n", &idx, &stat, &len, &cr) < 3) return -EINVAL; /* TODO: Send a response */ if (len > 164) return -EINVAL; /* TODO: Send a response */ msg.index = idx; msg.stat = stat; msg.is_last = (cmd->ret == 0); for (i = 0; resp[cr] >= '0' && resp[cr + 1] >= '0' && i < SMS_MAX_PDU_SIZE; i ++) { if (sscanf(resp + cr, "%2hhX", &pdu[i]) < 1) { gsmd_log(GSMD_DEBUG, "malformed input (%i)\n", i); return -EINVAL; /* TODO: Send a response */ } cr += 2; } if (sms_pdu_to_msg(&msg, pdu, len, i)) { gsmd_log(GSMD_DEBUG, "malformed PDU\n"); return -EINVAL; /* TODO: Send a response */ } return gsmd_ucmd_submit(gu, GSMD_MSG_SMS, GSMD_SMS_LIST, cmd->id, sizeof(msg), &msg);}static int sms_read_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){ struct gsmd_user *gu = ctx; struct gsmd_sms_list msg; int i, stat, len, cr; u_int8_t pdu[SMS_MAX_PDU_SIZE]; const char *colon; if (cmd->ret) return 0; /* TODO: Send a response */ /* FIXME: TEXT mode */ if ( sscanf(resp, "+CMGR: %i,,%i\n%n", &stat, &len, &cr) < 2 && sscanf(resp, "+CMGR: %i,\"%*[^\"]\",%i\n%n", &stat, &len, &cr) < 2) return -EINVAL; /* TODO: Send a response */ if (len > 164) return -EINVAL; /* TODO: Send a response */ msg.index = 0; colon = strchr(cmd->buf, '='); /* get a correct message index value on reading a SMS */ if (!strncmp(cmd->buf, "AT+CMGR", 7) && colon) msg.index = atoi(colon+1); msg.stat = stat; msg.is_last = 1; for (i = 0; resp[cr] >= '0' && resp[cr + 1] >= '0' && i < SMS_MAX_PDU_SIZE; i ++) { if (sscanf(resp + cr, "%2hhX", &pdu[i]) < 1) { gsmd_log(GSMD_DEBUG, "malformed input (%i)\n", i); return -EINVAL; /* TODO: Send a response */ } cr += 2; } if (sms_pdu_to_msg(&msg, pdu, len, i)) { gsmd_log(GSMD_DEBUG, "malformed PDU\n"); return -EINVAL; } return gsmd_ucmd_submit(gu, GSMD_MSG_SMS, GSMD_SMS_READ, cmd->id, sizeof(msg), &msg);}static int sms_send_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){ int msgref; if (cmd->ret == 0 || cmd->ret == -255) { if (sscanf(resp, "+CMGS: %i", &msgref) < 1) msgref = -EINVAL; } else msgref = -cmd->ret; return gsmd_ucmd_submit(ctx, GSMD_MSG_SMS, GSMD_SMS_SEND, cmd->id, sizeof(msgref), &msgref);}static int sms_write_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){ int result; if (cmd->ret == 0) { if (sscanf(resp, "+CMGW: %i", &result) < 1) result = -EINVAL; } else result = -cmd->ret; return gsmd_ucmd_submit(ctx, GSMD_MSG_SMS, GSMD_SMS_WRITE, cmd->id, sizeof(result), &result);}static int sms_delete_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){ int result = cmd->ret; return gsmd_ucmd_submit(ctx, GSMD_MSG_SMS, GSMD_SMS_DELETE, cmd->id, sizeof(result), &result);}static int usock_cpms_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){ struct gsmd_user *gu = ctx; struct gsmd_ucmd *ucmd = ucmd_alloc(sizeof(struct gsmd_sms_storage)); struct gsmd_sms_storage *gss = (typeof(gss)) ucmd->buf; char buf[3][3]; DEBUGP("entering(cmd=%p, gu=%p)\n", cmd, gu); if (!ucmd) return -ENOMEM; ucmd->hdr.version = GSMD_PROTO_VERSION; ucmd->hdr.msg_type = GSMD_MSG_SMS; ucmd->hdr.msg_subtype = GSMD_SMS_GET_MSG_STORAGE; ucmd->hdr.len = sizeof(struct gsmd_sms_storage); ucmd->hdr.id = cmd->id; if (sscanf(resp, "+CPMS: \"%2[A-Z]\",%hi,%hi," "\"%2[A-Z]\",%hi,%hi,\"%2[A-Z]\",%hi,%hi", buf[0], &gss->mem[0].used, &gss->mem[0].total, buf[1], &gss->mem[1].used, &gss->mem[1].total, buf[2], &gss->mem[2].used, &gss->mem[2].total) < 9) { talloc_free(ucmd); return -EINVAL; /* TODO: Send a response */ } gss->mem[0].memtype = parse_memtype(buf[0]); gss->mem[1].memtype = parse_memtype(buf[1]); gss->mem[2].memtype = parse_memtype(buf[2]); usock_cmd_enqueue(ucmd, gu); return 0;}static int usock_get_smsc_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp){ struct gsmd_addr ga; if (sscanf(resp, "+CSCA: \"%31[^\"]\",%hhi", ga.number, &ga.type) < 2) return -EINVAL; /* TODO: Send a response */ return gsmd_ucmd_submit(ctx, GSMD_MSG_SMS, GSMD_SMS_GET_SERVICE_CENTRE, cmd->id, sizeof(ga), &ga);}static const char *gsmd_cmgl_stat[] = { "REC UNREAD", "REC READ", "STO UNSENT", "STO SENT", "ALL",};/* main unix socket Short Message receiver */int usock_rcv_sms(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len){ /* FIXME: TEXT mode support!! */ struct gsmd_atcmd *cmd = NULL; struct gsmd_sms_delete *gsd; struct gsmd_sms_submit *gss; struct gsmd_sms_write *gsw; struct gsmd_addr *ga; enum ts0705_mem_type *storage; int *stat, *index; int atcmd_len; char buf[1024]; switch (gph->msg_subtype) { case GSMD_SMS_LIST: if(len < sizeof(*gph) + sizeof(int)) return -EINVAL; stat = (int *) ((void *)gph + sizeof(*gph)); if (*stat < 0 || *stat > 4) return -EINVAL; if (gu->gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT) atcmd_len = sprintf(buf, "AT+CMGL=\"%s\"", gsmd_cmgl_stat[*stat]); else atcmd_len = sprintf(buf, "AT+CMGL=%i", *stat); cmd = atcmd_fill(buf, atcmd_len + 1, &sms_list_cb, gu, gph->id, NULL); break; case GSMD_SMS_READ: if(len < sizeof(*gph) + sizeof(int)) return -EINVAL; index = (int *) ((void *)gph + sizeof(*gph)); atcmd_len = sprintf(buf, "AT+CMGR=%i", *index); cmd = atcmd_fill(buf, atcmd_len + 1, &sms_read_cb, gu, gph->id, NULL); break; case GSMD_SMS_SEND: if (len < sizeof(*gph) + sizeof(*gss)) return -EINVAL; gss = (struct gsmd_sms_submit *) ((void *) gph + sizeof(*gph)); if (gu->gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT) { atcmd_len = sprintf(buf, "AT+CMGS=\"%s\"\n%.*s", gss->addr.number, gss->payload.length, gss->payload.data); /* FIXME */ } else { atcmd_len = sprintf(buf, "AT+CMGS=%i\n", sms_pdu_make_smssubmit(NULL, gss) - 1); atcmd_len += sms_pdu_make_smssubmit(buf + atcmd_len, gss) * 2; } buf[atcmd_len ++] = 26; /* ^Z ends the message */ buf[atcmd_len ++] = 0; cmd = atcmd_fill(buf, atcmd_len, &sms_send_cb, gu, gph->id, NULL); break; case GSMD_SMS_WRITE: if (len < sizeof(*gph) + sizeof(*gsw)) return -EINVAL; gsw = (struct gsmd_sms_write *) ((void *) gph + sizeof(*gph)); if (gsw->stat > 4) return -EINVAL; if (gu->gsmd->flags & GSMD_FLAG_SMS_FMT_TEXT) { atcmd_len = sprintf(buf, "AT+CMGW=\"%s\"\n%.*s", gsw->sms.addr.number, gsw->sms.payload.length, gsw->sms.payload.data); /* FIXME */ } else { atcmd_len = sprintf(buf, "AT+CMGW=%i,%i\n", sms_pdu_make_smssubmit(NULL, &gsw->sms) - 1, gsw->stat); atcmd_len += sms_pdu_make_smssubmit(buf + atcmd_len, &gsw->sms) * 2; } buf[atcmd_len ++] = 26; /* ^Z ends the message */ buf[atcmd_len ++] = 0; cmd = atcmd_fill(buf, atcmd_len, &sms_write_cb, gu, gph->id, NULL); break; case GSMD_SMS_DELETE: if(len < sizeof(*gph) + sizeof(*gsd)) return -EINVAL; gsd = (struct gsmd_sms_delete *) ((void *)gph + sizeof(*gph)); atcmd_len = sprintf(buf, "AT+CMGD=%d,%d", gsd->index, gsd->delflg); cmd = atcmd_fill(buf, atcmd_len + 1, &sms_delete_cb, gu, gph->id, NULL); break; case GSMD_SMS_GET_MSG_STORAGE: cmd = atcmd_fill("AT+CPMS?", 8 + 1, usock_cpms_cb, gu, 0, NULL); break; case GSMD_SMS_SET_MSG_STORAGE: if (len < sizeof(*gph) + 3 * sizeof(enum ts0705_mem_type)) return -EINVAL; storage = (enum ts0705_mem_type *) ((void *) gph + sizeof(*gph)); atcmd_len = sprintf(buf, "AT+CPMS=\"%s\",\"%s\",\"%s\"", ts0705_memtype_name[storage[0]],
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -