LINUX.ORG.RU

charshunt как с ним работать


0

0

В один модем (http://www.linux.org.ru/view-message.jsp?msgid=3154236 ) надо периодически посылать команду AT+ZOPERTE="beeline" 
Почитав man pppd, я нашёл опцию pty, которая позволяет "пропускать" все данные через скрипт. 
Как же написать такой скрипт? То что сочинил я - не работает. Кто нибудь может подсказать как надо правильно?

#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <stdlib.h>

int main(void)
{
    struct timeval c,n;
    char t='a';
    int e=1;
    FILE *f;

    gettimeofday( &c, NULL);
    f=fopen("/dev/ttyUSB0","r+");

    while(e)
    {
        while( (t!='\n') || (t!=EOF) )
        {
            t=fgetc(stdin);
            fputc(t,f);
        }
        t='a';
        fflush(f);

        while( (t!='\n') || (t!=EOF) )
        {
            t=fgetc(f);
            fputc(t,stdout);
        }

        if ( ( feof(f) ) || ( feof(stdin) ) ) e=0;

        fflush(stdout);

        gettimeofday( &n, NULL);
        if ( (n.tv_sec-c.tv_sec) > 59 )
        {
            c=n;
            fprintf(f,"AT+ZOPERTER=\"beeline\"\r\n");
        }
        fflush(f);
    }
    fclose(f);

    return 0;
}
★★★

+++ - Switches the modem from data to command state; this command is not proceeded by AT.

не то??

dilmah ★★★★★
()

ИМХО, уберите все fputc и fgetc, используйте read/write + select на эти файловые дескрипторы --- так сделано в программе pptp.

Запускайте вашу программу через strace и будет ясно, где не работает.

mky ★★★★★
()
Ответ на: комментарий от mky

Слегка подправил:

#include <sys/types.h>         
#include <sys/stat.h>          
#include <sys/time.h>          
#include <time.h>              
#include <stdlib.h>            
#include <unistd.h>            
#include <fcntl.h>             
#include <errno.h>             
#include <sys/select.h>        

#define COUNT 1

int main(void)
{             
    struct timeval c,n,to;
    char t[COUNT];        
    char com[]="AT+ZOPERTE=\"beeline\"\r\n";
    char com1[]="END";                      
    ssize_t rc;                             
    int e=1, err0=0, err1=0;                
    int f,r,ri,i;                           
    int res, nfds;                          
    fd_set ready;                           
                                            
    i=0; while(com[i]!='\0')i++;            
    gettimeofday( &c, NULL);                
    f=open("/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_NDELAY);
    r=open("out.txt", O_WRONLY|O_APPEND|O_SYNC);
    ri=open("in.txt", O_WRONLY|O_APPEND|O_SYNC);
                                                                   
    if(f<0)e=0;                                                    
                                                                   
                                                                   
    while(e)                                                       
    {                                                              
        FD_ZERO(&ready);                                           
        FD_SET(0, &ready);                                         
        nfds=1;
        to.tv_usec=50;
        to.tv_sec=0;
        res=select(nfds, &ready, NULL, NULL, &to);
        if (res)
        {
            rc=read(0, t, COUNT); //stdin
            while( rc>0 )
            {
                write(f, t, rc);
                write(r, t, rc);
                rc=read(0, t, COUNT);
            }
        };
        //if(rc<0) err0=errno; else err0=t[0];
        err0=t[0];

        FD_ZERO(&ready);
        FD_SET(f, &ready);
        nfds=f+1;
        to.tv_usec=50;
        to.tv_sec=0;
        res=select(nfds, &ready, NULL, NULL, &to);
        if (res)
        {
            rc=read(f, t, COUNT);
            while( rc>0 )
            {
                write(1, t, rc); //stdout
                write(ri, t, rc);
                rc=read(f, t, COUNT);
            }
        };
        //if(rc<0)err1=errno; else err1=t[0];
        err1=t[0];
        if (  (err0==4)  || ( err1==4 ) ) e=0;
        gettimeofday( &n, NULL);
        if ( (n.tv_sec-c.tv_sec) > 59 )
        {
            c=n;
            write(f, com, i);
        }
    }
    write(r, com1, 3);
    write(ri, com1, 3);
    close(f);
    close(r);
    close(ri);

    return 0;
}

Но, всё равно не работает так как надо: после ожидания ответа OK от модема, pppd закрывает chat. При этом данные в порту есть (если после завершения программы сделать cat /dev/ttyUSB0 данные там будут), но 

18553 read(3, 0x7ffffc18ea4f, 1)        = -1 EAGAIN (Resource temporarily unavailable)
18553 select(1, [0], NULL, NULL, {0, 50}) = 1 (in [0], left {0, 50})
18553 read(0, 0x7ffffc18ea4f, 1)        = -1 EIO (Input/output error)
18553 select(4, [3], NULL, NULL, {0, 50}) = 0 (Timeout)
18553 select(1, [0], NULL, NULL, {0, 50}) = 1 (in [0], left {0, 50})
18553 read(0, 0x7ffffc18ea4f, 1)        = -1 EIO (Input/output error)

где 3 - дескриптор порта /dev/ttyUSB0
0 - сюда подключается pppd

Т.е. почему-то моя программа не может прочитать ответ модема, и соответственно chat её убивает через заданный промежуток времени.

ArtSh ★★★
() автор топика
Ответ на: комментарий от ArtSh

>Т.е. почему-то моя программа не может прочитать ответ модема

Не знаю, почему, может не нравится режим O_NDELAY...
Кстати, если этот режим стоит, то надо проверять результат write(f, t, rc).

Можете попробовать мой вариант:

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>


#define COUNT 1024
#define pppfd STDIN_FILENO

int main(void)
{
    struct timeval c,n,to;

    char com[]="AT+ZOPERTE=\"beeline\"\r\n";

    char usbwb[COUNT], pppwb[COUNT];
    int nub=0, jub=0, npb=0, jpb=0;
    fd_set rready, wready;

    int usbfd, mfd;
    int res, lencom;

    lencom=strlen(com);
    gettimeofday( &c, NULL);
    usbfd=open("/dev/ttyUSB0", O_RDWR|O_NOCTTY);

    if(usbfd<0) return 2;

    mfd=usbfd;                                                           
    if ( usbfd < pppfd) mfd=pppfd;
    mfd++;
                                                                    
    while(1){
        FD_ZERO(&rready); FD_SET(pppfd, &rready); FD_SET(usbfd, &rready);
        FD_ZERO(&wready); FD_SET(pppfd, &wready); FD_SET(usbfd, &wready);
        to.tv_usec=50000;
        to.tv_sec=0;
        res=select(mfd, &rready, &wready, NULL, &to);
        if (res<=0) continue;

        if ( nub > 0 && FD_ISSET(usbfd, &wready) ) {
            if ( (res=write(usbfd, usbwb+jub, nub)) > 0 ) {
                nub-=res;
                jub+=res;
            }
        }
        if ( npb > 0 && FD_ISSET(pppfd, &wready) ) {
            if ( (res=write(pppfd, pppwb+jpb, npb)) > 0 ) {
                npb-=res;
                jpb+=res;
            }
        }

        if ( nub <= 0 ) {
            gettimeofday(&n, NULL);
            if ( (n.tv_sec-c.tv_sec) > 59 ) {
                c=n;
                memcpy(usbwb, com, lencom);
                nub=lencom;
                jub=0;
            }
        }

        if ( nub <= 0 && FD_ISSET(pppfd, &rready) ) {
            if ( (nub=read(pppfd, usbwb, COUNT)) > 0 ) {
                jub=0;
            }
            if ( nub == 0 ) {
                return 3; // stdin is close !
            }
        }
        if ( npb <= 0 && FD_ISSET(usbfd, &rready) ) {
            if ( (npb=read(usbfd, pppwb, COUNT)) > 0 ) {
                jpb=0;
            }
            if ( npb == 0 ) {
                return 4; // /dev/ttyUSB0 is close !
            }
        }
    }

    return 0;
}

mky ★★★★★
()
Ответ на: комментарий от mky

Висит так, что даже магические клавиши не помогают. В strace огромное количество select'ов...

В общем, нашёл обходной манёвр: если указать опцию record, pppd устанавливает флаг O_NONBLOCK, после этого можно писать в порт кроном. Однако, делу это помогло не очень сильно: модем теперь отключается раз в 6 минут. Буду дальше следить за вендовой утилитой...

ArtSh ★★★
() автор топика
Ответ на: комментарий от ArtSh

>Висит

Ошибку поищу вечером, попробую запустить на ttyS0 модеме (нету USB-модемов). Наверное надо делать ioctl'ы при открытии порта (раз у pppd указывается crtscts).

>Буду дальше следить за вендовой утилитой...

Думаю, что надо детально разбирать все, что передаётся по USB, возможно, что это самый AT+ZOPERTE можно передавать только между пакетами ppp-протокола. Думаю, что раз уж вы взялись за правку ядра, то может имеет смысл поправить pppd. Насколько я помню там были простые исходники...

mky ★★★★★
()
Ответ на: комментарий от mky

>Ошибку поищу вечером, попробую запустить на ttyS0 модеме (нету USB-модемов). Наверное надо делать ioctl'ы при открытии порта (раз у pppd указывается crtscts).

А я подозреваю, что usbserial не успевает что-то переслать, или ожидает ответа или просто так зависает. Пару раз я видел сообщения о его смерти в dmesg.

>Думаю, что надо детально разбирать все, что передаётся по USB, возможно, что это самый AT+ZOPERTE можно передавать только между пакетами ppp-протокола.

Пробовал (блокировал устройство, посылал +++, потом команду, также если ничего не посылать через сеть, то pppd ничего не посылает в модем). Удалось продержаться 6 минут.

>Думаю, что раз уж вы взялись за правку ядра, то может имеет смысл поправить pppd. Насколько я помню там были простые исходники...

На самом деле не такие уж и простые (для меня).

P.S. Если соединение с интернетом не установлено, то посылка команды в порт работает как надо, модем не отключается через две минуты, а вот если он уже соединился с интернетом, то тут и начинаются проблемы. Сейчас я выяснил, что родная утилита посылает команды как-то хитро, через другую конечную точку. Ситуация осложняется ещё тем, что в винде модем видится как три устройства: два последовательных порта (в один из которых и посылаются все команды) и модем (в который посылаются/из которого принимаются данные). А до отладки драйверов под виндой я ещё не дорос...

ArtSh ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.