Esempio n. 1
0
static int telit2_socket_close(struct cellular *modem, int connid)
{
    at_set_timeout(modem->at, 150);
    at_command_simple(modem->at, "AT#SH=%d", connid);

    return 0;
}
Esempio n. 2
0
static int telit2_locate(struct cellular *modem, float *latitude, float *longitude, float *altitude)
{
    struct cellular_telit2 *priv = (struct cellular_telit2 *) modem;

    priv->locate_status = -1;
    at_set_timeout(modem->at, 150);
    cellular_command_simple_pdp(modem, "AT#AGPSSND");

    for (int i=0; i<TELIT2_LOCATE_TIMEOUT; i++) {
        sleep(1);
        if (priv->locate_status == 200) {
            *latitude = priv->latitude;
            *longitude = priv->longitude;
            *altitude = priv->altitude;
            return 0;
        }
        if (priv->locate_status != -1) {
            errno = ECONNABORTED;
            return -1;
        }
    }

    errno = ETIMEDOUT;
    return -1;
}
Esempio n. 3
0
static int telit2_ftp_close(struct cellular *modem)
{
    at_set_timeout(modem->at, 90);
    at_command_simple(modem->at, "AT#FTPCLOSE");

    return 0;
}
Esempio n. 4
0
/**
 * SIM800 IP configuration commands fail if the IP application is running,
 * even though the configuration settings are already right. The following
 * monkey dance is therefore needed.
 */
static int sim800_config(struct cellular *modem, const char *option, const char *value, int attempts)
{
    at_set_timeout(modem->at, 10);

    for (int i=0; i<attempts; i++) {
        /* Blindly try to set the configuration option. */
        at_command(modem->at, "AT+%s=%s", option, value);

        /* Query the setting status. */
        const char *response = at_command(modem->at, "AT+%s?", option);
        /* Bail out on timeouts. */
        if (response == NULL)
            return -1;

        /* Check if the setting has the correct value. */
        char expected[16];
        if (snprintf(expected, sizeof(expected), "+%s: %s", option, value) >= (int) sizeof(expected)) {
            return -1;
        }
        if (!strcmp(response, expected))
            return 0;

        vTaskDelay(pdMS_TO_TICKS(1000));
    }

    return -1;
}
Esempio n. 5
0
static int telit2_pdp_close(struct cellular *modem)
{
    at_set_timeout(modem->at, 150);
    at_command_simple(modem->at, "AT#SGACT=1,0");

    return 0;
}
Esempio n. 6
0
static int telit2_socket_waitack(struct cellular *modem, int connid)
{
    const char *response;

    at_set_timeout(modem->at, 5);
    for (int i=0; i<TELIT2_WAITACK_TIMEOUT; i++) {
        /* Read number of bytes waiting. */
        int ack_waiting;
        response = at_command(modem->at, "AT#SI=%d", connid);
        at_simple_scanf(response, "#SI: %*d,%*d,%*d,%*d,%d", &ack_waiting);

        /* ack_waiting is meaningless if socket is not connected. Check this. */
        int socket_status;
        response = at_command(modem->at, "AT#SS=%d", connid);
        at_simple_scanf(response, "#SS: %*d,%d", &socket_status);
        if (socket_status == 0) {
            errno = ECONNRESET;
            return -1;
        }

        /* Return if all bytes were acknowledged. */
        if (ack_waiting == 0)
            return 0;

        sleep(1);
    }

    errno = ETIMEDOUT;
    return -1;
}
Esempio n. 7
0
static ssize_t sim800_socket_send(struct cellular *modem, int connid, const void *buffer, size_t amount, int flags)
{
    struct cellular_sim800 *priv = (struct cellular_sim800 *) modem;
    (void) flags;
    if(connid == SIM800_NSOCKETS) {
      if(priv->spp_status != SIM800_SOCKET_STATUS_CONNECTED) {
        return -1;
      }
      if(amount > 1024) {
        return -1;
      }
      /* Request transmission. */
      at_send_raw(modem->at, buffer, amount);
      return amount;
    } else if(connid < SIM800_NSOCKETS) {
      if(priv->socket_status[connid] != SIM800_SOCKET_STATUS_CONNECTED) {
        return -1;
      }
      amount = amount > 1460 ? 1460 : amount;
      /* Request transmission. */
      at_set_timeout(modem->at, SET_TIMEOUT);
      at_expect_dataprompt(modem->at);
      at_command_simple(modem->at, "AT+CIPSEND=%d,%zu", connid, amount);

      /* Send raw data. */
      at_set_command_scanner(modem->at, scanner_cipsend);
      at_command_raw_simple(modem->at, buffer, amount);
    } else {
      return 0;
    }

    return amount;
}
Esempio n. 8
0
static int sim800_socket_connect(struct cellular *modem, int connid, const char *host, uint16_t port)
{
    struct cellular_sim800 *priv = (struct cellular_sim800 *) modem;

    if(connid == SIM800_NSOCKETS) {
      return !(SIM800_SOCKET_STATUS_CONNECTED == priv->spp_status);
    } else if(connid < SIM800_NSOCKETS) {
      /* Send connection request. */
      at_set_timeout(modem->at, SET_TIMEOUT);
      priv->socket_status[connid] = SIM800_SOCKET_STATUS_UNKNOWN;
      cellular_command_simple_pdp(modem, "AT+CIPSTART=%d,TCP,\"%s\",%d", connid, host, port);

      /* Wait for socket status URC. */
      for (int i=0; i<SIM800_CONNECT_TIMEOUT; i++) {
          if (priv->socket_status[connid] == SIM800_SOCKET_STATUS_CONNECTED) {
              return 0;
          } else if (priv->socket_status[connid] == SIM800_SOCKET_STATUS_ERROR) {
              return -1;
          }
          vTaskDelay(pdMS_TO_TICKS(1000));
      }
    }

    return -1;
}
Esempio n. 9
0
static int sim800_pdp_open(struct cellular *modem, const char *apn)
{
    at_set_timeout(modem->at, SET_TIMEOUT);

    /* Configure and open context for FTP/HTTP applications. */
    at_command_simple(modem->at, "AT+SAPBR=3,1,APN,\"%s\"", apn);
    at_command(modem->at, "AT+SAPBR=1,1");

    /* Skip the configuration if context is already open. */
    if (sim800_ipstatus(modem) == 0)
        return 0;

    /* Commands below don't check the response. This is intentional; instead
     * of trying to stay in sync with the GPRS state machine we blindly issue
     * the command sequence needed to transition through all the states and
     * reach IP STATUS. See SIM800 Series_TCPIP_Application Note_V1.01.pdf for
     * the GPRS states documentation. */

    /* Configure context for TCP/IP applications. */
    at_command(modem->at, "AT+CSTT=\"%s\"", apn);
    /* Establish context. */
    at_command(modem->at, "AT+CIICR");
    /* Read local IP address. Switches modem to IP STATUS state. */
    at_set_command_scanner(modem->at, scanner_cifsr);
    at_command(modem->at, "AT+CIFSR");

    return sim800_ipstatus(modem);
}
Esempio n. 10
0
static int telit2_ftp_get(struct cellular *modem, const char *filename)
{
    at_set_timeout(modem->at, 90);
    at_command_simple(modem->at, "AT#FTPGETPKT=\"%s\",0", filename);

    return 0;
}
Esempio n. 11
0
static int sim800_pdp_close(struct cellular *modem)
{
    at_set_timeout(modem->at, SET_TIMEOUT);
    at_set_command_scanner(modem->at, scanner_cipshut);
    at_command_simple(modem->at, "AT+CIPSHUT");

    return 0;
}
Esempio n. 12
0
static int telit2_pdp_open(struct cellular *modem, const char *apn)
{
    at_set_timeout(modem->at, 5);
    at_command_simple(modem->at, "AT+CGDCONT=1,IP,\"%s\"", apn);

    at_set_timeout(modem->at, 150);
    const char *response = at_command(modem->at, "AT#SGACT=1,1");

    if (response == NULL)
        return -1;

    if (!strcmp(response, "+CME ERROR: context already activated"))
        return 0;

    int ip[4];
    at_simple_scanf(response, "#SGACT: %d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]);

    return 0;
}
Esempio n. 13
0
static int telit2_socket_connect(struct cellular *modem, int connid, const char *host, uint16_t port)
{
    /* Reset socket configuration to default. */
    at_set_timeout(modem->at, 5);
    at_command_simple(modem->at, "AT#SCFGEXT=%d,0,0,0,0,0", connid);
    at_command_simple(modem->at, "AT#SCFGEXT2=%d,0,0,0,0,0", connid);

    /* Open connection. */
    cellular_command_simple_pdp(modem, "AT#SD=%d,0,%d,%s,0,0,1", connid, port, host);

    return 0;
}
Esempio n. 14
0
int sim800_socket_close(struct cellular *modem, int connid)
{
    struct cellular_sim800 *priv = (struct cellular_sim800 *) modem;

    if(connid == SIM800_NSOCKETS) {
      at_command_simple(modem->at, "AT+BTDISCONN=%d", priv->spp_connid);
    } else if(connid < SIM800_NSOCKETS) {
      at_set_timeout(modem->at, SET_TIMEOUT);
      at_set_command_scanner(modem->at, scanner_cipclose);
      at_command_simple(modem->at, "AT+CIPCLOSE=%d", connid);
    }
    return 0;
}
Esempio n. 15
0
static int sim800_attach(struct cellular *modem)
{
    at_set_callbacks(modem->at, &sim800_callbacks, (void *) modem);

    at_set_timeout(modem->at, 2);

    /* Perform autobauding. */
    for (int i=0; i<SIM800_AUTOBAUD_ATTEMPTS; i++) {
        const char *response = at_command(modem->at, "AT");
        if (response != NULL)
            /* Modem replied. Good. */
            break;
    }

    /* Disable local echo. */
    at_command(modem->at, "ATE0");

    /* Disable local echo again; make sure it was disabled successfully. */
    at_command_simple(modem->at, "ATE0");

    /* Initialize modem. */
    static const char *const init_strings[] = {
//        "AT+IPR=0",                     /* Enable autobauding if not already enabled. */
        "AT+IFC=0,0",                   /* Disable hardware flow control. */
        "AT+CMEE=2",                    /* Enable extended error reporting. */
        "AT+CLTS=0",                    /* Don't sync RTC with network time, it's broken. */
        "AT+CIURC=0",                   /* Disable "Call Ready" URC. */
        "AT&W0",                        /* Save configuration. */
        "AT+BTSPPCFG=\"TT\",1",
        "AT+BTPAIRCFG=0",
        "AT+BTSPPGET=1",
        "AT+BTPOWER=1",
        NULL
    };
    for (const char *const *command=init_strings; *command; command++)
        at_command_simple(modem->at, "%s", *command);

    /* Configure IP application. */

//    /* Switch to multiple connections mode; it's less buggy. */
//    if (sim800_config(modem, "CIPMUX", "1", SIM800_CIPCFG_RETRIES) != 0)
//        return -1;
//    /* Receive data manually. */
//    if (sim800_config(modem, "CIPRXGET", "1", SIM800_CIPCFG_RETRIES) != 0)
//        return -1;
//    /* Enable quick send mode. */
//    if (sim800_config(modem, "CIPQSEND", "1", SIM800_CIPCFG_RETRIES) != 0)
//        return -1;

    return 0;
}
Esempio n. 16
0
static ssize_t telit2_socket_send(struct cellular *modem, int connid, const void *buffer, size_t amount, int flags)
{
    (void) flags;

    /* Request transmission. */
    at_set_timeout(modem->at, 150);
    at_expect_dataprompt(modem->at);
    at_command_simple(modem->at, "AT#SSENDEXT=%d,%zu", connid, amount);

    /* Send raw data. */
    at_command_raw_simple(modem->at, buffer, amount);

    return amount;
}
Esempio n. 17
0
static int telit2_op_iccid(struct cellular *modem, char *buf, size_t len)
{
    char fmt[24];
    if (snprintf(fmt, sizeof(fmt), "#CCID: %%[0-9]%ds", (int) len) >= (int) sizeof(fmt)) {
        errno = ENOSPC;
        return -1;
    }

    at_set_timeout(modem->at, 5);
    const char *response = at_command(modem->at, "AT#CCID");
    at_simple_scanf(response, fmt, buf);
    buf[len-1] = '\0';

    return 0;
}
Esempio n. 18
0
static ssize_t telit2_socket_recv(struct cellular *modem, int connid, void *buffer, size_t length, int flags)
{
    (void) flags;

    int cnt = 0;
    while (cnt < (int) length) {
        int chunk = (int) length - cnt;
        /* Limit read size to avoid overflowing AT response buffer. */
        if (chunk > 128)
            chunk = 128;

        /* Perform the read. */
        at_set_timeout(modem->at, 150);
        at_set_command_scanner(modem->at, scanner_srecv);
        const char *response = at_command(modem->at, "AT#SRECV=%d,%d", connid, chunk);
        if (response == NULL)
            return -1;

        /* Find the header line. */
        int bytes;
        at_simple_scanf(response, "#SRECV: %*d,%d", &bytes);

        /* Bail out if we're out of data. Message is misleading. */
        /* FIXME: We should maybe block until we receive something? */
        if (!strcmp(response, "+CME ERROR: activation failed"))
            break;

        /* Locate the payload. */
        const char *data = strchr(response, '\n');
        if (data == NULL) {
            errno = EPROTO;
            return -1;
        }
        data += 1;

        /* Copy payload to result buffer. */
        memcpy((char *)buffer + cnt, data, bytes);
        cnt += bytes;
    }

    return cnt;
}
Esempio n. 19
0
static int sim800_ftp_getdata(struct cellular *modem, char *buffer, size_t length)
{
    struct cellular_sim800 *priv = (struct cellular_sim800 *) modem;

    int retries = 0;
retry:
    at_set_timeout(modem->at, SET_TIMEOUT);
    at_set_command_scanner(modem->at, scanner_ftpget2);
    const char *response = at_command(modem->at, "AT+FTPGET=2,%zu", length);

    if (response == NULL)
        return -1;

    int cnflength;
    if (sscanf(response, "+FTPGET: 2,%d", &cnflength) == 1) {
        /* Zero means no data is available. Wait for it. */
        if (cnflength == 0) {
            /* Bail out on timeout. */
            if (++retries >= SIM800_FTP_TIMEOUT) {
                return -1;
            }
            vTaskDelay(pdMS_TO_TICKS(1000));
            goto retry;
        }

        /* Locate the payload. */
        const char *data = strchr(response, '\n');
        if (data == NULL) {
            return -1;
        }
        data += 1;

        /* Copy payload to result buffer. */
        memcpy((char *)buffer, data, cnflength);
        return cnflength;
    } else if (priv->ftpget1_status == 0) {
        /* Transfer finished. */
        return 0;
    } else {
        return -1;
    }
}
Esempio n. 20
0
static int at_init(uart_dev_t *u, const char *recv_delimiter,
                    const char *send_delimiter, int timeout)
{
    if (!u || !recv_delimiter || !send_delimiter || (timeout < 0)) {
        LOGE(MODULE_NAME, "%s: invalid argument", __func__);
        return -1;
    }

    if (at_init_uart(u) != 0) return -1;
    at_set_timeout(timeout);
    at_set_recv_delimiter(recv_delimiter);
    at_set_send_delimiter(send_delimiter);
    if (at._mode == ASYN) {
        at_init_mutex();
        slist_init(&at.task_l);
        aos_task_new("at_worker", at_worker, NULL, 4096);
    }

    return 0;
}
Esempio n. 21
0
static int telit2_attach(struct cellular *modem)
{
    at_set_callbacks(modem->at, &telit2_callbacks, (void *) modem);

    at_set_timeout(modem->at, 1);
    at_command(modem->at, "AT");        /* Aid autobauding. Always a good idea. */
    at_command(modem->at, "ATE0");      /* Disable local echo. */

    /* Initialize modem. */
    static const char *const init_strings[] = {
        "AT&K0",                        /* Disable hardware flow control. */
        "AT#SELINT=2",                  /* Set Telit module compatibility level. */
        "AT+CMEE=2",                    /* Enable extended error reporting. */
        NULL
    };
    for (const char *const *command=init_strings; *command; command++)
        at_command_simple(modem->at, "%s", *command);

    return 0;
}
Esempio n. 22
0
/**
 * Retrieve AT+CIPSTATUS state.
 *
 * @returns Zero if context is open, -1 and sets errno otherwise.
 */
static int sim800_ipstatus(struct cellular *modem)
{
    at_set_timeout(modem->at, 10);
    at_set_command_scanner(modem->at, scanner_cipstatus);
    const char *response = at_command(modem->at, "AT+CIPSTATUS");

    if (response == NULL)
        return -1;

    const char *state = strstr(response, "STATE: ");
    if (!state) {
        return -1;
    }
    state += strlen("STATE: ");
    if (!strncmp(state, "IP STATUS", strlen("IP STATUS")))
        return 0;
    if (!strncmp(state, "IP PROCESSING", strlen("IP PROCESSING")))
        return 0;

    return -1;
}
Esempio n. 23
0
static int sim800_socket_waitack(struct cellular *modem, int connid)
{
    const char *response;
    if(connid == SIM800_NSOCKETS) {
      return 0;
    } else if(connid < SIM800_NSOCKETS) {
      at_set_timeout(modem->at, 5);
      for (int i=0; i<SIM800_WAITACK_TIMEOUT; i++) {
          /* Read number of bytes waiting. */
          int nacklen;
          response = at_command(modem->at, "AT+CIPACK=%d", connid);
          at_simple_scanf(response, "+CIPACK: %*d,%*d,%d", &nacklen);

          /* Return if all bytes were acknowledged. */
          if (nacklen == 0)
              return 0;

          vTaskDelay(pdMS_TO_TICKS(1000));
      }
    }
    return -1;
}
Esempio n. 24
0
int main(int argc, char *argv[])
{
    assert(argc-1 == 1);
    const char *devpath = argv[1];

    printf("allocating channel...\n");
    struct at *at = at_alloc_unix(devpath, B115200);

    printf("opening port...\n");
    assert(at_open(at) == 0);

    printf("attaching callbacks\n");
    at_set_callbacks(at, &generic_modem_callbacks, NULL);

    const char *commands[] = {
        "AT",
        "ATE0",
        "AT+CGMR",
        "AT+CGSN",
        "AT+CCID",
        "AT+CMEE=0",
        "AT+BLAH",
        "AT+CMEE=2",
        "AT+BLAH",
        NULL
    };

    printf("sending commands...\n");
    at_set_timeout(at, 10);
    for (const char **command=commands; *command; command++) {
        const char *result = at_command(at, *command);
        printf("%s => %s\n", *command, result ? result : strerror(errno));
    }

    printf("freeing resources...\n");
    at_free(at);

    return 0;
}
Esempio n. 25
0
static int telit2_op_clock_gettime(struct cellular *modem, struct timespec *ts)
{
    struct tm tm;
    int offset;

    at_set_timeout(modem->at, 1);
    const char *response = at_command(modem->at, "AT+CCLK?");
    memset(&tm, 0, sizeof(struct tm));
    at_simple_scanf(response, "+CCLK: \"%d/%d/%d,%d:%d:%d%d\"",
            &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
            &tm.tm_hour, &tm.tm_min, &tm.tm_sec,
            &offset);

    /* Most modems report some starting date way in the past when they have
     * no date/time estimation. */
    if (tm.tm_year < 14) {
        errno = EINVAL;
        return 1;
    }

    /* Adjust values and perform conversion. */
    tm.tm_year += 2000 - 1900;
    tm.tm_mon -= 1;
    time_t unix_time = timegm(&tm);
    if (unix_time == -1) {
        errno = EINVAL;
        return -1;
    }

    /* Telit modems return local date/time instead of UTC (as defined in 3GPP
     * 27.007). Remove the timezone shift. */
    unix_time -= 15*60*offset;

    /* All good. Return the result. */
    ts->tv_sec = unix_time;
    ts->tv_nsec = 0;
    return 0;
}
Esempio n. 26
0
static void at_worker(void *arg)
{
    char buf[RECV_BUFFER_SIZE] = {0};
    int  offset = 0;
    int  ret = 0;
    int at_task_empty = 0;
    char c;
    at_task_t *tsk;

    LOGD(MODULE_NAME, "at_work started.");
    at_set_timeout(500);

    while (true) {
        // read from uart and store buf
        ret = at_getc(&c);
        if (ret != 0) {
            continue;
        }

        if (offset + 1 >= RECV_BUFFER_SIZE) {
            LOGE(MODULE_NAME, "Fatal error, no one is handling AT uart");
            assert(0);
        }
        buf[offset++] = c;
        buf[offset] = 0;

        // check oob first
        for (int k = 0; k < at._oobs_num; k++) {
            oob_t *oob = &(at._oobs[k]);
            if (offset == oob->len &&
                memcmp(oob->prefix, buf, oob->len) == 0) {
                LOGD(MODULE_NAME, "AT! %s\r\n", oob->prefix);
                // oob.cb is to consume uart data if necessary
                oob->cb(oob->arg);
                // start a new round after oob cb
                memset(buf, 0, offset);
                offset = 0;
                continue;
            }
        }

        at_task_empty = slist_empty(&at.task_l);
        // if no task, continue recv
        if (at_task_empty) {
            LOGD(MODULE_NAME, "No task in queue");
            goto check_buffer;
        }

        // otherwise, get the first task in list
        tsk = slist_first_entry(&at.task_l, at_task_t, next);

        // check if a rsp end matched
        if (strcmp(buf + offset - strlen(RECV_STATUS_OK), RECV_STATUS_OK) == 0 ||
            strcmp(buf + offset - strlen(RECV_STATUS_ERROR), RECV_STATUS_ERROR) == 0) {
            LOGD(MODULE_NAME, "AT cammand rsp matched");
            LOGD(MODULE_NAME, "at task is going to be waked up: %d, smpr: %d",
                 (uint32_t)tsk, (uint32_t)&tsk->smpr);
            memcpy(tsk->rsp + tsk->rsp_offset, buf, offset);
            tsk->rsp_offset += offset;
            if (aos_sem_is_valid(&tsk->smpr)) {
                LOGD(MODULE_NAME, "at task is going to be waked up: %d, smpr: %d", 
                  (uint32_t)tsk, (uint32_t)&tsk->smpr);
                aos_sem_signal(&tsk->smpr); // wakeup send task
            }
            // start a new round after a match hit
            goto check_buffer;
        }

        if ((offset >= (RECV_BUFFER_SIZE - 2)) ||
            (strcmp(&buf[offset - at._recv_delim_size], at._recv_delimiter) == 0)) {
            if (tsk->rsp_offset + offset < tsk->rsp_len){
                memcpy(tsk->rsp + tsk->rsp_offset, buf, offset);
                tsk->rsp_offset += offset;
            }else{
                LOGE(MODULE_NAME, "invalid input for task reponse totlen is %d,tsk->rsp_offset is %d ,offset is %d\n", 
                    tsk->rsp_len, tsk->rsp_offset, offset);
                memset(tsk->rsp, 0, tsk->rsp_len);
                strcpy(tsk->rsp, RECV_STATUS_ERROR);
                if (aos_sem_is_valid(&tsk->smpr)) {
                    LOGD(MODULE_NAME, "at task is going to be waked up: %d, smpr: %d", 
                        (uint32_t)tsk, (uint32_t)&tsk->smpr);
                    aos_sem_signal(&tsk->smpr); // wakeup send task
                }
            }
            LOGD(MODULE_NAME, "Save buffer to task rsp, offset: %d tsk->rsp_offset = %d task->rsp_len is %d\n", 
                 offset, tsk->rsp_offset, tsk->rsp_len);
        }

check_buffer:
        // in case buffer is full
        if ((offset >= (RECV_BUFFER_SIZE - 2)) ||
            (strcmp(&buf[offset - at._recv_delim_size], at._recv_delimiter) == 0)) {
            LOGD(MODULE_NAME, "buffer full or new line hit, offset: %d, buf: %s", offset, buf);
            memset(buf, 0, offset);
            offset = 0;
        }
    }

    // never reach here
    return;
}
Esempio n. 27
0
static ssize_t sim800_socket_recv(struct cellular *modem, int connid, void *buffer, size_t length, int flags)
{
    struct cellular_sim800 *priv = (struct cellular_sim800 *) modem;
    (void) flags;

    int cnt = 0;
    // TODO its dumb and exceptions should be handled in other right way
    // FIXME: It has to be changed. Leave for now
    if(connid == SIM800_NSOCKETS) {
      if(priv->spp_status != SIM800_SOCKET_STATUS_CONNECTED) {
        return -1;
      }

      /* Copy payload to result buffer. */
      cnt = strlen(spp_recv_buf);
      if(cnt) {
          memcpy(buffer, spp_recv_buf, cnt);
          *(((char*)buffer) + cnt) = '\0';
          spp_recv_buf[0] = '\0';
      }
    }
    else if(connid < SIM800_NSOCKETS) {
      if(priv->socket_status[connid] != SIM800_SOCKET_STATUS_CONNECTED) {
        return -1;
      }
      char tries = 4;
      while ( (cnt < (int) length) && tries-- ){
          int chunk = (int) length - cnt;
          /* Limit read size to avoid overflowing AT response buffer. */
          chunk = chunk > 480 ? 480 : chunk;

          /* Perform the read. */
          at_set_timeout(modem->at, SET_TIMEOUT);
          at_set_command_scanner(modem->at, scanner_ciprxget);
          const char *response = at_command(modem->at, "AT+CIPRXGET=2,%d,%d", connid, chunk);
          if (response == NULL)
              return -1;

          /* Find the header line. */
          int requested, confirmed;
          // TODO:
          // 1. connid is not checked
          // 2. there is possible a bug here. if not all data are ready (confirmed < requested)
          // then wierd things can happen. see memcpy
          // requested should be equal to chunk
          // confirmed is that what can be read
          at_simple_scanf(response, "+CIPRXGET: 2,%*d,%d,%d", &requested, &confirmed);

          /* Bail out if we're out of data. */
          /* FIXME: We should maybe block until we receive something? */
          if (confirmed == 0)
              break;

          /* Locate the payload. */
          /* TODO: what if no \n is in input stream?
           * should use strnchr at least */
          const char *data = strchr(response, '\n');
          if (data++ == NULL) {
              return -1;
          }

          /* Copy payload to result buffer. */
          memcpy((char *)buffer + cnt, data, confirmed);
          cnt += confirmed;
      }
    }

    return cnt;
}
Esempio n. 28
0
static int at_init(const char *recv_prefix, const char *recv_success_postfix,
                   const char *recv_fail_postfix, const char *send_delimiter,
                   int timeout)
{
    if (!recv_prefix || !recv_success_postfix || !recv_fail_postfix ||
        !send_delimiter || (timeout < 0)) {
        LOGE(MODULE_NAME, "%s: invalid argument", __func__);
        return -1;
    }

    if (inited == 1) {
        LOGI(MODULE_NAME, "have already inited ,it will init again\r\n");
        inited = 0;
    }

    if (at_init_uart() != 0) {
        LOGE(MODULE_NAME, "at uart init fail \r\n");
        return -1;
    }

    memset(at._oobs, 0, sizeof(oob_t) * OOB_MAX);

    at_set_timeout(timeout);
    at_set_recv_delimiter(recv_prefix, recv_success_postfix, recv_fail_postfix);
    at_set_send_delimiter(send_delimiter);

    LOGD(MODULE_NAME,
         "at worker rcv prefix is %s success postfix is %s fail postfix is %s "
         "\r\n",
         recv_prefix, recv_success_postfix, recv_fail_postfix);
    if (at_init_at_mutex() != 0) {
        LOGE(MODULE_NAME, "at uart mutex init fail \r\n");
        return -1;
    }

    if (at_init_task_mutex() != 0) {
        at_uinit_at_mutex();
        LOGE(MODULE_NAME, "at mutex init fail \r\n");
        return -1;
    }

    slist_init(&at.task_l);

    if (at_worker_uart_send_mutex_init() != 0) {
        at_uinit_at_mutex();
        at_uinit_task_mutex();
        LOGE(MODULE_NAME, "fail to creat at worker sem\r\n");
    }

    if (aos_task_new("at_worker", at_worker, NULL, at_worker_stacksize)) {
        at_uinit_at_mutex();
        at_uinit_task_mutex();
        at_worker_uart_send_mutex_uinit();
        LOGE(MODULE_NAME, "fail to creat at task\r\n");
        return -1;
    }

    inited = 1;

    return 0;
}
Esempio n. 29
0
static int telit2_ftp_getdata(struct cellular *modem, char *buffer, size_t length)
{
    /* FIXME: This function's flow is really ugly. */
    int retries = 0;
retry:
    at_set_timeout(modem->at, 150);
    at_set_command_scanner(modem->at, scanner_ftprecv);
    const char *response = at_command(modem->at, "AT#FTPRECV=%zu", length);

    if (response == NULL)
        return -1;

    int bytes;
    if (sscanf(response, "#FTPRECV: %d", &bytes) == 1) {
        /* Zero means no data is available. Wait for it. */
        if (bytes == 0) {
            /* Bail out on timeout. */
            if (++retries >= TELIT2_FTP_TIMEOUT) {
                errno = ETIMEDOUT;
                return -1;
            }
            sleep(1);
            goto retry;
        }

        /* Locate the payload. */
        const char *data = strchr(response, '\n');
        if (data == NULL) {
            errno = EPROTO;
            return -1;
        }
        data += 1;

        /* Copy payload to result buffer. */
        memcpy(buffer, data, bytes);
        return bytes;
    }

    /* Error or EOF? */
    int eof;
    response = at_command(modem->at, "AT#FTPGETPKT?");
    /* Expected response: #FTPGETPKT: <remotefile>,<viewMode>,<eof> */
#if 0
    /* The %[] specifier is not supported on some embedded systems. */
    at_simple_scanf(response, "#FTPGETPKT: %*[^,],%*d,%d", &eof);
#else
    /* Parse manually. */
    if (response == NULL)
        return -1;
    errno = EPROTO;
    /* Check the initial part of the response. */
    if (strncmp(response, "#FTPGETPKT: ", 12))
        return -1;
    /* Skip the filename. */
    response = strchr(response, ',');
    if (response == NULL)
        return -1;
    response++;
    at_simple_scanf(response, "%*d,%d", &eof);
#endif

    if (eof == 1)
        return 0;

    return -1;
}