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