Qualcomm usb modem驱动小结
Qualcomm usb modem驱动小结
前段时间再为我们公司的模块产品sim5210写linux下的驱动, sim5210使用的是qualcomm的6280芯片, 该平台提供了USB功能, 并再USB之上提供了modem, diag, nmea等设备接口, 即再usb之上我们的模块实现了modem功能, diag(诊断)功能, nmea(gps)功能, 由于在linux下有现成的标准CDC modem的驱动, 所以我们以此为参考实现了我们的非标准modem, 和用于收发at command的diag的驱动. 下面我们重点总结一下modem驱动的编写方法, diag类似.
我们的modem驱动是tty+usb的层次关系, 即上层跟用户交互的接口使用tty驱动类型, 初始化时先注册一个设备文件, 以后用户使用时直接通过这个设备文件与设备打交道, 当用户的操作传递到我们的tty驱动层后, 在我们的驱动中在把这些操作(read, write)转化为对usb设备的操作, 最后通过usb总线与usb设备交互, 整个驱动结构如下:
下面详细讲解这个驱动的整个流程:
1 通过module_init() 和 module_exit()注册我们驱动的init和exit函数, init函数将会在驱动加载时被调用, exit函数将会在驱动卸载时被调用.
2 我们的init函数是
static int __init qcmdm_init()
{
/*1 调用alloc_tty_driver()分配一个tty_driver对象: qcmdm_tty_driver */
/*2 初始化qcmdm_tty_driver 的相关field*/
/*3 调用tty_set_operations 为qcmdm_tty_driver 设好操作函数表, 即tty驱动的函数表*/
/*4 调用tty_register_driver()把qcmdm_tty_driver注册到系统中去*/
/*调用usb_register()注册我们的usb驱动对象 qcmdm_usb_driver(静态分配并初始化好的)*/
return 0;
}
通过这一步, 我们注册了usb驱动对象, 和tty驱动对象, 但这时设备文件还没创建好,因此这个tty驱动还没法用, 当modem查上后linux内核会调用我们先前注册的usb驱动对象中的probe函数(整个调用流程可以参考我写的另一篇文章<<usb设备probe全过程>>)
我们的exit函数是:
static void __exit qcmdm_exit()
{
/*1 调用tty_unregister_driver() 来卸载qcmdm_tty_driver*/
/*2 调用put_tty_driver() 来释放qcmdm_tty_driver占用的内存*/
/*3 调用 usb_deregister()来下载qcmdm_usb_driver*/
}
3 我们qcmdm_usb_driver的probe函数:
static int qcmdm_probe(struct usb_interface *intf, /*匹配的接口*/
const struct usb_device_id *id /*驱动支持的设备表项*/)
{
/*
1 根据设备的配置判断这个interface是否就是我们驱动支持的接口,
一般到了这步说明这个接口匹配了我们的device_id列表(这是我们驱动
提供的用于判断一个接口是否是我们驱动支持的这么一个列表), 但由于我们
的设备是个多接口的设备,所以这里还要进一步判断是否匹配,
*/
/*
2 检测设备的其他信息是否和我们的真是设备的信息匹配(如端点数量,端点类型等)
*/
/*
* 3 一般每个驱动都会定义一个记录我们设备信息的私有数据结构,我的驱动中定义的是
* strcut qcmdm, 这里我们分配一个qcmdm的对象mdm,并初始化好它的各个字段(如保存各个端点信息等)
*/
/*4 我们在mdm中保存了一个读和写的urb列表, 这里我们为每个urb分配内存(usb_alloc_urb), 并为每个每个urb分配DMA缓冲(usb_buffer_alloc). 并初始化好每个urb(usb_fill_xxx_urb())*/
/*5 调用tty_register_device() 来把qcmdm_tty_driver和这个interface绑定起来,并创建设备文件, 以后对这个设备文件的操作就会映射到qcmdm_tty_driver的操作函数.*/
}
此外,我们还可以在probe中保存额外的一些信息, 如调用usb_set_intfdata(intf, mdm)来将mdm保存在intf的相关字段中, 这样在以后使用中可以直接通过usb_get_intfdata()来获取mdm指针.
4我们qcmdm_usb_driver的disconnect函数(在设备拔出时调用): 这个函数主要做一些和probe相反的工作
static void qcmdm_disconnect(struct usb_interface *intf)
{
/*1 删除urb (usb_kill_urb())*/
/*2 reset 读写list*/
/*3 释放相关资源, 如urb memory, usb dma memory等*/
/*4 调用tty_unregister_device()来释放驱动和设备的绑定,并删除设备文件*/
/*5 其他资源的释放或reset*/
}
总之在probe中申请了什么资源应该在disconnect中释放掉, 因为下次设备连上后,又会调用probe, 此时又会去分配资源.
5 打开函数: 这个函数是tty driver的一部分, 当打开我们创建的设备文件时会调用这个函数, 它的工作主要也是做一些初始化工作, 并调用usb_submit_urb()提交一个中断类型的urb(因为我们的设备上有个interrupt的端点, 用于设备上报一些自身状态的改变信息, 所以这里我们应该准备好接收这些状态信息)
6 write函数: 这也是tty driver的一部分, 在我们的驱动中保存了一个用于写usb的缓冲链表, 每次要写时就去获取一个空闲表项, 并把端点,数据等信息填充号这个表项中的urb, 特别的一般我们还会填充一个我们自己的用于完成后的回调函数. 然后调用usb_submit_urb提交这个写操作, 在usb写完或错误后会调用我们的回调函数(注意这是运行在中断上下文的), 这样我们就知道成功与否.
7 read函数: 这也是tty driver的一部分跟write相似,也有一个用于读的链表, 每个读操作也是先填充urb, 然后在提交,在完成后调用我们的回调函数, 此时我们得到了数据, 可以通过tty_insert_flip_string()和tty_flip_buffer_push()把数据提交到tty核心,在由tty核心交给用户. 由于在usb核心收到数据后应该快速的返回给用户, 因此在读的部分, 我们使用了tasklet, 以加快数据读出,又可避免直接在中断上下文读数据.
8 其他函数相对简单,在此不作介绍
Qualcomm usb modem驱动小结相关推荐
- 通用USB设备驱动源码分析
通用USB设备驱动源码分析 Author:aaron 前段时间写了篇<qualcomm usb modem驱动小结>的文章, 描述了自己如何为高通的一个usb modem设备写驱动的过程, ...
- 淘宝cp210X提示“VeriFone USB Modem”无法匹配驱动
淘宝cp210X提示"VeriFone USB Modem"无法匹配驱动 前段时间,在淘宝上买了cp210X usb转串口芯片,安装-调试板驱动CP210x-Windows-Dri ...
- Linux设备驱动之usb设备驱动详解
原文地址:http://blog.csdn.net/chenjin_zhong/article/details/6329316 1.Linux usb设备驱动框架 USB是通用串行总线的总称,Linu ...
- USB转串口驱动应用于macbook
USB转串口驱动应用于macbook 查到的资料支持 macbook的为 Prolific(PL2303) 和 keyspan 卸载驱动的方法: rm -rf /System/Library/Exte ...
- 第八章 USB 设备驱动移植
8.1 USB协议 USB协议系统主要组成,总线拓扑结构,内部层次关系,数据流模式,USB调度等等 8.1.1 主要组成部分 USB的连接部分,USB的 ...
- Linux usb设备驱动
原文地址:http://blog.csdn.net/chenjin_zhong/article/details/6329316 1.Linux usb设备驱动框架 USB是通用串行总线的总称,Linu ...
- linux hub设备,Linux设备驱动之USB hub驱动(续)
5.2.2:接口驱动中的hub_thread()函数 我们之前在分析usb_hub_init()的代码的时候,忽略掉了一部份. 代码片段如下所示: int usb_hub_init(void) { - ...
- Linux环境下使用 USB转串口驱动(二)
minicom是linux下串口通信的软件,它的使用完全依靠键盘的操作,虽然没有"超级终端"那么易用,但是使用习惯之后读者将会体会到它的高效与便利,下面将讲解minicom的安装和 ...
- USB gadget 驱动之 android.c
1. Gadget驱动 1.1 Gadget框架结构 kernel/drivers/usb/gadget,这个目录是android下usb gadget的主要目录. (1)Gadget功能组织单元:主 ...
最新文章
- 米勒罗宾素性测试(Miller–Rabin primality test)
- node.js初步认识
- WINDOWS高级窗口的客户区域拖动技术及其应用
- 你被人工智能给忽悠了吗?原来我们曾经认为的都是假的
- python 函数中所有print保存csv_python for循环print怎样才能输出csv呢
- 告别码公式的痛苦,公式OCR终于来了!
- 【Windows】Mathpix Snip-公式神器
- office软件提示“您的组织策略阻止我们进行该操作”错误的解决办法-终极汇总
- python中多态是什么意思_python类的多态是什么
- ASP.NET复习资料
- 麦吉尔大学 计算机科学和阿尔伯特,加拿大低龄留学-阿尔伯特学院-Albert College...
- 解决:No routes matched location “/“
- python求高阶导数_高阶导数 - 问答 - Python中文网
- windows通过浏览器远程连接Linux服务器的jupyter
- python爬虫app步骤_Python爬虫之App爬虫视频下载的实现
- Linux下自动重启系统
- 推荐系统-推荐引擎的架构
- lazarus ui设计_Golang绑定VCL和LCL组件
- matlab imagesc 坐标,[转载]matlab 中imagesc的用法
- 会计台式计算机使用年限,电脑等电子设备,使用年限必须是5年吗?残值 – 手机爱问...
热门文章
- 微信 html页面遮罩层,微信内网页提示浏览器打开代码——遮罩层提示代码实现!...
- 计算机机房分区,2021年高校计算机新建机房硬盘分区及软件安装计划硬盘分区教程win10.docx...
- 【R语言学习笔记】rep函数
- 【CSS用法】css限制一行文字数量,超出部分用省略号显示
- CF604B货物打包题解
- vue3 组件传值之 props 与 attrs 的区别
- 无线路由器接网线上网如何设置?
- linux中 gzip bizp2 xz zip怎么用,解压缩
- 如何去实现机械灵巧手玩魔方和弹钢琴_机械“影子手”上线!玩转魔方不在话下!...
- 小米运动显示同步到服务器失败,小米手环上的数据无法同步到手机APP上怎么办?解决方法看这里!...