您的位置:首页 > 其它

两个相同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来区分。再贴代码就没什么意义了。
因为只有一个设备名,和入口函数,系统注册加载时就当一个驱动来加载。只是按不同设备的参数执行不同函数罢了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  PIDVID相同 rtl8152
相关文章推荐