2  * drivers/media/video/v4l2-int-device.c
 
   4  * V4L2 internal ioctl interface.
 
   6  * Copyright (C) 2007 Nokia Corporation.
 
   8  * Contact: Sakari Ailus <sakari.ailus@nokia.com>
 
  10  * This program is free software; you can redistribute it and/or
 
  11  * modify it under the terms of the GNU General Public License
 
  12  * version 2 as published by the Free Software Foundation.
 
  14  * This program is distributed in the hope that it will be useful, but
 
  15  * WITHOUT ANY WARRANTY; without even the implied warranty of
 
  16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
  17  * General Public License for more details.
 
  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., 51 Franklin St, Fifth Floor, Boston, MA
 
  25 #include <linux/kernel.h>
 
  26 #include <linux/list.h>
 
  27 #include <linux/sort.h>
 
  28 #include <linux/string.h>
 
  30 #include <media/v4l2-int-device.h>
 
  32 static DEFINE_MUTEX(mutex);
 
  33 static LIST_HEAD(int_list);
 
  35 static void v4l2_int_device_try_attach_all(void)
 
  37         struct v4l2_int_device *m, *s;
 
  39         list_for_each_entry(m, &int_list, head) {
 
  40                 if (m->type != v4l2_int_type_master)
 
  43                 list_for_each_entry(s, &int_list, head) {
 
  44                         if (s->type != v4l2_int_type_slave)
 
  47                         /* Slave is connected? */
 
  48                         if (s->u.slave->master)
 
  51                         /* Slave wants to attach to master? */
 
  52                         if (s->u.slave->attach_to[0] != 0
 
  53                             && strncmp(m->name, s->u.slave->attach_to,
 
  57                         if (!try_module_get(m->module))
 
  60                         s->u.slave->master = m;
 
  61                         if (m->u.master->attach(s)) {
 
  62                                 s->u.slave->master = NULL;
 
  63                                 module_put(m->module);
 
  70 static int ioctl_sort_cmp(const void *a, const void *b)
 
  72         const struct v4l2_int_ioctl_desc *d1 = a, *d2 = b;
 
  74         if (d1->num > d2->num)
 
  77         if (d1->num < d2->num)
 
  83 int v4l2_int_device_register(struct v4l2_int_device *d)
 
  85         if (d->type == v4l2_int_type_slave)
 
  86                 sort(d->u.slave->ioctls, d->u.slave->num_ioctls,
 
  87                      sizeof(struct v4l2_int_ioctl_desc),
 
  88                      &ioctl_sort_cmp, NULL);
 
  90         list_add(&d->head, &int_list);
 
  91         v4l2_int_device_try_attach_all();
 
  96 EXPORT_SYMBOL_GPL(v4l2_int_device_register);
 
  98 void v4l2_int_device_unregister(struct v4l2_int_device *d)
 
 102         if (d->type == v4l2_int_type_slave
 
 103             && d->u.slave->master != NULL) {
 
 104                 d->u.slave->master->u.master->detach(d);
 
 105                 module_put(d->u.slave->master->module);
 
 106                 d->u.slave->master = NULL;
 
 108         mutex_unlock(&mutex);
 
 110 EXPORT_SYMBOL_GPL(v4l2_int_device_unregister);
 
 112 /* Adapted from search_extable in extable.c. */
 
 113 static v4l2_int_ioctl_func *find_ioctl(struct v4l2_int_slave *slave, int cmd,
 
 114                                        v4l2_int_ioctl_func *no_such_ioctl)
 
 116         const struct v4l2_int_ioctl_desc *first = slave->ioctls;
 
 117         const struct v4l2_int_ioctl_desc *last =
 
 118                 first + slave->num_ioctls - 1;
 
 120         while (first <= last) {
 
 121                 const struct v4l2_int_ioctl_desc *mid;
 
 123                 mid = (last - first) / 2 + first;
 
 127                 else if (mid->num > cmd)
 
 133         return no_such_ioctl;
 
 136 static int no_such_ioctl_0(struct v4l2_int_device *d)
 
 141 int v4l2_int_ioctl_0(struct v4l2_int_device *d, int cmd)
 
 143         return ((v4l2_int_ioctl_func_0 *)
 
 144                 find_ioctl(d->u.slave, cmd,
 
 145                            (v4l2_int_ioctl_func *)no_such_ioctl_0))(d);
 
 148 static int no_such_ioctl_1(struct v4l2_int_device *d, void *arg)
 
 153 int v4l2_int_ioctl_1(struct v4l2_int_device *d, int cmd, void *arg)
 
 155         return ((v4l2_int_ioctl_func_1 *)
 
 156                 find_ioctl(d->u.slave, cmd,
 
 157                            (v4l2_int_ioctl_func *)no_such_ioctl_1))(d, arg);
 
 160 MODULE_LICENSE("GPL");