1 /*
2  * Copyright 2007-2008 by Sascha Hlusiak. <saschahlusiak@freedesktop.org>
3  * Copyright 1995-1999 by Frederic Lepied, France. <Lepied@XFree86.org>
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and its
6  * documentation for any purpose is  hereby granted without fee, provided that
7  * the  above copyright   notice appear  in   all  copies and  that both  that
8  * copyright  notice   and   this  permission   notice  appear  in  supporting
9  * documentation, and that  the  names  of copyright holders not  be  used  in
10  * advertising or publicity pertaining to distribution of the software without
11  * specific,  written      prior  permission.  The copyright holders  make  no
12  * representations about the suitability of this software for any purpose.  It
13  * is provided "as is" without express or implied warranty.
14  *
15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16  * INCLUDING ALL IMPLIED   WARRANTIES OF MERCHANTABILITY  AND   FITNESS, IN NO
17  * EVENT  SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT   OR
18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19  * DATA  OR PROFITS, WHETHER  IN  AN ACTION OF  CONTRACT,  NEGLIGENCE OR OTHER
20  * TORTIOUS  ACTION, ARISING    OUT OF OR   IN  CONNECTION  WITH THE USE    OR
21  * PERFORMANCE OF THIS SOFTWARE.
22  */
23 
24 
25 
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 
30 
31 #include <xorg-server.h>
32 #include <xf86.h>
33 #include <xf86Xinput.h>
34 #include <X11/extensions/XKBsrv.h>
35 #include <X11/keysym.h>
36 #include <X11/XF86keysym.h>
37 #include <xf86Optrec.h>
38 
39 #include "jstk.h"
40 #include "jstk_key.h"
41 
42 #include <xkbsrv.h>
43 
44 #define MIN_KEYCODE 8
45 #define GLYPHS_PER_KEY 2
46 
47 #define AltMask		Mod1Mask
48 #define NumLockMask	Mod2Mask
49 #define AltLangMask	Mod3Mask
50 #define KanaMask	Mod4Mask
51 #define ScrollLockMask	Mod5Mask
52 
53 static void
jstkKbdCtrl(DeviceIntPtr device,KeybdCtrl * ctrl)54 jstkKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl)
55 {
56 }
57 
58 
59 /*
60  ***************************************************************************
61  *
62  * jstkInitKeys --
63  *
64  * Sets up the keymap, modmap and the keyboard device structs
65  *
66  ***************************************************************************
67  */
68 static int
jstkInitKeys(DeviceIntPtr pJstk,JoystickDevPtr priv)69 jstkInitKeys(DeviceIntPtr pJstk, JoystickDevPtr priv)
70 {
71     XkbSrvInfoPtr xkbi;
72     XkbControlsPtr ctrls;
73 
74     if (!InitKeyboardDeviceStruct(pJstk, &priv->rmlvo, NULL, jstkKbdCtrl))
75     {
76         ErrorF("unable to init keyboard device\n");
77         return !Success;
78     }
79 
80     /* Set Autorepeat and Delay */
81     if ((priv->repeat_delay || priv->repeat_interval) &&
82         pJstk->key &&
83         pJstk->key->xkbInfo)
84     {
85         xkbi = pJstk->key->xkbInfo;
86         if (xkbi && xkbi->desc)
87         {
88             ctrls = xkbi->desc->ctrls;
89             ctrls->repeat_delay = priv->repeat_delay;
90             ctrls->repeat_interval = priv->repeat_interval;
91         }
92     }
93 
94     return Success;
95 }
96 
97 
98 
99 /*
100  ***************************************************************************
101  *
102  * jstkGenerateKeys
103  *
104  * Generates a series of keydown or keyup events of the specified
105  * KEYSCANCODES
106  *
107  ***************************************************************************
108  */
109 void
jstkGenerateKeys(InputInfoPtr device,KEYSCANCODES keys,char pressed)110 jstkGenerateKeys(InputInfoPtr device, KEYSCANCODES keys, char pressed)
111 {
112     int i;
113     unsigned int k;
114 
115     if (device == NULL)
116         return;
117     for (i=0;i<MAXKEYSPERBUTTON;i++) {
118         if (pressed != 0)
119             k = keys[i];
120         else k = keys[MAXKEYSPERBUTTON - i - 1];
121 
122         if (k != 0) {
123             DBG(2, ErrorF("Generating key %s event with keycode %d\n",
124                 (pressed)?"press":"release", k));
125             xf86PostKeyboardEvent(device->dev, k, pressed);
126         }
127     }
128 }
129 
130 
131 /*
132  ***************************************************************************
133  *
134  * jstkKeyboardDeviceControlProc --
135  *
136  * Handles the initialization, etc. of the keyboard device
137  *
138  ***************************************************************************
139  */
140 Bool
jstkKeyboardDeviceControlProc(DeviceIntPtr dev,int what)141 jstkKeyboardDeviceControlProc(DeviceIntPtr       dev,
142                               int                what)
143 {
144     InputInfoPtr pInfo = dev->public.devicePrivate;
145     JoystickDevPtr priv  = pInfo->private;
146     if (!priv) {
147         DBG(2, ErrorF("jstkKeyboardDeviceControlProc: priv == NULL\n"));
148         return !Success;
149     }
150     switch (what) {
151     case DEVICE_INIT:
152         DBG(2, ErrorF("jstkKeyboardDeviceControlProc what=DEVICE_INIT\n"));
153         if (InitFocusClassDeviceStruct(dev) == FALSE) {
154             ErrorF("unable to init Focus class device\n");
155             return !Success;
156         }
157         if (jstkInitKeys(dev, priv) != Success)
158             return !Success;
159         break;
160     case DEVICE_ON:
161         DBG(2, ErrorF("jstkKeyboardDeviceControlProc what=DEVICE_ON\n"));
162         dev->public.on = TRUE;
163         break;
164     case DEVICE_OFF:
165         DBG(2, ErrorF("jstkKeyboardDeviceControlProc what=DEVICE_OFF\n"));
166         dev->public.on = FALSE;
167         break;
168     case DEVICE_CLOSE:
169         DBG(2, ErrorF("jstkKeyboardDeviceControlProc what=DEVICE_CLOSE\n"));
170         dev->public.on = FALSE;
171         break;
172     default:
173         return BadValue;
174     }
175 
176     return Success;
177 }
178 
179 
180 /*
181  ***************************************************************************
182  *
183  * jstkKeyboardPreInit --
184  *
185  * See comment in jstkCorePreInit() for details.
186  *
187  ***************************************************************************
188  */
189 
jstkKeyboardPreInit(InputDriverPtr drv,InputInfoPtr pInfo,int flags)190 int jstkKeyboardPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
191 {
192     JoystickDevPtr priv = NULL;
193     char *s;
194 
195     pInfo->private = priv = calloc(1, sizeof(JoystickDevRec));
196     if (!priv)
197         return BadAlloc;
198 
199     pInfo->device_control = jstkKeyboardDeviceControlProc;
200     pInfo->read_input = NULL;
201     pInfo->control_proc = NULL;
202     pInfo->switch_mode = NULL;
203     if (!(pInfo->flags & XI86_SERVER_FD))
204         pInfo->fd = -1;
205     pInfo->type_name = XI_JOYSTICK;
206 
207     /* parse keyboard-related options */
208     priv->repeat_delay = 0;
209     priv->repeat_interval = 0;
210 
211     /* Parse option for autorepeat */
212     if ((s = xf86SetStrOption(pInfo->options, "AutoRepeat", NULL))) {
213         int delay, rate;
214         if (sscanf(s, "%d %d", &delay, &rate) != 2) {
215             xf86Msg(X_ERROR, "%s: \"%s\" is not a valid AutoRepeat value",
216                     pInfo->name, s);
217         } else {
218             priv->repeat_delay = delay;
219             if (rate != 0)
220                 priv->repeat_interval = 1000/rate;
221             else priv->repeat_interval = 0;
222             DBG(1, xf86Msg(X_CONFIG, "Autorepeat set to delay=%d, interval=%d\n",
223                            priv->repeat_delay,priv->repeat_interval));
224         }
225         free(s);
226     }
227 
228     priv->rmlvo.rules = xf86SetStrOption(pInfo->options, "xkb_rules", NULL);
229     if (!priv->rmlvo.rules)
230 	priv->rmlvo.rules = xf86SetStrOption(pInfo->options, "XkbRules", "evdev");
231 
232     priv->rmlvo.model = xf86SetStrOption(pInfo->options, "xkb_model", NULL);
233     if (!priv->rmlvo.model)
234 	priv->rmlvo.model = xf86SetStrOption(pInfo->options, "XkbModel", "evdev");
235 
236     priv->rmlvo.layout = xf86SetStrOption(pInfo->options, "xkb_layout", NULL);
237     if (!priv->rmlvo.layout)
238 	priv->rmlvo.layout = xf86SetStrOption(pInfo->options, "XkbLayout", "us");
239 
240     priv->rmlvo.variant = xf86SetStrOption(pInfo->options, "xkb_variant", NULL);
241     if (!priv->rmlvo.variant)
242 	priv->rmlvo.variant = xf86SetStrOption(pInfo->options, "XkbVariant", "");
243 
244     priv->rmlvo.options = xf86SetStrOption(pInfo->options, "xkb_options", NULL);
245     if (!priv->rmlvo.options)
246 	priv->rmlvo.options = xf86SetStrOption(pInfo->options, "XkbOptions", "");
247 
248     return Success;
249 }
250 
251 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 14
252 static InputOption*
input_option_new(InputOption * list,char * key,char * value)253 input_option_new(InputOption* list, char *key, char *value)
254 {
255     InputOption *tmp;
256 
257     tmp = calloc(1, sizeof(*tmp));
258     tmp->key = key;
259     tmp->value = value;
260     tmp->next = list;
261 
262     return tmp;
263 }
264 
265 static void
input_option_free_list(InputOption ** list)266 input_option_free_list(InputOption **list)
267 {
268     InputOption *iopts = *list;
269 
270     while(iopts)
271     {
272         InputOption *tmp = iopts->next;
273         free(iopts->key);
274         free(iopts->value);
275         free(iopts);
276         iopts = tmp;
277     }
278 
279     *list = NULL;
280 }
281 
282 #endif
283 
284 InputInfoPtr
jstkKeyboardHotplug(InputInfoPtr pInfo,int flags)285 jstkKeyboardHotplug(InputInfoPtr pInfo, int flags)
286 {
287     int rc;
288     char name[512] = {0};
289     InputAttributes *attrs = NULL;
290     InputOption *iopts = NULL;
291     DeviceIntPtr dev;
292     XF86OptionPtr opts;
293 
294     /* duplicate option list, append to name */
295     opts = xf86OptionListDuplicate(pInfo->options);
296     strcpy(name, pInfo->name);
297     strcat(name, " (keys)");
298     opts = xf86ReplaceStrOption(opts, "Name", name);
299     opts = xf86ReplaceStrOption(opts, "_source", "_driver/joystick");
300     opts = xf86AddNewOption(opts, "Driver", pInfo->driver);
301 
302     while(opts)
303     {
304         iopts = input_option_new(iopts,
305                                  xf86OptionName(opts),
306                                  xf86OptionValue(opts));
307         opts = xf86NextOption(opts);
308     }
309 
310     /* duplicate attribute list */
311     attrs = DuplicateInputAttributes(pInfo->attrs);
312 
313     rc = NewInputDeviceRequest(iopts, attrs, &dev);
314 
315     input_option_free_list(&iopts);
316 
317     FreeInputAttributes(attrs);
318 
319     return (rc == Success) ? dev->public.devicePrivate : NULL;
320 }
321 
322 
323 /*
324  ***************************************************************************
325  *
326  * jstkKeyboardUnInit --
327  *
328  * Called when the keyboard slave device gets removed
329  *
330  ***************************************************************************
331  */
332 void
jstkKeyboardUnInit(InputDriverPtr drv,InputInfoPtr pInfo,int flags)333 jstkKeyboardUnInit(InputDriverPtr    drv,
334                    InputInfoPtr      pInfo,
335                    int               flags)
336 {
337     JoystickDevPtr device = (JoystickDevPtr) pInfo->private;
338     DBG(2, ErrorF("jstkKeyboardUnInit.\n"));
339 
340     device->keyboard_device = NULL;
341     pInfo->private = NULL;
342 
343     xf86DeleteInput(pInfo, 0);
344 }
345 
346