Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1137998
  • 博文数量: 241
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 2279
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-27 19:53
个人简介

JustForFun

文章分类

全部博文(241)

文章存档

2023年(8)

2022年(2)

2021年(3)

2020年(30)

2019年(11)

2018年(27)

2017年(54)

2016年(83)

2015年(23)

我的朋友

分类: LINUX

2020-09-04 01:32:46

官方网站的驱动可能会更好
ch340芯片兼容这个驱动。

module_usb_serial_driver(serial_drivers, id_table);


///////////////////////////////////


/*
 * 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)

///////////////////////////////////

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);

见宏实现
/* 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;
}









阅读(1652) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~