Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1415003f authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman
Browse files

staging: comedi: dt9812: remove attaching by serial number



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: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 98c83cfa
Loading
Loading
Loading
Loading
+58 −128
Original line number Diff line number Diff line
@@ -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);