From f090469e2776fea6a27a7ac6612b666d20dc9a05 Mon Sep 17 00:00:00 2001 From: James Maki Date: Fri, 10 Sep 2010 10:49:55 -0500 Subject: sms using text mode --- src/sms_list.c | 274 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 259 insertions(+), 15 deletions(-) (limited to 'src/sms_list.c') diff --git a/src/sms_list.c b/src/sms_list.c index 0ccec15..e6f29f1 100644 --- a/src/sms_list.c +++ b/src/sms_list.c @@ -42,6 +42,236 @@ #define CMGL_HEADER_START "+CMGL: " #define CMGR_HEADER_START "+CMGR: " +static int decode_timestamp_text_mode(const char *str, struct tm *tm) +{ + char *cp; + struct tm tm_now; + time_t now = time(NULL); + + localtime_r(&now, &tm_now); + + memset(tm, 0, sizeof(*tm)); + + cp = (char *) strptime(str, "%y/%m/%d,%H:%M:%S", tm); + if (!cp || *cp) { + log_error("timestamp could not be converted to tm"); + return -1; + } + + tm->tm_gmtoff = tm_now.tm_gmtoff; + + return 0; +} + +static int process_header_text_mode(struct msg_list_info *list_info, char *buf, size_t len) +{ + char *save = buf; + char *token; + + struct sms_msg *msg; + int index; + int status; + char *name; + char *timestamp = NULL; + int msg_len; + + token = atcmd_response_brk(&save); + if (!token) { + log_debug("response tokenizing failed at start"); + return -1; + } + + switch (list_info->cmd_type) { + case CMD_TYPE_CMGL: + token = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at index"); + return -1; + } + index = atoi(token); + + break; + case CMD_TYPE_CMGR: + index = list_info->index; + break; + default: + return false; + } + + token = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at msg-status"); + return -1; + } + status = msg_status_name_to_value(token); + + token = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at name"); + return -1; + } + name = token; + + if (list_info->cmd_type == CMD_TYPE_CMGR) { + timestamp = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at timestamp"); + return -1; + } + } + + token = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at lang"); + return -1; + } + + token = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at encode"); + return -1; + } + + if (list_info->cmd_type == CMD_TYPE_CMGR) { + token = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at prio"); + return -1; + } + if (*save == '\"') { + token = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at callback"); + return -1; + } + } + } + + token = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at msg-len"); + return -1; + } + msg_len = atoi(token); + + switch (status) { + case SMS_MSG_REC_UNREAD: + list_info->nr_unread++; + break; + case SMS_MSG_REC_READ: + list_info->nr_read++; + break; + case SMS_MSG_STO_UNSENT: + list_info->nr_unsent++; + break; + case SMS_MSG_STO_SENT: + list_info->nr_sent++; + break; + default: + log_warning("msg-status unknown"); + list_info->nr_unknown++; + } + + msg = sms_msg_alloc(); + if (!msg) { + log_error("out of memory"); + return -1; + } + + memset(msg, 0, sizeof(*msg)); + + msg->index = index; + msg->status = status; + snprintf(msg->name, sizeof(msg->name), "%s", name); + msg->len = msg_len; + if (timestamp) { + decode_timestamp_text_mode(timestamp, &msg->pdu.timestamp); + } + + list_add_tail(&msg->list, &list_info->msg_list); + + list_info->nr_msgs++; + + return 0; +} + +static ssize_t readn(int fd, void *buf, size_t len) +{ + ssize_t cc; + ssize_t total; + + total = 0; + + while (len) { + cc = read(fd, buf, len); + if (cc <= 0) { + return cc; + } + + total += cc; + buf = buf + cc; + len -= cc; + } + + log_debug("read: \"%.*J\"", len, buf); + + return total; +} + +static int sms_list_text_mode(int fd, struct msg_list_info *list_info) +{ + char buf[ATCMD_LINE_SIZE]; + int tmp; + struct sms_msg *msg; + + while (1) { + tmp = atcmd_readline(fd, buf, sizeof(buf)); + if (tmp <= 0) { + return -1; + } + + list_info->nr_lines++; + + if (!strncmp(buf, CMGL_HEADER_START, strlen(CMGL_HEADER_START)) || + !strncmp(buf, CMGR_HEADER_START, strlen(CMGR_HEADER_START))) { + tmp = process_header_text_mode(list_info, buf, sizeof(buf)); + if (tmp < 0) { + log_debug("process_header_text_mode failed"); + return -1; + } + + if (list_empty(&list_info->msg_list)) { + log_debug("empty list"); + return -1; + } + + msg = list_entry(list_info->msg_list.prev, typeof(*msg), list); + if (msg->len <= 0) { + continue; + } + if (msg->len >= PDU_UD_SIZE) { + continue; + } + + list_info->nr_lines++; + + tmp = readn(fd, msg->pdu.user_data, msg->len); + if (tmp <= 0) { + log_debug("read message failed"); + return -1; + } + + msg->pdu.user_data_len = msg->len; + } else if (!strcmp(buf, "OK")) { + return 0; + } else if (*buf) { + log_debug("AT response error: %s", buf); + + return -1; + } + } +} + static int process_header(struct msg_list_info *list_info, char *buf, size_t len) { char *save = buf; @@ -221,8 +451,8 @@ static int print_list_yaml(struct msg_list_info *list_info) enum { LIST_STATE_BLANK, - LIST_STATE_OPEN, - LIST_STATE_PDU, + LIST_STATE_HEADER, + LIST_STATE_DATA, LIST_STATE_CLOSE, }; @@ -244,16 +474,16 @@ static int list_info_callback(char *buf, size_t len, void *data) return -1; } - list_info->state = LIST_STATE_OPEN; + list_info->state = LIST_STATE_HEADER; return 0; - case LIST_STATE_OPEN: - log_debug("state: LIST_STATE_OPEN"); + case LIST_STATE_HEADER: + log_debug("state: LIST_STATE_HEADER"); if (!strncmp(buf, CMGL_HEADER_START, strlen(CMGL_HEADER_START)) || !strncmp(buf, CMGR_HEADER_START, strlen(CMGR_HEADER_START))) { - list_info->state = LIST_STATE_PDU; + list_info->state = LIST_STATE_DATA; return process_header(list_info, buf, len); } else if (!strcmp(buf, "OK")) { @@ -269,8 +499,8 @@ static int list_info_callback(char *buf, size_t len, void *data) return 0; } - case LIST_STATE_PDU: - log_debug("state: LIST_STATE_PDU"); + case LIST_STATE_DATA: + log_debug("state: LIST_STATE_DATA"); if (list_empty(&list_info->msg_list)) { log_debug("empty list"); @@ -285,7 +515,7 @@ static int list_info_callback(char *buf, size_t len, void *data) } } - list_info->state = LIST_STATE_OPEN; + list_info->state = LIST_STATE_HEADER; return 0; @@ -324,7 +554,11 @@ int sms_list_get(int fd, struct msg_list_info *list_info) switch (list_info->cmd_type) { case CMD_TYPE_CMGL: - atcmd_writeline(fd, "AT+CMGL=%d", list_info->status); + if (Global.core.sms_mode == SMS_TEXT_MODE) { + atcmd_writeline(fd, "AT+CMGL=\"%s\"", msg_status_value_to_name(list_info->status)); + } else { + atcmd_writeline(fd, "AT+CMGL=%d", list_info->status); + } break; case CMD_TYPE_CMGR: @@ -335,12 +569,22 @@ int sms_list_get(int fd, struct msg_list_info *list_info) return -1; } - tmp = atcmd_response_foreach_line(fd, list_info_callback, list_info); - if (tmp < 0) { - log_error("listing failed"); - sms_list_free(list_info); + if (Global.core.sms_mode == SMS_TEXT_MODE) { + tmp = sms_list_text_mode(fd, list_info); + if (tmp < 0) { + log_error("listing failed"); + sms_list_free(list_info); - return tmp; + return tmp; + } + } else if (Global.core.sms_mode == SMS_PDU_MODE) { + tmp = atcmd_response_foreach_line(fd, list_info_callback, list_info); + if (tmp < 0) { + log_error("listing failed"); + sms_list_free(list_info); + + return tmp; + } } return 0; -- cgit v1.2.3