diff options
Diffstat (limited to 'drivers/staging/comedi/drivers/vmk80xx.c')
-rw-r--r-- | drivers/staging/comedi/drivers/vmk80xx.c | 193 |
1 files changed, 86 insertions, 107 deletions
diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index baee8d767636..94010fc05905 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -64,37 +64,11 @@ Changelog: #include "../comedidev.h" -#define BOARDNAME "vmk80xx" - -MODULE_AUTHOR("Manuel Gebele <forensixs@gmx.de>"); -MODULE_DESCRIPTION("Velleman USB Board Low-Level Driver"); -MODULE_SUPPORTED_DEVICE("K8055/K8061 aka VM110/VM140"); -MODULE_VERSION("0.8.01"); -MODULE_LICENSE("GPL"); - enum { DEVICE_VMK8055, DEVICE_VMK8061 }; -static const struct usb_device_id vmk80xx_id_table[] = { - {USB_DEVICE(0x10cf, 0x5500), .driver_info = DEVICE_VMK8055}, - {USB_DEVICE(0x10cf, 0x5501), .driver_info = DEVICE_VMK8055}, - {USB_DEVICE(0x10cf, 0x5502), .driver_info = DEVICE_VMK8055}, - {USB_DEVICE(0x10cf, 0x5503), .driver_info = DEVICE_VMK8055}, - {USB_DEVICE(0x10cf, 0x8061), .driver_info = DEVICE_VMK8061}, - {USB_DEVICE(0x10cf, 0x8062), .driver_info = DEVICE_VMK8061}, - {USB_DEVICE(0x10cf, 0x8063), .driver_info = DEVICE_VMK8061}, - {USB_DEVICE(0x10cf, 0x8064), .driver_info = DEVICE_VMK8061}, - {USB_DEVICE(0x10cf, 0x8065), .driver_info = DEVICE_VMK8061}, - {USB_DEVICE(0x10cf, 0x8066), .driver_info = DEVICE_VMK8061}, - {USB_DEVICE(0x10cf, 0x8067), .driver_info = DEVICE_VMK8061}, - {USB_DEVICE(0x10cf, 0x8068), .driver_info = DEVICE_VMK8061}, - {} /* terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, vmk80xx_id_table); - #define VMK8055_DI_REG 0x00 #define VMK8055_DO_REG 0x01 #define VMK8055_AO1_REG 0x02 @@ -232,8 +206,6 @@ static struct vmk80xx_usb vmb[VMK80XX_MAX_BOARDS]; static DEFINE_MUTEX(glb_mutex); -static struct comedi_driver driver_vmk80xx; /* see below for initializer */ - static void vmk80xx_tx_callback(struct urb *urb) { struct vmk80xx_usb *dev = urb->context; @@ -1127,44 +1099,25 @@ static int vmk80xx_pwm_winsn(struct comedi_device *cdev, return n; } -static int vmk80xx_attach(struct comedi_device *cdev, - struct comedi_devconfig *it) +static int vmk80xx_attach_common(struct comedi_device *cdev, + struct vmk80xx_usb *dev) { - int i; - struct vmk80xx_usb *dev; int n_subd; struct comedi_subdevice *s; - int minor; - - mutex_lock(&glb_mutex); - - for (i = 0; i < VMK80XX_MAX_BOARDS; i++) - if (vmb[i].probed && !vmb[i].attached) - break; - - if (i == VMK80XX_MAX_BOARDS) { - mutex_unlock(&glb_mutex); - return -ENODEV; - } - - dev = &vmb[i]; + int ret; down(&dev->limit_sem); - cdev->board_name = dev->board.name; cdev->private = dev; - if (dev->board.model == VMK8055_MODEL) n_subd = 5; else n_subd = 6; - - if (alloc_subdevices(cdev, n_subd) < 0) { + ret = comedi_alloc_subdevices(cdev, n_subd); + if (ret) { up(&dev->limit_sem); - mutex_unlock(&glb_mutex); - return -ENOMEM; + return ret; } - /* Analog input subdevice */ s = cdev->subdevices + VMK80XX_SUBD_AI; s->type = COMEDI_SUBD_AI; @@ -1173,7 +1126,6 @@ static int vmk80xx_attach(struct comedi_device *cdev, s->maxdata = (1 << dev->board.ai_bits) - 1; s->range_table = dev->board.range; s->insn_read = vmk80xx_ai_rinsn; - /* Analog output subdevice */ s = cdev->subdevices + VMK80XX_SUBD_AO; s->type = COMEDI_SUBD_AO; @@ -1182,12 +1134,10 @@ static int vmk80xx_attach(struct comedi_device *cdev, s->maxdata = (1 << dev->board.ao_bits) - 1; s->range_table = dev->board.range; s->insn_write = vmk80xx_ao_winsn; - if (dev->board.model == VMK8061_MODEL) { s->subdev_flags |= SDF_READABLE; s->insn_read = vmk80xx_ao_rinsn; } - /* Digital input subdevice */ s = cdev->subdevices + VMK80XX_SUBD_DI; s->type = COMEDI_SUBD_DI; @@ -1196,7 +1146,6 @@ static int vmk80xx_attach(struct comedi_device *cdev, s->maxdata = 1; s->insn_read = vmk80xx_di_rinsn; s->insn_bits = vmk80xx_di_bits; - /* Digital output subdevice */ s = cdev->subdevices + VMK80XX_SUBD_DO; s->type = COMEDI_SUBD_DO; @@ -1205,12 +1154,10 @@ static int vmk80xx_attach(struct comedi_device *cdev, s->maxdata = 1; s->insn_write = vmk80xx_do_winsn; s->insn_bits = vmk80xx_do_bits; - if (dev->board.model == VMK8061_MODEL) { s->subdev_flags |= SDF_READABLE; s->insn_read = vmk80xx_do_rinsn; } - /* Counter subdevice */ s = cdev->subdevices + VMK80XX_SUBD_CNT; s->type = COMEDI_SUBD_COUNTER; @@ -1218,13 +1165,11 @@ static int vmk80xx_attach(struct comedi_device *cdev, s->n_chan = dev->board.cnt_chans; s->insn_read = vmk80xx_cnt_rinsn; s->insn_config = vmk80xx_cnt_cinsn; - if (dev->board.model == VMK8055_MODEL) { s->subdev_flags |= SDF_WRITEABLE; s->maxdata = (1 << dev->board.cnt_bits) - 1; s->insn_write = vmk80xx_cnt_winsn; } - /* PWM subdevice */ if (dev->board.model == VMK8061_MODEL) { s = cdev->subdevices + VMK80XX_SUBD_PWM; @@ -1235,19 +1180,51 @@ static int vmk80xx_attach(struct comedi_device *cdev, s->insn_read = vmk80xx_pwm_rinsn; s->insn_write = vmk80xx_pwm_winsn; } - dev->attached = 1; + dev_info(cdev->class_dev, "vmk80xx: board #%d [%s] attached\n", + dev->count, dev->board.name); + up(&dev->limit_sem); + return 0; +} - minor = cdev->minor; - - printk(KERN_INFO - "comedi%d: vmk80xx: board #%d [%s] attached to comedi\n", - minor, dev->count, dev->board.name); +/* called for COMEDI_DEVCONFIG ioctl for board_name "vmk80xx" */ +static int vmk80xx_attach(struct comedi_device *cdev, + struct comedi_devconfig *it) +{ + int i; + int ret; - up(&dev->limit_sem); + mutex_lock(&glb_mutex); + for (i = 0; i < VMK80XX_MAX_BOARDS; i++) + if (vmb[i].probed && !vmb[i].attached) + break; + if (i == VMK80XX_MAX_BOARDS) + ret = -ENODEV; + else + ret = vmk80xx_attach_common(cdev, &vmb[i]); mutex_unlock(&glb_mutex); + return ret; +} - return 0; +/* called via comedi_usb_auto_config() */ +static int vmk80xx_attach_usb(struct comedi_device *cdev, + struct usb_interface *intf) +{ + int i; + int ret; + + mutex_lock(&glb_mutex); + for (i = 0; i < VMK80XX_MAX_BOARDS; i++) + if (vmb[i].probed && vmb[i].intf == intf) + break; + if (i == VMK80XX_MAX_BOARDS) + ret = -ENODEV; + else if (vmb[i].attached) + ret = -EBUSY; + else + ret = vmk80xx_attach_common(cdev, &vmb[i]); + mutex_unlock(&glb_mutex); + return ret; } static void vmk80xx_detach(struct comedi_device *dev) @@ -1262,8 +1239,16 @@ static void vmk80xx_detach(struct comedi_device *dev) } } -static int vmk80xx_probe(struct usb_interface *intf, - const struct usb_device_id *id) +static struct comedi_driver vmk80xx_driver = { + .module = THIS_MODULE, + .driver_name = "vmk80xx", + .attach = vmk80xx_attach, + .detach = vmk80xx_detach, + .attach_usb = vmk80xx_attach_usb, +}; + +static int vmk80xx_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) { int i; struct vmk80xx_usb *dev; @@ -1405,7 +1390,7 @@ static int vmk80xx_probe(struct usb_interface *intf, mutex_unlock(&glb_mutex); - comedi_usb_auto_config(intf, &driver_vmk80xx); + comedi_usb_auto_config(intf, &vmk80xx_driver); return 0; error: @@ -1414,7 +1399,7 @@ error: return -ENODEV; } -static void vmk80xx_disconnect(struct usb_interface *intf) +static void vmk80xx_usb_disconnect(struct usb_interface *intf) { struct vmk80xx_usb *dev = usb_get_intfdata(intf); @@ -1442,41 +1427,35 @@ static void vmk80xx_disconnect(struct usb_interface *intf) mutex_unlock(&glb_mutex); } -/* TODO: Add support for suspend, resume, pre_reset, - * post_reset and flush */ -static struct usb_driver vmk80xx_driver = { - .name = "vmk80xx", - .probe = vmk80xx_probe, - .disconnect = vmk80xx_disconnect, - .id_table = vmk80xx_id_table +static const struct usb_device_id vmk80xx_usb_id_table[] = { + { USB_DEVICE(0x10cf, 0x5500), .driver_info = DEVICE_VMK8055 }, + { USB_DEVICE(0x10cf, 0x5501), .driver_info = DEVICE_VMK8055 }, + { USB_DEVICE(0x10cf, 0x5502), .driver_info = DEVICE_VMK8055 }, + { USB_DEVICE(0x10cf, 0x5503), .driver_info = DEVICE_VMK8055 }, + { USB_DEVICE(0x10cf, 0x8061), .driver_info = DEVICE_VMK8061 }, + { USB_DEVICE(0x10cf, 0x8062), .driver_info = DEVICE_VMK8061 }, + { USB_DEVICE(0x10cf, 0x8063), .driver_info = DEVICE_VMK8061 }, + { USB_DEVICE(0x10cf, 0x8064), .driver_info = DEVICE_VMK8061 }, + { USB_DEVICE(0x10cf, 0x8065), .driver_info = DEVICE_VMK8061 }, + { USB_DEVICE(0x10cf, 0x8066), .driver_info = DEVICE_VMK8061 }, + { USB_DEVICE(0x10cf, 0x8067), .driver_info = DEVICE_VMK8061 }, + { USB_DEVICE(0x10cf, 0x8068), .driver_info = DEVICE_VMK8061 }, + { } }; +MODULE_DEVICE_TABLE(usb, vmk80xx_usb_id_table); -static struct comedi_driver driver_vmk80xx = { - .module = THIS_MODULE, - .driver_name = "vmk80xx", - .attach = vmk80xx_attach, - .detach = vmk80xx_detach +/* TODO: Add support for suspend, resume, pre_reset, + * post_reset and flush */ +static struct usb_driver vmk80xx_usb_driver = { + .name = "vmk80xx", + .probe = vmk80xx_usb_probe, + .disconnect = vmk80xx_usb_disconnect, + .id_table = vmk80xx_usb_id_table, }; +module_comedi_usb_driver(vmk80xx_driver, vmk80xx_usb_driver); -static int __init vmk80xx_init(void) -{ - int retval; - - printk(KERN_INFO "vmk80xx: version 0.8.01 " - "Manuel Gebele <forensixs@gmx.de>\n"); - - retval = comedi_driver_register(&driver_vmk80xx); - if (retval < 0) - return retval; - - return usb_register(&vmk80xx_driver); -} - -static void __exit vmk80xx_exit(void) -{ - comedi_driver_unregister(&driver_vmk80xx); - usb_deregister(&vmk80xx_driver); -} - -module_init(vmk80xx_init); -module_exit(vmk80xx_exit); +MODULE_AUTHOR("Manuel Gebele <forensixs@gmx.de>"); +MODULE_DESCRIPTION("Velleman USB Board Low-Level Driver"); +MODULE_SUPPORTED_DEVICE("K8055/K8061 aka VM110/VM140"); +MODULE_VERSION("0.8.01"); +MODULE_LICENSE("GPL"); |