• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2010 Nokia Corporation <multimedia@maemo.org>
3 
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; either version 2.1 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18 
19 #include <stdarg.h>
20 #include <dlfcn.h>
21 #include <fcntl.h>
22 #include <glob.h>
23 #include <sys/stat.h>
24 #include <sys/mman.h>
25 #include "libv4l2.h"
26 #include "libv4l2-priv.h"
27 #include "libv4l-plugin.h"
28 
29 /* libv4l plugin support:
30    it is provided by functions v4l2_plugin_[open,close,etc].
31 
32    When open() is called libv4l dlopens files in /usr/lib[64]/libv4l/plugins
33    1 at a time and call open callback passing through the applications
34    parameters unmodified.
35 
36    If a plugin is relevant for the specified device node, it can indicate so
37    by returning a value other than -1 (the actual file descriptor).
38    As soon as a plugin returns another value than -1 plugin loading stops and
39    information about it (fd and corresponding library handle) is stored. For
40    each function v4l2_[ioctl,read,close,etc] is called corresponding
41    v4l2_plugin_* function which looks if there is loaded plugin for that file
42    and call it's callbacks.
43 
44    v4l2_plugin_* function indicates by it's first argument if plugin was used,
45    and if it was not then v4l2_* functions proceed with their usual behavior.
46 */
47 
48 #define PLUGINS_PATTERN LIBV4L2_PLUGIN_DIR "/*.so"
49 
v4l2_plugin_init(int fd,void ** plugin_lib_ret,void ** plugin_priv_ret,const struct libv4l_dev_ops ** dev_ops_ret)50 void v4l2_plugin_init(int fd, void **plugin_lib_ret, void **plugin_priv_ret,
51 		      const struct libv4l_dev_ops **dev_ops_ret)
52 {
53 	char *error;
54 	int glob_ret, i;
55 	void *plugin_library = NULL;
56 	const struct libv4l_dev_ops *libv4l2_plugin = NULL;
57 	glob_t globbuf;
58 
59 	*dev_ops_ret = v4lconvert_get_default_dev_ops();
60 	*plugin_lib_ret = NULL;
61 	*plugin_priv_ret = NULL;
62 
63 	glob_ret = glob(PLUGINS_PATTERN, 0, NULL, &globbuf);
64 
65 	if (glob_ret == GLOB_NOSPACE)
66 		return;
67 
68 	if (glob_ret == GLOB_ABORTED || glob_ret == GLOB_NOMATCH)
69 		goto leave;
70 
71 	for (i = 0; i < globbuf.gl_pathc; i++) {
72 		V4L2_LOG("PLUGIN: dlopen(%s);\n", globbuf.gl_pathv[i]);
73 
74 		plugin_library = dlopen(globbuf.gl_pathv[i], RTLD_LAZY);
75 		if (!plugin_library)
76 			continue;
77 
78 		dlerror(); /* Clear any existing error */
79 		libv4l2_plugin = (struct libv4l_dev_ops *)
80 			dlsym(plugin_library, "libv4l2_plugin");
81 		error = dlerror();
82 		if (error != NULL)  {
83 			V4L2_LOG_ERR("PLUGIN: dlsym failed: %s\n", error);
84 			dlclose(plugin_library);
85 			continue;
86 		}
87 
88 		if (!libv4l2_plugin->init ||
89 		    !libv4l2_plugin->close ||
90 		    !libv4l2_plugin->ioctl) {
91 			V4L2_LOG("PLUGIN: does not have all mandatory ops\n");
92 			dlclose(plugin_library);
93 			continue;
94 		}
95 
96 		*plugin_priv_ret = libv4l2_plugin->init(fd);
97 		if (!*plugin_priv_ret) {
98 			V4L2_LOG("PLUGIN: plugin open() returned NULL\n");
99 			dlclose(plugin_library);
100 			continue;
101 		}
102 
103 		*plugin_lib_ret = plugin_library;
104 		*dev_ops_ret = libv4l2_plugin;
105 		break;
106 	}
107 
108 leave:
109 	globfree(&globbuf);
110 }
111 
v4l2_plugin_cleanup(void * plugin_lib,void * plugin_priv,const struct libv4l_dev_ops * dev_ops)112 void v4l2_plugin_cleanup(void *plugin_lib, void *plugin_priv,
113 			 const struct libv4l_dev_ops *dev_ops)
114 {
115 	if (plugin_lib) {
116 		dev_ops->close(plugin_priv);
117 		dlclose(plugin_lib);
118 	}
119 }
120