Access Device File on Linux === 本篇用來記錄透過cpp實現在userspace存取Linux上的Device file, 及相關Lib的使用 讀取Linux上的eeprom --- ```cpp= #include <iostream> #include <array> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/i2c.h> #include <unistd.h> int main(){ int file = open("/sys/bus/i2c/devices/6-0054/eeprom", O_RDONLY); auto result = lseek(file, 0x0000, SEEK_SET); if (result < 0) { std::cout << "fail to seek\n"; return -1; } else { std::cout << "succeed to seek\n"; } std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData; // I2C_SMBUS_BLOCK_MAX from linux/i2c.h auto data = read(file, blockData.data(), 0x8); for (size_t i = 0; i < 8; i++) { std::cout << unsigned(blockData[i]) << std::endl; //轉成unsigned並顯示 } return 0; } ``` ### open ```cpp=11 int file = open("/sys/bus/i2c/devices/6-0054/eeprom", O_RDONLY); ``` 透過**open**回傳File Descriptor給其他需要存取檔案的函式使用,後面加上**O_RDONLY**表示使用唯讀的方式做開啟,另外還有**O_WRONLY**、**O_RDWR**可使用 :::info open 與開啟方式是由fctl.h提供 ::: --- ### lseek ```cpp=12 auto result = lseek(file, 0x0000, SEEK_SET); ``` 透過**lseek**把讀寫位置從檔案的**開始+offset**個位置,return 目前的偏移量,**SEEK_SET**表示從檔案的開始。 :::info lseek 由unistd.h提供 SEEK位置由fcnt.h提供 SEEK_CUR -> 檔案目前往後+offset SEEK_END -> 檔案結尾往後+offset ::: --- ### read ```cpp=24 std::array<uint8_t, I2C_SMBUS_BLOCK_MAX> blockData; auto data = read(file, blockData.data(), 0x8); ``` 建立一個uint8_t型態,長度為``I2C_SMBUS_BLOCK_MAX``的Array 並使用**read**讀取0x08個bytes的資料到blockData中 :::info read 由unistd.h 提供 read(int _fd, void _buf, size_t nbytes) ::: 獲得EEPROMSize --- 此範例使用stdio.h的fopen、fseek、ftell ```cpp= int checkEepromSize(std::string path) { FILE *pFile; pFile = fopen("/sys/bus/i2c/devices/6-0054/eeprom", "rd"); auto result = fseek(pFile, 0, SEEK_END); unsigned long len = (unsigned long)ftell(pFile); std::cout << "file len = " << len << std::endl; } ``` **流程:** 1. fopen開啟檔案 2. fseek移動檔案游標位置到最後 3. ftell獲得從檔案頭到目前位置的byte數 :::info fopen, fseek, ftell 由stdio.h提供 ::: 討論 --- **open 與 fopen有何差異?** > 1. open 是較低階的IO,UNIX的system call,return **file descriptor** > 2. fopen 是標準C定義的函數,底層實作也是會call到open,return 一個指向檔案的**ptr** > 3. open無緩衝,fopen有緩衝(buffer);在使用read時只分配2K buffer若檔案超過,則須執行多次system call讀取資料,fread可以直接指定buffer大小只需要執行一次從HD讀出 > 4. 由於open是較低級別的IO,可更接近系統可以存取到fopen無法訪問的訊息 > 5. open可指定開啟的權限