I2C/SMBus 功能檢查


介紹

因為不是每個I2C或SMBus適配器都實現了I2C規范中的所有內容,當client被賦予附加到適配器的選項時,它不能相信它需要的所有東西都實現了:client需要一些方法來檢查適配器是否具有所需的功能。

功能常量

關於最新的功能常量列表,請查看<uapi/linux/i2c.h>!

I2C_FUNC_I2C

純i2c-level命令(純SMBus適配器通常不能執行這些命令)

I2C_FUNC_10BIT_ADDR

處理10位地址擴展

I2C_FUNC_PROTOCOL_MANGLING

了解I2C_M_IGNORE_NAK, I2C_M_REV_DIR_ADDR 和 I2C_M_NO_RD_ACK標志(修改I2C協議!)

I2C_FUNC_NOSTART

可以跳過重復的啟動順序

I2C_FUNC_SMBUS_QUICK

處理SMBus write_quick命令

I2C_FUNC_SMBUS_READ_BYTE

處理SMBus read_byte命令

I2C_FUNC_SMBUS_WRITE_BYTE

處理SMBus write_byte命令

I2C_FUNC_SMBUS_READ_BYTE_DATA

處理SMBus read_byte_data命令

I2C_FUNC_SMBUS_WRITE_BYTE_DATA

處理SMBus write_byte_data命令

I2C_FUNC_SMBUS_READ_WORD_DATA

處理SMBus read_word_data命令

I2C_FUNC_SMBUS_WRITE_WORD_DATA

處理SMBus write_byte_data命令

I2C_FUNC_SMBUS_PROC_CALL

處理SMBus process_call命令

I2C_FUNC_SMBUS_READ_BLOCK_DATA

處理SMBus read_block_data命令

I2C_FUNC_SMBUS_WRITE_BLOCK_DATA

處理SMBus write_block_data命令

I2C_FUNC_SMBUS_READ_I2C_BLOCK

處理SMBus read_i2c_block_data命令

I2C_FUNC_SMBUS_WRITE_I2C_BLOCK

處理SMBus write_i2c_block_data命令

 

為了方便起見,還定義了上述標志的一些組合:

I2C_FUNC_SMBUS_BYTE

處理SMBus read_byte和write_byte命令

I2C_FUNC_SMBUS_BYTE_DATA

處理SMBus read_byte_data和write_byte_data命令

I2C_FUNC_SMBUS_WORD_DATA

處理SMBus read_word_data和write_word_data命令

I2C_FUNC_SMBUS_BLOCK_DATA

處理SMBus read_block_data和write_block_data命令

I2C_FUNC_SMBUS_I2C_BLOCK

處理SMBus read_i2c_block_data和write_i2c_block_data命令

I2C_FUNC_SMBUS_EMUL

處理所有可以由真正的I2C適配器模擬的SMBus命令 (使用透明仿真層)

在3.5之前的內核版本中,I2C_FUNC_NOSTART作為I2C_FUNC_PROTOCOL_MANGLING的一部分實現。

適配器(Adapter)實現

當您編寫一個新的適配器驅動程序時,您必須實現一個函數回調功能。下面給出了典型的實現。

典型的僅SMBus適配器將列出它支持的所有SMBus事務。這個例子來自於i2c-piix4驅動程序:

static u32 piix4_func(struct i2c_adapter *adapter)
{
      return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
             I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
             I2C_FUNC_SMBUS_BLOCK_DATA;
}

典型的 full-I2C 適配器將使用以下內容(來自i2c-pxa驅動程序):

static u32 i2c_pxa_functionality(struct i2c_adapter *adap)
{
      return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}

I2C_FUNC_SMBUS_EMUL包含了所有的SMBus事務(添加了I2C塊事務),i2c-core可以使用I2C_FUNC_I2C模擬這些事務,而無需適配器驅動程序的任何幫助。其思想是讓客戶端驅動程序檢查對SMBus函數的支持,而不必關心所述函數是由適配器在硬件中實現的,還是由i2c-core 在I2C適配器上軟件模擬的。

Client 檢查

在client嘗試附加到adapter,或甚至進行測試以檢查其支持的某個設備是否存在於adapter上之前,應該檢查所需的功能是否存在。典型的方法是(從lm75驅動程序摘錄):

static int lm75_detect(...)
{
      (...)
      if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
                                   I2C_FUNC_SMBUS_WORD_DATA))
              goto exit;
      (...)
}

在這里,lm75驅動程序檢查適配器是否可以同時執行SMBus字節數據和SMBus字數據事務。如果沒有,那么驅動程序將不能在這個適配器上工作,也就沒有繼續下去的意義。如果上面的檢查成功,那么驅動程序知道它可以調用以下函數: i2c_smbus_read_byte_data(), i2c_smbus_write_byte_data(), i2c_smbus_read_word_data() 和 i2c_smbus_write_word_data()。作為經驗法則,用 i2c_check_functions() 測試的功能常量應該與驅動程序調用的 i2c_smbus_* 函數完全匹配。

注意,上面的檢查並不能說明這些功能是由底層適配器在硬件中實現的,還是由 i2c-core 在軟件中模擬的。Client 驅動程序不必關心這一點,因為 i2c-core 將在I2C適配器上透明地實現SMBus事務。

通過/dev檢查

如果試圖從用戶空間程序訪問適配器,則必須使用/dev接口。當然,您仍然需要檢查您需要的功能是否得到支持。這是使用I2C_FUNCS ioctl完成的。下面是一個改編自i2cdetect程序的示例:

int file;
if (file = open("/dev/i2c-0", O_RDWR) < 0) {
      /* Some kind of error handling */
      exit(1);
}
if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
      /* Some kind of error handling */
      exit(1);
}
if (!(funcs & I2C_FUNC_SMBUS_QUICK)) {
      /* Oops, the needed functionality (SMBus write_quick function) is
         not available! */
      exit(1);
}
/* Now it is safe to use the SMBus write_quick command */

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM