Blame view
drivers/media/video/v4l2-int-device.c
3.86 KB
9b5d0f1e6
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
/* * drivers/media/video/v4l2-int-device.c * * V4L2 internal ioctl interface. * * Copyright (C) 2007 Nokia Corporation. * * Contact: Sakari Ailus <sakari.ailus@nokia.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include <linux/kernel.h> #include <linux/list.h> #include <linux/sort.h> #include <linux/string.h> #include <media/v4l2-int-device.h> static DEFINE_MUTEX(mutex); static LIST_HEAD(int_list); |
36499e525
|
34 |
void v4l2_int_device_try_attach_all(void) |
9b5d0f1e6
|
35 |
{ |
a991f44b7
|
36 |
struct v4l2_int_device *m, *s; |
9b5d0f1e6
|
37 |
|
a991f44b7
|
38 |
list_for_each_entry(m, &int_list, head) { |
9b5d0f1e6
|
39 40 |
if (m->type != v4l2_int_type_master) continue; |
a991f44b7
|
41 |
list_for_each_entry(s, &int_list, head) { |
9b5d0f1e6
|
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
if (s->type != v4l2_int_type_slave) continue; /* Slave is connected? */ if (s->u.slave->master) continue; /* Slave wants to attach to master? */ if (s->u.slave->attach_to[0] != 0 && strncmp(m->name, s->u.slave->attach_to, V4L2NAMESIZE)) continue; if (!try_module_get(m->module)) continue; |
2c94a674e
|
57 58 59 |
s->u.slave->master = m; if (m->u.master->attach(s)) { s->u.slave->master = NULL; |
9b5d0f1e6
|
60 61 62 |
module_put(m->module); continue; } |
9b5d0f1e6
|
63 64 65 |
} } } |
36499e525
|
66 |
EXPORT_SYMBOL_GPL(v4l2_int_device_try_attach_all); |
9b5d0f1e6
|
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
static int ioctl_sort_cmp(const void *a, const void *b) { const struct v4l2_int_ioctl_desc *d1 = a, *d2 = b; if (d1->num > d2->num) return 1; if (d1->num < d2->num) return -1; return 0; } int v4l2_int_device_register(struct v4l2_int_device *d) { if (d->type == v4l2_int_type_slave) sort(d->u.slave->ioctls, d->u.slave->num_ioctls, sizeof(struct v4l2_int_ioctl_desc), &ioctl_sort_cmp, NULL); mutex_lock(&mutex); list_add(&d->head, &int_list); v4l2_int_device_try_attach_all(); mutex_unlock(&mutex); return 0; } |
261efd12f
|
94 |
EXPORT_SYMBOL_GPL(v4l2_int_device_register); |
9b5d0f1e6
|
95 96 97 98 99 100 101 102 103 104 105 106 107 |
void v4l2_int_device_unregister(struct v4l2_int_device *d) { mutex_lock(&mutex); list_del(&d->head); if (d->type == v4l2_int_type_slave && d->u.slave->master != NULL) { d->u.slave->master->u.master->detach(d); module_put(d->u.slave->master->module); d->u.slave->master = NULL; } mutex_unlock(&mutex); } |
261efd12f
|
108 |
EXPORT_SYMBOL_GPL(v4l2_int_device_unregister); |
9b5d0f1e6
|
109 |
|
9b5d0f1e6
|
110 |
/* Adapted from search_extable in extable.c. */ |
63116febb
|
111 112 |
static v4l2_int_ioctl_func *find_ioctl(struct v4l2_int_slave *slave, int cmd, v4l2_int_ioctl_func *no_such_ioctl) |
9b5d0f1e6
|
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
{ const struct v4l2_int_ioctl_desc *first = slave->ioctls; const struct v4l2_int_ioctl_desc *last = first + slave->num_ioctls - 1; while (first <= last) { const struct v4l2_int_ioctl_desc *mid; mid = (last - first) / 2 + first; if (mid->num < cmd) first = mid + 1; else if (mid->num > cmd) last = mid - 1; else return mid->func; } |
63116febb
|
130 131 132 133 134 |
return no_such_ioctl; } static int no_such_ioctl_0(struct v4l2_int_device *d) { |
61c310dc1
|
135 |
return -ENOIOCTLCMD; |
9b5d0f1e6
|
136 137 138 139 |
} int v4l2_int_ioctl_0(struct v4l2_int_device *d, int cmd) { |
63116febb
|
140 141 |
return ((v4l2_int_ioctl_func_0 *) find_ioctl(d->u.slave, cmd, |
098c645e3
|
142 |
(v4l2_int_ioctl_func *)no_such_ioctl_0))(d); |
63116febb
|
143 |
} |
36499e525
|
144 |
EXPORT_SYMBOL_GPL(v4l2_int_ioctl_0); |
63116febb
|
145 146 147 |
static int no_such_ioctl_1(struct v4l2_int_device *d, void *arg) { |
61c310dc1
|
148 |
return -ENOIOCTLCMD; |
9b5d0f1e6
|
149 150 151 152 |
} int v4l2_int_ioctl_1(struct v4l2_int_device *d, int cmd, void *arg) { |
63116febb
|
153 154 |
return ((v4l2_int_ioctl_func_1 *) find_ioctl(d->u.slave, cmd, |
098c645e3
|
155 |
(v4l2_int_ioctl_func *)no_such_ioctl_1))(d, arg); |
9b5d0f1e6
|
156 |
} |
36499e525
|
157 |
EXPORT_SYMBOL_GPL(v4l2_int_ioctl_1); |
19ac111c0
|
158 159 |
MODULE_LICENSE("GPL"); |