usb摄像头驱动-core层usb设备的注册

news2025/1/18 6:46:34

usb摄像头驱动-core层driver.c


文章目录

  • usb摄像头驱动-core层driver.c
  • usb_bus_type
    • usb_device_match
    • usb_uevent
  • usb_register_driver


在这里插入图片描述

在这里插入图片描述

在ubuntu中接入罗技c920摄像头打印的信息如下:
在这里插入图片描述

在内核中,/driver/usb/core/driver.c 文件扮演了 USB 核心驱动程序管理的重要角色。该文件包含了 USB 核心驱动程序的实现,负责管理和调度 USB 设备的注册、匹配、连接和断开等操作。
具体而言,driver.c 文件的功能和作用包括:
USB 驱动程序的注册和注销:该文件实现了 usb_register_driver 和 usb_deregister_driver 函数,用于注册和注销 USB 驱动程序。

USB 设备的匹配和连接:通过实现 usb_match_id 函数和 usb_probe_interface 函数,该文件负责在 USB 子系统中进行设备的匹配和连接。当 USB 设备插入时,USB 核心会调用 usb_probe_interface 函数,以便驱动程序对设备进行初始化和配置。

USB 设备的断开和注销:通过实现 usb_disconnect 函数和 usb_remove_interface 函数,该文件负责在 USB 设备断开时执行相应的操作。当 USB 设备断开连接时,USB 核心会调用 usb_disconnect 函数,以便驱动程序对设备进行清理和注销。

驱动程序与 USB 接口的关联:通过实现 usb_register_interface 和 usb_deregister_interface 函数,该文件负责将驱动程序与 USB 接口进行关联。这样,在 USB 设备连接时,USB 核心可以根据驱动程序与接口的关联关系,选择正确的驱动程序来处理设备。

USB 驱动程序的挂起和恢复:通过实现 usb_suspend_interface 和 usb_resume_interface 函数,该文件处理 USB 设备的挂起和恢复操作。当 USB 设备进入挂起状态或从挂起状态恢复时,USB 核心会调用相应的函数通知驱动程序执行相应的操作。

总结起来,/driver/usb/core/driver.c 文件在内核中扮演了 USB 核心驱动程序管理的关键角色。它实现了 USB 驱动程序的注册、匹配、连接和断开等功能,负责与 USB 子系统协作,管理 USB 设备的初始化、配置和操作等操作。该文件的功能对于整个 USB 子系统的正常运行至关重要。

usb_bus_type

在/driver/usb/core/driver.c文件中,下面的内容定义了一个名为usb_bus_type的struct bus_type结构体,并对其成员进行了初始化。该结构体用于表示USB总线类型,并定义了与USB总线相关的操作。
具体来说,下面的内容的作用如下:
.name = “usb”:设置总线类型的名称为"usb",用于标识USB总线。
.match = usb_device_match:指定匹配函数为
usb_device_match。匹配函数用于在插入USB设备时判断该设备是否与该总线类型的驱动程序匹配。
.uevent = usb_uevent:指定uevent函数为
usb_uevent。uevent函数用于生成和发送与USB设备插入和拔出相关的uevent事件。
这些成员的初始化可以使USB核心了解USB总线类型,并在需要的时候调用相应的函数,从而实现与USB总线相关的操作和事件处理。
在实际使用中,USB总线类型结构体usb_bus_type会与具体的USB驱动程序进行关联,以便在USB设备插入和拔出时触发相应的操作。这样,当有新的USB设备插入时,USB核心会调用匹配函数进行驱动程序的匹配,并根据匹配结果调用相应的probe函数来初始化和配置驱动程序与设备的连接。同时,uevent函数可以生成和发送uevent事件,通知用户空间有关USB设备的信息变化。

/* USB总线类型结构体 */
struct bus_type usb_bus_type = {
    /* 名称 */
    .name =     "usb",
    /* 匹配函数 */
    .match =    usb_device_match,
    /* uevent函数 */
    .uevent =   usb_uevent,
};

usb_device_match

static int usb_device_match(struct device *dev, struct device_driver *drv)
{
    /* devices and interfaces are handled separately */
    if (is_usb_device(dev)) { // 如果是 USB 设备

        /* interface drivers never match devices */
        if (!is_usb_device_driver(drv)) // 如果不是 USB 设备驱动
            return 0;

        /* TODO: Add real matching code */ // TODO: 添加真正的匹配代码
        return 1;

    } else if (is_usb_interface(dev)) { // 如果是 USB 接口
        struct usb_interface *intf;
        struct usb_driver *usb_drv;
        const struct usb_device_id *id;

        /* device drivers never match interfaces */
        if (is_usb_device_driver(drv)) // 如果是 USB 设备驱动
            return 0;

        intf = to_usb_interface(dev); // 获取 USB 接口
        usb_drv = to_usb_driver(drv); // 获取 USB 驱动

        id = usb_match_id(intf, usb_drv->id_table); // 匹配 USB 设备 ID
        if (id)
            return 1;

        id = usb_match_dynamic_id(intf, usb_drv); // 匹配动态 USB 设备 ID
        if (id)
            return 1;
    }

    return 0;
}

该函数的作用是判断USB设备和设备驱动是否匹配,用于设备与驱动之间的匹配过程。
函数的主要步骤如下:
首先判断设备类型,如果是USB设备,则执行设备匹配逻辑;如果是USB接口,则执行接口匹配逻辑。
如果是USB设备,首先判断驱动类型是否为USB设备驱动。如果是USB设备驱动,返回0,表示设备和驱动不匹配。如果不是USB设备驱动,执行后续的实际匹配代码(TODO:此处需要添加真正的匹配代码),并返回1表示设备和驱动匹配。
如果是USB接口,首先获取USB接口和USB驱动的相关信息。然后调用
usb_match_id函数,通过USB设备ID表来匹配USB设备ID。如果匹配成功,返回1表示设备和驱动匹配。如果未匹配成功,调用
usb_match_dynamic_id函数,通过动态USB设备ID匹配来匹配设备和驱动。如果匹配成功,返回1表示设备和驱动匹配。
如果以上都不匹配,则返回0表示设备和驱动不匹配。
该函数在USB核心中用于设备和驱动的匹配过程。当有USB设备或接口与设备驱动进行匹配时,USB核心会调用该函数来判断设备和驱动是否匹配,从而确定是否加载对应的驱动程序。

usb_uevent

static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
{
    struct usb_device *usb_dev;

    if (is_usb_device(dev)) { // 如果是 USB 设备
        usb_dev = to_usb_device(dev); // 获取 USB 设备
    } else if (is_usb_interface(dev)) { // 如果是 USB 接口
        struct usb_interface *intf = to_usb_interface(dev); // 获取 USB 接口
        usb_dev = interface_to_usbdev(intf); // 获取 USB 设备
    } else {
        return 0; // 如果不是 USB 设备或 USB 接口,返回 0
    }

    if (usb_dev->devnum < 0) { // 如果设备号小于 0
        /* driver is often null here; dev_dbg() would oops */
        pr_debug("usb %s: already deleted?\n", dev_name(dev)); // 打印调试信息
        return -ENODEV; // 返回错误码
    }
    if (!usb_dev->bus) { // 如果设备总线不存在
        pr_debug("usb %s: bus removed?\n", dev_name(dev)); // 打印调试信息
        return -ENODEV; // 返回错误码
    }

    /* per-device configurations are common */ // 常见的每个设备的配置
    if (add_uevent_var(env, "PRODUCT=%x/%x/%x",
               le16_to_cpu(usb_dev->descriptor.idVendor),
               le16_to_cpu(usb_dev->descriptor.idProduct),
               le16_to_cpu(usb_dev->descriptor.bcdDevice))) // 添加设备信息
        return -ENOMEM; // 返回错误码

    /* class-based driver binding models */ // 基于类的驱动程序绑定模型
    if (add_uevent_var(env, "TYPE=%d/%d/%d",
               usb_dev->descriptor.bDeviceClass,
               usb_dev->descriptor.bDeviceSubClass,
               usb_dev->descriptor.bDeviceProtocol)) // 添加设备类型信息
        return -ENOMEM; // 返回错误码

    return 0; // 返回成功
}

该函数的作用是处理USB设备的uevent事件,即生成与USB设备插入和拔出相关的环境变量,并将其添加到uevent环境中。
函数的主要步骤如下:
判断设备类型,如果是USB设备,则获取USB设备;如果是USB接口,则获取对应的USB设备。
检查设备号和设备总线的有效性。如果设备号小于0或设备总线不存在,打印调试信息并返回错误码。
通过
add_uevent_var函数将设备的产品信息(vendor ID、product ID和device version)添加到uevent环境中。
通过
add_uevent_var函数将设备的类型信息(device class、device subclass和device protocol)添加到uevent环境中。
返回成功。
该函数在USB核心中起到了生成与USB设备插入和拔出相关的uevent事件的作用。当有USB设备插入或拔出时,USB核心会调用该函数来获取设备的相关信息,并生成相应的uevent事件,通知用户空间进行设备的动态管理和配置

usb_register_driver

/driver/usb/core/driver.c
函数 usb_register_driver 用于注册一个 USB 驱动程序,并将其与 USB 子系统进行关联。它的作用是告诉 USB 子系统,有一个新的驱动程序可用于管理特定类型的 USB 设备。
该函数的参数包括:
new_driver:指向 usb_driver 结构的指针,表示要注册的驱动程序。
owner:指向驱动程序所属内核模块的指针,通常是使用 THIS_MODULE 宏。
mod_name:表示驱动程序所属模块的名称,用于标识该驱动程序。
usb_register_driver 函数在驱动程序初始化阶段调用,通常在驱动程序的入口点函数中使用。当驱动程序调用 usb_register_driver 注册成功后,USB 子系统会将该驱动程序添加到其驱动程序列表中,并在有匹配的 USB 设备插入时调用该驱动程序的相应回调函数。
驱动程序注册后,USB 子系统会与该驱动程序进行协作,以匹配和管理符合驱动程序定义的设备。当插入符合驱动程序定义的 USB 设备时,USB 子系统会调用驱动程序中的回调函数来执行设备的初始化、配置、数据传输和管理等操作。
总结起来,usb_register_driver 函数的作用是将一个 USB 驱动程序注册到 USB 子系统中,以便USB子系统能够调用驱动程序的相应回调函数来管理特定类型的USB设备。通常在驱动程序初始化阶段调用该函数。

int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
            const char *mod_name)
{
    int retval = 0;

    if (usb_disabled())
        return -ENODEV;

    // 设置驱动的相关信息
    new_driver->drvwrap.for_devices = 0; // 0表示注册的是接口驱动
    new_driver->drvwrap.driver.name = new_driver->name; // 驱动名
    new_driver->drvwrap.driver.bus = &usb_bus_type; // 驱动所属总线
    new_driver->drvwrap.driver.probe = usb_probe_interface; // 探测函数
    new_driver->drvwrap.driver.remove = usb_unbind_interface; // 卸载函数
    new_driver->drvwrap.driver.owner = owner; // 模块所有者
    new_driver->drvwrap.driver.mod_name = mod_name; // 模块名
    spin_lock_init(&new_driver->dynids.lock); // 初始化动态ID锁
    INIT_LIST_HEAD(&new_driver->dynids.list); // 初始化动态ID链表

    // 注册驱动
    retval = driver_register(&new_driver->drvwrap.driver);
    if (retval)
        goto out;

    // 创建新ID文件
    retval = usb_create_newid_files(new_driver);
    if (retval)
        goto out_newid;

    pr_info("%s: registered new interface driver %s\n",
            usbcore_name, new_driver->name);

out:
    return retval;

out_newid:
    driver_unregister(&new_driver->drvwrap.driver);

    printk(KERN_ERR "%s: error %d registering interface "
            "   driver %s\n",
            usbcore_name, retval, new_driver->name);
    goto out;
}
EXPORT_SYMBOL_GPL(usb_register_driver);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/556853.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

复现ms17-010漏洞

复现ms17-010 复现条件环境操作效果 让我们来看看“hkl”在干嘛 复现 条件 1.靶机必须为win8以下。 2.靶机必须同攻击机处于相同网段&#xff08;即倒数第二位相同&#xff09;。 3.靶机的445端口必须要开启。 环境 虚拟机kali为攻击机&#xff0c;win7虚拟机为靶机。 kali…

SELECT LAST_INSERT_ID()自增主键冲突或者为0问题

问题 数据库为mysql&#xff1b; mapper.xml文件为mybatis-generator自动生成的&#xff1b; 连接池使用DruidDataSource&#xff1b; 最终生成的insertSelective如下&#xff1a; 出现问题&#xff1a; 主键冲突&#xff1a;[WMyBatisTraceInterceptor:54][com.mysql.jdbc.…

如何定位OOM

造成OOM的原因 定位OOM 针对第一和第二种情况需要定位OOM 系统已经挂了&#xff1a; 通过堆dump文件定位。 当JVM发生OOM时&#xff0c;自动生成DUMP文件&#xff1a; -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath${目录} java -Xms10M -Xmx10M -XX:HeapDumpOnOutOfMemo…

c#中的json数据

JSON数据 数据传输的语言&#xff0c;用于前后端数据交互的语言&#xff0c;注意xml的区别。 json和xml的区别 xml&#xff1a;可扩展标记语言&#xff0c;是一种用于标记电子文件使其具有结构性的标记语言。 json&#xff1a;(JavaScript Object Notation, JS 对象简谱) 是…

昆仲被投企业「鲲游光电」近期完成新一轮数亿元融资,继续致力于探索前沿光电子领域产品与创新应用|昆仲·链

鲲游光电(North Ocean Photonics)是专注于晶圆级光学、光集成领域的高科技企业&#xff0c;总部位于中国上海。依托自身深厚的技术积累、高精度的制造工艺&#xff0c;鲲游光电通过融合集成光学与集成电路的创新思路&#xff0c;致力于探索前沿光子、光电子领域的实现与创新应用…

MyBatis环境搭建配置、增删改查操作、分页、事务操作、动态SQL、缓存机制、注解开发

MyBatis 文章目录 MyBatisXML语言简介用途各部分注解声明元素属性注释CDATA转义字符 搭建环境读取实体类创建实体与映射关系的文件 配置MyBatis创建工具类接口实现 Mybatis工作流程增删改查指定映射规则指定构造方法字段名称带下划线处理条件查询插入数据复杂查询和事务一对多查…

Codeforces Round 860 (Div. 2)

A Showstopper 题意&#xff1a;给你两个长度为n的数组a和b&#xff0c;每次操作你可以互换a[i]与b[i]&#xff0c;问最终能否满足 思路&#xff1a;若a[i]>b[i]&#xff0c;我们就进行操作。这样数组b元素都是较大的&#xff0c; 一定比不操作更优。最后判断是否满足条件…

Python中的异常处理机制

什么是异常与异常处理 异常就是错误 异常会导致程序崩溃并停止运行 能监控并捕获到异常&#xff0c;将异常部位的程序进行修理使得程序继续正常运行 异常的语法结构 try:<代码块1> 被try关键字检查并保护的业务代码except <异常的类型>:<代码块2> # 代码…

Mybatis源码细节探究:sqlSessionFactory.openSession()这个方法到底发生了什么?

给自己的每日一句 不从恶人的计谋&#xff0c;不站罪人的道路&#xff0c;不坐亵慢人的座位&#xff0c;惟喜爱耶和华的律法&#xff0c;昼夜思想&#xff0c;这人便为有福&#xff01;他要像一棵树栽在溪水旁&#xff0c;按时候结果子&#xff0c;叶子也不枯干。凡他所做的尽…

【笔记】【Javascript】浅面了解原型和原型链

前言 原型和原型链是学习前端必备知识笔记中有些个人理解后整理的笔记&#xff0c;可能有所偏差&#xff0c;也恳请读者帮忙指出&#xff0c;谢谢。 免责声明 为了方便&#xff0c;本文中使用的部分图片来自于网络&#xff0c;如有侵权,请联系博主进行删除&#xff0c;感谢其…

C++ 二分查找法 LeetCode:704. 二分查找

class Solution { public:int search(vector<int>& nums, int target) {int length nums.size();//计算容器长度int left 0;//0int right length-1;//5int middle 0;/*while(left<right){middle (leftright)/2;//middle (leftright)>>1;if(nums[middl…

mysql子查询嵌套

目录 前言 一、实际需求解决 1.方式1&#xff1a;自连接 2.方式2&#xff1a;子查询 二、单行子查询 1.操作符子查询 三、相关子查询 四、自定义语句 五、子查询的问题 1.空值问题 2.非法使用子查询 六、多行子查询 七、聚合函数的嵌套使用 八、多行子查询空值问题…

Python爬虫实战——获取指定博主所有专栏链接及博文链接

Python爬虫实战——获取指定博主所有专栏链接及博文链接 0. 前言1. 第三方库的安装2. 代码3. 演示效果 0. 前言 本节学习使用爬虫来爬取指定csdn用户的所有专栏下的文章 操作系统&#xff1a;Windows10 专业版 开发环境&#xff1a;Pycahrm Comunity 2022.3 Python解释器版…

带你学C带你飞-P16拾遗

自增运算符 #include <stdio.h> int main() {int i5,j;j i;printf("i%d,j%d",i,j);i5;ji;printf("i%d,j%d",i,j); }i:先使用i的值&#xff0c;再对i自身进行加一 i&#xff1a;先对i自身加一&#xff0c;再赋值给j 逗号运算符 条件运算符 三目运…

【Linux】冯诺依曼体系结构、操作系统概念、进程概念

文章目录 前言一、冯诺依曼体系结构1.简介冯诺依曼体系2.CPU3.存储器3.IO&#xff08;输入输出&#xff09;4.总结 二、操作系统&#xff08;OS&#xff09;1.操作系统是什么&#xff1f;2.为什么有操作系统&#xff1f;&#xff08;功能&#xff09;3.操作系统如何实现功能&am…

MySQL之触发器相关操作

1. 概念 触发器&#xff0c;就是⼀种特殊的存储过程。触发器和存储过程⼀样是⼀个能够完成特定功能、存储 在数据库服务器上的SQL⽚段&#xff0c;但是触发器⽆需调⽤&#xff0c;当对数据表中的数据执⾏DML操作时 ⾃动触发这个SQL⽚段的执⾏&#xff0c;⽆需⼿动调⽤。 在MyS…

前端食堂技术周刊第 83 期:TS 5.1 RC、Nuxt 3.5、INP、Kinp、管理 GitHub 通知、WebXR

By Midjournery 美味值&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f; 口味&#xff1a;杏花乌龙拿铁 食堂技术周刊仓库地址&#xff1a;https://github.com/Geekhyt/weekly 本期摘要 TypeScript 5.1 RCNuxt 3.5INP 将成为新的 Core Web…

【LeetCode232】用栈模拟实现队列

你好&#xff0c;欢迎来到我的博客&#xff01;作为一名程序员&#xff0c;我经常刷LeetCode题目来提升自己的编程能力。在我的博客里&#xff0c;我会分享一些我自己做过的题目和解题思路&#xff0c;希望能够帮助到大家。今天&#xff0c;我想和大家分享一道挑战性较高的题目…

【牛客刷题专栏】0x29:JZ31 栈的压入、弹出序列(C语言编程题)

前言 个人推荐在牛客网刷题(点击可以跳转)&#xff0c;它登陆后会保存刷题记录进度&#xff0c;重新登录时写过的题目代码不会丢失。个人刷题练习系列专栏&#xff1a;个人CSDN牛客刷题专栏。 题目来自&#xff1a;牛客/题库 / 在线编程 / 剑指offer&#xff1a; 目录 前言问…

周赛346(括号匹配问题变形、双指针、模拟/打表预处理+DFS)

文章目录 周赛346[2696. 删除子串后的字符串最小长度](https://leetcode.cn/problems/minimum-string-length-after-removing-substrings/)暴力模拟使用栈 [2697. 字典序最小回文串](https://leetcode.cn/problems/lexicographically-smallest-palindrome/)双指针 [2698. 求一个…