LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Embedded & Single-board computer (https://www.linuxquestions.org/questions/linux-embedded-and-single-board-computer-78/)
-   -   ioctl() only works after iterating over data with printf function (https://www.linuxquestions.org/questions/linux-embedded-and-single-board-computer-78/ioctl-only-works-after-iterating-over-data-with-printf-function-4175689569/)

scotty7 01-30-2021 04:00 PM

ioctl() only works after iterating over data with printf function
 
Hi everyone,

Noob here. I've been playing around with reading & writing i2c from userspace and I've come up against a weird issue.

I've created a variadic function to send a number of bytes to an i2c device. It works great if I include the 'debug printf for loop'. It iterates through the data I'm about to send, casts it as an integer (because I couldn't find a printf formatter for a short) and prints it out. For some reason if I comment out that loop, then the ioctl function will return an error.

I didn't think casting inside a printf statement would do anything to the original data, so the fact that it's messing with the code after it is odd to me. If anyone can shine some light on why this is happening I would appreciate it.

Code:

bool i2c_write(short addr, short reg, short num, ...){

        va_list data;
        va_start(data, num);
       
        size_t size = num+1;
        unsigned char *send_buffer = malloc(size);

        if(send_buffer == NULL){
                printf("i2c_write: Could not allocate memory");
                return false;
        }
       
        send_buffer[0] = reg;
        for(int i = 0; i<num; i++){
                send_buffer[i+1] = (unsigned char)va_arg(data, int);
        }

        //debug to see sent data
        // for(int i = 0; i<size; i++){
        //        printf("send buffer [%d]: %d", i, (int)send_buffer[i]);
        // }

        va_end(data);

        struct i2c_rdwr_ioctl_data burst;
        struct i2c_msg i2c_message;
       
        burst.nmsgs                = 1;
        burst.msgs                = &i2c_message;

        i2c_msg.addr        = addr;
        i2c_msg.buf                = send_buffer;
        i2c_msg.len                = num+1;

        int result = ioctl(i2c_fd, I2C_RDWR, &burst); //actually send the data

        free(send_buffer);

        if(result < num){        //check for the correct number of send bytes, doesn't seem to work atm
                printf("i2c_write: data was not sent properly, %d bytes sent. %s",result,strerror(errno));
                return false;
        }else{
                return true;
        }
}


scotty7 02-03-2021 11:14 PM

Fixed it! Well actually someone else suggested I try it, and it ended up being the culprit.

Not setting the flag on some ioctl calls was causing the issue. On every call to ioctl it seems to set the flags to <some value>. Then on subsequent calls, if the flags were not set, the ioctl function would read these bad flags, and fail.

Lesson learned. Set the flags, even if you don't think they need setting.


All times are GMT -5. The time now is 11:29 AM.