LIRC libraries LinuxInfraredRemoteControl

- Main Page
- Related Pages
- Modules
- Data Structures
- Files
- Examples

- File List
- Globals

drv_admin.c
Go to the documentation of this file.
1
10 #ifdef HAVE_CONFIG_H
11 # include <config.h>
12 #endif
13
14 #include <stdio.h>
15 #include <dirent.h>
16 #include <dlfcn.h>
17
18 #include "lirc/driver.h"
19 #include "lirc/drv_admin.h"
20 #include "lirc/lirc_options.h"
21 #include "lirc_log.h"
22
23 #include "driver.h"
24
25 static const char* const PLUGIN_FILE_EXTENSION = "so";
26
27
29 #define MAX_PLUGINS 256
30
31 extern struct driver drv;
34 typedef struct {
35 char* array[MAX_PLUGINS];
36 int size;
37 } char_array;
38
40 static void* last_plugin = NULL;
41
43 const struct driver drv_null = {
44 .name = "null",
45 .device = "/dev/null",
46 .features = 0,
47 .send_mode = 0,
48 .rec_mode = 0,
49 .code_length = 0,
50 .init_func = NULL,
51 .deinit_func = NULL,
52 .send_func = NULL,
53 .rec_func = NULL,
54 .decode_func = NULL,
55 .readdata = NULL,
56 .drvctl_func = default_drvctl,
57 .open_func = default_open,
58 .close_func = default_close,
59 .api_version = 2,
60 .driver_version = "0.9.2"
61 };
62
63
69 static int ends_with_so(const char* str)
70 {
71 char* dot = strrchr(str, '.');
72
73 return (NULL == dot) ? 0 : strcmp(dot + 1, PLUGIN_FILE_EXTENSION) == 0;
74 }
75
76
78 static int line_cmp(const void* arg1, const void* arg2)
79 {
80 return strcmp(*(const char**)arg1, *(const char**)arg2);
81 }
82
83
85 static struct driver* add_hw_name(struct driver* hw, void* arg)
86 {
87 char_array* a = (char_array*)arg;
88
89 if (a->size >= MAX_PLUGINS) {
90 logprintf(LIRC_ERROR, "Too many plugins(%d)", MAX_PLUGINS);
91 return hw;
92 }
93 a->array[a->size] = strdup(hw->name);
94 a->size += 1;
95 return NULL;
96 }
97
98
99 static struct driver* match_hw_name(struct driver* drv, void* name)
100 {
101 // drv_guest_func. Returns hw if hw->name == name, else NULL.
102 if (drv == (struct driver*)NULL || name == NULL)
103 return (struct driver*)NULL;
104 if (strcasecmp(drv->name, (char*)name) == 0)
105 return drv;
106 return (struct driver*)NULL;
107 }
108
109
110 static struct driver*
111 visit_plugin(const char* path, drv_guest_func func, void* arg)
112 {
113 // Apply func(hw, arg) for all drivers found in plugin on path.
114 struct driver** drivers;
115 struct driver* result = (struct driver*)NULL;
116
117 (void)dlerror();
118 if (last_plugin != NULL)
119 dlclose(last_plugin);
120 last_plugin = dlopen(path, RTLD_NOW);
121 if (last_plugin == NULL) {
122 logprintf(LIRC_ERROR, dlerror());
123 return result;
124 }
125 drivers = (struct driver**)dlsym(last_plugin, "hardwares");
126 if (drivers == (struct driver**)NULL) {
127 logprintf(LIRC_WARNING,
128 "No hardwares entrypoint found in %s", path);
129 } else {
130 for (; *drivers; drivers++) {
131 if ((*drivers)->name == NULL) {
132 logprintf(LIRC_WARNING,
133 "No driver name in %s", path);
134 continue;
135 }
136 result = (*func)(*drivers, arg);
137 if (result != (struct driver*)NULL)
138 break;
139 }
140 }
141 return result;
142 }
143
144
145 /* Apply plugin_guest(path, drv_guest, arg) to all so-files in dir. */
146 static struct driver* for_each_plugin_in_dir(const char* dirpath,
147 plugin_guest_func plugin_guest,
148 drv_guest_func drv_guest,
149 void* arg)
150 {
151 DIR* dir;
152 struct dirent* ent;
153 struct driver* result = (struct driver*)NULL;
154 char path[128];
155 char buff[128];
156
157 dir = opendir(dirpath);
158 if (dir == NULL) {
159 logprintf(LIRC_INFO, "Cannot open plugindir %s", dirpath);
160 return (struct driver*)NULL;
161 }
162 while ((ent = readdir(dir)) != NULL) {
163 if (!ends_with_so(ent->d_name))
164 continue;
165 strncpy(buff, dirpath, sizeof(buff) - 1);
166 if (buff[strlen(buff) - 1] == '/')
167 buff[strlen(buff) - 1] = '\0';
168 snprintf(path, sizeof(path),
169 "%s/%s", buff, ent->d_name);
170 result = plugin_guest(path, drv_guest, arg);
171 if (result != (struct driver*)NULL)
172 break;
173 }
174 closedir(dir);
175 return result;
176 }
177
178
179 static struct driver* for_each_path(plugin_guest_func plg_guest,
180 drv_guest_func drv_guest,
181 void* arg)
182 {
183 const char* pluginpath;
184 char* tmp_path;
185 char* s;
186 struct driver* result = (struct driver*)NULL;
187
188 pluginpath = ciniparser_getstring(lirc_options,
189 "lircd:plugindir",
190 getenv(PLUGINDIR_VAR));
191 if (pluginpath == NULL)
192 pluginpath = PLUGINDIR;
193 if (strchr(pluginpath, ':') == (char*)NULL) {
194 return for_each_plugin_in_dir(pluginpath,
195 plg_guest,
196 drv_guest,
197 arg);
198 }
199 tmp_path = alloca(strlen(pluginpath) + 1);
200 strncpy(tmp_path, pluginpath, strlen(pluginpath) + 1);
201 for (s = strtok(tmp_path, ":"); s != NULL; s = strtok(NULL, ":")) {
202 result = for_each_plugin_in_dir(s,
203 plg_guest,
204 drv_guest,
205 arg);
206 if (result != (struct driver*)NULL)
207 break;
208 }
209 return result;
210 }
211
212
213 struct driver* for_each_driver(drv_guest_func func, void* arg)
214 {
215 return for_each_path(visit_plugin, func, arg);
216 }
217
218
219 void for_each_plugin(plugin_guest_func plugin_guest, void* arg)
220 {
221 for_each_path(plugin_guest, NULL, arg);
222 }
223
224
229 void hw_print_drivers(FILE* file)
230 {
231 char_array names;
232 int i;
233
234 names.size = 0;
235 if (for_each_driver(add_hw_name, (void*)&names) != NULL) {
236 fprintf(stderr, "Too many plugins (%d)\n", MAX_PLUGINS);
237 return;
238 }
239 qsort(names.array, names.size, sizeof(char*), line_cmp);
240 for (i = 0; i < names.size; i += 1) {
241 fprintf(file, "%s\n", names.array[i]);
242 free(names.array[i]);
243 }
244 }
245
246
247 int hw_choose_driver(const char* name)
248 {
249 struct driver* found;
250
251 if (name == NULL) {
252 memcpy(&drv, &drv_null, sizeof(struct driver));
253 return 0;
254 }
255 if (strcasecmp(name, "dev/input") == 0)
256 /* backwards compatibility */
257 name = "devinput";
258 found = for_each_driver(match_hw_name, (void*)name);
259 if (found != (struct driver*)NULL) {
260 memcpy(&drv, found, sizeof(struct driver));
261 return 0;
262 }
263 return -1;
264 }
ciniparser_getstring
const char * ciniparser_getstring(dictionary *d, const char *key, char *def)
Get the string associated to a key.
Definition: ciniparser.c:286
default_close
int default_close(void)
Definition: driver.c:43
plugin_guest_func
struct driver *(* plugin_guest_func)(const char *, drv_guest_func, void *)
Definition: drv_admin.h:41
lirc_log.h
Logging functionality.
driver.h
Interface to the userspace drivers.
MAX_PLUGINS
#define MAX_PLUGINS
Definition: drv_admin.c:29
drv_null
const struct driver drv_null
Definition: drv_admin.c:43
PLUGINDIR
#define PLUGINDIR
Definition: lirc_config.h:80
hw_print_drivers
void hw_print_drivers(FILE *file)
Prints all drivers known to the system to the file given as argument.
Definition: drv_admin.c:229
drv
struct driver drv
Definition: driver.c:20
drv_guest_func
struct driver *(* drv_guest_func)(struct driver *, void *)
Definition: drv_admin.h:32
PLUGINDIR_VAR
#define PLUGINDIR_VAR
Definition: lirc_config.h:101
default_drvctl
int default_drvctl(unsigned int fd, void *arg)
Definition: driver.c:48
driver
Definition: driver.h:83
hw_choose_driver
int hw_choose_driver(const char *name)
Definition: drv_admin.c:247
driver::name
const char * name
Definition: driver.h:175
default_open
int default_open(const char *path)
Definition: driver.c:28
for_each_plugin
void for_each_plugin(plugin_guest_func plugin_guest, void *arg)
Definition: drv_admin.c:219
for_each_driver
struct driver * for_each_driver(drv_guest_func func, void *arg)
Definition: drv_admin.c:213