filename | src/drivers/input_lirc.c |
changeset | 1015:ad448bedc48a |
next | 1024:c67f2d61ab97 |
author | nkeynes |
date | Tue Jun 02 23:16:26 2009 +0000 (13 years ago) |
permissions | -rw-r--r-- |
last change | "MythTV" patch from Wahrhaft, thanks!: * Add support for LIRC input devices * Add hotkey input support * Add command-line option for immediate fullscreen |
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 #ifndef _GNU_SOURCE
20 #define _GNU_SOURCE
21 #endif
22 #include <sys/types.h>
23 #include <sys/ioctl.h>
24 #include <errno.h>
25 #include <stdio.h>
26 #include <signal.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <dirent.h>
32 #include <ctype.h>
34 #include <glib/giochannel.h>
35 #include <glib.h>
37 #include <lirc/lirc_client.h>
39 #include "lxdream.h"
40 #include "display.h"
41 #include "maple/maple.h"
42 #include "drivers/input_lirc.h"
44 typedef struct input_lirc {
45 struct input_driver driver;
46 char name[5];
47 int fd;
48 GIOChannel *channel;
49 } *input_lirc_t;
51 #define MAX_KEYSYMS 256
52 static char *keysyms[MAX_KEYSYMS];
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 gboolean input_lirc_callback( GIOChannel *source, GIOCondition condition, gpointer data );
58 input_driver_t system_lirc_driver;
60 void input_lirc_create()
61 {
62 input_lirc_t system_lirc_driver = g_malloc0(sizeof(struct input_lirc));
63 strcpy(system_lirc_driver->name, "LIRC");
64 system_lirc_driver->driver.id = system_lirc_driver->name;
65 system_lirc_driver->driver.resolve_keysym = input_lirc_resolve_keysym;
66 system_lirc_driver->driver.get_keysym_for_keycode = input_lirc_keysym_for_keycode;
67 system_lirc_driver->driver.destroy = NULL;
69 system_lirc_driver->fd = lirc_init("lxdream", 1);
70 if (system_lirc_driver->fd == -1) {
71 WARN("Could not initialize LIRC. LIRC hotkeys will be disabled.");
72 return;
73 }
75 system_lirc_driver->channel = g_io_channel_unix_new(system_lirc_driver->fd);
76 g_io_channel_set_flags(system_lirc_driver->channel, G_IO_FLAG_IS_READABLE | G_IO_FLAG_NONBLOCK, NULL);
77 g_io_add_watch(system_lirc_driver->channel, G_IO_IN|G_IO_ERR|G_IO_HUP, input_lirc_callback, system_lirc_driver);
78 memset(keysyms, 0, MAX_KEYSYMS);
79 input_register_device((input_driver_t)system_lirc_driver, MAX_KEYSYMS - 1);
80 INFO("LIRC initialized");
81 }
83 void input_lirc_shutdown(void)
84 {
85 input_lirc_t lirc = (input_lirc_t)system_lirc_driver;
86 g_io_channel_shutdown(lirc->channel, FALSE, NULL );
87 g_io_channel_unref(lirc->channel);
88 lirc_deinit();
89 g_free(system_lirc_driver);
90 }
92 static uint16_t input_lirc_resolve_keysym( input_driver_t dev, const gchar *str )
93 {
94 //LIRC uses keysyms but no keycodes. To generate a keycode, we'll just make them up as we go.
95 //As long as we store keysyms instead of keycodes in any config files, this should be fine.
96 uint16_t i;
97 for (i = 1; i < MAX_KEYSYMS && keysyms[i] != NULL; i++) {
98 if (strcasecmp(str, keysyms[i]) == 0) {
99 //keycode already exists
100 return i;
101 }
102 }
104 if (i < MAX_KEYSYMS) {
105 //this key is not in the list yet, so make a new keycode for it
106 keysyms[i] = g_strdup(str);
107 return i;
108 } else {
109 //if your remote has more than 256 buttons, you may need to increase MAX_KEYSYMS
110 ERROR("LIRC has too many keysyms!");
111 return 0;
112 }
113 }
115 static gchar *input_lirc_keysym_for_keycode( input_driver_t dev, uint16_t keycode )
116 {
117 //This won't work if you send in keycodes that haven't been fired by the callback
118 //or looked up using resolve_keysym yet. This shouldn't be a problem, since these
119 //two functions are the only way to get a keycode in the first place.
121 if (keycode < MAX_KEYSYMS)
122 return g_strdup(keysyms[keycode]);
123 else
124 return NULL;
125 }
127 gboolean input_lirc_callback( GIOChannel *source, GIOCondition condition, gpointer data )
128 {
129 int ret;
130 char *code, *c;
131 char keysym[256];
133 input_lirc_t lirc = (input_lirc_t)data;
135 if (condition & G_IO_IN)
136 {
137 //loop through all queued commands
138 while ((ret = lirc_nextcode(&code)) == 0 && code != NULL)
139 {
140 INFO("LIRC code (%s)", code);
141 //code contains id, repeat count, and keysym separated by spaces
142 gchar **code_split = g_strsplit(code, " ", 4);
144 //eliminate repeats by only accepting the first instance of a keysym
145 if (atoi(code_split[1]) == 0)
146 {
147 input_event_keydown((input_driver_t)lirc, input_lirc_resolve_keysym((input_driver_t)lirc, code_split[2]), MAX_PRESSURE);
148 }
150 g_strfreev(code_split);
151 free(code);
152 }
153 }
154 return TRUE;
155 }
.