两个相同VID PID的不同设备加载同一个KO文件中的不同驱动
2015-01-10 10:48
656 查看
两个相同VID PID的不同设备加载同一个KO文件中的不同驱动
问题:Realtek两个不同芯片的USB-TO-ETHERNET,PID
VID都同为:8152。因为客户手中已经有一部分老的产品了,目前停产,新的产品使用不同的芯片。
需求:USB-TO-ETHERNET只是我们的外围设备的一部分,所以要求不管客户使用哪一个设备接进来,都能和主机搭配工作。
解决方案概述:
1,这是USB设备,所以通用USB接口标准会读取其设备描述。找出两种设备的关键不同点,我们的情况是:新旧设备的bNumConfigurations值不同,一个是1,另一个是2。
2,将驱动名统一为8152,跟据bNumConfigurations不同,加载不同的函数即可;
过程和代码:
1,先将新设备的驱动加入到kernel中,并确认新的驱动配新的设备可以工作。老的设备就不用说了,因为已经在工作中。
2,PIDVID加载时,只认一个驱动的名字。我这里设为“rtl8152”,所以驱动入口也只有一个。
static struct usb_driver rtl8152_driver = {
.name= MODULENAME,
.probe= rtl8152_probe,
.disconnect= rtl8152_disconnect,
.id_table= rtl8152_table,
.suspend= rtl8152_suspend,
.resume= rtl8152_resume
};
static int __init usb_rtl8152_init(void)
{
returnusb_register(&rtl8152_driver);
}
static void __exit usb_rtl8152_exit(void)
{
usb_deregister(&rtl8152_driver);
}
接下来要区分不同的设备执行不同的函数了。
贴代码最实际:
static int rtl8152_probe(structusb_interface *intf,
const struct usb_device_id
*id)
{
structusb_device *udev = interface_to_usbdev(intf);
rtl8152_t*tp;
structnet_device *netdev;
usb_driver_set_configuration(udev,1);
return-ENODEV;
}
if(udev->descriptor.bNumConfigurations==1)
rtl815x=1;//--------------当bNumConfigurations为1时执行老驱动的函数;
else
rtl815x=2;//--------------当bNumConfigurations为其它时执行新驱动的函数;
netdev= alloc_etherdev(sizeof(rtl8152_t));
if(!netdev) {
printk("Outof memory");
return-ENOMEM;
}
tp= netdev_priv(netdev);
tp->msg_enable= 0x7FFF;
tp->intr_buff= kmalloc(INTBUFSIZE, GFP_KERNEL);
if(!tp->intr_buff) {
free_netdev(netdev);
return-ENOMEM;
}
if(rtl815x==1)//老驱动
{
tasklet_init(&tp->tl,r8152u_rx_fixup, (unsigned long)tp);
spin_lock_init(&tp->rx_pool_lock);
INIT_DELAYED_WORK(&tp->schedule,r8152u_rtl_work_func_t);
tp->udev= udev;
tp->netdev= netdev;
#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,29)
netdev->netdev_ops= &rtl8152_netdev_ops;
#else
netdev->open= rtl8152u_open;
netdev->stop= rtl8152u_close;
netdev->get_stats= rtl8152u_get_stats;
netdev->hard_start_xmit= rtl8152u_start_xmit;
netdev->tx_timeout= rtl8152u_tx_timeout;
// netdev->change_mtu
= eth_change_mtu;
netdev->set_mac_address= rtl8152u_set_mac_address;
netdev->do_ioctl= rtl8152u_ioctl;
netdev->set_multicast_list= rtl8152u_set_rx_mode;
#endif /* HAVE_NET_DEVICE_OPS */
netdev->watchdog_timeo= RTL8152_TX_TIMEOUT;
netdev->features&= ~NETIF_F_IP_CSUM;
SET_ETHTOOL_OPS(netdev,&r8152u_ops);
tp->intr_interval= 100; /*
100ms */
if(!r8152u_alloc_all_urbs(tp)) {
err("outof memory");
gotoout;
}
if(!rtl8152u_reset(tp)) {
err("couldn'treset the device");
gotoout1;
}
r8152u_fill_skb_pool(tp);
rtl8152u_set_ethernet_addr(tp);
}
else
{//新驱动
tasklet_init(&tp->tl,rx_fixup, (unsigned long)tp);
INIT_DELAYED_WORK(&tp->schedule,rtl_work_func_t);
tp->udev= udev;
tp->netdev= netdev;
#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,29)
netdev->netdev_ops= &rtl8152_netdev_ops;
#else
netdev->open= rtl8152_open;
netdev->stop= rtl8152_close;
netdev->get_stats= rtl8152_get_stats;
netdev->hard_start_xmit= rtl8152_start_xmit;
netdev->tx_timeout= rtl8152_tx_timeout;
// netdev->change_mtu
= eth_change_mtu;
netdev->set_mac_address= rtl8152_set_mac_address;
netdev->do_ioctl= rtl8152_ioctl;
netdev->set_multicast_list= rtl8152_set_rx_mode;
#endif /* HAVE_NET_DEVICE_OPS */
netdev->watchdog_timeo= RTL8152_TX_TIMEOUT;
netdev->features&= ~NETIF_F_IP_CSUM;
SET_ETHTOOL_OPS(netdev,&ops);
tp->intr_interval= 100; /*
100ms */
tp->speed= 0;
r8152b_init(tp);
if(!alloc_all_urbs(tp)) {
printk("outof memory");
gotoout;
}
tp->rx_skb= netdev_alloc_skb_ip_align(netdev, RTL8152_MTU + sizeof(RxDesc));
if(!tp->rx_skb)
gotoout1;
}
usb_set_intfdata(intf,tp);
SET_NETDEV_DEV(netdev,&intf->dev);
if(register_netdev(netdev) != 0) {
printk("couldn'tregister the device");
gotoout2;
}
dev_info(&intf->dev,"%s: rtl8152 is detected\n", netdev->name);
return0;
out2:
usb_set_intfdata(intf,NULL);
if(rtl815x==1)
{
r8152u_free_skb_pool(tp);
}
else
{
dev_kfree_skb(tp->rx_skb);
}
out1:
if(rtl815x==1)
{
r8152u_free_all_urbs(tp);
}
else
{
free_all_urbs(tp);
}
out:
kfree(tp->intr_buff);
free_netdev(netdev);
return-EIO;
}
static void rtl8152_disconnect(structusb_interface *intf)
{
rtl8152_t*tp = usb_get_intfdata(intf);
usb_set_intfdata(intf,NULL);
if(tp) {
set_bit(RTL8152_UNPLUG,&tp->flags);
tasklet_kill(&tp->tl);
unregister_netdev(tp->netdev);
if(rtl815x==1)
{
r8152u_unlink_all_urbs(tp);
r8152u_free_all_urbs(tp);
r8152u_free_skb_pool(tp);
}
else
{
free_all_urbs(tp);
}
if(tp->rx_skb)
dev_kfree_skb(tp->rx_skb);
kfree(tp->intr_buff);
free_netdev(tp->netdev);
}
}
/* table of devices that work with thisdriver */
static struct usb_device_id rtl8152_table[]= {//这个就一样了,就是因为这个PIDVID相同才到//这地步了
{USB_DEVICE_VER(VENDOR_ID_REALTEK,PRODUCT_ID_RTL8152, 0x2000, 0x2000)},
// {USB_DEVICE(VENDOR_ID_REALTEK,PRODUCT_ID_RTL8152)},
{}
};
MODULE_DEVICE_TABLE(usb, rtl8152_table);
其它函数和变量同样可以用全局变量:rtl815x==1/2来区分。再贴代码就没什么意义了。
因为只有一个设备名,和入口函数,系统注册加载时就当一个驱动来加载。只是按不同设备的参数执行不同函数罢了。
问题:Realtek两个不同芯片的USB-TO-ETHERNET,PID
VID都同为:8152。因为客户手中已经有一部分老的产品了,目前停产,新的产品使用不同的芯片。
需求:USB-TO-ETHERNET只是我们的外围设备的一部分,所以要求不管客户使用哪一个设备接进来,都能和主机搭配工作。
解决方案概述:
1,这是USB设备,所以通用USB接口标准会读取其设备描述。找出两种设备的关键不同点,我们的情况是:新旧设备的bNumConfigurations值不同,一个是1,另一个是2。
2,将驱动名统一为8152,跟据bNumConfigurations不同,加载不同的函数即可;
过程和代码:
1,先将新设备的驱动加入到kernel中,并确认新的驱动配新的设备可以工作。老的设备就不用说了,因为已经在工作中。
2,PIDVID加载时,只认一个驱动的名字。我这里设为“rtl8152”,所以驱动入口也只有一个。
static struct usb_driver rtl8152_driver = {
.name= MODULENAME,
.probe= rtl8152_probe,
.disconnect= rtl8152_disconnect,
.id_table= rtl8152_table,
.suspend= rtl8152_suspend,
.resume= rtl8152_resume
};
static int __init usb_rtl8152_init(void)
{
returnusb_register(&rtl8152_driver);
}
static void __exit usb_rtl8152_exit(void)
{
usb_deregister(&rtl8152_driver);
}
接下来要区分不同的设备执行不同的函数了。
贴代码最实际:
static int rtl8152_probe(structusb_interface *intf,
const struct usb_device_id
*id)
{
structusb_device *udev = interface_to_usbdev(intf);
rtl8152_t*tp;
structnet_device *netdev;
usb_driver_set_configuration(udev,1);
return-ENODEV;
}
if(udev->descriptor.bNumConfigurations==1)
rtl815x=1;//--------------当bNumConfigurations为1时执行老驱动的函数;
else
rtl815x=2;//--------------当bNumConfigurations为其它时执行新驱动的函数;
netdev= alloc_etherdev(sizeof(rtl8152_t));
if(!netdev) {
printk("Outof memory");
return-ENOMEM;
}
tp= netdev_priv(netdev);
tp->msg_enable= 0x7FFF;
tp->intr_buff= kmalloc(INTBUFSIZE, GFP_KERNEL);
if(!tp->intr_buff) {
free_netdev(netdev);
return-ENOMEM;
}
if(rtl815x==1)//老驱动
{
tasklet_init(&tp->tl,r8152u_rx_fixup, (unsigned long)tp);
spin_lock_init(&tp->rx_pool_lock);
INIT_DELAYED_WORK(&tp->schedule,r8152u_rtl_work_func_t);
tp->udev= udev;
tp->netdev= netdev;
#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,29)
netdev->netdev_ops= &rtl8152_netdev_ops;
#else
netdev->open= rtl8152u_open;
netdev->stop= rtl8152u_close;
netdev->get_stats= rtl8152u_get_stats;
netdev->hard_start_xmit= rtl8152u_start_xmit;
netdev->tx_timeout= rtl8152u_tx_timeout;
// netdev->change_mtu
= eth_change_mtu;
netdev->set_mac_address= rtl8152u_set_mac_address;
netdev->do_ioctl= rtl8152u_ioctl;
netdev->set_multicast_list= rtl8152u_set_rx_mode;
#endif /* HAVE_NET_DEVICE_OPS */
netdev->watchdog_timeo= RTL8152_TX_TIMEOUT;
netdev->features&= ~NETIF_F_IP_CSUM;
SET_ETHTOOL_OPS(netdev,&r8152u_ops);
tp->intr_interval= 100; /*
100ms */
if(!r8152u_alloc_all_urbs(tp)) {
err("outof memory");
gotoout;
}
if(!rtl8152u_reset(tp)) {
err("couldn'treset the device");
gotoout1;
}
r8152u_fill_skb_pool(tp);
rtl8152u_set_ethernet_addr(tp);
}
else
{//新驱动
tasklet_init(&tp->tl,rx_fixup, (unsigned long)tp);
INIT_DELAYED_WORK(&tp->schedule,rtl_work_func_t);
tp->udev= udev;
tp->netdev= netdev;
#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,29)
netdev->netdev_ops= &rtl8152_netdev_ops;
#else
netdev->open= rtl8152_open;
netdev->stop= rtl8152_close;
netdev->get_stats= rtl8152_get_stats;
netdev->hard_start_xmit= rtl8152_start_xmit;
netdev->tx_timeout= rtl8152_tx_timeout;
// netdev->change_mtu
= eth_change_mtu;
netdev->set_mac_address= rtl8152_set_mac_address;
netdev->do_ioctl= rtl8152_ioctl;
netdev->set_multicast_list= rtl8152_set_rx_mode;
#endif /* HAVE_NET_DEVICE_OPS */
netdev->watchdog_timeo= RTL8152_TX_TIMEOUT;
netdev->features&= ~NETIF_F_IP_CSUM;
SET_ETHTOOL_OPS(netdev,&ops);
tp->intr_interval= 100; /*
100ms */
tp->speed= 0;
r8152b_init(tp);
if(!alloc_all_urbs(tp)) {
printk("outof memory");
gotoout;
}
tp->rx_skb= netdev_alloc_skb_ip_align(netdev, RTL8152_MTU + sizeof(RxDesc));
if(!tp->rx_skb)
gotoout1;
}
usb_set_intfdata(intf,tp);
SET_NETDEV_DEV(netdev,&intf->dev);
if(register_netdev(netdev) != 0) {
printk("couldn'tregister the device");
gotoout2;
}
dev_info(&intf->dev,"%s: rtl8152 is detected\n", netdev->name);
return0;
out2:
usb_set_intfdata(intf,NULL);
if(rtl815x==1)
{
r8152u_free_skb_pool(tp);
}
else
{
dev_kfree_skb(tp->rx_skb);
}
out1:
if(rtl815x==1)
{
r8152u_free_all_urbs(tp);
}
else
{
free_all_urbs(tp);
}
out:
kfree(tp->intr_buff);
free_netdev(netdev);
return-EIO;
}
static void rtl8152_disconnect(structusb_interface *intf)
{
rtl8152_t*tp = usb_get_intfdata(intf);
usb_set_intfdata(intf,NULL);
if(tp) {
set_bit(RTL8152_UNPLUG,&tp->flags);
tasklet_kill(&tp->tl);
unregister_netdev(tp->netdev);
if(rtl815x==1)
{
r8152u_unlink_all_urbs(tp);
r8152u_free_all_urbs(tp);
r8152u_free_skb_pool(tp);
}
else
{
free_all_urbs(tp);
}
if(tp->rx_skb)
dev_kfree_skb(tp->rx_skb);
kfree(tp->intr_buff);
free_netdev(tp->netdev);
}
}
/* table of devices that work with thisdriver */
static struct usb_device_id rtl8152_table[]= {//这个就一样了,就是因为这个PIDVID相同才到//这地步了
{USB_DEVICE_VER(VENDOR_ID_REALTEK,PRODUCT_ID_RTL8152, 0x2000, 0x2000)},
// {USB_DEVICE(VENDOR_ID_REALTEK,PRODUCT_ID_RTL8152)},
{}
};
MODULE_DEVICE_TABLE(usb, rtl8152_table);
其它函数和变量同样可以用全局变量:rtl815x==1/2来区分。再贴代码就没什么意义了。
因为只有一个设备名,和入口函数,系统注册加载时就当一个驱动来加载。只是按不同设备的参数执行不同函数罢了。
相关文章推荐
- pig加载两个不同字段个数的文件?load file with different items(f1有42列,f2有43列读到一个对象中)
- pig加载两个不同字段个数的文件?load file with different items(f1有42列,f2有43列读到一个对象中)
- C#中,有两个不同的CS文件,但这两个文件具有相同的命名空间(namespace)。一个CS文件要用另一个CS文件中的类的话,下面有一个处理方式。
- 不同手机在豌豆夹上显示同一个设备名的解决方法 && 修改PID/VID后的ADB重新识别 && 单设备多个PID的识别
- xcode应用程序更名,使一个设备安装两个相同应用(名字不同)
- 文件比较. 写一个比较两个文本文件的程序. 如果不同, 给出第一个不同处的行号和 列号.
- 同一个服务器上建两个数据库名字不同库相同的数据库
- 设备驱动------KEIL下分散加载文件的使用
- sql语句——不同的表根据相同的字段值将两个表指定的字段合并为一个表
- 构造前缀碰撞法可制作两个内容不同但具有相同MD5验证码的文件
- 9-6 文件比较。写一个比较两个文本文件的程序。如果不同,给出第一个不同处的行号和列号。
- 有个数组a[100]存放了100个数,这100个数取自1-99,且只有两个相同的数,剩下的98个数不同,写一个搜索算法找出相同的那个数的值.(注意空间效率时间效率尽可能要低)
- MD5值相同的两个不同的文件
- linux 停 HID 设备 节点文件 访问 查找 VID PID
- 节点文件将两个不同格式的XML文件,进行节点对照,并生成一个用于对照功能的XML
- jboss7静态变量由于不同的类加载器在两个模块中不相同
- linux 统计两个文件中相同或不同的行
- 使用shell 统计文本行数,输出两个文件不同或相同的行
- 不同的布局文件怎么加载到一个activity中
- Sencha Touch 2.2根据不同设备自动加载相应样式文件及Sencha Touch 2.3中各主题说明