Example #1
0
static const char *readline(void)
{
    ssize_t count;

    char *p_read = NULL;
    char *p_eol = NULL;
    char *ret = NULL;

    struct atcontext *ac = getAtContext();
    read(ac->fd,NULL,0);

    /* This is a little odd. I use *s_ATBufferCur == 0 to mean
     * "buffer consumed completely". If it points to a character,
     * then the buffer continues until a \0.
     */
    if (*ac->ATBufferCur == '\0') {
        /* Empty buffer. */
        ac->ATBufferCur = ac->ATBuffer;
        *ac->ATBufferCur = '\0';
        p_read = ac->ATBuffer;
    } else {   /* *s_ATBufferCur != '\0' */
        /* There's data in the buffer from the last read. */

        /* skip over leading newlines */
        while (*ac->ATBufferCur == '\r' || *ac->ATBufferCur == '\n')
            ac->ATBufferCur++;

        p_eol = findNextEOL(ac->ATBufferCur);

        if (p_eol == NULL) {
            /* A partial line. Move it up and prepare to read more. */
            size_t len;

            len = strlen(ac->ATBufferCur);

            memmove(ac->ATBuffer, ac->ATBufferCur, len + 1);
            p_read = ac->ATBuffer + len;
            ac->ATBufferCur = ac->ATBuffer;
        }
        /* Otherwise, (p_eol !- NULL) there is a complete line 
           that will be returned from the while () loop below. */
    }

    while (p_eol == NULL) {
        int err;
        struct pollfd pfds[2];

        /* This condition should be synchronized with the read function call
         * size argument below.
         */
        if (0 >= MAX_AT_RESPONSE - (p_read - ac->ATBuffer) - 2) {
            ALOGE("%s() ERROR: Input line exceeded buffer", __func__);
            /* Ditch buffer and start over again. */
            ac->ATBufferCur = ac->ATBuffer;
            *ac->ATBufferCur = '\0';
            p_read = ac->ATBuffer;
        }

        /* If our fd is invalid, we are probably closed. Return. */
        if (ac->fd < 0)
            return NULL;

        pfds[0].fd = ac->fd;
        pfds[0].events = POLLIN | POLLERR;

        pfds[1].fd = ac->readerCmdFds[0];
        pfds[1].events = POLLIN;

        err = poll(pfds, 2, -1);

        if (err < 0) {
            ALOGE("%s() poll: error: %s", __func__, strerror(errno));
            return NULL;
        }

        if (pfds[1].revents & POLLIN) {
            char buf[10];

            /* Just drain it. We don't care, this is just for waking up. */
            read(pfds[1].fd, &buf, 1);
            continue;
        }

        if (pfds[0].revents & POLLERR) {
            ALOGE("%s() POLLERR event! Returning...", __func__);
            return NULL;
        }

        if (!(pfds[0].revents & POLLIN))
            continue;

        do
            /* The size argument should be synchronized to the ditch buffer
             * condition above.
             */
            count = read(ac->fd, p_read,
                         MAX_AT_RESPONSE - (p_read - ac->ATBuffer) - 2);

        while (count < 0 && errno == EINTR);

        if (count > 0) {
            AT_DUMP( "<< ", p_read, count );
            ac->readCount += count;

            /* Implementation requires extra EOS or EOL to get it right if
             * there are no trailing newlines in the read buffer. Adding extra
             * EOS does not harm even if there actually were trailing EOLs.
             */
            p_read[count] = '\0';
            p_read[count+1] = '\0';

            /* Skip over leading newlines. */
            while (*ac->ATBufferCur == '\r' || *ac->ATBufferCur == '\n')
                ac->ATBufferCur++;

            p_eol = findNextEOL(ac->ATBufferCur);
            p_read += count;
        } else if (count <= 0) {
            /* Read error encountered or EOF reached. */
            if (count == 0)
                ALOGD("%s() atchannel: EOF reached.", __func__);
            else
                ALOGD("%s() atchannel: read error %s", __func__, strerror(errno));

            return NULL;
        }
    }

    /* A full line in the buffer. Place a \0 over the \r and return. */

    ret = ac->ATBufferCur;
    *p_eol = '\0';

    /* The extra EOS added after read takes care of the case when there is no
     * valid data after p_eol.
     */
    ac->ATBufferCur = p_eol + 1;     /* This will always be <= p_read,    
                                        and there will be a \0 at *p_read. */

    ALOGI("AT(%d)< %s", ac->fd, ret);
    return ret;
}
Example #2
0
static const char *readline()
{
    ssize_t count;

    char *p_read = NULL;
    char *p_eol = NULL;
    char *ret;

    /* this is a little odd. I use *s_ATBufferCur == 0 to
     * mean "buffer consumed completely". If it points to a character, than
     * the buffer continues until a \0
     */
    if (*s_ATBufferCur == '\0') {
        /* empty buffer */
        s_ATBufferCur = s_ATBuffer;
        *s_ATBufferCur = '\0';
        p_read = s_ATBuffer;
    } else {   /* *s_ATBufferCur != '\0' */
        /* there's data in the buffer from the last read */

        // skip over leading newlines
        while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
            s_ATBufferCur++;

        p_eol = findNextEOL(s_ATBufferCur);

        if (p_eol == NULL) {
            /* a partial line. move it up and prepare to read more */
            size_t len;

            len = strlen(s_ATBufferCur);

            memmove(s_ATBuffer, s_ATBufferCur, len + 1);
            p_read = s_ATBuffer + len;
            s_ATBufferCur = s_ATBuffer;
        }
        /* Otherwise, (p_eol !- NULL) there is a complete line  */
        /* that will be returned the while () loop below        */
    }

    while (p_eol == NULL) {
        if (0 == MAX_AT_RESPONSE - (p_read - s_ATBuffer)) {
            LOGE("ERROR: Input line exceeded buffer\n");
            /* ditch buffer and start over again */
            s_ATBufferCur = s_ATBuffer;
            *s_ATBufferCur = '\0';
            p_read = s_ATBuffer;
        }

        do {
            count = read(s_fd, p_read,
                         MAX_AT_RESPONSE - (p_read - s_ATBuffer));
        } while (count < 0 && errno == EINTR);

        if (count > 0) {
            AT_DUMP( "<< ", p_read, count );
            s_readCount += count;

            p_read[count] = '\0';

            // skip over leading newlines
            while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
                s_ATBufferCur++;

            p_eol = findNextEOL(s_ATBufferCur);
            p_read += count;
        } else if (count <= 0) {
            /* read error encountered or EOF reached */
            if(count == 0) {
                LOGD("atchannel: EOF reached");
            } else {
                LOGD("atchannel: read error %s", strerror(errno));
            }
            return NULL;
        }
    }

    /* a full line in the buffer. Place a \0 over the \r and return */

    ret = s_ATBufferCur;
    *p_eol = '\0';
    s_ATBufferCur = p_eol + 1; /* this will always be <= p_read,    */
    /* and there will be a \0 at *p_read */

    LOGD("AT< %s\n", ret);
    return ret;
}
Example #3
0
static const char *readline(void)
{
    ssize_t count;

    char *p_read = NULL;
    char *p_eol = NULL;
    char *ret = NULL;

    struct atcontext *context = get_at_context();

    ENTER;

    read(context->fd,NULL,0);

    /* This is a little odd. I use *s_ATBufferCur == 0 to mean
     * "buffer consumed completely". If it points to a character,
     * then the buffer continues until a \0.
     */
    if (*context->ATBufferCur == '\0') {
        /* Empty buffer. */
        context->ATBufferCur = context->ATBuffer;
        *context->ATBufferCur = '\0';
        p_read = context->ATBuffer;
    } else {   /* *s_ATBufferCur != '\0' */
        /* There's data in the buffer from the last read. */

        /* skip over leading newlines */
        while (*context->ATBufferCur == '\r' || *context->ATBufferCur == '\n')
            context->ATBufferCur++;

        p_eol = findNextEOL(context->ATBufferCur);

        if (p_eol == NULL) {
            /* A partial line. Move it up and prepare to read more. */
            size_t len;

            len = strlen(context->ATBufferCur);

            memmove(context->ATBuffer, context->ATBufferCur, len + 1);
            p_read = context->ATBuffer + len;
            context->ATBufferCur = context->ATBuffer;
        }
        /* Otherwise, (p_eol !- NULL) there is a complete line 
           that will be returned from the while () loop below. */
    }

    while (p_eol == NULL) {
        int err;
        struct pollfd pfds[2];

        if (0 >= MAX_AT_RESPONSE - (p_read - context->ATBuffer)) {
            MBMLOGE("%s() ERROR: Input line exceeded buffer", __FUNCTION__);
            /* Ditch buffer and start over again. */
            context->ATBufferCur = context->ATBuffer;
            *context->ATBufferCur = '\0';
            p_read = context->ATBuffer;
        }

        /* If our fd is invalid, we are probably closed. Return. */
        if (context->fd < 0) {
            EXIT;
            return NULL;
        }

        pfds[0].fd = context->fd;
        pfds[0].events = POLLIN | POLLERR;

        pfds[1].fd = context->readerCmdFds[0];
        pfds[1].events = POLLIN;

        err = poll(pfds, 2, -1);

        if (err < 0) {
            MBMLOGE("%s() poll: error: %s", __FUNCTION__, strerror(errno));
            EXIT;
            return NULL;
        }

        if (pfds[1].revents & POLLIN) {
            char buf[10];

            /* Just drain it. We don't care, this is just for waking up. */
            read(pfds[1].fd, &buf, 1);
            continue;
        }

        if (pfds[0].revents & POLLERR) {
            MBMLOGE("POLLERR! Returning..");
            EXIT;
            return NULL;
        }

        if (!(pfds[0].revents & POLLIN)) {
            continue;
        }

        do {
            count = read(context->fd, p_read,
                            MAX_AT_RESPONSE - (p_read - context->ATBuffer));
        } while (count < 0 && ((errno == EINTR) || (errno == EAGAIN)));

        if (count > 0) {
            AT_DUMP( "<< ", p_read, count );
            context->readCount += count;

            p_read[count] = '\0';

            /* Skip over leading newlines. */
            while (*context->ATBufferCur == '\r' || *context->ATBufferCur == '\n')
                context->ATBufferCur++;

            p_eol = findNextEOL(context->ATBufferCur);
            p_read += count;
        } else if (count <= 0) {
            /* Read error encountered or EOF reached. */
            if (count == 0) {
                MBMLOGE("%s() atchannel: EOF reached.", __FUNCTION__);
            } else {
                MBMLOGE("%s() atchannel: read error %s", __FUNCTION__, strerror(errno));
            }
            EXIT;
            return NULL;
        }
    }

    /* A full line in the buffer. Place a \0 over the \r and return. */

    ret = context->ATBufferCur;
    *p_eol = '\0';
    context->ATBufferCur = p_eol + 1;     /* This will always be <= p_read,    
                                        and there will be a \0 at *p_read. */

    MBMLOGD("AT(%d)< %s", context->fd, ret);

    EXIT;
    return ret;
}