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 |
nkeynes@1015 | 1 | /** |
nkeynes@1015 | 2 | * $Id: $ |
nkeynes@1015 | 3 | * |
nkeynes@1015 | 4 | * LIRC input device support |
nkeynes@1015 | 5 | * |
nkeynes@1015 | 6 | * Copyright (c) 2009 wahrhaft |
nkeynes@1015 | 7 | * |
nkeynes@1015 | 8 | * This program is free software; you can redistribute it and/or modify |
nkeynes@1015 | 9 | * it under the terms of the GNU General Public License as published by |
nkeynes@1015 | 10 | * the Free Software Foundation; either version 2 of the License, or |
nkeynes@1015 | 11 | * (at your option) any later version. |
nkeynes@1015 | 12 | * |
nkeynes@1015 | 13 | * This program is distributed in the hope that it will be useful, |
nkeynes@1015 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
nkeynes@1015 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
nkeynes@1015 | 16 | * GNU General Public License for more details. |
nkeynes@1015 | 17 | */ |
nkeynes@1015 | 18 | |
nkeynes@1015 | 19 | #ifndef _GNU_SOURCE |
nkeynes@1015 | 20 | #define _GNU_SOURCE |
nkeynes@1015 | 21 | #endif |
nkeynes@1015 | 22 | #include <sys/types.h> |
nkeynes@1015 | 23 | #include <sys/ioctl.h> |
nkeynes@1015 | 24 | #include <errno.h> |
nkeynes@1015 | 25 | #include <stdio.h> |
nkeynes@1015 | 26 | #include <signal.h> |
nkeynes@1015 | 27 | #include <string.h> |
nkeynes@1015 | 28 | #include <stdlib.h> |
nkeynes@1015 | 29 | #include <unistd.h> |
nkeynes@1015 | 30 | #include <fcntl.h> |
nkeynes@1015 | 31 | #include <dirent.h> |
nkeynes@1015 | 32 | #include <ctype.h> |
nkeynes@1015 | 33 | |
nkeynes@1015 | 34 | #include <glib/giochannel.h> |
nkeynes@1015 | 35 | #include <glib.h> |
nkeynes@1015 | 36 | |
nkeynes@1015 | 37 | #include <lirc/lirc_client.h> |
nkeynes@1015 | 38 | |
nkeynes@1015 | 39 | #include "lxdream.h" |
nkeynes@1015 | 40 | #include "display.h" |
nkeynes@1015 | 41 | #include "maple/maple.h" |
nkeynes@1015 | 42 | #include "drivers/input_lirc.h" |
nkeynes@1015 | 43 | |
nkeynes@1015 | 44 | typedef struct input_lirc { |
nkeynes@1015 | 45 | struct input_driver driver; |
nkeynes@1015 | 46 | char name[5]; |
nkeynes@1015 | 47 | int fd; |
nkeynes@1015 | 48 | GIOChannel *channel; |
nkeynes@1015 | 49 | } *input_lirc_t; |
nkeynes@1015 | 50 | |
nkeynes@1015 | 51 | #define MAX_KEYSYMS 256 |
nkeynes@1015 | 52 | static char *keysyms[MAX_KEYSYMS]; |
nkeynes@1015 | 53 | |
nkeynes@1015 | 54 | static uint16_t input_lirc_resolve_keysym( input_driver_t dev, const gchar *str ); |
nkeynes@1015 | 55 | static gchar *input_lirc_keysym_for_keycode( input_driver_t dev, uint16_t keycode ); |
nkeynes@1015 | 56 | static gboolean input_lirc_callback( GIOChannel *source, GIOCondition condition, gpointer data ); |
nkeynes@1015 | 57 | |
nkeynes@1015 | 58 | input_driver_t system_lirc_driver; |
nkeynes@1015 | 59 | |
nkeynes@1015 | 60 | void input_lirc_create() |
nkeynes@1015 | 61 | { |
nkeynes@1015 | 62 | input_lirc_t system_lirc_driver = g_malloc0(sizeof(struct input_lirc)); |
nkeynes@1015 | 63 | strcpy(system_lirc_driver->name, "LIRC"); |
nkeynes@1015 | 64 | system_lirc_driver->driver.id = system_lirc_driver->name; |
nkeynes@1015 | 65 | system_lirc_driver->driver.resolve_keysym = input_lirc_resolve_keysym; |
nkeynes@1015 | 66 | system_lirc_driver->driver.get_keysym_for_keycode = input_lirc_keysym_for_keycode; |
nkeynes@1015 | 67 | system_lirc_driver->driver.destroy = NULL; |
nkeynes@1015 | 68 | |
nkeynes@1015 | 69 | system_lirc_driver->fd = lirc_init("lxdream", 1); |
nkeynes@1015 | 70 | if (system_lirc_driver->fd == -1) { |
nkeynes@1015 | 71 | WARN("Could not initialize LIRC. LIRC hotkeys will be disabled."); |
nkeynes@1015 | 72 | return; |
nkeynes@1015 | 73 | } |
nkeynes@1015 | 74 | |
nkeynes@1015 | 75 | system_lirc_driver->channel = g_io_channel_unix_new(system_lirc_driver->fd); |
nkeynes@1015 | 76 | g_io_channel_set_flags(system_lirc_driver->channel, G_IO_FLAG_IS_READABLE | G_IO_FLAG_NONBLOCK, NULL); |
nkeynes@1015 | 77 | g_io_add_watch(system_lirc_driver->channel, G_IO_IN|G_IO_ERR|G_IO_HUP, input_lirc_callback, system_lirc_driver); |
nkeynes@1015 | 78 | memset(keysyms, 0, MAX_KEYSYMS); |
nkeynes@1015 | 79 | input_register_device((input_driver_t)system_lirc_driver, MAX_KEYSYMS - 1); |
nkeynes@1015 | 80 | INFO("LIRC initialized"); |
nkeynes@1015 | 81 | } |
nkeynes@1015 | 82 | |
nkeynes@1015 | 83 | void input_lirc_shutdown(void) |
nkeynes@1015 | 84 | { |
nkeynes@1015 | 85 | input_lirc_t lirc = (input_lirc_t)system_lirc_driver; |
nkeynes@1015 | 86 | g_io_channel_shutdown(lirc->channel, FALSE, NULL ); |
nkeynes@1015 | 87 | g_io_channel_unref(lirc->channel); |
nkeynes@1015 | 88 | lirc_deinit(); |
nkeynes@1015 | 89 | g_free(system_lirc_driver); |
nkeynes@1015 | 90 | } |
nkeynes@1015 | 91 | |
nkeynes@1015 | 92 | static uint16_t input_lirc_resolve_keysym( input_driver_t dev, const gchar *str ) |
nkeynes@1015 | 93 | { |
nkeynes@1015 | 94 | //LIRC uses keysyms but no keycodes. To generate a keycode, we'll just make them up as we go. |
nkeynes@1015 | 95 | //As long as we store keysyms instead of keycodes in any config files, this should be fine. |
nkeynes@1015 | 96 | uint16_t i; |
nkeynes@1015 | 97 | for (i = 1; i < MAX_KEYSYMS && keysyms[i] != NULL; i++) { |
nkeynes@1015 | 98 | if (strcasecmp(str, keysyms[i]) == 0) { |
nkeynes@1015 | 99 | //keycode already exists |
nkeynes@1015 | 100 | return i; |
nkeynes@1015 | 101 | } |
nkeynes@1015 | 102 | } |
nkeynes@1015 | 103 | |
nkeynes@1015 | 104 | if (i < MAX_KEYSYMS) { |
nkeynes@1015 | 105 | //this key is not in the list yet, so make a new keycode for it |
nkeynes@1015 | 106 | keysyms[i] = g_strdup(str); |
nkeynes@1015 | 107 | return i; |
nkeynes@1015 | 108 | } else { |
nkeynes@1015 | 109 | //if your remote has more than 256 buttons, you may need to increase MAX_KEYSYMS |
nkeynes@1015 | 110 | ERROR("LIRC has too many keysyms!"); |
nkeynes@1015 | 111 | return 0; |
nkeynes@1015 | 112 | } |
nkeynes@1015 | 113 | } |
nkeynes@1015 | 114 | |
nkeynes@1015 | 115 | static gchar *input_lirc_keysym_for_keycode( input_driver_t dev, uint16_t keycode ) |
nkeynes@1015 | 116 | { |
nkeynes@1015 | 117 | //This won't work if you send in keycodes that haven't been fired by the callback |
nkeynes@1015 | 118 | //or looked up using resolve_keysym yet. This shouldn't be a problem, since these |
nkeynes@1015 | 119 | //two functions are the only way to get a keycode in the first place. |
nkeynes@1015 | 120 | |
nkeynes@1015 | 121 | if (keycode < MAX_KEYSYMS) |
nkeynes@1015 | 122 | return g_strdup(keysyms[keycode]); |
nkeynes@1015 | 123 | else |
nkeynes@1015 | 124 | return NULL; |
nkeynes@1015 | 125 | } |
nkeynes@1015 | 126 | |
nkeynes@1015 | 127 | gboolean input_lirc_callback( GIOChannel *source, GIOCondition condition, gpointer data ) |
nkeynes@1015 | 128 | { |
nkeynes@1015 | 129 | int ret; |
nkeynes@1015 | 130 | char *code, *c; |
nkeynes@1015 | 131 | char keysym[256]; |
nkeynes@1015 | 132 | |
nkeynes@1015 | 133 | input_lirc_t lirc = (input_lirc_t)data; |
nkeynes@1015 | 134 | |
nkeynes@1015 | 135 | if (condition & G_IO_IN) |
nkeynes@1015 | 136 | { |
nkeynes@1015 | 137 | //loop through all queued commands |
nkeynes@1015 | 138 | while ((ret = lirc_nextcode(&code)) == 0 && code != NULL) |
nkeynes@1015 | 139 | { |
nkeynes@1015 | 140 | INFO("LIRC code (%s)", code); |
nkeynes@1015 | 141 | //code contains id, repeat count, and keysym separated by spaces |
nkeynes@1015 | 142 | gchar **code_split = g_strsplit(code, " ", 4); |
nkeynes@1015 | 143 | |
nkeynes@1015 | 144 | //eliminate repeats by only accepting the first instance of a keysym |
nkeynes@1015 | 145 | if (atoi(code_split[1]) == 0) |
nkeynes@1015 | 146 | { |
nkeynes@1015 | 147 | input_event_keydown((input_driver_t)lirc, input_lirc_resolve_keysym((input_driver_t)lirc, code_split[2]), MAX_PRESSURE); |
nkeynes@1015 | 148 | } |
nkeynes@1015 | 149 | |
nkeynes@1015 | 150 | g_strfreev(code_split); |
nkeynes@1015 | 151 | free(code); |
nkeynes@1015 | 152 | } |
nkeynes@1015 | 153 | } |
nkeynes@1015 | 154 | return TRUE; |
nkeynes@1015 | 155 | } |
nkeynes@1015 | 156 |
.