⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcan_usb.c

📁 linux下的CAN BUS驱动代码。适合在arm平台使用。
💻 C
📖 第 1 页 / 共 2 页
字号:
              dev->wInitStep = 0;              kfree(dev);    }  }    return 0;}// dummy entries for request and free irqstatic int pcan_usb_req_irq(struct pcandev *dev){  DPRINTK(KERN_DEBUG "%s: pcan_usb_req_irq()\n", DEVICE_NAME);  return 0;}static void pcan_usb_free_irq(struct pcandev *dev){  DPRINTK(KERN_DEBUG "%s: pcan_usb_free_irq()\n", DEVICE_NAME);  // mis-used here for another purpose  // pcan_usb_free_irq() calls when the last path to device just closing  // and the device itself is already plugged out  if ((dev) && (!dev->ucPhysicallyInstalled))    pcan_usb_cleanup(dev);}// interface depended open and closestatic int pcan_usb_open(struct pcandev *dev){  DPRINTK(KERN_DEBUG "%s: pcan_usb_open(), minor = %d.\n", DEVICE_NAME, dev->nMinor);  return 0;}static int pcan_usb_release(struct pcandev *dev){  DPRINTK(KERN_DEBUG "%s: pcan_usb_release(), minor = %d.\n", DEVICE_NAME, dev->nMinor);  return 0;}// emulated device access functions// call is only possible if device existsstatic int pcan_usb_device_open(struct pcandev *dev, u16 btr0btr1, u8 bExtended, u8 bListenOnly){  int err = 0;  DPRINTK(KERN_DEBUG "%s: pcan_usb_device_open(), minor = %d.\n", DEVICE_NAME, dev->nMinor);  // in general, when second open() occures  // remove and unlink urbs, when interface is already running  if ((dev->nOpenPaths) && (dev->device_release))    dev->device_release(dev);  // first action: turn CAN off  if ((err = pcan_hw_SetCANOff(dev)))    goto fail;  if ((err = pcan_usb_start(dev)))    goto fail;  // init hardware specific parts  if ((err = pcan_hw_Init(dev, btr0btr1, bListenOnly)))    goto fail;  // store extended mode (standard still accepted)  dev->bExtended = bExtended;  // take a fresh status  dev->wCANStatus = 0;  // copy from NT driver  mdelay(20);  // last action: turn CAN on  if ((err = pcan_hw_SetCANOn(dev)))    goto fail;      // delay to get first messages read  set_current_state(TASK_INTERRUPTIBLE);  schedule_timeout(STARTUP_WAIT_TIME * HZ);  fail:  return err;}static void pcan_usb_device_release(struct pcandev *dev){  DPRINTK(KERN_DEBUG "%s: pcan_usb_device_release(), minor = %d.\n", DEVICE_NAME, dev->nMinor);  // do not stop usb immediately, give a chance for the PCAN-USB to send this telegram  schedule();  mdelay(100);  pcan_usb_stop(dev);}static int pcan_usb_device_write(struct pcandev *dev){  return pcan_usb_write(dev);}#ifdef NETDEV_SUPPORTstatic int pcan_usb_device_write_frame(struct pcandev *dev, struct can_frame *cf){  return pcan_usb_write_frame(dev, cf);}#endif#ifndef LINUX_26//****************************************************************************// special assignment of minors due to PuP//static int assignMinorNumber(struct pcandev *dev){  int searchedMinor;  u8 occupied;  struct pcandev   *devWork = (struct pcandev *)NULL;  struct list_head *ptr;  DPRINTK(KERN_DEBUG "%s: assignMinorNumber()\n", DEVICE_NAME);  for (searchedMinor = PCAN_USB_MINOR_BASE; searchedMinor < (PCAN_USB_MINOR_BASE + 8); searchedMinor++)  {    occupied = 0;    // loop trough my devices    for (ptr = pcan_drv.devices.next; ptr != &pcan_drv.devices; ptr = ptr->next)    {      devWork = (struct pcandev *)ptr;        // stop if it is occupied      if (devWork->nMinor == searchedMinor)      {        occupied = 1;        break;      }    }        // jump out when the first available number is found    if (!occupied)      break;  }  if (!occupied)  {    dev->nMinor = searchedMinor;    return 0;  }  else  {    dev->nMinor = -1;    return -ENXIO;  }}#endif//****************************************************************************// propagate getting of serial number to my 'small' interface//int  pcan_usb_getSerialNumber(struct pcandev *dev){    if (dev && dev->ucPhysicallyInstalled)    return pcan_hw_getSNR(dev, &dev->port.usb.dwSerialNumber);  else    return -ENODEV;}//****************************************************************************// things todo after plugin or plugout of device (and power on too)//#ifdef LINUX_26static int pcan_usb_plugin(struct usb_interface *interface, const struct usb_device_id *id){  struct pcandev *dev = NULL;  int    err = 0;  int    i;  USB_PORT *u;  struct usb_host_interface *iface_desc;  struct usb_endpoint_descriptor *endpoint;  struct usb_device *usb_dev = interface_to_usbdev(interface);  DPRINTK(KERN_DEBUG "%s: pcan_usb_plugin(0x%04x, 0x%04x)\n", DEVICE_NAME,           usb_dev->descriptor.idVendor, usb_dev->descriptor.idProduct);  // take the 1st configuration (it's default)  if ((err = usb_reset_configuration (usb_dev)) < 0)   {    printk(KERN_ERR "%s: usb_set_configuration() failed!\n", DEVICE_NAME);    goto reject;  }      // only 1 interface is supported  if ((err = usb_set_interface (usb_dev, 0, 0)) < 0)   {    printk(KERN_ERR "%s: usb_set_interface() failed!\n", DEVICE_NAME);    goto reject;  }    // allocate memory for my device  if ((dev = (struct pcandev *)kmalloc(sizeof(struct pcandev), GFP_ATOMIC)) == NULL)  {    printk(KERN_ERR "%s: pcan_usb_plugin - memory allocation failed!\n", DEVICE_NAME);    err = -ENOMEM;    goto reject;  }  memset(dev, 0x00, sizeof(*dev));  dev->wInitStep = 0;  u   = &dev->port.usb;  // init structure elements to defaults  pcan_soft_init(dev, "usb", HW_USB);  // preset finish flags  atomic_set(&u->param_xmit_finished, 0);  // preset active URB counter  atomic_set(&u->active_urbs, 0);  // override standard device access functions  dev->device_open      = pcan_usb_device_open;  dev->device_release   = pcan_usb_device_release;  dev->device_write     = pcan_usb_device_write;  #ifdef NETDEV_SUPPORT  dev->netdevice_write  = pcan_usb_device_write_frame;  #endif  // init process wait queues  init_waitqueue_head(&dev->read_queue);  init_waitqueue_head(&dev->write_queue);  // set this before any instructions, fill struct pcandev, part 1    dev->wInitStep   = 0;             dev->readreg     = NULL;  dev->writereg    = NULL;  dev->cleanup     = pcan_usb_cleanup;  dev->req_irq     = pcan_usb_req_irq;  dev->free_irq    = pcan_usb_free_irq;  dev->open        = pcan_usb_open;  dev->release     = pcan_usb_release;  dev->filter      = pcan_create_filter_chain();  // store pointer to kernel supplied usb_dev  u->usb_dev          = usb_dev;  u->ucHardcodedDevNr = (u8)(usb_dev->descriptor.bcdDevice & 0xff);  u->ucRevision       = (u8)(usb_dev->descriptor.bcdDevice >> 8);  u->pUSBtime         = NULL;  printk(KERN_INFO "%s: usb hardware revision = %d\n", DEVICE_NAME, u->ucRevision);  // get endpoint addresses (numbers) and associated max data length (only from setting 0)  iface_desc = &interface->altsetting[0];  for (i = 0; i < iface_desc->desc.bNumEndpoints; i++)  {    endpoint = &iface_desc->endpoint[i].desc;        u->Endpoint[i].ucNumber = endpoint->bEndpointAddress;    u->Endpoint[i].wDataSz  = endpoint->wMaxPacketSize;  }  init_waitqueue_head(&u->usb_wait_queue);  dev->wInitStep = 1;  // add into list of devices  list_add_tail(&dev->list, &pcan_drv.devices);  // add this device to the list          dev->wInitStep = 2;    // assign the device as plugged in  dev->ucPhysicallyInstalled = 1;  pcan_drv.wDeviceCount++;  usb_devices++;   dev->wInitStep = 3;    if ((err = pcan_usb_allocate_resources(dev)))    goto reject;  dev->wInitStep = 4;  usb_set_intfdata(interface, dev);  if ((err = usb_register_dev(interface, &pcan_class)) < 0)  {    usb_set_intfdata(interface, NULL);    goto reject;  }    dev->nMinor = interface->minor;    // get serial number early  pcan_usb_getSerialNumber(dev);    #ifdef NETDEV_SUPPORT  pcan_netdev_register(dev);  #endif    printk(KERN_INFO "%s: usb device minor %d found\n", DEVICE_NAME, dev->nMinor);  return 0;  reject:  pcan_usb_cleanup(dev);    printk(KERN_ERR "%s: pcan_usb_plugin() failed! (%d)\n", DEVICE_NAME, err);    return err;}#else#ifdef LINUX_24static void *pcan_usb_plugin(struct usb_device *usb_dev, unsigned int interface, const struct usb_device_id *id_table)#elsestatic void *pcan_usb_plugin(struct usb_device *usb_dev, unsigned int interface)#endif{  struct pcandev *dev = NULL;  int    err = 0;  int    i;  USB_PORT *u;  struct usb_interface_descriptor *current_interface_setting;  DPRINTK(KERN_DEBUG "%s: pcan_usb_plugin(0x%04x, 0x%04x, %d)\n", DEVICE_NAME,          usb_dev->descriptor.idVendor, usb_dev->descriptor.idProduct, interface);  // take the 1st configuration (it's default)  if (usb_set_configuration (usb_dev, usb_dev->config[0].bConfigurationValue) < 0)  {    printk(KERN_ERR "%s: usb_set_configuration() failed!\n", DEVICE_NAME);    goto reject;  }  // only 1 interface is supported  if (usb_set_interface (usb_dev, 0, 0) < 0)  {    printk(KERN_ERR "%s: usb_set_interface() failed!\n", DEVICE_NAME);    goto reject;  }    // allocate memory for my device  if ((dev = (struct pcandev *)kmalloc(sizeof(struct pcandev), GFP_ATOMIC)) == NULL)  {    printk(KERN_ERR "%s: pcan_usb_plugin - memory allocation failed!\n", DEVICE_NAME);    goto reject;  }  dev->wInitStep = 0;  u   = &dev->port.usb;  // init structure elements to defaults  pcan_soft_init(dev, "usb", HW_USB);  // preset finish flags  atomic_set(&u->param_xmit_finished, 0);  // preset active URB counter  atomic_set(&u->active_urbs, 0);  // override standard device access functions  dev->device_open      = pcan_usb_device_open;  dev->device_release   = pcan_usb_device_release;  dev->device_write     = pcan_usb_device_write;  #ifdef NETDEV_SUPPORT  dev->netdevice_write  = pcan_usb_device_write_frame;  #endif  // init process wait queues  init_waitqueue_head(&dev->read_queue);  init_waitqueue_head(&dev->write_queue);  // set this before any instructions, fill struct pcandev, part 1  dev->wInitStep   = 0;             dev->readreg     = NULL;  dev->writereg    = NULL;  dev->cleanup     = pcan_usb_cleanup;  dev->req_irq     = pcan_usb_req_irq;  dev->free_irq    = pcan_usb_free_irq;  dev->open        = pcan_usb_open;  dev->release     = pcan_usb_release;  if ((err = assignMinorNumber(dev)))    goto reject;  // store pointer to kernel supplied usb_dev  u->usb_dev          = usb_dev;  u->ucHardcodedDevNr = (u8)(usb_dev->descriptor.bcdDevice & 0xff);  u->ucRevision       = (u8)(usb_dev->descriptor.bcdDevice >> 8);  u->pUSBtime         = NULL;  printk(KERN_INFO "%s: usb hardware revision = %d\n", DEVICE_NAME, u->ucRevision);  // get endpoint addresses (numbers) and associated max data length  current_interface_setting = &usb_dev->actconfig->interface->altsetting[usb_dev->actconfig->interface->act_altsetting];  for (i = 0; i < 4; i++)  {    u->Endpoint[i].ucNumber = current_interface_setting->endpoint[i].bEndpointAddress;    u->Endpoint[i].wDataSz  = current_interface_setting->endpoint[i].wMaxPacketSize;  }  init_waitqueue_head(&u->usb_wait_queue);  dev->wInitStep = 1;  // add into list of devices  list_add_tail(&dev->list, &pcan_drv.devices);  // add this device to the list  dev->wInitStep = 2;  // assign the device as plugged in  dev->ucPhysicallyInstalled = 1;  pcan_drv.wDeviceCount++;  usb_devices++;   dev->wInitStep = 3;  if ((err = pcan_usb_allocate_resources(dev)))    goto reject;  dev->wInitStep = 4;  printk(KERN_INFO "%s: usb device minor %d found\n", DEVICE_NAME, dev->nMinor);  #ifdef NETDEV_SUPPORT  pcan_netdev_register(dev);  #endif  return (void *)dev;  reject:  pcan_usb_cleanup(dev);    printk(KERN_ERR "%s: pcan_usb_plugin() failed! (%d)\n", DEVICE_NAME, err);  return NULL;}#endif#ifdef NETDEV_SUPPORTstatic void pcan_usb_plugout_netdev(struct pcandev *dev){  struct net_device *ndev = dev->netdev;  if (ndev) {    netif_stop_queue(ndev);    pcan_netdev_unregister(dev);  }}#endif//****************************************************************************// is called at plug out of device//#ifdef LINUX_26static void pcan_usb_plugout(struct usb_interface *interface){  struct pcandev *dev = usb_get_intfdata(interface);  if (dev)  {    DPRINTK(KERN_DEBUG "%s: pcan_usb_plugout(%d)\n", DEVICE_NAME, dev->nMinor);    #ifdef NETDEV_SUPPORT    pcan_usb_plugout_netdev(dev);    #endif    usb_set_intfdata(interface, NULL);        usb_deregister_dev(interface, &pcan_class);        // mark this device as plugged out    dev->ucPhysicallyInstalled = 0;    // do not remove resources if the device is still in use    if (!dev->nOpenPaths)      pcan_usb_cleanup(dev);  }}#elsestatic void pcan_usb_plugout(struct usb_device *usb_dev, void *drv_context){  struct pcandev *dev = (struct pcandev *)drv_context;  if (dev)  {    DPRINTK(KERN_DEBUG "%s: pcan_usb_plugout(%d)\n", DEVICE_NAME, dev->nMinor);    #ifdef NETDEV_SUPPORT    pcan_usb_plugout_netdev(dev);    #endif    // mark this device as plugged out    dev->ucPhysicallyInstalled = 0;    // do not remove resources if the device is still in use    if (!dev->nOpenPaths)      pcan_usb_cleanup(dev);  }}#endif//****************************************************************************// small interface to rest of driver, only init and deinit//static int pcan_usb_init(void){  DPRINTK(KERN_DEBUG "%s: pcan_usb_init()\n", DEVICE_NAME);  memset (&pcan_drv.usbdrv, 0, sizeof(pcan_drv.usbdrv));    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,24) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)  pcan_drv.usbdrv.owner       = THIS_MODULE;  #endif    pcan_drv.usbdrv.probe       = pcan_usb_plugin;  pcan_drv.usbdrv.disconnect  = pcan_usb_plugout;  pcan_drv.usbdrv.name        = DEVICE_NAME;  pcan_drv.usbdrv.id_table    = pcan_usb_ids;  return usb_register(&pcan_drv.usbdrv);}void pcan_usb_deinit(void){  DPRINTK(KERN_DEBUG "%s: pcan_usb_deinit()\n", DEVICE_NAME);  if (pcan_drv.usbdrv.probe == pcan_usb_plugin)  {    // then it was registered    // unregister usb parts, makes a plugout of registered devices    usb_deregister(&pcan_drv.usbdrv);  }}//----------------------------------------------------------------------------// init for usb based devices from peakint pcan_usb_register_devices(void){  int err;  DPRINTK(KERN_DEBUG "%s: pcan_usb_register_devices()\n", DEVICE_NAME);  if (!(err = pcan_usb_init()))  {    DPRINTK(KERN_DEBUG "%s: pcan_usb_register_devices() is OK\n", DEVICE_NAME);  }  return err;} 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -