1 /*
2     comedi/drivers/serial2002.c
3     Skeleton code for a Comedi driver
4 
5     COMEDI - Linux Control and Measurement Device Interface
6     Copyright (C) 2002 Anders Blomdell <anders.blomdell@control.lth.se>
7 
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12 
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17 */
18 
19 /*
20 Driver: serial2002
21 Description: Driver for serial connected hardware
22 Devices:
23 Author: Anders Blomdell
24 Updated: Fri,  7 Jun 2002 12:56:45 -0700
25 Status: in development
26 
27 */
28 
29 #include <linux/module.h>
30 #include "../comedidev.h"
31 
32 #include <linux/delay.h>
33 #include <linux/sched.h>
34 #include <linux/slab.h>
35 
36 #include <linux/termios.h>
37 #include <asm/ioctls.h>
38 #include <linux/serial.h>
39 #include <linux/poll.h>
40 
41 struct serial2002_range_table_t {
42 	/*  HACK... */
43 	int length;
44 	struct comedi_krange range;
45 };
46 
47 struct serial2002_private {
48 	int port;		/*  /dev/ttyS<port> */
49 	int speed;		/*  baudrate */
50 	struct file *tty;
51 	unsigned int ao_readback[32];
52 	unsigned char digital_in_mapping[32];
53 	unsigned char digital_out_mapping[32];
54 	unsigned char analog_in_mapping[32];
55 	unsigned char analog_out_mapping[32];
56 	unsigned char encoder_in_mapping[32];
57 	struct serial2002_range_table_t in_range[32], out_range[32];
58 };
59 
60 struct serial_data {
61 	enum { is_invalid, is_digital, is_channel } kind;
62 	int index;
63 	unsigned long value;
64 };
65 
66 /*
67  * The configuration serial_data.value read from the device is
68  * a bitmask that defines specific options of a channel:
69  *
70  * 4:0 - the channel to configure
71  * 7:5 - the kind of channel
72  * 9:8 - the command used to configure the channel
73  *
74  * The remaining bits vary in use depending on the command:
75  *
76  * BITS     15:10 - the channel bits (maxdata)
77  * MIN/MAX  12:10 - the units multiplier for the scale
78  *          13    - the sign of the scale
79  *          33:14 - the base value for the range
80  */
81 #define S2002_CFG_CHAN(x)		((x) & 0x1f)
82 #define S2002_CFG_KIND(x)		(((x) >> 5) & 0x7)
83 #define S2002_CFG_KIND_INVALID		0
84 #define S2002_CFG_KIND_DIGITAL_IN	1
85 #define S2002_CFG_KIND_DIGITAL_OUT	2
86 #define S2002_CFG_KIND_ANALOG_IN	3
87 #define S2002_CFG_KIND_ANALOG_OUT	4
88 #define S2002_CFG_KIND_ENCODER_IN	5
89 #define S2002_CFG_CMD(x)		(((x) >> 8) & 0x3)
90 #define S2002_CFG_CMD_BITS		0
91 #define S2002_CFG_CMD_MIN		1
92 #define S2002_CFG_CMD_MAX		2
93 #define S2002_CFG_BITS(x)		(((x) >> 10) & 0x3f)
94 #define S2002_CFG_UNITS(x)		(((x) >> 10) & 0x7)
95 #define S2002_CFG_SIGN(x)		(((x) >> 13) & 0x1)
96 #define S2002_CFG_BASE(x)		(((x) >> 14) & 0xfffff)
97 
serial2002_tty_ioctl(struct file * f,unsigned op,unsigned long param)98 static long serial2002_tty_ioctl(struct file *f, unsigned op,
99 				 unsigned long param)
100 {
101 	if (f->f_op->unlocked_ioctl)
102 		return f->f_op->unlocked_ioctl(f, op, param);
103 
104 	return -ENOSYS;
105 }
106 
serial2002_tty_write(struct file * f,unsigned char * buf,int count)107 static int serial2002_tty_write(struct file *f, unsigned char *buf, int count)
108 {
109 	const char __user *p = (__force const char __user *)buf;
110 	int result;
111 	loff_t offset = 0;
112 	mm_segment_t oldfs;
113 
114 	oldfs = get_fs();
115 	set_fs(KERNEL_DS);
116 	result = __vfs_write(f, p, count, &offset);
117 	set_fs(oldfs);
118 	return result;
119 }
120 
serial2002_tty_read_poll_wait(struct file * f,int timeout)121 static void serial2002_tty_read_poll_wait(struct file *f, int timeout)
122 {
123 	struct poll_wqueues table;
124 	struct timeval start, now;
125 
126 	do_gettimeofday(&start);
127 	poll_initwait(&table);
128 	while (1) {
129 		long elapsed;
130 		int mask;
131 
132 		mask = f->f_op->poll(f, &table.pt);
133 		if (mask & (POLLRDNORM | POLLRDBAND | POLLIN |
134 			    POLLHUP | POLLERR)) {
135 			break;
136 		}
137 		do_gettimeofday(&now);
138 		elapsed = 1000000 * (now.tv_sec - start.tv_sec) +
139 			  now.tv_usec - start.tv_usec;
140 		if (elapsed > timeout)
141 			break;
142 		set_current_state(TASK_INTERRUPTIBLE);
143 		schedule_timeout(((timeout - elapsed) * HZ) / 10000);
144 	}
145 	poll_freewait(&table);
146 }
147 
serial2002_tty_read(struct file * f,int timeout)148 static int serial2002_tty_read(struct file *f, int timeout)
149 {
150 	unsigned char ch;
151 	int result;
152 
153 	result = -1;
154 	if (!IS_ERR(f)) {
155 		mm_segment_t oldfs;
156 		char __user *p = (__force char __user *)&ch;
157 		loff_t offset = 0;
158 
159 		oldfs = get_fs();
160 		set_fs(KERNEL_DS);
161 		if (f->f_op->poll) {
162 			serial2002_tty_read_poll_wait(f, timeout);
163 
164 			if (__vfs_read(f, p, 1, &offset) == 1)
165 				result = ch;
166 		} else {
167 			/* Device does not support poll, busy wait */
168 			int retries = 0;
169 
170 			while (1) {
171 				retries++;
172 				if (retries >= timeout)
173 					break;
174 
175 				if (__vfs_read(f, p, 1, &offset) == 1) {
176 					result = ch;
177 					break;
178 				}
179 				udelay(100);
180 			}
181 		}
182 		set_fs(oldfs);
183 	}
184 	return result;
185 }
186 
serial2002_tty_setspeed(struct file * f,int speed)187 static void serial2002_tty_setspeed(struct file *f, int speed)
188 {
189 	struct termios termios;
190 	struct serial_struct serial;
191 	mm_segment_t oldfs;
192 
193 	oldfs = get_fs();
194 	set_fs(KERNEL_DS);
195 
196 	/* Set speed */
197 	serial2002_tty_ioctl(f, TCGETS, (unsigned long)&termios);
198 	termios.c_iflag = 0;
199 	termios.c_oflag = 0;
200 	termios.c_lflag = 0;
201 	termios.c_cflag = CLOCAL | CS8 | CREAD;
202 	termios.c_cc[VMIN] = 0;
203 	termios.c_cc[VTIME] = 0;
204 	switch (speed) {
205 	case 2400:
206 		termios.c_cflag |= B2400;
207 		break;
208 	case 4800:
209 		termios.c_cflag |= B4800;
210 		break;
211 	case 9600:
212 		termios.c_cflag |= B9600;
213 		break;
214 	case 19200:
215 		termios.c_cflag |= B19200;
216 		break;
217 	case 38400:
218 		termios.c_cflag |= B38400;
219 		break;
220 	case 57600:
221 		termios.c_cflag |= B57600;
222 		break;
223 	case 115200:
224 		termios.c_cflag |= B115200;
225 		break;
226 	default:
227 		termios.c_cflag |= B9600;
228 		break;
229 	}
230 	serial2002_tty_ioctl(f, TCSETS, (unsigned long)&termios);
231 
232 	/* Set low latency */
233 	serial2002_tty_ioctl(f, TIOCGSERIAL, (unsigned long)&serial);
234 	serial.flags |= ASYNC_LOW_LATENCY;
235 	serial2002_tty_ioctl(f, TIOCSSERIAL, (unsigned long)&serial);
236 
237 	set_fs(oldfs);
238 }
239 
serial2002_poll_digital(struct file * f,int channel)240 static void serial2002_poll_digital(struct file *f, int channel)
241 {
242 	char cmd;
243 
244 	cmd = 0x40 | (channel & 0x1f);
245 	serial2002_tty_write(f, &cmd, 1);
246 }
247 
serial2002_poll_channel(struct file * f,int channel)248 static void serial2002_poll_channel(struct file *f, int channel)
249 {
250 	char cmd;
251 
252 	cmd = 0x60 | (channel & 0x1f);
253 	serial2002_tty_write(f, &cmd, 1);
254 }
255 
serial2002_read(struct file * f,int timeout)256 static struct serial_data serial2002_read(struct file *f, int timeout)
257 {
258 	struct serial_data result;
259 	int length;
260 
261 	result.kind = is_invalid;
262 	result.index = 0;
263 	result.value = 0;
264 	length = 0;
265 	while (1) {
266 		int data = serial2002_tty_read(f, timeout);
267 
268 		length++;
269 		if (data < 0) {
270 			break;
271 		} else if (data & 0x80) {
272 			result.value = (result.value << 7) | (data & 0x7f);
273 		} else {
274 			if (length == 1) {
275 				switch ((data >> 5) & 0x03) {
276 				case 0:
277 					result.value = 0;
278 					result.kind = is_digital;
279 					break;
280 				case 1:
281 					result.value = 1;
282 					result.kind = is_digital;
283 					break;
284 				}
285 			} else {
286 				result.value =
287 				    (result.value << 2) | ((data & 0x60) >> 5);
288 				result.kind = is_channel;
289 			}
290 			result.index = data & 0x1f;
291 			break;
292 		}
293 	}
294 	return result;
295 }
296 
serial2002_write(struct file * f,struct serial_data data)297 static void serial2002_write(struct file *f, struct serial_data data)
298 {
299 	if (data.kind == is_digital) {
300 		unsigned char ch =
301 		    ((data.value << 5) & 0x20) | (data.index & 0x1f);
302 		serial2002_tty_write(f, &ch, 1);
303 	} else {
304 		unsigned char ch[6];
305 		int i = 0;
306 
307 		if (data.value >= (1L << 30)) {
308 			ch[i] = 0x80 | ((data.value >> 30) & 0x03);
309 			i++;
310 		}
311 		if (data.value >= (1L << 23)) {
312 			ch[i] = 0x80 | ((data.value >> 23) & 0x7f);
313 			i++;
314 		}
315 		if (data.value >= (1L << 16)) {
316 			ch[i] = 0x80 | ((data.value >> 16) & 0x7f);
317 			i++;
318 		}
319 		if (data.value >= (1L << 9)) {
320 			ch[i] = 0x80 | ((data.value >> 9) & 0x7f);
321 			i++;
322 		}
323 		ch[i] = 0x80 | ((data.value >> 2) & 0x7f);
324 		i++;
325 		ch[i] = ((data.value << 5) & 0x60) | (data.index & 0x1f);
326 		i++;
327 		serial2002_tty_write(f, ch, i);
328 	}
329 }
330 
331 struct config_t {
332 	short int kind;
333 	short int bits;
334 	int min;
335 	int max;
336 };
337 
serial2002_setup_subdevice(struct comedi_subdevice * s,struct config_t * cfg,struct serial2002_range_table_t * range,unsigned char * mapping,int kind)338 static int serial2002_setup_subdevice(struct comedi_subdevice *s,
339 				      struct config_t *cfg,
340 				      struct serial2002_range_table_t *range,
341 				      unsigned char *mapping,
342 				      int kind)
343 {
344 	const struct comedi_lrange **range_table_list = NULL;
345 	unsigned int *maxdata_list;
346 	int j, chan;
347 
348 	for (chan = 0, j = 0; j < 32; j++) {
349 		if (cfg[j].kind == kind)
350 			chan++;
351 	}
352 	s->n_chan = chan;
353 	s->maxdata = 0;
354 	kfree(s->maxdata_list);
355 	maxdata_list = kmalloc_array(s->n_chan, sizeof(unsigned int),
356 				     GFP_KERNEL);
357 	if (!maxdata_list)
358 		return -ENOMEM;
359 	s->maxdata_list = maxdata_list;
360 	kfree(s->range_table_list);
361 	s->range_table = NULL;
362 	s->range_table_list = NULL;
363 	if (kind == 1 || kind == 2) {
364 		s->range_table = &range_digital;
365 	} else if (range) {
366 		range_table_list = kmalloc_array(s->n_chan, sizeof(*range),
367 						 GFP_KERNEL);
368 		if (!range_table_list)
369 			return -ENOMEM;
370 		s->range_table_list = range_table_list;
371 	}
372 	for (chan = 0, j = 0; j < 32; j++) {
373 		if (cfg[j].kind == kind) {
374 			if (mapping)
375 				mapping[chan] = j;
376 			if (range) {
377 				range[j].length = 1;
378 				range[j].range.min = cfg[j].min;
379 				range[j].range.max = cfg[j].max;
380 				range_table_list[chan] =
381 				    (const struct comedi_lrange *)&range[j];
382 			}
383 			maxdata_list[chan] = ((long long)1 << cfg[j].bits) - 1;
384 			chan++;
385 		}
386 	}
387 	return 0;
388 }
389 
serial2002_setup_subdevs(struct comedi_device * dev)390 static int serial2002_setup_subdevs(struct comedi_device *dev)
391 {
392 	struct serial2002_private *devpriv = dev->private;
393 	struct config_t *di_cfg;
394 	struct config_t *do_cfg;
395 	struct config_t *ai_cfg;
396 	struct config_t *ao_cfg;
397 	struct config_t *cfg;
398 	struct comedi_subdevice *s;
399 	int result = 0;
400 	int i;
401 
402 	/* Allocate the temporary structs to hold the configuration data */
403 	di_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL);
404 	do_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL);
405 	ai_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL);
406 	ao_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL);
407 	if (!di_cfg || !do_cfg || !ai_cfg || !ao_cfg) {
408 		result = -ENOMEM;
409 		goto err_alloc_configs;
410 	}
411 
412 	/* Read the configuration from the connected device */
413 	serial2002_tty_setspeed(devpriv->tty, devpriv->speed);
414 	serial2002_poll_channel(devpriv->tty, 31);
415 	while (1) {
416 		struct serial_data data = serial2002_read(devpriv->tty, 1000);
417 		int kind = S2002_CFG_KIND(data.value);
418 		int channel = S2002_CFG_CHAN(data.value);
419 		int range = S2002_CFG_BASE(data.value);
420 		int cmd = S2002_CFG_CMD(data.value);
421 
422 		if (data.kind != is_channel || data.index != 31 ||
423 		    kind == S2002_CFG_KIND_INVALID)
424 			break;
425 
426 		switch (kind) {
427 		case S2002_CFG_KIND_DIGITAL_IN:
428 			cfg = di_cfg;
429 			break;
430 		case S2002_CFG_KIND_DIGITAL_OUT:
431 			cfg = do_cfg;
432 			break;
433 		case S2002_CFG_KIND_ANALOG_IN:
434 			cfg = ai_cfg;
435 			break;
436 		case S2002_CFG_KIND_ANALOG_OUT:
437 			cfg = ao_cfg;
438 			break;
439 		case S2002_CFG_KIND_ENCODER_IN:
440 			cfg = ai_cfg;
441 			break;
442 		default:
443 			cfg = NULL;
444 			break;
445 		}
446 		if (!cfg)
447 			continue;	/* unknown kind, skip it */
448 
449 		cfg[channel].kind = kind;
450 
451 		switch (cmd) {
452 		case S2002_CFG_CMD_BITS:
453 			cfg[channel].bits = S2002_CFG_BITS(data.value);
454 			break;
455 		case S2002_CFG_CMD_MIN:
456 		case S2002_CFG_CMD_MAX:
457 			switch (S2002_CFG_UNITS(data.value)) {
458 			case 0:
459 				range *= 1000000;
460 				break;
461 			case 1:
462 				range *= 1000;
463 				break;
464 			case 2:
465 				range *= 1;
466 				break;
467 			}
468 			if (S2002_CFG_SIGN(data.value))
469 				range = -range;
470 			if (cmd == S2002_CFG_CMD_MIN)
471 				cfg[channel].min = range;
472 			else
473 				cfg[channel].max = range;
474 			break;
475 		}
476 	}
477 
478 	/* Fill in subdevice data */
479 	for (i = 0; i <= 4; i++) {
480 		unsigned char *mapping = NULL;
481 		struct serial2002_range_table_t *range = NULL;
482 		int kind = 0;
483 
484 		s = &dev->subdevices[i];
485 
486 		switch (i) {
487 		case 0:
488 			cfg = di_cfg;
489 			mapping = devpriv->digital_in_mapping;
490 			kind = S2002_CFG_KIND_DIGITAL_IN;
491 			break;
492 		case 1:
493 			cfg = do_cfg;
494 			mapping = devpriv->digital_out_mapping;
495 			kind = S2002_CFG_KIND_DIGITAL_OUT;
496 			break;
497 		case 2:
498 			cfg = ai_cfg;
499 			mapping = devpriv->analog_in_mapping;
500 			range = devpriv->in_range;
501 			kind = S2002_CFG_KIND_ANALOG_IN;
502 			break;
503 		case 3:
504 			cfg = ao_cfg;
505 			mapping = devpriv->analog_out_mapping;
506 			range = devpriv->out_range;
507 			kind = S2002_CFG_KIND_ANALOG_OUT;
508 			break;
509 		case 4:
510 			cfg = ai_cfg;
511 			mapping = devpriv->encoder_in_mapping;
512 			range = devpriv->in_range;
513 			kind = S2002_CFG_KIND_ENCODER_IN;
514 			break;
515 		}
516 
517 		if (serial2002_setup_subdevice(s, cfg, range, mapping, kind))
518 			break;	/* err handled below */
519 	}
520 	if (i <= 4) {
521 		/*
522 		 * Failed to allocate maxdata_list or range_table_list
523 		 * for a subdevice that needed it.
524 		 */
525 		result = -ENOMEM;
526 		for (i = 0; i <= 4; i++) {
527 			s = &dev->subdevices[i];
528 			kfree(s->maxdata_list);
529 			s->maxdata_list = NULL;
530 			kfree(s->range_table_list);
531 			s->range_table_list = NULL;
532 		}
533 	}
534 
535 err_alloc_configs:
536 	kfree(di_cfg);
537 	kfree(do_cfg);
538 	kfree(ai_cfg);
539 	kfree(ao_cfg);
540 
541 	if (result) {
542 		if (devpriv->tty) {
543 			filp_close(devpriv->tty, NULL);
544 			devpriv->tty = NULL;
545 		}
546 	}
547 
548 	return result;
549 }
550 
serial2002_open(struct comedi_device * dev)551 static int serial2002_open(struct comedi_device *dev)
552 {
553 	struct serial2002_private *devpriv = dev->private;
554 	int result;
555 	char port[20];
556 
557 	sprintf(port, "/dev/ttyS%d", devpriv->port);
558 	devpriv->tty = filp_open(port, O_RDWR, 0);
559 	if (IS_ERR(devpriv->tty)) {
560 		result = (int)PTR_ERR(devpriv->tty);
561 		dev_err(dev->class_dev, "file open error = %d\n", result);
562 	} else {
563 		result = serial2002_setup_subdevs(dev);
564 	}
565 	return result;
566 }
567 
serial2002_close(struct comedi_device * dev)568 static void serial2002_close(struct comedi_device *dev)
569 {
570 	struct serial2002_private *devpriv = dev->private;
571 
572 	if (!IS_ERR(devpriv->tty) && devpriv->tty)
573 		filp_close(devpriv->tty, NULL);
574 }
575 
serial2002_di_insn_read(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)576 static int serial2002_di_insn_read(struct comedi_device *dev,
577 				   struct comedi_subdevice *s,
578 				   struct comedi_insn *insn,
579 				   unsigned int *data)
580 {
581 	struct serial2002_private *devpriv = dev->private;
582 	int n;
583 	int chan;
584 
585 	chan = devpriv->digital_in_mapping[CR_CHAN(insn->chanspec)];
586 	for (n = 0; n < insn->n; n++) {
587 		struct serial_data read;
588 
589 		serial2002_poll_digital(devpriv->tty, chan);
590 		while (1) {
591 			read = serial2002_read(devpriv->tty, 1000);
592 			if (read.kind != is_digital || read.index == chan)
593 				break;
594 		}
595 		data[n] = read.value;
596 	}
597 	return n;
598 }
599 
serial2002_do_insn_write(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)600 static int serial2002_do_insn_write(struct comedi_device *dev,
601 				    struct comedi_subdevice *s,
602 				    struct comedi_insn *insn,
603 				    unsigned int *data)
604 {
605 	struct serial2002_private *devpriv = dev->private;
606 	int n;
607 	int chan;
608 
609 	chan = devpriv->digital_out_mapping[CR_CHAN(insn->chanspec)];
610 	for (n = 0; n < insn->n; n++) {
611 		struct serial_data write;
612 
613 		write.kind = is_digital;
614 		write.index = chan;
615 		write.value = data[n];
616 		serial2002_write(devpriv->tty, write);
617 	}
618 	return n;
619 }
620 
serial2002_ai_insn_read(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)621 static int serial2002_ai_insn_read(struct comedi_device *dev,
622 				   struct comedi_subdevice *s,
623 				   struct comedi_insn *insn,
624 				   unsigned int *data)
625 {
626 	struct serial2002_private *devpriv = dev->private;
627 	int n;
628 	int chan;
629 
630 	chan = devpriv->analog_in_mapping[CR_CHAN(insn->chanspec)];
631 	for (n = 0; n < insn->n; n++) {
632 		struct serial_data read;
633 
634 		serial2002_poll_channel(devpriv->tty, chan);
635 		while (1) {
636 			read = serial2002_read(devpriv->tty, 1000);
637 			if (read.kind != is_channel || read.index == chan)
638 				break;
639 		}
640 		data[n] = read.value;
641 	}
642 	return n;
643 }
644 
serial2002_ao_insn_write(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)645 static int serial2002_ao_insn_write(struct comedi_device *dev,
646 				    struct comedi_subdevice *s,
647 				    struct comedi_insn *insn,
648 				    unsigned int *data)
649 {
650 	struct serial2002_private *devpriv = dev->private;
651 	int n;
652 	int chan;
653 
654 	chan = devpriv->analog_out_mapping[CR_CHAN(insn->chanspec)];
655 	for (n = 0; n < insn->n; n++) {
656 		struct serial_data write;
657 
658 		write.kind = is_channel;
659 		write.index = chan;
660 		write.value = data[n];
661 		serial2002_write(devpriv->tty, write);
662 		devpriv->ao_readback[chan] = data[n];
663 	}
664 	return n;
665 }
666 
serial2002_ao_insn_read(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)667 static int serial2002_ao_insn_read(struct comedi_device *dev,
668 				   struct comedi_subdevice *s,
669 				   struct comedi_insn *insn,
670 				   unsigned int *data)
671 {
672 	struct serial2002_private *devpriv = dev->private;
673 	int n;
674 	int chan = CR_CHAN(insn->chanspec);
675 
676 	for (n = 0; n < insn->n; n++)
677 		data[n] = devpriv->ao_readback[chan];
678 
679 	return n;
680 }
681 
serial2002_encoder_insn_read(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)682 static int serial2002_encoder_insn_read(struct comedi_device *dev,
683 					struct comedi_subdevice *s,
684 					struct comedi_insn *insn,
685 					unsigned int *data)
686 {
687 	struct serial2002_private *devpriv = dev->private;
688 	int n;
689 	int chan;
690 
691 	chan = devpriv->encoder_in_mapping[CR_CHAN(insn->chanspec)];
692 	for (n = 0; n < insn->n; n++) {
693 		struct serial_data read;
694 
695 		serial2002_poll_channel(devpriv->tty, chan);
696 		while (1) {
697 			read = serial2002_read(devpriv->tty, 1000);
698 			if (read.kind != is_channel || read.index == chan)
699 				break;
700 		}
701 		data[n] = read.value;
702 	}
703 	return n;
704 }
705 
serial2002_attach(struct comedi_device * dev,struct comedi_devconfig * it)706 static int serial2002_attach(struct comedi_device *dev,
707 			     struct comedi_devconfig *it)
708 {
709 	struct serial2002_private *devpriv;
710 	struct comedi_subdevice *s;
711 	int ret;
712 
713 	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
714 	if (!devpriv)
715 		return -ENOMEM;
716 
717 	devpriv->port = it->options[0];
718 	devpriv->speed = it->options[1];
719 
720 	ret = comedi_alloc_subdevices(dev, 5);
721 	if (ret)
722 		return ret;
723 
724 	/* digital input subdevice */
725 	s = &dev->subdevices[0];
726 	s->type		= COMEDI_SUBD_DI;
727 	s->subdev_flags	= SDF_READABLE;
728 	s->n_chan	= 0;
729 	s->maxdata	= 1;
730 	s->range_table	= &range_digital;
731 	s->insn_read	= serial2002_di_insn_read;
732 
733 	/* digital output subdevice */
734 	s = &dev->subdevices[1];
735 	s->type		= COMEDI_SUBD_DO;
736 	s->subdev_flags	= SDF_WRITABLE;
737 	s->n_chan	= 0;
738 	s->maxdata	= 1;
739 	s->range_table	= &range_digital;
740 	s->insn_write	= serial2002_do_insn_write;
741 
742 	/* analog input subdevice */
743 	s = &dev->subdevices[2];
744 	s->type		= COMEDI_SUBD_AI;
745 	s->subdev_flags	= SDF_READABLE | SDF_GROUND;
746 	s->n_chan	= 0;
747 	s->maxdata	= 1;
748 	s->range_table	= NULL;
749 	s->insn_read	= serial2002_ai_insn_read;
750 
751 	/* analog output subdevice */
752 	s = &dev->subdevices[3];
753 	s->type		= COMEDI_SUBD_AO;
754 	s->subdev_flags	= SDF_WRITABLE;
755 	s->n_chan	= 0;
756 	s->maxdata	= 1;
757 	s->range_table	= NULL;
758 	s->insn_write	= serial2002_ao_insn_write;
759 	s->insn_read	= serial2002_ao_insn_read;
760 
761 	/* encoder input subdevice */
762 	s = &dev->subdevices[4];
763 	s->type		= COMEDI_SUBD_COUNTER;
764 	s->subdev_flags	= SDF_READABLE | SDF_LSAMPL;
765 	s->n_chan	= 0;
766 	s->maxdata	= 1;
767 	s->range_table	= NULL;
768 	s->insn_read	= serial2002_encoder_insn_read;
769 
770 	dev->open	= serial2002_open;
771 	dev->close	= serial2002_close;
772 
773 	return 0;
774 }
775 
serial2002_detach(struct comedi_device * dev)776 static void serial2002_detach(struct comedi_device *dev)
777 {
778 	struct comedi_subdevice *s;
779 	int i;
780 
781 	for (i = 0; i < dev->n_subdevices; i++) {
782 		s = &dev->subdevices[i];
783 		kfree(s->maxdata_list);
784 		kfree(s->range_table_list);
785 	}
786 }
787 
788 static struct comedi_driver serial2002_driver = {
789 	.driver_name	= "serial2002",
790 	.module		= THIS_MODULE,
791 	.attach		= serial2002_attach,
792 	.detach		= serial2002_detach,
793 };
794 module_comedi_driver(serial2002_driver);
795 
796 MODULE_AUTHOR("Comedi http://www.comedi.org");
797 MODULE_DESCRIPTION("Comedi low-level driver");
798 MODULE_LICENSE("GPL");
799