0

How can I identify the SMBus device address on the terminal? Also, I would like to know how to set the clock frequency in the i2c.h file.

I attempted to use i2cdetect -y 6, but unfortunately, it did not work. Are there any alternative methods for detecting the SMBus device?

Normally, I2C runs at around 400KHz, while SMBus operates at 100KHz. I wish to set the clock frequency to 100KHz to match the SMBus protocol. How to set the clock frequency on i2c.h file?

My i2c6.h code is as follows

#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <cstdlib>
#include <cstring>
#include <unistd.h> // For close() function

int i2cfd;
static const char *device_name = "/dev/i2c-6";
#define ARRAY_SIZE(a)   (sizeof(a) / sizeof(*a))

int opendevice(void)
{
    i2cfd = open(device_name, O_RDWR);
    if (i2cfd < 0) {
        perror("Error opening I2C device");
    } else {
        // Set the I2C functionality flags to enable SMBus (which includes 100kHz clock frequency)
        if (ioctl(i2cfd, I2C_FUNCS, I2C_FUNC_I2C) < 0) {
            perror("Error setting I2C functionality");
            close(i2cfd);
            i2cfd = -1;
        }
    }
    return i2cfd;
}

void closedevice(void)
{
    if (i2cfd >= 0) {
        close(i2cfd);
        i2cfd = -1;
    }
}

int do_rdwr(struct i2c_msg *msgs, int nmsgs)
{
    struct i2c_rdwr_ioctl_data msgset = {
            .msgs = msgs,
            .nmsgs = static_cast<__u32>(nmsgs),
    };
    if (msgs == NULL || nmsgs <= 0)
        return -1;
    if (ioctl(i2cfd, I2C_RDWR, &msgset) < 0)
        return -1;
    return 0;
}

int read_i2c_device_16(uint8_t address, uint16_t offset, uint8_t *buf, uint16_t count)
{
    uint8_t offset_data[] =  {static_cast<uint8_t>(offset >> 8), static_cast<uint8_t>(offset & 0x00FF)};

    struct i2c_msg msgs[] = {
            {address, 0, ARRAY_SIZE(offset_data), static_cast<__u8 *>((void *) offset_data)},
            {address, I2C_M_RD, count, static_cast<__u8 *>((void *) buf)}
    };

    if (do_rdwr(msgs, ARRAY_SIZE(msgs)))
        return -1;
    return 0;
}

int write_i2c_device_16(uint8_t address, uint16_t offset, const uint8_t *buf, int len)
{
    uint8_t *data = (uint8_t *)malloc((2 + len) * sizeof(*data));

    struct i2c_msg msgs[] = {
            {address, 0, static_cast<__u16>((2 + len) * sizeof(*data)), static_cast<__u8 *>((void *) data)}
    };

    if (!data) {
        len = -1;
        goto err_malloc;
    }

    data[0] = offset >> 8;
    data[1] = offset & 0xFF;
    memcpy(data + 2, buf, len);

    if (do_rdwr(msgs, ARRAY_SIZE(msgs))) {
        len = -1;
        goto err_do_rdwr;
    }

    err_do_rdwr:
    free(data);
    err_malloc:
    return len;
}

int read_i2c_device_8(uint8_t address, uint8_t offset, uint8_t* buf)
{
    struct i2c_msg msgs[] = {
            {address, 0, 1, &offset},
            {address, I2C_M_RD, 1, buf}
    };

    if (do_rdwr(msgs, ARRAY_SIZE(msgs))) {
        return -1;
    }
    return 0;
}

int write_i2c_device_8(uint8_t address, uint8_t offset, uint8_t *data)
{
    int retval = 2;
    uint8_t *buffer = (uint8_t *)malloc(2 * sizeof(*data));
    struct i2c_msg msgs[] = {
            {address, 0, 2, buffer}
    };
    if (!buffer)
    {
        retval = -1;
        return retval;
    }
    buffer[0] = offset;
    memcpy(buffer + 1, data, 1);
    if (do_rdwr(msgs, ARRAY_SIZE(msgs))) {
        retval = -1;
    }
    free(buffer);
    return retval;
}
0andriy
  • 4,183
  • 1
  • 24
  • 37
  • How *it did not work* exactly? Are you sure device is connected to adapter with index 6? Clock frequency is specific to controller, not to a connected device. – dimich Jul 28 '23 at 06:49

0 Answers0