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

📄 pcan_usb.c

📁 CAN 驱动编程
💻 C
📖 第 1 页 / 共 2 页
字号:
}static int pcan_usb_stop(struct pcandev *dev){  int err = 0;  USB_PORT *u = &dev->port.usb;  unsigned long dwFlags = 0;  int i = 100;  DPRINTK(KERN_DEBUG "%s: pcan_usb_stop()\n", DEVICE_NAME);   err = pcan_hw_SetCANOff(dev);  // wait until all has settled  mdelay(5);  // unlink URB  spin_lock_irqsave(&u->lock, dwFlags);  if (u->read_data->status == -EINPROGRESS)  {    err = usb_unlink_urb(u->read_data);    DPRINTK(KERN_DEBUG "%s: usb_unlink_urb(), read = %d\n", DEVICE_NAME, err);  }  spin_unlock_irqrestore (&u->lock, dwFlags);  // unlink writeURB  spin_lock_irqsave(&u->lock, dwFlags);  if (u->write_data->status == -EINPROGRESS)  {    err = usb_unlink_urb(u->write_data);    DPRINTK(KERN_DEBUG "%s: usb_unlink_urb(), write = %d\n", DEVICE_NAME, err);  }  spin_unlock_irqrestore (&u->lock, dwFlags);  // unlink parameter urb  spin_lock_irqsave(&u->lock, dwFlags);  if (u->param_urb->status == -EINPROGRESS)  {    err = usb_unlink_urb(u->param_urb);    DPRINTK(KERN_DEBUG "%s: usb_unlink_urb(), param = %d\n", DEVICE_NAME, err);  }  spin_unlock_irqrestore (&u->lock, dwFlags);  // wait until all urbs returned to sender  // (I hope) this should be no problem because all urb's are unlinked   while ((atomic_read(&u->active_urbs) > 0) && (i--))    schedule();  if (i <= 0)  {    DPRINTK(KERN_ERR "%s: have still active URBs: %d!\n", DEVICE_NAME, atomic_read(&u->active_urbs));  }  return err;}//****************************************************************************// remove device resources //static int pcan_usb_cleanup(struct pcandev *dev){  DPRINTK(KERN_DEBUG "%s: pcan_usb_cleanup()\n", DEVICE_NAME);  if (dev)  {    pcan_usb_free_resources(dev);    switch(dev->wInitStep)    {      case 3: usb_devices--;              pcan_drv.wDeviceCount--;      case 2: list_del(&dev->list);      case 1:       case 0: 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()\n", DEVICE_NAME);  return 0;}static int pcan_usb_release(struct pcandev *dev){  DPRINTK(KERN_DEBUG "%s: pcan_usb_release()\n", DEVICE_NAME);  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()\n", DEVICE_NAME);  // 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;  fail:  return err;}static void pcan_usb_device_release(struct pcandev *dev){  DPRINTK(KERN_DEBUG "%s: pcan_usb_device_release()\n", DEVICE_NAME);  // do not stop usb immediately, give a chance for the USB-dongle to send this telegram  mdelay(100);  pcan_usb_stop(dev);}static int pcan_usb_device_write(struct pcandev *dev){  return pcan_usb_write(dev);}//****************************************************************************// 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;  }}//****************************************************************************// things todo after plugin or plugout of device (and power on too)//#ifndef LINUX_22static 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);  if ((usb_dev->descriptor.idVendor  == PCAN_USB_VENDOR_ID)  &&       (usb_dev->descriptor.idProduct == PCAN_USB_PRODUCT_ID))  {    // 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_KERNEL)) == 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;    // 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->pvXptr           = NULL;    printk(KERN_INFO "%s: 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;    }    spin_lock_init(&u->lock);    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;    printk(KERN_INFO "%s: pcan_usb_plugin() is OK (minor = %d).\n", DEVICE_NAME, dev->nMinor);    return (void *)dev;    reject:    pcan_usb_cleanup(dev);        printk(KERN_ERR "%s: pcan_usb_plugin() failed! (%d)\n", DEVICE_NAME, err);  }  return NULL;}//****************************************************************************// is called at plug out of device//static 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);    // 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);  }}//****************************************************************************// 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;}//****************************************************************************// small interface to rest of driver, only init and deinit//int pcan_usb_init(void){  DPRINTK(KERN_DEBUG "%s: pcan_usb_init()\n", DEVICE_NAME);	memset (&pcan_drv.usbdrv, 0, sizeof(pcan_drv.usbdrv));  pcan_drv.usbdrv.probe       = pcan_usb_plugin;  pcan_drv.usbdrv.disconnect  = pcan_usb_plugout;  pcan_drv.usbdrv.name        = DEVICE_NAME;  pcan_drv.usbdrv.minor       = PCAN_USB_MINOR_BASE;  #ifndef LINUX_22  pcan_drv.usbdrv.id_table    = pcan_usb_ids;  #endif  return usb_register(&pcan_drv.usbdrv);}void pcan_usb_deinit(void){  DPRINTK(KERN_DEBUG "%s: pcan_usb_deinit()\n", DEVICE_NAME);  // unregister usb parts, makes a plugout of registered devices  usb_deregister(&pcan_drv.usbdrv);} 

⌨️ 快捷键说明

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