22 #ifdef GWINSZ_IN_SYS_IOCTL
23 # include <sys/ioctl.h>
27 #include "lirc/driver.h"
28 #include "lirc/drv_admin.h"
29 #include "lirc/lirc_options.h"
36 static const char*
const PLUGIN_FILE_EXTENSION =
"so";
40 #define MAX_PLUGINS 256
51 static void* last_plugin = NULL;
56 .device =
"/dev/null",
71 .driver_version =
"0.9.2"
80 static int ends_with_so(
const char* str)
82 char* dot = strrchr(str,
'.');
84 return (NULL == dot) ? 0 : strcmp(dot + 1, PLUGIN_FILE_EXTENSION) == 0;
89 static int line_cmp(
const void* arg1,
const void* arg2)
91 return strcmp(*(
const char**)arg1, *(
const char**)arg2);
96 static struct driver* add_hw_name(
struct driver* hw,
void* arg)
98 char_array* a = (char_array*)arg;
104 a->array[a->size] = strdup(hw->
name);
113 if (drv == (
struct driver*)NULL || name == NULL)
114 return (
struct driver*)NULL;
115 if (strcasecmp(drv->
name, (
char*)name) == 0)
117 return (
struct driver*)NULL;
129 if (last_plugin != NULL)
130 dlclose(last_plugin);
131 last_plugin = dlopen(path, RTLD_NOW);
132 if (last_plugin == NULL) {
136 drivers = (
struct driver**)dlsym(last_plugin,
"hardwares");
137 if (drivers == (
struct driver**)NULL) {
138 log_warn(
"No hardwares entrypoint found in %s", path);
140 for (; *drivers; drivers++) {
141 if ((*drivers)->name == NULL) {
142 log_warn(
"No driver name in %s", path);
145 result = (*func)(*drivers, arg);
146 if (result != (
struct driver*)NULL)
155 static struct driver* for_each_plugin_in_dir(
const char* dirpath,
166 dir = opendir(dirpath);
168 log_info(
"Cannot open plugindir %s", dirpath);
169 return (
struct driver*)NULL;
171 while ((ent = readdir(dir)) != NULL) {
172 if (!ends_with_so(ent->d_name))
174 strncpy(buff, dirpath,
sizeof(buff) - 1);
175 if (buff[strlen(buff) - 1] ==
'/')
176 buff[strlen(buff) - 1] =
'\0';
177 snprintf(path,
sizeof(path),
178 "%s/%s", buff, ent->d_name);
179 result = plugin_guest(path, drv_guest, arg);
180 if (result != (
struct driver*)NULL)
191 const char* pluginpath_arg)
193 const char* pluginpath;
198 if (pluginpath_arg == NULL) {
202 if (pluginpath == NULL)
205 pluginpath = pluginpath_arg;
207 if (strchr(pluginpath,
':') == (
char*)NULL) {
208 return for_each_plugin_in_dir(pluginpath,
213 tmp_path = alloca(strlen(pluginpath) + 1);
214 strncpy(tmp_path, pluginpath, strlen(pluginpath) + 1);
215 for (s = strtok(tmp_path,
":"); s != NULL; s = strtok(NULL,
":")) {
216 result = for_each_plugin_in_dir(s,
220 if (result != (
struct driver*)NULL)
229 const char* pluginpath)
231 return for_each_path(visit_plugin, func, arg, pluginpath);
237 const char* pluginpath)
239 for_each_path(plugin_guest, NULL, arg, pluginpath);
244 static void get_columns(FILE* f, char_array names,
int* cols,
int* width)
247 struct winsize winsize;
252 if (!isatty(fileno(f)))
254 if (ioctl(fileno(f), TIOCGWINSZ, &winsize) != 0)
256 for (i = 0; i < names.size; i += 1) {
257 if (strlen(names.array[i]) > maxlen)
258 maxlen = strlen(names.array[i]);
261 *cols = winsize.ws_col / maxlen;
280 fprintf(stderr,
"Too many plugins (%d)\n",
MAX_PLUGINS);
283 qsort(names.array, names.size,
sizeof(
char*), line_cmp);
284 get_columns(file, names, &cols, &width);
285 snprintf(format,
sizeof(format),
"%%-%ds", width);
286 for (i = 0; i < names.size; i += 1) {
287 fprintf(file, format, names.array[i]);
288 if ((i + 1) % cols == 0)
290 free(names.array[i]);
292 if ((i + 1) % cols != 0)
302 memcpy(&drv, &drv_null,
sizeof(
struct driver));
306 if (strcasecmp(name,
"dev/input") == 0)
310 if (found != (
struct driver*)NULL) {
311 memcpy(&drv, found,
sizeof(
struct driver));
const char * ciniparser_getstring(dictionary *d, const char *key, char *def)
Get the string associated to a key.
int default_close(void)
For now, a placeholder.
int fd
Set by the driver after init().
struct driver *(* plugin_guest_func)(const char *, drv_guest_func, void *)
Argument to for_each_plugin.
Interface to the userspace drivers.
#define log_warn(fmt,...)
Log a warning message.
#define MAX_PLUGINS
Max number if plugins handled.
const struct driver drv_null
Default driver, a placeholder.
logchannel_t
Log channels used to filter messages.
#define PLUGINDIR
Default directory for plugins/drivers.
#define log_error(fmt,...)
Log an error message.
void for_each_plugin(plugin_guest_func plugin_guest, void *arg, const char *pluginpath)
Apply func to all plugins (i.
void hw_print_drivers(FILE *file)
Prints all drivers known to the system to the file given as argument.
struct driver drv
Access to otherwise private drv.
struct driver *(* drv_guest_func)(struct driver *, void *)
Argument to for_each_driver().
#define PLUGINDIR_VAR
Environment variable holding defaults for PLUGINDIR.
int default_drvctl(unsigned int fd, void *arg)
Return DRV_ERR_NOTIMPLEMENTED.
struct driver * for_each_driver(drv_guest_func func, void *arg, const char *pluginpath)
Apply func to all existing drivers.
The data the driver exports i.
int hw_choose_driver(const char *name)
Search for driver with given name, update global drv with driver data if found.
const char * name
Driver name, as listed by -H help and used as argument to i –driver.
int default_open(const char *path)
Stores path in drv.device if non-null.
#define log_info(fmt,...)
Log an info message.