videocodec.c (cf626b0da78df6669c6b5f51ddd9a70a0702e579) | videocodec.c (2a0c28063de23646bb56152095ce73ea2284dc26) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-or-later |
|
1/* 2 * VIDEO MOTION CODECs internal API for video devices 3 * 4 * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's 5 * bound to a master device. 6 * 7 * (c) 2002 Wolfgang Scherr <scherr@net4you.at> | 2/* 3 * VIDEO MOTION CODECs internal API for video devices 4 * 5 * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's 6 * bound to a master device. 7 * 8 * (c) 2002 Wolfgang Scherr <scherr@net4you.at> |
8 * 9 * $Id: videocodec.c,v 1.1.2.8 2003/03/29 07:16:04 rbultje Exp $ 10 * 11 * ------------------------------------------------------------------------ 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or 16 * (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * ------------------------------------------------------------------------ | |
24 */ 25 | 9 */ 10 |
26#define VIDEOCODEC_VERSION "v0.2" 27 | |
28#include <linux/kernel.h> 29#include <linux/module.h> 30#include <linux/init.h> 31#include <linux/types.h> 32#include <linux/slab.h> 33 | 11#include <linux/kernel.h> 12#include <linux/module.h> 13#include <linux/init.h> 14#include <linux/types.h> 15#include <linux/slab.h> 16 |
34// kernel config is here (procfs flag) 35 36#ifdef CONFIG_PROC_FS 37#include <linux/proc_fs.h> 38#include <linux/seq_file.h> 39#include <linux/uaccess.h> 40#endif 41 | |
42#include "videocodec.h" 43 | 17#include "videocodec.h" 18 |
44static int debug; 45module_param(debug, int, 0); 46MODULE_PARM_DESC(debug, "Debug level (0-4)"); 47 48#define dprintk(num, format, args...) \ 49 do { \ 50 if (debug >= num) \ 51 printk(format, ##args); \ 52 } while (0) 53 | |
54struct attached_list { 55 struct videocodec *codec; 56 struct attached_list *next; 57}; 58 59struct codec_list { 60 const struct videocodec *codec; 61 int attached; 62 struct attached_list *list; 63 struct codec_list *next; 64}; 65 | 19struct attached_list { 20 struct videocodec *codec; 21 struct attached_list *next; 22}; 23 24struct codec_list { 25 const struct videocodec *codec; 26 int attached; 27 struct attached_list *list; 28 struct codec_list *next; 29}; 30 |
66static struct codec_list *codeclist_top = NULL; | 31static struct codec_list *codeclist_top; |
67 68/* ================================================= */ 69/* function prototypes of the master/slave interface */ 70/* ================================================= */ 71 | 32 33/* ================================================= */ 34/* function prototypes of the master/slave interface */ 35/* ================================================= */ 36 |
72struct videocodec * 73videocodec_attach (struct videocodec_master *master) | 37struct videocodec *videocodec_attach(struct videocodec_master *master) |
74{ 75 struct codec_list *h = codeclist_top; | 38{ 39 struct codec_list *h = codeclist_top; |
40 struct zoran *zr; |
|
76 struct attached_list *a, *ptr; 77 struct videocodec *codec; 78 int res; 79 80 if (!master) { | 41 struct attached_list *a, *ptr; 42 struct videocodec *codec; 43 int res; 44 45 if (!master) { |
81 dprintk(1, KERN_ERR "videocodec_attach: no data\n"); | 46 pr_err("%s: no data\n", __func__); |
82 return NULL; 83 } 84 | 47 return NULL; 48 } 49 |
85 dprintk(2, 86 "videocodec_attach: '%s', flags %lx, magic %lx\n", 87 master->name, master->flags, master->magic); | 50 zr = videocodec_master_to_zoran(master); |
88 | 51 |
52 zrdev_dbg(zr, "%s: '%s', flags %lx, magic %lx\n", __func__, 53 master->name, master->flags, master->magic); 54 |
|
89 if (!h) { | 55 if (!h) { |
90 dprintk(1, 91 KERN_ERR 92 "videocodec_attach: no device available\n"); | 56 zrdev_err(zr, "%s: no device available\n", __func__); |
93 return NULL; 94 } 95 96 while (h) { 97 // attach only if the slave has at least the flags 98 // expected by the master 99 if ((master->flags & h->codec->flags) == master->flags) { | 57 return NULL; 58 } 59 60 while (h) { 61 // attach only if the slave has at least the flags 62 // expected by the master 63 if ((master->flags & h->codec->flags) == master->flags) { |
100 dprintk(4, "videocodec_attach: try '%s'\n", 101 h->codec->name); | 64 zrdev_dbg(zr, "%s: try '%s'\n", __func__, h->codec->name); |
102 | 65 |
103 if (!try_module_get(h->codec->owner)) 104 return NULL; | 66 codec = kmemdup(h->codec, sizeof(struct videocodec), GFP_KERNEL); 67 if (!codec) 68 goto out_kfree; |
105 | 69 |
106 codec = kmemdup(h->codec, sizeof(struct videocodec), 107 GFP_KERNEL); 108 if (!codec) { 109 dprintk(1, 110 KERN_ERR 111 "videocodec_attach: no mem\n"); 112 goto out_module_put; 113 } 114 | |
115 res = strlen(codec->name); | 70 res = strlen(codec->name); |
116 snprintf(codec->name + res, sizeof(codec->name) - res, 117 "[%d]", h->attached); | 71 snprintf(codec->name + res, sizeof(codec->name) - res, "[%d]", h->attached); |
118 codec->master_data = master; 119 res = codec->setup(codec); 120 if (res == 0) { | 72 codec->master_data = master; 73 res = codec->setup(codec); 74 if (res == 0) { |
121 dprintk(3, "videocodec_attach '%s'\n", 122 codec->name); 123 ptr = kzalloc(sizeof(struct attached_list), GFP_KERNEL); 124 if (!ptr) { 125 dprintk(1, 126 KERN_ERR 127 "videocodec_attach: no memory\n"); | 75 zrdev_dbg(zr, "%s: '%s'\n", __func__, codec->name); 76 ptr = kzalloc(sizeof(*ptr), GFP_KERNEL); 77 if (!ptr) |
128 goto out_kfree; | 78 goto out_kfree; |
129 } | |
130 ptr->codec = codec; 131 132 a = h->list; 133 if (!a) { 134 h->list = ptr; | 79 ptr->codec = codec; 80 81 a = h->list; 82 if (!a) { 83 h->list = ptr; |
135 dprintk(4, 136 "videocodec: first element\n"); | 84 zrdev_dbg(zr, "videocodec: first element\n"); |
137 } else { 138 while (a->next) 139 a = a->next; // find end 140 a->next = ptr; | 85 } else { 86 while (a->next) 87 a = a->next; // find end 88 a->next = ptr; |
141 dprintk(4, 142 "videocodec: in after '%s'\n", 143 h->codec->name); | 89 zrdev_dbg(zr, "videocodec: in after '%s'\n", 90 h->codec->name); |
144 } 145 146 h->attached += 1; 147 return codec; | 91 } 92 93 h->attached += 1; 94 return codec; |
148 } else { 149 kfree(codec); | |
150 } | 95 } |
96 kfree(codec); |
|
151 } 152 h = h->next; 153 } 154 | 97 } 98 h = h->next; 99 } 100 |
155 dprintk(1, KERN_ERR "videocodec_attach: no codec found!\n"); | 101 zrdev_err(zr, "%s: no codec found!\n", __func__); |
156 return NULL; 157 | 102 return NULL; 103 |
158 out_module_put: 159 module_put(h->codec->owner); | |
160 out_kfree: 161 kfree(codec); 162 return NULL; 163} 164 | 104 out_kfree: 105 kfree(codec); 106 return NULL; 107} 108 |
165int 166videocodec_detach (struct videocodec *codec) | 109int videocodec_detach(struct videocodec *codec) |
167{ 168 struct codec_list *h = codeclist_top; | 110{ 111 struct codec_list *h = codeclist_top; |
112 struct zoran *zr; |
|
169 struct attached_list *a, *prev; 170 int res; 171 172 if (!codec) { | 113 struct attached_list *a, *prev; 114 int res; 115 116 if (!codec) { |
173 dprintk(1, KERN_ERR "videocodec_detach: no data\n"); | 117 pr_err("%s: no data\n", __func__); |
174 return -EINVAL; 175 } 176 | 118 return -EINVAL; 119 } 120 |
177 dprintk(2, 178 "videocodec_detach: '%s', type: %x, flags %lx, magic %lx\n", 179 codec->name, codec->type, codec->flags, codec->magic); | 121 zr = videocodec_to_zoran(codec); |
180 | 122 |
123 zrdev_dbg(zr, "%s: '%s', type: %x, flags %lx, magic %lx\n", __func__, 124 codec->name, codec->type, codec->flags, codec->magic); 125 |
|
181 if (!h) { | 126 if (!h) { |
182 dprintk(1, 183 KERN_ERR "videocodec_detach: no device left...\n"); | 127 zrdev_err(zr, "%s: no device left...\n", __func__); |
184 return -ENXIO; 185 } 186 187 while (h) { 188 a = h->list; 189 prev = NULL; 190 while (a) { 191 if (codec == a->codec) { 192 res = a->codec->unset(a->codec); 193 if (res >= 0) { | 128 return -ENXIO; 129 } 130 131 while (h) { 132 a = h->list; 133 prev = NULL; 134 while (a) { 135 if (codec == a->codec) { 136 res = a->codec->unset(a->codec); 137 if (res >= 0) { |
194 dprintk(3, 195 "videocodec_detach: '%s'\n", 196 a->codec->name); | 138 zrdev_dbg(zr, "%s: '%s'\n", __func__, 139 a->codec->name); |
197 a->codec->master_data = NULL; 198 } else { | 140 a->codec->master_data = NULL; 141 } else { |
199 dprintk(1, 200 KERN_ERR 201 "videocodec_detach: '%s'\n", 202 a->codec->name); | 142 zrdev_err(zr, "%s: '%s'\n", __func__, a->codec->name); |
203 a->codec->master_data = NULL; 204 } | 143 a->codec->master_data = NULL; 144 } |
205 if (prev == NULL) { | 145 if (!prev) { |
206 h->list = a->next; | 146 h->list = a->next; |
207 dprintk(4, 208 "videocodec: delete first\n"); | 147 zrdev_dbg(zr, "videocodec: delete first\n"); |
209 } else { 210 prev->next = a->next; | 148 } else { 149 prev->next = a->next; |
211 dprintk(4, 212 "videocodec: delete middle\n"); | 150 zrdev_dbg(zr, "videocodec: delete middle\n"); |
213 } | 151 } |
214 module_put(a->codec->owner); | |
215 kfree(a->codec); 216 kfree(a); 217 h->attached -= 1; 218 return 0; 219 } 220 prev = a; 221 a = a->next; 222 } 223 h = h->next; 224 } 225 | 152 kfree(a->codec); 153 kfree(a); 154 h->attached -= 1; 155 return 0; 156 } 157 prev = a; 158 a = a->next; 159 } 160 h = h->next; 161 } 162 |
226 dprintk(1, KERN_ERR "videocodec_detach: given codec not found!\n"); | 163 zrdev_err(zr, "%s: given codec not found!\n", __func__); |
227 return -EINVAL; 228} 229 | 164 return -EINVAL; 165} 166 |
230int 231videocodec_register (const struct videocodec *codec) | 167int videocodec_register(const struct videocodec *codec) |
232{ 233 struct codec_list *ptr, *h = codeclist_top; | 168{ 169 struct codec_list *ptr, *h = codeclist_top; |
170 struct zoran *zr; |
|
234 235 if (!codec) { | 171 172 if (!codec) { |
236 dprintk(1, KERN_ERR "videocodec_register: no data!\n"); | 173 pr_err("%s: no data!\n", __func__); |
237 return -EINVAL; 238 } 239 | 174 return -EINVAL; 175 } 176 |
240 dprintk(2, 241 "videocodec: register '%s', type: %x, flags %lx, magic %lx\n", 242 codec->name, codec->type, codec->flags, codec->magic); | 177 zr = videocodec_to_zoran((struct videocodec *)codec); |
243 | 178 |
244 ptr = kzalloc(sizeof(struct codec_list), GFP_KERNEL); 245 if (!ptr) { 246 dprintk(1, KERN_ERR "videocodec_register: no memory\n"); | 179 zrdev_dbg(zr, 180 "videocodec: register '%s', type: %x, flags %lx, magic %lx\n", 181 codec->name, codec->type, codec->flags, codec->magic); 182 183 ptr = kzalloc(sizeof(*ptr), GFP_KERNEL); 184 if (!ptr) |
247 return -ENOMEM; | 185 return -ENOMEM; |
248 } | |
249 ptr->codec = codec; 250 251 if (!h) { 252 codeclist_top = ptr; | 186 ptr->codec = codec; 187 188 if (!h) { 189 codeclist_top = ptr; |
253 dprintk(4, "videocodec: hooked in as first element\n"); | 190 zrdev_dbg(zr, "videocodec: hooked in as first element\n"); |
254 } else { 255 while (h->next) 256 h = h->next; // find the end 257 h->next = ptr; | 191 } else { 192 while (h->next) 193 h = h->next; // find the end 194 h->next = ptr; |
258 dprintk(4, "videocodec: hooked in after '%s'\n", 259 h->codec->name); | 195 zrdev_dbg(zr, "videocodec: hooked in after '%s'\n", 196 h->codec->name); |
260 } 261 262 return 0; 263} 264 | 197 } 198 199 return 0; 200} 201 |
265int 266videocodec_unregister (const struct videocodec *codec) | 202int videocodec_unregister(const struct videocodec *codec) |
267{ 268 struct codec_list *prev = NULL, *h = codeclist_top; | 203{ 204 struct codec_list *prev = NULL, *h = codeclist_top; |
205 struct zoran *zr; |
|
269 270 if (!codec) { | 206 207 if (!codec) { |
271 dprintk(1, KERN_ERR "videocodec_unregister: no data!\n"); | 208 pr_err("%s: no data!\n", __func__); |
272 return -EINVAL; 273 } 274 | 209 return -EINVAL; 210 } 211 |
275 dprintk(2, 276 "videocodec: unregister '%s', type: %x, flags %lx, magic %lx\n", 277 codec->name, codec->type, codec->flags, codec->magic); | 212 zr = videocodec_to_zoran((struct videocodec *)codec); |
278 | 213 |
214 zrdev_dbg(zr, 215 "videocodec: unregister '%s', type: %x, flags %lx, magic %lx\n", 216 codec->name, codec->type, codec->flags, codec->magic); 217 |
|
279 if (!h) { | 218 if (!h) { |
280 dprintk(1, 281 KERN_ERR 282 "videocodec_unregister: no device left...\n"); | 219 zrdev_err(zr, "%s: no device left...\n", __func__); |
283 return -ENXIO; 284 } 285 286 while (h) { 287 if (codec == h->codec) { 288 if (h->attached) { | 220 return -ENXIO; 221 } 222 223 while (h) { 224 if (codec == h->codec) { 225 if (h->attached) { |
289 dprintk(1, 290 KERN_ERR 291 "videocodec: '%s' is used\n", 292 h->codec->name); | 226 zrdev_err(zr, "videocodec: '%s' is used\n", 227 h->codec->name); |
293 return -EBUSY; 294 } | 228 return -EBUSY; 229 } |
295 dprintk(3, "videocodec: unregister '%s' is ok.\n", 296 h->codec->name); 297 if (prev == NULL) { | 230 zrdev_dbg(zr, "videocodec: unregister '%s' is ok.\n", 231 h->codec->name); 232 if (!prev) { |
298 codeclist_top = h->next; | 233 codeclist_top = h->next; |
299 dprintk(4, 300 "videocodec: delete first element\n"); | 234 zrdev_dbg(zr, 235 "videocodec: delete first element\n"); |
301 } else { 302 prev->next = h->next; | 236 } else { 237 prev->next = h->next; |
303 dprintk(4, 304 "videocodec: delete middle element\n"); | 238 zrdev_dbg(zr, 239 "videocodec: delete middle element\n"); |
305 } 306 kfree(h); 307 return 0; 308 } 309 prev = h; 310 h = h->next; 311 } 312 | 240 } 241 kfree(h); 242 return 0; 243 } 244 prev = h; 245 h = h->next; 246 } 247 |
313 dprintk(1, 314 KERN_ERR 315 "videocodec_unregister: given codec not found!\n"); | 248 zrdev_err(zr, "%s: given codec not found!\n", __func__); |
316 return -EINVAL; 317} 318 | 249 return -EINVAL; 250} 251 |
319#ifdef CONFIG_PROC_FS 320static int proc_videocodecs_show(struct seq_file *m, void *v) | 252int videocodec_debugfs_show(struct seq_file *m) |
321{ 322 struct codec_list *h = codeclist_top; 323 struct attached_list *a; 324 | 253{ 254 struct codec_list *h = codeclist_top; 255 struct attached_list *a; 256 |
325 seq_printf(m, "<S>lave or attached <M>aster name type flags magic "); 326 seq_printf(m, "(connected as)\n"); | 257 seq_puts(m, "<S>lave or attached <M>aster name type flags magic "); 258 seq_puts(m, "(connected as)\n"); |
327 328 while (h) { 329 seq_printf(m, "S %32s %04x %08lx %08lx (TEMPLATE)\n", | 259 260 while (h) { 261 seq_printf(m, "S %32s %04x %08lx %08lx (TEMPLATE)\n", |
330 h->codec->name, h->codec->type, | 262 h->codec->name, h->codec->type, |
331 h->codec->flags, h->codec->magic); 332 a = h->list; 333 while (a) { 334 seq_printf(m, "M %32s %04x %08lx %08lx (%s)\n", | 263 h->codec->flags, h->codec->magic); 264 a = h->list; 265 while (a) { 266 seq_printf(m, "M %32s %04x %08lx %08lx (%s)\n", |
335 a->codec->master_data->name, | 267 a->codec->master_data->name, |
336 a->codec->master_data->type, 337 a->codec->master_data->flags, 338 a->codec->master_data->magic, 339 a->codec->name); 340 a = a->next; 341 } 342 h = h->next; 343 } 344 345 return 0; 346} | 268 a->codec->master_data->type, 269 a->codec->master_data->flags, 270 a->codec->master_data->magic, 271 a->codec->name); 272 a = a->next; 273 } 274 h = h->next; 275 } 276 277 return 0; 278} |
347#endif 348 349/* ===================== */ 350/* hook in driver module */ 351/* ===================== */ 352static int __init 353videocodec_init (void) 354{ 355#ifdef CONFIG_PROC_FS 356 static struct proc_dir_entry *videocodec_proc_entry; 357#endif 358 359 printk(KERN_INFO "Linux video codec intermediate layer: %s\n", 360 VIDEOCODEC_VERSION); 361 362#ifdef CONFIG_PROC_FS 363 videocodec_proc_entry = proc_create_single("videocodecs", 0, NULL, 364 proc_videocodecs_show); 365 if (!videocodec_proc_entry) { 366 dprintk(1, KERN_ERR "videocodec: can't init procfs.\n"); 367 } 368#endif 369 return 0; 370} 371 372static void __exit 373videocodec_exit (void) 374{ 375#ifdef CONFIG_PROC_FS 376 remove_proc_entry("videocodecs", NULL); 377#endif 378} 379 380EXPORT_SYMBOL(videocodec_attach); 381EXPORT_SYMBOL(videocodec_detach); 382EXPORT_SYMBOL(videocodec_register); 383EXPORT_SYMBOL(videocodec_unregister); 384 385module_init(videocodec_init); 386module_exit(videocodec_exit); 387 388MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>"); 389MODULE_DESCRIPTION("Intermediate API module for video codecs " 390 VIDEOCODEC_VERSION); 391MODULE_LICENSE("GPL"); | |