1 /***************************************************************************
3 * probe-xkb.c : Probe for keyboard device information
5 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
6 * Use is subject to license terms.
8 * Licensed under the Academic Free License version 2.1
10 **************************************************************************/
22 #include <sys/ioctl.h>
23 #include <sys/stropts.h>
34 #define MAXLINELEN 256
35 #define COMMENTCHAR '#'
36 #define KBD_DEFAULT_DEVICE "/dev/kbd"
37 #define XKBTABLE_PATH "/usr/X11/lib/X11/xkb/xkbtable.map"
39 static int global_linenumber
= 0;
40 static char line
[MAXLINELEN
+ 1];
45 priv_set_t
*pPrivSet
= NULL
;
46 priv_set_t
*lPrivSet
= NULL
;
49 * Start with the 'basic' privilege set and then remove any
50 * of the 'basic' privileges that will not be needed.
52 if ((pPrivSet
= priv_str_to_set("basic", ",", NULL
)) == NULL
) {
53 HAL_INFO(("Error in setting the priv"));
57 /* Clear privileges we will not need from the 'basic' set */
58 (void) priv_delset(pPrivSet
, PRIV_FILE_LINK_ANY
);
59 (void) priv_delset(pPrivSet
, PRIV_PROC_INFO
);
60 (void) priv_delset(pPrivSet
, PRIV_PROC_SESSION
);
61 (void) priv_delset(pPrivSet
, PRIV_PROC_EXEC
);
62 (void) priv_delset(pPrivSet
, PRIV_PROC_FORK
);
64 (void) priv_addset(pPrivSet
, PRIV_SYS_DEVICES
);
65 (void) priv_addset(pPrivSet
, PRIV_FILE_DAC_READ
);
67 /* Set the permitted privilege set. */
68 if (setppriv(PRIV_SET
, PRIV_PERMITTED
, pPrivSet
) != 0) {
72 /* Clear the limit set. */
73 if ((lPrivSet
= priv_allocset()) == NULL
) {
77 priv_emptyset(lPrivSet
);
79 if (setppriv(PRIV_SET
, PRIV_LIMIT
, lPrivSet
) != 0) {
83 priv_freeset(lPrivSet
);
84 priv_freeset(pPrivSet
);
88 get_kbd_layout_type(char *device_file
, int *kbd_type
, int *kbd_layout
)
93 if ((fd
= open(device_file
, O_RDONLY
| O_NONBLOCK
)) < 0) {
94 HAL_DEBUG(("Cannot open %s: %s", device_file
, strerror(errno
)));
99 * For usb keyboard devices, we need to first push "usbkbm" module upon
102 if (strstr(device_file
, "hid") != NULL
) {
103 if (ioctl(fd
, I_FIND
, "usbkbm") == 0) {
104 (void) ioctl(fd
, I_PUSH
, "usbkbm");
105 HAL_DEBUG(("usbkbm module has been pushed %s", strerror(errno
)));
109 if (ioctl(fd
, KIOCTYPE
, kbd_type
) < 0) {
110 HAL_DEBUG(("get keyboard type failed %s: %s",
111 device_file
, strerror(errno
)));
114 if (ioctl(fd
, KIOCLAYOUT
, kbd_layout
) < 0) {
115 HAL_DEBUG(("get keyboard layout failed %s: %s",
116 device_file
, strerror(errno
)));
129 /* Skips over the white space character in the string. */
133 while ((*ptr
== ' ') || (*ptr
== '\t')) {
137 /* This should not occur. but .. */
154 ptr
= fgets(line
, MAXLINELEN
, fp
);
163 if (ptr
[0] == COMMENTCHAR
) {
168 if (ptr
[0] == '\n') {
172 if ((tmp
= strchr(ptr
, '#')) != NULL
) {
176 if (ptr
[strlen(ptr
) - 1] == '\n') {
177 /* get rid of '\n' */
178 ptr
[strlen(ptr
) - 1] = '\0';
181 ptr
= skipwhite(ptr
);
190 sun_find_xkbnames(int kb_type
, int kb_layout
, char **xkb_keymap
,
191 char **xkb_model
, char **xkb_layout
)
193 const char *type
, *layout
;
194 char *keymap
, *defkeymap
= NULL
;
195 char *model
, *defmodel
= NULL
;
196 char *xkblay
, *defxkblay
= NULL
;
198 int found_error
= 0, found_keytable
= 0;
201 if ((fp
= fopen(XKBTABLE_PATH
, "r")) == NULL
) {
205 global_linenumber
= 0;
206 while (getaline(fp
)) {
207 if ((type
= strtok(line
, " \t\n")) == NULL
) {
211 if ((layout
= strtok(NULL
, " \t\n")) == NULL
) {
215 if ((keymap
= strtok(NULL
, " \t\n")) == NULL
) {
219 /* These two are optional entries */
220 model
= strtok(NULL
, " \t\n");
221 if ((model
== NULL
) || (*model
== COMMENTCHAR
)) {
222 model
= xkblay
= NULL
;
224 xkblay
= strtok(NULL
, " \t\n");
225 if ((xkblay
!= NULL
) && (*xkblay
== COMMENTCHAR
)) {
235 /* record default entry if/when found */
237 if (defkeymap
== NULL
) {
238 defkeymap
= strdup(keymap
);
239 defmodel
= strdup(model
);
240 defxkblay
= strdup(xkblay
);
242 } else if (atoi(type
) == kb_type
) {
243 if (*layout
== '*') {
244 defkeymap
= strdup(keymap
);
245 defmodel
= strdup(model
);
246 defxkblay
= strdup(xkblay
);
247 } else if (atoi(layout
) == kb_layout
) {
256 if (!found_keytable
) {
262 if ((keymap
!= NULL
) && (strcmp(keymap
, "-") != 0)) {
263 *xkb_keymap
= keymap
;
265 if ((model
!= NULL
) && (strcmp(model
, "-") != 0)) {
268 if ((xkblay
!= NULL
) && (strcmp(xkblay
, "-") != 0)) {
269 *xkb_layout
= xkblay
;
276 main(int argc
, char *argv
[])
281 LibHalContext
*ctx
= NULL
;
282 LibHalChangeSet
*cs
= NULL
;
284 int kbd_type
, kbd_layout
;
285 char *xkbkeymap
= NULL
, *xkbmodel
= NULL
, *xkblayout
= NULL
;
287 if ((udi
= getenv("UDI")) == NULL
) {
291 if ((device_file
= getenv("HAL_PROP_INPUT_DEVICE")) == NULL
) {
298 dbus_error_init(&error
);
299 if ((ctx
= libhal_ctx_init_direct(&error
)) == NULL
) {
303 if ((cs
= libhal_device_new_changeset(udi
)) == NULL
) {
304 HAL_DEBUG(("Cannot allocate changeset"));
308 HAL_DEBUG(("Doing probe-xkb for %s (udi=%s)", device_file
, udi
));
310 if (get_kbd_layout_type(device_file
, &kbd_type
, &kbd_layout
)) {
315 * For some usb keyboard that is not self-identifying, get keyboard's
316 * layout and type from system default keyboard device--/dev/kbd.
318 if ((kbd_layout
== 0) && (strstr(device_file
, "hid") != NULL
)) {
319 if (get_kbd_layout_type(KBD_DEFAULT_DEVICE
,
320 &kbd_type
, &kbd_layout
)) {
325 if (sun_find_xkbnames(kbd_type
, kbd_layout
,
326 &xkbkeymap
, &xkbmodel
, &xkblayout
)) {
331 * If doesn't find matching entry in xkbtable.map, using default
332 * values setting in 10-x11-input.fdi
334 if ((xkbmodel
!= NULL
) && (xkblayout
!= NULL
)) {
335 libhal_changeset_set_property_string(cs
,
336 "input.x11_options.XkbModel", xkbmodel
);
337 libhal_changeset_set_property_string(cs
,
338 "input.x11_options.XkbLayout", xkblayout
);
340 libhal_device_commit_changeset(ctx
, cs
, &error
);
347 libhal_device_free_changeset(cs
);
351 libhal_ctx_shutdown(ctx
, &error
);
352 libhal_ctx_free(ctx
);
353 if (dbus_error_is_set(&error
)) {
354 dbus_error_free(&error
);