S3C2440驅動簡析——I2C驅動(3)

     書接上回,在討論完i2c設備、i2c適配器等初始化和刪除相應驅動的程序後,我們在這個小節把注意力放在file_operations裏面的幾個函數操作上,先貼上file_operations結構體代碼,讓我們先看看其包含了哪幾個函數。

 

 

這個結構體想必大家對其結構都相當清晰啦,由此可見,i2c驅動爲用戶空間提供的操作函數包括:

1.no_llseek

2.i2cdev_read

3.i2cdev_write

4.i2cdev_ioctl

5.i2cdev_open

6.i2cdev_release

 

下面就對它們逐一進行分析:

1.no_llseek

從結構體i2cdev_fops 的成員名字llseek推測,其作用應該是改變當前I2C器件讀寫的位置,而現在正如大家所見,驅動程序並未實現這功能。

 

 

2.i2cdev_read

 

read函數主要做的事情有:

(1)struct i2c_client *client = file->private_data;

       通過參數傳入的file(在上一篇博文有闡述)而找到像對應的一個i2c設備,接下來函數就是對該設備進行操作。

(2)ret = i2c_master_recv(client, tmp, count);

       其中i2c_master_recv函數在i2c-core.c 中實現,爲了使本文結構更加清晰,故把跟硬件打交道的代碼文件i2c-core.c 放在後面的博文分析。在這裏,我們只需簡單地理解爲i2c_master_recv函數的作用是通過調用上文提及的i2c設備,並從其中提取count 字節的內容存到tmp 緩衝區裏。

(3)ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret;

       若無異常情況發生,就會調用咱們非常熟悉的copy_to_user 函數,這個函數在這裏就不贅述了,建議還沒掌握的朋友查找相關資料,或者我前面的博文都有提及過,這個是基礎吖!

 

 

3.i2cdev_write

 

write函數又做了什麼事情呢?

(1)struct i2c_client *client = file->private_data;

       見上文read函數中的解釋。

(2)tmp = memdup_user(buf, count);

       memdup_user 函數在Util.c 中實現,源代碼如下

      

      函數的作用一目瞭然,就是把指針src 所指向長度爲len 的內容中copy_from_user 到函數返回的指針。

(3)ret = i2c_master_send(client, tmp, count);

       把緩存器tmp 裏的內容發送到設備client 。

 

 

4.i2cdev_ioctl

 

由於i2c適配器的設備節點代表的是整條i2c總線,所以在對其進行具體的文件系統操作之前還必須指明
待訪問設備的總線地址。指明地址的操作通過ioctl 系統調用完成的,它最終調用設備方法i2cdev_ioctl。ioctl函數還是採用我們非常熟悉的switch-case邏輯結構,其各種命令對應的操作分析如下

case I2C_SLAVE:
case I2C_SLAVE_FORCE: 設置從設備地址

 

case I2C_TENBIT: 設置7bit 地址 or 10bit 地址

 

case I2C_PEC: 如果I2C_PEC != 0 , to use PEC with SMBus

 

case I2C_FUNCS: 返回控制器算法所支持的傳輸種類

 

case I2C_RDWR: 執行i2cdev_ioctl_rdrw函數,代碼如下

整個函數主要做了以下幾件事

(1)copy_from_user(&rdwr_arg,
                              (struct i2c_rdwr_ioctl_data __user *)arg,
                              sizeof(rdwr_arg))

       獲得用戶傳進來的命令,並存放在rdwr_arg。

(2)copy_from_user(rdwr_pa, rdwr_arg.msgs,
                              rdwr_arg.nmsgs * sizeof(struct i2c_msg))

       把指針rdwr_pa指向結構體rdwr_arg的成員msgs。

(3)整個for循環實質就是把要進行傳輸的每個msg的信息copy到字符串指針data_ptrs當中。

(4)res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs);

       i2c_transfer ()函數用於進行I2C適配器和I2C設備之間的一組消息交互,i2c_transfer()函數本身不具備驅動適配器物理硬件完成消息交互的能力,它只是尋找到i2c_adapter對應的i2c_algorithm,並使用i2c_algorithmmaster_xfer()函數真正驅動硬件流程。至於i2c_algorithm和master_xfer等在接下來的博文介紹。

(5)while循環裏把data_ptrs所存的信息統統copy_to_user。

case I2C_SMBUS: 執行i2cdev_ioctl_smbus 函數,主要調用i2c_smbus_xfer,函數在i2c-core.c 裏實現。在這裏我們先簡單理解此函數作用爲選擇smbus 通信協議。

case I2C_RETRIES: 設置重發次數

case I2C_TIMEOUT: 設置超時時間,設定爲 arg * 10 (ms)

呼呼~ioctl函數總算帶過了,具體沒有深入的地方,均是涉及到i2c-core.c 和數據結構i2c_algorithm的地方,這兩個東東留待接下來的博文再來收拾。

5.i2cdev_open

最後兩個函數來點輕鬆的,一眼掃下來,就是一些註冊、初始化等工作,唯一要注意地方是這個open函數比之前所介紹的其他驅動多了一點綁定的工作,如:

client->driver = &i2cdev_driver;

client->adapter = adap;
file->private_data = client;

至於其用意,不記得的朋友建議翻看本i2c驅動系列的第一篇博文。

 

6.i2cdev_release

對照着open函數來看,這個release豈不是小菜一碟?

 

 

 

    到此爲止,i2c-dev.c 的驅動代碼分析暫告一段落,由於本人水平所限,不能很深刻、到位的寫出這份驅動代碼的分析,還請各位看客多多提點。內容錯漏,請嚴厲指出!接下來本系列的第4篇博文將講述i2c-core.c 和數據結構i2c_algorithm,敬請關注!

 

本系列博文鏈接:

I2C驅動(1)http://blog.csdn.net/jarvis_xian/archive/2011/05/27/6449939.aspx
I2C驅動(2)http://blog.csdn.net/jarvis_xian/archive/2011/05/27/6451168.aspx
I2C驅動(3)http://blog.csdn.net/jarvis_xian/archive/2011/05/28/6452431.aspx
I2C驅動(4)http://blog.csdn.net/jarvis_xian/archive/2011/05/30/6455697.aspx

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章