Merge branch 'bugzilla-15749' into release
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / comedi / drivers / comedi_bond.c
1 /*
2 comedi/drivers/comedi_bond.c
3 A Comedi driver to 'bond' or merge multiple drivers and devices as one.
4
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
7 Copyright (C) 2005 Calin A. Culianu <calin@ajvar.org>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
23 */
24 /*
25 Driver: comedi_bond
26 Description: A driver to 'bond' (merge) multiple subdevices from multiple
27 devices together as one.
28 Devices:
29 Author: ds
30 Updated: Mon, 10 Oct 00:18:25 -0500
31 Status: works
32
33 This driver allows you to 'bond' (merge) multiple comedi subdevices
34 (coming from possibly difference boards and/or drivers) together. For
35 example, if you had a board with 2 different DIO subdevices, and
36 another with 1 DIO subdevice, you could 'bond' them with this driver
37 so that they look like one big fat DIO subdevice. This makes writing
38 applications slightly easier as you don't have to worry about managing
39 different subdevices in the application -- you just worry about
40 indexing one linear array of channel id's.
41
42 Right now only DIO subdevices are supported as that's the personal itch
43 I am scratching with this driver. If you want to add support for AI and AO
44 subdevs, go right on ahead and do so!
45
46 Commands aren't supported -- although it would be cool if they were.
47
48 Configuration Options:
49 List of comedi-minors to bond. All subdevices of the same type
50 within each minor will be concatenated together in the order given here.
51 */
52
53 /*
54 * The previous block comment is used to automatically generate
55 * documentation in Comedi and Comedilib. The fields:
56 *
57 * Driver: the name of the driver
58 * Description: a short phrase describing the driver. Don't list boards.
59 * Devices: a full list of the boards that attempt to be supported by
60 * the driver. Format is "(manufacturer) board name [comedi name]",
61 * where comedi_name is the name that is used to configure the board.
62 * See the comment near board_name: in the struct comedi_driver structure
63 * below. If (manufacturer) or [comedi name] is missing, the previous
64 * value is used.
65 * Author: you
66 * Updated: date when the _documentation_ was last updated. Use 'date -R'
67 * to get a value for this.
68 * Status: a one-word description of the status. Valid values are:
69 * works - driver works correctly on most boards supported, and
70 * passes comedi_test.
71 * unknown - unknown. Usually put there by ds.
72 * experimental - may not work in any particular release. Author
73 * probably wants assistance testing it.
74 * bitrotten - driver has not been update in a long time, probably
75 * doesn't work, and probably is missing support for significant
76 * Comedi interface features.
77 * untested - author probably wrote it "blind", and is believed to
78 * work, but no confirmation.
79 *
80 * These headers should be followed by a blank line, and any comments
81 * you wish to say about the driver. The comment area is the place
82 * to put any known bugs, limitations, unsupported features, supported
83 * command triggers, whether or not commands are supported on particular
84 * subdevices, etc.
85 *
86 * Somewhere in the comment should be information about configuration
87 * options that are used with comedi_config.
88 */
89
90 #include "../comedilib.h"
91 #include "../comedidev.h"
92 #include <linux/string.h>
93 #include <linux/slab.h>
94
95 /* The maxiumum number of channels per subdevice. */
96 #define MAX_CHANS 256
97
98 #define MODULE_NAME "comedi_bond"
99 #ifdef MODULE_LICENSE
100 MODULE_LICENSE("GPL");
101 #endif
102 #ifndef STR
103 # define STR1(x) #x
104 # define STR(x) STR1(x)
105 #endif
106
107 static int debug;
108 module_param(debug, int, 0644);
109 MODULE_PARM_DESC(debug, "If true, print extra cryptic debugging output useful"
110 "only to developers.");
111
112 #define LOG_MSG(x...) printk(KERN_INFO MODULE_NAME": "x)
113 #define DEBUG(x...) \
114 do { \
115 if (debug) \
116 printk(KERN_DEBUG MODULE_NAME": DEBUG: "x); \
117 } while (0)
118 #define WARNING(x...) printk(KERN_WARNING MODULE_NAME ": WARNING: "x)
119 #define ERROR(x...) printk(KERN_ERR MODULE_NAME ": INTERNAL ERROR: "x)
120 MODULE_AUTHOR("Calin A. Culianu");
121 MODULE_DESCRIPTION(MODULE_NAME "A driver for COMEDI to bond multiple COMEDI "
122 "devices together as one. In the words of John Lennon: "
123 "'And the world will live as one...'");
124
125 /*
126 * Board descriptions for two imaginary boards. Describing the
127 * boards in this way is optional, and completely driver-dependent.
128 * Some drivers use arrays such as this, other do not.
129 */
130 struct BondingBoard {
131 const char *name;
132 };
133
134 static const struct BondingBoard bondingBoards[] = {
135 {
136 .name = MODULE_NAME,
137 },
138 };
139
140 /*
141 * Useful for shorthand access to the particular board structure
142 */
143 #define thisboard ((const struct BondingBoard *)dev->board_ptr)
144
145 struct BondedDevice {
146 void *dev;
147 unsigned minor;
148 unsigned subdev;
149 unsigned subdev_type;
150 unsigned nchans;
151 unsigned chanid_offset; /* The offset into our unified linear
152 channel-id's of chanid 0 on this
153 subdevice. */
154 };
155
156 /* this structure is for data unique to this hardware driver. If
157 several hardware drivers keep similar information in this structure,
158 feel free to suggest moving the variable to the struct comedi_device struct. */
159 struct Private {
160 # define MAX_BOARD_NAME 256
161 char name[MAX_BOARD_NAME];
162 struct BondedDevice **devs;
163 unsigned ndevs;
164 struct BondedDevice *chanIdDevMap[MAX_CHANS];
165 unsigned nchans;
166 };
167
168 /*
169 * most drivers define the following macro to make it easy to
170 * access the private structure.
171 */
172 #define devpriv ((struct Private *)dev->private)
173
174 /*
175 * The struct comedi_driver structure tells the Comedi core module
176 * which functions to call to configure/deconfigure (attach/detach)
177 * the board, and also about the kernel module that contains
178 * the device code.
179 */
180 static int bonding_attach(struct comedi_device *dev,
181 struct comedi_devconfig *it);
182 static int bonding_detach(struct comedi_device *dev);
183 /** Build Private array of all devices.. */
184 static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it);
185 static void doDevUnconfig(struct comedi_device *dev);
186 /* Ugly implementation of realloc that always copies memory around -- I'm lazy,
187 * what can I say? I like to do wasteful memcopies.. :) */
188 static void *Realloc(const void *ptr, size_t len, size_t old_len);
189
190 static struct comedi_driver driver_bonding = {
191 .driver_name = MODULE_NAME,
192 .module = THIS_MODULE,
193 .attach = bonding_attach,
194 .detach = bonding_detach,
195 /* It is not necessary to implement the following members if you are
196 * writing a driver for a ISA PnP or PCI card */
197 /* Most drivers will support multiple types of boards by
198 * having an array of board structures. These were defined
199 * in skel_boards[] above. Note that the element 'name'
200 * was first in the structure -- Comedi uses this fact to
201 * extract the name of the board without knowing any details
202 * about the structure except for its length.
203 * When a device is attached (by comedi_config), the name
204 * of the device is given to Comedi, and Comedi tries to
205 * match it by going through the list of board names. If
206 * there is a match, the address of the pointer is put
207 * into dev->board_ptr and driver->attach() is called.
208 *
209 * Note that these are not necessary if you can determine
210 * the type of board in software. ISA PnP, PCI, and PCMCIA
211 * devices are such boards.
212 */
213 .board_name = &bondingBoards[0].name,
214 .offset = sizeof(struct BondingBoard),
215 .num_names = ARRAY_SIZE(bondingBoards),
216 };
217
218 static int bonding_dio_insn_bits(struct comedi_device *dev,
219 struct comedi_subdevice *s,
220 struct comedi_insn *insn, unsigned int *data);
221 static int bonding_dio_insn_config(struct comedi_device *dev,
222 struct comedi_subdevice *s,
223 struct comedi_insn *insn,
224 unsigned int *data);
225
226 /*
227 * Attach is called by the Comedi core to configure the driver
228 * for a particular board. If you specified a board_name array
229 * in the driver structure, dev->board_ptr contains that
230 * address.
231 */
232 static int bonding_attach(struct comedi_device *dev,
233 struct comedi_devconfig *it)
234 {
235 struct comedi_subdevice *s;
236
237 LOG_MSG("comedi%d\n", dev->minor);
238
239 /*
240 * Allocate the private structure area. alloc_private() is a
241 * convenient macro defined in comedidev.h.
242 */
243 if (alloc_private(dev, sizeof(struct Private)) < 0)
244 return -ENOMEM;
245
246 /*
247 * Setup our bonding from config params.. sets up our Private struct..
248 */
249 if (!doDevConfig(dev, it))
250 return -EINVAL;
251
252 /*
253 * Initialize dev->board_name. Note that we can use the "thisboard"
254 * macro now, since we just initialized it in the last line.
255 */
256 dev->board_name = devpriv->name;
257
258 /*
259 * Allocate the subdevice structures. alloc_subdevice() is a
260 * convenient macro defined in comedidev.h.
261 */
262 if (alloc_subdevices(dev, 1) < 0)
263 return -ENOMEM;
264
265 s = dev->subdevices + 0;
266 s->type = COMEDI_SUBD_DIO;
267 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
268 s->n_chan = devpriv->nchans;
269 s->maxdata = 1;
270 s->range_table = &range_digital;
271 s->insn_bits = bonding_dio_insn_bits;
272 s->insn_config = bonding_dio_insn_config;
273
274 LOG_MSG("attached with %u DIO channels coming from %u different "
275 "subdevices all bonded together. "
276 "John Lennon would be proud!\n",
277 devpriv->nchans, devpriv->ndevs);
278
279 return 1;
280 }
281
282 /*
283 * _detach is called to deconfigure a device. It should deallocate
284 * resources.
285 * This function is also called when _attach() fails, so it should be
286 * careful not to release resources that were not necessarily
287 * allocated by _attach(). dev->private and dev->subdevices are
288 * deallocated automatically by the core.
289 */
290 static int bonding_detach(struct comedi_device *dev)
291 {
292 LOG_MSG("comedi%d: remove\n", dev->minor);
293 doDevUnconfig(dev);
294 return 0;
295 }
296
297 /* DIO devices are slightly special. Although it is possible to
298 * implement the insn_read/insn_write interface, it is much more
299 * useful to applications if you implement the insn_bits interface.
300 * This allows packed reading/writing of the DIO channels. The
301 * comedi core can convert between insn_bits and insn_read/write */
302 static int bonding_dio_insn_bits(struct comedi_device *dev,
303 struct comedi_subdevice *s,
304 struct comedi_insn *insn, unsigned int *data)
305 {
306 #define LSAMPL_BITS (sizeof(unsigned int)*8)
307 unsigned nchans = LSAMPL_BITS, num_done = 0, i;
308 if (insn->n != 2)
309 return -EINVAL;
310
311 if (devpriv->nchans < nchans)
312 nchans = devpriv->nchans;
313
314 /* The insn data is a mask in data[0] and the new data
315 * in data[1], each channel cooresponding to a bit. */
316 for (i = 0; num_done < nchans && i < devpriv->ndevs; ++i) {
317 struct BondedDevice *bdev = devpriv->devs[i];
318 /* Grab the channel mask and data of only the bits corresponding
319 to this subdevice.. need to shift them to zero position of
320 course. */
321 /* Bits corresponding to this subdev. */
322 unsigned int subdevMask = ((1 << bdev->nchans) - 1);
323 unsigned int writeMask, dataBits;
324
325 /* Argh, we have >= LSAMPL_BITS chans.. take all bits */
326 if (bdev->nchans >= LSAMPL_BITS)
327 subdevMask = (unsigned int)(-1);
328
329 writeMask = (data[0] >> num_done) & subdevMask;
330 dataBits = (data[1] >> num_done) & subdevMask;
331
332 /* Read/Write the new digital lines */
333 if (comedi_dio_bitfield(bdev->dev, bdev->subdev, writeMask,
334 &dataBits) != 2)
335 return -EINVAL;
336
337 /* Make room for the new bits in data[1], the return value */
338 data[1] &= ~(subdevMask << num_done);
339 /* Put the bits in the return value */
340 data[1] |= (dataBits & subdevMask) << num_done;
341 /* Save the new bits to the saved state.. */
342 s->state = data[1];
343
344 num_done += bdev->nchans;
345 }
346
347 return insn->n;
348 }
349
350 static int bonding_dio_insn_config(struct comedi_device *dev,
351 struct comedi_subdevice *s,
352 struct comedi_insn *insn, unsigned int *data)
353 {
354 int chan = CR_CHAN(insn->chanspec), ret, io_bits = s->io_bits;
355 unsigned int io;
356 struct BondedDevice *bdev;
357
358 if (chan < 0 || chan >= devpriv->nchans)
359 return -EINVAL;
360 bdev = devpriv->chanIdDevMap[chan];
361
362 /* The input or output configuration of each digital line is
363 * configured by a special insn_config instruction. chanspec
364 * contains the channel to be changed, and data[0] contains the
365 * value COMEDI_INPUT or COMEDI_OUTPUT. */
366 switch (data[0]) {
367 case INSN_CONFIG_DIO_OUTPUT:
368 io = COMEDI_OUTPUT; /* is this really necessary? */
369 io_bits |= 1 << chan;
370 break;
371 case INSN_CONFIG_DIO_INPUT:
372 io = COMEDI_INPUT; /* is this really necessary? */
373 io_bits &= ~(1 << chan);
374 break;
375 case INSN_CONFIG_DIO_QUERY:
376 data[1] =
377 (io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
378 return insn->n;
379 break;
380 default:
381 return -EINVAL;
382 break;
383 }
384 /* 'real' channel id for this subdev.. */
385 chan -= bdev->chanid_offset;
386 ret = comedi_dio_config(bdev->dev, bdev->subdev, chan, io);
387 if (ret != 1)
388 return -EINVAL;
389 /* Finally, save the new io_bits values since we didn't get
390 an error above. */
391 s->io_bits = io_bits;
392 return insn->n;
393 }
394
395 static void *Realloc(const void *oldmem, size_t newlen, size_t oldlen)
396 {
397 void *newmem = kmalloc(newlen, GFP_KERNEL);
398
399 if (newmem && oldmem)
400 memcpy(newmem, oldmem, min(oldlen, newlen));
401 kfree(oldmem);
402 return newmem;
403 }
404
405 static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it)
406 {
407 int i;
408 void *devs_opened[COMEDI_NUM_BOARD_MINORS];
409
410 memset(devs_opened, 0, sizeof(devs_opened));
411 devpriv->name[0] = 0;;
412 /* Loop through all comedi devices specified on the command-line,
413 building our device list */
414 for (i = 0; i < COMEDI_NDEVCONFOPTS && (!i || it->options[i]); ++i) {
415 char file[] = "/dev/comediXXXXXX";
416 int minor = it->options[i];
417 void *d;
418 int sdev = -1, nchans, tmp;
419 struct BondedDevice *bdev = NULL;
420
421 if (minor < 0 || minor >= COMEDI_NUM_BOARD_MINORS) {
422 ERROR("Minor %d is invalid!\n", minor);
423 return 0;
424 }
425 if (minor == dev->minor) {
426 ERROR("Cannot bond this driver to itself!\n");
427 return 0;
428 }
429 if (devs_opened[minor]) {
430 ERROR("Minor %d specified more than once!\n", minor);
431 return 0;
432 }
433
434 snprintf(file, sizeof(file), "/dev/comedi%u", minor);
435 file[sizeof(file) - 1] = 0;
436
437 d = devs_opened[minor] = comedi_open(file);
438
439 if (!d) {
440 ERROR("Minor %u could not be opened\n", minor);
441 return 0;
442 }
443
444 /* Do DIO, as that's all we support now.. */
445 while ((sdev = comedi_find_subdevice_by_type(d, COMEDI_SUBD_DIO,
446 sdev + 1)) > -1) {
447 nchans = comedi_get_n_channels(d, sdev);
448 if (nchans <= 0) {
449 ERROR("comedi_get_n_channels() returned %d "
450 "on minor %u subdev %d!\n",
451 nchans, minor, sdev);
452 return 0;
453 }
454 bdev = kmalloc(sizeof(*bdev), GFP_KERNEL);
455 if (!bdev) {
456 ERROR("Out of memory.\n");
457 return 0;
458 }
459 bdev->dev = d;
460 bdev->minor = minor;
461 bdev->subdev = sdev;
462 bdev->subdev_type = COMEDI_SUBD_DIO;
463 bdev->nchans = nchans;
464 bdev->chanid_offset = devpriv->nchans;
465
466 /* map channel id's to BondedDevice * pointer.. */
467 while (nchans--)
468 devpriv->chanIdDevMap[devpriv->nchans++] = bdev;
469
470 /* Now put bdev pointer at end of devpriv->devs array
471 * list.. */
472
473 /* ergh.. ugly.. we need to realloc :( */
474 tmp = devpriv->ndevs * sizeof(bdev);
475 devpriv->devs =
476 Realloc(devpriv->devs,
477 ++devpriv->ndevs * sizeof(bdev), tmp);
478 if (!devpriv->devs) {
479 ERROR("Could not allocate memory. "
480 "Out of memory?");
481 return 0;
482 }
483
484 devpriv->devs[devpriv->ndevs - 1] = bdev;
485 {
486 /** Append dev:subdev to devpriv->name */
487 char buf[20];
488 int left =
489 MAX_BOARD_NAME - strlen(devpriv->name) - 1;
490 snprintf(buf, sizeof(buf), "%d:%d ", dev->minor,
491 bdev->subdev);
492 buf[sizeof(buf) - 1] = 0;
493 strncat(devpriv->name, buf, left);
494 }
495
496 }
497 }
498
499 if (!devpriv->nchans) {
500 ERROR("No channels found!\n");
501 return 0;
502 }
503
504 return 1;
505 }
506
507 static void doDevUnconfig(struct comedi_device *dev)
508 {
509 unsigned long devs_closed = 0;
510
511 if (devpriv) {
512 while (devpriv->ndevs-- && devpriv->devs) {
513 struct BondedDevice *bdev;
514
515 bdev = devpriv->devs[devpriv->ndevs];
516 if (!bdev)
517 continue;
518 if (!(devs_closed & (0x1 << bdev->minor))) {
519 comedi_close(bdev->dev);
520 devs_closed |= (0x1 << bdev->minor);
521 }
522 kfree(bdev);
523 }
524 kfree(devpriv->devs);
525 devpriv->devs = NULL;
526 kfree(devpriv);
527 dev->private = NULL;
528 }
529 }
530
531 static int __init init(void)
532 {
533 return comedi_driver_register(&driver_bonding);
534 }
535
536 static void __exit cleanup(void)
537 {
538 comedi_driver_unregister(&driver_bonding);
539 }
540
541 module_init(init);
542 module_exit(cleanup);