📄 pcan_usb.c
字号:
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 + -