These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / staging / comedi / drivers / serial2002.c
1 /*
2  * serial2002.c
3  * Comedi driver for serial connected hardware
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 #include <linux/module.h>
29 #include "../comedidev.h"
30
31 #include <linux/delay.h>
32 #include <linux/sched.h>
33 #include <linux/slab.h>
34 #include <linux/ktime.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
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 -ENOTTY;
105 }
106
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
121 static void serial2002_tty_read_poll_wait(struct file *f, int timeout)
122 {
123         struct poll_wqueues table;
124         ktime_t start, now;
125
126         start = ktime_get();
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                 now = ktime_get();
138                 elapsed = ktime_us_delta(now, start);
139                 if (elapsed > timeout)
140                         break;
141                 set_current_state(TASK_INTERRUPTIBLE);
142                 schedule_timeout(((timeout - elapsed) * HZ) / 10000);
143         }
144         poll_freewait(&table);
145 }
146
147 static int serial2002_tty_read(struct file *f, int timeout)
148 {
149         unsigned char ch;
150         int result;
151
152         result = -1;
153         if (!IS_ERR(f)) {
154                 mm_segment_t oldfs;
155                 char __user *p = (__force char __user *)&ch;
156                 loff_t offset = 0;
157
158                 oldfs = get_fs();
159                 set_fs(KERNEL_DS);
160                 if (f->f_op->poll) {
161                         serial2002_tty_read_poll_wait(f, timeout);
162
163                         if (__vfs_read(f, p, 1, &offset) == 1)
164                                 result = ch;
165                 } else {
166                         /* Device does not support poll, busy wait */
167                         int retries = 0;
168
169                         while (1) {
170                                 retries++;
171                                 if (retries >= timeout)
172                                         break;
173
174                                 if (__vfs_read(f, p, 1, &offset) == 1) {
175                                         result = ch;
176                                         break;
177                                 }
178                                 usleep_range(100, 1000);
179                         }
180                 }
181                 set_fs(oldfs);
182         }
183         return result;
184 }
185
186 static void serial2002_tty_setspeed(struct file *f, int speed)
187 {
188         struct termios termios;
189         struct serial_struct serial;
190         mm_segment_t oldfs;
191
192         oldfs = get_fs();
193         set_fs(KERNEL_DS);
194
195         /* Set speed */
196         serial2002_tty_ioctl(f, TCGETS, (unsigned long)&termios);
197         termios.c_iflag = 0;
198         termios.c_oflag = 0;
199         termios.c_lflag = 0;
200         termios.c_cflag = CLOCAL | CS8 | CREAD;
201         termios.c_cc[VMIN] = 0;
202         termios.c_cc[VTIME] = 0;
203         switch (speed) {
204         case 2400:
205                 termios.c_cflag |= B2400;
206                 break;
207         case 4800:
208                 termios.c_cflag |= B4800;
209                 break;
210         case 9600:
211                 termios.c_cflag |= B9600;
212                 break;
213         case 19200:
214                 termios.c_cflag |= B19200;
215                 break;
216         case 38400:
217                 termios.c_cflag |= B38400;
218                 break;
219         case 57600:
220                 termios.c_cflag |= B57600;
221                 break;
222         case 115200:
223                 termios.c_cflag |= B115200;
224                 break;
225         default:
226                 termios.c_cflag |= B9600;
227                 break;
228         }
229         serial2002_tty_ioctl(f, TCSETS, (unsigned long)&termios);
230
231         /* Set low latency */
232         serial2002_tty_ioctl(f, TIOCGSERIAL, (unsigned long)&serial);
233         serial.flags |= ASYNC_LOW_LATENCY;
234         serial2002_tty_ioctl(f, TIOCSSERIAL, (unsigned long)&serial);
235
236         set_fs(oldfs);
237 }
238
239 static void serial2002_poll_digital(struct file *f, int channel)
240 {
241         char cmd;
242
243         cmd = 0x40 | (channel & 0x1f);
244         serial2002_tty_write(f, &cmd, 1);
245 }
246
247 static void serial2002_poll_channel(struct file *f, int channel)
248 {
249         char cmd;
250
251         cmd = 0x60 | (channel & 0x1f);
252         serial2002_tty_write(f, &cmd, 1);
253 }
254
255 static struct serial_data serial2002_read(struct file *f, int timeout)
256 {
257         struct serial_data result;
258         int length;
259
260         result.kind = is_invalid;
261         result.index = 0;
262         result.value = 0;
263         length = 0;
264         while (1) {
265                 int data = serial2002_tty_read(f, timeout);
266
267                 length++;
268                 if (data < 0) {
269                         break;
270                 } else if (data & 0x80) {
271                         result.value = (result.value << 7) | (data & 0x7f);
272                 } else {
273                         if (length == 1) {
274                                 switch ((data >> 5) & 0x03) {
275                                 case 0:
276                                         result.value = 0;
277                                         result.kind = is_digital;
278                                         break;
279                                 case 1:
280                                         result.value = 1;
281                                         result.kind = is_digital;
282                                         break;
283                                 }
284                         } else {
285                                 result.value =
286                                     (result.value << 2) | ((data & 0x60) >> 5);
287                                 result.kind = is_channel;
288                         }
289                         result.index = data & 0x1f;
290                         break;
291                 }
292         }
293         return result;
294 }
295
296 static void serial2002_write(struct file *f, struct serial_data data)
297 {
298         if (data.kind == is_digital) {
299                 unsigned char ch =
300                     ((data.value << 5) & 0x20) | (data.index & 0x1f);
301                 serial2002_tty_write(f, &ch, 1);
302         } else {
303                 unsigned char ch[6];
304                 int i = 0;
305
306                 if (data.value >= (1L << 30)) {
307                         ch[i] = 0x80 | ((data.value >> 30) & 0x03);
308                         i++;
309                 }
310                 if (data.value >= (1L << 23)) {
311                         ch[i] = 0x80 | ((data.value >> 23) & 0x7f);
312                         i++;
313                 }
314                 if (data.value >= (1L << 16)) {
315                         ch[i] = 0x80 | ((data.value >> 16) & 0x7f);
316                         i++;
317                 }
318                 if (data.value >= (1L << 9)) {
319                         ch[i] = 0x80 | ((data.value >> 9) & 0x7f);
320                         i++;
321                 }
322                 ch[i] = 0x80 | ((data.value >> 2) & 0x7f);
323                 i++;
324                 ch[i] = ((data.value << 5) & 0x60) | (data.index & 0x1f);
325                 i++;
326                 serial2002_tty_write(f, ch, i);
327         }
328 }
329
330 struct config_t {
331         short int kind;
332         short int bits;
333         int min;
334         int max;
335 };
336
337 static int serial2002_setup_subdevice(struct comedi_subdevice *s,
338                                       struct config_t *cfg,
339                                       struct serial2002_range_table_t *range,
340                                       unsigned char *mapping,
341                                       int kind)
342 {
343         const struct comedi_lrange **range_table_list = NULL;
344         unsigned int *maxdata_list;
345         int j, chan;
346
347         for (chan = 0, j = 0; j < 32; j++) {
348                 if (cfg[j].kind == kind)
349                         chan++;
350         }
351         s->n_chan = chan;
352         s->maxdata = 0;
353         kfree(s->maxdata_list);
354         maxdata_list = kmalloc_array(s->n_chan, sizeof(unsigned int),
355                                      GFP_KERNEL);
356         if (!maxdata_list)
357                 return -ENOMEM;
358         s->maxdata_list = maxdata_list;
359         kfree(s->range_table_list);
360         s->range_table = NULL;
361         s->range_table_list = NULL;
362         if (kind == 1 || kind == 2) {
363                 s->range_table = &range_digital;
364         } else if (range) {
365                 range_table_list = kmalloc_array(s->n_chan, sizeof(*range),
366                                                  GFP_KERNEL);
367                 if (!range_table_list)
368                         return -ENOMEM;
369                 s->range_table_list = range_table_list;
370         }
371         for (chan = 0, j = 0; j < 32; j++) {
372                 if (cfg[j].kind == kind) {
373                         if (mapping)
374                                 mapping[chan] = j;
375                         if (range && range_table_list) {
376                                 range[j].length = 1;
377                                 range[j].range.min = cfg[j].min;
378                                 range[j].range.max = cfg[j].max;
379                                 range_table_list[chan] =
380                                     (const struct comedi_lrange *)&range[j];
381                         }
382                         maxdata_list[chan] = ((long long)1 << cfg[j].bits) - 1;
383                         chan++;
384                 }
385         }
386         return 0;
387 }
388
389 static int serial2002_setup_subdevs(struct comedi_device *dev)
390 {
391         struct serial2002_private *devpriv = dev->private;
392         struct config_t *di_cfg;
393         struct config_t *do_cfg;
394         struct config_t *ai_cfg;
395         struct config_t *ao_cfg;
396         struct config_t *cfg;
397         struct comedi_subdevice *s;
398         int result = 0;
399         int i;
400
401         /* Allocate the temporary structs to hold the configuration data */
402         di_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL);
403         do_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL);
404         ai_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL);
405         ao_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL);
406         if (!di_cfg || !do_cfg || !ai_cfg || !ao_cfg) {
407                 result = -ENOMEM;
408                 goto err_alloc_configs;
409         }
410
411         /* Read the configuration from the connected device */
412         serial2002_tty_setspeed(devpriv->tty, devpriv->speed);
413         serial2002_poll_channel(devpriv->tty, 31);
414         while (1) {
415                 struct serial_data data = serial2002_read(devpriv->tty, 1000);
416                 int kind = S2002_CFG_KIND(data.value);
417                 int channel = S2002_CFG_CHAN(data.value);
418                 int range = S2002_CFG_BASE(data.value);
419                 int cmd = S2002_CFG_CMD(data.value);
420
421                 if (data.kind != is_channel || data.index != 31 ||
422                     kind == S2002_CFG_KIND_INVALID)
423                         break;
424
425                 switch (kind) {
426                 case S2002_CFG_KIND_DIGITAL_IN:
427                         cfg = di_cfg;
428                         break;
429                 case S2002_CFG_KIND_DIGITAL_OUT:
430                         cfg = do_cfg;
431                         break;
432                 case S2002_CFG_KIND_ANALOG_IN:
433                         cfg = ai_cfg;
434                         break;
435                 case S2002_CFG_KIND_ANALOG_OUT:
436                         cfg = ao_cfg;
437                         break;
438                 case S2002_CFG_KIND_ENCODER_IN:
439                         cfg = ai_cfg;
440                         break;
441                 default:
442                         cfg = NULL;
443                         break;
444                 }
445                 if (!cfg)
446                         continue;       /* unknown kind, skip it */
447
448                 cfg[channel].kind = kind;
449
450                 switch (cmd) {
451                 case S2002_CFG_CMD_BITS:
452                         cfg[channel].bits = S2002_CFG_BITS(data.value);
453                         break;
454                 case S2002_CFG_CMD_MIN:
455                 case S2002_CFG_CMD_MAX:
456                         switch (S2002_CFG_UNITS(data.value)) {
457                         case 0:
458                                 range *= 1000000;
459                                 break;
460                         case 1:
461                                 range *= 1000;
462                                 break;
463                         case 2:
464                                 range *= 1;
465                                 break;
466                         }
467                         if (S2002_CFG_SIGN(data.value))
468                                 range = -range;
469                         if (cmd == S2002_CFG_CMD_MIN)
470                                 cfg[channel].min = range;
471                         else
472                                 cfg[channel].max = range;
473                         break;
474                 }
475         }
476
477         /* Fill in subdevice data */
478         for (i = 0; i <= 4; i++) {
479                 unsigned char *mapping = NULL;
480                 struct serial2002_range_table_t *range = NULL;
481                 int kind = 0;
482
483                 s = &dev->subdevices[i];
484
485                 switch (i) {
486                 case 0:
487                         cfg = di_cfg;
488                         mapping = devpriv->digital_in_mapping;
489                         kind = S2002_CFG_KIND_DIGITAL_IN;
490                         break;
491                 case 1:
492                         cfg = do_cfg;
493                         mapping = devpriv->digital_out_mapping;
494                         kind = S2002_CFG_KIND_DIGITAL_OUT;
495                         break;
496                 case 2:
497                         cfg = ai_cfg;
498                         mapping = devpriv->analog_in_mapping;
499                         range = devpriv->in_range;
500                         kind = S2002_CFG_KIND_ANALOG_IN;
501                         break;
502                 case 3:
503                         cfg = ao_cfg;
504                         mapping = devpriv->analog_out_mapping;
505                         range = devpriv->out_range;
506                         kind = S2002_CFG_KIND_ANALOG_OUT;
507                         break;
508                 case 4:
509                         cfg = ai_cfg;
510                         mapping = devpriv->encoder_in_mapping;
511                         range = devpriv->in_range;
512                         kind = S2002_CFG_KIND_ENCODER_IN;
513                         break;
514                 }
515
516                 if (serial2002_setup_subdevice(s, cfg, range, mapping, kind))
517                         break;  /* err handled below */
518         }
519         if (i <= 4) {
520                 /*
521                  * Failed to allocate maxdata_list or range_table_list
522                  * for a subdevice that needed it.
523                  */
524                 result = -ENOMEM;
525                 for (i = 0; i <= 4; i++) {
526                         s = &dev->subdevices[i];
527                         kfree(s->maxdata_list);
528                         s->maxdata_list = NULL;
529                         kfree(s->range_table_list);
530                         s->range_table_list = NULL;
531                 }
532         }
533
534 err_alloc_configs:
535         kfree(di_cfg);
536         kfree(do_cfg);
537         kfree(ai_cfg);
538         kfree(ao_cfg);
539
540         if (result) {
541                 if (devpriv->tty) {
542                         filp_close(devpriv->tty, NULL);
543                         devpriv->tty = NULL;
544                 }
545         }
546
547         return result;
548 }
549
550 static int serial2002_open(struct comedi_device *dev)
551 {
552         struct serial2002_private *devpriv = dev->private;
553         int result;
554         char port[20];
555
556         sprintf(port, "/dev/ttyS%d", devpriv->port);
557         devpriv->tty = filp_open(port, O_RDWR, 0);
558         if (IS_ERR(devpriv->tty)) {
559                 result = (int)PTR_ERR(devpriv->tty);
560                 dev_err(dev->class_dev, "file open error = %d\n", result);
561         } else {
562                 result = serial2002_setup_subdevs(dev);
563         }
564         return result;
565 }
566
567 static void serial2002_close(struct comedi_device *dev)
568 {
569         struct serial2002_private *devpriv = dev->private;
570
571         if (!IS_ERR(devpriv->tty) && devpriv->tty)
572                 filp_close(devpriv->tty, NULL);
573 }
574
575 static int serial2002_di_insn_read(struct comedi_device *dev,
576                                    struct comedi_subdevice *s,
577                                    struct comedi_insn *insn,
578                                    unsigned int *data)
579 {
580         struct serial2002_private *devpriv = dev->private;
581         int n;
582         int chan;
583
584         chan = devpriv->digital_in_mapping[CR_CHAN(insn->chanspec)];
585         for (n = 0; n < insn->n; n++) {
586                 struct serial_data read;
587
588                 serial2002_poll_digital(devpriv->tty, chan);
589                 while (1) {
590                         read = serial2002_read(devpriv->tty, 1000);
591                         if (read.kind != is_digital || read.index == chan)
592                                 break;
593                 }
594                 data[n] = read.value;
595         }
596         return n;
597 }
598
599 static int serial2002_do_insn_write(struct comedi_device *dev,
600                                     struct comedi_subdevice *s,
601                                     struct comedi_insn *insn,
602                                     unsigned int *data)
603 {
604         struct serial2002_private *devpriv = dev->private;
605         int n;
606         int chan;
607
608         chan = devpriv->digital_out_mapping[CR_CHAN(insn->chanspec)];
609         for (n = 0; n < insn->n; n++) {
610                 struct serial_data write;
611
612                 write.kind = is_digital;
613                 write.index = chan;
614                 write.value = data[n];
615                 serial2002_write(devpriv->tty, write);
616         }
617         return n;
618 }
619
620 static int serial2002_ai_insn_read(struct comedi_device *dev,
621                                    struct comedi_subdevice *s,
622                                    struct comedi_insn *insn,
623                                    unsigned int *data)
624 {
625         struct serial2002_private *devpriv = dev->private;
626         int n;
627         int chan;
628
629         chan = devpriv->analog_in_mapping[CR_CHAN(insn->chanspec)];
630         for (n = 0; n < insn->n; n++) {
631                 struct serial_data read;
632
633                 serial2002_poll_channel(devpriv->tty, chan);
634                 while (1) {
635                         read = serial2002_read(devpriv->tty, 1000);
636                         if (read.kind != is_channel || read.index == chan)
637                                 break;
638                 }
639                 data[n] = read.value;
640         }
641         return n;
642 }
643
644 static int serial2002_ao_insn_write(struct comedi_device *dev,
645                                     struct comedi_subdevice *s,
646                                     struct comedi_insn *insn,
647                                     unsigned int *data)
648 {
649         struct serial2002_private *devpriv = dev->private;
650         int n;
651         int chan;
652
653         chan = devpriv->analog_out_mapping[CR_CHAN(insn->chanspec)];
654         for (n = 0; n < insn->n; n++) {
655                 struct serial_data write;
656
657                 write.kind = is_channel;
658                 write.index = chan;
659                 write.value = data[n];
660                 serial2002_write(devpriv->tty, write);
661                 devpriv->ao_readback[chan] = data[n];
662         }
663         return n;
664 }
665
666 static int serial2002_ao_insn_read(struct comedi_device *dev,
667                                    struct comedi_subdevice *s,
668                                    struct comedi_insn *insn,
669                                    unsigned int *data)
670 {
671         struct serial2002_private *devpriv = dev->private;
672         int n;
673         int chan = CR_CHAN(insn->chanspec);
674
675         for (n = 0; n < insn->n; n++)
676                 data[n] = devpriv->ao_readback[chan];
677
678         return n;
679 }
680
681 static int serial2002_encoder_insn_read(struct comedi_device *dev,
682                                         struct comedi_subdevice *s,
683                                         struct comedi_insn *insn,
684                                         unsigned int *data)
685 {
686         struct serial2002_private *devpriv = dev->private;
687         int n;
688         int chan;
689
690         chan = devpriv->encoder_in_mapping[CR_CHAN(insn->chanspec)];
691         for (n = 0; n < insn->n; n++) {
692                 struct serial_data read;
693
694                 serial2002_poll_channel(devpriv->tty, chan);
695                 while (1) {
696                         read = serial2002_read(devpriv->tty, 1000);
697                         if (read.kind != is_channel || read.index == chan)
698                                 break;
699                 }
700                 data[n] = read.value;
701         }
702         return n;
703 }
704
705 static int serial2002_attach(struct comedi_device *dev,
706                              struct comedi_devconfig *it)
707 {
708         struct serial2002_private *devpriv;
709         struct comedi_subdevice *s;
710         int ret;
711
712         devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
713         if (!devpriv)
714                 return -ENOMEM;
715
716         devpriv->port = it->options[0];
717         devpriv->speed = it->options[1];
718
719         ret = comedi_alloc_subdevices(dev, 5);
720         if (ret)
721                 return ret;
722
723         /* digital input subdevice */
724         s = &dev->subdevices[0];
725         s->type         = COMEDI_SUBD_DI;
726         s->subdev_flags = SDF_READABLE;
727         s->n_chan       = 0;
728         s->maxdata      = 1;
729         s->range_table  = &range_digital;
730         s->insn_read    = serial2002_di_insn_read;
731
732         /* digital output subdevice */
733         s = &dev->subdevices[1];
734         s->type         = COMEDI_SUBD_DO;
735         s->subdev_flags = SDF_WRITABLE;
736         s->n_chan       = 0;
737         s->maxdata      = 1;
738         s->range_table  = &range_digital;
739         s->insn_write   = serial2002_do_insn_write;
740
741         /* analog input subdevice */
742         s = &dev->subdevices[2];
743         s->type         = COMEDI_SUBD_AI;
744         s->subdev_flags = SDF_READABLE | SDF_GROUND;
745         s->n_chan       = 0;
746         s->maxdata      = 1;
747         s->range_table  = NULL;
748         s->insn_read    = serial2002_ai_insn_read;
749
750         /* analog output subdevice */
751         s = &dev->subdevices[3];
752         s->type         = COMEDI_SUBD_AO;
753         s->subdev_flags = SDF_WRITABLE;
754         s->n_chan       = 0;
755         s->maxdata      = 1;
756         s->range_table  = NULL;
757         s->insn_write   = serial2002_ao_insn_write;
758         s->insn_read    = serial2002_ao_insn_read;
759
760         /* encoder input subdevice */
761         s = &dev->subdevices[4];
762         s->type         = COMEDI_SUBD_COUNTER;
763         s->subdev_flags = SDF_READABLE | SDF_LSAMPL;
764         s->n_chan       = 0;
765         s->maxdata      = 1;
766         s->range_table  = NULL;
767         s->insn_read    = serial2002_encoder_insn_read;
768
769         dev->open       = serial2002_open;
770         dev->close      = serial2002_close;
771
772         return 0;
773 }
774
775 static void serial2002_detach(struct comedi_device *dev)
776 {
777         struct comedi_subdevice *s;
778         int i;
779
780         for (i = 0; i < dev->n_subdevices; i++) {
781                 s = &dev->subdevices[i];
782                 kfree(s->maxdata_list);
783                 kfree(s->range_table_list);
784         }
785 }
786
787 static struct comedi_driver serial2002_driver = {
788         .driver_name    = "serial2002",
789         .module         = THIS_MODULE,
790         .attach         = serial2002_attach,
791         .detach         = serial2002_detach,
792 };
793 module_comedi_driver(serial2002_driver);
794
795 MODULE_AUTHOR("Comedi http://www.comedi.org");
796 MODULE_DESCRIPTION("Comedi low-level driver");
797 MODULE_LICENSE("GPL");