filename | src/drivers/input_lirc.c |
changeset | 1015:ad448bedc48a |
next | 1024:c67f2d61ab97 |
author | nkeynes |
date | Tue Jun 02 23:16:26 2009 +0000 (14 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 |
file | annotate | diff | log | raw |
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +00001.2 +++ b/src/drivers/input_lirc.c Tue Jun 02 23:16:26 2009 +00001.3 @@ -0,0 +1,156 @@1.4 +/**1.5 + * $Id: $1.6 + *1.7 + * LIRC input device support1.8 + *1.9 + * Copyright (c) 2009 wahrhaft1.10 + *1.11 + * This program is free software; you can redistribute it and/or modify1.12 + * it under the terms of the GNU General Public License as published by1.13 + * the Free Software Foundation; either version 2 of the License, or1.14 + * (at your option) any later version.1.15 + *1.16 + * This program is distributed in the hope that it will be useful,1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1.19 + * GNU General Public License for more details.1.20 + */1.21 +1.22 +#ifndef _GNU_SOURCE1.23 +#define _GNU_SOURCE1.24 +#endif1.25 +#include <sys/types.h>1.26 +#include <sys/ioctl.h>1.27 +#include <errno.h>1.28 +#include <stdio.h>1.29 +#include <signal.h>1.30 +#include <string.h>1.31 +#include <stdlib.h>1.32 +#include <unistd.h>1.33 +#include <fcntl.h>1.34 +#include <dirent.h>1.35 +#include <ctype.h>1.36 +1.37 +#include <glib/giochannel.h>1.38 +#include <glib.h>1.39 +1.40 +#include <lirc/lirc_client.h>1.41 +1.42 +#include "lxdream.h"1.43 +#include "display.h"1.44 +#include "maple/maple.h"1.45 +#include "drivers/input_lirc.h"1.46 +1.47 +typedef struct input_lirc {1.48 + struct input_driver driver;1.49 + char name[5];1.50 + int fd;1.51 + GIOChannel *channel;1.52 +} *input_lirc_t;1.53 +1.54 +#define MAX_KEYSYMS 2561.55 +static char *keysyms[MAX_KEYSYMS];1.56 +1.57 +static uint16_t input_lirc_resolve_keysym( input_driver_t dev, const gchar *str );1.58 +static gchar *input_lirc_keysym_for_keycode( input_driver_t dev, uint16_t keycode );1.59 +static gboolean input_lirc_callback( GIOChannel *source, GIOCondition condition, gpointer data );1.60 +1.61 +input_driver_t system_lirc_driver;1.62 +1.63 +void input_lirc_create()1.64 +{1.65 + input_lirc_t system_lirc_driver = g_malloc0(sizeof(struct input_lirc));1.66 + strcpy(system_lirc_driver->name, "LIRC");1.67 + system_lirc_driver->driver.id = system_lirc_driver->name;1.68 + system_lirc_driver->driver.resolve_keysym = input_lirc_resolve_keysym;1.69 + system_lirc_driver->driver.get_keysym_for_keycode = input_lirc_keysym_for_keycode;1.70 + system_lirc_driver->driver.destroy = NULL;1.71 +1.72 + system_lirc_driver->fd = lirc_init("lxdream", 1);1.73 + if (system_lirc_driver->fd == -1) {1.74 + WARN("Could not initialize LIRC. LIRC hotkeys will be disabled.");1.75 + return;1.76 + }1.77 +1.78 + system_lirc_driver->channel = g_io_channel_unix_new(system_lirc_driver->fd);1.79 + g_io_channel_set_flags(system_lirc_driver->channel, G_IO_FLAG_IS_READABLE | G_IO_FLAG_NONBLOCK, NULL);1.80 + g_io_add_watch(system_lirc_driver->channel, G_IO_IN|G_IO_ERR|G_IO_HUP, input_lirc_callback, system_lirc_driver);1.81 + memset(keysyms, 0, MAX_KEYSYMS);1.82 + input_register_device((input_driver_t)system_lirc_driver, MAX_KEYSYMS - 1);1.83 + INFO("LIRC initialized");1.84 +}1.85 +1.86 +void input_lirc_shutdown(void)1.87 +{1.88 + input_lirc_t lirc = (input_lirc_t)system_lirc_driver;1.89 + g_io_channel_shutdown(lirc->channel, FALSE, NULL );1.90 + g_io_channel_unref(lirc->channel);1.91 + lirc_deinit();1.92 + g_free(system_lirc_driver);1.93 +}1.94 +1.95 +static uint16_t input_lirc_resolve_keysym( input_driver_t dev, const gchar *str )1.96 +{1.97 + //LIRC uses keysyms but no keycodes. To generate a keycode, we'll just make them up as we go.1.98 + //As long as we store keysyms instead of keycodes in any config files, this should be fine.1.99 + uint16_t i;1.100 + for (i = 1; i < MAX_KEYSYMS && keysyms[i] != NULL; i++) {1.101 + if (strcasecmp(str, keysyms[i]) == 0) {1.102 + //keycode already exists1.103 + return i;1.104 + }1.105 + }1.106 +1.107 + if (i < MAX_KEYSYMS) {1.108 + //this key is not in the list yet, so make a new keycode for it1.109 + keysyms[i] = g_strdup(str);1.110 + return i;1.111 + } else {1.112 + //if your remote has more than 256 buttons, you may need to increase MAX_KEYSYMS1.113 + ERROR("LIRC has too many keysyms!");1.114 + return 0;1.115 + }1.116 +}1.117 +1.118 +static gchar *input_lirc_keysym_for_keycode( input_driver_t dev, uint16_t keycode )1.119 +{1.120 + //This won't work if you send in keycodes that haven't been fired by the callback1.121 + //or looked up using resolve_keysym yet. This shouldn't be a problem, since these1.122 + //two functions are the only way to get a keycode in the first place.1.123 +1.124 + if (keycode < MAX_KEYSYMS)1.125 + return g_strdup(keysyms[keycode]);1.126 + else1.127 + return NULL;1.128 +}1.129 +1.130 +gboolean input_lirc_callback( GIOChannel *source, GIOCondition condition, gpointer data )1.131 +{1.132 + int ret;1.133 + char *code, *c;1.134 + char keysym[256];1.135 +1.136 + input_lirc_t lirc = (input_lirc_t)data;1.137 +1.138 + if (condition & G_IO_IN)1.139 + {1.140 + //loop through all queued commands1.141 + while ((ret = lirc_nextcode(&code)) == 0 && code != NULL)1.142 + {1.143 + INFO("LIRC code (%s)", code);1.144 + //code contains id, repeat count, and keysym separated by spaces1.145 + gchar **code_split = g_strsplit(code, " ", 4);1.146 +1.147 + //eliminate repeats by only accepting the first instance of a keysym1.148 + if (atoi(code_split[1]) == 0)1.149 + {1.150 + input_event_keydown((input_driver_t)lirc, input_lirc_resolve_keysym((input_driver_t)lirc, code_split[2]), MAX_PRESSURE);1.151 + }1.152 +1.153 + g_strfreev(code_split);1.154 + free(code);1.155 + }1.156 + }1.157 + return TRUE;1.158 +}1.159 +
.