/* must have more buffers due to buggy USB ctr */
#define NUMOFOUTBUFFERSHIGH 10
-/* Total number of usbdux devices */
-#define NUMUSBDUX 16
-
/* Analogue in subdevice */
#define SUBDEV_AD 0
};
struct usbdux_private {
- /* attached? */
- int attached;
- /* is it associated with a subdevice? */
- int probed;
/* pointer to the usb-device */
struct usb_device *usbdev;
/* actual number of in-buffers */
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 usbdux_private usbduxsub[NUMUSBDUX];
-
-static DEFINE_SEMAPHORE(start_stop_sem);
-
/*
* Stops the data acquision
* It should be safe to call this function from any context
/* prevent other CPUs from submitting new commands just now */
down(&this_usbduxsub->sem);
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
/* unlink only if the urb really has been submitted */
res = usbdux_ai_stop(this_usbduxsub, this_usbduxsub->ai_cmd_running);
up(&this_usbduxsub->sem);
/* prevent other CPUs from submitting a command just now */
down(&this_usbduxsub->sem);
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
/* unlink only if it is really running */
res = usbdux_ao_stop(this_usbduxsub, this_usbduxsub->ao_cmd_running);
up(&this_usbduxsub->sem);
int err = 0, i;
unsigned int tmp_timer;
- if (!(this_usbduxsub->probed))
- return -ENODEV;
-
/* Step 1 : check if triggers are trivially valid */
err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
return -EFAULT;
down(&this_usbduxsub->sem);
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
dev_dbg(&this_usbduxsub->interface->dev,
"comedi%d: usbdux_ai_inttrig\n", dev->minor);
/* block other CPUs from starting an ai_cmd */
down(&this_usbduxsub->sem);
-
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
if (this_usbduxsub->ai_cmd_running) {
dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
"ai_cmd not possible. Another ai_cmd is running.\n",
dev->minor, insn->n, insn->subdev);
down(&this_usbduxsub->sem);
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
if (this_usbduxsub->ai_cmd_running) {
dev_err(&this_usbduxsub->interface->dev,
"comedi%d: ai_insn_read not possible. "
return -EFAULT;
down(&this_usbduxsub->sem);
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
for (i = 0; i < insn->n; i++)
data[i] = this_usbduxsub->out_buffer[chan];
"comedi%d: ao_insn_write\n", dev->minor);
down(&this_usbduxsub->sem);
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
if (this_usbduxsub->ao_cmd_running) {
dev_err(&this_usbduxsub->interface->dev,
"comedi%d: ao_insn_write: "
return -EFAULT;
down(&this_usbduxsub->sem);
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
if (trignum != 0) {
dev_err(&this_usbduxsub->interface->dev,
"comedi%d: usbdux_ao_inttrig: invalid trignum\n",
if (!this_usbduxsub)
return -EFAULT;
- if (!(this_usbduxsub->probed))
- return -ENODEV;
-
/* Step 1 : check if triggers are trivially valid */
err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
return -EFAULT;
down(&this_usbduxsub->sem);
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
dev_dbg(&this_usbduxsub->interface->dev,
"comedi%d: %s\n", dev->minor, __func__);
down(&this_usbduxsub->sem);
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
-
/* The insn data is a mask in data[0] and the new data
* in data[1], each channel cooresponding to a bit. */
s->state &= ~data[0];
return -EFAULT;
down(&this_usbduxsub->sem);
-
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
-
err = send_dux_commands(this_usbduxsub, READCOUNTERCOMMAND);
if (err < 0) {
up(&this_usbduxsub->sem);
return -EFAULT;
down(&this_usbduxsub->sem);
-
- if (!(this_usbduxsub->probed)) {
- up(&this_usbduxsub->sem);
- return -ENODEV;
- }
-
this_usbduxsub->dux_commands[1] = insn->chanspec;
*((int16_t *) (this_usbduxsub->dux_commands + 2)) = cpu_to_le16(*data);
if (usbduxsub_tmp->interface)
usb_set_intfdata(usbduxsub_tmp->interface, NULL);
- usbduxsub_tmp->probed = 0;
-
if (usbduxsub_tmp->urb_in) {
if (usbduxsub_tmp->ai_cmd_running) {
usbduxsub_tmp->ai_cmd_running = 0;
usbduxsub_tmp->pwm_cmd_running = 0;
}
-static int usbdux_attach_common(struct comedi_device *dev,
- struct usbdux_private *udev)
+static int usbdux_attach_common(struct comedi_device *dev)
{
+ struct usbdux_private *udev = dev->private;
int ret;
struct comedi_subdevice *s = NULL;
int n_subdevs;
return ret;
}
- /* private structure is also simply the usb-structure */
- dev->private = udev;
-
/* the first subdevice is the A/D converter */
s = &dev->subdevices[SUBDEV_AD];
/* the URBs get the comedi subdevice */
s->insn_config = usbdux_pwm_config;
usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
}
- /* finally decide that it's attached */
- udev->attached = 1;
up(&udev->sem);
static int usbdux_auto_attach(struct comedi_device *dev,
unsigned long context_unused)
{
- struct usb_interface *uinterf = comedi_to_usb_interface(dev);
- struct usbdux_private *this_usbduxsub = usb_get_intfdata(uinterf);
- struct usb_device *usb = usbduxsub->usbdev;
- int ret;
-
- dev->private = this_usbduxsub; /* This is temporary... */
- ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
- usbdux_firmware_upload, 0);
- if (ret < 0) {
- dev->private = NULL;
- return ret;
- }
-
- dev->private = NULL;
-
- down(&start_stop_sem);
- if (!this_usbduxsub || !this_usbduxsub->probed) {
- dev_err(dev->class_dev,
- "usbdux: error: auto_attach failed, not connected\n");
- ret = -ENODEV;
- } else if (this_usbduxsub->attached) {
- dev_err(dev->class_dev,
- "error: auto_attach failed, already attached\n");
- ret = -ENODEV;
- } else
- ret = usbdux_attach_common(dev, this_usbduxsub);
- up(&start_stop_sem);
- return ret;
-}
-
-static void usbdux_detach(struct comedi_device *dev)
-{
- struct usbdux_private *devpriv = dev->private;
-
- down(&start_stop_sem);
- if (devpriv) {
- down(&devpriv->sem);
- tidy_up(devpriv);
- dev->private = NULL;
- devpriv->attached = 0;
- devpriv->comedidev = NULL;
- up(&devpriv->sem);
- }
- up(&start_stop_sem);
-}
-
-static struct comedi_driver usbdux_driver = {
- .driver_name = "usbdux",
- .module = THIS_MODULE,
- .auto_attach = usbdux_auto_attach,
- .detach = usbdux_detach,
-};
-
-static int usbdux_usb_probe(struct usb_interface *uinterf,
- const struct usb_device_id *id)
-{
- struct usb_device *udev = interface_to_usbdev(uinterf);
- struct device *dev = &uinterf->dev;
- struct usbdux_private *devpriv = NULL;
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
+ struct usb_device *usb = comedi_to_usb_dev(dev);
+ struct usbdux_private *devpriv;
int ret;
- int i;
- down(&start_stop_sem);
-
- for (i = 0; i < NUMUSBDUX; i++) {
- if (!usbduxsub[i].probed) {
- devpriv = &usbduxsub[i];
- break;
- }
- }
- if (!devpriv) {
- dev_err(dev, "Too many usbdux-devices connected.\n");
- up(&start_stop_sem);
- return -EMFILE;
- }
+ devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
+ if (!devpriv)
+ return -ENOMEM;
sema_init(&devpriv->sem, 1);
- devpriv->usbdev = udev;
- devpriv->interface = uinterf;
- devpriv->ifnum = uinterf->altsetting->desc.bInterfaceNumber;
- usb_set_intfdata(uinterf, devpriv);
+ devpriv->usbdev = usb;
+ devpriv->interface = intf;
+ devpriv->ifnum = intf->altsetting->desc.bInterfaceNumber;
+ usb_set_intfdata(intf, devpriv);
devpriv->high_speed = (devpriv->usbdev->speed == USB_SPEED_HIGH);
if (devpriv->high_speed) {
} else {
devpriv->num_in_buffers = NUMOFINBUFFERSFULL;
devpriv->num_out_buffers = NUMOFOUTBUFFERSFULL;
- devpriv->size_pwm_buf = 0;
}
ret = usbdux_alloc_usb_buffers(devpriv);
if (ret) {
tidy_up(devpriv);
- up(&start_stop_sem);
return ret;
}
/* setting to alternate setting 3: enabling iso ep and bulk ep. */
ret = usb_set_interface(devpriv->usbdev, devpriv->ifnum, 3);
if (ret < 0) {
- dev_err(dev,
+ dev_err(dev->class_dev,
"could not set alternate setting 3 in high speed\n");
tidy_up(devpriv);
- up(&start_stop_sem);
return ret;
}
- devpriv->ai_cmd_running = 0;
- devpriv->ao_cmd_running = 0;
- devpriv->pwm_cmd_running = 0;
+ ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
+ usbdux_firmware_upload, 0);
+ if (ret < 0)
+ return ret;
- /* we've reached the bottom of the function */
- devpriv->probed = 1;
- up(&start_stop_sem);
+ return usbdux_attach_common(dev);
+}
+
+static void usbdux_detach(struct comedi_device *dev)
+{
+ struct usbdux_private *devpriv = dev->private;
- return comedi_usb_auto_config(uinterf, &usbdux_driver, 0);
+ if (devpriv) {
+ down(&devpriv->sem);
+ tidy_up(devpriv);
+ devpriv->comedidev = NULL;
+ up(&devpriv->sem);
+ }
+}
+
+static struct comedi_driver usbdux_driver = {
+ .driver_name = "usbdux",
+ .module = THIS_MODULE,
+ .auto_attach = usbdux_auto_attach,
+ .detach = usbdux_detach,
+};
+
+static int usbdux_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return comedi_usb_auto_config(intf, &usbdux_driver, 0);
}
static const struct usb_device_id usbdux_usb_table[] = {
{ USB_DEVICE(0x13d8, 0x0002) },
{ }
};
-
MODULE_DEVICE_TABLE(usb, usbdux_usb_table);
static struct usb_driver usbdux_usb_driver = {