hid_info函数分析
昨天博文《linux下无线鼠标驱动执行流程》中有一行输出信息很让我迷惑,如下所示:
[ 3597.864715] generic-usb :1D57:0016.0006: input,hidraw2: USB HID v1. Mouse [HID Wireless Mouse HID Wireless Mouse] on usb-::1d.-1.2/input0
该行信息中最后 "input,hidraw2: USB HID v1.10 Mouse [HID Wireless Mouse HID Wireless Mouse] on usb-0000:00:1d.7-1.2/input0"这一部分内容
对应hid_info的第二个参数(位于drivers/hid/hid-core.c):
hid_info(hdev, "%s: %s HID v%x.%02x %s [%s] on %s\n", buf, bus, hdev->version >> , hdev->version & 0xff, type, hdev->name, hdev->phys)
但是该行前面的"generic-usb 0003:1D57:0016.0006:"却不知道是从哪儿生成的,因此我想追踪一下hid_info函数的执行过程。
hid_info定义如下(include/linux/hid.h):
#define hid_info(hid, fmt, arg...) \
dev_info(&(hid)->dev, fmt, ##arg)
而dev_info函数定义如下(include/linux/device.h):
#define dev_info(dev, fmt, arg...) _dev_info(dev, fmt, ##arg)
_dev_info函数定义如下(drivers/base/core.c):
#ifdef CONFIG_PRINTK int __dev_printk(const char *level, const struct device *dev,
struct va_format *vaf)
{
if (!dev)
return printk("%s(NULL device *): %pV", level, vaf); return printk("%s%s %s: %pV",
level, dev_driver_string(dev), dev_name(dev), vaf);
}
EXPORT_SYMBOL(__dev_printk); int dev_printk(const char *level, const struct device *dev,
const char *fmt, ...)
{
struct va_format vaf;
va_list args;
int r; va_start(args, fmt); vaf.fmt = fmt;
vaf.va = &args; r = __dev_printk(level, dev, &vaf);
va_end(args); return r;
}
EXPORT_SYMBOL(dev_printk); #define define_dev_printk_level(func, kern_level) \
int func(const struct device *dev, const char *fmt, ...) \
{ \
struct va_format vaf; \
va_list args; \
int r; \
\
va_start(args, fmt); \
\
vaf.fmt = fmt; \
vaf.va = &args; \
\
r = __dev_printk(kern_level, dev, &vaf); \
va_end(args); \
\
return r; \
} \
EXPORT_SYMBOL(func); define_dev_printk_level(dev_emerg, KERN_EMERG);
define_dev_printk_level(dev_alert, KERN_ALERT);
define_dev_printk_level(dev_crit, KERN_CRIT);
define_dev_printk_level(dev_err, KERN_ERR);
define_dev_printk_level(dev_warn, KERN_WARNING);
define_dev_printk_level(dev_notice, KERN_NOTICE);
define_dev_printk_level(_dev_info, KERN_INFO); #endif
上面这部分函数定义只有在定义CONFIG_PRINTK时才有效,需要查看内核配置文件是否有其定义.
查看当前内核配置:
$uname -a
Linux debian 3.2.---pae # SMP Debian 3.2.- i686 GNU/Linux
查看 /boot/config-3.2.0-4-686-pae文件中确实定义了CONFIG_RPINTK:
CONFIG_PRINTK=y
上面的函数定义实际上就是将最终调用下面内容:
printk("%s%s %s: %pV", KERN_INFO, dev_driver_string(dev), dev_name(dev), vaf);
KERN_INFO定义如下(include/linux/printk.h):
#define KERN_INFO "<6>" /* informational */
dev_driver_string定义如下(drivers/base/core.c):
const char *dev_driver_string(const struct device *dev)
{
struct device_driver *drv; /* dev->driver can change to NULL underneath us because of unbinding,
* so be careful about accessing it. dev->bus and dev->class should
* never change once they are set, so they don't need special care.
*/
drv = ACCESS_ONCE(dev->driver);
return drv ? drv->name :
(dev->bus ? dev->bus->name :
(dev->class ? dev->class->name : ""));
}
EXPORT_SYMBOL(dev_driver_string);
dev_name函数定义如下(include/linux/device.h):
static inline const char *dev_name(const struct device *dev)
{
/* Use the init name until the kobject becomes available */
if (dev->init_name)
return dev->init_name; return kobject_name(&dev->kobj);
}
dev_driver_string获取驱动的字符串,最终使用的驱动是usbhid,其定义如下(drivers/hid/usbhid/hid-core.c):
static struct hid_driver hid_usb_driver = {
.name = "generic-usb",
.id_table = hid_usb_table,
};
所以驱动名称就是generic-usb。
而dev_name中则查看其init_name的值是否为空,如果不为空返回init_name,如果为空,则返回其kobj的名称。
此处init_name为空(默认值为NULL,在源代码中也没有找到相关的赋值),所以使用的是kobj的名称。
在函数hid_add_device(drivers/hid/hid-core.c)中有下面的代码:
dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus,
hdev->vendor, hdev->product, atomic_inc_return(&id));
该行代码将kobj的值设定成总线、vendor、product以及id连接成的字符串。
从我的前一篇博文中提到vendor和product分别是0x1d57和0x0016,此处使用%04X,那么中间的vendor和product
应该分别是1D57和0016,这与上面的输出信息是一致的。
hid_info函数大致执行流程就这样,但是我还是没弄清楚usbhid和hid模块之间是如何有机联系起来的,等到对usb模块
有了更深入了解后再回头来看二者之间的联系。
hid_info函数分析的更多相关文章
- split(),preg_split()与explode()函数分析与介
split(),preg_split()与explode()函数分析与介 发布时间:2013-06-01 18:32:45 来源:尔玉毕业设计 评论:0 点击:965 split()函数可以实 ...
- string函数分析
string函数分析string函数包含在string.c文件中,经常被C文件使用.1. strcpy函数原型: char* strcpy(char* str1,char* str2);函数功能: 把 ...
- start_amboot()函数分析
一.整体流程 start_amboot()函数是执行完start.S汇编文件后第一个C语言函数,完成的功能自然还是初始化的工作 . 1.全局变量指针r8设定,以及全局变量区清零 2.执行一些类初始化函 ...
- uboot的jumptable_init函数分析
一.函数说明 函数功能:安装系统函数指针 函数位置:common/exports.c 二.函数分析 void jumptable_init (void) { int i; gd->jt = (v ...
- Linux-0.11内核源代码分析系列:内存管理get_free_page()函数分析
Linux-0.11内存管理模块是源码中比較难以理解的部分,如今把笔者个人的理解发表 先发Linux-0.11内核内存管理get_free_page()函数分析 有时间再写其它函数或者文件的:) /* ...
- 31.QPainter-rotate()函数分析-文字旋转不倾斜,图片旋转实现等待
在上章和上上上章: 28.QT-QPainter介绍 30.QT-渐变之QLinearGradient. QConicalGradient.QRadialGradient 学习了QPainter基础绘 ...
- 如何验证一个地址可否使用—— MmIsAddressValid函数分析
又是一篇内核函数分析的博文,我个人觉得Windows的内核是最好的老师,当你想实现一个功能之前可以看看Windows内核是怎么做的,说不定就有灵感呢:) 首先看下官方的注释说明: /*++ Routi ...
- STM32F10X固件库函数——串口清状态位函数分析
STM32F10X固件库函数——串口清状态位函数分析 最近在测试串口热插拔功能的时候,意外发现STM32F10X的串口库函数中,清理串口状态位函数稍稍有点不解.下面是改函数的源码: /******** ...
- 常用string函数分析
string函数分析string函数包含在string.c文件中,经常被C文件使用.1. strcpy函数原型: char* strcpy(char* str1,char* str2);函数功能: 把 ...
随机推荐
- android电话状态的监听
电话状态的监听: /*** * 继承PhoneStateListener类,我们能够又一次其内部的各种监听方法 然后通过手机状态改变时,系统自己主动触发这些方法来实现我们想要的功能 */ class ...
- (二)spark算子 分为3大类
transgormation的算子对key-value类型的数据有三种: (1)输入 与 输出为一对一关系 mapValue();针对key-value类型的数据并只对其中的value进行操作,不对 ...
- FILE 创建
public class CreateDelFileUtils implements Serializable{ /** * */ private static final long serialVe ...
- 【Python+selenium Wendriver API】之下拉框定位
上代码: # coding:utf-8 from selenium import webdriver from selenium.webdriver.common.action_chains impo ...
- gen_server2 与gen_server的对比
在erlang杀手级应用rabbitmq中,不难发现,有一个gen_server2.erl模块.而在rabbitmq中,gen_server2.erl是对gen_server.erl模块的重写. Ra ...
- 嵌入式开发之字符叠加---gb2313 国标码,utf8 国际码,unicode 无码
(1)国标码简介 (2)编码转换 (3)时间获取 (4)显示切换 最近做了个字符叠加,包括时间叠加,字符中文叠加,位置移动,等功能开启.因为一般的字符叠加的点阵式16位,然后填充着16位的编码是gb2 ...
- git入门五(分支合并冲突和衍合)
分支合并冲突的处理 合并分支的冲突时在不同的分支中修改了同一个文件的同一部分,程序无法把两份有差异的文件合并,这时候需要人为的干预解决冲突.当前处于master 分支,当dev 分支和master ...
- XtraBackup全备与增量备份
一.XtraBackup安装 下载地址:http://www.percona.com/downloads/XtraBackup/XtraBackup-2.2.8/source/ 安装步骤: ===== ...
- 2016 acm香港网络赛 F题. Crazy Driver(水题)
原题网址:https://open.kattis.com/problems/driver Crazy Driver In the Linear City, there are N gates arra ...
- python tensorflow 学习
Tensorflow系列——Saver的用法:http://blog.csdn.net/u011500062/article/details/51728830 Tensorflow学习系列(二): t ...