linux 4.1 usb驱动之usb_serial芯片ch341

官方网站的驱动可能会更好http://www.wch.cn/download/CH341SER_LINUX_ZIP.html
ch340芯片兼容这个驱动。
<drivers/usb/serial/ch341.c>
module_usb_serial_driver(serial_drivers, id_table);

///
<include/linux/usb/serial.h>

/*

  • module_usb_serial_driver() - Helper macro for registering a USB Serial driver
  • @__serial_drivers: list of usb_serial drivers to register
  • @__ids: all device ids that @__serial_drivers bind to
  • Helper macro for USB serial drivers which do not do anything special
  • in module init/exit. This eliminates a lot of boilerplate. Each
  • module may only use this macro once, and calling it replaces
  • module_init() and module_exit()

*/
#define usb_serial_module_driver(__name, __serial_drivers, __ids)
static int __init usb_serial_module_init(void)
{
//最终还是调用到这里了
return usb_serial_register_drivers(__serial_drivers,
__name, __ids);
}
module_init(usb_serial_module_init);
static void __exit usb_serial_module_exit(void)
{
usb_serial_deregister_drivers(__serial_drivers);
}
module_exit(usb_serial_module_exit);
#define module_usb_serial_driver(__serial_drivers, __ids)
usb_serial_module_driver(KBUILD_MODNAME, __serial_drivers, __ids)

///
<drivers/usb/serial/ch341.c>
static struct usb_serial_driver ch341_device = {
.driver = {
.owner = THIS_MODULE,
.name = “ch341-uart”,
},

                        //id_table  module_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);

见宏实现<include/linux/module.h>
/* 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))))


<drivers/usb/serial/usb-serial.c>
/**

  • 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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xx-xx-xxx-xxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值