0
votes

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

1
and how are you writing the data to the port? - isedev
You are not writing "hex data". You are writing (from the looks of your code) binary data, which you represent as hex in a string. That is not "hex data". - unwind
..and how does that thing know there are five chars, as hinted at by @isedev? I hope the answer is not 'because of a null terminator' because, looking at the data.... - Martin James
I've update with write function code. [unwind] Yes...sorry i've forgot to specify Binary Data as Hex String..what kind of serial settings i've to do? - Mitsus
When you call write_port(), don't use strlen() since the data is not a string, but binary (as @MartinJames pointed out, just making it more concrete since you're still not showing that part of the code). - unwind

1 Answers

2
votes

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).