diff options
Diffstat (limited to 'drivers/staging/comedi/drivers/serial2002.c')
-rw-r--r-- | drivers/staging/comedi/drivers/serial2002.c | 895 |
1 files changed, 415 insertions, 480 deletions
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index e6177b48cca..8900086374d 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -31,8 +31,6 @@ Status: in development */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include "../comedidev.h" #include <linux/delay.h> @@ -72,7 +70,40 @@ struct serial_data { unsigned long value; }; -static long tty_ioctl(struct file *f, unsigned op, unsigned long param) +/* + * The configuration serial_data.value read from the device is + * a bitmask that defines specific options of a channel: + * + * 4:0 - the channel to configure + * 7:5 - the kind of channel + * 9:8 - the command used to configure the channel + * + * The remaining bits vary in use depending on the command: + * + * BITS 15:10 - the channel bits (maxdata) + * MIN/MAX 12:10 - the units multiplier for the scale + * 13 - the sign of the scale + * 33:14 - the base value for the range + */ +#define S2002_CFG_CHAN(x) ((x) & 0x1f) +#define S2002_CFG_KIND(x) (((x) >> 5) & 0x7) +#define S2002_CFG_KIND_INVALID 0 +#define S2002_CFG_KIND_DIGITAL_IN 1 +#define S2002_CFG_KIND_DIGITAL_OUT 2 +#define S2002_CFG_KIND_ANALOG_IN 3 +#define S2002_CFG_KIND_ANALOG_OUT 4 +#define S2002_CFG_KIND_ENCODER_IN 5 +#define S2002_CFG_CMD(x) (((x) >> 8) & 0x3) +#define S2002_CFG_CMD_BITS 0 +#define S2002_CFG_CMD_MIN 1 +#define S2002_CFG_CMD_MAX 2 +#define S2002_CFG_BITS(x) (((x) >> 10) & 0x3f) +#define S2002_CFG_UNITS(x) (((x) >> 10) & 0x7) +#define S2002_CFG_SIGN(x) (((x) >> 13) & 0x1) +#define S2002_CFG_BASE(x) (((x) >> 14) & 0xfffff) + +static long serial2002_tty_ioctl(struct file *f, unsigned op, + unsigned long param) { if (f->f_op->unlocked_ioctl) return f->f_op->unlocked_ioctl(f, op, param); @@ -80,39 +111,58 @@ static long tty_ioctl(struct file *f, unsigned op, unsigned long param) return -ENOSYS; } -static int tty_write(struct file *f, unsigned char *buf, int count) +static int serial2002_tty_write(struct file *f, unsigned char *buf, int count) { + const char __user *p = (__force const char __user *)buf; int result; mm_segment_t oldfs; oldfs = get_fs(); set_fs(KERNEL_DS); f->f_pos = 0; - result = f->f_op->write(f, buf, count, &f->f_pos); + result = f->f_op->write(f, p, count, &f->f_pos); set_fs(oldfs); return result; } -#if 0 -/* - * On 2.6.26.3 this occaisonally gave me page faults, worked around by - * settings.c_cc[VMIN] = 0; settings.c_cc[VTIME] = 0 - */ -static int tty_available(struct file *f) +static int serial2002_tty_readb(struct file *f, unsigned char *buf) { - long result = 0; - mm_segment_t oldfs; + char __user *p = (__force char __user *)buf; - oldfs = get_fs(); - set_fs(KERNEL_DS); - tty_ioctl(f, FIONREAD, (unsigned long)&result); - set_fs(oldfs); - return result; + f->f_pos = 0; + return f->f_op->read(f, p, 1, &f->f_pos); +} + +static void serial2002_tty_read_poll_wait(struct file *f, int timeout) +{ + struct poll_wqueues table; + struct timeval start, now; + + do_gettimeofday(&start); + poll_initwait(&table); + while (1) { + long elapsed; + int mask; + + mask = f->f_op->poll(f, &table.pt); + if (mask & (POLLRDNORM | POLLRDBAND | POLLIN | + POLLHUP | POLLERR)) { + break; + } + do_gettimeofday(&now); + elapsed = (1000000 * (now.tv_sec - start.tv_sec) + + now.tv_usec - start.tv_usec); + if (elapsed > timeout) + break; + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(((timeout - elapsed) * HZ) / 10000); + } + poll_freewait(&table); } -#endif -static int tty_read(struct file *f, int timeout) +static int serial2002_tty_read(struct file *f, int timeout) { + unsigned char ch; int result; result = -1; @@ -122,50 +172,19 @@ static int tty_read(struct file *f, int timeout) oldfs = get_fs(); set_fs(KERNEL_DS); if (f->f_op->poll) { - struct poll_wqueues table; - struct timeval start, now; - - do_gettimeofday(&start); - poll_initwait(&table); - while (1) { - long elapsed; - int mask; - - mask = f->f_op->poll(f, &table.pt); - if (mask & (POLLRDNORM | POLLRDBAND | POLLIN | - POLLHUP | POLLERR)) { - break; - } - do_gettimeofday(&now); - elapsed = - (1000000 * (now.tv_sec - start.tv_sec) + - now.tv_usec - start.tv_usec); - if (elapsed > timeout) - break; - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(((timeout - - elapsed) * HZ) / 10000); - } - poll_freewait(&table); - { - unsigned char ch; + serial2002_tty_read_poll_wait(f, timeout); - f->f_pos = 0; - if (f->f_op->read(f, &ch, 1, &f->f_pos) == 1) - result = ch; - } + if (serial2002_tty_readb(f, &ch) == 1) + result = ch; } else { /* Device does not support poll, busy wait */ int retries = 0; while (1) { - unsigned char ch; - retries++; if (retries >= timeout) break; - f->f_pos = 0; - if (f->f_op->read(f, &ch, 1, &f->f_pos) == 1) { + if (serial2002_tty_readb(f, &ch) == 1) { result = ch; break; } @@ -177,90 +196,76 @@ static int tty_read(struct file *f, int timeout) return result; } -static void tty_setspeed(struct file *f, int speed) +static void serial2002_tty_setspeed(struct file *f, int speed) { + struct termios termios; + struct serial_struct serial; mm_segment_t oldfs; oldfs = get_fs(); set_fs(KERNEL_DS); - { - /* Set speed */ - struct termios settings; - - tty_ioctl(f, TCGETS, (unsigned long)&settings); -/* printk("Speed: %d\n", settings.c_cflag & (CBAUD | CBAUDEX)); */ - settings.c_iflag = 0; - settings.c_oflag = 0; - settings.c_lflag = 0; - settings.c_cflag = CLOCAL | CS8 | CREAD; - settings.c_cc[VMIN] = 0; - settings.c_cc[VTIME] = 0; - switch (speed) { - case 2400:{ - settings.c_cflag |= B2400; - } - break; - case 4800:{ - settings.c_cflag |= B4800; - } - break; - case 9600:{ - settings.c_cflag |= B9600; - } - break; - case 19200:{ - settings.c_cflag |= B19200; - } - break; - case 38400:{ - settings.c_cflag |= B38400; - } - break; - case 57600:{ - settings.c_cflag |= B57600; - } - break; - case 115200:{ - settings.c_cflag |= B115200; - } - break; - default:{ - settings.c_cflag |= B9600; - } - break; - } - tty_ioctl(f, TCSETS, (unsigned long)&settings); -/* printk("Speed: %d\n", settings.c_cflag & (CBAUD | CBAUDEX)); */ - } - { - /* Set low latency */ - struct serial_struct settings; - tty_ioctl(f, TIOCGSERIAL, (unsigned long)&settings); - settings.flags |= ASYNC_LOW_LATENCY; - tty_ioctl(f, TIOCSSERIAL, (unsigned long)&settings); + /* Set speed */ + serial2002_tty_ioctl(f, TCGETS, (unsigned long)&termios); + termios.c_iflag = 0; + termios.c_oflag = 0; + termios.c_lflag = 0; + termios.c_cflag = CLOCAL | CS8 | CREAD; + termios.c_cc[VMIN] = 0; + termios.c_cc[VTIME] = 0; + switch (speed) { + case 2400: + termios.c_cflag |= B2400; + break; + case 4800: + termios.c_cflag |= B4800; + break; + case 9600: + termios.c_cflag |= B9600; + break; + case 19200: + termios.c_cflag |= B19200; + break; + case 38400: + termios.c_cflag |= B38400; + break; + case 57600: + termios.c_cflag |= B57600; + break; + case 115200: + termios.c_cflag |= B115200; + break; + default: + termios.c_cflag |= B9600; + break; } + serial2002_tty_ioctl(f, TCSETS, (unsigned long)&termios); + + /* Set low latency */ + serial2002_tty_ioctl(f, TIOCGSERIAL, (unsigned long)&serial); + serial.flags |= ASYNC_LOW_LATENCY; + serial2002_tty_ioctl(f, TIOCSSERIAL, (unsigned long)&serial); set_fs(oldfs); } -static void poll_digital(struct file *f, int channel) +static void serial2002_poll_digital(struct file *f, int channel) { char cmd; cmd = 0x40 | (channel & 0x1f); - tty_write(f, &cmd, 1); + serial2002_tty_write(f, &cmd, 1); } -static void poll_channel(struct file *f, int channel) +static void serial2002_poll_channel(struct file *f, int channel) { char cmd; cmd = 0x60 | (channel & 0x1f); - tty_write(f, &cmd, 1); + serial2002_tty_write(f, &cmd, 1); } -static struct serial_data serial_read(struct file *f, int timeout) +static struct serial_data serial2002_read(struct file *f, int timeout) { struct serial_data result; int length; @@ -270,26 +275,23 @@ static struct serial_data serial_read(struct file *f, int timeout) result.value = 0; length = 0; while (1) { - int data = tty_read(f, timeout); + int data = serial2002_tty_read(f, timeout); length++; if (data < 0) { - pr_err("Failed to read serial.\n"); break; } else if (data & 0x80) { result.value = (result.value << 7) | (data & 0x7f); } else { if (length == 1) { switch ((data >> 5) & 0x03) { - case 0:{ - result.value = 0; - result.kind = is_digital; - } + case 0: + result.value = 0; + result.kind = is_digital; break; - case 1:{ - result.value = 1; - result.kind = is_digital; - } + case 1: + result.value = 1; + result.kind = is_digital; break; } } else { @@ -305,12 +307,12 @@ static struct serial_data serial_read(struct file *f, int timeout) } -static void serial_write(struct file *f, struct serial_data data) +static void serial2002_write(struct file *f, struct serial_data data) { if (data.kind == is_digital) { unsigned char ch = ((data.value << 5) & 0x20) | (data.index & 0x1f); - tty_write(f, &ch, 1); + serial2002_tty_write(f, &ch, 1); } else { unsigned char ch[6]; int i = 0; @@ -334,319 +336,250 @@ static void serial_write(struct file *f, struct serial_data data) i++; ch[i] = ((data.value << 5) & 0x60) | (data.index & 0x1f); i++; - tty_write(f, ch, i); + serial2002_tty_write(f, ch, i); } } -static int serial_2002_open(struct comedi_device *dev) +struct config_t { + short int kind; + short int bits; + int min; + int max; +}; + +static int serial2002_setup_subdevice(struct comedi_subdevice *s, + struct config_t *cfg, + struct serial2002_range_table_t *range, + unsigned char *mapping, + int kind) { - struct serial2002_private *devpriv = dev->private; - int result; - char port[20]; + const struct comedi_lrange **range_table_list = NULL; + unsigned int *maxdata_list; + int j, chan; - sprintf(port, "/dev/ttyS%d", devpriv->port); - devpriv->tty = filp_open(port, O_RDWR, 0); - if (IS_ERR(devpriv->tty)) { - result = (int)PTR_ERR(devpriv->tty); - dev_err(dev->class_dev, "file open error = %d\n", result); - } else { - struct config_t { - - short int kind; - short int bits; - int min; - int max; - }; - - struct config_t *dig_in_config; - struct config_t *dig_out_config; - struct config_t *chan_in_config; - struct config_t *chan_out_config; - int i; - - result = 0; - dig_in_config = kcalloc(32, sizeof(struct config_t), - GFP_KERNEL); - dig_out_config = kcalloc(32, sizeof(struct config_t), - GFP_KERNEL); - chan_in_config = kcalloc(32, sizeof(struct config_t), - GFP_KERNEL); - chan_out_config = kcalloc(32, sizeof(struct config_t), - GFP_KERNEL); - if (!dig_in_config || !dig_out_config - || !chan_in_config || !chan_out_config) { - result = -ENOMEM; - goto err_alloc_configs; + for (chan = 0, j = 0; j < 32; j++) { + if (cfg[j].kind == kind) + chan++; + } + s->n_chan = chan; + s->maxdata = 0; + kfree(s->maxdata_list); + maxdata_list = kmalloc(sizeof(unsigned int) * s->n_chan, GFP_KERNEL); + if (!maxdata_list) + return -ENOMEM; + s->maxdata_list = maxdata_list; + kfree(s->range_table_list); + s->range_table = NULL; + s->range_table_list = NULL; + if (kind == 1 || kind == 2) { + s->range_table = &range_digital; + } else if (range) { + range_table_list = + kmalloc(sizeof(struct serial2002_range_table_t) * + s->n_chan, GFP_KERNEL); + if (!range_table_list) + return -ENOMEM; + s->range_table_list = range_table_list; + } + for (chan = 0, j = 0; j < 32; j++) { + if (cfg[j].kind == kind) { + if (mapping) + mapping[chan] = j; + if (range) { + range[j].length = 1; + range[j].range.min = cfg[j].min; + range[j].range.max = cfg[j].max; + range_table_list[chan] = + (const struct comedi_lrange *)&range[j]; + } + maxdata_list[chan] = ((long long)1 << cfg[j].bits) - 1; + chan++; } + } + return 0; +} - tty_setspeed(devpriv->tty, devpriv->speed); - poll_channel(devpriv->tty, 31); /* Start reading configuration */ - while (1) { - struct serial_data data; +static int serial2002_setup_subdevs(struct comedi_device *dev) +{ + struct serial2002_private *devpriv = dev->private; + struct config_t *di_cfg; + struct config_t *do_cfg; + struct config_t *ai_cfg; + struct config_t *ao_cfg; + struct config_t *cfg; + struct comedi_subdevice *s; + int result = 0; + int i; - data = serial_read(devpriv->tty, 1000); - if (data.kind != is_channel || data.index != 31 - || !(data.value & 0xe0)) { - break; - } else { - int command, channel, kind; - struct config_t *cur_config = NULL; - - channel = data.value & 0x1f; - kind = (data.value >> 5) & 0x7; - command = (data.value >> 8) & 0x3; - switch (kind) { - case 1:{ - cur_config = dig_in_config; - } - break; - case 2:{ - cur_config = dig_out_config; - } - break; - case 3:{ - cur_config = chan_in_config; - } - break; - case 4:{ - cur_config = chan_out_config; - } - break; - case 5:{ - cur_config = chan_in_config; - } - break; - } + /* Allocate the temporary structs to hold the configuration data */ + di_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL); + do_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL); + ai_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL); + ao_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL); + if (!di_cfg || !do_cfg || !ai_cfg || !ao_cfg) { + result = -ENOMEM; + goto err_alloc_configs; + } - if (cur_config) { - cur_config[channel].kind = kind; - switch (command) { - case 0:{ - cur_config[channel].bits - = - (data.value >> 10) & - 0x3f; - } - break; - case 1:{ - int unit, sign, min; - unit = - (data.value >> 10) & - 0x7; - sign = - (data.value >> 13) & - 0x1; - min = - (data.value >> 14) & - 0xfffff; - - switch (unit) { - case 0:{ - min = - min - * - 1000000; - } - break; - case 1:{ - min = - min - * - 1000; - } - break; - case 2:{ - min = - min - * 1; - } - break; - } - if (sign) - min = -min; - cur_config[channel].min - = min; - } - break; - case 2:{ - int unit, sign, max; - unit = - (data.value >> 10) & - 0x7; - sign = - (data.value >> 13) & - 0x1; - max = - (data.value >> 14) & - 0xfffff; - - switch (unit) { - case 0:{ - max = - max - * - 1000000; - } - break; - case 1:{ - max = - max - * - 1000; - } - break; - case 2:{ - max = - max - * 1; - } - break; - } - if (sign) - max = -max; - cur_config[channel].max - = max; - } - break; - } - } - } - } - for (i = 0; i <= 4; i++) { - /* Fill in subdev data */ - struct config_t *c; - unsigned char *mapping = NULL; - struct serial2002_range_table_t *range = NULL; - int kind = 0; - - switch (i) { - case 0:{ - c = dig_in_config; - mapping = devpriv->digital_in_mapping; - kind = 1; - } + /* Read the configuration from the connected device */ + serial2002_tty_setspeed(devpriv->tty, devpriv->speed); + serial2002_poll_channel(devpriv->tty, 31); + while (1) { + struct serial_data data; + + data = serial2002_read(devpriv->tty, 1000); + if (data.kind != is_channel || data.index != 31 || + S2002_CFG_KIND(data.value) == S2002_CFG_KIND_INVALID) { + break; + } else { + int channel = S2002_CFG_CHAN(data.value); + int range = S2002_CFG_BASE(data.value); + + switch (S2002_CFG_KIND(data.value)) { + case S2002_CFG_KIND_DIGITAL_IN: + cfg = di_cfg; break; - case 1:{ - c = dig_out_config; - mapping = devpriv->digital_out_mapping; - kind = 2; - } + case S2002_CFG_KIND_DIGITAL_OUT: + cfg = do_cfg; break; - case 2:{ - c = chan_in_config; - mapping = devpriv->analog_in_mapping; - range = devpriv->in_range; - kind = 3; - } + case S2002_CFG_KIND_ANALOG_IN: + cfg = ai_cfg; break; - case 3:{ - c = chan_out_config; - mapping = devpriv->analog_out_mapping; - range = devpriv->out_range; - kind = 4; - } + case S2002_CFG_KIND_ANALOG_OUT: + cfg = ao_cfg; break; - case 4:{ - c = chan_in_config; - mapping = devpriv->encoder_in_mapping; - range = devpriv->in_range; - kind = 5; - } + case S2002_CFG_KIND_ENCODER_IN: + cfg = ai_cfg; break; - default:{ - c = NULL; - } + default: + cfg = NULL; break; } - if (c) { - struct comedi_subdevice *s; - const struct comedi_lrange **range_table_list = - NULL; - unsigned int *maxdata_list; - int j, chan; - - for (chan = 0, j = 0; j < 32; j++) { - if (c[j].kind == kind) - chan++; - } - s = &dev->subdevices[i]; - s->n_chan = chan; - s->maxdata = 0; - kfree(s->maxdata_list); - s->maxdata_list = maxdata_list = - kmalloc(sizeof(unsigned int) * s->n_chan, - GFP_KERNEL); - if (!s->maxdata_list) - break; /* error handled below */ - kfree(s->range_table_list); - s->range_table = NULL; - s->range_table_list = NULL; - if (kind == 1 || kind == 2) { - s->range_table = &range_digital; - } else if (range) { - s->range_table_list = range_table_list = - kmalloc(sizeof - (struct - serial2002_range_table_t) * - s->n_chan, GFP_KERNEL); - if (!s->range_table_list) - break; /* err handled below */ - } - for (chan = 0, j = 0; j < 32; j++) { - if (c[j].kind == kind) { - if (mapping) - mapping[chan] = j; - if (range) { - range[j].length = 1; - range[j].range.min = - c[j].min; - range[j].range.max = - c[j].max; - range_table_list[chan] = - (const struct - comedi_lrange *) - &range[j]; - } - maxdata_list[chan] = - ((long long)1 << c[j].bits) - - 1; - chan++; - } + if (!cfg) + continue; /* unknown kind, skip it */ + + cfg[channel].kind = S2002_CFG_KIND(data.value); + + switch (S2002_CFG_CMD(data.value)) { + case S2002_CFG_CMD_BITS: + cfg[channel].bits = S2002_CFG_BITS(data.value); + break; + case S2002_CFG_CMD_MIN: + case S2002_CFG_CMD_MAX: + switch (S2002_CFG_UNITS(data.value)) { + case 0: + range *= 1000000; + break; + case 1: + range *= 1000; + break; + case 2: + range *= 1; + break; } + if (S2002_CFG_SIGN(data.value)) + range = -range; + if (S2002_CFG_CMD(data.value) == + S2002_CFG_CMD_MIN) + cfg[channel].min = range; + else + cfg[channel].max = range; + break; } } - if (i <= 4) { - /* Failed to allocate maxdata_list or range_table_list - * for a subdevice that needed it. */ - result = -ENOMEM; - for (i = 0; i <= 4; i++) { - struct comedi_subdevice *s; - - s = &dev->subdevices[i]; - kfree(s->maxdata_list); - s->maxdata_list = NULL; - kfree(s->range_table_list); - s->range_table_list = NULL; - } + } + + /* Fill in subdevice data */ + for (i = 0; i <= 4; i++) { + unsigned char *mapping = NULL; + struct serial2002_range_table_t *range = NULL; + int kind = 0; + + s = &dev->subdevices[i]; + + switch (i) { + case 0: + cfg = di_cfg; + mapping = devpriv->digital_in_mapping; + kind = S2002_CFG_KIND_DIGITAL_IN; + break; + case 1: + cfg = do_cfg; + mapping = devpriv->digital_out_mapping; + kind = S2002_CFG_KIND_DIGITAL_OUT; + break; + case 2: + cfg = ai_cfg; + mapping = devpriv->analog_in_mapping; + range = devpriv->in_range; + kind = S2002_CFG_KIND_ANALOG_IN; + break; + case 3: + cfg = ao_cfg; + mapping = devpriv->analog_out_mapping; + range = devpriv->out_range; + kind = S2002_CFG_KIND_ANALOG_OUT; + break; + case 4: + cfg = ai_cfg; + mapping = devpriv->encoder_in_mapping; + range = devpriv->in_range; + kind = S2002_CFG_KIND_ENCODER_IN; + break; } + if (serial2002_setup_subdevice(s, cfg, range, mapping, kind)) + break; /* err handled below */ + } + if (i <= 4) { + /* + * Failed to allocate maxdata_list or range_table_list + * for a subdevice that needed it. + */ + result = -ENOMEM; + for (i = 0; i <= 4; i++) { + s = &dev->subdevices[i]; + kfree(s->maxdata_list); + s->maxdata_list = NULL; + kfree(s->range_table_list); + s->range_table_list = NULL; + } + } + err_alloc_configs: - kfree(dig_in_config); - kfree(dig_out_config); - kfree(chan_in_config); - kfree(chan_out_config); - - if (result) { - if (devpriv->tty) { - filp_close(devpriv->tty, NULL); - devpriv->tty = NULL; - } + kfree(di_cfg); + kfree(do_cfg); + kfree(ai_cfg); + kfree(ao_cfg); + + if (result) { + if (devpriv->tty) { + filp_close(devpriv->tty, NULL); + devpriv->tty = NULL; } } + + return result; +} + +static int serial2002_open(struct comedi_device *dev) +{ + struct serial2002_private *devpriv = dev->private; + int result; + char port[20]; + + sprintf(port, "/dev/ttyS%d", devpriv->port); + devpriv->tty = filp_open(port, O_RDWR, 0); + if (IS_ERR(devpriv->tty)) { + result = (int)PTR_ERR(devpriv->tty); + dev_err(dev->class_dev, "file open error = %d\n", result); + } else { + result = serial2002_setup_subdevs(dev); + } return result; } -static void serial_2002_close(struct comedi_device *dev) +static void serial2002_close(struct comedi_device *dev) { struct serial2002_private *devpriv = dev->private; @@ -654,9 +587,10 @@ static void serial_2002_close(struct comedi_device *dev) filp_close(devpriv->tty, NULL); } -static int serial2002_di_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int serial2002_di_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct serial2002_private *devpriv = dev->private; int n; @@ -666,9 +600,9 @@ static int serial2002_di_rinsn(struct comedi_device *dev, for (n = 0; n < insn->n; n++) { struct serial_data read; - poll_digital(devpriv->tty, chan); + serial2002_poll_digital(devpriv->tty, chan); while (1) { - read = serial_read(devpriv->tty, 1000); + read = serial2002_read(devpriv->tty, 1000); if (read.kind != is_digital || read.index == chan) break; } @@ -677,9 +611,10 @@ static int serial2002_di_rinsn(struct comedi_device *dev, return n; } -static int serial2002_do_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int serial2002_do_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct serial2002_private *devpriv = dev->private; int n; @@ -692,14 +627,15 @@ static int serial2002_do_winsn(struct comedi_device *dev, write.kind = is_digital; write.index = chan; write.value = data[n]; - serial_write(devpriv->tty, write); + serial2002_write(devpriv->tty, write); } return n; } -static int serial2002_ai_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int serial2002_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct serial2002_private *devpriv = dev->private; int n; @@ -709,9 +645,9 @@ static int serial2002_ai_rinsn(struct comedi_device *dev, for (n = 0; n < insn->n; n++) { struct serial_data read; - poll_channel(devpriv->tty, chan); + serial2002_poll_channel(devpriv->tty, chan); while (1) { - read = serial_read(devpriv->tty, 1000); + read = serial2002_read(devpriv->tty, 1000); if (read.kind != is_channel || read.index == chan) break; } @@ -720,9 +656,10 @@ static int serial2002_ai_rinsn(struct comedi_device *dev, return n; } -static int serial2002_ao_winsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int serial2002_ao_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct serial2002_private *devpriv = dev->private; int n; @@ -735,15 +672,16 @@ static int serial2002_ao_winsn(struct comedi_device *dev, write.kind = is_channel; write.index = chan; write.value = data[n]; - serial_write(devpriv->tty, write); + serial2002_write(devpriv->tty, write); devpriv->ao_readback[chan] = data[n]; } return n; } -static int serial2002_ao_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int serial2002_ao_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct serial2002_private *devpriv = dev->private; int n; @@ -755,9 +693,10 @@ static int serial2002_ao_rinsn(struct comedi_device *dev, return n; } -static int serial2002_ei_rinsn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int serial2002_encoder_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct serial2002_private *devpriv = dev->private; int n; @@ -767,9 +706,9 @@ static int serial2002_ei_rinsn(struct comedi_device *dev, for (n = 0; n < insn->n; n++) { struct serial_data read; - poll_channel(devpriv->tty, chan); + serial2002_poll_channel(devpriv->tty, chan); while (1) { - read = serial_read(devpriv->tty, 1000); + read = serial2002_read(devpriv->tty, 1000); if (read.kind != is_channel || read.index == chan) break; } @@ -785,20 +724,13 @@ static int serial2002_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev_dbg(dev->class_dev, "serial2002: attach\n"); - dev->board_name = dev->driver->driver_name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); if (!devpriv) return -ENOMEM; dev->private = devpriv; - dev->open = serial_2002_open; - dev->close = serial_2002_close; devpriv->port = it->options[0]; devpriv->speed = it->options[1]; - dev_dbg(dev->class_dev, "/dev/ttyS%d @ %d\n", devpriv->port, - devpriv->speed); ret = comedi_alloc_subdevices(dev, 5); if (ret) @@ -806,51 +738,54 @@ static int serial2002_attach(struct comedi_device *dev, /* digital input subdevice */ s = &dev->subdevices[0]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 0; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_read = &serial2002_di_rinsn; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 0; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_read = serial2002_di_insn_read; /* digital output subdevice */ s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITEABLE; - s->n_chan = 0; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_write = &serial2002_do_winsn; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITEABLE; + s->n_chan = 0; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_write = serial2002_do_insn_write; /* analog input subdevice */ 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->insn_read = &serial2002_ai_rinsn; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + s->n_chan = 0; + s->maxdata = 1; + s->range_table = NULL; + s->insn_read = serial2002_ai_insn_read; /* analog output subdevice */ s = &dev->subdevices[3]; - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITEABLE; - s->n_chan = 0; - s->maxdata = 1; - s->range_table = NULL; - s->insn_write = &serial2002_ao_winsn; - s->insn_read = &serial2002_ao_rinsn; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITEABLE; + s->n_chan = 0; + s->maxdata = 1; + s->range_table = NULL; + s->insn_write = serial2002_ao_insn_write; + s->insn_read = serial2002_ao_insn_read; /* encoder input subdevice */ s = &dev->subdevices[4]; - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_READABLE | SDF_LSAMPL; - s->n_chan = 0; - s->maxdata = 1; - s->range_table = NULL; - s->insn_read = &serial2002_ei_rinsn; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_LSAMPL; + s->n_chan = 0; + s->maxdata = 1; + s->range_table = NULL; + s->insn_read = serial2002_encoder_insn_read; + + dev->open = serial2002_open; + dev->close = serial2002_close; - return 1; + return 0; } static void serial2002_detach(struct comedi_device *dev) @@ -858,7 +793,7 @@ static void serial2002_detach(struct comedi_device *dev) struct comedi_subdevice *s; int i; - for (i = 0; i < 5; i++) { + for (i = 0; i < dev->n_subdevices; i++) { s = &dev->subdevices[i]; kfree(s->maxdata_list); kfree(s->range_table_list); |