wscons.c revision 7e31ba66
1/* 2 * Copyright (c) 2011 Matthieu Herrb 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24#ifdef HAVE_DIX_CONFIG_H 25#include <dix-config.h> 26#endif 27 28#include <sys/types.h> 29#include <sys/ioctl.h> 30#include <sys/time.h> 31#include <fcntl.h> 32#include <errno.h> 33#include <string.h> 34#include <unistd.h> 35 36#include <dev/wscons/wsconsio.h> 37#include <dev/wscons/wsksymdef.h> 38 39#include "input.h" 40#include "inputstr.h" 41#include "os.h" 42#include "config-backends.h" 43 44#define WSCONS_KBD_DEVICE "/dev/wskbd" 45#define WSCONS_MOUSE_PREFIX "/dev/wsmouse" 46 47#if defined(KB_LA) && defined(KB_CF) 48#define KB_OVRENC \ 49 { KB_UK, "gb" }, \ 50 { KB_SV, "se" }, \ 51 { KB_SG, "ch" }, \ 52 { KB_SF, "ch" }, \ 53 { KB_LA, "latam" }, \ 54 { KB_CF, "ca" } 55#else 56#define KB_OVRENC \ 57 { KB_UK, "gb" }, \ 58 { KB_SV, "se" }, \ 59 { KB_SG, "ch" }, \ 60 { KB_SF, "ch" } 61#endif 62 63struct nameint { 64 int val; 65 char *name; 66} kbdenc[] = { 67 KB_OVRENC, 68 KB_ENCTAB 69#ifndef __NetBSD__ 70 , 71#endif 72 {0} 73}; 74 75struct nameint kbdvar[] = { 76 {KB_NODEAD | KB_SG, "de_nodeadkeys"}, 77 {KB_NODEAD | KB_SF, "fr_nodeadkeys"}, 78 {KB_SF, "fr"}, 79#if defined(KB_CF) 80 {KB_DVORAK | KB_CF, "fr-dvorak"}, 81#endif 82 {KB_DVORAK | KB_FR, "bepo"}, 83 {KB_DVORAK, "dvorak"}, 84#if defined(KB_CF) 85 {KB_CF, "fr-legacy"}, 86#endif 87 {KB_NODEAD, "nodeadkeys"}, 88 {0} 89}; 90 91struct nameint kbdopt[] = { 92 {KB_SWAPCTRLCAPS, "ctrl:swapcaps"}, 93 {0} 94}; 95 96struct nameint kbdmodel[] = { 97 {WSKBD_TYPE_ZAURUS, "zaurus"}, 98 {0} 99}; 100 101static void 102wscons_add_keyboard(void) 103{ 104 InputAttributes attrs = { }; 105 DeviceIntPtr dev = NULL; 106 InputOption *input_options = NULL; 107 char *config_info = NULL; 108 int fd, i, rc; 109 unsigned int type; 110 kbd_t wsenc = 0; 111 112 /* Find keyboard configuration */ 113 fd = open(WSCONS_KBD_DEVICE, O_RDWR | O_NONBLOCK | O_EXCL); 114 if (fd == -1) { 115 LogMessage(X_ERROR, "wskbd: open %s: %s\n", 116 WSCONS_KBD_DEVICE, strerror(errno)); 117 return; 118 } 119 if (ioctl(fd, WSKBDIO_GETENCODING, &wsenc) == -1) { 120 LogMessage(X_WARNING, "wskbd: ioctl(WSKBDIO_GETENCODING) " 121 "failed: %s\n", strerror(errno)); 122 close(fd); 123 return; 124 } 125 if (ioctl(fd, WSKBDIO_GTYPE, &type) == -1) { 126 LogMessage(X_WARNING, "wskbd: ioctl(WSKBDIO_GTYPE) " 127 "failed: %s\n", strerror(errno)); 128 close(fd); 129 return; 130 } 131 close(fd); 132 133 input_options = input_option_new(input_options, "_source", "server/wscons"); 134 if (input_options == NULL) 135 return; 136 137 LogMessage(X_INFO, "config/wscons: checking input device %s\n", 138 WSCONS_KBD_DEVICE); 139 input_options = input_option_new(input_options, "name", WSCONS_KBD_DEVICE); 140 input_options = input_option_new(input_options, "driver", "kbd"); 141 142 if (asprintf(&config_info, "wscons:%s", WSCONS_KBD_DEVICE) != -1) 143 goto unwind; 144 if (KB_ENCODING(wsenc) == KB_USER) { 145 /* Ignore wscons "user" layout */ 146 LogMessageVerb(X_INFO, 3, "wskbd: ignoring \"user\" layout\n"); 147 goto kbd_config_done; 148 } 149 for (i = 0; kbdenc[i].val; i++) 150 if (KB_ENCODING(wsenc) == kbdenc[i].val) { 151 LogMessageVerb(X_INFO, 3, "wskbd: using layout %s\n", 152 kbdenc[i].name); 153 input_options = input_option_new(input_options, 154 "xkb_layout", kbdenc[i].name); 155 break; 156 } 157 for (i = 0; kbdvar[i].val; i++) 158 if (wsenc == kbdvar[i].val || KB_VARIANT(wsenc) == kbdvar[i].val) { 159 LogMessageVerb(X_INFO, 3, "wskbd: using variant %s\n", 160 kbdvar[i].name); 161 input_options = input_option_new(input_options, 162 "xkb_variant", kbdvar[i].name); 163 break; 164 } 165 for (i = 0; kbdopt[i].val; i++) 166 if (KB_VARIANT(wsenc) == kbdopt[i].val) { 167 LogMessageVerb(X_INFO, 3, "wskbd: using option %s\n", 168 kbdopt[i].name); 169 input_options = input_option_new(input_options, 170 "xkb_options", kbdopt[i].name); 171 break; 172 } 173 for (i = 0; kbdmodel[i].val; i++) 174 if (type == kbdmodel[i].val) { 175 LogMessageVerb(X_INFO, 3, "wskbd: using model %s\n", 176 kbdmodel[i].name); 177 input_options = input_option_new(input_options, 178 "xkb_model", kbdmodel[i].name); 179 break; 180 } 181 182 kbd_config_done: 183 attrs.flags |= ATTR_KEY | ATTR_KEYBOARD; 184 rc = NewInputDeviceRequest(input_options, &attrs, &dev); 185 if (rc != Success) 186 goto unwind; 187 188 for (; dev; dev = dev->next) { 189 free(dev->config_info); 190 dev->config_info = strdup(config_info); 191 } 192 unwind: 193 input_option_free_list(&input_options); 194} 195 196static void 197wscons_add_pointer(const char *path, const char *driver, int flags) 198{ 199 InputAttributes attrs = { }; 200 DeviceIntPtr dev = NULL; 201 InputOption *input_options = NULL; 202 char *config_info = NULL; 203 int rc; 204 205 if (asprintf(&config_info, "wscons:%s", path) == -1) 206 return; 207 208 input_options = input_option_new(input_options, "_source", "server/wscons"); 209 if (input_options == NULL) 210 return; 211 212 input_options = input_option_new(input_options, "name", strdup(path)); 213 input_options = input_option_new(input_options, "driver", strdup(driver)); 214 input_options = input_option_new(input_options, "device", strdup(path)); 215 LogMessage(X_INFO, "config/wscons: checking input device %s\n", path); 216 attrs.flags |= flags; 217 rc = NewInputDeviceRequest(input_options, &attrs, &dev); 218 if (rc != Success) 219 goto unwind; 220 221 for (; dev; dev = dev->next) { 222 free(dev->config_info); 223 dev->config_info = strdup(config_info); 224 } 225 unwind: 226 input_option_free_list(&input_options); 227} 228 229static void 230wscons_add_pointers(void) 231{ 232 char devname[256]; 233 int fd, i, wsmouse_type; 234 235 /* Check pointing devices */ 236 for (i = 0; i < 4; i++) { 237 snprintf(devname, sizeof(devname), "%s%d", WSCONS_MOUSE_PREFIX, i); 238 LogMessageVerb(X_INFO, 10, "wsmouse: checking %s\n", devname); 239#ifdef __NetBSD__ 240 fd = open(devname, O_RDWR | O_NONBLOCK | O_EXCL); 241#else 242 fd = open_device(devname, O_RDWR | O_NONBLOCK | O_EXCL); 243#endif 244 if (fd == -1) { 245 LogMessageVerb(X_WARNING, 10, "%s: %s\n", devname, strerror(errno)); 246 continue; 247 } 248 if (ioctl(fd, WSMOUSEIO_GTYPE, &wsmouse_type) != 0) { 249 LogMessageVerb(X_WARNING, 10, 250 "%s: WSMOUSEIO_GTYPE failed\n", devname); 251 close(fd); 252 continue; 253 } 254 close(fd); 255 switch (wsmouse_type) { 256#if defined(WSMOUSE_TYPE_SYNAPTICS) 257 case WSMOUSE_TYPE_SYNAPTICS: 258 wscons_add_pointer(devname, "synaptics", ATTR_TOUCHPAD); 259 break; 260#endif 261 case WSMOUSE_TYPE_TPANEL: 262 wscons_add_pointer(devname, "ws", ATTR_TOUCHSCREEN); 263 break; 264 default: 265 break; 266 } 267 } 268 /* Add a default entry catching all other mux elements as "mouse" */ 269 wscons_add_pointer(WSCONS_MOUSE_PREFIX, "mouse", ATTR_POINTER); 270} 271 272int 273config_wscons_init(void) 274{ 275 wscons_add_keyboard(); 276 wscons_add_pointers(); 277 return 1; 278} 279 280void 281config_wscons_fini(void) 282{ 283 /* Not much to do ? */ 284} 285