summaryrefslogtreecommitdiff
path: root/drivers/staging/comedi/drivers/dt9812.c
diff options
context:
space:
mode:
authorH Hartley Sweeten <hsweeten@visionengravers.com>2013-05-14 14:30:20 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-05-16 16:26:00 -0700
commitb78750c1234d2abafb12c61a9e96c7860f47a6e7 (patch)
treeba641d1d2e7a8ae07a40764f13955e03e7116620 /drivers/staging/comedi/drivers/dt9812.c
parent8db1eba1e267bcd8d524eab3bdc2357b6d770f33 (diff)
staging: comedi: dt9812: convert to use comedi (*auto_attach)
Converting this driver to use the comedi (*auto_attach) mechanism allows pushing the usb (*probe) into the comedi (*auto_attach) and the usb (disconnect) into the comedi (*detach). This removes the disconnect between the usb driver and the comedi driver. Now when the comedi driver is attached it will always have a usb device associated with it. This removes the 16 usb device limitation and allows bringing all the private data into a single struct that can be kzalloc'ed when the comedi driver is (*auto_attached). It also allows removing the the sanity checks that make sure a usb device is connected to the comedi device in the helper functions. For aesthetic reasons, add some whitespace to the subdevice init. Also, fix the analog out subdevice. There are 2 analog output channels available on the usb device. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Cc: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/comedi/drivers/dt9812.c')
-rw-r--r--drivers/staging/comedi/drivers/dt9812.c458
1 files changed, 173 insertions, 285 deletions
diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
index 57bdb06921e3..0efff288a86a 100644
--- a/drivers/staging/comedi/drivers/dt9812.c
+++ b/drivers/staging/comedi/drivers/dt9812.c
@@ -45,7 +45,6 @@ for my needs.
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
-#include <linux/kref.h>
#include <linux/uaccess.h>
#include <linux/usb.h>
@@ -258,55 +257,26 @@ struct dt9812_usb_cmd {
#endif
};
-#define DT9812_NUM_SLOTS 16
-
-static DEFINE_SEMAPHORE(dt9812_mutex);
-
-struct usb_dt9812 {
- struct slot_dt9812 *slot;
- struct usb_device *udev;
- u16 vendor;
- u16 product;
- u16 device;
- u32 serial;
+struct dt9812_private {
+ struct semaphore sem;
struct {
__u8 addr;
size_t size;
} cmd_wr, cmd_rd;
- struct kref kref;
-};
-
-struct dt9812_private {
- struct semaphore sem;
- struct slot_dt9812 *slot;
+ u32 serial;
+ u16 vendor;
+ u16 product;
+ u16 device;
u16 ao_shadow[2];
u8 do_shadow;
};
-struct slot_dt9812 {
- struct usb_dt9812 *usb;
- struct dt9812_private *devpriv;
-};
-
-static struct slot_dt9812 dt9812[DT9812_NUM_SLOTS];
-
-static inline struct usb_dt9812 *to_dt9812_dev(struct kref *d)
-{
- return container_of(d, struct usb_dt9812, kref);
-}
-
-static void dt9812_delete(struct kref *kref)
-{
- struct usb_dt9812 *dev = to_dt9812_dev(kref);
-
- usb_put_dev(dev->udev);
- kfree(dev);
-}
-
-static int dt9812_read_info(struct usb_dt9812 *dev, int offset, void *buf,
- size_t buf_size)
+static int dt9812_read_info(struct comedi_device *dev,
+ int offset, void *buf, size_t buf_size)
{
- struct usb_device *usb = dev->udev;
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
+ struct usb_device *usb = interface_to_usbdev(intf);
+ struct dt9812_private *devpriv = dev->private;
struct dt9812_usb_cmd cmd;
int count, ret;
@@ -316,19 +286,22 @@ static int dt9812_read_info(struct usb_dt9812 *dev, int offset, void *buf,
cmd.u.flash_data_info.numbytes = cpu_to_le16(buf_size);
/* DT9812 only responds to 32 byte writes!! */
- ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, dev->cmd_wr.addr),
+ ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr),
&cmd, 32, &count, HZ * 1);
if (ret)
return ret;
- return usb_bulk_msg(usb, usb_rcvbulkpipe(usb, dev->cmd_rd.addr),
+ return usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr),
buf, buf_size, &count, HZ * 1);
}
-static int dt9812_read_multiple_registers(struct usb_dt9812 *dev, int reg_count,
- u8 *address, u8 *value)
+static int dt9812_read_multiple_registers(struct comedi_device *dev,
+ int reg_count, u8 *address,
+ u8 *value)
{
- struct usb_device *usb = dev->udev;
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
+ struct usb_device *usb = interface_to_usbdev(intf);
+ struct dt9812_private *devpriv = dev->private;
struct dt9812_usb_cmd cmd;
int i, count, ret;
@@ -338,20 +311,22 @@ static int dt9812_read_multiple_registers(struct usb_dt9812 *dev, int reg_count,
cmd.u.read_multi_info.address[i] = address[i];
/* DT9812 only responds to 32 byte writes!! */
- ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, dev->cmd_wr.addr),
+ ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr),
&cmd, 32, &count, HZ * 1);
if (ret)
return ret;
- return usb_bulk_msg(usb, usb_rcvbulkpipe(usb, dev->cmd_rd.addr),
+ return usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr),
value, reg_count, &count, HZ * 1);
}
-static int dt9812_write_multiple_registers(struct usb_dt9812 *dev,
+static int dt9812_write_multiple_registers(struct comedi_device *dev,
int reg_count, u8 *address,
u8 *value)
{
- struct usb_device *usb = dev->udev;
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
+ struct usb_device *usb = interface_to_usbdev(intf);
+ struct dt9812_private *devpriv = dev->private;
struct dt9812_usb_cmd cmd;
int i, count;
@@ -363,14 +338,17 @@ static int dt9812_write_multiple_registers(struct usb_dt9812 *dev,
}
/* DT9812 only responds to 32 byte writes!! */
- return usb_bulk_msg(usb, usb_sndbulkpipe(usb, dev->cmd_wr.addr),
+ return usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr),
&cmd, 32, &count, HZ * 1);
}
-static int dt9812_rmw_multiple_registers(struct usb_dt9812 *dev, int reg_count,
+static int dt9812_rmw_multiple_registers(struct comedi_device *dev,
+ int reg_count,
struct dt9812_rmw_byte *rmw)
{
- struct usb_device *usb = dev->udev;
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
+ struct usb_device *usb = interface_to_usbdev(intf);
+ struct dt9812_private *devpriv = dev->private;
struct dt9812_usb_cmd cmd;
int i, count;
@@ -380,30 +358,26 @@ static int dt9812_rmw_multiple_registers(struct usb_dt9812 *dev, int reg_count,
cmd.u.rmw_multi_info.rmw[i] = rmw[i];
/* DT9812 only responds to 32 byte writes!! */
- return usb_bulk_msg(usb, usb_sndbulkpipe(usb, dev->cmd_wr.addr),
+ return usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr),
&cmd, 32, &count, HZ * 1);
}
static int dt9812_digital_in(struct comedi_device *dev, u8 *bits)
{
struct dt9812_private *devpriv = dev->private;
- struct slot_dt9812 *slot = devpriv->slot;
- int ret = -ENODEV;
+ u8 reg[2] = { F020_SFR_P3, F020_SFR_P1 };
+ u8 value[2];
+ int ret;
down(&devpriv->sem);
- if (slot->usb) {
- u8 reg[2] = { F020_SFR_P3, F020_SFR_P1 };
- u8 value[2];
-
- ret = dt9812_read_multiple_registers(slot->usb, 2, reg, value);
- if (ret == 0) {
- /*
- * bits 0-6 in F020_SFR_P3 are bits 0-6 in the digital
- * input port bit 3 in F020_SFR_P1 is bit 7 in the
- * digital input port
- */
- *bits = (value[0] & 0x7f) | ((value[1] & 0x08) << 4);
- }
+ ret = dt9812_read_multiple_registers(dev, 2, reg, value);
+ if (ret == 0) {
+ /*
+ * bits 0-6 in F020_SFR_P3 are bits 0-6 in the digital
+ * input port bit 3 in F020_SFR_P1 is bit 7 in the
+ * digital input port
+ */
+ *bits = (value[0] & 0x7f) | ((value[1] & 0x08) << 4);
}
up(&devpriv->sem);
@@ -413,17 +387,13 @@ static int dt9812_digital_in(struct comedi_device *dev, u8 *bits)
static int dt9812_digital_out(struct comedi_device *dev, u8 bits)
{
struct dt9812_private *devpriv = dev->private;
- struct slot_dt9812 *slot = devpriv->slot;
- int ret = -ENODEV;
+ u8 reg[1] = { F020_SFR_P2 };
+ u8 value[1] = { bits };
+ int ret;
down(&devpriv->sem);
- if (slot->usb) {
- u8 reg[1] = { F020_SFR_P2 };
- u8 value[1] = { bits };
-
- ret = dt9812_write_multiple_registers(slot->usb, 1, reg, value);
- devpriv->do_shadow = bits;
- }
+ ret = dt9812_write_multiple_registers(dev, 1, reg, value);
+ devpriv->do_shadow = bits;
up(&devpriv->sem);
return ret;
@@ -444,10 +414,8 @@ static void dt9812_configure_mux(struct comedi_device *dev,
struct dt9812_rmw_byte *rmw, int channel)
{
struct dt9812_private *devpriv = dev->private;
- struct slot_dt9812 *slot = devpriv->slot;
- struct usb_dt9812 *usb = slot->usb;
- if (usb->device == DT9812_DEVID_DT9812_10) {
+ if (devpriv->device == DT9812_DEVID_DT9812_10) {
/* In the DT9812/10V MUX is selected by P1.5-7 */
rmw->address = F020_SFR_P1;
rmw->and_mask = 0xe0;
@@ -465,11 +433,9 @@ static void dt9812_configure_gain(struct comedi_device *dev,
enum dt9812_gain gain)
{
struct dt9812_private *devpriv = dev->private;
- struct slot_dt9812 *slot = devpriv->slot;
- struct usb_dt9812 *usb = slot->usb;
/* In the DT9812/10V, there is an external gain of 0.5 */
- if (usb->device == DT9812_DEVID_DT9812_10)
+ if (devpriv->device == DT9812_DEVID_DT9812_10)
gain <<= 1;
rmw->address = F020_SFR_ADC0CF;
@@ -516,7 +482,6 @@ static int dt9812_analog_in(struct comedi_device *dev,
int channel, u16 *value, enum dt9812_gain gain)
{
struct dt9812_private *devpriv = dev->private;
- struct slot_dt9812 *slot = devpriv->slot;
struct dt9812_rmw_byte rmw[3];
u8 reg[3] = {
F020_SFR_ADC0CN,
@@ -524,11 +489,9 @@ static int dt9812_analog_in(struct comedi_device *dev,
F020_SFR_ADC0L
};
u8 val[3];
- int ret = -ENODEV;
+ int ret;
down(&devpriv->sem);
- if (!slot->usb)
- goto exit;
/* 1 select the gain */
dt9812_configure_gain(dev, &rmw[0], gain);
@@ -541,12 +504,12 @@ static int dt9812_analog_in(struct comedi_device *dev,
rmw[2].and_mask = 0xff;
rmw[2].or_value = F020_MASK_ADC0CN_AD0EN | F020_MASK_ADC0CN_AD0BUSY;
- ret = dt9812_rmw_multiple_registers(slot->usb, 3, rmw);
+ ret = dt9812_rmw_multiple_registers(dev, 3, rmw);
if (ret)
goto exit;
/* read the status and ADC */
- ret = dt9812_read_multiple_registers(slot->usb, 3, reg, val);
+ ret = dt9812_read_multiple_registers(dev, 3, reg, val);
if (ret)
goto exit;
@@ -561,7 +524,7 @@ static int dt9812_analog_in(struct comedi_device *dev,
*/
if ((val[0] & (F020_MASK_ADC0CN_AD0INT | F020_MASK_ADC0CN_AD0BUSY)) ==
F020_MASK_ADC0CN_AD0INT) {
- switch (slot->usb->device) {
+ switch (devpriv->device) {
case DT9812_DEVID_DT9812_10:
/*
* For DT9812-10V the personality module set the
@@ -597,53 +560,51 @@ static int dt9812_analog_out_shadow(struct comedi_device *dev,
static int dt9812_analog_out(struct comedi_device *dev, int channel, u16 value)
{
struct dt9812_private *devpriv = dev->private;
- struct slot_dt9812 *slot = devpriv->slot;
- int ret = -ENODEV;
+ struct dt9812_rmw_byte rmw[3];
+ int ret;
down(&devpriv->sem);
- if (slot->usb) {
- struct dt9812_rmw_byte rmw[3];
- switch (channel) {
- case 0:
- /* 1. Set DAC mode */
- rmw[0].address = F020_SFR_DAC0CN;
- rmw[0].and_mask = 0xff;
- rmw[0].or_value = F020_MASK_DACxCN_DACxEN;
-
- /* 2 load low byte of DAC value first */
- rmw[1].address = F020_SFR_DAC0L;
- rmw[1].and_mask = 0xff;
- rmw[1].or_value = value & 0xff;
-
- /* 3 load high byte of DAC value next to latch the
- 12-bit value */
- rmw[2].address = F020_SFR_DAC0H;
- rmw[2].and_mask = 0xff;
- rmw[2].or_value = (value >> 8) & 0xf;
- break;
+ switch (channel) {
+ case 0:
+ /* 1. Set DAC mode */
+ rmw[0].address = F020_SFR_DAC0CN;
+ rmw[0].and_mask = 0xff;
+ rmw[0].or_value = F020_MASK_DACxCN_DACxEN;
+
+ /* 2 load low byte of DAC value first */
+ rmw[1].address = F020_SFR_DAC0L;
+ rmw[1].and_mask = 0xff;
+ rmw[1].or_value = value & 0xff;
+
+ /* 3 load high byte of DAC value next to latch the
+ 12-bit value */
+ rmw[2].address = F020_SFR_DAC0H;
+ rmw[2].and_mask = 0xff;
+ rmw[2].or_value = (value >> 8) & 0xf;
+ break;
- case 1:
- /* 1. Set DAC mode */
- rmw[0].address = F020_SFR_DAC1CN;
- rmw[0].and_mask = 0xff;
- rmw[0].or_value = F020_MASK_DACxCN_DACxEN;
-
- /* 2 load low byte of DAC value first */
- rmw[1].address = F020_SFR_DAC1L;
- rmw[1].and_mask = 0xff;
- rmw[1].or_value = value & 0xff;
-
- /* 3 load high byte of DAC value next to latch the
- 12-bit value */
- rmw[2].address = F020_SFR_DAC1H;
- rmw[2].and_mask = 0xff;
- rmw[2].or_value = (value >> 8) & 0xf;
- break;
- }
- ret = dt9812_rmw_multiple_registers(slot->usb, 3, rmw);
- devpriv->ao_shadow[channel] = value;
+ case 1:
+ /* 1. Set DAC mode */
+ rmw[0].address = F020_SFR_DAC1CN;
+ rmw[0].and_mask = 0xff;
+ rmw[0].or_value = F020_MASK_DACxCN_DACxEN;
+
+ /* 2 load low byte of DAC value first */
+ rmw[1].address = F020_SFR_DAC1L;
+ rmw[1].and_mask = 0xff;
+ rmw[1].or_value = value & 0xff;
+
+ /* 3 load high byte of DAC value next to latch the
+ 12-bit value */
+ rmw[2].address = F020_SFR_DAC1H;
+ rmw[2].and_mask = 0xff;
+ rmw[2].or_value = (value >> 8) & 0xf;
+ break;
}
+ ret = dt9812_rmw_multiple_registers(dev, 3, rmw);
+ devpriv->ao_shadow[channel] = value;
+
up(&devpriv->sem);
return ret;
@@ -727,10 +688,11 @@ static int dt9812_ao_winsn(struct comedi_device *dev,
return n;
}
-static int dt9812_find_endpoints(struct usb_interface *intf,
- struct usb_dt9812 *devpriv)
+static int dt9812_find_endpoints(struct comedi_device *dev)
{
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
struct usb_host_interface *host = intf->cur_altsetting;
+ struct dt9812_private *devpriv = dev->private;
struct usb_endpoint_descriptor *ep;
int i;
@@ -774,24 +736,26 @@ static int dt9812_find_endpoints(struct usb_interface *intf,
return 0;
}
-static int dt9812_reset_device(struct usb_interface *intf,
- struct usb_dt9812 *devpriv)
+static int dt9812_reset_device(struct comedi_device *dev)
{
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
+ struct usb_device *usb = interface_to_usbdev(intf);
+ struct dt9812_private *devpriv = dev->private;
int ret;
int i;
u32 tmp32;
u16 tmp16;
u8 tmp8;
- ret = dt9812_read_info(devpriv, 0, &tmp8, sizeof(tmp8));
+ ret = dt9812_read_info(dev, 0, &tmp8, sizeof(tmp8));
if (ret) {
/*
* Seems like a configuration reset is necessary if driver is
* reloaded while device is attached
*/
- usb_reset_configuration(devpriv->udev);
+ usb_reset_configuration(usb);
for (i = 0; i < 10; i++) {
- ret = dt9812_read_info(devpriv, 1, &tmp8, sizeof(tmp8));
+ ret = dt9812_read_info(dev, 1, &tmp8, sizeof(tmp8));
if (ret == 0)
break;
}
@@ -801,28 +765,28 @@ static int dt9812_reset_device(struct usb_interface *intf,
}
}
- ret = dt9812_read_info(devpriv, 1, &tmp16, sizeof(tmp16));
+ ret = dt9812_read_info(dev, 1, &tmp16, sizeof(tmp16));
if (ret) {
dev_err(&intf->dev, "failed to read vendor id\n");
return ret;
}
devpriv->vendor = le16_to_cpu(tmp16);
- ret = dt9812_read_info(devpriv, 3, &tmp16, sizeof(tmp16));
+ ret = dt9812_read_info(dev, 3, &tmp16, sizeof(tmp16));
if (ret) {
dev_err(&intf->dev, "failed to read product id\n");
return ret;
}
devpriv->product = le16_to_cpu(tmp16);
- ret = dt9812_read_info(devpriv, 5, &tmp16, sizeof(tmp16));
+ ret = dt9812_read_info(dev, 5, &tmp16, sizeof(tmp16));
if (ret) {
dev_err(&intf->dev, "failed to read device id\n");
return ret;
}
devpriv->device = le16_to_cpu(tmp16);
- ret = dt9812_read_info(devpriv, 7, &tmp32, sizeof(tmp32));
+ ret = dt9812_read_info(dev, 7, &tmp32, sizeof(tmp32));
if (ret) {
dev_err(&intf->dev, "failed to read serial number\n");
return ret;
@@ -837,11 +801,11 @@ static int dt9812_reset_device(struct usb_interface *intf,
return 0;
}
-static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int dt9812_auto_attach(struct comedi_device *dev,
+ unsigned long context)
{
- struct slot_dt9812 *slot = NULL;
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
struct dt9812_private *devpriv;
- int i;
struct comedi_subdevice *s;
bool is_unipolar;
int ret;
@@ -850,186 +814,110 @@ static int dt9812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (!devpriv)
return -ENOMEM;
dev->private = devpriv;
- sema_init(&devpriv->sem, 1);
- down(&dt9812_mutex);
+ sema_init(&devpriv->sem, 1);
+ usb_set_intfdata(intf, devpriv);
- /*
- * Find the first unused slot for the comedi device
- * that has a usb device connected.
- */
- 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;
- }
+ ret = dt9812_find_endpoints(dev);
+ if (ret)
+ return ret;
- slot->devpriv = devpriv;
- devpriv->slot = slot;
- is_unipolar = (slot->usb->device == DT9812_DEVID_DT9812_2PT5);
+ ret = dt9812_reset_device(dev);
+ if (ret)
+ return ret;
- up(&dt9812_mutex);
+ is_unipolar = (devpriv->device == DT9812_DEVID_DT9812_2PT5);
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
return ret;
- /* digital input subdevice */
+ /* Digital Input subdevice */
s = &dev->subdevices[0];
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
- s->n_chan = 8;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_read = &dt9812_di_rinsn;
-
- /* digital output subdevice */
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 8;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_read = dt9812_di_rinsn;
+
+ /* Digital Output subdevice */
s = &dev->subdevices[1];
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITEABLE;
- s->n_chan = 8;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_write = &dt9812_do_winsn;
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITEABLE;
+ s->n_chan = 8;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_write = dt9812_do_winsn;
devpriv->do_shadow = 0;
- /* analog input subdevice */
+ /* Analog Input subdevice */
s = &dev->subdevices[2];
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND;
- s->n_chan = 8;
- s->maxdata = 4095;
- s->range_table = is_unipolar ? &range_unipolar2_5 : &range_bipolar10;
- s->insn_read = &dt9812_ai_rinsn;
-
- /* analog output subdevice */
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND;
+ s->n_chan = 8;
+ s->maxdata = 0x0fff;
+ s->range_table = is_unipolar ? &range_unipolar2_5 : &range_bipolar10;
+ s->insn_read = dt9812_ai_rinsn;
+
+ /* Analog Output subdevice */
s = &dev->subdevices[3];
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE;
- s->n_chan = 0;
- s->maxdata = 4095;
- s->range_table = is_unipolar ? &range_unipolar2_5 : &range_bipolar10;
- s->insn_write = &dt9812_ao_winsn;
- s->insn_read = &dt9812_ao_rinsn;
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITEABLE;
+ s->n_chan = 2;
+ s->maxdata = 0x0fff;
+ s->range_table = is_unipolar ? &range_unipolar2_5 : &range_bipolar10;
+ s->insn_write = dt9812_ao_winsn;
+ s->insn_read = dt9812_ao_rinsn;
devpriv->ao_shadow[0] = is_unipolar ? 0x0000 : 0x0800;
devpriv->ao_shadow[1] = is_unipolar ? 0x0000 : 0x0800;
- dev_info(dev->class_dev, "successfully attached to dt9812.\n");
-
return 0;
}
static void dt9812_detach(struct comedi_device *dev)
{
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
struct dt9812_private *devpriv = dev->private;
- if (devpriv && devpriv->slot)
- devpriv->slot = NULL;
-}
-
-static struct comedi_driver dt9812_comedi_driver = {
- .module = THIS_MODULE,
- .driver_name = "dt9812",
- .attach = dt9812_attach,
- .detach = dt9812_detach,
-};
-
-static int dt9812_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct slot_dt9812 *slot = NULL;
- struct usb_dt9812 *dev = NULL;
- int retval = -ENOMEM;
- int i;
-
- /* allocate memory for our device state and initialize it */
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (dev == NULL)
- goto error;
-
- 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;
- }
-
- slot->usb = dev;
- dev->slot = slot;
-
- up(&dt9812_mutex);
-
- dev->udev = usb_get_dev(interface_to_usbdev(intf));
-
- retval = dt9812_find_endpoints(intf, dev);
- if (retval)
- goto error;
-
- retval = dt9812_reset_device(intf, dev);
- if (retval)
- goto error;
+ if (!devpriv)
+ return;
- /* save our data pointer in this interface device */
- usb_set_intfdata(intf, dev);
+ down(&devpriv->sem);
- return 0;
+ usb_set_intfdata(intf, NULL);
-error:
- if (dev)
- kref_put(&dev->kref, dt9812_delete);
- return retval;
+ up(&devpriv->sem);
}
-static void dt9812_disconnect(struct usb_interface *intf)
-{
- struct usb_dt9812 *dev;
- int minor = intf->minor;
-
- down(&dt9812_mutex);
- dev = usb_get_intfdata(intf);
- if (dev->slot) {
- dev->slot->usb = NULL;
- dev->slot = NULL;
- }
- usb_set_intfdata(intf, NULL);
- up(&dt9812_mutex);
-
- /* queue final destruction */
- kref_put(&dev->kref, dt9812_delete);
+static struct comedi_driver dt9812_driver = {
+ .driver_name = "dt9812",
+ .module = THIS_MODULE,
+ .auto_attach = dt9812_auto_attach,
+ .detach = dt9812_detach,
+};
- dev_info(&intf->dev, "USB Dt9812 #%d now disconnected\n", minor);
+static int dt9812_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return comedi_usb_auto_config(intf, &dt9812_driver, id->driver_info);
}
-static const struct usb_device_id dt9812_table[] = {
+static const struct usb_device_id dt9812_usb_table[] = {
{ USB_DEVICE(0x0867, 0x9812) },
{ }
};
-MODULE_DEVICE_TABLE(usb, dt9812_table);
+MODULE_DEVICE_TABLE(usb, dt9812_usb_table);
static struct usb_driver dt9812_usb_driver = {
.name = "dt9812",
- .id_table = dt9812_table,
- .probe = dt9812_probe,
- .disconnect = dt9812_disconnect,
+ .id_table = dt9812_usb_table,
+ .probe = dt9812_usb_probe,
+ .disconnect = comedi_usb_auto_unconfig,
};
-module_comedi_usb_driver(dt9812_comedi_driver, dt9812_usb_driver);
+module_comedi_usb_driver(dt9812_driver, dt9812_usb_driver);
MODULE_AUTHOR("Anders Blomdell <anders.blomdell@control.lth.se>");
MODULE_DESCRIPTION("Comedi DT9812 driver");