Currently this driver supports attaching 16 usb devices to 16 comedi devices. The user can pass the 32-bit serial number of the usb device when attaching to force a comedi device to attach to a specific usb device. It's also possible to attach a comedi device without having an attached usb device. When the device is first opened the comedi_device (*open) function in this driver then checks to see if a usb device has been attached. If so the subdevice information is updated based on the usb device and the comedi device is then operational. If a usb device is not attached the (*open) returns -ENODEV. To simplify converting this driver to the comedi (*auto_attach) mechanism, remove the attaching by serial number option. Modify the usb (*probe) so that the first available slot is used. If all the slots are used return -ENODEV. Modify the comedi (*attach) so that the first unused slot that has an attached usb device is used. If all the slots are used return -ENODEV. Since this ensures that the comedi device has an attached usb device, remove the (*open) function and fully initialize the subdevices during the (*attach). Fix the comedi (*detach) so that the slot is made available after detaching. Signed-off-by: H Hartley Sweeten <hsweeten@xxxxxxxxxxxxxxxxxxx> Cc: Ian Abbott <abbotti@xxxxxxxxx> Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/staging/comedi/drivers/dt9812.c | 186 ++++++++++---------------------- 1 file changed, 58 insertions(+), 128 deletions(-) diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 1fda98c..b797517 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -281,12 +281,10 @@ struct usb_dt9812 { struct dt9812_private { struct slot_dt9812 *slot; - u32 serial; }; struct slot_dt9812 { struct semaphore mutex; - u32 serial; struct usb_dt9812 *usb; struct dt9812_private *devpriv; }; @@ -654,63 +652,6 @@ static int dt9812_analog_out(struct slot_dt9812 *slot, int channel, u16 value) return result; } -/* - * Comedi functions - */ - -static int dt9812_comedi_open(struct comedi_device *dev) -{ - struct dt9812_private *devpriv = dev->private; - int result = -ENODEV; - - down(&devpriv->slot->mutex); - if (devpriv->slot->usb) { - /* We have an attached device, fill in current range info */ - struct comedi_subdevice *s; - - s = &dev->subdevices[0]; - s->n_chan = 8; - s->maxdata = 1; - - s = &dev->subdevices[1]; - s->n_chan = 8; - s->maxdata = 1; - - s = &dev->subdevices[2]; - s->n_chan = 8; - switch (devpriv->slot->usb->device) { - case 0:{ - s->maxdata = 4095; - s->range_table = &range_bipolar10; - } - break; - case 1:{ - s->maxdata = 4095; - s->range_table = &range_unipolar2_5; - } - break; - } - - s = &dev->subdevices[3]; - s->n_chan = 2; - switch (devpriv->slot->usb->device) { - case 0:{ - s->maxdata = 4095; - s->range_table = &range_bipolar10; - } - break; - case 1:{ - s->maxdata = 4095; - s->range_table = &range_unipolar2_5; - } - break; - } - result = 0; - } - up(&devpriv->slot->mutex); - return result; -} - static int dt9812_di_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -796,9 +737,11 @@ static int dt9812_ao_winsn(struct comedi_device *dev, static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it) { + struct slot_dt9812 *slot = NULL; struct dt9812_private *devpriv; int i; struct comedi_subdevice *s; + bool range_2_5; int ret; devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); @@ -806,13 +749,30 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -ENOMEM; dev->private = devpriv; + down(&dt9812_mutex); + /* - * Special open routine, since USB unit may be unattached at - * comedi_config time, hence range can not be determined + * Find the first unused slot for the comedi device + * that has a usb device connected. */ - dev->open = dt9812_comedi_open; + for (i = 0; i < DT9812_NUM_SLOTS; i++) { + if (dt9812[i].usb && !dt9812[i].devpriv) { + slot = &dt9812[i]; + break; + } + } + if (!slot) { + up(&dt9812_mutex); + return -ENODEV; + } - devpriv->serial = it->options[0]; + down(&slot->mutex); + slot->devpriv = devpriv; + devpriv->slot = slot; + range_2_5 = (slot->usb->device == DT9812_DEVID_DT9812_2PT5); + up(&slot->mutex); + + up(&dt9812_mutex); ret = comedi_alloc_subdevices(dev, 4); if (ret) @@ -822,7 +782,7 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it) s = &dev->subdevices[0]; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; - s->n_chan = 0; + s->n_chan = 8; s->maxdata = 1; s->range_table = &range_digital; s->insn_read = &dt9812_di_rinsn; @@ -831,7 +791,7 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it) s = &dev->subdevices[1]; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITEABLE; - s->n_chan = 0; + s->n_chan = 8; s->maxdata = 1; s->range_table = &range_digital; s->insn_write = &dt9812_do_winsn; @@ -840,9 +800,9 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it) s = &dev->subdevices[2]; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND; - s->n_chan = 0; - s->maxdata = 1; - s->range_table = NULL; + s->n_chan = 8; + s->maxdata = 4095; + s->range_table = range_2_5 ? &range_unipolar2_5 : &range_bipolar10; s->insn_read = &dt9812_ai_rinsn; /* analog output subdevice */ @@ -850,48 +810,22 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITEABLE; s->n_chan = 0; - s->maxdata = 1; - s->range_table = NULL; + s->maxdata = 4095; + s->range_table = range_2_5 ? &range_unipolar2_5 : &range_bipolar10; s->insn_write = &dt9812_ao_winsn; s->insn_read = &dt9812_ao_rinsn; dev_info(dev->class_dev, "successfully attached to dt9812.\n"); - down(&dt9812_mutex); - /* Find a slot for the comedi device */ - { - struct slot_dt9812 *first = NULL; - struct slot_dt9812 *best = NULL; - for (i = 0; i < DT9812_NUM_SLOTS; i++) { - if (!first && !dt9812[i].devpriv) { - /* First free slot from comedi side */ - first = &dt9812[i]; - } - if (!best && - dt9812[i].usb && - dt9812[i].usb->serial == devpriv->serial) { - /* We have an attaced device with matching ID */ - best = &dt9812[i]; - } - } - if (!best) - best = first; - if (best) { - down(&best->mutex); - best->devpriv = devpriv; - best->serial = devpriv->serial; - devpriv->slot = best; - up(&best->mutex); - } - } - up(&dt9812_mutex); - return 0; } static void dt9812_detach(struct comedi_device *dev) { - /* Nothing to cleanup */ + struct dt9812_private *devpriv = dev->private; + + if (devpriv && devpriv->slot) + devpriv->slot = NULL; } static struct comedi_driver dt9812_comedi_driver = { @@ -904,10 +838,11 @@ static struct comedi_driver dt9812_comedi_driver = { static int dt9812_probe(struct usb_interface *interface, const struct usb_device_id *id) { - int retval = -ENOMEM; + struct slot_dt9812 *slot = NULL; struct usb_dt9812 *dev = NULL; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; + int retval = -ENOMEM; int i; u8 fw; @@ -918,6 +853,28 @@ static int dt9812_probe(struct usb_interface *interface, kref_init(&dev->kref); + down(&dt9812_mutex); + + /* Find an empty slot for the usb device */ + for (i = 0; i < DT9812_NUM_SLOTS; i++) { + if (!dt9812[i].usb) { + slot = &dt9812[i]; + break; + } + } + if (!slot) { + up(&dt9812_mutex); + retval = -ENODEV; + goto error; + } + + down(&slot->mutex); + slot->usb = dev; + dev->slot = slot; + up(&slot->mutex); + + up(&dt9812_mutex); + dev->udev = usb_get_dev(interface_to_usbdev(interface)); dev->interface = interface; @@ -1034,31 +991,6 @@ static int dt9812_probe(struct usb_interface *interface, dev_info(&interface->dev, "USB DT9812 (%4.4x.%4.4x.%4.4x) #0x%8.8x\n", dev->vendor, dev->product, dev->device, dev->serial); - down(&dt9812_mutex); - { - /* Find a slot for the USB device */ - struct slot_dt9812 *first = NULL; - struct slot_dt9812 *best = NULL; - - for (i = 0; i < DT9812_NUM_SLOTS; i++) { - if (!first && !dt9812[i].usb && dt9812[i].serial == 0) - first = &dt9812[i]; - if (!best && dt9812[i].serial == dev->serial) - best = &dt9812[i]; - } - - if (!best) - best = first; - - if (best) { - down(&best->mutex); - best->usb = dev; - dev->slot = best; - up(&best->mutex); - } - } - up(&dt9812_mutex); - return 0; error: @@ -1109,11 +1041,9 @@ static int __init usb_dt9812_init(void) /* Initialize all driver slots */ for (i = 0; i < DT9812_NUM_SLOTS; i++) { sema_init(&dt9812[i].mutex, 1); - dt9812[i].serial = 0; dt9812[i].usb = NULL; dt9812[i].devpriv = NULL; } - dt9812[12].serial = 0x0; return comedi_usb_driver_register(&dt9812_comedi_driver, &dt9812_usb_driver); -- 1.8.1.4 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/devel