wscons.c revision 35c4bbdf
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 <dev/wscons/wsconsio.h> 29#include <dev/wscons/wsksymdef.h> 30 31#include <sys/ioctl.h> 32#include <errno.h> 33#include <string.h> 34#include <unistd.h> 35 36#include "input.h" 37#include "inputstr.h" 38#include "os.h" 39#include "config-backends.h" 40 41#define WSCONS_KBD_DEVICE "/dev/wskbd" 42#define WSCONS_MOUSE_PREFIX "/dev/wsmouse" 43 44#define KB_OVRENC \ 45 { KB_UK, "gb" }, \ 46 { KB_SV, "se" }, \ 47 { KB_SG, "ch" }, \ 48 { KB_SF, "ch" }, \ 49 { KB_LA, "latam" }, \ 50 { KB_CF, "ca" } 51 52struct nameint { 53 int val; 54 char *name; 55} kbdenc[] = { 56 KB_OVRENC, 57 KB_ENCTAB, 58 {0} 59}; 60 61struct nameint kbdvar[] = { 62 {KB_NODEAD | KB_SG, "de_nodeadkeys"}, 63 {KB_NODEAD | KB_SF, "fr_nodeadkeys"}, 64 {KB_SF, "fr"}, 65 {KB_DVORAK | KB_CF, "fr-dvorak"}, 66 {KB_DVORAK | KB_FR, "bepo"}, 67 {KB_DVORAK, "dvorak"}, 68 {KB_CF, "fr-legacy"}, 69 {KB_NODEAD, "nodeadkeys"}, 70 {0} 71}; 72 73struct nameint kbdopt[] = { 74 {KB_SWAPCTRLCAPS, "ctrl:swapcaps"}, 75 {0} 76}; 77 78struct nameint kbdmodel[] = { 79 {WSKBD_TYPE_ZAURUS, "zaurus"}, 80 {0} 81}; 82 83static void 84wscons_add_keyboard(void) 85{ 86 InputAttributes attrs = { }; 87 DeviceIntPtr dev = NULL; 88 InputOption *input_options = NULL; 89 char *config_info = NULL; 90 int fd, i, rc; 91 unsigned int type; 92 kbd_t wsenc = 0; 93 94 /* Find keyboard configuration */ 95 fd = open(WSCONS_KBD_DEVICE, O_RDWR | O_NONBLOCK | O_EXCL); 96 if (fd == -1) { 97 LogMessage(X_ERROR, "wskbd: open %s: %s\n", 98 WSCONS_KBD_DEVICE, strerror(errno)); 99 return; 100 } 101 if (ioctl(fd, WSKBDIO_GETENCODING, &wsenc) == -1) { 102 LogMessage(X_WARNING, "wskbd: ioctl(WSKBDIO_GETENCODING) " 103 "failed: %s\n", strerror(errno)); 104 close(fd); 105 return; 106 } 107 if (ioctl(fd, WSKBDIO_GTYPE, &type) == -1) { 108 LogMessage(X_WARNING, "wskbd: ioctl(WSKBDIO_GTYPE) " 109 "failed: %s\n", strerror(errno)); 110 close(fd); 111 return; 112 } 113 close(fd); 114 115 input_options = input_option_new(input_options, "_source", "server/wscons"); 116 if (input_options == NULL) 117 return; 118 119 LogMessage(X_INFO, "config/wscons: checking input device %s\n", 120 WSCONS_KBD_DEVICE); 121 input_options = input_option_new(input_options, "name", WSCONS_KBD_DEVICE); 122 input_options = input_option_new(input_options, "driver", "kbd"); 123 124 config_info = Xprintf("wscons:%s", WSCONS_KBD_DEVICE); 125 if (!config_info) 126 goto unwind; 127 if (KB_ENCODING(wsenc) == KB_USER) { 128 /* Ignore wscons "user" layout */ 129 LogMessageVerb(X_INFO, 3, "wskbd: ignoring \"user\" layout\n"); 130 goto kbd_config_done; 131 } 132 for (i = 0; kbdenc[i].val; i++) 133 if (KB_ENCODING(wsenc) == kbdenc[i].val) { 134 LogMessageVerb(X_INFO, 3, "wskbd: using layout %s\n", 135 kbdenc[i].name); 136 input_options = input_option_new(input_options, 137 "xkb_layout", kbdenc[i].name); 138 break; 139 } 140 for (i = 0; kbdvar[i].val; i++) 141 if (wsenc == kbdvar[i].val || KB_VARIANT(wsenc) == kbdvar[i].val) { 142 LogMessageVerb(X_INFO, 3, "wskbd: using variant %s\n", 143 kbdvar[i].name); 144 input_options = input_option_new(input_options, 145 "xkb_variant", kbdvar[i].name); 146 break; 147 } 148 for (i = 0; kbdopt[i].val; i++) 149 if (KB_VARIANT(wsenc) == kbdopt[i].val) { 150 LogMessageVerb(X_INFO, 3, "wskbd: using option %s\n", 151 kbdopt[i].name); 152 input_options = input_option_new(input_options, 153 "xkb_options", kbdopt[i].name); 154 break; 155 } 156 for (i = 0; kbdmodel[i].val; i++) 157 if (type == kbdmodel[i].val) { 158 LogMessageVerb(X_INFO, 3, "wskbd: using model %s\n", 159 kbdmodel[i].name); 160 input_options = input_option_new(input_options, 161 "xkb_model", kbdmodel[i].name); 162 break; 163 } 164 165 kbd_config_done: 166 attrs.flags |= ATTR_KEYBOARD; 167 rc = NewInputDeviceRequest(input_options, &attrs, &dev); 168 if (rc != Success) 169 goto unwind; 170 171 for (; dev; dev = dev->next) { 172 free(dev->config_info); 173 dev->config_info = strdup(config_info); 174 } 175 unwind: 176 input_option_free_list(&input_options); 177} 178 179static void 180wscons_add_pointer(const char *path, const char *driver, int flags) 181{ 182 InputAttributes attrs = { }; 183 DeviceIntPtr dev = NULL; 184 InputOption *input_options = NULL; 185 char *config_info = NULL; 186 int rc; 187 188 config_info = Xprintf("wscons:%s", path); 189 if (!config_info) 190 return; 191 192 input_options = input_option_new(input_options, "_source", "server/wscons"); 193 if (input_options == NULL) 194 return; 195 196 input_options = input_option_new(input_options, "name", strdup(path)); 197 input_options = input_option_new(input_options, "driver", strdup(driver)); 198 input_options = input_option_new(input_options, "device", strdup(path)); 199 LogMessage(X_INFO, "config/wscons: checking input device %s\n", path); 200 attrs.flags |= flags; 201 rc = NewInputDeviceRequest(input_options, &attrs, &dev); 202 if (rc != Success) 203 goto unwind; 204 205 for (; dev; dev = dev->next) { 206 free(dev->config_info); 207 dev->config_info = strdup(config_info); 208 } 209 unwind: 210 input_option_free_list(&input_options); 211} 212 213static void 214wscons_add_pointers(void) 215{ 216 char devname[256]; 217 int fd, i, wsmouse_type; 218 219 /* Check pointing devices */ 220 for (i = 0; i < 4; i++) { 221 snprintf(devname, sizeof(devname), "%s%d", WSCONS_MOUSE_PREFIX, i); 222 LogMessageVerb(X_INFO, 10, "wsmouse: checking %s\n", devname); 223 fd = open_device(devnamem O_RDWR | O_NONBLOCK | O_EXCL); 224 if (fd == -1) { 225 LogMessageVerb(X_WARNING, 10, "%s: %s\n", devname, strerror(errno)); 226 continue; 227 } 228 if (ioctl(fd, WSMOUSEIO_GTYPE, &wsmouse_type) != 0) { 229 LogMessageVerb(X_WARNING, 10, 230 "%s: WSMOUSEIO_GTYPE failed\n", devname); 231 close(fd); 232 continue; 233 } 234 close(fd); 235 switch (wsmouse_type) { 236 case WSMOUSE_TYPE_SYNAPTICS: 237 wscons_add_pointer(devname, "synaptics", ATTR_TOUCHPAD); 238 break; 239 case WSMOUSE_TYPE_TPANEL: 240 wscons_add_pointer(devname, "ws", ATTR_TOUCHSCREEN); 241 break; 242 default: 243 break; 244 } 245 } 246 /* Add a default entry catching all other mux elements as "mouse" */ 247 wscons_add_pointer(WSCONS_MOUSE_PREFIX, "mouse", ATTR_POINTER); 248} 249 250int 251config_wscons_init(void) 252{ 253 wscons_add_keyboard(); 254 wscons_add_pointers(); 255 return 1; 256} 257 258void 259config_wscons_fini(void) 260{ 261 /* Not much to do ? */ 262} 263