static struct usb_serial_driver ch341_device = {

.driver = {

.owner    = THIS_MODULE,

.name    = "ch341-uart",

},

//id_tablemodule_usb_serial_driver(serial_drivers,id_table);两处都涉及id_table

.id_table          =id_table,

.num_ports         = 1,

.open              = ch341_open,

.dtr_rts       = ch341_dtr_rts,

.carrier_raised       = ch341_carrier_raised,

.close             = ch341_close,

.set_termios       = ch341_set_termios,

.break_ctl         = ch341_break_ctl,

.tiocmget          = ch341_tiocmget,

.tiocmset          = ch341_tiocmset,

.tiocmiwait        = usb_serial_generic_tiocmiwait,

.read_int_callback = ch341_read_int_callback,

.port_probe        = ch341_port_probe,

.port_remove       = ch341_port_remove,

.reset_resume      = ch341_reset_resume,

};

static struct usb_serial_driver * const serial_drivers[] = {

&ch341_device, NULL

};

static const struct usb_device_id id_table[] = {

{ USB_DEVICE(0x4348, 0x5523) },

{ USB_DEVICE(0x1a86, 0x7523) },            //CH340芯片的VID PID

{ USB_DEVICE(0x1a86, 0x5523) },            //CH341芯片USB转串口VID PID

{ },

};

/

这些ID表是不是看不懂,请看CH340DS1.DOC文件

字节地址        简称       配置数据区域的说明                                                 默认值

05H~04H   VID      Vendor ID,厂商识别码,高字节在后,任意值。设置为 0000H 或 0FFFFH 则 VID 和 PID 使用厂商默认值          1A86H

07H~06H   PID          Product ID,产品识别码,高字节在后,任意值                                          7523H

MODULE_DEVICE_TABLE

该宏生成一个名为__mod_usb__id_table_device_table的局部变量,该变量指向第二个参数,是id_table的别名。内核构建时,depmod程序会在所有模块中搜索符号__mod_usb__id_table_device_table,把数据(设备列表)从模块中抽出,添加到映射文件/lib/modules/KERNEL_VERSION/modules.usbmap中,当depmod结束之后,所有的USB设备连同他们的模块名字都被该文件列出。当内核告知热插拔系统一个新的USB设备被发现时,热插拔系统使用modules.usbmap文件来找寻恰当的驱动程序

MODULE_DEVICE_TABLE(usb,id_table);

见宏实现/* Creates an alias so file2alias.c can find device table. */

#define MODULE_DEVICE_TABLE(type, name)                    \

extern const typeof(name) __mod_##type##__##name##_device_table        \

__attribute__ ((unused, alias(__stringify(name))))

/**

* usb_serial_register_drivers - register drivers for a usb-serial module

* @serial_drivers: NULL-terminated array of pointers to drivers to be registered

* @name: name of the usb_driver for this set of @serial_drivers

* @id_table: list of all devices this @serial_drivers set binds to

*

* Registers all the drivers in the @serial_drivers array, and dynamically

* creates a struct usb_driver with the name @name and id_table of @id_table.

*/

int usb_serial_register_drivers(struct usb_serial_driver *const serial_drivers[],

const char *name,

const struct usb_device_id *id_table)

{

int rc;

struct usb_driver *udriver;

struct usb_serial_driver * const *sd;

/*

* udriver must be registered before any of the serial drivers,

* because the store_new_id() routine for the serial drivers (in

* bus.c) probes udriver.

*

* Performance hack: We don't want udriver to be probed until

* the serial drivers are registered, because the probe would

* simply fail for lack of a matching serial driver.

* So we leave udriver's id_table set to NULL until we are all set.

*

* Suspend/resume support is implemented in the usb-serial core,

* so fill in the PM-related fields in udriver.

*/

udriver = kzalloc(sizeof(*udriver), GFP_KERNEL);

if (!udriver)

return -ENOMEM;

udriver->name = name;

udriver->no_dynamic_id = 1;

udriver->supports_autosuspend = 1;

udriver->suspend = usb_serial_suspend;

udriver->resume = usb_serial_resume;

udriver->probe = usb_serial_probe;

udriver->disconnect = usb_serial_disconnect;

/* we only set the reset_resume field if the serial_driver has one */

for (sd = serial_drivers; *sd; ++sd) {

if ((*sd)->reset_resume) {

udriver->reset_resume = usb_serial_reset_resume;

break;

}

}

rc = usb_register(udriver);

if (rc)

return rc;

for (sd = serial_drivers; *sd; ++sd) {

(*sd)->usb_driver = udriver;

rc = usb_serial_register(*sd);

if (rc)

goto failed;

}

/* Now set udriver's id_table and look for matches */

udriver->id_table = id_table;

rc = driver_attach(&udriver->drvwrap.driver);

return 0;

failed:

while (sd-- > serial_drivers)

usb_serial_deregister(*sd);

usb_deregister(udriver);

return rc;

}

往linux内核添加ch341,linux 4.1 usb驱动之usb_serial芯片ch341相关推荐

  1. linux内核添加模块,linux中添加内核模块

    1.  内核模块简介 Linux 内核的 整 体结构 非 常 庞 大 ,其 包 含 的 组 件也 非 常多 , 如 何使用 需 要 的 组 件 呢? 方 法 一 : 把 所有的 组 件都 编译 进 内 ...

  2. linux内核添加lrz,linux 调试之lrz的移植与一些说明

    开发板:RT5350 编译器:mipsel-linux-gcc ( 如果是arm平台和arm_linux的话,请参照修改即可) 1.获取源码:lrzsz-0.12.20.tar.gz 2. 解压: t ...

  3. exfat linux 驱动_(实例)Linux 内核添加exfat驱动

    背景: 由于exfat是常用的文件系统格式,而Linux由于版权的问题,没有在官方中添加有关的驱动. 但是 微软也同意开源了,所以比较新的 Linux 会支持这一块. 为了支持exfat的驱动,我们需 ...

  4. 向linux内核增加新的系统调用,为linux内核添加新的系统调用

    为linux内核添加新的系统调用 作者:李志勇 更多精彩: 更多精彩: 开发平台:x86 ubuntu 目标平台:S3C6410 linux3.4.4 一.    打开内核源码目录下arch/arm/ ...

  5. linux 怎么往内核加驱动,向Linux内核添加驱动

    Linux内核中提供了很多设备的驱动代码,但每个项目中总会需要添加我们自己的驱动,比如我们需要添加红外遥控驱动.我们可以先独立去编写和调试这个驱动,等成熟后应该放到内核目录树中,使用make modu ...

  6. linux内核添加系统调用(详细)

    linux内核添加系统调用(详细) 说在前面: 这是我第五次编译内核,分别踩了很多坑.中途问过wz佬,佬让我用qemu.我还是最后换ubuntu虚拟机跑了.现在已经有点emo了. 这篇博客是我第五次的 ...

  7. 【Linux 内核】编译 Linux 内核 ① ( 下载指定版本的 Linux 内核源码 | Linux 内核版本号含义 | 主版本号 | 次版本号 | 小版本号 | 稳定版本 )

    文章目录 一.下载 Linux 内核 1.下载最新版本 Linux 内核 2.下载指定版本 Linux 内核 二.Linux 内核版本号含义 一.下载 Linux 内核 1.下载最新版本 Linux ...

  8. linux内核基本模型,Linux设备模型(1)_基本概念

    Linux设备模型(1)_基本概念 作者:wowo 发布于:2014-2-27 17:01 分类:统一设备模型 1. 前言 在"Linux内核的整体架构"中,蜗蜗有提到,由于Lin ...

  9. 编译3.0的linux内核,1-3-编译Linux内核

    1-3-编译Linux内核 1.将Linux源码包拷贝到共享文件夹. 2.进入共享文件夹. 3.解压,命令#tar xvfj Kernel_3.0.8_TQ210_for_Linux_v2.2.tar ...

  10. linux内核 can总线,Linux Canbus调试笔记

    http://blog.csdn.net/flydream0/article/details/8161418 CAN总线在嵌入式Linux下驱动程序的实现 http://www.21ic.com/ap ...

最新文章

  1. 机器学习(6)KNN算法(K-近邻算法)
  2. 3gpp文件头文件解析_居于LLVM 的命令行参数解析
  3. 泛海三江手动控制盘怎么设置_热板机如何操作控制系统?
  4. python计算最大回撤_Python进阶量化交易场外篇3——最大回撤评价策略风险
  5. BugkuCTF-Crypto题MathEnglish
  6. 【收藏】RPM包制作和spec文件详解
  7. python读、写、修改、追写excel文件(xlrd / xlwt / xlutils / openpyxl)
  8. [译] Commit 提交指南
  9. python百度文库下载器_真正百度文库免费下载,比冰点文库下载器还更牛x!
  10. 软件视频会议系统 服务器要求,视频会议系统招标要求.docx
  11. 卸载奇安信天擎,流氓软件
  12. 多个服务器数据互通_8月6日部分服务器数据互通公告!
  13. 黑客帝国神级影评,转至豆瓣。 — — 哲思。
  14. Unity学习2:如何实现个性化渲染平面(图文详细)
  15. C++核心准则讨论:如果一个类是资源句柄,则它需要一个构造函数,一个析构函数以及复制和/或移动操作
  16. Coursera--DataStructure-加州理工大学圣地亚哥分校课程
  17. #榜样的力量#航班管家全球大交通出行疫情追踪服务系统丨数据猿新冠战“疫”公益策划...
  18. edge 禁止网页自动刷新_如何在Microsoft Edge中自动翻译网页
  19. 插件自动解决谷歌翻译用不了,win、mac、linux通用,附链接
  20. 使用Lanproxy搭建内网穿透服务完整教程

热门文章

  1. 白帽子讲Web安全(纪念版)笔记
  2. 第三单元JML地铁系统博客 By Wazaki
  3. C语言中的常见关键字
  4. 单片机破解的常用方法及应对策略
  5. 可靠性试验与环境试验概述
  6. 求极限简单总结 (基础)
  7. 绿联串口线linux驱动下载,绿联usb转串口驱动
  8. C++语言对C语言的扩展(二)
  9. RC ORC Parquet 格式比较和性能测试
  10. cad上样条曲线上的点太多了_CAD样条曲线添加控制点