diff options
| author | Uros Majstorovic <majstor@majstor.org> | 2024-09-04 21:07:29 +0200 | 
|---|---|---|
| committer | Uros Majstorovic <majstor@majstor.org> | 2024-09-04 21:07:29 +0200 | 
| commit | 9da5f8409c85637361d7bc69b721f6d9d3087b7b (patch) | |
| tree | f53bd2d8f9f59b683519ce87551db6ee23be2062 /fw/esp32/components/eos/cell_sms.c | |
| parent | ec892bf2e7620fb58e635b900ab4a0e44e3488bd (diff) | |
esp32 cellular modem driver fix
Diffstat (limited to 'fw/esp32/components/eos/cell_sms.c')
| -rw-r--r-- | fw/esp32/components/eos/cell_sms.c | 340 | 
1 files changed, 203 insertions, 137 deletions
| diff --git a/fw/esp32/components/eos/cell_sms.c b/fw/esp32/components/eos/cell_sms.c index ac710f9..f1f8b33 100644 --- a/fw/esp32/components/eos/cell_sms.c +++ b/fw/esp32/components/eos/cell_sms.c @@ -15,170 +15,213 @@  static const char *TAG = "EOS SMS"; -static char cmd[256]; +static char _pdu_in[2048]; +static char _pdu_out[2048]; -static char pdu[4096]; -static int pdu_len; +extern char *at_cmd_buf; -static uint8_t udh[GSM_UDH_SIZE]; -static int udh_len; +static ssize_t sms_encode(unsigned char *buffer, uint16_t buf_len, char *pdu, size_t pdu_size) { +    ucp_t ch; +    size_t pdu_len; +    ssize_t rv; +    int i; -static uint8_t msg[GSM_MSG_SIZE]; -static int msg_len; -static uint8_t msg_enc; +    char *addr; +    uint8_t addr_type; +    size_t addr_len; + +    uint8_t txt[GSM_UD_SIZE]; +    size_t txt_len; + +    uint16_t flags; + +    if (buf_len < 2) return EOS_ERR_SIZE; +    flags = buffer[0] << 8; +    flags |= buffer[1]; +    buffer += 2; +    buf_len -= 2; + +    if (buf_len < 2) return EOS_ERR_SIZE; +    switch (buffer[0]) { +        case EOS_CELL_SMS_ADDRTYPE_INTL: +            addr_type = GSM_EXT | GSM_TON_INTERNATIONAL | GSM_NPI_TELEPHONE; +            break; + +        case EOS_CELL_SMS_ADDRTYPE_OTHER: +            addr_type = GSM_EXT | GSM_TON_UNKNOWN | GSM_NPI_TELEPHONE; +            break; + +        default: +            return EOS_ERR; +    } +    addr_len = buffer[1]; +    addr = (char *)buffer + 2; -static char orig_addr[GSM_ADDR_SIZE]; -static int orig_addr_len; -static uint8_t orig_addr_type; +    if (buf_len < 2 + addr_len) return EOS_ERR_SIZE; +    buffer += 2 + addr_len; +    buf_len -= 2 + addr_len; -static char smsc_addr[GSM_ADDR_SIZE]; -static int smsc_addr_len; -static uint8_t smsc_addr_type; +    i = 0; +    txt_len = 0; +    while (i < buf_len) { +        int _rv; + +        if (buf_len - i < 4) { +            _rv = utf8_len_str(buffer + i); +            if (_rv < 0) return EOS_ERR; +            if (buf_len - i < _rv) return EOS_ERR_SIZE; +        } -static char smsc_timestamp[GSM_TS_SIZE]; +        _rv = utf8_dec(buffer + i, &ch); +        if (_rv < 0) return EOS_ERR; +        if (ch >= 0xffff) return EOS_ERR; +        i += _rv; -uint16_t flags; +        _rv = gsm_ucs2_to_7bit((char *)txt + txt_len, sizeof(txt) - txt_len, ch); +        if (_rv < 0) return EOS_ERR; +        txt_len += _rv; +    } + +    if (pdu_size < 2) return EOS_ERR_SIZE; +    pdu_putc(pdu, 0); -static int sms_decode(unsigned char *buf, uint16_t *_len) { -    int i, j, rv; -    uint16_t len = 0; -    uint8_t smsc_info, smsc_info_len; +    rv = gsm_sms_enc(pdu + 2, pdu_size - 2, addr, addr_len, addr_type, NULL, 0, txt, txt_len, GSM_ENC_7BIT, flags); +    if (rv < 0) return EOS_ERR; +    pdu_len = rv + 2; + +    return pdu_len; +} -    if (pdu_len < 2) return EOS_ERR; -    smsc_info = pdu_getc(pdu); +static ssize_t sms_decode(char *pdu, size_t pdu_len, unsigned char *buf, uint16_t buf_size) { +    uint16_t buf_len = 0; +    ssize_t rv; +    int i, j; + +    char smsc_addr[GSM_ADDR_SIZE]; +    size_t smsc_addr_len; +    uint8_t smsc_info, smsc_info_len, smsc_addr_type; + +    char orig_addr[GSM_ADDR_SIZE]; +    size_t orig_addr_len; +    uint8_t orig_addr_type; + +    uint8_t udh[GSM_UDH_SIZE]; +    size_t udh_len; + +    uint8_t txt[GSM_UD_SIZE]; +    size_t txt_len; +    uint8_t txt_enc; + +    char smsc_timestamp[GSM_TS_SIZE]; +    uint16_t flags; + +    if (pdu_len < 2) return EOS_ERR_SIZE; +    rv = pdu_getc(pdu, &smsc_info); +    if (rv < 0) return rv;      smsc_info_len = 2 * (smsc_info + 1); -    if (pdu_len < smsc_info_len) return EOS_ERR; +    if (pdu_len < smsc_info_len) return EOS_ERR_SIZE;      if (smsc_info > 1) { -        pdu_putc((smsc_info - 1) * 2, pdu); +        /* SMSC address - currently not used */ +        pdu_putc(pdu, (smsc_info - 1) * 2);          rv = gsm_addr_dec(pdu, pdu_len, smsc_addr, &smsc_addr_len, &smsc_addr_type);          if (rv < 0) smsc_addr_len = 0;      } -    rv = gsm_sms_dec(pdu + smsc_info_len, pdu_len - smsc_info_len, orig_addr, &orig_addr_len, &orig_addr_type, udh, &udh_len, msg, &msg_len, smsc_timestamp, &msg_enc, &flags); -    if (rv == GSM_ERR_NOT_SUPPORTED) ESP_LOGE(TAG, "Message not supported: %s", pdu); -    if (rv < 0) return rv; -    if (msg_enc == GSM_ENC_8BIT) return EOS_ERR; +    rv = gsm_sms_dec(pdu + smsc_info_len, pdu_len - smsc_info_len, orig_addr, &orig_addr_len, &orig_addr_type, udh, &udh_len, txt, &txt_len, &txt_enc, smsc_timestamp, &flags); +    if ((rv == GSM_ERR_NOTSUPPORTED) || (txt_enc == GSM_ENC_8BIT)) { +        ESP_LOGE(TAG, "Message not supported: %s", pdu); +        return EOS_ERR_NOTSUPPORTED; +    } +    if (rv < 0) return EOS_ERR; +    if (buf_size < buf_len + 2) return EOS_ERR_SIZE;      buf[0] = flags >> 8;      buf[1] = flags; -    len += 2; +    buf_len += 2; -    memcpy(buf + len, smsc_timestamp, GSM_TS_SIZE); -    len += GSM_TS_SIZE; +    if (buf_size < buf_len + GSM_TS_SIZE) return EOS_ERR_SIZE; +    memcpy(buf + buf_len, smsc_timestamp, GSM_TS_SIZE); +    buf_len += GSM_TS_SIZE;      if ((orig_addr_type & GSM_TON) == GSM_TON_ALPHANUMERIC) { -        buf[len] = EOS_CELL_SMS_ADDRTYPE_ALPHA; -        buf[len + 1] = 0; -        len += 2; +        if (buf_size < buf_len + 2) return EOS_ERR_SIZE; +        buf[buf_len] = EOS_CELL_SMS_ADDRTYPE_ALPHA; +        buf[buf_len + 1] = 0; +        buf_len += 2;          i = 0;          j = 0;          while (i < orig_addr_len) {              uint16_t ch; +            int _rv; -            rv = gsm_7bit_to_ucs2((char *)orig_addr + i, orig_addr_len - i, &ch); -            if (rv < 0) return EOS_ERR; -            i += rv; -            rv = utf8_enc(ch, buf + len + j); -            if (rv < 0) return EOS_ERR; -            j += rv; +            _rv = gsm_7bit_to_ucs2((char *)orig_addr + i, orig_addr_len - i, &ch); +            if (_rv < 0) return EOS_ERR; +            i += _rv; + +            if (buf_size - buf_len - j < 4) { +                _rv = utf8_len_ch(ch); +                if (_rv < 0) return EOS_ERR; +                if (buf_size - buf_len - j < _rv) return EOS_ERR_SIZE; +            } + +            _rv = utf8_enc(ch, buf + buf_len + j); +            if (_rv < 0) return EOS_ERR; +            j += _rv;          } -        buf[len - 1] = j; -        len += j; +        buf[buf_len - 1] = j; +        buf_len += j;      } else { -        buf[len] = ((orig_addr_type & GSM_TON) == GSM_TON_INTERNATIONAL) ? EOS_CELL_SMS_ADDRTYPE_INTL : EOS_CELL_SMS_ADDRTYPE_OTHER; -        buf[len + 1] = orig_addr_len; -        len += 2; -        memcpy(buf + len, orig_addr, orig_addr_len); -        len += orig_addr_len; +        if (buf_size < buf_len + 2) return EOS_ERR_SIZE; +        buf[buf_len] = ((orig_addr_type & GSM_TON) == GSM_TON_INTERNATIONAL) ? EOS_CELL_SMS_ADDRTYPE_INTL : EOS_CELL_SMS_ADDRTYPE_OTHER; +        buf[buf_len + 1] = orig_addr_len; +        buf_len += 2; + +        if (buf_size < buf_len + orig_addr_len) return EOS_ERR_SIZE; +        memcpy(buf + buf_len, orig_addr, orig_addr_len); +        buf_len += orig_addr_len;      }      i = 0;      j = 0; -    while (i < msg_len) { -        utf32_t ch; +    while (i < txt_len) { +        ucp_t ch; +        int _rv; -        if (msg_enc == GSM_ENC_7BIT) { +        if (txt_enc == GSM_ENC_7BIT) {              uint16_t _ch; -            rv = gsm_7bit_to_ucs2((char *)msg + i, msg_len - i, &_ch); +            _rv = gsm_7bit_to_ucs2((char *)txt + i, txt_len - i, &_ch); +            if (_rv < 0) return EOS_ERR;              ch = _ch;          } else { -            if (((msg_len - i) < 4) && (utf16_len(msg + i) > 2)) { -                rv = EOS_ERR; -            } else { -                rv = utf16_dec(msg + i, &ch); +            if (txt_len - i < 2) return EOS_ERR_SIZE; +            if (txt_len - i < 4) { +                _rv = utf16_len_str(txt + i); +                if (_rv < 0) return EOS_ERR; +                if (txt_len - i < _rv) return EOS_ERR_SIZE;              } +            _rv = utf16_dec(txt + i, &ch); +            if (_rv < 0) return EOS_ERR;          } -        if (rv < 0) return EOS_ERR; -        i += rv; +        i += _rv; -        rv = utf8_enc(ch, buf + len + j); -        if (rv < 0) return EOS_ERR; -        j += rv; -    } -    buf[len + j] = '\0'; -    len += j + 1; -    *_len = len; - -    return EOS_OK; -} - -static int sms_encode(unsigned char *buffer, uint16_t len) { -    utf32_t ch; -    int i, rv; -    char *addr; -    uint8_t addr_type; -    int addr_len; - -    if (len < 2) return EOS_ERR; -    flags = buffer[0] << 8; -    flags |= buffer[1]; -    buffer += 2; -    len -= 2; - -    if (len < 2) return EOS_ERR; -    switch (buffer[0]) { -        case EOS_CELL_SMS_ADDRTYPE_INTL: -            addr_type = GSM_EXT | GSM_TON_INTERNATIONAL | GSM_NPI_TELEPHONE; -            break; - -        case EOS_CELL_SMS_ADDRTYPE_OTHER: -            addr_type = GSM_EXT | GSM_TON_UNKNOWN | GSM_NPI_TELEPHONE; -            break; - -        default: -            return EOS_ERR; -    } -    addr_len = buffer[1]; -    addr = (char *)buffer + 2; - -    if (len < 2 + addr_len) return EOS_ERR; -    buffer += 2 + addr_len; -    len -= 2 + addr_len; - -    i = 0; -    msg_len = 0; -    while (i < len) { -        rv = utf8_dec(buffer + i, &ch); -        if (rv < 0) return EOS_ERR; -        if (ch >= 0xffff) return EOS_ERR; -        i += rv; +        if (buf_size - buf_len - j < 4) { +            _rv = utf8_len_ch(ch); +            if (_rv < 0) return EOS_ERR; +            if (buf_size - buf_len - j < _rv) return EOS_ERR_SIZE; +        } -        rv = gsm_ucs2_to_7bit(ch, (char *)msg + msg_len, sizeof(msg) - msg_len); -        if (rv < 0) return EOS_ERR; -        msg_len += rv; +        _rv = utf8_enc(ch, buf + buf_len + j); +        if (_rv < 0) return EOS_ERR; +        j += _rv;      } +    if (buf_size < buf_len + j + 1) return EOS_ERR_SIZE; +    buf[buf_len + j] = '\0'; +    buf_len += j + 1; -    pdu_putc(0, pdu); -    rv = gsm_sms_enc(addr, addr_len, addr_type, NULL, 0, msg, msg_len, GSM_ENC_7BIT, flags, pdu + 2, sizeof(pdu) - 4); -    if (rv < 0) return EOS_ERR; -    pdu_len = rv; -    pdu[pdu_len + 2] = CTRL_Z; -    pdu[pdu_len + 3] = '\0'; - -    return EOS_OK; +    return buf_len;  }  void eos_cell_sms_handler(unsigned char mtype, unsigned char *buffer, uint16_t buf_len) { @@ -190,34 +233,40 @@ void eos_cell_sms_handler(unsigned char mtype, unsigned char *buffer, uint16_t b          case EOS_CELL_MTYPE_SMS_LIST: {              if (buf_len < 1) return; -            rv = snprintf(cmd, sizeof(cmd), "AT+CMGL=%d\r", buffer[0]); -            if ((rv < 0) || (rv >= sizeof(cmd))) return; +            rv = snprintf(at_cmd_buf, AT_SIZE_CMD_BUF, "AT+CMGL=%d\r", buffer[0]); +            if ((rv < 0) || (rv >= AT_SIZE_CMD_BUF)) return;              rv = eos_modem_take(1000);              if (rv) return; -            at_cmd(cmd); +            at_cmd(at_cmd_buf);              do {                  unsigned char *buf; -                uint16_t len; +                uint16_t buf_len; + +                char *pdu = _pdu_in; +                size_t pdu_size = sizeof(_pdu_in); +                size_t pdu_len; +                ssize_t _rv;                  rv = at_expect("^\\+CMGL: [0-9]+,[0-9],.*,[0-9]+$", "^OK", 1000);                  if (rv) break; -                rv = eos_modem_readln(pdu, sizeof(pdu), 1000); +                rv = eos_modem_readln(pdu, pdu_size, 1000);                  if (rv) break;                  pdu_len = strlen(pdu);                  buf = eos_net_alloc();                  buf[0] = EOS_CELL_MTYPE_SMS | EOS_CELL_MTYPE_SMS_LIST_ITEM; -                rv = sms_decode(buf + 1, &len); -                if (rv) { +                _rv = sms_decode(pdu, pdu_len, buf + 1, EOS_NET_SIZE_BUF - 1); +                if (_rv < 0) {                      eos_net_free(buf);                      continue;                  } -                eos_net_send(EOS_NET_MTYPE_CELL, buf, len + 1); +                buf_len = _rv; +                eos_net_send(EOS_NET_MTYPE_CELL, buf, buf_len + 1);              } while (1);              eos_modem_give(); @@ -227,16 +276,26 @@ void eos_cell_sms_handler(unsigned char mtype, unsigned char *buffer, uint16_t b          case EOS_CELL_MTYPE_SMS_MSG: {              char b[4]; -            rv = sms_encode(buffer, buf_len); -            if (rv) return; +            char *pdu = _pdu_in; +            size_t pdu_size = sizeof(_pdu_in); +            size_t pdu_len; +            ssize_t _rv; + +            _rv = sms_encode(buffer, buf_len, pdu, pdu_size); +            if (_rv < 0) return; -            rv = snprintf(cmd, sizeof(cmd), "AT+CMGS=%d\r", pdu_len / 2); -            if ((rv < 0) || (rv >= sizeof(cmd))) return; +            pdu_len = _rv; +            if (pdu_size < pdu_len + 2) return; +            pdu[pdu_len] = CTRL_Z; +            pdu[pdu_len + 1] = '\0'; + +            rv = snprintf(at_cmd_buf, AT_SIZE_CMD_BUF, "AT+CMGS=%d\r", pdu_len / 2); +            if ((rv < 0) || (rv >= AT_SIZE_CMD_BUF)) return;              rv = eos_modem_take(1000);              if (rv) return; -            at_cmd(cmd); +            at_cmd(at_cmd_buf);              // wait for: '> ' (0d 0a 3e 20)              eos_modem_read(b, 4, 1000);              at_cmd(pdu); @@ -250,10 +309,16 @@ void eos_cell_sms_handler(unsigned char mtype, unsigned char *buffer, uint16_t b  }  static void sms_received_handler(char *urc, regmatch_t m[]) { +    char cmd[32];      unsigned char *buf; -    uint16_t len; +    uint16_t buf_len;      int ref, rv; +    char *pdu = _pdu_out; +    size_t pdu_size = sizeof(_pdu_out); +    size_t pdu_len; +    ssize_t _rv; +      sscanf(urc + m[1].rm_so, "%d", &ref);      rv = snprintf(cmd, sizeof(cmd), "AT+CMGR=%d\r", ref); @@ -264,7 +329,7 @@ static void sms_received_handler(char *urc, regmatch_t m[]) {      rv = at_expect("^\\+CMGR: [0-9],.*,[0-9]+$", "^ERROR", 1000);      if (rv) return; -    rv = eos_modem_readln(pdu, sizeof(pdu), 1000); +    rv = eos_modem_readln(pdu, pdu_size, 1000);      if (rv) return;      pdu_len = strlen(pdu); @@ -273,13 +338,14 @@ static void sms_received_handler(char *urc, regmatch_t m[]) {      buf = eos_net_alloc();      buf[0] = EOS_CELL_MTYPE_SMS | EOS_CELL_MTYPE_SMS_MSG; -    rv = sms_decode(buf + 1, &len); -    if (rv) { +    _rv = sms_decode(pdu, pdu_len, buf + 1, EOS_NET_SIZE_BUF - 1); +    if (_rv < 0) {          eos_net_free(buf);          return;      } -    eos_net_send(EOS_NET_MTYPE_CELL, buf, len + 1); +    buf_len = _rv; +    eos_net_send(EOS_NET_MTYPE_CELL, buf, buf_len + 1);  }  void eos_cell_sms_init(void) { | 
