-#define DRIVER_VERSION "v0.99a"
+#define DRIVER_VERSION "v1.0"
#define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com"
#define DRIVER_DESC "USB-DUXfast, BerndPorr@f2s.com"
/*
/*
Driver: usbduxfast
-Description: ITL USB-DUXfast
-Devices: [ITL] USB-DUX (usbduxfast.o)
-Author: Bernd Porr <BerndPorr@f2s.com>
-Updated: 04 Dec 2006
-Status: testing
+Description: Driver for USB-DUX-FAST of INCITE Technology Limited
+Devices: [ITL] USB-DUX (usbduxfast)
+Author: Bernd Porr <tech@linux-usb-daq.co.uk>
+Updated: 13 May 2012
+Status: stable
+
+The device has one subdevice for analogue input.
+ - subdevice: 0
+ number of channels: 16
+ max data value: 4096
+ ranges:
+ all channelss:
+ range = 0 : [-0.75 V,0.75 V]
+ range = 1 : [-0.5 V,0.5 V]
+ command:
+ The channel-list allows 1,2,3 and 16 channels.
+ start: now|ext|int (external trigger via pin at HD-D connector)
+ scan_begin: follow|timer|ext
+ convert: timer|ext (contains the sampling interval. Min interval
+ for single channel acquisition is 33us
+ and for multiplexed acquisition 300us)
+ scan_end: count
+ stop: none|count
+
+Configuration options:
+ The device requires firmware which is usually
+ uploaded automatically by udev/hotplug at the moment
+ the driver module is being loaded.
+ In case udev/hotplug is not enabled you need to upload
+ the firmware with comedi_config -i usbduxfast_firmware.bin
+ The firmware is usually installed under /lib/firmware
+ or can be downloaded form http://www.linux-usb-daq.co.uk.
*/
/*
* Added insn command basically for testing. Sample rate is 1MHz/16ch=62.5kHz
* 0.99: Ian Abbott pointed out a bug which has been corrected. Thanks!
* 0.99a: added external trigger.
+ * 1.00: added firmware kernel request to the driver which fixed
+ * udev coldplug problem
*/
#include <linux/kernel.h>
+#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/usb.h>
-#include <linux/smp_lock.h>
#include <linux/fcntl.h>
#include <linux/compiler.h>
#include "comedi_fc.h"
#define BOARDNAME "usbduxfast"
// timeout for the USB-transfer
-#define EZTIMEOUT 30
+#define BULK_TIMEOUT 1000
// constants for "firmware" upload and download
#define USBDUXFASTSUB_FIRMWARE 0xA0
uint8_t *dux_commands;
// counter which ignores the first buffers
int ignore;
- struct semaphore sem;
+ struct mutex mutex;
} usbduxfastsub_t;
// The pointer to the private usb-data of the driver
// initialised before comedi can access it.
static usbduxfastsub_t usbduxfastsub[NUMUSBDUXFAST];
-static DECLARE_MUTEX(start_stop_sem);
+static DEFINE_MUTEX(start_stop_mutex);
// bulk transfers to usbduxfast
usb_sndbulkpipe(this_usbduxfastsub->usbdev,
CHANNELLISTEP),
this_usbduxfastsub->dux_commands,
- SIZEOFDUXBUFFER, &nsent, 10000);
+ SIZEOFDUXBUFFER, &nsent, BULK_TIMEOUT);
if (result < 0) {
printk("comedi%d: could not transmit dux_commands to the usb-device, err=%d\n", this_usbduxfastsub->comedidev->minor, result);
}
printk("comedi: usbduxfast_ai_cancel: this_usbduxfastsub=NULL\n");
return -EFAULT;
}
- down(&this_usbduxfastsub->sem);
+ mutex_lock(&this_usbduxfastsub->mutex);
if (!(this_usbduxfastsub->probed)) {
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return -ENODEV;
}
// unlink
res = usbduxfast_ai_stop(this_usbduxfastsub, 1);
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return res;
}
this_usbduxfastsub->ai_sample_count -= n;
}
// write the full buffer to comedi
- cfc_write_array_to_buffer(s,
- urb->transfer_buffer, urb->actual_length);
+ err = cfc_write_array_to_buffer(s,
+ urb->transfer_buffer, urb->actual_length);
+
+ if (unlikely(err == 0)) {
+ /* buffer overflow */
+ usbduxfast_ai_stop(this_usbduxfastsub, 0);
+ return;
+ }
// tell comedi that data is there
comedi_event(this_usbduxfastsub->comedidev, s);
int errcode = 0;
unsigned char local_transfer_buffer[16];
- if (usbduxfastsub->probed) {
- // 7f92 to zero
- local_transfer_buffer[0] = 0;
- errcode = USB_CONTROL_MSG(usbduxfastsub->usbdev,
- // create a pipe for a control transfer
- usb_sndctrlpipe(usbduxfastsub->usbdev, 0),
- // bRequest, "Firmware"
- USBDUXFASTSUB_FIRMWARE,
- // bmRequestType
- VENDOR_DIR_OUT,
- // Value
- USBDUXFASTSUB_CPUCS,
- // Index
- 0x0000,
- // address of the transfer buffer
- local_transfer_buffer,
- // Length
- 1,
- // Timeout
- EZTIMEOUT);
- if (errcode < 0) {
- printk("comedi_: usbduxfast_: control msg failed (start)\n");
- return errcode;
- }
+ // 7f92 to zero
+ local_transfer_buffer[0] = 0;
+ errcode = USB_CONTROL_MSG(usbduxfastsub->usbdev,
+ // create a pipe for a control transfer
+ usb_sndctrlpipe(usbduxfastsub->usbdev, 0),
+ // bRequest, "Firmware"
+ USBDUXFASTSUB_FIRMWARE,
+ // bmRequestType
+ VENDOR_DIR_OUT,
+ // Value
+ USBDUXFASTSUB_CPUCS,
+ // Index
+ 0x0000,
+ // address of the transfer buffer
+ local_transfer_buffer,
+ // Length
+ 1,
+ // Timeout
+ BULK_TIMEOUT);
+ if (errcode < 0) {
+ printk("comedi_: usbduxfast_: control msg failed (start)\n");
+ return errcode;
}
return 0;
}
int errcode = 0;
unsigned char local_transfer_buffer[16];
- if (usbduxfastsub->probed) {
- // 7f92 to one
- local_transfer_buffer[0] = 1;
- errcode = USB_CONTROL_MSG
- (usbduxfastsub->usbdev,
- usb_sndctrlpipe(usbduxfastsub->usbdev, 0),
- // bRequest, "Firmware"
- USBDUXFASTSUB_FIRMWARE,
- // bmRequestType
- VENDOR_DIR_OUT,
- // Value
- USBDUXFASTSUB_CPUCS,
- // Index
- 0x0000, local_transfer_buffer,
- // Length
- 1,
- // Timeout
- EZTIMEOUT);
- if (errcode < 0) {
- printk("comedi_: usbduxfast: control msg failed (stop)\n");
- return errcode;
- }
+ // 7f92 to one
+ local_transfer_buffer[0] = 1;
+ errcode = USB_CONTROL_MSG
+ (usbduxfastsub->usbdev,
+ usb_sndctrlpipe(usbduxfastsub->usbdev, 0),
+ // bRequest, "Firmware"
+ USBDUXFASTSUB_FIRMWARE,
+ // bmRequestType
+ VENDOR_DIR_OUT,
+ // Value
+ USBDUXFASTSUB_CPUCS,
+ // Index
+ 0x0000, local_transfer_buffer,
+ // Length
+ 1,
+ // Timeout
+ BULK_TIMEOUT);
+ if (errcode < 0) {
+ printk("comedi_: usbduxfast: control msg failed (stop)\n");
+ return errcode;
}
return 0;
}
{
int errcode;
- if (usbduxfastsub->probed) {
-#ifdef CONFIG_COMEDI_DEBUG
- printk("comedi%d: usbduxfast: uploading %d bytes",
- usbduxfastsub->comedidev->minor, len);
- printk(" to addr %d, first byte=%d.\n",
- startAddr, local_transfer_buffer[0]);
-#endif
- errcode = USB_CONTROL_MSG
- (usbduxfastsub->usbdev,
- usb_sndctrlpipe(usbduxfastsub->usbdev, 0),
- // brequest, firmware
- USBDUXFASTSUB_FIRMWARE,
- // bmRequestType
- VENDOR_DIR_OUT,
- // value
- startAddr,
- // index
- 0x0000,
- // our local safe buffer
- local_transfer_buffer,
- // length
- len,
- // timeout
- EZTIMEOUT);
-#ifdef CONFIG_COMEDI_DEBUG
- printk("comedi_: usbduxfast: result=%d\n", errcode);
-#endif
- if (errcode < 0) {
- printk("comedi_: usbduxfast: uppload failed\n");
- return errcode;
- }
- } else {
- // no device on the bus for this index
- return -EFAULT;
+ errcode = USB_CONTROL_MSG
+ (usbduxfastsub->usbdev,
+ usb_sndctrlpipe(usbduxfastsub->usbdev, 0),
+ // brequest, firmware
+ USBDUXFASTSUB_FIRMWARE,
+ // bmRequestType
+ VENDOR_DIR_OUT,
+ // value
+ startAddr,
+ // index
+ 0x0000,
+ // our local safe buffer
+ local_transfer_buffer,
+ // length
+ len,
+ // timeout
+ BULK_TIMEOUT);
+ if (errcode < 0) {
+ printk("comedi_: usbduxfast: uppload failed\n");
+ return errcode;
}
return 0;
}
if (!this_usbduxfastsub) {
return -EFAULT;
}
- down(&this_usbduxfastsub->sem);
+ mutex_lock(&this_usbduxfastsub->mutex);
if (!(this_usbduxfastsub->probed)) {
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return -ENODEV;
}
#ifdef CONFIG_COMEDI_DEBUG
if (trignum != 0) {
printk("comedi%d: usbduxfast_ai_inttrig: invalid trignum\n",
dev->minor);
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return -EINVAL;
}
if (!(this_usbduxfastsub->ai_cmd_running)) {
if (ret < 0) {
printk("comedi%d: usbduxfast_ai_inttrig: urbSubmit: err=%d\n", dev->minor, ret);
this_usbduxfastsub->ai_cmd_running = 0;
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return ret;
}
s->async->inttrig = NULL;
printk("comedi%d: ai_inttrig but acqu is already running\n",
dev->minor);
}
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return 1;
}
if (!this_usbduxfastsub) {
return -EFAULT;
}
- down(&this_usbduxfastsub->sem);
+ mutex_lock(&this_usbduxfastsub->mutex);
if (!(this_usbduxfastsub->probed)) {
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return -ENODEV;
}
if (this_usbduxfastsub->ai_cmd_running) {
printk("comedi%d: ai_cmd not possible. Another ai_cmd is running.\n", dev->minor);
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return -EBUSY;
}
// set current channel of the running aquisition to zero
chan = CR_CHAN(cmd->chanlist[i]);
if (chan != i) {
printk("comedi%d: cmd is accepting only consecutive channels.\n", dev->minor);
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return -EINVAL;
}
if ((gain != CR_RANGE(cmd->chanlist[i]))
&& (cmd->chanlist_len > 3)) {
printk("comedi%d: the gain must be the same for all channels.\n", dev->minor);
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return -EINVAL;
}
if (i >= NUMCHANNELS) {
steps = 0;
if (cmd->scan_begin_src == TRIG_TIMER) {
printk("comedi%d: usbduxfast: scan_begin_src==TRIG_TIMER not valid.\n", dev->minor);
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return -EINVAL;
}
if (cmd->convert_src == TRIG_TIMER) {
}
if ((steps < MIN_SAMPLING_PERIOD) && (cmd->chanlist_len != 1)) {
printk("comedi%d: usbduxfast: ai_cmd: steps=%ld, scan_begin_arg=%d. Not properly tested by cmdtest?\n", dev->minor, steps, cmd->scan_begin_arg);
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return -EINVAL;
}
if (steps > MAX_SAMPLING_PERIOD) {
printk("comedi%d: usbduxfast: ai_cmd: sampling rate too low.\n",
dev->minor);
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return -EINVAL;
}
if ((cmd->start_src == TRIG_EXT) && (cmd->chanlist_len != 1)
&& (cmd->chanlist_len != 16)) {
printk("comedi%d: usbduxfast: ai_cmd: TRIG_EXT only with 1 or 16 channels possible.\n", dev->minor);
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return -EINVAL;
}
#ifdef CONFIG_COMEDI_DEBUG
default:
printk("comedi %d: unsupported combination of channels\n",
dev->minor);
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return -EFAULT;
}
result = send_dux_commands(this_usbduxfastsub, SENDADCOMMANDS);
if (result < 0) {
printk("comedi%d: adc command could not be submitted. Aborting...\n", dev->minor);
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return result;
}
if (cmd->stop_src == TRIG_COUNT) {
(cmd->stop_arg) * (cmd->scan_end_arg);
if (usbduxfastsub->ai_sample_count < 1) {
printk("comedi%d: (cmd->stop_arg)*(cmd->scan_end_arg)<1, aborting.\n", dev->minor);
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return -EFAULT;
}
this_usbduxfastsub->ai_continous = 0;
if (ret < 0) {
this_usbduxfastsub->ai_cmd_running = 0;
// fixme: unlink here??
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return ret;
}
s->async->inttrig = NULL;
// wait for an internal signal
s->async->inttrig = usbduxfast_ai_inttrig;
}
- up(&this_usbduxfastsub->sem);
+ mutex_unlock(&this_usbduxfastsub->mutex);
return 0;
}
printk("comedi%d: ai_insn_read, insn->n=%d, insn->subdev=%d\n",
dev->minor, insn->n, insn->subdev);
#endif
- down(&usbduxfastsub->sem);
+ mutex_lock(&usbduxfastsub->mutex);
if (!(usbduxfastsub->probed)) {
- up(&usbduxfastsub->sem);
+ mutex_unlock(&usbduxfastsub->mutex);
return -ENODEV;
}
if (usbduxfastsub->ai_cmd_running) {
printk("comedi%d: ai_insn_read not possible. Async Command is running.\n", dev->minor);
- up(&usbduxfastsub->sem);
+ mutex_unlock(&usbduxfastsub->mutex);
return -EBUSY;
}
// sample one channel
err = send_dux_commands(usbduxfastsub, SENDADCOMMANDS);
if (err < 0) {
printk("comedi%d: adc command could not be submitted. Aborting...\n", dev->minor);
- up(&usbduxfastsub->sem);
+ mutex_unlock(&usbduxfastsub->mutex);
return err;
}
#ifdef CONFIG_COMEDI_DEBUG
err = USB_BULK_MSG(usbduxfastsub->usbdev,
usb_rcvbulkpipe(usbduxfastsub->usbdev, BULKINEP),
usbduxfastsub->transfer_buffer,
- SIZEINBUF, &actual_length, 10000);
+ SIZEINBUF, &actual_length, BULK_TIMEOUT);
if (err < 0) {
printk("comedi%d: insn timeout. No data.\n",
dev->minor);
- up(&usbduxfastsub->sem);
+ mutex_unlock(&usbduxfastsub->mutex);
return err;
}
}
err = USB_BULK_MSG(usbduxfastsub->usbdev,
usb_rcvbulkpipe(usbduxfastsub->usbdev, BULKINEP),
usbduxfastsub->transfer_buffer,
- SIZEINBUF, &actual_length, 10000);
+ SIZEINBUF, &actual_length, BULK_TIMEOUT);
if (err < 0) {
printk("comedi%d: insn data error: %d\n",
dev->minor, err);
- up(&usbduxfastsub->sem);
+ mutex_unlock(&usbduxfastsub->mutex);
return err;
}
n = actual_length / sizeof(uint16_t);
if ((n % 16) != 0) {
printk("comedi%d: insn data packet corrupted.\n",
dev->minor);
- up(&usbduxfastsub->sem);
+ mutex_unlock(&usbduxfastsub->mutex);
return -EINVAL;
}
for (j = chan; (j < n) && (i < insn->n); j = j + 16) {
i++;
}
}
- up(&usbduxfastsub->sem);
+ mutex_unlock(&usbduxfastsub->mutex);
return i;
}
#define FIRMWARE_MAX_LEN 0x2000
// taken from David Brownell's fxload and adjusted for this driver
-static int read_firmware(usbduxfastsub_t * usbduxfastsub, void *firmwarePtr,
- long size)
+static int read_firmware(usbduxfastsub_t * usbduxfastsub,
+ const void *firmwarePtr,
+ long size)
{
int i = 0;
unsigned char *fp = (char *)firmwarePtr;
usbduxfastsub_tmp->ai_cmd_running = 0;
}
+static void usbduxfast_firmware_request_complete_handler(
+ const struct firmware *fw,
+ void *context)
+{
+ usbduxfastsub_t * usbduxfastsub_tmp = (usbduxfastsub_t *)context;
+ struct usb_device *usbdev = usbduxfastsub_tmp->usbdev;
+ int ret;
+
+ if(fw == NULL) {
+ return;
+ }
+
+ // we need to upload the firmware here because fw will be
+ // freed one we've left this function
+ ret=read_firmware(usbduxfastsub_tmp,
+ fw->data,
+ fw->size);
+
+ if (ret) {
+ dev_err(&usbdev->dev,
+ "Could not upload firmware (err=%d)\n",
+ ret);
+ return;
+ }
+
+ comedi_usb_auto_config(usbdev, BOARDNAME);
+}
+
// allocate memory for the urbs and initialise them
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
static void *usbduxfastsub_probe(struct usb_device *udev,
- unsigned int interfnum, const struct usb_device_id *id)
+ unsigned int interfnum,
+ const struct usb_device_id *id)
{
#else
static int usbduxfastsub_probe(struct usb_interface *uinterf,
#endif
int i;
int index;
+ int ret;
if (udev->speed != USB_SPEED_HIGH) {
printk("comedi_: usbduxfast_: This driver needs USB 2.0 to operate. Aborting...\n");
#ifdef CONFIG_COMEDI_DEBUG
printk("comedi_: usbduxfast_: finding a free structure for the usb-device\n");
#endif
- down(&start_stop_sem);
+ mutex_lock(&start_stop_mutex);
// look for a free place in the usbduxfast array
index = -1;
for (i = 0; i < NUMUSBDUXFAST; i++) {
// no more space
if (index == -1) {
printk("Too many usbduxfast-devices connected.\n");
- up(&start_stop_sem);
+ mutex_unlock(&start_stop_mutex);
return PROBE_ERR_RETURN(-EMFILE);
}
#ifdef CONFIG_COMEDI_DEBUG
printk("comedi_: usbduxfast: usbduxfastsub[%d] is ready to connect to comedi.\n", index);
#endif
- init_MUTEX(&(usbduxfastsub[index].sem));
+ mutex_init(&(usbduxfastsub[index].mutex));
// save a pointer to the usb device
usbduxfastsub[index].usbdev = udev;
if (!usbduxfastsub[index].dux_commands) {
printk("comedi_: usbduxfast: error alloc space for dac commands\n");
tidy_up(&(usbduxfastsub[index]));
- up(&start_stop_sem);
+ mutex_unlock(&start_stop_mutex);
return PROBE_ERR_RETURN(-ENOMEM);
}
// create space of the instruction buffer
if (!(usbduxfastsub[index].insnBuffer)) {
printk("comedi_: usbduxfast: could not alloc space for insnBuffer\n");
tidy_up(&(usbduxfastsub[index]));
- up(&start_stop_sem);
+ mutex_unlock(&start_stop_mutex);
return PROBE_ERR_RETURN(-ENOMEM);
}
// setting to alternate setting 1: enabling bulk ep
if (i < 0) {
printk("comedi_: usbduxfast%d: could not switch to alternate setting 1.\n", index);
tidy_up(&(usbduxfastsub[index]));
- up(&start_stop_sem);
+ mutex_unlock(&start_stop_mutex);
return PROBE_ERR_RETURN(-ENODEV);
}
usbduxfastsub[index].urbIn = USB_ALLOC_URB(0);
if (usbduxfastsub[index].urbIn == NULL) {
printk("comedi_: usbduxfast%d: Could not alloc. urb\n", index);
tidy_up(&(usbduxfastsub[index]));
- up(&start_stop_sem);
+ mutex_unlock(&start_stop_mutex);
return PROBE_ERR_RETURN(-ENOMEM);
}
usbduxfastsub[index].transfer_buffer = kmalloc(SIZEINBUF, GFP_KERNEL);
printk("comedi_: usbduxfast%d: could not alloc. transb.\n",
index);
tidy_up(&(usbduxfastsub[index]));
- up(&start_stop_sem);
+ mutex_unlock(&start_stop_mutex);
return PROBE_ERR_RETURN(-ENOMEM);
}
// we've reached the bottom of the function
usbduxfastsub[index].probed = 1;
- up(&start_stop_sem);
+ mutex_unlock(&start_stop_mutex);
+
+ ret = request_firmware_nowait(THIS_MODULE,
+ FW_ACTION_HOTPLUG,
+ "usbduxfast_firmware.hex",
+ &udev->dev,
+ GFP_KERNEL,
+ usbduxfastsub + index,
+ usbduxfast_firmware_request_complete_handler);
+
+ if (ret) {
+ dev_err(&udev->dev,
+ "could not load firmware (err=%d)\n",
+ ret);
+ return ret;
+ }
+
printk("comedi_: usbduxfast%d has been successfully initialized.\n",
- index);
+ index);
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
return (void *)(&usbduxfastsub[index]);
#else
printk("comedi_: usbduxfast: BUG! called with wrong ptr!!!\n");
return;
}
- down(&start_stop_sem);
- down(&usbduxfastsub_tmp->sem);
+
+ comedi_usb_auto_unconfig(udev);
+
+ mutex_lock(&start_stop_mutex);
+ mutex_lock(&usbduxfastsub_tmp->mutex);
tidy_up(usbduxfastsub_tmp);
- up(&usbduxfastsub_tmp->sem);
- up(&start_stop_sem);
+ mutex_unlock(&usbduxfastsub_tmp->mutex);
+ mutex_unlock(&start_stop_mutex);
#ifdef CONFIG_COMEDI_DEBUG
printk("comedi_: usbduxfast: disconnected from the usb\n");
#endif
comedi_subdevice *s = NULL;
dev->private = NULL;
- down(&start_stop_sem);
+ mutex_lock(&start_stop_mutex);
// find a valid device which has been detected by the probe function of the usb
index = -1;
for (i = 0; i < NUMUSBDUXFAST; i++) {
if (index < 0) {
printk("comedi%d: usbduxfast: error: attach failed, no usbduxfast devs connected to the usb bus.\n", dev->minor);
- up(&start_stop_sem);
+ mutex_unlock(&start_stop_mutex);
return -ENODEV;
}
- down(&(usbduxfastsub[index].sem));
+ mutex_lock(&(usbduxfastsub[index].mutex));
// pointer back to the corresponding comedi device
usbduxfastsub[index].comedidev = dev;
// trying to upload the firmware into the chip
if (comedi_aux_data(it->options, 0) &&
- it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
- read_firmware(usbduxfastsub,
- comedi_aux_data(it->options, 0),
- it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]);
+ it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
+ read_firmware(&usbduxfastsub[index],
+ comedi_aux_data(it->options, 0),
+ it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]);
}
dev->board_name = BOARDNAME;
if ((ret = alloc_subdevices(dev, N_SUBDEVICES)) < 0) {
printk("comedi%d: usbduxfast: error alloc space for subdev\n",
dev->minor);
- up(&start_stop_sem);
+ mutex_unlock(&start_stop_mutex);
return ret;
}
// finally decide that it's attached
usbduxfastsub[index].attached = 1;
- up(&(usbduxfastsub[index].sem));
+ mutex_unlock(&(usbduxfastsub[index].mutex));
- up(&start_stop_sem);
+ mutex_unlock(&start_stop_mutex);
printk("comedi%d: successfully attached to usbduxfast.\n", dev->minor);
return -EFAULT;
}
- down(&usbduxfastsub_tmp->sem);
- down(&start_stop_sem);
+ mutex_lock(&usbduxfastsub_tmp->mutex);
+ mutex_lock(&start_stop_mutex);
// Don't allow detach to free the private structure
// It's one entry of of usbduxfastsub[]
dev->private = NULL;
printk("comedi%d: usbduxfast: detach: successfully removed\n",
dev->minor);
#endif
- up(&start_stop_sem);
- up(&usbduxfastsub_tmp->sem);
+ mutex_unlock(&start_stop_mutex);
+ mutex_unlock(&usbduxfastsub_tmp->mutex);
return 0;
}
for (index = 0; index < NUMUSBDUXFAST; index++) {
memset(&(usbduxfastsub[index]), 0x00,
sizeof(usbduxfastsub[index]));
- init_MUTEX(&(usbduxfastsub[index].sem));
+ mutex_init(&(usbduxfastsub[index].mutex));
+ }
+}
+
+static void uninit_usb_devices(void)
+{
+ int index;
+
+ for (index = 0; index < NUMUSBDUXFAST; index++) {
+ mutex_destroy(&(usbduxfastsub[index].mutex));
}
}
// registering the usb-system _and_ the comedi-driver
static int init_usbduxfast(void)
{
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": "
+ DRIVER_VERSION ":" DRIVER_DESC "\n");
init_usb_devices();
usb_register(&usbduxfastsub_driver);
comedi_driver_register(&driver_usbduxfast);
{
comedi_driver_unregister(&driver_usbduxfast);
usb_deregister(&usbduxfastsub_driver);
+ uninit_usb_devices();
}
module_init(init_usbduxfast);