从 userland 读取 32k i2c eeprom

Reading a 32k i2c eeprom from userland

我需要读取嵌入式设备中的 eeprom。

到目前为止,这个“几乎”成功了:

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>

#include <linux/i2c-dev.h>


#define READ_SIZE   (256)
#define NB_PAGES    (128)



void dump_to_file(const char *output_file_path,
          const uint8_t *buffer, const int buffer_length)
{
    int output_file = open(output_file_path, O_RDWR|O_APPEND|O_CREAT);
    if (output_file < 0) {
        printf("Failed opening output file %s\n", output_file_path);
        return;
    }

    write(output_file, buffer, buffer_length);
}


int main(int argc, char *argv[])
{
    /* got these values from i2cdetect */
    const char *i2c_device = "/dev/i2c-4";
    const int device_address = 0x50;

    /* open the i2c device file */
    int file = open(i2c_device, O_RDWR);
    if (file < 0) {
        printf("Failed opening %s\n", i2c_device);
        return 1;
    }

    if (ioctl(file, I2C_SLAVE, device_address) < 0) {
        printf("Failed addressing device at %02X\n", device_address);
        close(file);
        return 1;
    }

    int i = 0;
    for (i = 0; i < NB_PAGES; i++) {
        char buf[READ_SIZE] = {0};

        if (read(file, buf, READ_SIZE) != READ_SIZE) {
            printf("Failed reading\n");
            close(file);
            return 1;
        }

        dump_to_file(argv[1], buf, READ_SIZE);
    }

    close(file);

    return 0;
}

我所说的“几乎”是指它会转储完整的 eeprom,但 START 取决于最后读取的块..
它并不总是相同的。
如果我读了 10 个块。然后 运行 再次阅读该程序,我阅读了下一个而不是前 10 个。

如何设置起始地址?

更新: 如果我这样做:

i2cset -y 4 0x50 0x00 0x00

和 运行 上面的代码,它有效。 那么如何在代码中放置与 i2cset 命令等效的内容呢?

完成! 这并不容易,因为我在任何地方都找不到文档……但我认为,由于 eeprom 是 32K,也许它“像”一个 24c256。但即使在那种情况下,在我决定凭直觉之前,我在用户空间中什么也找不到。 我研究了i2cset源码,了解了它的作用,并把它写进了代码。

这是结果,它从用户空间转储了一个完整的 i2c 32k eprom。

请注意,可以在此处找到完整的备份和还原实用程序: https://gist.github.com/Zibri/cf8ac0b311301aeeaa8910c7da824bff

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>


#define READ_SIZE       (256)
#define NB_PAGES        (128)

void dump_to_file(const char *output_file_path,
                  const uint8_t *buffer, const int buffer_length)
{
        int output_file = open(output_file_path, O_RDWR|O_APPEND|O_CREAT);
        if (output_file < 0) {
                printf("Failed opening output file %s\n", output_file_path);
                return;
        }

        write(output_file, buffer, buffer_length);
}


int main(int argc, char *argv[])
{

        const char *i2c_device = "/dev/i2c-4";
        const int device_address = 0x50;

        int file = open(i2c_device, O_RDWR);
        if (file < 0) {
                printf("Failed opening %s\n", i2c_device);
                return 1;
        }

        if (ioctl(file, I2C_SLAVE, device_address) < 0) {
                printf("Failed addressing device at %02X\n", device_address);
                close(file);
                return 1;
        }

        int i = 0;

        write(file,'\x00\x00',2); // ADDRESS

        for (i = 0; i < NB_PAGES; i++) {
                char buf[READ_SIZE] = {0};

                if (read(file, buf, READ_SIZE) != READ_SIZE) {
                        printf("Failed reading\n");
                        close(file);
                        return 1;
                }

                dump_to_file(argv[1], buf, READ_SIZE);
        }

        close(file);

        return 0;
}