11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * VIDEO MOTION CODECs internal API for video devices 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bound to a master device. 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (c) 2002 Wolfgang Scherr <scherr@net4you.at> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * $Id: videocodec.c,v 1.1.2.8 2003/03/29 07:16:04 rbultje Exp $ 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ------------------------------------------------------------------------ 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version. 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details. 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ------------------------------------------------------------------------ 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VIDEOCODEC_VERSION "v0.2" 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// kernel config is here (procfs flag) 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PROC_FS 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h> 429faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyan#include <linux/seq_file.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "videocodec.h" 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 48ff699e6bd02eb1c6d02c7c2b576c2ee6caab201cDouglas Schilling Landgrafstatic int debug; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debug, int, 0); 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "Debug level (0-4)"); 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define dprintk(num, format, args...) \ 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { \ 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (debug >= num) \ 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(format, ##args); \ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (0) 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct attached_list { 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct videocodec *codec; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct attached_list *next; 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct codec_list { 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct videocodec *codec; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int attached; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct attached_list *list; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct codec_list *next; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct codec_list *codeclist_top = NULL; 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ================================================= */ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* function prototypes of the master/slave interface */ 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ================================================= */ 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct videocodec * 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvideocodec_attach (struct videocodec_master *master) 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct codec_list *h = codeclist_top; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct attached_list *a, *ptr; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct videocodec *codec; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int res; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!master) { 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(1, KERN_ERR "videocodec_attach: no data\n"); 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(2, 9022c4a4e98ece0eaff13b3d0ac73c5283013eb6b1Mauro Carvalho Chehab "videocodec_attach: '%s', flags %lx, magic %lx\n", 9122c4a4e98ece0eaff13b3d0ac73c5283013eb6b1Mauro Carvalho Chehab master->name, master->flags, master->magic); 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!h) { 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(1, 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds KERN_ERR 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "videocodec_attach: no device available\n"); 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (h) { 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // attach only if the slave has at least the flags 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // expected by the master 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((master->flags & h->codec->flags) == master->flags) { 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(4, "videocodec_attach: try '%s'\n", 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h->codec->name); 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!try_module_get(h->codec->owner)) 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1107a12f4b50dad4fdffd218c6fba6b9564bf86185eJulia Lawall codec = kmemdup(h->codec, sizeof(struct videocodec), 1117a12f4b50dad4fdffd218c6fba6b9564bf86185eJulia Lawall GFP_KERNEL); 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!codec) { 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(1, 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds KERN_ERR 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "videocodec_attach: no mem\n"); 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_module_put; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snprintf(codec->name, sizeof(codec->name), 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%s[%d]", codec->name, h->attached); 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds codec->master_data = master; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = codec->setup(codec); 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (res == 0) { 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(3, "videocodec_attach '%s'\n", 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds codec->name); 1267408187d223f63d46a13b6a35b8f96b032c2f623Panagiotis Issaris ptr = kzalloc(sizeof(struct attached_list), GFP_KERNEL); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ptr) { 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(1, 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds KERN_ERR 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "videocodec_attach: no memory\n"); 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_kfree; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr->codec = codec; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a = h->list; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!a) { 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h->list = ptr; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(4, 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "videocodec: first element\n"); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (a->next) 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a = a->next; // find end 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a->next = ptr; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(4, 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "videocodec: in after '%s'\n", 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h->codec->name); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h->attached += 1; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return codec; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(codec); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h = h->next; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(1, KERN_ERR "videocodec_attach: no codec found!\n"); 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out_module_put: 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds module_put(h->codec->owner); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out_kfree: 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(codec); 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvideocodec_detach (struct videocodec *codec) 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct codec_list *h = codeclist_top; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct attached_list *a, *prev; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int res; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!codec) { 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(1, KERN_ERR "videocodec_detach: no data\n"); 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(2, 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "videocodec_detach: '%s', type: %x, flags %lx, magic %lx\n", 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds codec->name, codec->type, codec->flags, codec->magic); 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!h) { 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(1, 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds KERN_ERR "videocodec_detach: no device left...\n"); 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENXIO; 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (h) { 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a = h->list; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev = NULL; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (a) { 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (codec == a->codec) { 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res = a->codec->unset(a->codec); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (res >= 0) { 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(3, 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "videocodec_detach: '%s'\n", 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a->codec->name); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a->codec->master_data = NULL; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(1, 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds KERN_ERR 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "videocodec_detach: '%s'\n", 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a->codec->name); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a->codec->master_data = NULL; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (prev == NULL) { 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h->list = a->next; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(4, 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "videocodec: delete first\n"); 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev->next = a->next; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(4, 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "videocodec: delete middle\n"); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds module_put(a->codec->owner); 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(a->codec); 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(a); 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h->attached -= 1; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev = a; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a = a->next; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h = h->next; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(1, KERN_ERR "videocodec_detach: given codec not found!\n"); 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvideocodec_register (const struct videocodec *codec) 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct codec_list *ptr, *h = codeclist_top; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!codec) { 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(1, KERN_ERR "videocodec_register: no data!\n"); 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(2, 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "videocodec: register '%s', type: %x, flags %lx, magic %lx\n", 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds codec->name, codec->type, codec->flags, codec->magic); 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2477408187d223f63d46a13b6a35b8f96b032c2f623Panagiotis Issaris ptr = kzalloc(sizeof(struct codec_list), GFP_KERNEL); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ptr) { 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(1, KERN_ERR "videocodec_register: no memory\n"); 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr->codec = codec; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!h) { 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds codeclist_top = ptr; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(4, "videocodec: hooked in as first element\n"); 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (h->next) 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h = h->next; // find the end 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h->next = ptr; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(4, "videocodec: hooked in after '%s'\n", 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h->codec->name); 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvideocodec_unregister (const struct videocodec *codec) 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct codec_list *prev = NULL, *h = codeclist_top; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!codec) { 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(1, KERN_ERR "videocodec_unregister: no data!\n"); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(2, 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "videocodec: unregister '%s', type: %x, flags %lx, magic %lx\n", 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds codec->name, codec->type, codec->flags, codec->magic); 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!h) { 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(1, 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds KERN_ERR 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "videocodec_unregister: no device left...\n"); 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENXIO; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (h) { 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (codec == h->codec) { 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (h->attached) { 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(1, 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds KERN_ERR 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "videocodec: '%s' is used\n", 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h->codec->name); 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(3, "videocodec: unregister '%s' is ok.\n", 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h->codec->name); 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (prev == NULL) { 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds codeclist_top = h->next; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(4, 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "videocodec: delete first element\n"); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev->next = h->next; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(4, 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "videocodec: delete middle element\n"); 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(h); 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev = h; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h = h->next; 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(1, 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds KERN_ERR 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "videocodec_unregister: given codec not found!\n"); 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PROC_FS 3239faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyanstatic int proc_videocodecs_show(struct seq_file *m, void *v) 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct codec_list *h = codeclist_top; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct attached_list *a; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3289faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyan seq_printf(m, "<S>lave or attached <M>aster name type flags magic "); 3299faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyan seq_printf(m, "(connected as)\n"); 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h = codeclist_top; 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (h) { 3339faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyan seq_printf(m, "S %32s %04x %08lx %08lx (TEMPLATE)\n", 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h->codec->name, h->codec->type, 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h->codec->flags, h->codec->magic); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a = h->list; 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (a) { 3389faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyan seq_printf(m, "M %32s %04x %08lx %08lx (%s)\n", 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a->codec->master_data->name, 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a->codec->master_data->type, 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a->codec->master_data->flags, 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a->codec->master_data->magic, 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a->codec->name); 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a = a->next; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h = h->next; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3499faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyan return 0; 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3529faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyanstatic int proc_videocodecs_open(struct inode *inode, struct file *file) 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3549faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyan return single_open(file, proc_videocodecs_show, NULL); 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3569faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyan 3579faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyanstatic const struct file_operations videocodecs_proc_fops = { 3589faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyan .owner = THIS_MODULE, 3599faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyan .open = proc_videocodecs_open, 3609faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyan .read = seq_read, 3619faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyan .llseek = seq_lseek, 3629faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyan .release = single_release, 3639faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyan}; 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ===================== */ 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* hook in driver module */ 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ===================== */ 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvideocodec_init (void) 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PROC_FS 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static struct proc_dir_entry *videocodec_proc_entry; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "Linux video codec intermediate layer: %s\n", 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds VIDEOCODEC_VERSION); 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PROC_FS 3809faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyan videocodec_proc_entry = proc_create("videocodecs", 0, NULL, &videocodecs_proc_fops); 3819faa2d75822e1950b3aacc8ccbdf0cdb595e47deAlexey Dobriyan if (!videocodec_proc_entry) { 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(1, KERN_ERR "videocodec: can't init procfs.\n"); 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvideocodec_exit (void) 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PROC_FS 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remove_proc_entry("videocodecs", NULL); 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(videocodec_attach); 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(videocodec_detach); 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(videocodec_register); 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(videocodec_unregister); 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(videocodec_init); 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(videocodec_exit); 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>"); 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Intermediate API module for video codecs " 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds VIDEOCODEC_VERSION); 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 408