예제 #1
0
static bool at_vrecv(const char *response, va_list args)
{
    char *_buffer = at._buffer;
    char *_recv_delimiter = at._recv_delimiter;
    char c;
    int  ret = 0;
vrecv_start:
    while (response[0]) {
        int i = 0;
        int offset = 0;

        while (response[i]) {
            if (memcmp(&response[i + 1 - at._recv_delim_size], _recv_delimiter,
                       at._recv_delim_size) == 0) {
                i++;
                break;
            } else if (response[i] == '%' && response[i + 1] != '%' &&
                       response[i + 1] != '*') {
                _buffer[offset++] = '%';
                _buffer[offset++] = '*';
                i++;
            } else {
                _buffer[offset++] = response[i++];
            }
        }

        _buffer[offset++] = '%';
        _buffer[offset++] = 'n';
        _buffer[offset++] = 0;

        int j = 0;

        while (true) {
            ret = at_getc(&c);
            if (ret != 0) {
                return false;
            }
            _buffer[offset + j++] = c;
            _buffer[offset + j] = 0;

            for (int k = 0; k < at._oobs_num; k++) {
                oob_t *oob = &(at._oobs[k]);
                if (j == oob->len &&
                    memcmp(oob->prefix, at._buffer + offset, oob->len) == 0) {
                    LOGD(MODULE_NAME, "AT! %s\r\n", oob->prefix);
                    oob->cb(oob->arg);

                    goto vrecv_start;
                }
            }

            int count = -1;
            sscanf(_buffer + offset, _buffer, &count);

            if (count == j) {
                LOGD(MODULE_NAME, "AT= %s\r\n", _buffer + offset);
                memcpy(_buffer, response, i);
                _buffer[i] = 0;
                vsscanf(_buffer + offset, _buffer, args);
                response += i;
                break;
            }

            if (j + 1 >= BUFFER_SIZE - offset ||
                strcmp(&_buffer[offset + j - at._recv_delim_size],
                       _recv_delimiter) == 0) {
                LOGD(MODULE_NAME, "AT< %s", _buffer + offset);
                j = 0;
            }
        }
    }

    return true;
}
예제 #2
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;
}
예제 #3
0
파일: atparser.c 프로젝트: wosayttn/aos
static void at_worker(void *arg)
{
    int        offset                  = 0;
    int        ret                     = 0;
    int        at_task_empty           = 0;
    int        at_task_reponse_begin   = 0;
    int        memcpy_size             = 0;
    int        rsp_prefix_len          = 0;
    int        rsp_success_postfix_len = 0;
    int        rsp_fail_postfix_len    = 0;
    char       c;
    at_task_t *tsk;
    char *     buf                 = NULL;
    char *     rsp_prefix          = NULL;
    char *     rsp_success_postfix = NULL;
    char *     rsp_fail_postfix    = NULL;
    oob_t *    oob                 = NULL;

    LOGD(MODULE_NAME, "at_work started.");

    buf = aos_malloc(RECV_BUFFER_SIZE);
    if (NULL == buf) {
        LOGE(MODULE_NAME, "AT worker fail to malloc ,task exist \r\n");
        aos_task_exit(0);
        return;
    }

    memset(buf, 0, RECV_BUFFER_SIZE);

    while (true) {
        // read from uart and store buf
        if (at._mode != ASYN) {
            aos_msleep(1);
        }

        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");
            continue;
        }
        buf[offset++] = c;
        buf[offset]   = 0;

        for (int k = 0; k < at._oobs_num; k++) {
            oob = &(at._oobs[k]);
            if (oob->reallen > 0 ||
                (offset >= strlen(oob->prefix) &&
                 memcmp(oob->prefix, buf + offset - strlen(oob->prefix),
                        strlen(oob->prefix)) == 0)) {
                LOGD(MODULE_NAME, "AT! %s\r\n", oob->prefix);
                if (oob->postfix == NULL) {
                    oob->cb(oob->arg, NULL, 0);
                    memset(buf + offset - strlen(oob->prefix), 0, offset);
                    offset -= strlen(oob->prefix);
                } else {
                    if (oob->reallen == 0) {
                        memset(oob->oobinputdata, 0, oob->maxlen);
                        memcpy(oob->oobinputdata, oob->prefix,
                               strlen(oob->prefix) - 1);
                        oob->reallen += strlen(oob->prefix) - 1;
                    }

                    if (oob->reallen < oob->maxlen) {
                        oob->oobinputdata[oob->reallen] = c;
                        oob->reallen++;
                        if ((oob->reallen >=
                             strlen(oob->prefix) + strlen(oob->postfix)) &&
                            (strncmp(oob->oobinputdata + oob->reallen -
                                       strlen(oob->postfix),
                                     oob->postfix,
                                     strlen(oob->postfix)) == 0)) {
                            /*recv postfix*/
                            oob->cb(oob->arg, oob->oobinputdata, oob->reallen);
                            memset(oob->oobinputdata, 0, oob->reallen);
                            oob->reallen = 0;
                            memset(buf, 0, offset);
                            offset = 0;
                        }
                    } else {
                        LOGE(MODULE_NAME,
                             "invalid oob %s input , for oversize %s \r\n",
                             oob->prefix, oob->oobinputdata);
                        memset(oob->oobinputdata, 0, oob->reallen);
                        oob->reallen = 0;
                        memset(buf, 0, offset);
                        offset = 0;
                    }
                    /*oob data maybe more than buf size */
                    if (offset > (RECV_BUFFER_SIZE - 2)) {
                        memset(buf, 0, offset);
                        offset = 0;
                    }
                }
                continue;
            }
        }

        aos_mutex_lock(&at.task_mutex, AOS_WAIT_FOREVER);
        at_task_empty = slist_empty(&at.task_l);

        if (!at_task_empty) {
            tsk = slist_first_entry(&at.task_l, at_task_t, next);
        }
        aos_mutex_unlock(&at.task_mutex);

        // if no task, continue recv
        if (at_task_empty) {
            LOGD(MODULE_NAME, "No task in queue");
            goto check_buffer;
        }

        if (NULL != tsk->rsp_prefix && 0 != tsk->rsp_prefix_len) {
            rsp_prefix     = tsk->rsp_prefix;
            rsp_prefix_len = tsk->rsp_prefix_len;
        } else {
            rsp_prefix     = at._default_recv_prefix;
            rsp_prefix_len = at._recv_prefix_len;
        }

        if (NULL != tsk->rsp_success_postfix &&
            0 != tsk->rsp_success_postfix_len) {
            rsp_success_postfix     = tsk->rsp_success_postfix;
            rsp_success_postfix_len = tsk->rsp_success_postfix_len;
        } else {
            rsp_success_postfix     = at._default_recv_success_postfix;
            rsp_success_postfix_len = at._recv_success_postfix_len;
        }

        if (NULL != tsk->rsp_fail_postfix && 0 != tsk->rsp_fail_postfix_len) {
            rsp_fail_postfix     = tsk->rsp_fail_postfix;
            rsp_fail_postfix_len = tsk->rsp_fail_postfix_len;
        } else {
            rsp_fail_postfix     = at._default_recv_fail_postfix;
            rsp_fail_postfix_len = at._recv_fail_postfix_len;
        }

        if (offset >= rsp_prefix_len && at_task_reponse_begin == 0 &&
            (strncmp(buf + offset - rsp_prefix_len, rsp_prefix,
                     rsp_prefix_len) == 0)) {
            at_task_reponse_begin = 1;
        }

        if (at_task_reponse_begin == 1) {
            if (tsk->rsp_offset < tsk->rsp_len) {
                tsk->rsp[tsk->rsp_offset] = c;
                tsk->rsp_offset++;

                if ((tsk->rsp_offset >= rsp_success_postfix_len &&
                     strncmp(
                       tsk->rsp + tsk->rsp_offset - rsp_success_postfix_len,
                       rsp_success_postfix, rsp_success_postfix_len) == 0) ||
                    (tsk->rsp_offset >= rsp_fail_postfix_len &&
                     strncmp(tsk->rsp + tsk->rsp_offset - rsp_fail_postfix_len,
                             rsp_fail_postfix, rsp_fail_postfix_len) == 0)) {
                    aos_sem_signal(&tsk->smpr);
                    at_task_reponse_begin = 0;
                    memset(buf, 0, offset);
                    offset = 0;
                }
            } else {
                memset(tsk->rsp, 0, tsk->rsp_len);
                strcpy(tsk->rsp, rsp_fail_postfix);
                aos_sem_signal(&tsk->smpr);
                at_task_reponse_begin = 0;
                memset(buf, 0, offset);
                offset = 0;
            }
        }
    check_buffer:
        // in case buffer is full
        if (offset > (RECV_BUFFER_SIZE - 2)) {
            printf("buffer full \r\n");
            memcpy_size = rsp_prefix_len > rsp_success_postfix_len
                            ? rsp_prefix_len
                            : rsp_success_postfix_len;
            memcpy_size = memcpy_size > rsp_fail_postfix_len
                            ? memcpy_size
                            : rsp_fail_postfix_len;
            memcpy(buf, buf + offset - memcpy_size, memcpy_size);
            memset(buf + memcpy_size, 0, offset - memcpy_size);
            offset = memcpy_size;
        }
    }

    return;
}