cserial-portposixansi-ctermios

POSIX C Serial Port Write Cut Buffer


3i've a small C program for read and write Hex Data over serial port. In reading i've not problems, bu when i try to write a Hex Data as this:

static const unsigned char cmdActuatorOn[] = "\x41\x54\x2B\x18\x12\x00\x12\x4B"

i see that the write function send over serial port only 5 bytes...so i suppose that it for any reason cut Hex Data at "0x00" character. Below my serial port settings:

int init_port(char const *const device)
{
    int descriptor, result;
    struct termios settings;


    descriptor = open(device, O_RDWR | O_NOCTTY);

    result = fcntl(descriptor, F_SETFL, O_NONBLOCK);

    result = tcgetattr(descriptor, &settings);

    settings.c_cflag &= ~PARENB;
    settings.c_cflag &= ~CSTOPB;
    settings.c_cflag &= ~CSIZE;
    settings.c_cflag |=  CS8;

    settings.c_iflag |= IGNPAR;
    settings.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY | INPCK);// raw data input mode
    settings.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);// raw data output
    settings.c_oflag &= ~OPOST;// setting timeouts
    settings.c_cc[VMIN] = 1; // minimum number of chars to read in noncanonical (raw mode)
    settings.c_cc[VTIME] = 5; // time in deciseconds to wait for data in noncanonical mode (raw mode)

    cfsetispeed(&settings, B9600);
    cfsetospeed(&settings, B9600);


    result = tcsetattr(descriptor, TCSANOW, &settings);

    return descriptor;
}

Function for write data is:

int write_port(void const *const data, size_t const size)
{
    unsigned char const *p = (unsigned char const *)data;
    unsigned char const *const q = (unsigned char const *)data + size;
    ssize_t n;

    while (p < q) {
        do {
            n = write(port_descriptor, p, (size_t)(q - p));
        } while (n == (ssize_t)-1 && errno == EINTR);
        if (n == (ssize_t)-1 && errno == EWOULDBLOCK) {
                /* Sleep for a millisecond, then retry. */
                usleep(1000);
                continue;
        }

        if (n == (ssize_t)-1)
                return errno;
        else
            if (n < (ssize_t)1)
                    return EIO;

        p += (size_t)n;
    }

    if (p != q)
        return EIO;

    return 0;
}

I call function write_data as below:

result = write_port(cmdActuatorOn, strlen(cmdActuatorOn));

This work fine for others binary data as:

static const unsigned char cmdGetCoordAddress[] = "\x40\x04\x2B\x02\x08\x52\x41\x9D";
static const unsigned char cmdReadCoordChannelAddress[] = "\x43\x12\x0B\x07\x08";
static const unsigned char cmdReadCoordPanId[] = "\xAF\x50\x2B\x07\x09\x52\x49\x90";

Write function in this case write all correct bytes on serial port. Only cmdActuatorOn not, so i suppose that 0x00 is the problem.

Where are my errors? I've wrong serial port configuration? I set it for use with Raw Mode...is ot correct?

Thanks a lot


Solution

  • You are calling strlen() on data which is not a standard C string.

    To be more specific, your data has an embedded '\0'-byte, which in C means "end of string". Thus, strlen("\x41\x54\x2B\x18\x12\x00\x12\x4B") is 5. It doesn't matter how many bytes follow that \x00, as far as strlen() is concerned the string ends there.

    Since you're actually after the size of the array, it's better to use that, i.e. use sizeof cmdGetCoordAddress and so on. Note that this won't work if you don't have access to the actual array, i.e. if the array has decayed into a pointer it won't work and then you need to pass the size from the point where the array declaration is available.

    Since your arrays are global, sizeof will work.

    So write the call:

    result = write_port(cmdActuatorOn, sizeof cmdActuatorOn);
    

    Note that this only works since cmdActuatorOn is declared as an array, though. If you do the very similiar:

    static const unsigned char *cmdGetCoordAddress = "\x40\x04\x2B\x02\x08\x52\x41\x9D";
    

    Then the name cmdGetCoordAddress refers to a pointer of type unsigned char *, and sizeof will yield the size of that particular type (typically 4 or 8).