src/core/linux/SDL_evdev.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 24 Jun 2015 17:55:38 -0700
changeset 9780 7f9b74280df6
parent 9779 49b5a975a238
child 9998 f67cf37e9cd4
permissions -rw-r--r--
Fixed whitespace in SDL_evdev.c
gabomdq@7753
     1
/*
gabomdq@7753
     2
  Simple DirectMedia Layer
slouken@9619
     3
  Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
gabomdq@7753
     4
gabomdq@7753
     5
  This software is provided 'as-is', without any express or implied
gabomdq@7753
     6
  warranty.  In no event will the authors be held liable for any damages
gabomdq@7753
     7
  arising from the use of this software.
gabomdq@7753
     8
gabomdq@7753
     9
  Permission is granted to anyone to use this software for any purpose,
gabomdq@7753
    10
  including commercial applications, and to alter it and redistribute it
gabomdq@7753
    11
  freely, subject to the following restrictions:
gabomdq@7753
    12
gabomdq@7753
    13
  1. The origin of this software must not be misrepresented; you must not
gabomdq@7753
    14
     claim that you wrote the original software. If you use this software
gabomdq@7753
    15
     in a product, an acknowledgment in the product documentation would be
gabomdq@7753
    16
     appreciated but is not required.
gabomdq@7753
    17
  2. Altered source versions must be plainly marked as such, and must not be
gabomdq@7753
    18
     misrepresented as being the original software.
gabomdq@7753
    19
  3. This notice may not be removed or altered from any source distribution.
gabomdq@7753
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
gabomdq@7753
    22
gabomdq@7753
    23
#ifdef SDL_INPUT_LINUXEV
gabomdq@7753
    24
gabomdq@7753
    25
/* This is based on the linux joystick driver */
gabomdq@7753
    26
/* References: https://www.kernel.org/doc/Documentation/input/input.txt 
gabomdq@7753
    27
 *             https://www.kernel.org/doc/Documentation/input/event-codes.txt
gabomdq@7753
    28
 *             /usr/include/linux/input.h
gabomdq@7753
    29
 *             The evtest application is also useful to debug the protocol
gabomdq@7753
    30
 */
gabomdq@7753
    31
gabomdq@7753
    32
gabomdq@7753
    33
#include "SDL_evdev.h"
gabomdq@7753
    34
#define _THIS SDL_EVDEV_PrivateData *_this
gabomdq@7753
    35
static _THIS = NULL;
gabomdq@7753
    36
gabomdq@7753
    37
#include <sys/stat.h>
gabomdq@7753
    38
#include <unistd.h>
gabomdq@7753
    39
#include <fcntl.h>
gabomdq@7753
    40
#include <sys/ioctl.h>
gabomdq@7753
    41
#include <limits.h>             /* For the definition of PATH_MAX */
gabomdq@7778
    42
#include <linux/input.h>
gabomdq@7778
    43
#ifdef SDL_INPUT_LINUXKD
gabomdq@7778
    44
#include <linux/kd.h>
gabomdq@7778
    45
#include <linux/keyboard.h>
gabomdq@7778
    46
#endif
gabomdq@7753
    47
gabomdq@7809
    48
gabomdq@7809
    49
/* We need this to prevent keystrokes from appear in the console */
gabomdq@7809
    50
#ifndef KDSKBMUTE
gabomdq@7809
    51
#define KDSKBMUTE 0x4B51
gabomdq@7809
    52
#endif
gabomdq@7809
    53
#ifndef KDSKBMODE
gabomdq@7809
    54
#define KDSKBMODE 0x4B45
gabomdq@7809
    55
#endif
gabomdq@7809
    56
#ifndef K_OFF
gabomdq@7809
    57
#define K_OFF 0x04
gabomdq@7809
    58
#endif
gabomdq@7809
    59
gabomdq@7753
    60
#include "SDL.h"
gabomdq@7753
    61
#include "SDL_assert.h"
gabomdq@7753
    62
#include "SDL_endian.h"
gabomdq@7753
    63
#include "../../core/linux/SDL_udev.h"
gabomdq@7753
    64
#include "SDL_scancode.h"
gabomdq@7753
    65
#include "../../events/SDL_events_c.h"
gabomdq@7753
    66
gabomdq@7753
    67
/* This isn't defined in older Linux kernel headers */
gabomdq@7753
    68
#ifndef SYN_DROPPED
gabomdq@7753
    69
#define SYN_DROPPED 3
gabomdq@7753
    70
#endif
gabomdq@7753
    71
gabomdq@7755
    72
static SDL_Scancode SDL_EVDEV_translate_keycode(int keycode);
gabomdq@7755
    73
static void SDL_EVDEV_sync_device(SDL_evdevlist_item *item);
gabomdq@7767
    74
static int SDL_EVDEV_device_removed(const char *devpath);
gabomdq@7753
    75
gabomdq@7755
    76
#if SDL_USE_LIBUDEV
slouken@7788
    77
static int SDL_EVDEV_device_added(const char *devpath);
slouken@7788
    78
void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
gabomdq@7755
    79
#endif /* SDL_USE_LIBUDEV */
gabomdq@7753
    80
gabomdq@7753
    81
static SDL_Scancode EVDEV_Keycodes[] = {
gabomdq@7753
    82
    SDL_SCANCODE_UNKNOWN,       /*  KEY_RESERVED        0 */
gabomdq@7753
    83
    SDL_SCANCODE_ESCAPE,        /*  KEY_ESC         1 */
gabomdq@7753
    84
    SDL_SCANCODE_1,             /*  KEY_1           2 */
gabomdq@7753
    85
    SDL_SCANCODE_2,             /*  KEY_2           3 */
gabomdq@7753
    86
    SDL_SCANCODE_3,             /*  KEY_3           4 */
gabomdq@7753
    87
    SDL_SCANCODE_4,             /*  KEY_4           5 */
gabomdq@7753
    88
    SDL_SCANCODE_5,             /*  KEY_5           6 */
gabomdq@7753
    89
    SDL_SCANCODE_6,             /*  KEY_6           7 */
gabomdq@7753
    90
    SDL_SCANCODE_7,             /*  KEY_7           8 */
gabomdq@7753
    91
    SDL_SCANCODE_8,             /*  KEY_8           9 */
gabomdq@7753
    92
    SDL_SCANCODE_9,             /*  KEY_9           10 */
gabomdq@7753
    93
    SDL_SCANCODE_0,             /*  KEY_0           11 */
gabomdq@7753
    94
    SDL_SCANCODE_MINUS,         /*  KEY_MINUS       12 */
gabomdq@7753
    95
    SDL_SCANCODE_EQUALS,        /*  KEY_EQUAL       13 */
gabomdq@7753
    96
    SDL_SCANCODE_BACKSPACE,     /*  KEY_BACKSPACE       14 */
gabomdq@7753
    97
    SDL_SCANCODE_TAB,           /*  KEY_TAB         15 */
gabomdq@7753
    98
    SDL_SCANCODE_Q,             /*  KEY_Q           16 */
gabomdq@7753
    99
    SDL_SCANCODE_W,             /*  KEY_W           17 */
gabomdq@7753
   100
    SDL_SCANCODE_E,             /*  KEY_E           18 */
gabomdq@7753
   101
    SDL_SCANCODE_R,             /*  KEY_R           19 */
gabomdq@7753
   102
    SDL_SCANCODE_T,             /*  KEY_T           20 */
gabomdq@7753
   103
    SDL_SCANCODE_Y,             /*  KEY_Y           21 */
gabomdq@7753
   104
    SDL_SCANCODE_U,             /*  KEY_U           22 */
gabomdq@7753
   105
    SDL_SCANCODE_I,             /*  KEY_I           23 */
gabomdq@7753
   106
    SDL_SCANCODE_O,             /*  KEY_O           24 */
gabomdq@7753
   107
    SDL_SCANCODE_P,             /*  KEY_P           25 */
gabomdq@7753
   108
    SDL_SCANCODE_LEFTBRACKET,   /*  KEY_LEFTBRACE       26 */
gabomdq@7753
   109
    SDL_SCANCODE_RIGHTBRACKET,  /*  KEY_RIGHTBRACE      27 */
gabomdq@7753
   110
    SDL_SCANCODE_RETURN,        /*  KEY_ENTER       28 */
gabomdq@7753
   111
    SDL_SCANCODE_LCTRL,         /*  KEY_LEFTCTRL        29 */
gabomdq@7753
   112
    SDL_SCANCODE_A,             /*  KEY_A           30 */
gabomdq@7753
   113
    SDL_SCANCODE_S,             /*  KEY_S           31 */
gabomdq@7753
   114
    SDL_SCANCODE_D,             /*  KEY_D           32 */
gabomdq@7753
   115
    SDL_SCANCODE_F,             /*  KEY_F           33 */
gabomdq@7753
   116
    SDL_SCANCODE_G,             /*  KEY_G           34 */
gabomdq@7753
   117
    SDL_SCANCODE_H,             /*  KEY_H           35 */
gabomdq@7753
   118
    SDL_SCANCODE_J,             /*  KEY_J           36 */
gabomdq@7753
   119
    SDL_SCANCODE_K,             /*  KEY_K           37 */
gabomdq@7753
   120
    SDL_SCANCODE_L,             /*  KEY_L           38 */
gabomdq@7753
   121
    SDL_SCANCODE_SEMICOLON,     /*  KEY_SEMICOLON       39 */
gabomdq@7753
   122
    SDL_SCANCODE_APOSTROPHE,    /*  KEY_APOSTROPHE      40 */
gabomdq@7753
   123
    SDL_SCANCODE_GRAVE,         /*  KEY_GRAVE       41 */
gabomdq@7753
   124
    SDL_SCANCODE_LSHIFT,        /*  KEY_LEFTSHIFT       42 */
gabomdq@7753
   125
    SDL_SCANCODE_BACKSLASH,     /*  KEY_BACKSLASH       43 */
gabomdq@7753
   126
    SDL_SCANCODE_Z,             /*  KEY_Z           44 */
gabomdq@7753
   127
    SDL_SCANCODE_X,             /*  KEY_X           45 */
gabomdq@7753
   128
    SDL_SCANCODE_C,             /*  KEY_C           46 */
gabomdq@7753
   129
    SDL_SCANCODE_V,             /*  KEY_V           47 */
gabomdq@7753
   130
    SDL_SCANCODE_B,             /*  KEY_B           48 */
gabomdq@7753
   131
    SDL_SCANCODE_N,             /*  KEY_N           49 */
gabomdq@7753
   132
    SDL_SCANCODE_M,             /*  KEY_M           50 */
gabomdq@7753
   133
    SDL_SCANCODE_COMMA,         /*  KEY_COMMA       51 */
gabomdq@7753
   134
    SDL_SCANCODE_PERIOD,        /*  KEY_DOT         52 */
gabomdq@7753
   135
    SDL_SCANCODE_SLASH,         /*  KEY_SLASH       53 */
gabomdq@7753
   136
    SDL_SCANCODE_RSHIFT,        /*  KEY_RIGHTSHIFT      54 */
gabomdq@7753
   137
    SDL_SCANCODE_KP_MULTIPLY,   /*  KEY_KPASTERISK      55 */
gabomdq@7753
   138
    SDL_SCANCODE_LALT,          /*  KEY_LEFTALT     56 */
gabomdq@7753
   139
    SDL_SCANCODE_SPACE,         /*  KEY_SPACE       57 */
gabomdq@7753
   140
    SDL_SCANCODE_CAPSLOCK,      /*  KEY_CAPSLOCK        58 */
gabomdq@7753
   141
    SDL_SCANCODE_F1,            /*  KEY_F1          59 */
gabomdq@7753
   142
    SDL_SCANCODE_F2,            /*  KEY_F2          60 */
gabomdq@7753
   143
    SDL_SCANCODE_F3,            /*  KEY_F3          61 */
gabomdq@7753
   144
    SDL_SCANCODE_F4,            /*  KEY_F4          62 */
gabomdq@7753
   145
    SDL_SCANCODE_F5,            /*  KEY_F5          63 */
gabomdq@7753
   146
    SDL_SCANCODE_F6,            /*  KEY_F6          64 */
gabomdq@7753
   147
    SDL_SCANCODE_F7,            /*  KEY_F7          65 */
gabomdq@7753
   148
    SDL_SCANCODE_F8,            /*  KEY_F8          66 */
gabomdq@7753
   149
    SDL_SCANCODE_F9,            /*  KEY_F9          67 */
gabomdq@7753
   150
    SDL_SCANCODE_F10,           /*  KEY_F10         68 */
gabomdq@7753
   151
    SDL_SCANCODE_NUMLOCKCLEAR,  /*  KEY_NUMLOCK     69 */
gabomdq@7753
   152
    SDL_SCANCODE_SCROLLLOCK,    /*  KEY_SCROLLLOCK      70 */
gabomdq@7753
   153
    SDL_SCANCODE_KP_7,          /*  KEY_KP7         71 */
gabomdq@7753
   154
    SDL_SCANCODE_KP_8,          /*  KEY_KP8         72 */
gabomdq@7753
   155
    SDL_SCANCODE_KP_9,          /*  KEY_KP9         73 */
gabomdq@7753
   156
    SDL_SCANCODE_KP_MINUS,      /*  KEY_KPMINUS     74 */
gabomdq@7753
   157
    SDL_SCANCODE_KP_4,          /*  KEY_KP4         75 */
gabomdq@7753
   158
    SDL_SCANCODE_KP_5,          /*  KEY_KP5         76 */
gabomdq@7753
   159
    SDL_SCANCODE_KP_6,          /*  KEY_KP6         77 */
gabomdq@7753
   160
    SDL_SCANCODE_KP_PLUS,       /*  KEY_KPPLUS      78 */
gabomdq@7753
   161
    SDL_SCANCODE_KP_1,          /*  KEY_KP1         79 */
gabomdq@7753
   162
    SDL_SCANCODE_KP_2,          /*  KEY_KP2         80 */
gabomdq@7753
   163
    SDL_SCANCODE_KP_3,          /*  KEY_KP3         81 */
gabomdq@7753
   164
    SDL_SCANCODE_KP_0,          /*  KEY_KP0         82 */
gabomdq@7753
   165
    SDL_SCANCODE_KP_PERIOD,     /*  KEY_KPDOT       83 */
gabomdq@7753
   166
    SDL_SCANCODE_UNKNOWN,       /*  84 */
gabomdq@7753
   167
    SDL_SCANCODE_LANG5,         /*  KEY_ZENKAKUHANKAKU  85 */
gabomdq@7753
   168
    SDL_SCANCODE_UNKNOWN,       /*  KEY_102ND       86 */
gabomdq@7753
   169
    SDL_SCANCODE_F11,           /*  KEY_F11         87 */
gabomdq@7753
   170
    SDL_SCANCODE_F12,           /*  KEY_F12         88 */
gabomdq@7753
   171
    SDL_SCANCODE_UNKNOWN,       /*  KEY_RO          89 */
gabomdq@7753
   172
    SDL_SCANCODE_LANG3,         /*  KEY_KATAKANA        90 */
gabomdq@7753
   173
    SDL_SCANCODE_LANG4,         /*  KEY_HIRAGANA        91 */
gabomdq@7753
   174
    SDL_SCANCODE_UNKNOWN,       /*  KEY_HENKAN      92 */
gabomdq@7753
   175
    SDL_SCANCODE_LANG3,         /*  KEY_KATAKANAHIRAGANA    93 */
gabomdq@7753
   176
    SDL_SCANCODE_UNKNOWN,       /*  KEY_MUHENKAN        94 */
gabomdq@7753
   177
    SDL_SCANCODE_KP_COMMA,      /*  KEY_KPJPCOMMA       95 */
gabomdq@7753
   178
    SDL_SCANCODE_KP_ENTER,      /*  KEY_KPENTER     96 */
gabomdq@7753
   179
    SDL_SCANCODE_RCTRL,         /*  KEY_RIGHTCTRL       97 */
gabomdq@7753
   180
    SDL_SCANCODE_KP_DIVIDE,     /*  KEY_KPSLASH     98 */
gabomdq@7753
   181
    SDL_SCANCODE_SYSREQ,        /*  KEY_SYSRQ       99 */
gabomdq@7753
   182
    SDL_SCANCODE_RALT,          /*  KEY_RIGHTALT        100 */
gabomdq@7753
   183
    SDL_SCANCODE_UNKNOWN,       /*  KEY_LINEFEED        101 */
gabomdq@7753
   184
    SDL_SCANCODE_HOME,          /*  KEY_HOME        102 */
gabomdq@7753
   185
    SDL_SCANCODE_UP,            /*  KEY_UP          103 */
gabomdq@7753
   186
    SDL_SCANCODE_PAGEUP,        /*  KEY_PAGEUP      104 */
gabomdq@7753
   187
    SDL_SCANCODE_LEFT,          /*  KEY_LEFT        105 */
gabomdq@7753
   188
    SDL_SCANCODE_RIGHT,         /*  KEY_RIGHT       106 */
gabomdq@7753
   189
    SDL_SCANCODE_END,           /*  KEY_END         107 */
gabomdq@7753
   190
    SDL_SCANCODE_DOWN,          /*  KEY_DOWN        108 */
gabomdq@7753
   191
    SDL_SCANCODE_PAGEDOWN,      /*  KEY_PAGEDOWN        109 */
gabomdq@7753
   192
    SDL_SCANCODE_INSERT,        /*  KEY_INSERT      110 */
gabomdq@7753
   193
    SDL_SCANCODE_DELETE,        /*  KEY_DELETE      111 */
gabomdq@7753
   194
    SDL_SCANCODE_UNKNOWN,       /*  KEY_MACRO       112 */
gabomdq@7753
   195
    SDL_SCANCODE_MUTE,          /*  KEY_MUTE        113 */
gabomdq@7753
   196
    SDL_SCANCODE_VOLUMEDOWN,    /*  KEY_VOLUMEDOWN      114 */
gabomdq@7753
   197
    SDL_SCANCODE_VOLUMEUP,      /*  KEY_VOLUMEUP        115 */
gabomdq@7753
   198
    SDL_SCANCODE_POWER,         /*  KEY_POWER       116 SC System Power Down */
gabomdq@7753
   199
    SDL_SCANCODE_KP_EQUALS,     /*  KEY_KPEQUAL     117 */
gabomdq@7753
   200
    SDL_SCANCODE_KP_MINUS,      /*  KEY_KPPLUSMINUS     118 */
gabomdq@7753
   201
    SDL_SCANCODE_PAUSE,         /*  KEY_PAUSE       119 */
gabomdq@7753
   202
    SDL_SCANCODE_UNKNOWN,       /*  KEY_SCALE       120 AL Compiz Scale (Expose) */
gabomdq@7753
   203
    SDL_SCANCODE_KP_COMMA,      /*  KEY_KPCOMMA     121 */
gabomdq@7753
   204
    SDL_SCANCODE_LANG1,         /*  KEY_HANGEUL,KEY_HANGUEL 122 */
gabomdq@7753
   205
    SDL_SCANCODE_LANG2,         /*  KEY_HANJA       123 */
gabomdq@7753
   206
    SDL_SCANCODE_INTERNATIONAL3,/*  KEY_YEN         124 */
gabomdq@7753
   207
    SDL_SCANCODE_LGUI,          /*  KEY_LEFTMETA        125 */
gabomdq@7753
   208
    SDL_SCANCODE_RGUI,          /*  KEY_RIGHTMETA       126 */
gabomdq@7753
   209
    SDL_SCANCODE_APPLICATION,   /*  KEY_COMPOSE     127 */
gabomdq@7753
   210
    SDL_SCANCODE_STOP,          /*  KEY_STOP        128 AC Stop */
gabomdq@7753
   211
    SDL_SCANCODE_AGAIN,         /*  KEY_AGAIN       129 */
gabomdq@7753
   212
    SDL_SCANCODE_UNKNOWN,       /*  KEY_PROPS       130 AC Properties */
gabomdq@7753
   213
    SDL_SCANCODE_UNDO,          /*  KEY_UNDO        131 AC Undo */
gabomdq@7753
   214
    SDL_SCANCODE_UNKNOWN,       /*  KEY_FRONT       132 */
gabomdq@7753
   215
    SDL_SCANCODE_COPY,          /*  KEY_COPY        133 AC Copy */
gabomdq@7753
   216
    SDL_SCANCODE_UNKNOWN,       /*  KEY_OPEN        134 AC Open */
gabomdq@7753
   217
    SDL_SCANCODE_PASTE,         /*  KEY_PASTE       135 AC Paste */
gabomdq@7753
   218
    SDL_SCANCODE_FIND,          /*  KEY_FIND        136 AC Search */
gabomdq@7753
   219
    SDL_SCANCODE_CUT,           /*  KEY_CUT         137 AC Cut */
gabomdq@7753
   220
    SDL_SCANCODE_HELP,          /*  KEY_HELP        138 AL Integrated Help Center */
gabomdq@7753
   221
    SDL_SCANCODE_MENU,          /*  KEY_MENU        139 Menu (show menu) */
gabomdq@7753
   222
    SDL_SCANCODE_CALCULATOR,    /*  KEY_CALC        140 AL Calculator */
gabomdq@7753
   223
    SDL_SCANCODE_UNKNOWN,       /*  KEY_SETUP       141 */
gabomdq@7753
   224
    SDL_SCANCODE_SLEEP,         /*  KEY_SLEEP       142 SC System Sleep */
gabomdq@7753
   225
    SDL_SCANCODE_UNKNOWN,       /*  KEY_WAKEUP      143 System Wake Up */
gabomdq@7753
   226
    SDL_SCANCODE_UNKNOWN,       /*  KEY_FILE        144 AL Local Machine Browser */
gabomdq@7753
   227
    SDL_SCANCODE_UNKNOWN,       /*  KEY_SENDFILE        145 */
gabomdq@7753
   228
    SDL_SCANCODE_UNKNOWN,       /*  KEY_DELETEFILE      146 */
gabomdq@7753
   229
    SDL_SCANCODE_UNKNOWN,       /*  KEY_XFER        147 */
gabomdq@7753
   230
    SDL_SCANCODE_APP1,          /*  KEY_PROG1       148 */
gabomdq@7753
   231
    SDL_SCANCODE_APP1,          /*  KEY_PROG2       149 */
gabomdq@7753
   232
    SDL_SCANCODE_WWW,           /*  KEY_WWW         150 AL Internet Browser */
gabomdq@7753
   233
    SDL_SCANCODE_UNKNOWN,       /*  KEY_MSDOS       151 */
gabomdq@7753
   234
    SDL_SCANCODE_UNKNOWN,       /*  KEY_COFFEE,KEY_SCREENLOCK      152 AL Terminal Lock/Screensaver */
gabomdq@7753
   235
    SDL_SCANCODE_UNKNOWN,       /*  KEY_DIRECTION       153 */
gabomdq@7753
   236
    SDL_SCANCODE_UNKNOWN,       /*  KEY_CYCLEWINDOWS    154 */
gabomdq@7753
   237
    SDL_SCANCODE_MAIL,          /*  KEY_MAIL        155 */
gabomdq@7753
   238
    SDL_SCANCODE_AC_BOOKMARKS,  /*  KEY_BOOKMARKS       156 AC Bookmarks */
gabomdq@7753
   239
    SDL_SCANCODE_COMPUTER,      /*  KEY_COMPUTER        157 */
gabomdq@7753
   240
    SDL_SCANCODE_AC_BACK,       /*  KEY_BACK        158 AC Back */
gabomdq@7753
   241
    SDL_SCANCODE_AC_FORWARD,    /*  KEY_FORWARD     159 AC Forward */
gabomdq@7753
   242
    SDL_SCANCODE_UNKNOWN,       /*  KEY_CLOSECD     160 */
gabomdq@7753
   243
    SDL_SCANCODE_EJECT,         /*  KEY_EJECTCD     161 */
gabomdq@7753
   244
    SDL_SCANCODE_UNKNOWN,       /*  KEY_EJECTCLOSECD    162 */
gabomdq@7753
   245
    SDL_SCANCODE_AUDIONEXT,     /*  KEY_NEXTSONG        163 */
gabomdq@7753
   246
    SDL_SCANCODE_AUDIOPLAY,     /*  KEY_PLAYPAUSE       164 */
gabomdq@7753
   247
    SDL_SCANCODE_AUDIOPREV,     /*  KEY_PREVIOUSSONG    165 */
gabomdq@7753
   248
    SDL_SCANCODE_AUDIOSTOP,     /*  KEY_STOPCD      166 */
gabomdq@7753
   249
    SDL_SCANCODE_UNKNOWN,       /*  KEY_RECORD      167 */
gabomdq@7753
   250
    SDL_SCANCODE_UNKNOWN,       /*  KEY_REWIND      168 */
gabomdq@7753
   251
    SDL_SCANCODE_UNKNOWN,       /*  KEY_PHONE       169 Media Select Telephone */
gabomdq@7753
   252
    SDL_SCANCODE_UNKNOWN,       /*  KEY_ISO         170 */
gabomdq@7753
   253
    SDL_SCANCODE_UNKNOWN,       /*  KEY_CONFIG      171 AL Consumer Control Configuration */
gabomdq@7753
   254
    SDL_SCANCODE_AC_HOME,       /*  KEY_HOMEPAGE        172 AC Home */
gabomdq@7753
   255
    SDL_SCANCODE_AC_REFRESH,    /*  KEY_REFRESH     173 AC Refresh */
gabomdq@7753
   256
    SDL_SCANCODE_UNKNOWN,       /*  KEY_EXIT        174 AC Exit */
gabomdq@7753
   257
    SDL_SCANCODE_UNKNOWN,       /*  KEY_MOVE        175 */
gabomdq@7753
   258
    SDL_SCANCODE_UNKNOWN,       /*  KEY_EDIT        176 */
gabomdq@7753
   259
    SDL_SCANCODE_UNKNOWN,       /*  KEY_SCROLLUP        177 */
gabomdq@7753
   260
    SDL_SCANCODE_UNKNOWN,       /*  KEY_SCROLLDOWN      178 */
gabomdq@7753
   261
    SDL_SCANCODE_KP_LEFTPAREN,  /*  KEY_KPLEFTPAREN     179 */
gabomdq@7753
   262
    SDL_SCANCODE_KP_RIGHTPAREN, /*  KEY_KPRIGHTPAREN    180 */
gabomdq@7753
   263
    SDL_SCANCODE_UNKNOWN,       /*  KEY_NEW         181 AC New */
gabomdq@7753
   264
    SDL_SCANCODE_AGAIN,         /*  KEY_REDO        182 AC Redo/Repeat */
gabomdq@7753
   265
    SDL_SCANCODE_F13,           /*  KEY_F13         183 */
gabomdq@7753
   266
    SDL_SCANCODE_F14,           /*  KEY_F14         184 */
gabomdq@7753
   267
    SDL_SCANCODE_F15,           /*  KEY_F15         185 */
gabomdq@7753
   268
    SDL_SCANCODE_F16,           /*  KEY_F16         186 */
gabomdq@7753
   269
    SDL_SCANCODE_F17,           /*  KEY_F17         187 */
gabomdq@7753
   270
    SDL_SCANCODE_F18,           /*  KEY_F18         188 */
gabomdq@7753
   271
    SDL_SCANCODE_F19,           /*  KEY_F19         189 */
gabomdq@7753
   272
    SDL_SCANCODE_F20,           /*  KEY_F20         190 */
gabomdq@7753
   273
    SDL_SCANCODE_F21,           /*  KEY_F21         191 */
gabomdq@7753
   274
    SDL_SCANCODE_F22,           /*  KEY_F22         192 */
gabomdq@7753
   275
    SDL_SCANCODE_F23,           /*  KEY_F23         193 */
gabomdq@7753
   276
    SDL_SCANCODE_F24,           /*  KEY_F24         194 */
gabomdq@7753
   277
    SDL_SCANCODE_UNKNOWN,       /*  195 */
gabomdq@7753
   278
    SDL_SCANCODE_UNKNOWN,       /*  196 */
gabomdq@7753
   279
    SDL_SCANCODE_UNKNOWN,       /*  197 */
gabomdq@7753
   280
    SDL_SCANCODE_UNKNOWN,       /*  198 */
gabomdq@7753
   281
    SDL_SCANCODE_UNKNOWN,       /*  199 */
gabomdq@7753
   282
    SDL_SCANCODE_UNKNOWN,       /*  KEY_PLAYCD      200 */
gabomdq@7753
   283
    SDL_SCANCODE_UNKNOWN,       /*  KEY_PAUSECD     201 */
gabomdq@7753
   284
    SDL_SCANCODE_UNKNOWN,       /*  KEY_PROG3       202 */
gabomdq@7753
   285
    SDL_SCANCODE_UNKNOWN,       /*  KEY_PROG4       203 */
gabomdq@7753
   286
    SDL_SCANCODE_UNKNOWN,       /*  KEY_DASHBOARD       204 AL Dashboard */
gabomdq@7753
   287
    SDL_SCANCODE_UNKNOWN,       /*  KEY_SUSPEND     205 */
gabomdq@7753
   288
    SDL_SCANCODE_UNKNOWN,       /*  KEY_CLOSE       206 AC Close */
gabomdq@7753
   289
    SDL_SCANCODE_UNKNOWN,       /*  KEY_PLAY        207 */
gabomdq@7753
   290
    SDL_SCANCODE_UNKNOWN,       /*  KEY_FASTFORWARD     208 */
gabomdq@7753
   291
    SDL_SCANCODE_UNKNOWN,       /*  KEY_BASSBOOST       209 */
gabomdq@7753
   292
    SDL_SCANCODE_UNKNOWN,       /*  KEY_PRINT       210 AC Print */
gabomdq@7753
   293
    SDL_SCANCODE_UNKNOWN,       /*  KEY_HP          211 */
gabomdq@7753
   294
    SDL_SCANCODE_UNKNOWN,       /*  KEY_CAMERA      212 */
gabomdq@7753
   295
    SDL_SCANCODE_UNKNOWN,       /*  KEY_SOUND       213 */
gabomdq@7753
   296
    SDL_SCANCODE_UNKNOWN,       /*  KEY_QUESTION        214 */
gabomdq@7753
   297
    SDL_SCANCODE_UNKNOWN,       /*  KEY_EMAIL       215 */
gabomdq@7753
   298
    SDL_SCANCODE_UNKNOWN,       /*  KEY_CHAT        216 */
gabomdq@7753
   299
    SDL_SCANCODE_UNKNOWN,       /*  KEY_SEARCH      217 */
gabomdq@7753
   300
    SDL_SCANCODE_UNKNOWN,       /*  KEY_CONNECT     218 */
gabomdq@7753
   301
    SDL_SCANCODE_UNKNOWN,       /*  KEY_FINANCE     219 AL Checkbook/Finance */
gabomdq@7753
   302
    SDL_SCANCODE_UNKNOWN,       /*  KEY_SPORT       220 */
gabomdq@7753
   303
    SDL_SCANCODE_UNKNOWN,       /*  KEY_SHOP        221 */
gabomdq@7753
   304
    SDL_SCANCODE_UNKNOWN,       /*  KEY_ALTERASE        222 */
gabomdq@7753
   305
    SDL_SCANCODE_UNKNOWN,       /*  KEY_CANCEL      223 AC Cancel */
gabomdq@7753
   306
    SDL_SCANCODE_UNKNOWN,       /*  KEY_BRIGHTNESSDOWN  224 */
gabomdq@7753
   307
    SDL_SCANCODE_UNKNOWN,       /*  KEY_BRIGHTNESSUP    225 */
gabomdq@7753
   308
    SDL_SCANCODE_UNKNOWN,       /*  KEY_MEDIA       226 */
gabomdq@7753
   309
    SDL_SCANCODE_UNKNOWN,       /*  KEY_SWITCHVIDEOMODE 227 Cycle between available video outputs (Monitor/LCD/TV-out/etc) */
gabomdq@7753
   310
    SDL_SCANCODE_UNKNOWN,       /*  KEY_KBDILLUMTOGGLE  228 */
gabomdq@7753
   311
    SDL_SCANCODE_UNKNOWN,       /*  KEY_KBDILLUMDOWN    229 */
gabomdq@7753
   312
    SDL_SCANCODE_UNKNOWN,       /*  KEY_KBDILLUMUP      230 */
gabomdq@7753
   313
    SDL_SCANCODE_UNKNOWN,       /*  KEY_SEND        231 AC Send */
gabomdq@7753
   314
    SDL_SCANCODE_UNKNOWN,       /*  KEY_REPLY       232 AC Reply */
gabomdq@7753
   315
    SDL_SCANCODE_UNKNOWN,       /*  KEY_FORWARDMAIL     233 AC Forward Msg */
gabomdq@7753
   316
    SDL_SCANCODE_UNKNOWN,       /*  KEY_SAVE        234 AC Save */
gabomdq@7753
   317
    SDL_SCANCODE_UNKNOWN,       /*  KEY_DOCUMENTS       235 */
gabomdq@7753
   318
    SDL_SCANCODE_UNKNOWN,       /*  KEY_BATTERY     236  */
gabomdq@7753
   319
    SDL_SCANCODE_UNKNOWN,       /*  KEY_BLUETOOTH       237 */
gabomdq@7753
   320
    SDL_SCANCODE_UNKNOWN,       /*  KEY_WLAN        238 */
gabomdq@7753
   321
    SDL_SCANCODE_UNKNOWN,       /*  KEY_UWB         239 */
gabomdq@7753
   322
    SDL_SCANCODE_UNKNOWN,       /*  KEY_UNKNOWN     240 */
gabomdq@7753
   323
    SDL_SCANCODE_UNKNOWN,       /*  KEY_VIDEO_NEXT      241 drive next video source */
gabomdq@7753
   324
    SDL_SCANCODE_UNKNOWN,       /*  KEY_VIDEO_PREV      242 drive previous video source */
gabomdq@7753
   325
    SDL_SCANCODE_UNKNOWN,       /*  KEY_BRIGHTNESS_CYCLE    243 brightness up, after max is min */
gabomdq@7753
   326
    SDL_SCANCODE_UNKNOWN,       /*  KEY_BRIGHTNESS_ZERO 244 brightness off, use ambient */
gabomdq@7753
   327
    SDL_SCANCODE_UNKNOWN,       /*  KEY_DISPLAY_OFF     245 display device to off state */
gabomdq@7753
   328
    SDL_SCANCODE_UNKNOWN,       /*  KEY_WIMAX       246 */
gabomdq@7753
   329
    SDL_SCANCODE_UNKNOWN,       /*  KEY_RFKILL      247 Key that controls all radios */
gabomdq@7753
   330
    SDL_SCANCODE_UNKNOWN,       /*  KEY_MICMUTE     248 Mute / unmute the microphone */
gabomdq@7753
   331
};
gabomdq@7753
   332
gabomdq@7753
   333
static Uint8 EVDEV_MouseButtons[] = {
gabomdq@7753
   334
    SDL_BUTTON_LEFT,            /*  BTN_LEFT        0x110 */
gabomdq@7753
   335
    SDL_BUTTON_RIGHT,           /*  BTN_RIGHT       0x111 */
gabomdq@7753
   336
    SDL_BUTTON_MIDDLE,          /*  BTN_MIDDLE      0x112 */
gabomdq@7753
   337
    SDL_BUTTON_X1,              /*  BTN_SIDE        0x113 */
gabomdq@7753
   338
    SDL_BUTTON_X2,              /*  BTN_EXTRA       0x114 */
gabomdq@7753
   339
    SDL_BUTTON_X2 + 1,          /*  BTN_FORWARD     0x115 */
gabomdq@7753
   340
    SDL_BUTTON_X2 + 2,          /*  BTN_BACK        0x116 */
gabomdq@7753
   341
    SDL_BUTTON_X2 + 3           /*  BTN_TASK        0x117 */
gabomdq@7753
   342
};
gabomdq@7753
   343
icculus@9729
   344
static const char* EVDEV_consoles[] = {
gabomdq@7778
   345
    "/proc/self/fd/0",
gabomdq@7778
   346
    "/dev/tty",
gabomdq@7778
   347
    "/dev/tty0",
gabomdq@7778
   348
    "/dev/tty1",
gabomdq@7778
   349
    "/dev/tty2",
gabomdq@7778
   350
    "/dev/tty3",
gabomdq@7778
   351
    "/dev/tty4",
gabomdq@7778
   352
    "/dev/tty5",
gabomdq@7778
   353
    "/dev/tty6",
gabomdq@7778
   354
    "/dev/vc/0",
gabomdq@7778
   355
    "/dev/console"
gabomdq@7778
   356
};
gabomdq@7778
   357
gabomdq@7778
   358
#define IS_CONSOLE(fd) isatty (fd) && ioctl(fd, KDGKBTYPE, &arg) == 0 && ((arg == KB_101) || (arg == KB_84))
gabomdq@7778
   359
gabomdq@7778
   360
static int SDL_EVDEV_get_console_fd(void)
gabomdq@7778
   361
{
gabomdq@7778
   362
    int fd, i;
gabomdq@7778
   363
    char arg = 0;
gabomdq@7778
   364
    
gabomdq@7778
   365
    /* Try a few consoles to see which one we have read access to */
gabomdq@7778
   366
    
slouken@9780
   367
    for(i = 0; i < SDL_arraysize(EVDEV_consoles); i++) {
gabomdq@7778
   368
        fd = open(EVDEV_consoles[i], O_RDONLY);
gabomdq@7778
   369
        if (fd >= 0) {
gabomdq@7778
   370
            if (IS_CONSOLE(fd)) return fd;
gabomdq@7778
   371
            close(fd);
gabomdq@7778
   372
        }
gabomdq@7778
   373
    }
gabomdq@7778
   374
    
gabomdq@7778
   375
    /* Try stdin, stdout, stderr */
gabomdq@7778
   376
    
slouken@9780
   377
    for(fd = 0; fd < 3; fd++) {
gabomdq@7778
   378
        if (IS_CONSOLE(fd)) return fd;
gabomdq@7778
   379
    }
gabomdq@7778
   380
    
gabomdq@7778
   381
    /* We won't be able to send SDL_TEXTINPUT events */
gabomdq@7778
   382
    return -1;
gabomdq@7778
   383
}
gabomdq@7778
   384
gabomdq@7809
   385
/* Prevent keystrokes from reaching the tty */
gabomdq@7809
   386
static int SDL_EVDEV_mute_keyboard(int tty, int *kb_mode)
gabomdq@7809
   387
{
gabomdq@7809
   388
    char arg;
gabomdq@7809
   389
    
gabomdq@7809
   390
    *kb_mode = 0; /* FIXME: Is this a sane default in case KDGKBMODE fails? */
gabomdq@7809
   391
    if (!IS_CONSOLE(tty)) {
gabomdq@7809
   392
        return SDL_SetError("Tried to mute an invalid tty");
gabomdq@7809
   393
    }
gabomdq@7809
   394
    ioctl(tty, KDGKBMODE, kb_mode); /* It's not fatal if this fails */
gabomdq@7809
   395
    if (ioctl(tty, KDSKBMUTE, 1) && ioctl(tty, KDSKBMODE, K_OFF)) {
gabomdq@7809
   396
        return SDL_SetError("EVDEV: Failed muting keyboard");
gabomdq@7809
   397
    }
gabomdq@7809
   398
    
gabomdq@7809
   399
    return 0;  
gabomdq@7809
   400
}
gabomdq@7809
   401
gabomdq@7809
   402
/* Restore the keyboard mode for given tty */
gabomdq@7809
   403
static void SDL_EVDEV_unmute_keyboard(int tty, int kb_mode)
gabomdq@7809
   404
{
gabomdq@7809
   405
    if (ioctl(tty, KDSKBMUTE, 0) && ioctl(tty, KDSKBMODE, kb_mode)) {
gabomdq@7809
   406
        SDL_Log("EVDEV: Failed restoring keyboard mode");
gabomdq@7809
   407
    }
gabomdq@7809
   408
}
gabomdq@7809
   409
gabomdq@7809
   410
/* Read /sys/class/tty/tty0/active and open the tty */
gabomdq@7809
   411
static int SDL_EVDEV_get_active_tty()
gabomdq@7809
   412
{
gabomdq@7809
   413
    int fd, len;
gabomdq@7809
   414
    char ttyname[NAME_MAX + 1];
gabomdq@7809
   415
    char ttypath[PATH_MAX+1] = "/dev/";
gabomdq@7809
   416
    char arg;
gabomdq@7809
   417
    
gabomdq@7809
   418
    fd = open("/sys/class/tty/tty0/active", O_RDONLY);
gabomdq@7809
   419
    if (fd < 0) {
gabomdq@7809
   420
        return SDL_SetError("Could not determine which tty is active");
gabomdq@7809
   421
    }
gabomdq@7809
   422
    
gabomdq@7809
   423
    len = read(fd, ttyname, NAME_MAX);
gabomdq@7809
   424
    close(fd);
gabomdq@7809
   425
    
gabomdq@7809
   426
    if (len <= 0) {
gabomdq@7809
   427
        return SDL_SetError("Could not read which tty is active");
gabomdq@7809
   428
    }
gabomdq@7809
   429
    
gabomdq@7809
   430
    if (ttyname[len-1] == '\n') {
gabomdq@7809
   431
        ttyname[len-1] = '\0';
gabomdq@7809
   432
    }
gabomdq@7809
   433
    else {
gabomdq@7809
   434
        ttyname[len] = '\0';
gabomdq@7809
   435
    }
gabomdq@7809
   436
    
gabomdq@7809
   437
    SDL_strlcat(ttypath, ttyname, PATH_MAX);
gabomdq@7809
   438
    fd = open(ttypath, O_RDWR | O_NOCTTY);
gabomdq@7809
   439
    if (fd < 0) {
gabomdq@7809
   440
        return SDL_SetError("Could not open tty: %s", ttypath);
gabomdq@7809
   441
    }
gabomdq@7809
   442
    
gabomdq@7809
   443
    if (!IS_CONSOLE(fd)) {
gabomdq@7809
   444
        close(fd);
gabomdq@7809
   445
        return SDL_SetError("Invalid tty obtained: %s", ttypath);
gabomdq@7809
   446
    }
gabomdq@7809
   447
gabomdq@7809
   448
    return fd;  
gabomdq@7809
   449
}
gabomdq@7809
   450
gabomdq@7753
   451
int
gabomdq@7753
   452
SDL_EVDEV_Init(void)
gabomdq@7753
   453
{
gabomdq@7753
   454
    int retval = 0;
gabomdq@7753
   455
    
gabomdq@7753
   456
    if (_this == NULL) {
gabomdq@7778
   457
        
gabomdq@7753
   458
        _this = (SDL_EVDEV_PrivateData *) SDL_calloc(1, sizeof(*_this));
gabomdq@7753
   459
        if(_this == NULL) {
gabomdq@7753
   460
            return SDL_OutOfMemory();
gabomdq@7753
   461
        }
gabomdq@7753
   462
gabomdq@7753
   463
#if SDL_USE_LIBUDEV
gabomdq@7753
   464
        if (SDL_UDEV_Init() < 0) {
gabomdq@7753
   465
            SDL_free(_this);
gabomdq@7753
   466
            _this = NULL;
gabomdq@7753
   467
            return -1;
gabomdq@7753
   468
        }
gabomdq@7753
   469
gabomdq@7753
   470
        /* Set up the udev callback */
slouken@9780
   471
        if (SDL_UDEV_AddCallback(SDL_EVDEV_udev_callback) < 0) {
gabomdq@7753
   472
            SDL_EVDEV_Quit();
gabomdq@7753
   473
            return -1;
gabomdq@7753
   474
        }
gabomdq@7753
   475
        
gabomdq@7753
   476
        /* Force a scan to build the initial device list */
gabomdq@7753
   477
        SDL_UDEV_Scan();
gabomdq@7753
   478
#else
gabomdq@7753
   479
        /* TODO: Scan the devices manually, like a caveman */
gabomdq@7753
   480
#endif /* SDL_USE_LIBUDEV */
gabomdq@7778
   481
        
gabomdq@7778
   482
        /* We need a physical terminal (not PTS) to be able to translate key code to symbols via the kernel tables */
gabomdq@7778
   483
        _this->console_fd = SDL_EVDEV_get_console_fd();
gabomdq@7809
   484
        
gabomdq@7809
   485
        /* Mute the keyboard so keystrokes only generate evdev events and do not leak through to the console */
gabomdq@7809
   486
        _this->tty = STDIN_FILENO;
gabomdq@7809
   487
        if (SDL_EVDEV_mute_keyboard(_this->tty, &_this->kb_mode) < 0) {
gabomdq@7809
   488
            /* stdin is not a tty, probably we were launched remotely, so we try to disable the active tty */
gabomdq@7809
   489
            _this->tty = SDL_EVDEV_get_active_tty();
gabomdq@7809
   490
            if (_this->tty >= 0) {
gabomdq@7809
   491
                if (SDL_EVDEV_mute_keyboard(_this->tty, &_this->kb_mode) < 0) {
gabomdq@7809
   492
                    close(_this->tty);
gabomdq@7809
   493
                    _this->tty = -1;
gabomdq@7809
   494
                }
gabomdq@7809
   495
            }
gabomdq@7809
   496
        }
gabomdq@7753
   497
    }
gabomdq@7753
   498
    
gabomdq@7753
   499
    _this->ref_count += 1;
gabomdq@7753
   500
    
gabomdq@7753
   501
    return retval;
gabomdq@7753
   502
}
gabomdq@7753
   503
gabomdq@7753
   504
void
gabomdq@7753
   505
SDL_EVDEV_Quit(void)
gabomdq@7753
   506
{
gabomdq@7753
   507
    if (_this == NULL) {
gabomdq@7753
   508
        return;
gabomdq@7753
   509
    }
gabomdq@7753
   510
    
gabomdq@7753
   511
    _this->ref_count -= 1;
gabomdq@7753
   512
    
gabomdq@7753
   513
    if (_this->ref_count < 1) {
gabomdq@7753
   514
        
gabomdq@7753
   515
#if SDL_USE_LIBUDEV
gabomdq@7753
   516
        SDL_UDEV_DelCallback(SDL_EVDEV_udev_callback);
gabomdq@7753
   517
        SDL_UDEV_Quit();
gabomdq@7753
   518
#endif /* SDL_USE_LIBUDEV */
gabomdq@7753
   519
       
gabomdq@7778
   520
        if (_this->console_fd >= 0) {
gabomdq@7778
   521
            close(_this->console_fd);
gabomdq@7778
   522
        }
gabomdq@7809
   523
        
gabomdq@7809
   524
        if (_this->tty >= 0) {
gabomdq@7809
   525
            SDL_EVDEV_unmute_keyboard(_this->tty, _this->kb_mode);
gabomdq@7809
   526
            close(_this->tty);
gabomdq@7809
   527
        }
gabomdq@7809
   528
        
gabomdq@7753
   529
        /* Remove existing devices */
gabomdq@7753
   530
        while(_this->first != NULL) {
gabomdq@7753
   531
            SDL_EVDEV_device_removed(_this->first->path);
gabomdq@7753
   532
        }
gabomdq@7753
   533
        
gabomdq@7753
   534
        SDL_assert(_this->first == NULL);
gabomdq@7753
   535
        SDL_assert(_this->last == NULL);
gabomdq@7753
   536
        SDL_assert(_this->numdevices == 0);
gabomdq@7753
   537
        
gabomdq@7753
   538
        SDL_free(_this);
gabomdq@7753
   539
        _this = NULL;
gabomdq@7753
   540
    }
gabomdq@7753
   541
}
gabomdq@7753
   542
gabomdq@7755
   543
#if SDL_USE_LIBUDEV
slouken@7788
   544
void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
gabomdq@7753
   545
{
gabomdq@7753
   546
    if (devpath == NULL) {
gabomdq@7753
   547
        return;
gabomdq@7753
   548
    }
gabomdq@7753
   549
    
slouken@9779
   550
    switch(udev_type) {
slouken@7788
   551
    case SDL_UDEV_DEVICEADDED:
slouken@9779
   552
        if (!(udev_class & (SDL_UDEV_DEVICE_MOUSE|SDL_UDEV_DEVICE_KEYBOARD))) {
slouken@9779
   553
            return;
slouken@9779
   554
        }
slouken@7788
   555
        SDL_EVDEV_device_added(devpath);
slouken@7788
   556
        break;
gabomdq@7753
   557
            
slouken@7788
   558
    case SDL_UDEV_DEVICEREMOVED:
slouken@7788
   559
        SDL_EVDEV_device_removed(devpath);
slouken@7788
   560
        break;
gabomdq@7753
   561
            
slouken@7788
   562
    default:
slouken@7788
   563
        break;
gabomdq@7753
   564
    }
gabomdq@7753
   565
}
gabomdq@7753
   566
gabomdq@7755
   567
#endif /* SDL_USE_LIBUDEV */
gabomdq@7755
   568
gabomdq@7753
   569
void 
gabomdq@7753
   570
SDL_EVDEV_Poll(void)
gabomdq@7753
   571
{
gabomdq@7753
   572
    struct input_event events[32];
gabomdq@7753
   573
    int i, len;
gabomdq@7753
   574
    SDL_evdevlist_item *item;
gabomdq@7753
   575
    SDL_Scancode scan_code;
gabomdq@7753
   576
    int mouse_button;
gabomdq@7753
   577
    SDL_Mouse *mouse;
gabomdq@7778
   578
#ifdef SDL_INPUT_LINUXKD
gabomdq@7778
   579
    Uint16 modstate;
gabomdq@7778
   580
    struct kbentry kbe;
gabomdq@7778
   581
    static char keysym[8];
gabomdq@7778
   582
    char *end;
gabomdq@7778
   583
    Uint32 kval;
gabomdq@7778
   584
#endif
gabomdq@7778
   585
slouken@9159
   586
    if (!_this) {
slouken@9159
   587
        return;
slouken@9159
   588
    }
slouken@9159
   589
gabomdq@7753
   590
#if SDL_USE_LIBUDEV
gabomdq@7753
   591
    SDL_UDEV_Poll();
gabomdq@7753
   592
#endif
gabomdq@7778
   593
slouken@7788
   594
    mouse = SDL_GetMouse();
slouken@7788
   595
gabomdq@7753
   596
    for (item = _this->first; item != NULL; item = item->next) {
gabomdq@7753
   597
        while ((len = read(item->fd, events, (sizeof events))) > 0) {
gabomdq@7753
   598
            len /= sizeof(events[0]);
gabomdq@7753
   599
            for (i = 0; i < len; ++i) {
slouken@7788
   600
                switch (events[i].type) {
slouken@7788
   601
                case EV_KEY:
slouken@7788
   602
                    if (events[i].code >= BTN_MOUSE && events[i].code < BTN_MOUSE + SDL_arraysize(EVDEV_MouseButtons)) {
slouken@7788
   603
                        mouse_button = events[i].code - BTN_MOUSE;
slouken@7788
   604
                        if (events[i].value == 0) {
slouken@7788
   605
                            SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, EVDEV_MouseButtons[mouse_button]);
slouken@7788
   606
                        } else if (events[i].value == 1) {
slouken@7788
   607
                            SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_PRESSED, EVDEV_MouseButtons[mouse_button]);
slouken@7788
   608
                        }
slouken@7788
   609
                        break;
slouken@7788
   610
                    }
slouken@7788
   611
slouken@7788
   612
                    /* Probably keyboard */
slouken@7788
   613
                    scan_code = SDL_EVDEV_translate_keycode(events[i].code);
slouken@7788
   614
                    if (scan_code != SDL_SCANCODE_UNKNOWN) {
slouken@7788
   615
                        if (events[i].value == 0) {
slouken@7788
   616
                            SDL_SendKeyboardKey(SDL_RELEASED, scan_code);
slouken@9780
   617
                        } else if (events[i].value == 1 || events[i].value == 2 /* Key repeated */) {
slouken@7788
   618
                            SDL_SendKeyboardKey(SDL_PRESSED, scan_code);
gabomdq@7778
   619
#ifdef SDL_INPUT_LINUXKD
slouken@7788
   620
                            if (_this->console_fd >= 0) {
slouken@7788
   621
                                kbe.kb_index = events[i].code;
slouken@7788
   622
                                /* Convert the key to an UTF-8 char */
slouken@7788
   623
                                /* Ref: http://www.linuxjournal.com/article/2783 */
slouken@7788
   624
                                modstate = SDL_GetModState();
slouken@7788
   625
                                kbe.kb_table = 0;
slouken@7788
   626
                                
slouken@7788
   627
                                /* Ref: http://graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching */
slouken@9780
   628
                                kbe.kb_table |= -((modstate & KMOD_LCTRL) != 0) & (1 << KG_CTRLL | 1 << KG_CTRL);
slouken@9780
   629
                                kbe.kb_table |= -((modstate & KMOD_RCTRL) != 0) & (1 << KG_CTRLR | 1 << KG_CTRL);
slouken@9780
   630
                                kbe.kb_table |= -((modstate & KMOD_LSHIFT) != 0) & (1 << KG_SHIFTL | 1 << KG_SHIFT);
slouken@9780
   631
                                kbe.kb_table |= -((modstate & KMOD_RSHIFT) != 0) & (1 << KG_SHIFTR | 1 << KG_SHIFT);
slouken@9780
   632
                                kbe.kb_table |= -((modstate & KMOD_LALT) != 0) & (1 << KG_ALT);
slouken@9780
   633
                                kbe.kb_table |= -((modstate & KMOD_RALT) != 0) & (1 << KG_ALTGR);
gabomdq@7778
   634
slouken@7788
   635
                                if (ioctl(_this->console_fd, KDGKBENT, (unsigned long)&kbe) == 0 && 
slouken@7788
   636
                                    ((KTYP(kbe.kb_value) == KT_LATIN) || (KTYP(kbe.kb_value) == KT_ASCII) || (KTYP(kbe.kb_value) == KT_LETTER))) 
slouken@7788
   637
                                {
slouken@7788
   638
                                    kval = KVAL(kbe.kb_value);
slouken@7788
   639
                                    
slouken@7788
   640
                                    /* While there's a KG_CAPSSHIFT symbol, it's not useful to build the table index with it
slouken@7788
   641
                                     * because 1 << KG_CAPSSHIFT overflows the 8 bits of kb_table 
slouken@7788
   642
                                     * So, we do the CAPS LOCK logic here. Note that isalpha depends on the locale!
slouken@7788
   643
                                     */
slouken@9780
   644
                                    if (modstate & KMOD_CAPS && isalpha(kval)) {
slouken@9780
   645
                                        if (isupper(kval)) {
slouken@7788
   646
                                            kval = tolower(kval);
slouken@7788
   647
                                        } else {
slouken@7788
   648
                                            kval = toupper(kval);
gabomdq@7778
   649
                                        }
gabomdq@7753
   650
                                    }
slouken@7788
   651
                                     
slouken@7788
   652
                                    /* Convert to UTF-8 and send */
slouken@9780
   653
                                    end = SDL_UCS4ToUTF8(kval, keysym);
slouken@7788
   654
                                    *end = '\0';
slouken@7788
   655
                                    SDL_SendKeyboardText(keysym);
gabomdq@7753
   656
                                }
gabomdq@7778
   657
                            }
slouken@7788
   658
#endif /* SDL_INPUT_LINUXKD */
gabomdq@7753
   659
                        }
slouken@7788
   660
                    }
slouken@7788
   661
                    break;
slouken@7788
   662
                case EV_ABS:
slouken@7788
   663
                    switch(events[i].code) {
slouken@7788
   664
                    case ABS_X:
slouken@7788
   665
                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
slouken@7788
   666
                        break;
slouken@7788
   667
                    case ABS_Y:
slouken@7788
   668
                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value);
slouken@7788
   669
                        break;
gabomdq@7753
   670
                    default:
gabomdq@7753
   671
                        break;
slouken@7788
   672
                    }
slouken@7788
   673
                    break;
slouken@7788
   674
                case EV_REL:
slouken@7788
   675
                    switch(events[i].code) {
slouken@7788
   676
                    case REL_X:
slouken@7788
   677
                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, events[i].value, 0);
slouken@7788
   678
                        break;
slouken@7788
   679
                    case REL_Y:
slouken@7788
   680
                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, 0, events[i].value);
slouken@7788
   681
                        break;
slouken@7788
   682
                    case REL_WHEEL:
urkle@9257
   683
                        SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value, SDL_MOUSEWHEEL_NORMAL);
slouken@7788
   684
                        break;
slouken@7788
   685
                    case REL_HWHEEL:
urkle@9257
   686
                        SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL);
slouken@7788
   687
                        break;
slouken@7788
   688
                    default:
slouken@7788
   689
                        break;
slouken@7788
   690
                    }
slouken@7788
   691
                    break;
slouken@7788
   692
                case EV_SYN:
slouken@7788
   693
                    switch (events[i].code) {
slouken@7788
   694
                    case SYN_DROPPED:
slouken@7788
   695
                        SDL_EVDEV_sync_device(item);
slouken@7788
   696
                        break;
slouken@7788
   697
                    default:
slouken@7788
   698
                        break;
slouken@7788
   699
                    }
slouken@7788
   700
                    break;
gabomdq@7753
   701
                }
gabomdq@7753
   702
            }
gabomdq@7753
   703
        }    
gabomdq@7753
   704
    }
gabomdq@7753
   705
}
gabomdq@7753
   706
gabomdq@7753
   707
static SDL_Scancode
gabomdq@7753
   708
SDL_EVDEV_translate_keycode(int keycode)
gabomdq@7753
   709
{
gabomdq@7753
   710
    SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
gabomdq@7753
   711
gabomdq@7753
   712
    if (keycode < SDL_arraysize(EVDEV_Keycodes)) {
gabomdq@7753
   713
        scancode = EVDEV_Keycodes[keycode];
gabomdq@7753
   714
    }
gabomdq@7753
   715
    if (scancode == SDL_SCANCODE_UNKNOWN) {
gabomdq@7753
   716
        SDL_Log("The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list <sdl@libsdl.org> EVDEV KeyCode %d \n", keycode);
gabomdq@7753
   717
    }
gabomdq@7753
   718
    return scancode;
gabomdq@7753
   719
}
gabomdq@7753
   720
gabomdq@7753
   721
static void
gabomdq@7753
   722
SDL_EVDEV_sync_device(SDL_evdevlist_item *item) 
gabomdq@7753
   723
{
gabomdq@7753
   724
    /* TODO: get full state of device and report whatever is required */
gabomdq@7753
   725
}
gabomdq@7753
   726
gabomdq@7755
   727
#if SDL_USE_LIBUDEV
gabomdq@7753
   728
static int
slouken@7788
   729
SDL_EVDEV_device_added(const char *devpath)
gabomdq@7753
   730
{
gabomdq@7753
   731
    SDL_evdevlist_item *item;
gabomdq@7753
   732
gabomdq@7753
   733
    /* Check to make sure it's not already in list. */
gabomdq@7753
   734
    for (item = _this->first; item != NULL; item = item->next) {
slouken@9780
   735
        if (SDL_strcmp(devpath, item->path) == 0) {
gabomdq@7753
   736
            return -1;  /* already have this one */
gabomdq@7753
   737
        }
gabomdq@7753
   738
    }
gabomdq@7753
   739
    
gabomdq@7753
   740
    item = (SDL_evdevlist_item *) SDL_calloc(1, sizeof (SDL_evdevlist_item));
gabomdq@7753
   741
    if (item == NULL) {
gabomdq@7753
   742
        return SDL_OutOfMemory();
gabomdq@7753
   743
    }
gabomdq@7753
   744
gabomdq@7753
   745
    item->fd = open(devpath, O_RDONLY, 0);
gabomdq@7753
   746
    if (item->fd < 0) {
gabomdq@7753
   747
        SDL_free(item);
gabomdq@7753
   748
        return SDL_SetError("Unable to open %s", devpath);
gabomdq@7753
   749
    }
gabomdq@7753
   750
    
gabomdq@7753
   751
    item->path = SDL_strdup(devpath);
gabomdq@7753
   752
    if (item->path == NULL) {
gabomdq@7753
   753
        close(item->fd);
gabomdq@7753
   754
        SDL_free(item);
gabomdq@7753
   755
        return SDL_OutOfMemory();
gabomdq@7753
   756
    }
gabomdq@7753
   757
    
gabomdq@7753
   758
    /* Non blocking read mode */
gabomdq@7753
   759
    fcntl(item->fd, F_SETFL, O_NONBLOCK);
gabomdq@7753
   760
    
gabomdq@7753
   761
    if (_this->last == NULL) {
gabomdq@7753
   762
        _this->first = _this->last = item;
gabomdq@7753
   763
    } else {
gabomdq@7753
   764
        _this->last->next = item;
gabomdq@7753
   765
        _this->last = item;
gabomdq@7753
   766
    }
gabomdq@7753
   767
    
gabomdq@7753
   768
    SDL_EVDEV_sync_device(item);
gabomdq@7753
   769
    
gabomdq@7753
   770
    return _this->numdevices++;
gabomdq@7753
   771
}
gabomdq@7767
   772
#endif /* SDL_USE_LIBUDEV */
gabomdq@7753
   773
gabomdq@7753
   774
static int
gabomdq@7753
   775
SDL_EVDEV_device_removed(const char *devpath)
gabomdq@7753
   776
{
gabomdq@7753
   777
    SDL_evdevlist_item *item;
gabomdq@7753
   778
    SDL_evdevlist_item *prev = NULL;
gabomdq@7753
   779
gabomdq@7753
   780
    for (item = _this->first; item != NULL; item = item->next) {
gabomdq@7753
   781
        /* found it, remove it. */
slouken@9780
   782
        if (SDL_strcmp(devpath, item->path) == 0) {
gabomdq@7753
   783
            if (prev != NULL) {
gabomdq@7753
   784
                prev->next = item->next;
gabomdq@7753
   785
            } else {
gabomdq@7753
   786
                SDL_assert(_this->first == item);
gabomdq@7753
   787
                _this->first = item->next;
gabomdq@7753
   788
            }
gabomdq@7753
   789
            if (item == _this->last) {
gabomdq@7753
   790
                _this->last = prev;
gabomdq@7753
   791
            }
gabomdq@7753
   792
            close(item->fd);
gabomdq@7753
   793
            SDL_free(item->path);
gabomdq@7753
   794
            SDL_free(item);
gabomdq@7753
   795
            _this->numdevices--;
gabomdq@7753
   796
            return 0;
gabomdq@7753
   797
        }
gabomdq@7753
   798
        prev = item;
gabomdq@7753
   799
    }
gabomdq@7753
   800
gabomdq@7753
   801
    return -1;
gabomdq@7753
   802
}
gabomdq@7767
   803
gabomdq@7753
   804
gabomdq@7753
   805
#endif /* SDL_INPUT_LINUXEV */
gabomdq@7753
   806
gabomdq@7753
   807
/* vi: set ts=4 sw=4 expandtab: */
gabomdq@7778
   808