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

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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值