两个相同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来区分。再贴代码就没什么意义了。

因为只有一个设备名,和入口函数,系统注册加载时就当一个驱动来加载。只是按不同设备的参数执行不同函数罢了。

两个相同VID PID的不同设备加载同一个KO文件中的不同驱动相关推荐

  1. MTK6592平台 touchpanel驱动设备加载(一)

    前言: 从事android驱动调试工作已有一年多了,之前一直没有系统的看一下内核,正好这几个月有时间,整理了一下关于内核中对设备.驱动的调用关系,目前我是在mtk6592 kk 平台以touchpan ...

  2. 如果在一个工程中有两个vhd文件,就相当于有两个模块,那么对于这个工程整体的bdf文件生成,怎么把这两个模块都加到同一个bdf文件中。bdf文件中两个模块之间的连线及输入输出,是自己输进去的还是自动生

    如果在一个工程中有两个vhd文件,就相当于有两个模块,那么对于这个工程整体的bdf文件生成,怎么把这两个模块都加到同一个bdf文件中.bdf文件中两个模块之间的连线及输入输出,是自己输进去的还是自动生 ...

  3. 设备栈中各个设备加载顺序

    如题,这是前几天某同事问我的问题.他假设设备栈中有Pdo,Fdo,以及附属于Fdo的设备上下过滤驱动以及类上下过滤驱动,在这种情况下,OS会以怎样的顺序加载这些设备? 我第一反应是当然先加载Fdo,然 ...

  4. MTK6592平台 touchpanel驱动设备加载(三)

    项目初期对新的IC供应商压求: 1,各个片脚的电压域,待机和工作时候的电压必须在BB端端口电压域范围 2,中断触发方式,我们要求是下降沿触发,必须要改 3,flash分区情况和大小 4,flash是否 ...

  5. VirtualBox 下USB 设备加载的步骤及无法加载的解决办法

    1. 将u盘插入电脑,在windows能够识别后,进入VirtualBox的选定要加载的虚拟机,选择设置-->选择usb设备项 2. 选择右边的第一或者是第二个图标,增加一个新的筛选器,第一个图 ...

  6. 两个class写在同一个java文件中

    第一种: 一个public类,多个非public类,例如:public class A{}class B{}第二个class前面不能加public. 第二种: 第二种是内部类,写在公共类体里面的,例如 ...

  7. MTK6592平台 touchpanel驱动设备加载(二)

    关于设备驱动加载,我这边整理出的函数调用关系流程图见下,主要为了解释进程如何调用驱动里面的probe函数

  8. 如何在inf文件中修改pid、vid

    Inf文件即Device Information File(设备信息文件),用于引导驱动程序(*.sys)的安装.它实质上是一个文本文件,可以用记事本工具打开查看和编辑. 简单介绍一下USB设备驱动程 ...

  9. Linux查看U盘的Vid,CheckUDisk(查看USB的VID/PID/厂商信息)v5.4

    CheckUDisk是一个免费的USB存储设备检测工具,能查看诸如USB存储设备名称.盘符.VID&PID.序列号.制造商信息.产品信息.版本.传输速度等连接到PC上的U盘信息.支持Win98 ...

最新文章

  1. 从未在一起更让人遗憾_我们从未在一起和我们最终没在一起,哪一个更让人难过?...
  2. [转]机器学习和深度学习资料汇总【01】
  3. Python 'takes exactly 1 argument (2 given)' Python error
  4. JZOJ 5431. 【NOIP2017提高A组集训10.28】序列操作
  5. golang PHP的区别,erlang和golang的区别
  6. ubuntu下数据库的导入导出
  7. 我被认定为高层次人才了!
  8. ubuntu安装宝塔界面
  9. 智百威收银系统服务器连接不上,收银系统进入不了收银系统怎么办 – 手机爱问...
  10. UniWebview Bug处理记录
  11. Cisco Packet Tracer中配置链路聚合
  12. 车载以太网交换机功能和应用案例汇总, 适用于AVB/TSN, 802.1AS(gPTP时钟同步)
  13. 微信小程序流量主广告怎么加圆角
  14. 计算机无法对NAS硬盘操作,群晖NAS联机失败不要慌,我用经验告诉你,这样做就能完美解决...
  15. Date与Calander使用及异同
  16. linux桌面支持hdpi,用于HiDPI显示器的最佳Linux桌面环境 | MOS86
  17. 以太坊源码分析-同步之Syncing接口
  18. 【音视频相关】nvidia-smi 命令扩展及问题分析举例(dmon/pmon/GPU性能相关)
  19. 注册表编辑器被改这样恢复
  20. Java对接HJ212协议设备

热门文章

  1. Java基础-逻辑运算符
  2. APP常见测试点总结
  3. low_n/Unirep
  4. Oracle数据库登陆报错ORA-00257
  5. python——turtle
  6. 登录功能通用测试用例设计
  7. js 获取文本框的值 并传输到指定位置
  8. 鼠标移动到上面变小手和鼠標其他效果
  9. SEO网站优化技巧整合
  10. BGP项目实验案例(基于华为设备)