LINUX.ORG.RU

>По манам там полгода разбираться.

неа, пол дня

man open
man tcgetattr
man tcsetattr

man select
man read

man write
man tcdrain

man close

если надо чтобы две проги одновременно тыкались на один порт

man fcntl

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

watcher_port_t*watcher_open_port(char*devfile, speed_t speed){                                                                                                 
    struct termios ti;                                                                                                                                         
    watcher_port_t*port=malloc(sizeof(watcher_port_t));                                                                                                        
                                                                                                                                                               
    port->debug=WPD_DEBUG;                                                                                                                                     
                                                                                                                                                               
    port->fd = open(devfile, O_RDWR | O_NOCTTY);                                                                                                               
    if (port->fd == -1) {syslog(LOG_ERR,"watcher_open_port():error opening '%s': %s\n", devfile, strerror(errno)); free(port);return NULL; }                   
                                                                                                                                                               
    if(strlen(devfile)<sizeof(wcd_port_t))strcpy(port->name,devfile);                                                                                          
    else {                                                                                                                                                     
        syslog(LOG_WARNING,"watcher_open_port():PORT NAME is too big. Truncated."); strncpy(port->name,devfile,wcd_port_size-1);                               
        port->name[wcd_port_size-1]='\0';                                                                                                                      
    }                                                                                                                                                          
                                                                                                                                                               
    w_port_lockw (port);                                                                                                                                       
                                                                                                                                                               
    if (tcgetattr(port->fd, &ti) < 0){                                                                                                                         
        syslog(LOG_ERR, "watcher_open_port():error setting terminal line modes for '%s': %s\n", devfile, strerror(errno)); close(port->fd);free(port);         
        return NULL;                                                                                                                                           
    }                                                                                                                                                          
                                                                                                                                                               
    cfmakeraw(&ti);                                                                                                                                            
    cfsetispeed(&ti, speed);                                                                                                                                   
    cfsetospeed(&ti, speed);                                                                                                                                   
                                                                                                                                                               
    ti.c_iflag &= ~(INPCK | IGNPAR | PARMRK);                                                                                                                  
    ti.c_iflag |= IGNBRK;                                                                                                                                      
                                                                                                                                                               
    ti.c_cflag |= PARENB;              /* parity */                                                                                                            
    ti.c_cflag &= ~PARODD;             /* no parity by odd*/                                                                                                   
    ti.c_cflag &= ~CSTOPB;             /* 1 stop bit */                                                                                                        
    ti.c_cflag |= CLOCAL;                                                                                                                                      
    ti.c_cflag |= HUPCL;                                                                                                                                       
                                                                                                                                                               
    ti.c_cc[VMIN] = 0;                                                                                                                                         
    ti.c_cc[VTIME] = 0;                                                                                                                                        
                                                                                                                                                               
    if (tcsetattr(port->fd, TCSANOW, &ti) < 0) {                                                                                                               
        syslog(LOG_ERR,"watcher_open_port():error setting terminal line modes for '%s': %s\n", devfile, strerror(errno)); close(port->fd);free(port);          
        return NULL;                                                                                                                                           
    }                                                                                                                                                          
                                                                                                                                                               
    if (-1==tcflush(port->fd, TCIOFLUSH)) {                                                                                                                    
        syslog(LOG_ERR,"watcher_open_port():error flushing both input and output data for '%s': %s\n", devfile, strerror(errno));                              
        close(port->fd);free(port); return NULL;                                                                                                               
    }                                                                                                                                                          
                                                                                                                                                               
    return port;                                                                                                                                               
};

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

//==============================================================================
==================                                                             
//@return: 1 - success                                                                                                                                         
//         0 - must never return. if return then we have internal programm error                                                                               
//     other - error write to port                                                                                                                             
int watcher_write_port(const watcher_port_t* port,unsigned char*buff,const unsigned buff_size){                                                                
    int ret_code,err_no;                                                                                                                                       
    if(!buff_size){                                                                                                                                            
        syslog(LOG_WARNING,"%s:WARNING:Unexpected write 0 bytes to port %s : Possible Internal program error.Please report cvv@email.zp.ua",                   
            __func__,port->name);   return 1;                                                                                                                  
    }                                                                                                                                                          
                                                                                                                                                               
    //Пишем в порт                                                                                                                                             
    errno=0;                                                                                                                                                   
    ret_code=write(port->fd, buff, buff_size);                                                                                                                 
    err_no=errno;                                                                                                                                              
    //Обрабатываем результат записи в порт                                                                                                                     
    if(ret_code<0)               { syslog(LOG_ERR,"%s:write:ERROR:can't write to port %s : %s",                                                                
                                         __func__,port->name,strerror(errno));  return -err_no;                                                                
    }else if(ret_code!=buff_size){ syslog(LOG_ERR,"%s:write:ERROR:Unexpected error write to port %s : Possible Internal program error."                        
                                "Please report cvv@email.zp.ua. Exit", __func__,port->name); exit(1);                                                          
    }else if(port->debug)        { watcher_log_data  (__func__,port,WD_TRANSMITED,buff,buff_size);                                                             
    }                                                                                                                                                          
                                                                                                                                                               
    //Ждём ухода данных из порта                                                                                                                               
    errno=0;                                                                                                                                                   
    ret_code=tcdrain(port->fd);                                                                                                                                
    err_no=errno;                                                                                                                                              
    switch(ret_code){                                                                                                                                          
        case -1:syslog(LOG_ERR,"%s:tcdrain:ERROR:can't drain data in port %s : %s",                                                                            
                                         __func__,port->name,strerror(errno));  return -err_no; break;                                                         
        case  0:if(port->debug)  syslog(LOG_INFO,"%s:tcdrain:INFO:data in port %s successfully drained",                                                       
                                         __func__,port->name);                  return 1;       break;                                                         
        default:syslog(LOG_ERR,"%s:tcdrain:ERROR:Unexpected error drain data in port %s : Possible Internal program error."                                    
                   " Please report cvv@email.zp.ua. Exit", __func__,port->name);exit(1);                                                                       
    }                                                                                                                                                          
    //Сюда мы попадать не должны но для отлова багов                                                                                                           
    syslog(LOG_ERR,"%s:ERROR:Unexpected error in port %s : Internal program error.Please report cvv@email.zp.ua", __func__,port->name); return 0;              
};                                                                                                                                                             

cvv ★★★★★
()

//==============================================================================
===                                                                            
//ф-я читает из порта пакет данных считая разделителем паузу длительностью timeout                                                                             
//@return: <0 - error                                                                                                                                          
//          0 - no answer                                                                                                                                      
//         >0 - quantity of readed bytes                                                                                                                       
int watcher_read_port(const watcher_port_t*port,unsigned char*buff,const unsigned buff_size,struct timeval *timeout){                                          
    fd_set rfds;                                                                                                                                               
    struct timeval tv;                                                                                                                                         
                                                                                                                                                               
    unsigned  byte_counter=0;//счётчик прочитанных байт                                                                                                        
    long      bytes_readed;                                                                                                                                    
                                                                                                                                                               
    bool force_exit, transfer_breaked=false;                                                                                                                   
    long long time_base=gettime_usec();//Здеся надо добавить обработку ошибок                                                                                  
                                                                                                                                                               
    int err_no;                                                                                                                                                
                                                                                                                                                               
    do{                                                                                                                                                        
        FD_ZERO(&rfds);                 FD_SET(port->fd, &rfds);/* Watch port->fd to see when it has input. */                                                 
        tv.tv_sec = timeout->tv_sec;    tv.tv_usec = timeout->tv_usec;                                                                                         
                                                                                                                                                               
        errno=0;                                                                                                                                               
        switch (select(port->fd+1, &rfds, NULL, NULL, &tv)){        /* Don't rely on the value of tv now! */                                                   
            case -1:if((errno != EINTR)&&(errno != EAGAIN)){/*обработкa EINTR & EAGAIN*/                                                                       
                        err_no=errno;syslog(LOG_ERR,"%s(%s):select:ERROR:%s",__func__,port->
;name,strerror(errno));return -err_no;                              
                    }else break;                                                                                                                               
            case  0:/*out by timeout. Предполагаем что пакет дочитан.*/                                                                                        
            transfer_breaked=true; break;                                                                                                                      
            default:/*there are available data*/                                                                                                               
            errno=0;                                                                                                                                           
                    bytes_readed=read(port->fd,buff+byte_counter,buff_size-byte_counter);                                                                      
            err_no=errno;                                                                                                                                      
                    switch(bytes_readed){                                                                                                                      
                        case -1:/*Здесь надо добавить обработку EINTR & EAGAIN*/                                                                               
                if((errno != EINTR)&&(errno != EAGAIN)){                                                                                                       
                    syslog(LOG_ERR, "%s(%s):read:ERROR:%s",__func__,port->name,strerror(errno));return -err_no;                                                
                }else break;                                                                                                                                   
                        case  0:syslog(LOG_ERR, "%s(%s):read:Possible Internal programm error:After select() readed 0 bytes."                                  
                        " Please report to <cvv@email.zp.ua>",__func__,port->name); exit(1);break;                                                             
                        default:byte_counter+=bytes_readed;                                                                                                    
                    }                                                                                                                                          
    }                                                                                                                                                          
    force_exit=(((gettime_usec()-time_base)>1000000)&&(byte_counter==0))  ||  ((byte_counter>0)&&transfer_breaked) || (buff_size==byte_counter);               
    }while(!force_exit);                                                                                                                                       
                                                                                                                                                               
    if(port->debug) watcher_log_data  (__func__,port,WD_RECEIVED,buff,byte_counter);                                                                           
                                                                                                                                                               
    return byte_counter;                                                                                                                                       
} 

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

google->posix serial programming guide - там всё достаточно нормально описано

anonymous
()

Можно ли с com-портами работать на java в linux и free-bsd? Образовалась задачка управлять группой устройств по rs-485 half duplex через переходник rs485-to-rs232 от icp/das, либо через адаптер moxa cp-132ul, что выбрать: c++ или java? На c++ приходилось лет 6 - 7 назад решать в windows похожие задачи, но на java, вроде как, приложения быстрее лепятся... Так на чём?

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

если не производить их настройку то можно. но если попытатся изменить параметры порта то скорее всего будут траблы. лучше С здесь ничего нету. Правда мож есть врапперы для С++

ЗЫ: А что гугль расказал на тему programming+serial+java????

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

>если не производить их настройку то можно. но если попытатся изменить параметры порта то скорее всего будут траблы. лучше С здесь ничего нету. Правда мож есть врапперы для С++

Интересует именно полный контроль: менять скорость, паритет и т.д.

>ЗЫ: А что гугль расказал на тему programming+serial+java????

Есть одна статейка на ряде порталов:

http://lib.juga.ru/article/articleview/90/1/5/

http://javaportal.ru/java/articles/com_port.html

http://www.javable.com/docs/articles/comm/

Там кратко описан некий пакет javax.comm:

http://java.sun.com/products/javacomm/javadocs/packages.html

http://java.sun.com/products/javacomm/index.html

Лезем по 2-й ссылке и видим, что его порта ни под linux ни под free-bsd нет. :(

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

блин, да в нем нет ни блокируемого IO, ни асинхронного

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