日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux内核__force,Linux内核学习:I2C_SLAVE_FORCE

發(fā)布時(shí)間:2025/3/20 linux 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux内核__force,Linux内核学习:I2C_SLAVE_FORCE 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在Linux內(nèi)核源代碼include/linux/i2c-dev.h文件內(nèi),有如下定義:

#define I2C_SLAVE0x0703/* Use this slave address */

#define I2C_SLAVE_FORCE0x0706/* Use this slave address, even if it

is already in use by a driver! */

看注釋,意思就是當(dāng)某個(gè)i2c設(shè)備地址已經(jīng)關(guān)聯(lián)了某個(gè)內(nèi)核driver時(shí),再用I2C_SLAVE作為ioctl的flag就無法取得該設(shè)備的控制權(quán)了。這時(shí),應(yīng)該使用I2C_SLAVE_FORCE。

再次搜索,找到drivers/i2c/i2c-dev.c文件:

static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

{

struct i2c_client *client = file->private_data;

unsigned long funcs;

dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n",

cmd, arg);

switch (cmd) {

case I2C_SLAVE:

case I2C_SLAVE_FORCE:

/* NOTE: devices set up to work with "new style" drivers

* can't use I2C_SLAVE, even when the device node is not

* bound to a driver. Only I2C_SLAVE_FORCE will work.

*

* Setting the PEC flag here won't affect kernel drivers,

* which will be using the i2c_client node registered with

* the driver model core. Likewise, when that client has

* the PEC flag already set, the i2c-dev driver won't see

* (or use) this setting.

*/

if ((arg > 0x3ff) || // 如果地址不只10位

(((client->flags & I2C_M_TEN) == 0) && arg > 0x7f)) // 如果地址設(shè)置為7位但實(shí)際卻超過7位

return -EINVAL;

if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg))

return -EBUSY;

/* REVISIT: address could become busy later */

client->addr = arg;

return 0;

case I2C_TENBIT:上面的第一個(gè)參數(shù)file,舉個(gè)例子,它可以是/dev/i2c-2,那么由此得到的client應(yīng)該是掛在這個(gè)i2c-2總線上的所有i2c設(shè)備吧,這是我的理解。

這里case I2C_SLAVE后面是空的,實(shí)際上應(yīng)該是轉(zhuǎn)移到下一條分支case I2C_SLAVE_FORCE去了,也就是說這兩種情況的后續(xù)處理放在了一起。

如果cmd == I2C_SLAVE并且總線上掛的設(shè)備中已經(jīng)有地址為arg的設(shè)備在用了,則給出-EBUSY,這其實(shí)就是說你往相同的i2c總線上掛兩個(gè)i2c地址一樣的設(shè)備,肯定有潛在的問題,Linux不建議你這樣干。

這個(gè)也是我之前遇到過的情況。解決辦法就是設(shè)置flag為I2C_SLAVE_FORCE,這樣,就可以跳過這個(gè)檢測(cè)條件,將我想要使用的設(shè)備地址arg強(qiáng)行傳遞給該總線,而不理可能導(dǎo)致的問題,這就叫FORCE,后果自負(fù)!

client->addr = arg;

另外一個(gè)問題:client為什么是通過file->private_data傳遞的?這就要看下面的代碼了。

它描述的大概流程是這樣的:inode -> minor -> i2c_dev -> adap -> client,即通過inode一步步生成了client,最后把client傳遞進(jìn)file->private_data,和i2cdev_ioctl()中的傳遞方向正好相反。而且這個(gè)i2cdev_open()發(fā)生在上面的i2cdev_ioctl()之前。

static int i2cdev_open(struct inode *inode, struct file *file)

{

unsigned int minor = iminor(inode);

struct i2c_client *client;

struct i2c_adapter *adap;

struct i2c_dev *i2c_dev;

i2c_dev = i2c_dev_get_by_minor(minor);

if (!i2c_dev)

return -ENODEV;

adap = i2c_get_adapter(i2c_dev->adap->nr);

if (!adap)

return -ENODEV;

/* This creates an anonymous i2c_client, which may later be

* pointed to some address using I2C_SLAVE or I2C_SLAVE_FORCE.

*

* This client is ** NEVER REGISTERED ** with the driver model

* or I2C core code!! It just holds private copies of addressing

* information and maybe a PEC flag.

*/

client = kzalloc(sizeof(*client), GFP_KERNEL);

if (!client) {

i2c_put_adapter(adap);

return -ENOMEM;

}

snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);

client->adapter = adap;

file->private_data = client;

return 0;

}

注意到上面的注釋中的一段話,意思是它只創(chuàng)建一個(gè)匿名的i2c_client,這個(gè)i2c_client以后可以通過I2C_SLAVE或I2C_SLAVE_FORCE flag指向某些i2c設(shè)備地址。而且這個(gè)i2c_client絕對(duì)不會(huì)注冊(cè)到driver model或者I2C core代碼中。它只是用于暫時(shí)的hold住地址信息的私有拷貝(and maybe a PEC flag,這句話暫時(shí)不理吧).

總結(jié)

以上是生活随笔為你收集整理的linux内核__force,Linux内核学习:I2C_SLAVE_FORCE的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。