filename | src/drivers/input_lirc.c |
changeset | 1075:1a21750d300c |
prev | 1050:7d88277590d9 |
next | 1296:30ecee61f811 |
author | nkeynes |
date | Fri Jul 31 13:45:32 2009 +1000 (14 years ago) |
permissions | -rw-r--r-- |
last change | Remove or change the level of a bunch of INFO messages that shouldn't really be INFO level |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
3 *
4 * LIRC input device support
5 *
6 * Copyright (c) 2009 wahrhaft
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
19 #include <sys/types.h>
20 #include <sys/ioctl.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <signal.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <dirent.h>
29 #include <ctype.h>
31 #include <glib/giochannel.h>
32 #include <glib.h>
34 #include <lirc/lirc_client.h>
36 #include "lxdream.h"
37 #include "plugin.h"
38 #include "display.h"
39 #include "maple/maple.h"
41 typedef struct input_lirc {
42 struct input_driver driver;
43 char name[5];
44 int fd;
45 GIOChannel *channel;
46 } *input_lirc_t;
48 #define MAX_KEYSYMS 65536
49 static GData *keysyms;
50 static uint16_t last_keycode;
51 static GQuark keysym_by_keycode_result;
54 static uint16_t input_lirc_resolve_keysym( input_driver_t dev, const gchar *str );
55 static gchar *input_lirc_keysym_for_keycode( input_driver_t dev, uint16_t keycode );
56 static void get_keysym_by_keycode(GQuark key_id, gpointer data, gpointer user_data);
57 static gboolean input_lirc_callback( GIOChannel *source, GIOCondition condition, gpointer data );
59 input_driver_t system_lirc_driver;
61 static gboolean input_lirc_init()
62 {
63 input_lirc_t system_lirc_driver = g_malloc0(sizeof(struct input_lirc));
64 strcpy(system_lirc_driver->name, "LIRC");
65 system_lirc_driver->driver.id = system_lirc_driver->name;
66 system_lirc_driver->driver.resolve_keysym = input_lirc_resolve_keysym;
67 system_lirc_driver->driver.get_keysym_for_keycode = input_lirc_keysym_for_keycode;
68 system_lirc_driver->driver.destroy = NULL;
70 system_lirc_driver->fd = lirc_init("lxdream", 1);
71 if (system_lirc_driver->fd == -1) {
72 WARN("Could not initialize LIRC. LIRC hotkeys will be disabled.");
73 return FALSE;
74 }
76 system_lirc_driver->channel = g_io_channel_unix_new(system_lirc_driver->fd);
77 g_io_channel_set_flags(system_lirc_driver->channel, G_IO_FLAG_IS_READABLE | G_IO_FLAG_NONBLOCK, NULL);
78 g_io_add_watch(system_lirc_driver->channel, G_IO_IN|G_IO_ERR|G_IO_HUP, input_lirc_callback, system_lirc_driver);
79 g_datalist_init(&keysyms);
80 input_register_device((input_driver_t)system_lirc_driver, MAX_KEYSYMS - 1);
81 return TRUE;
82 }
84 void input_lirc_shutdown(void)
85 {
86 input_lirc_t lirc = (input_lirc_t)system_lirc_driver;
87 g_io_channel_shutdown(lirc->channel, FALSE, NULL );
88 g_io_channel_unref(lirc->channel);
89 lirc_deinit();
90 g_free(system_lirc_driver);
91 }
93 static uint16_t input_lirc_resolve_keysym( input_driver_t dev, const gchar *str )
94 {
95 //LIRC uses keysyms but no keycodes. To generate a keycode, we'll just make them up as we go.
96 //As long as we store keysyms instead of keycodes in any config files, this should be fine.
98 uint16_t keycode;
99 keycode = (uint16_t)GPOINTER_TO_INT(g_datalist_get_data(&keysyms, str));
101 if (keycode == 0) {
102 //this key is not in the list yet, so make a new keycode for it
103 g_datalist_set_data(&keysyms, str, GINT_TO_POINTER(++last_keycode));
104 return last_keycode;
105 } else {
106 return keycode;
107 }
109 }
111 static gchar *input_lirc_keysym_for_keycode( input_driver_t dev, uint16_t keycode )
112 {
113 //This won't work if you send in keycodes that haven't been fired by the callback
114 //or looked up using resolve_keysym yet. This shouldn't be a problem, since these
115 //two functions are the only way to get a keycode in the first place.
117 if (keycode <= last_keycode) {
118 //reverse lookup
119 keysym_by_keycode_result = 0;
120 g_datalist_foreach(&keysyms, get_keysym_by_keycode, GINT_TO_POINTER(keycode));
121 return g_strdup(g_quark_to_string(keysym_by_keycode_result));
122 } else {
123 return NULL;
124 }
125 }
127 static void get_keysym_by_keycode(GQuark key_id, gpointer data, gpointer user_data)
128 {
129 if (data == user_data)
130 keysym_by_keycode_result = key_id;
131 }
133 static gboolean input_lirc_callback( GIOChannel *source, GIOCondition condition, gpointer data )
134 {
135 int ret;
136 char *code, *c;
138 input_lirc_t lirc = (input_lirc_t)data;
140 if (condition & G_IO_IN)
141 {
142 //loop through all queued commands
143 while ((ret = lirc_nextcode(&code)) == 0 && code != NULL)
144 {
145 //code contains id, repeat count, and keysym separated by spaces
146 gchar **code_split = g_strsplit(code, " ", 4);
148 //eliminate repeats by only accepting the first instance of a keysym
149 if (atoi(code_split[1]) == 0)
150 {
151 input_event_keydown((input_driver_t)lirc, input_lirc_resolve_keysym((input_driver_t)lirc, code_split[2]), MAX_PRESSURE);
152 }
154 g_strfreev(code_split);
155 free(code);
156 }
157 }
158 return TRUE;
159 }
161 DEFINE_PLUGIN( PLUGIN_INPUT_DRIVER, "lirc", input_lirc_init );
.