hid-ft260驱动学习笔记 2 - probe

目录

1. 结构体ft260_device

2. hid设备的初始化

3. ft260初始化


上一节中有讲到ft260_driver的结构体,其中成员函数probe就是这个probe函数。

static struct hid_driver ft260_driver = {
	.name		= "ft260",
	.id_table	= ft260_devices,
	.probe		= ft260_probe,
	.remove		= ft260_remove,
	.raw_event	= ft260_raw_event,
};

当设备插入系统,系统通过id_table判断设备是否符合当前驱动,符合则调用probe函数。

static const struct hid_device_id ft260_devices[] = {
	{ HID_USB_DEVICE(USB_VENDOR_ID_FUTURE_TECHNOLOGY,
			 USB_DEVICE_ID_FT260) },
	{ /* END OF LIST */ }
};

这里对应FT260的VID和PID。

1. 结构体ft260_device

这个结构体用于表示本设备,这是内核驱动常规的写法。在probe函数里面会动态分配一个该结构的指针空间。

struct ft260_device *dev;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);

kzalloc函数用于分配内存,sizeof(*dev)获取dev类型的大小,GFP_KERNEL表示在内核模式下分配内存。

该指针会存储到hdev的私有数据区域,同时该指针的私有数据区域hdev也保存HID的设备结构体hdev。

hid_set_drvdata(hdev, dev);
dev->hdev = hdev;

ft260_probe的参数struct hid_device *hdev会贯穿所有的api函数,所以在其他函数这个参数就可以实现各个函数之间参数的传递。

2. hid设备的初始化

先判断hid设备是不是USB设备。

if (!hid_is_usb(hdev))
    return -EINVAL;

接着解析hid设备的报告描述符,将解析的结果保存在hdev指向的数据结构中。

ret = hid_parse(hdev);
if (ret) {
	hid_err(hdev, "failed to parse HID\n");
	goto hid_fail;
}

然后启动hid设备的硬件

ret = hid_hw_start(hdev, 0);
if (ret) {
	hid_err(hdev, "failed to start HID HW\n");
	goto hid_fail;
}

在Linux源码里面查看这个函数:

/**
 * hid_hw_start - start underlying HW
 * @hdev: hid device
 * @connect_mask: which outputs to connect, see HID_CONNECT_*
 *
 * Call this in probe function *after* hid_parse. This will setup HW
 * buffers and start the device (if not defeirred to device open).
 * hid_hw_stop must be called if this was successful.
 */
int hid_hw_start(struct hid_device *hdev, unsigned int connect_mask)

connect_mask为0则表示没有链接需求。

最后是打开该hid设备

ret = hid_hw_open(hdev);
if (ret) {
	hid_err(hdev, "failed to open HID HW\n");
	goto err_hid_stop;
}

打开成功后就能够读写这个设备了。

3. ft260初始化

先通过ft260_hid_feature_report_get获取芯片版本号,需要查看FT260的AN_394手册4.4.1 CHip Version了解细节

ret = ft260_hid_feature_report_get(hdev, FT260_CHIP_VERSION,
				   (u8 *)&version, sizeof(version));
if (ret < 0) {
	hid_err(hdev, "failed to retrieve chip version\n");
	goto err_hid_close;
}

hid_info(hdev, "chip code: %02x%02x %02x%02x\n",
	version.chip_code[0], version.chip_code[1],
	version.chip_code[2], version.chip_code[3]);

再通过ft260_get_interface_type获取到当前设备的接口类型,

static int ft260_get_interface_type(struct ft260_device *dev,
    struct ft260_get_system_status_report *cfg)

这个属于FT260内部定义的命令,需要查看FT260的AN_394手册4.4.2 Get System Status了解细节,其实就是读入26个字节

struct ft260_get_system_status_report {
	u8 report;		/* FT260_SYSTEM_SETTINGS */
	u8 chip_mode;		/* DCNF0 and DCNF1 status, bits 0-1 */
	u8 clock_ctl;		/* 0 - 12MHz, 1 - 24MHz, 2 - 48MHz */
	u8 suspend_status;	/* 0 - not suspended, 1 - suspended */
	u8 pwren_status;	/* 0 - FT260 is not ready, 1 - ready */
	u8 i2c_enable;		/* 0 - disabled, 1 - enabled */
	u8 uart_mode;		/* 0 - OFF; 1 - RTS_CTS, 2 - DTR_DSR, */
				/* 3 - XON_XOFF, 4 - No flow control */
	u8 hid_over_i2c_en;	/* 0 - disabled, 1 - enabled */
	u8 gpio2_func;		/* 0 - GPIO,  1 - SUSPOUT, */
				/* 2 - PWREN, 4 - TX_LED */
	u8 gpioa_func;		/* 0 - GPIO, 3 - TX_ACTIVE, 4 - TX_LED */
	u8 gpiog_func;		/* 0 - GPIO, 2 - PWREN, */
				/* 5 - RX_LED, 6 - BCD_DET */
	u8 suspend_out_pol;	/* 0 - active-high, 1 - active-low */
	u8 enable_wakeup_int;	/* 0 - disabled, 1 - enabled */
	u8 intr_cond;		/* Interrupt trigger conditions */
	u8 power_saving_en;	/* 0 - disabled, 1 - enabled */
	u8 reserved[10];
} __packed;

ret = ft260_get_system_config(hdev, cfg);
if (ret < 0)
	return ret;

由于FT260可以硬件上配置为3种模式:仅UART、仅I2C和两者都有,所以需要通过chip_mode判断当前接口是哪种模式

switch (cfg->chip_mode) {
case FT260_MODE_ALL:
case FT260_MODE_BOTH:
	if (dev->iface_id == 1)
		ret = FT260_IFACE_UART;
	else
		ret = FT260_IFACE_I2C;
	break;
case FT260_MODE_UART:
	ret = FT260_IFACE_UART;
	break;
case FT260_MODE_I2C:
	ret = FT260_IFACE_I2C;
	break;
}

当两者都有的模式时,FT260在系统里面会有2个接口,一个是UART,另一个则为I2C。

最后就是根据模式选择不同的probe。

if (ret == FT260_IFACE_I2C)
	ret = ft260_i2c_probe(dev, &cfg);
else
	ret = ft260_uart_probe(dev, &cfg);
if (ret)
	goto err_hid_close;

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

服务器本地部署文件服务器minio

minio类似于阿里云的OSS&#xff0c;为不方便把图、文、日志等形式的文件保存在公有云上的&#xff0c;可以在自己的服务器上部署文件服务器 看过本人前几个文章的&#xff0c;使用docker就会很快上手部署&#xff0c;直接上所有代码 #添加镜像 docker search minio docker p…

jvm 03 JVM的运行时数据区域 ,(类常量池,运行时常量池,字符串常量池这个三个的区别),操作系统内存模型JMM和JVM的内存模型联系

方法区在jdk8后&#xff0c;改成元空间 JVM内存模型&#xff1a; JMM 主内存&#xff1a;本地方法区和堆 工作内存&#xff1a;私有的工作栈 其实一个JVM内存模型&#xff08;主要就是运行时数据区域&#xff09;一个Java进程的JMM&#xff0c;工作内存JVM中线程的内存区域…

关于umjs的主题切换实现

注意本文写作日期2024年7月7日&#xff0c;我目前是最新版本的 注意&#xff1a;该功能仅 antd v5 可用 最后目标实现 先说一下&#xff0c;umijs布局默认是内置ant-design/pro-layout布局写的 看一下官网ProLayout - 高级布局和布局与菜单 直接在app.tsx加入以下&#xff…

Git管理源代码、git简介,工作区、暂存区和仓库区,git远程仓库github,创建远程仓库、配置SSH,克隆项目

学习目标 能够说出git的作用和管理源代码的特点能够如何创建git仓库并添加忽略文件能够使用add、commit、push、pull等命令实现源代码管理能够使用github远程仓库托管源代码能够说出代码冲突原因和解决办法能够说出 git 标签的作用能够使用使用git实现分支创建&#xff0c;合并…

磐维2.0数据库日常维护

磐维数据库简介 “中国移动磐维数据库”&#xff08;ChinaMobileDB&#xff09;&#xff0c;简称“磐维数据库”&#xff08;PanWeiDB&#xff09;。是中国移动信息技术中心首个基于中国本土开源数据库打造的面向ICT基础设施的自研数据库产品。 其产品内核能力基于华为 OpenG…

pyrender 离线渲染包安装教程

pyrender 离线渲染包安装教程 安装 安装 官方安装教程:https://pyrender.readthedocs.io/en/latest/install/index.html#installmesa 首先 pip install pyrenderclang6.0安装 下载地址:https://releases.llvm.org/download.html#6.0.0 注意下好是叫&#xff1a;clangllvm-6…

L04_MySQL知识图谱

这些知识点你都掌握了吗&#xff1f;大家可以对着问题看下自己掌握程度如何&#xff1f;对于没掌握的知识点&#xff0c;大家自行网上搜索&#xff0c;都会有对应答案&#xff0c;本文不做知识点详细说明&#xff0c;只做简要文字或图示引导。 1 基础 1.1内部组件结构 1.2 数据…

尚品汇-(十四)

&#xff08;1&#xff09;提交git 商品后台管理到此已经完成&#xff0c;我们可以把项目提交到公共的环境&#xff0c;原来使用svn&#xff0c;现在使用git 首先在本地创建ssh key&#xff1b; 命令&#xff1a;ssh-keygen -t rsa -C "your_emailyouremail.com" I…

用kimi实现一键实体识别与关系抽取

实体识别与关系抽取是自然语言处理&#xff08;NLP&#xff09;中的两个重要任务&#xff0c;通常被视为知识图谱构建的基础技术。 实体识别&#xff08;Named Entity Recognition, NER&#xff09;&#xff1a; 实体识别的目标是从文本中识别出具有特定意义的实体&#xff0…

动手学深度学习(Pytorch版)代码实践 -循环神经网络- 56门控循环单元(`GRU`)

56门控循环单元&#xff08;GRU&#xff09; 我们讨论了如何在循环神经网络中计算梯度&#xff0c; 以及矩阵连续乘积可以导致梯度消失或梯度爆炸的问题。 下面我们简单思考一下这种梯度异常在实践中的意义&#xff1a; 我们可能会遇到这样的情况&#xff1a;早期观测值对预测…

Nacos2.X源码分析:服务注册、服务发现流程

文章目录 Nacos2.1.X源码源码下载服务注册NacosClient端NacosServer端 服务发现NacosClient端NacosServer端 Nacos2.1.X源码 源码下载 源码下载地址 服务注册 官方文档&#xff0c;对于NamingService接口服务注册方法的说明 Nacos2.X 服务注册总流程图 NacosClient端 一个…

华为OSPF配置DR和BDR与指定DR

基础配置 <Huawei>sys #进入配置模式 Enter system view, return user view with CtrlZ. [Huawei]un in en #关闭报文弹窗 Info: Information center is disabled. [Huawei]sys R1 #设备名更改为R1 [R1]int g0/0/0 …

智能物联网鱼缸

硬件部分及接线图 工具 继电器、开发板、物联网os、云平台 微信小程序 结构&#xff1a;images、pages两个为主体。 标题头部分 <view class"container"> <view class"head_box"> <image src"/images/面性鱼缸.png"><…

【Java】详解String类中的各种方法

创建字符串 常见的创建字符串的三种方式&#xff1a; // 方式一 String str "hello world"; // 方式二 String str2 new String("hello world"); // 方式三 char[] array {a, b, c}; String str3 new String(array); "hello" 这样的字符串字…

昇思学习打卡-8-FCN图像语义分割

目录 FCN介绍FCN所用的技术训练数据的可视化模型训练模型推理FCN的优点和不足优点不足 FCN介绍 FCN主要用于图像分割领域&#xff0c;是一种端到端的分割方法&#xff0c;是深度学习应用在图像语义分割的开山之作。通过进行像素级的预测直接得出与原图大小相等的label map。因…

3-4 优化器和学习率

3-4 优化器和学习率 主目录点这里 优化器是机器学习和深度学习模型训练过程中用于调整模型参数的方法。它的主要目标是通过最小化损失函数来找到模型参数的最优值&#xff0c;从而提升模型的性能。 在深度学习中&#xff0c;优化器使用反向传播算法计算损失函数相对于模型参数…

C++ 函数高级——函数的占位参数

C中函数的形参列表里可以有占位参数&#xff0c;用来做占位&#xff0c;调用函数时必须填补改位置 语法&#xff1a; 返回值类型 函数名&#xff08;数据类型&#xff09;{ } 在现阶段函数的占位参数存在意义不大&#xff0c;但是后面的课程中会用到该技术 示例&#xff1a;…

TypeScript:5分钟上手创建一个简单的Web应用

一、练习TypeScript实例 1.1 在src目录里创建greeter.ts greeter.ts文件代码 // https://www.tslang.cn/docs/handbook/typescript-in-5-minutes.html // 格式化快捷键&#xff1a;https://blog.csdn.net/Dontla/article/details/130255699 function greeter(name: string) …

Windows电脑下载、安装VS Code的方法

本文介绍Visual Studio Code&#xff08;VS Code&#xff09;软件在Windows操作系统电脑中的下载、安装、运行方法。 Visual Studio Code&#xff08;简称VS Code&#xff09;是一款由微软开发的免费、开源的源代码编辑器&#xff0c;支持跨平台使用&#xff0c;可在Windows、m…

采煤机作业3D虚拟仿真教学线上展示增强应急培训效果

在化工行业的生产现场&#xff0c;安全永远是首要之务。为了加强从业人员的应急响应能力和危机管理能力&#xff0c;纷纷引入化工行业工艺VR模拟培训&#xff0c;让应急演练更加生动、高效。 化工行业工艺VR模拟培训软件基于真实的厂区环境&#xff0c;精确还原了各类事件场景和…