struct semaphore sem;
};
-/*
- * The pointer to the private usb-data of the driver
- * is also the private data for the comedi-device.
- * This has to be global as the usb subsystem needs
- * global variables. The other reason is that this
- * structure must be there _before_ any comedi
- * command is issued. The usb subsystem must be
- * initialised before comedi can access it.
- */
-static struct usbduxfast_private usbduxfastsub[NUMUSBDUXFAST];
-
-static DEFINE_SEMAPHORE(start_stop_sem);
-
/*
* bulk transfers to usbduxfast
*/
devpriv->ai_cmd_running = 0;
}
-static int usbduxfast_attach_common(struct comedi_device *dev,
- struct usbduxfast_private *devpriv)
+static int usbduxfast_attach_common(struct comedi_device *dev)
{
+ struct usbduxfast_private *devpriv = dev->private;
struct comedi_subdevice *s;
int ret;
down(&devpriv->sem);
- devpriv->comedidev = dev;
-
ret = comedi_alloc_subdevices(dev, 1);
if (ret) {
up(&devpriv->sem);
return ret;
}
- dev->private = devpriv;
-
/* Analog Input subdevice */
s = &dev->subdevices[SUBDEV_AD];
dev->read_subdev = s;
return 0;
}
-static int usbduxfast_auto_attach(struct comedi_device *dev,
- unsigned long context_unused)
-{
- struct usb_interface *intf = comedi_to_usb_interface(dev);
- struct usbduxfast_private *devpriv;
- int ret;
-
- dev->private = NULL;
- down(&start_stop_sem);
- devpriv = usb_get_intfdata(intf);
- if (!devpriv || !devpriv->probed) {
- dev_err(dev->class_dev,
- "usbduxfast: error: auto_attach failed, not connected\n");
- ret = -ENODEV;
- } else if (devpriv->attached) {
- dev_err(dev->class_dev,
- "usbduxfast: error: auto_attach failed, already attached\n");
- ret = -ENODEV;
- } else
- ret = usbduxfast_attach_common(dev, devpriv);
- up(&start_stop_sem);
- return ret;
-}
-
-static void usbduxfast_detach(struct comedi_device *dev)
-{
- struct usbduxfast_private *devpriv = dev->private;
-
- if (devpriv) {
- down(&devpriv->sem);
- down(&start_stop_sem);
- dev->private = NULL;
- devpriv->attached = 0;
- devpriv->comedidev = NULL;
- tidy_up(devpriv);
- up(&start_stop_sem);
- up(&devpriv->sem);
- }
-}
-
-static struct comedi_driver usbduxfast_driver = {
- .driver_name = "usbduxfast",
- .module = THIS_MODULE,
- .auto_attach = usbduxfast_auto_attach,
- .detach = usbduxfast_detach,
-};
-
static int usbduxfast_request_firmware(struct usb_interface *intf)
{
struct usb_device *usb = interface_to_usbdev(intf);
return ret;
}
-static int usbduxfast_usb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
+static int usbduxfast_auto_attach(struct comedi_device *dev,
+ unsigned long context_unused)
{
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
struct usb_device *usb = interface_to_usbdev(intf);
- struct usbduxfast_private *devpriv = NULL;
- int i;
+ struct usbduxfast_private *devpriv;
int ret;
if (usb->speed != USB_SPEED_HIGH) {
return -ENODEV;
}
- down(&start_stop_sem);
- /* look for a free place in the usbduxfast array */
- for (i = 0; i < NUMUSBDUXFAST; i++) {
- if (!usbduxfastsub[i].probed) {
- devpriv = &usbduxfastsub[i];
- break;
- }
- }
-
- /* no more space */
- if (!devpriv) {
- dev_err(&intf->dev,
- "Too many usbduxfast-devices connected.\n");
- up(&start_stop_sem);
- return -EMFILE;
- }
+ devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
+ if (!devpriv)
+ return -ENOMEM;
+ dev->private = devpriv;
sema_init(&devpriv->sem, 1);
+ devpriv->comedidev = dev;
devpriv->usb = usb;
devpriv->intf = intf;
devpriv->ifnum = intf->altsetting->desc.bInterfaceNumber;
devpriv->dux_commands = kmalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
if (!devpriv->dux_commands) {
tidy_up(devpriv);
- up(&start_stop_sem);
return -ENOMEM;
}
devpriv->insnBuffer = kmalloc(SIZEINSNBUF, GFP_KERNEL);
if (!devpriv->insnBuffer) {
tidy_up(devpriv);
- up(&start_stop_sem);
return -ENOMEM;
}
- i = usb_set_interface(devpriv->usb, devpriv->ifnum, 1);
- if (i < 0) {
+ ret = usb_set_interface(devpriv->usb, devpriv->ifnum, 1);
+ if (ret < 0) {
dev_err(&intf->dev,
"could not switch to alternate setting 1\n");
tidy_up(devpriv);
- up(&start_stop_sem);
return -ENODEV;
}
if (!devpriv->urbIn) {
dev_err(&intf->dev, "Could not alloc. urb\n");
tidy_up(devpriv);
- up(&start_stop_sem);
return -ENOMEM;
}
devpriv->transfer_buffer = kmalloc(SIZEINBUF, GFP_KERNEL);
if (!devpriv->transfer_buffer) {
tidy_up(devpriv);
- up(&start_stop_sem);
return -ENOMEM;
}
devpriv->probed = 1;
- up(&start_stop_sem);
/*
* Request, and upload, the firmware so we can
return ret;
}
+ return usbduxfast_attach_common(dev);
+}
+
+static void usbduxfast_detach(struct comedi_device *dev)
+{
+ struct usbduxfast_private *devpriv = dev->private;
+
+ if (devpriv) {
+ down(&devpriv->sem);
+ devpriv->attached = 0;
+ devpriv->comedidev = NULL;
+ tidy_up(devpriv);
+ up(&devpriv->sem);
+ }
+}
+
+static struct comedi_driver usbduxfast_driver = {
+ .driver_name = "usbduxfast",
+ .module = THIS_MODULE,
+ .auto_attach = usbduxfast_auto_attach,
+ .detach = usbduxfast_detach,
+};
+
+static int usbduxfast_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
return comedi_usb_auto_config(intf, &usbduxfast_driver, 0);
}