官方网站的驱动可能会更好
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;
}
阅读(1770) | 评论(0) | 转发(0) |