diff options
author | Philipp Zabel <philipp.zabel@gmail.com> | 2007-07-31 09:56:27 +0000 |
---|---|---|
committer | Philipp Zabel <philipp.zabel@gmail.com> | 2007-07-31 09:56:27 +0000 |
commit | 1d28b8f0f05e4a3b0a97a28e25027eb7e1203687 (patch) | |
tree | 5e002e9883560a110fc2e201d378e0e9ab9229ab /packages/gsm/files/sms-hacks.patch | |
parent | 00b20a5a4b14c59424f4c4328addd3f8c4311d39 (diff) |
libgsmd: update gsmd patches
- alive-start-if-interpreter-ready.patch and
vendor-qc-v0.patch went upstream
- add mlbuf-static-bss.patch and
Andrzej Zaborowski's sms-hacks.patch and libgsmd-tool-fix.patch
Diffstat (limited to 'packages/gsm/files/sms-hacks.patch')
-rw-r--r-- | packages/gsm/files/sms-hacks.patch | 821 |
1 files changed, 821 insertions, 0 deletions
diff --git a/packages/gsm/files/sms-hacks.patch b/packages/gsm/files/sms-hacks.patch new file mode 100644 index 0000000000..e94386ae39 --- /dev/null +++ b/packages/gsm/files/sms-hacks.patch @@ -0,0 +1,821 @@ +From 3e5832569d3b29a90b29b5d5ac0ffad4765bcff3 Mon Sep 17 00:00:00 2001 +From: Andrzej Zaborowski <balrog@zabor.org> +Date: Fri, 6 Jul 2007 06:55:12 +0200 +Subject: [PATCH] SMS hacks 2 + +--- + include/gsmd/gsmd.h | 8 ++- + include/gsmd/usock.h | 35 ++++++++- + include/gsmd/vendorplugin.h | 2 +- + include/libgsmd/sms.h | 2 +- + src/gsmd/atcmd.c | 130 +++++++++++++++++++------------- + src/gsmd/sms_cb.c | 19 ++++- + src/gsmd/usock.c | 175 +++++++++++++++++++++++++++++++++++++----- + src/gsmd/vendor_ti.c | 2 +- + src/libgsmd/libgsmd_sms.c | 26 +++++-- + 11 files changed, 320 insertions(+), 91 deletions(-) + +Index: gsm/include/gsmd/gsmd.h +=================================================================== +--- gsm.orig/include/gsmd/gsmd.h 2007-07-31 11:44:32.000000000 +0200 ++++ gsm/include/gsmd/gsmd.h 2007-07-31 11:46:44.000000000 +0200 +@@ -27,6 +27,7 @@ + u_int32_t buflen; + u_int16_t id; + u_int8_t flags; ++ char *cur; + char buf[]; + }; + +@@ -36,6 +37,8 @@ + LLPARSE_STATE_IDLE_LF, /* LF before response (V1) */ + LLPARSE_STATE_RESULT, /* within result payload */ + LLPARSE_STATE_RESULT_CR, /* CR after result */ ++ LLPARSE_STATE_PROMPT, /* within a "> " prompt */ ++ LLPARSE_STATE_PROMPT_SPC, /* a complete "> " prompt */ + LLPARSE_STATE_ERROR, /* something went wrong */ + /* ... idle again */ + }; +@@ -52,6 +55,7 @@ + unsigned int flags; + void *ctx; + int (*cb)(const char *buf, int len, void *ctx); ++ int (*prompt_cb)(void *ctx); + char *cur; + char buf[LLPARSE_BUF_SIZE]; + }; +@@ -59,6 +63,7 @@ + struct gsmd; + + #define GSMD_FLAG_V0 0x0001 /* V0 responses to be expected from TA */ ++#define GSMD_FLAG_SMS_FMT 0x0002 /* Use TEXT rather than PDU mode */ + + struct gsmd { + unsigned int flags; +@@ -92,7 +97,8 @@ + + extern int gsmdlog_init(const char *path); + /* write a message to the daemons' logfile */ +-void __gsmd_log(int level, const char *file, int line, const char *function, const char *message, ...); ++void __gsmd_log(int level, const char *file, int line, const char *function, const char *message, ...) ++ __attribute__ ((__format__ (__printf__, 5, 6))); + /* macro for logging including filename and line number */ + #define gsmd_log(level, format, args ...) \ + __gsmd_log(level, __FILE__, __LINE__, __FUNCTION__, format, ## args) +Index: gsm/include/gsmd/usock.h +=================================================================== +--- gsm.orig/include/gsmd/usock.h 2007-07-31 11:44:32.000000000 +0200 ++++ gsm/include/gsmd/usock.h 2007-07-31 11:46:44.000000000 +0200 +@@ -139,7 +139,7 @@ + /* for SMS-SUBMIT, SMS-DELIVER */ + enum gsmd_sms_tp_udhi { + GSMD_SMS_TP_UDHI_NO_HEADER = (0<<6), +- GSMD_SMS_TP_UDHI_WTIH_HEADER = (1<<6), ++ GSMD_SMS_TP_UDHI_WITH_HEADER = (1<<6), + }; + + /* SMS delflg from 3GPP TS 07.05, Clause 3.5.4 */ +@@ -160,6 +160,34 @@ + GSMD_PHONEBOOK_GET_SUPPORT = 6, + }; + ++/* Type-of-Address, Numbering Plan Identification field */ ++enum gsmd_toa_npi { ++ GSMD_TOA_NPI_UNKNOWN = 0x0, ++ GSMD_TOA_NPI_ISDN = 0x1, ++ GSMD_TOA_NPI_DATA = 0x3, ++ GSMD_TOA_NPI_TELEX = 0x4, ++ GSMD_TOA_NPI_NATIONAL = 0x8, ++ GSMD_TOA_NPI_PRIVATE = 0x9, ++ GSMD_TOA_NPI_ERMES = 0xa, ++ GSMD_TOA_NPI_RESERVED = 0xf, ++}; ++ ++/* Type-of-Address, Type-of-Number field */ ++enum gsmd_toa_ton { ++ GSMD_TOA_TON_UNKNOWN = (0<<4), ++ GSMD_TOA_TON_INTERNATIONAL = (1<<4), ++ GSMD_TOA_TON_NATIONAL = (2<<4), ++ GSMD_TOA_TON_NETWORK = (3<<4), ++ GSMD_TOA_TON_SUBSCRIBER = (4<<4), ++ GSMD_TOA_TON_ALPHANUMERIC = (5<<4), ++ GSMD_TOA_TON_ABBREVIATED = (6<<4), ++}; ++ ++/* Type-of-Address, bit 7 always 1 */ ++enum gsmd_toa_reserved { ++ GSMD_TOA_RESERVED = (1<<7), ++}; ++ + /* Length from 3GPP TS 04.08, Clause 10.5.4.7 */ + + #define GSMD_ADDR_MAXLEN 32 +@@ -269,6 +297,11 @@ + char user_data[140]; + } __attribute__ ((packed)); + ++struct gsmd_sms_send { ++ struct gsmd_addr addr; ++ struct gsmd_sms payload; ++}; ++ + /* Refer to GSM 07.07 subclause 8.12 */ + struct gsmd_phonebook_readrg { + u_int8_t index1; +Index: gsm/include/gsmd/vendorplugin.h +=================================================================== +--- gsm.orig/include/gsmd/vendorplugin.h 2007-07-31 11:46:28.000000000 +0200 ++++ gsm/include/gsmd/vendorplugin.h 2007-07-31 11:46:44.000000000 +0200 +@@ -12,7 +12,7 @@ + struct gsmd_vendor_plugin { + struct llist_head list; + unsigned char *name; +- unsigned char *ext_chars; ++ char *ext_chars; + unsigned int num_unsolicit; + const struct gsmd_unsolicit *unsolicit; + int (*detect)(struct gsmd *g); +Index: gsm/include/libgsmd/sms.h +=================================================================== +--- gsm.orig/include/libgsmd/sms.h 2007-07-31 11:44:32.000000000 +0200 ++++ gsm/include/libgsmd/sms.h 2007-07-31 11:46:44.000000000 +0200 +@@ -83,7 +83,7 @@ + extern int lgsmd_sms_send(struct lgsm_handle *lh, const struct lgsm_sms *sms); + + /* Write Message to Memory */ +-extern int lgsmd_sms_write(struct lgsm_handle *lh, ++extern int lgsmd_sms_write(struct lgsm_handle *lh, + const struct lgsm_sms_write *sms_write); + + /* Packing of 7-bit characters, refer to GSM 03.38 subclause 6.1.2.1.1 */ +Index: gsm/src/gsmd/atcmd.c +=================================================================== +--- gsm.orig/src/gsmd/atcmd.c 2007-07-31 11:46:42.000000000 +0200 ++++ gsm/src/gsmd/atcmd.c 2007-07-31 11:47:03.000000000 +0200 +@@ -82,9 +82,12 @@ + + switch (llp->state) { + case LLPARSE_STATE_IDLE: ++ case LLPARSE_STATE_PROMPT_SPC: + if (llp->flags & LGSM_ATCMD_F_EXTENDED) { + if (byte == '\r') + llp->state = LLPARSE_STATE_IDLE_CR; ++ else if (byte == '>') ++ llp->state = LLPARSE_STATE_PROMPT; + else { + #ifdef STRICT + llp->state = LLPARSE_STATE_ERROR; +@@ -108,6 +111,8 @@ + /* can we really go directly into result_cr ? */ + if (byte == '\r') + llp->state = LLPARSE_STATE_RESULT_CR; ++ else if (byte == '>') ++ llp->state = LLPARSE_STATE_PROMPT; + else { + llp->state = LLPARSE_STATE_RESULT; + ret = llparse_append(llp, byte); +@@ -127,6 +132,16 @@ + memset(llp->buf, 0, LLPARSE_BUF_SIZE); + } + break; ++ case LLPARSE_STATE_PROMPT: ++ if (byte == ' ') ++ llp->state = LLPARSE_STATE_PROMPT_SPC; ++ else { ++ /* this was not a real "> " prompt */ ++ llparse_append(llp, '>'); ++ ret = llparse_append(llp, byte); ++ llp->state = LLPARSE_STATE_RESULT; ++ } ++ break; + case LLPARSE_STATE_ERROR: + break; + } +@@ -147,6 +162,10 @@ + /* FIXME: what to do with return value ? */ + llp->cb(llp->buf, llp->cur - llp->buf, llp->ctx); + } ++ ++ /* if a full SMS-style prompt was received, poke the select */ ++ if (llp->state == LLPARSE_STATE_PROMPT_SPC) ++ llp->prompt_cb(llp->ctx); + } + + return 0; +@@ -178,7 +197,7 @@ + { + struct gsmd *g = ctx; + struct gsmd_atcmd *cmd = NULL; +- int rc = 0, final = 0; ++ int rc = 0; + + DEBUGP("buf=`%s'(%d)\n", buf, len); + +@@ -232,7 +251,6 @@ + DEBUGP("error number %lu\n", err_nr); + if (cmd) + cmd->ret = err_nr; +- final = 1; + goto final_cb; + } + if (!strncmp(buf+1, "CMS ERROR", 9)) { +@@ -242,7 +260,6 @@ + DEBUGP("error number %lu\n", err_nr); + if (cmd) + cmd->ret = err_nr; +- final = 1; + goto final_cb; + } + +@@ -274,7 +291,7 @@ + + /* it might be a multiline response, so if there's a previous + response, send out mlbuf and start afresh with an empty buffer */ +- if (mlbuf[0] != 0) { ++ if (mlbuf_len) { + if (!cmd->cb) { + gsmd_log(GSMD_NOTICE, "command without cb!!!\n"); + } else { +@@ -282,8 +299,8 @@ + cmd->resp = mlbuf; + rc = cmd->cb(cmd, cmd->ctx, cmd->resp); + DEBUGP("Clearing mlbuf\n"); +- mlbuf[0] = 0; + } ++ mlbuf_len = 0; + } + + /* the current buf will be appended to mlbuf below */ +@@ -302,7 +319,6 @@ + DEBUGP("unspecified error\n"); + if (cmd) + cmd->ret = 4; +- final = 1; + goto final_cb; + } + +@@ -311,7 +327,6 @@ + /* Part of Case 'C' */ + if (cmd) + cmd->ret = 0; +- final = 1; + goto final_cb; + } + +@@ -320,14 +335,12 @@ + if (!strncmp(buf, "NO CARRIER", 11) || + ((g->flags & GSMD_FLAG_V0) && buf[0] == '3')) { + /* Part of Case 'D' */ +- final = 1; + goto final_cb; + } + + if (!strncmp(buf, "BUSY", 4) || + ((g->flags & GSMD_FLAG_V0) && buf[0] == '7')) { + /* Part of Case 'D' */ +- final = 1; + goto final_cb; + } + } +@@ -335,21 +348,13 @@ + /* we reach here, if we are at an information response that needs to be + * passed on */ + +- if (mlbuf[0] == 0) { +- DEBUGP("Filling mlbuf\n"); +- strncat(mlbuf, buf, sizeof(mlbuf)-1); +- } else { +- DEBUGP("Appending buf to mlbuf\n"); +- mlbuf_len = strlen(mlbuf); +- if (mlbuf_len+1 < sizeof(mlbuf)) { +- mlbuf[mlbuf_len] = '\n'; +- mlbuf[mlbuf_len+1] = '\0'; +- strncat(mlbuf, buf, sizeof(mlbuf)-mlbuf_len-2); +- } else { +- DEBUGP("response too big for mlbuf!!!\n"); +- return -EFBIG; +- } +- } ++ if (mlbuf_len) ++ mlbuf[mlbuf_len ++] = '\n'; ++ DEBUGP("Appending buf to mlbuf\n"); ++ if (len > sizeof(mlbuf) - mlbuf_len) ++ len = sizeof(mlbuf) - mlbuf_len; ++ memcpy(mlbuf + mlbuf_len, buf, len); ++ mlbuf_len += len; + return 0; + + final_cb: +@@ -366,13 +371,16 @@ + } else { + DEBUGP("Calling final cmd->cb()\n"); + /* send final result code if there is no information response in mlbuf */ +- if (mlbuf[0] == 0) +- cmd->resp = buf; +- else ++ if (mlbuf_len) { + cmd->resp = mlbuf; ++ mlbuf[mlbuf_len] = 0; ++ gsmd_log(GSMD_NOTICE, ++ "the text discarded is %s\n", buf); ++ } else ++ cmd->resp = buf; + rc = cmd->cb(cmd, cmd->ctx, cmd->resp); + DEBUGP("Clearing mlbuf\n"); +- mlbuf[0] = 0; ++ mlbuf_len = 0; + } + + /* remove from list of currently executing cmds */ +@@ -385,7 +393,15 @@ + g->gfd_uart.when |= GSMD_FD_WRITE; + + return rc; +-} ++} ++ ++/* called when the modem asked for a new line of a multiline atcmd */ ++static int atcmd_prompt(void *data) ++{ ++ struct gsmd *g = data; ++ ++ g->gfd_uart.when |= GSMD_FD_WRITE; ++} + + /* callback to be called if [virtual] UART has some data for us */ + static int atcmd_select_cb(int fd, unsigned int what, void *data) +@@ -393,6 +409,7 @@ + int len, rc; + static char rxbuf[1024]; + struct gsmd *g = data; ++ char *cr; + + if (what & GSMD_FD_READ) { + memset(rxbuf, 0, sizeof(rxbuf)); +@@ -416,8 +433,12 @@ + if ((what & GSMD_FD_WRITE) && g->interpreter_ready) { + struct gsmd_atcmd *pos, *pos2; + llist_for_each_entry_safe(pos, pos2, &g->pending_atcmds, list) { +- len = strlen(pos->buf); +- rc = write(fd, pos->buf, strlen(pos->buf)); ++ cr = strchr(pos->cur, '\n'); ++ if (cr) ++ len = cr - pos->cur; ++ else ++ len = pos->buflen; ++ rc = write(fd, pos->cur, len); + if (rc == 0) { + gsmd_log(GSMD_ERROR, "write returns 0, aborting\n"); + break; +@@ -426,27 +447,32 @@ + fd, rc); + return rc; + } +- if (rc < len) { +- gsmd_log(GSMD_FATAL, "short write!!! FIXME!\n"); +- exit(3); +- } ++ if (cr && rc == len) ++ rc ++; /* Skip the \n */ ++ pos->buflen -= rc; ++ pos->cur += rc; + write(fd, "\r", 1); +- /* success: remove from global list of to-be-sent atcmds */ +- llist_del(&pos->list); +- /* append to global list of executing atcmds */ +- llist_add_tail(&pos->list, &g->busy_atcmds); ++ ++ if (!pos->buflen) { ++ /* success: remove from global list of ++ * to-be-sent atcmds */ ++ llist_del(&pos->list); ++ /* append to global list of executing atcmds */ ++ llist_add_tail(&pos->list, &g->busy_atcmds); + + /* we only send one cmd at the moment */ +- g->gfd_uart.when &= ~GSMD_FD_WRITE; + break; ++ } else { ++ /* The write was short or the atcmd has more ++ * lines to send after a "> ". */ ++ if (!(rc < len)) ++ break; ++ } + } +- } + +-#if 0 +- if (llist_empty(&g->pending_atcmds)) ++ /* Either pending_atcmds is empty or a command has to wait */ + g->gfd_uart.when &= ~GSMD_FD_WRITE; +-#endif +- ++ } + + return 0; + } +@@ -457,10 +483,10 @@ + { + int buflen = strlen(cmd); + struct gsmd_atcmd *atcmd; +- ++ + if (rlen > buflen) + buflen = rlen; +- ++ + atcmd = talloc_size(__atcmd_ctx, sizeof(*atcmd)+ buflen); + if (!atcmd) + return NULL; +@@ -471,6 +497,7 @@ + atcmd->ret = -255; + atcmd->buflen = buflen; + atcmd->buf[buflen-1] = '\0'; ++ atcmd->cur = atcmd->buf; + atcmd->cb = cb; + atcmd->resp = NULL; + strncpy(atcmd->buf, cmd, buflen-1); +@@ -483,8 +510,9 @@ + { + DEBUGP("submitting command `%s'\n", cmd->buf); + ++ if (llist_empty(&g->pending_atcmds)) ++ g->gfd_uart.when |= GSMD_FD_WRITE; + llist_add_tail(&cmd->list, &g->pending_atcmds); +- g->gfd_uart.when |= GSMD_FD_WRITE; + + return 0; + } +@@ -520,9 +548,9 @@ + g->llp.cur = g->llp.buf; + g->llp.len = sizeof(g->llp.buf); + g->llp.cb = &ml_parse; ++ g->llp.prompt_cb = &atcmd_prompt; + g->llp.ctx = g; + g->llp.flags = LGSM_ATCMD_F_EXTENDED; + + return gsmd_register_fd(&g->gfd_uart); +-} +- ++} +Index: gsm/src/gsmd/sms_cb.c +=================================================================== +--- gsm.orig/src/gsmd/sms_cb.c 2007-07-31 11:44:32.000000000 +0200 ++++ gsm/src/gsmd/sms_cb.c 2007-07-31 11:46:44.000000000 +0200 +@@ -91,9 +91,6 @@ + if (!ucmd) + return -ENOMEM; + +- +- +- + ucmd->hdr.version = GSMD_PROTO_VERSION; + ucmd->hdr.msg_type = GSMD_MSG_SMS; + ucmd->hdr.msg_subtype = GSMD_SMS_GETMSG_STORAGE; +@@ -188,14 +185,26 @@ + int sms_cb_init(struct gsmd *gsmd) + { + struct gsmd_atcmd *atcmd; ++ char buffer[10]; + + atcmd = atcmd_fill("AT+CSMS=0", NULL, gu, 0); + if (!atcmd) + return -ENOMEM; + atcmd_submit(gsmd, atcmd); + +- /* Switch into "text mode" (Section 3.2.3) */ +- atcdm = atcmd_fill("AT+CMGF=1", 9, &sms_cb_init_cb, gu, 0); ++ /* If text mode, set the encoding */ ++ if (gu->gsmd->flags & GSMD_FLAG_SMS_FMT) { ++ atcmd = atcmd_fill("AT+CSCS=\"IRA\"", 13, NULL, gu, 0); ++ if (!atcmd) ++ return -ENOMEM; ++ atcmd_submit(gsmd, atcmd); ++ } ++ ++ /* Switch into desired mode (Section 3.2.3) */ ++ snprintf(buffer, sizeof(buffer), "AT+CMGF=%i", ++ (gu->gsmd->flags & GSMD_FLAG_SMS_FMT) ? ++ GSMD_SMS_FMT_TEXT : GSMD_SMS_FMT_PDU); ++ atcmd = atcmd_fill(buffer, strlen(buffer), &sms_cb_init_cb, gu, 0); + if (!atcmd) + return -ENOMEM; + +Index: gsm/src/gsmd/usock.c +=================================================================== +--- gsm.orig/src/gsmd/usock.c 2007-07-31 11:44:32.000000000 +0200 ++++ gsm/src/gsmd/usock.c 2007-07-31 11:46:44.000000000 +0200 +@@ -75,7 +75,7 @@ + ucmd->hdr.version = GSMD_PROTO_VERSION; + ucmd->hdr.msg_type = GSMD_MSG_PASSTHROUGH; + ucmd->hdr.msg_subtype = GSMD_PASSTHROUGH_RESP; +- ucmd->hdr.len = strlen(resp)+1; ++ ucmd->hdr.len = rlen; + ucmd->hdr.id = cmd->id; + memcpy(ucmd->buf, resp, ucmd->hdr.len); + +@@ -100,7 +100,7 @@ + + 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), gph->id); ++ u_int32_t *evtmask = (u_int32_t *) ((char *)gph + sizeof(*gph)); + + if (len < sizeof(*gph) + sizeof(u_int32_t)) + return -EINVAL; +@@ -471,18 +471,15 @@ + + static int sms_send_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp) + { +- struct gsmd_user *gu = ctx; ++ struct gsmd_user *gu = (struct gsmd_user *) ctx; + struct gsmd_ucmd *ucmd; +- +- ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_SMS, +- GSMD_SMS_SEND, 0); ++ ++ ucmd = gsmd_ucmd_fill(strlen(resp) + 1, ++ GSMD_MSG_SMS, GSMD_SMS_SEND, cmd->id); + if (!ucmd) + return -ENOMEM; +- + strcpy(ucmd->buf, resp); +- + usock_cmd_enqueue(ucmd, gu); +- + return 0; + } + +@@ -520,34 +517,142 @@ + return 0; + } + ++int packing_7bit_character(char *src, char *dest) ++{ ++ int i,j = 0; ++ unsigned char ch1, ch2; ++ char tmp[2]; ++ int shift = 0; ++ ++ *dest = '\0'; ++ ++ for ( i=0; i<strlen(src); i++ ) { ++ ++ ch1 = src[i] & 0x7F; ++ ch1 = ch1 >> shift; ++ ch2 = src[(i+1)] & 0x7F; ++ ch2 = ch2 << (7-shift); ++ ++ ch1 = ch1 | ch2; ++ ++ j = strlen(dest); ++ sprintf(tmp, "%X", (ch1 >> 4)); ++ dest[j++] = tmp[0]; ++ sprintf(tmp, "%X", (ch1 & 0x0F)); ++ dest[j++] = tmp[0]; ++ dest[j++] = '\0'; ++ ++ shift++; ++ ++ if ( 7 == shift ) { ++ shift = 0; ++ i++; ++ } ++ } ++ ++ return 0; ++} ++ ++/* Refer to GSM 03.40 subclause 9.2.3.3, for SMS-SUBMIT */ ++static int usock_pdu_make_smssubmit(char *dest, struct gsmd_sms_send *src) ++{ ++ u_int8_t header[10 + GSMD_ADDR_MAXLEN]; ++ int pos = 0, i, coding7bit = 1; ++ ++ /* (Should be optional but some modems require it) SMSC Length octet ++ * is prepended. If omitted or zero, use SMSC stored in the phone. */ ++ header[pos ++] = 0x00; ++ ++ header[pos ++] = ++ GSMD_SMS_TP_MTI_SUBMIT | ++ (0 << 2) | /* Reject Duplicates: 0 */ ++ GSMD_SMS_TP_VPF_NOT_PRESENT | ++ GSMD_SMS_TP_SRR_NOT_REQUEST | ++ GSMD_SMS_TP_UDHI_NO_HEADER | ++ GSMD_SMS_TP_RP_NOT_SET; ++ ++ /* TP-Message-Reference - 00 lets the phone set the number itself */ ++ header[pos ++] = 0x00; ++ ++ header[pos ++] = strlen(src->addr.number); ++ header[pos ++] = src->addr.type; ++ for (i = 0; src->addr.number[i]; i ++) { ++ header[pos] = src->addr.number[i ++] - '0'; ++ if (src->addr.number[i]) ++ header[pos ++] |= (src->addr.number[i] - '0') << 4; ++ else { ++ header[pos ++] |= 0xf0; ++ break; ++ } ++ } ++ ++ /* TP-Protocol-Identifier - 00 means implicit */ ++ header[pos ++] = 0x00; ++ ++ /* TP-Data-Coding-Scheme - 00 for 7-bit default alphabet */ ++ header[pos ++] = coding7bit ? 0x00 : 0x04; ++ ++ /* TP-Validity-Period, if present, would go here */ ++ ++ header[pos ++] = src->payload.length; ++ ++ if (dest) { ++ for (i = 0; i < pos; i ++) { ++ sprintf(dest, "%02X", header[i]); ++ dest += 2; ++ } ++ if (coding7bit) ++ packing_7bit_character(src->payload.data, dest); ++ else ++ for (i = 0; i < src->payload.length; i ++) { ++ sprintf(dest, "%02X", src->payload.data[i]); ++ dest += 2; ++ } ++ } ++ ++ if (coding7bit) ++ return ((src->payload.length * 7 + 7) >> 3) + pos; ++ else ++ return src->payload.length + pos; ++} ++ ++static const char *gsmd_cmgl_stat[] = { ++ "REC UNREAD", "REC READ", "STO UNSENT", "STO SENT", "ALL", ++}; ++ + static 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 *gs; ++ struct gsmd_sms_send *gss; + struct gsmd_sms_write *gsw; + int *stat, *index; + int atcmd_len; + char buf[1024]; +- ++ + switch (gph->msg_subtype) { + case GSMD_SMS_LIST: + /* FIXME: only support PDU mode!! */ + if(len < sizeof(*gph) + sizeof(int)) + return -EINVAL; +- stat = (int *) ((void *)gph + sizeof(*gph)); ++ stat = (int *) ((void *)gph + sizeof(*gph)); ++ if (*stat < 0 || *stat > 4) ++ return -EINVAL; + +- sprintf(buf, "%d", *stat); +- +- atcmd_len = 1 + strlen("AT+CMGL=") + strlen(buf); +- cmd = atcmd_fill("AT+CMGL=", atcmd_len, +- &sms_list_cb, gu, gph->id); ++ if (gu->gsmd->flags & GSMD_FLAG_SMS_FMT) ++ 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); + if (!cmd) + return -ENOMEM; +- sprintf(cmd->buf, "AT+CMGL=%s", buf); + break; ++ + case GSMD_SMS_READ: + /* FIXME: only support PDU mode!! */ + if(len < sizeof(*gph) + sizeof(int)) +@@ -563,6 +668,34 @@ + return -ENOMEM; + sprintf(cmd->buf, "AT+CMGR=%s", buf); + break; ++ ++ case GSMD_SMS_SEND: ++ if (len < sizeof(*gph) + sizeof(*gss)) ++ return -EINVAL; ++ gss = (struct gsmd_sms_send *) ((void *) gph + sizeof(*gph)); ++ ++ if (gu->gsmd->flags & GSMD_FLAG_SMS_FMT) { ++ atcmd_len = sprintf(buf, "AT+CMGS=\"%s\"\n%.*s", ++ gss->addr.number, ++ gss->payload.length, ++ gss->payload.data); ++ } else { ++ atcmd_len = sprintf(buf, "AT+CMGS=%i\n", ++ usock_pdu_make_smssubmit(NULL, ++ gss) - 1); ++ atcmd_len += usock_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); ++ if (!cmd) ++ return -ENOMEM; ++ break; ++ case GSMD_SMS_WRITE: ++ gsmd_log(GSMD_DEBUG, "sms write\n"); ++ break; + #if 0 + case GSMD_SMS_SEND: + /* FIXME: only support PDU mode!! */ +@@ -610,8 +743,8 @@ + default: + return -EINVAL; + } +- +- gsmd_log(GSMD_DEBUG, "%s\n", cmd->buf); ++ ++ gsmd_log(GSMD_DEBUG, "%s\n", cmd ? cmd->buf : 0); + if (cmd) + return atcmd_submit(gu->gsmd, cmd); + else +@@ -867,7 +1000,7 @@ + [GSMD_MSG_PIN] = &usock_rcv_pin, + [GSMD_MSG_PHONE] = &usock_rcv_phone, + [GSMD_MSG_NETWORK] = &usock_rcv_network, +- [GSMD_MSG_SMS] = &usock_rcv_sms, ++ [GSMD_MSG_SMS] = &usock_rcv_sms, + //[GSMD_MSG_PHONEBOOK] = &usock_rcv_phonebook, + }; + +Index: gsm/src/gsmd/vendor_ti.c +=================================================================== +--- gsm.orig/src/gsmd/vendor_ti.c 2007-07-31 11:46:28.000000000 +0200 ++++ gsm/src/gsmd/vendor_ti.c 2007-07-31 11:46:44.000000000 +0200 +@@ -277,7 +277,7 @@ + + static int ticalypso_initsettings(struct gsmd *g) + { +- int rc; ++ int rc = 0; + struct gsmd_atcmd *cmd; + + /* use +CTZR: to report time zone changes */ +Index: gsm/src/libgsmd/libgsmd_sms.c +=================================================================== +--- gsm.orig/src/libgsmd/libgsmd_sms.c 2007-07-31 11:44:32.000000000 +0200 ++++ gsm/src/libgsmd/libgsmd_sms.c 2007-07-31 11:46:44.000000000 +0200 +@@ -83,19 +83,33 @@ + return 0; + } + +-int lgsmd_sms_send(struct lgsm_handle *lh, +- const struct lgsm_sms *sms) ++#ifndef MIN ++# define MIN(a,b) (((a) < (b)) ? (a) : (b)) ++#endif ++ ++int lgsmd_sms_send(struct lgsm_handle *lh, ++ const struct lgsm_sms *sms) + { + /* FIXME: only support PDU mode */ + struct gsmd_msg_hdr *gmh; +- struct gsmd_sms *gs; ++ struct gsmd_sms_send *gss; + int rc; + + gmh = lgsm_gmh_fill(GSMD_MSG_SMS, +- GSMD_SMS_SEND, sizeof(*gs)); ++ GSMD_SMS_SEND, sizeof(*gss)); + if (!gmh) + return -ENOMEM; +- gs = (struct gsmd_sms *) gmh->data; ++ gss = (struct gsmd_sms_send *) gmh->data; ++ ++ gss->addr.type = ++ GSMD_TOA_NPI_ISDN | ++ GSMD_TOA_TON_UNKNOWN | ++ GSMD_TOA_RESERVED; ++ strncpy(gss->addr.number, sms->addr, sizeof(gss->addr.number)); ++ ++ gss->payload.length = ++ MIN(strlen(sms->data), sizeof(gss->payload.data)); ++ memcpy(gss->payload.data, sms->data, gss->payload.length); + + rc = lgsm_send(lh, gmh); + if (rc < gmh->len + sizeof(*gmh)) { +@@ -108,7 +122,7 @@ + return 0; + } + +-int lgsmd_sms_write(struct lgsm_handle *lh, ++int lgsmd_sms_write(struct lgsm_handle *lh, + const struct lgsm_sms_write *sms_write) + { + /* FIXME: only support PDU mode */ + |