brintos

brintos / linux-shallow public Read only

0
0
Text · 6.1 KiB · 8efc5e0 Raw
279 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * VIDEO MOTION CODECs internal API for video devices4 *5 * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's6 * bound to a master device.7 *8 * (c) 2002 Wolfgang Scherr <scherr@net4you.at>9 */10 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 17#include "videocodec.h"18 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 31static struct codec_list *codeclist_top;32 33/* ================================================= */34/* function prototypes of the master/slave interface */35/* ================================================= */36 37struct videocodec *videocodec_attach(struct videocodec_master *master)38{39	struct codec_list *h = codeclist_top;40	struct zoran *zr;41	struct attached_list *a, *ptr;42	struct videocodec *codec;43	int res;44 45	if (!master) {46		pr_err("%s: no data\n", __func__);47		return NULL;48	}49 50	zr = videocodec_master_to_zoran(master);51 52	zrdev_dbg(zr, "%s: '%s', flags %lx, magic %lx\n", __func__,53		  master->name, master->flags, master->magic);54 55	if (!h) {56		zrdev_err(zr, "%s: no device available\n", __func__);57		return NULL;58	}59 60	while (h) {61		// attach only if the slave has at least the flags62		// expected by the master63		if ((master->flags & h->codec->flags) == master->flags) {64			zrdev_dbg(zr, "%s: try '%s'\n", __func__, h->codec->name);65 66			codec = kmemdup(h->codec, sizeof(struct videocodec), GFP_KERNEL);67			if (!codec)68				goto out_kfree;69 70			res = strlen(codec->name);71			snprintf(codec->name + res, sizeof(codec->name) - res, "[%d]", h->attached);72			codec->master_data = master;73			res = codec->setup(codec);74			if (res == 0) {75				zrdev_dbg(zr, "%s: '%s'\n", __func__, codec->name);76				ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);77				if (!ptr)78					goto out_kfree;79				ptr->codec = codec;80 81				a = h->list;82				if (!a) {83					h->list = ptr;84					zrdev_dbg(zr, "videocodec: first element\n");85				} else {86					while (a->next)87						a = a->next;	// find end88					a->next = ptr;89					zrdev_dbg(zr, "videocodec: in after '%s'\n",90						  h->codec->name);91				}92 93				h->attached += 1;94				return codec;95			}96			kfree(codec);97		}98		h = h->next;99	}100 101	zrdev_err(zr, "%s: no codec found!\n", __func__);102	return NULL;103 104 out_kfree:105	kfree(codec);106	return NULL;107}108 109int videocodec_detach(struct videocodec *codec)110{111	struct codec_list *h = codeclist_top;112	struct zoran *zr;113	struct attached_list *a, *prev;114	int res;115 116	if (!codec) {117		pr_err("%s: no data\n", __func__);118		return -EINVAL;119	}120 121	zr = videocodec_to_zoran(codec);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 126	if (!h) {127		zrdev_err(zr, "%s: no device left...\n", __func__);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) {138					zrdev_dbg(zr, "%s: '%s'\n", __func__,139						  a->codec->name);140					a->codec->master_data = NULL;141				} else {142					zrdev_err(zr, "%s: '%s'\n", __func__, a->codec->name);143					a->codec->master_data = NULL;144				}145				if (!prev) {146					h->list = a->next;147					zrdev_dbg(zr, "videocodec: delete first\n");148				} else {149					prev->next = a->next;150					zrdev_dbg(zr, "videocodec: delete middle\n");151				}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 163	zrdev_err(zr, "%s: given codec not found!\n", __func__);164	return -EINVAL;165}166 167int videocodec_register(const struct videocodec *codec)168{169	struct codec_list *ptr, *h = codeclist_top;170	struct zoran *zr;171 172	if (!codec) {173		pr_err("%s: no data!\n", __func__);174		return -EINVAL;175	}176 177	zr = videocodec_to_zoran((struct videocodec *)codec);178 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)185		return -ENOMEM;186	ptr->codec = codec;187 188	if (!h) {189		codeclist_top = ptr;190		zrdev_dbg(zr, "videocodec: hooked in as first element\n");191	} else {192		while (h->next)193			h = h->next;	// find the end194		h->next = ptr;195		zrdev_dbg(zr, "videocodec: hooked in after '%s'\n",196			  h->codec->name);197	}198 199	return 0;200}201 202int videocodec_unregister(const struct videocodec *codec)203{204	struct codec_list *prev = NULL, *h = codeclist_top;205	struct zoran *zr;206 207	if (!codec) {208		pr_err("%s: no data!\n", __func__);209		return -EINVAL;210	}211 212	zr = videocodec_to_zoran((struct videocodec *)codec);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 218	if (!h) {219		zrdev_err(zr, "%s: no device left...\n", __func__);220		return -ENXIO;221	}222 223	while (h) {224		if (codec == h->codec) {225			if (h->attached) {226				zrdev_err(zr, "videocodec: '%s' is used\n",227					  h->codec->name);228				return -EBUSY;229			}230			zrdev_dbg(zr, "videocodec: unregister '%s' is ok.\n",231				  h->codec->name);232			if (!prev) {233				codeclist_top = h->next;234				zrdev_dbg(zr,235					  "videocodec: delete first element\n");236			} else {237				prev->next = h->next;238				zrdev_dbg(zr,239					  "videocodec: delete middle element\n");240			}241			kfree(h);242			return 0;243		}244		prev = h;245		h = h->next;246	}247 248	zrdev_err(zr, "%s: given codec not found!\n", __func__);249	return -EINVAL;250}251 252int videocodec_debugfs_show(struct seq_file *m)253{254	struct codec_list *h = codeclist_top;255	struct attached_list *a;256 257	seq_puts(m, "<S>lave or attached <M>aster name  type flags    magic    ");258	seq_puts(m, "(connected as)\n");259 260	while (h) {261		seq_printf(m, "S %32s %04x %08lx %08lx (TEMPLATE)\n",262			   h->codec->name, h->codec->type,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",267				   a->codec->master_data->name,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}279