最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Linux I2C驅(qū)動(dòng)注冊(cè)詳解

 更新時(shí)間:2025年07月22日 09:24:45   作者:大肥周  
文章介紹了I2C驅(qū)動(dòng)注冊(cè)機(jī)制,核心是structi2c_driver結(jié)構(gòu)體,需填充name、probe和id_table字段,name用于顯示驅(qū)動(dòng)名稱,probe在設(shè)備匹配后調(diào)用(無(wú)論設(shè)備是否存在),通過(guò)設(shè)備樹(shù)或靜態(tài)注冊(cè)識(shí)別設(shè)備,最終觸發(fā)驅(qū)動(dòng)探針流程

注冊(cè)接口

#define i2c_add_driver(driver) \
       i2c_register_driver(THIS_MODULE, driver)

int i2c_register_driver(struct module *owner, struct i2c_driver *driver)

注冊(cè)的結(jié)構(gòu)體是struct i2c_driver,主要填充name、probe和id_table字段,其中name是驅(qū)動(dòng)名稱,到時(shí)會(huì)在/sys/bus/i2c/drivers顯示這個(gè)驅(qū)動(dòng)名稱,probe會(huì)在I2C設(shè)備匹配后調(diào)用,不是發(fā)現(xiàn)I2C設(shè)備,即便實(shí)際上這個(gè)設(shè)備不在,但是代碼里注冊(cè)了這個(gè)設(shè)備,或者設(shè)備樹(shù)里配置了這個(gè)設(shè)備,就會(huì)被調(diào)用。

driver.of_match_table和 id_table兩個(gè)成員列出的是驅(qū)動(dòng)程序所能支持的所有設(shè)備,其中driver.of_match_table里的設(shè)備,是跟設(shè)備樹(shù)匹配的,id_table是跟靜態(tài)注冊(cè)是調(diào)用的struct i2c_board_info里的name做比較的。

示例代碼

驅(qū)動(dòng)注冊(cè):

static int __devinit zsl_i2c_drv_probe(struct i2c_client *client, const struct i2c_device_id *id)
{	
	struct property *pp = NULL;
	uint8_t buf[4];
	struct i2c_msg msgs[2] = {{0}, {0}};
	int len = sizeof(msgs) / sizeof(msgs[0]);

	printk(KERN_INFO "%s: %x\n",__func__,client->addr);

	pp = of_find_property(client->dev.of_node, "testdata", NULL);
	if (pp)
		printk(KERN_INFO "%s: %d:%s \n",__func__,pp->length,(char *)pp->value);
	
	dump_stack();

	if (client->adapter)
	{
		buf[0] = 0;
		buf[1] = 4;
		buf[2] = 0;
		buf[3] = 0;
		memset(msgs,0,sizeof(struct i2c_msg)*2);
		msgs[0].addr  = client->addr;
		msgs[0].flags = 0x0;
		msgs[0].len   = 2;
		msgs[0].buf   = buf;
		
		msgs[1].addr  = client->addr;
		msgs[1].flags = I2C_M_RD;
		msgs[1].len   = 4;
		msgs[1].buf   = buf;

		if (i2c_transfer(client->adapter, msgs,	len) == len)
			printk(KERN_INFO "zsl i2c_transfer r: %d:%x %x %x %x\n",len,buf[0],buf[1],buf[2],buf[3]);
		
		buf[0] = 0;
		buf[1] = 4;
		buf[2] = 7;
		buf[3] = 8;

		memset(msgs,0,sizeof(struct i2c_msg)*2);
		msgs[0].addr = client->addr;
		msgs[0].flags = 0;
		msgs[0].len = 4;
		msgs[0].buf = buf;
		
		if (i2c_transfer(client->adapter, msgs,	1) == 1)
			printk(KERN_INFO "zsl i2c_transfer w: %d:%x %x %x %x\n",1,buf[0],buf[1],buf[2],buf[3]);

		buf[0] = 0;
		buf[1] = 4;
		buf[2] = 0;
		buf[3] = 0;
		memset(msgs,0,sizeof(struct i2c_msg)*2);
		msgs[0].addr  = client->addr;
		msgs[0].flags = 0x0;
		msgs[0].len   = 2;
		msgs[0].buf   = buf;
		
		msgs[1].addr  = client->addr;
		msgs[1].flags = I2C_M_RD;
		msgs[1].len   = 4;
		msgs[1].buf   = buf;
		msleep(100);
		len = i2c_transfer(client->adapter, msgs, len);
		if (2 == len)
			printk(KERN_INFO "zsl i2c_transfer r: %d:%x %x %x %x\n",len,buf[0],buf[1],buf[2],buf[3]);				
	}
	
    return 0;
}
 
static void __devexit zsl_i2c_drv_remove(struct i2c_client *client)
{
	printk(KERN_INFO "%s: \n",__func__);
}
 
static const struct i2c_device_id zsl_dev_id_table[] = {
    { "zsl_i2c_dev", 0 },
    {}
};//這里的名字很重要,驅(qū)動(dòng)第一種匹配設(shè)備的方式要用到
 
static const struct of_device_id zsl_of_match_ids[] = {
	{ .compatible = "i2c_name,zsl",		.data = NULL },
	{ /* END OF LIST */ } //最后一項(xiàng)為空,用于判斷數(shù)組遍歷完成
};

static struct i2c_driver zsl_i2c_driver = {
    .driver        = {
        .name        = "zsl_i2c",
        .owner        = THIS_MODULE,
        .of_match_table = zsl_of_match_ids,//設(shè)備樹(shù)匹配用
    },
    .probe		= zsl_i2c_drv_probe,
    .remove		= __devexit_p(zsl_i2c_drv_remove),
    .id_table	= zsl_dev_id_table,  //設(shè)備樹(shù)不需要,i2c_register_board_info匹配使用
};

void zsl_i2c_drv_init(void)
{
    i2c_add_driver(&zsl_i2c_driver);
}

靜態(tài)設(shè)備注冊(cè)

static struct i2c_board_info zsl_i2c_dev = {
    I2C_BOARD_INFO("zsl_i2c_dev", 0x50),//這個(gè)名字很重要,用于匹配 I2C 驅(qū)動(dòng)
};

static struct i2c_client *zsl_i2c_client;

void zsl_i2c_dev_init(void)
{
       i2c_register_board_info(4, &zsl_i2c_dev, 1);
}

設(shè)備樹(shù)注冊(cè)

&i2c4 {
       zsli2c0: zsli2c@50 {
              compatible = "i2c_name,zsl";
              status = "okay";
              testdata = "asdfg";
              reg = <0x50>;
       };
};

運(yùn)行后probe就會(huì)被調(diào)用,無(wú)論配的是什么地址,0x50設(shè)備存在,0x60設(shè)備不存在,probe都能被調(diào)用,但是0x60的讀不到數(shù)據(jù)。

調(diào)用關(guān)系

probe里的堆棧打印如下:

從芯片廠家的I2C驅(qū)動(dòng)初始化接口rk3x_i2c_driver_init開(kāi)始,使用platform_driver_register接口注冊(cè)rk3x_i2c_driver,當(dāng)設(shè)備樹(shù)里有對(duì)應(yīng)的I2C總線時(shí),就會(huì)注冊(cè)I2C設(shè)備,匹配后調(diào)用這里的probe接口rk3x_i2c_probe。

rk3x_i2c_probe里會(huì)初始化 Rockchip I2C控制器,調(diào)用 i2c_register_adapter將 I2C 適配器注冊(cè)到內(nèi)核,進(jìn)而調(diào)用of_i2c_register_devices 掃描設(shè)備樹(shù),調(diào)用i2c_new_client_device創(chuàng)建配置的I2C設(shè)備。

i2c_new_client_device里會(huì)創(chuàng)建struct i2c_client并調(diào)用device_register注冊(cè)到內(nèi)核,觸發(fā) device_add,內(nèi)核會(huì)嘗試匹配驅(qū)動(dòng)(通過(guò) compatible 字符串或者name)。如果匹配成功,調(diào)用 i2c_device_probe到probe接口的zsl_i2c_drv_probe。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Linux下SVN服務(wù)器同時(shí)支持Apache的http和svnserve獨(dú)立服務(wù)器兩種模式且使用相同的訪問(wèn)權(quán)限賬號(hào)

    Linux下SVN服務(wù)器同時(shí)支持Apache的http和svnserve獨(dú)立服務(wù)器兩種模式且使用相同的訪問(wèn)權(quán)限賬號(hào)

    這篇文章主要介紹了Linux下SVN服務(wù)器同時(shí)支持Apache的http和svnserve獨(dú)立服務(wù)器兩種模式且使用相同的訪問(wèn)權(quán)限賬號(hào),需要的朋友可以參考下
    2015-07-07
  • Linux如何使用docker方式搭建SQL Server

    Linux如何使用docker方式搭建SQL Server

    這篇文章主要介紹了Linux如何使用docker方式搭建SQL Server問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Ubuntu無(wú)網(wǎng)絡(luò)連接及標(biāo)識(shí)的解決方法

    Ubuntu無(wú)網(wǎng)絡(luò)連接及標(biāo)識(shí)的解決方法

    本文已解決 Ubuntu無(wú)網(wǎng)絡(luò)連接/無(wú)網(wǎng)絡(luò)標(biāo)識(shí)解決方法的相關(guān)問(wèn)題,并總結(jié)提出了幾種可用解決方案,如果有遇到相同問(wèn)題的朋友可以參考閱讀下本文,對(duì)解決問(wèn)題有一定的幫助
    2024-09-09
  • 詳解Linux文件系統(tǒng):ext4及更高版本

    詳解Linux文件系統(tǒng):ext4及更高版本

    今天小編就為大家分享一篇關(guān)于Linux文件系統(tǒng):ext4及更高版本的詳解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-09-09
  • Linux虛擬機(jī)系統(tǒng)化部署母盤流程

    Linux虛擬機(jī)系統(tǒng)化部署母盤流程

    文章介紹了系統(tǒng)化部署母盤的原因和方法,包括配置vim個(gè)性化軟件倉(cāng)庫(kù)、自動(dòng)掛載光盤映像、配置網(wǎng)絡(luò)和關(guān)閉SELinux及防火墻
    2026-02-02
  • Linux之軟件包管理器yum詳解

    Linux之軟件包管理器yum詳解

    文章介紹了現(xiàn)代類Unix操作系統(tǒng)中軟件包管理和包存儲(chǔ)庫(kù)的工作原理,以及如何使用包管理器如yum來(lái)安裝、更新和卸載軟件,文章還介紹了如何配置yum源,更新系統(tǒng)軟件包和查看已安裝的軟件
    2025-01-01
  • CentOS---常用網(wǎng)絡(luò)配置詳解

    CentOS---常用網(wǎng)絡(luò)配置詳解

    本篇文章主要介紹了CentOS網(wǎng)絡(luò)配置詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。
    2016-12-12
  • 在CentOS上安裝nmap失敗的完整解決方案

    在CentOS上安裝nmap失敗的完整解決方案

    在CentOS/RHEL系統(tǒng)上安裝nmap失敗的問(wèn)題通常與軟件源配置或依賴關(guān)系有關(guān),以下是專業(yè)解決方案,包括修復(fù)軟件源配置、手動(dòng)安裝nmap、使用EPEL倉(cāng)庫(kù)和編譯安裝等方法,需要的朋友可以參考下
    2025-10-10
  • centos7利用yum安裝lnmp的教程(linux+nginx+php7.1+mysql5.7)

    centos7利用yum安裝lnmp的教程(linux+nginx+php7.1+mysql5.7)

    lnmp相信不用多介紹了,大家應(yīng)該都知道,下面這篇文章主要給大家介紹了關(guān)于centos7利用yum安裝lnmp(linux+nginx+php7.1+mysql5.7)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2018-03-03
  • Linux UDP網(wǎng)絡(luò)編程套接字sockets介紹

    Linux UDP網(wǎng)絡(luò)編程套接字sockets介紹

    文章主要講解了IP地址、端口號(hào)、Socket及TCP/UDP協(xié)議的基礎(chǔ)知識(shí),重點(diǎn)包括地址結(jié)構(gòu)、字節(jié)序轉(zhuǎn)換、網(wǎng)絡(luò)通信模型與實(shí)現(xiàn),強(qiáng)調(diào)Socket作為應(yīng)用層與網(wǎng)絡(luò)層交互的接口,以及TCP可靠傳輸與UDP高效但不可靠傳輸?shù)膮^(qū)別
    2025-08-08

最新評(píng)論

长岭县| 美姑县| 星座| 读书| 淳安县| 宝鸡市| 鸡泽县| 甘南县| 平遥县| 东海县| 宁波市| 朝阳市| 和龙市| 淮滨县| 资源县| 巴中市| 大余县| 来宾市| 龙江县| 沾益县| 双峰县| 孟津县| 乌兰浩特市| 府谷县| 奇台县| 屯昌县| 澄迈县| 大港区| 札达县| 南漳县| 徐汇区| 武清区| 平阳县| 宽甸| 屏山县| 恩施市| 佛冈县| 信宜市| 盘锦市| 郯城县| 香河县|