0

Реферат: Я пишу snooper ttyUSB. Код должен считывать (2) данные из последовательного порта и записывать (2) на другой последовательный порт. Чтение из последовательного порта отлично работает с/bin/cat, но с моим кодом не работает.Написание ttyUSB snooper failing

Установка аппаратного обеспечения: Я сделал перекрестный кабель FTDI и поставил один конец на компьютере под управлением Windows XP как Com2, а другой конец на современной Linux-машине в качестве/dev/ttyUSB0. У машины Linux есть USB-кабель Serial, который отображается как/dev/ttyUSB1. Он связан с фактическим аппаратным блоком, который я пытаюсь отслеживать. Я подтвердил, что оборудование отлично работает.

Эта часть работы: я буду «кошка/DEV/ttyUSB0>/TMP/данные», а затем есть проблема машины WinXP «чтение с устройства по COM2», а следующие шесть (6) байт данных будут отправлены.

\x02\x01\x40\x00\x0a\x9e 

Этот «пакет» отправляется в 4 раза или около того с очень небольшой задержкой, это, кажется, код WinXP просто попробовать несколько раз. Если я воспроизведу это только один раз, это сработает.

Если я просто делаю «cat/tmp/data>/dev/ttyUSB1», аппаратное устройство ответит правильно, указав, что оно получило команду. Большой!

Проблема и мой код: Я пишу некоторый код, который будет работать на машине Linux, которая будет читать (2) из ​​/ DEV/ttyUSB0 и записать его на/DEV/ttyUSB1 и наоборот. Однако по какой-то неизвестной причине он получит только 4 байта в первом «пакете», а затем 5 в последующих 3 попытках. Иногда 5 байтов кажутся слегка «поврежденными», то есть я вижу \ xffffff для последнего или второго байта. Вот мой код:

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <strings.h> 

void hexdump(char *data, int size) { 
    for (size_t i = 0; i < size; ++i) 
     printf("%02x ", data[i]); 
    putchar('\n'); 
} 

int main() { 
    int fdzero; 
    int fdone; 

    int maxfd; 

    fd_set sockrd; 
    struct timeval timer; 

    char data[10]; 
    int size; 
    char tmp; 

    fdzero = open("/dev/ttyUSB0", O_RDWR); 
    if (fdzero == -1) { 
     perror("Failed to open /dev/ttyUSB0"); 
     return 1; 
    } 

    fdone = open("/dev/ttyUSB1", O_RDWR); 
    if (fdone == -1) { 
     perror("Failed to open /dev/ttyUSB1"); 
     return 1; 
    } 

    if (fdzero > fdone) 
     maxfd = fdzero; 
    else 
     maxfd = fdone; 

    printf("Enter loop\n"); 
    for(;;) { 
     bzero(data, 10); 
//  fflush(NULL); 
     FD_ZERO(&sockrd); 
     FD_SET(fdzero, &sockrd); 
     FD_SET(fdone, &sockrd); 

     timer.tv_sec = 60; 
     timer.tv_usec = 0; 

     select(maxfd+1, &sockrd, NULL, NULL, &timer); 

     if (FD_ISSET(fdzero, &sockrd)) { 

      size = read(fdzero, data, 10); 
      if (size == -1) { 
       perror("Failed to read /dev/ttyUSB0"); 
       break; 
      } 

      size = write(fdone, data, size); 
      if (size == -1) { 
       perror("Failed to write to /dev/ttyUSB1"); 
       break; 
      } 
      printf("ttyUSB0 -> ttyUSB1: %d\n", size); 
     } 


     // This portion does not trigger yet, but its a mirror 
     // Yes, I know...bad code :(
     else { 
      size = read(fdone, data, 10); 
      if (size == -1) { 
       perror("Failed to read /dev/ttyUSB1"); 
       break; 
      } 
      size = write(fdzero, data, size); 
      if (size == -1) { 
       perror("Failed to write to /dev/ttyUSB0"); 
       break; 
      } 
      printf("ttyUSB1 -> ttyUSB0: %d\n", size); 
     } 

     // Used to monitor what is read()/write() 
     hexdump(data, size); 
    } 

    return 0; 
} 

Когда я на самом деле запустить этот код, я вижу это:

# cc snoop.c -o snoop 
# ./snoop 
Enter loop 
ttyUSB0 -> ttyUSB1: 4 
02 00 40 ffffff9e 
ttyUSB0 -> ttyUSB1: 4 
02 00 40 ffffff9e 
ttyUSB0 -> ttyUSB1: 4 
02 00 40 ffffff9e 
ttyUSB0 -> ttyUSB1: 5 
01 02 00 40 ffffff9e 
ttyUSB0 -> ttyUSB1: 5 
01 02 00 40 ffffff9e 
ttyUSB0 -> ttyUSB1: 5 
01 02 00 40 ffffff9e 

Обратите внимание, что в настоящее время получили только 4 или 5 байт, а затем передаются через в любой момент времени. Не 6. Также обратите внимание, что «пакет» искажен. Что в мире может вызвать это?

рациональность, если вы заинтересованы: У меня есть старое программное обеспечение, которое работает только на Windows XP и не будет работать в виртуальной машине (это известная проблема). Я хотел бы захватить трафик через последовательный порт. Я купил машину WinXP только для этого.

+0

Я подозреваю, что это связано с бит контроля четности? –

ответ

0

Хорошо, так что ваши два вопроса:

Иногда, 5 байт появляются несколько «повреждены», то есть я вижу \ xffffff для последнего или предпоследнего байта.

Это из-за того, как printf интерпретирует данные, поступающие (this может представлять интерес). Он передается как char, который подписан. В этом случае интерпретируются старшие биты. Чтобы исправить эту часть, ваш hexdump(char* data, int len) должен быть либо hexdump(unsigned char* data, int len), либо использовать размер байтового типа, такой как uint8_t, чтобы ваша подпись выглядела как hexdump(uint8_t* data, int len).

Однако по какой-то неизвестной причине он получит только 4 байта в первом «пакете», а затем 5 в последующих 3 попытках.

Это почти наверняка связано с тем, что вы не устанавливаете никаких параметров на последовательном порту. Один из символов, который у вас есть, - 0x0A, который является символом перевода строки. Это либо игнорируется драйвером последовательного порта, либо транслируется на другой символ. Чтобы это исправить, необходимо установить параметры последовательного порта, чтобы быть сырыми и не переводить любые символы, которые приходят в Я вообще делать что-то вроде следующего:.

struct termios newio; 
if(tcgetattr(fd, &newio) < 0){ /* error handling here */ }  

/* Set some default settings */ 
newio.c_iflag |= IGNBRK; 
newio.c_iflag &= ~BRKINT; 
newio.c_iflag &= ~ICRNL; 
newio.c_oflag = 0; 
newio.c_lflag = 0; 
newio.c_cc[VTIME] = 0; 
newio.c_cc[VMIN] = 1; 

/* Set our baud rate */ 
cfsetospeed(&newio, B9600); 
cfsetispeed(&newio, B9600); 

/* Character size = 8 */ 
newio.c_cflag &= ~CSIZE; 
newio.c_cflag |= CS8; 

/* One stop bit */ 
newio.c_cflag &= ~CSTOPB; 

/* Parity = none */ 
newio.c_iflag &= ~IGNPAR; 
newio.c_cflag &= ~(PARODD | PARENB); 
newio.c_iflag |= IGNPAR; 

/* No flow control */ 
newio.c_iflag &= ~(IXON | IXOFF | IXANY); 

/* Set our serial port settings */ 
if(tcsetattr(fd, TCSANOW, &newio) < 0) { /* error handling code here */ } 

Если вы не хотите, чтобы установить параметры последовательного порта таким образом, я написал small library, который должен абстрагировать небольшие детали для вас.

+0

Похоже, что это трюк! –

+0

Похоже, что это трюк! Как ни странно, он работает некоторое время, а затем внезапно поток соединения выходит из строя. Я не уверен, почему и программное обеспечение, которое я отслеживаю, не выдает сообщение об ошибке. Существуют ли какие-либо другие настройки соединения, которые могут привести к лучшему соединению? –

+0

Нет других настроек, о которых я могу думать. Настройки, которые я опубликовал, я получил из [GTKTerm] (https://fedorahosted.org/gtkterm/), хотя, возможно, я пропустил настройку. – rm5248