static void wscons_add_pointer(const char *path, const char *driver, int flags) { InputAttributes attrs = { }; DeviceIntPtr dev = NULL; InputOption *input_options = NULL; char *config_info = NULL; int rc; config_info = Xprintf("wscons:%s", path); if (!config_info) return; input_options = input_option_new(input_options, "_source", "server/wscons"); if (input_options == NULL) return; input_options = input_option_new(input_options, "name", strdup(path)); input_options = input_option_new(input_options, "driver", strdup(driver)); input_options = input_option_new(input_options, "device", strdup(path)); LogMessage(X_INFO, "config/wscons: checking input device %s\n", path); attrs.flags |= flags; rc = NewInputDeviceRequest(input_options, &attrs, &dev); if (rc != Success) goto unwind; for (; dev; dev = dev->next) { free(dev->config_info); dev->config_info = strdup(config_info); } unwind: input_option_free_list(&input_options); }
/** * Initialize all supported input devices present and referenced in the * xorg.conf. */ void InitInput(int argc, char **argv) { InputInfoPtr *pInfo; DeviceIntPtr dev; xf86Info.vtRequestsPending = FALSE; /* Enable threaded input */ InputThreadPreInit(); mieqInit(); /* Initialize all configured input devices */ for (pInfo = xf86ConfigLayout.inputs; pInfo && *pInfo; pInfo++) { (*pInfo)->options = xf86AddNewOption((*pInfo)->options, "driver", (*pInfo)->driver); (*pInfo)->options = xf86AddNewOption((*pInfo)->options, "identifier", (*pInfo)->name); /* If one fails, the others will too */ if (NewInputDeviceRequest((*pInfo)->options, NULL, &dev) == BadAlloc) break; } config_init(); }
/** * Initialize all supported input devices present and referenced in the * xorg.conf. */ void InitInput(int argc, char **argv) { InputInfoPtr* pInfo; DeviceIntPtr dev; xf86Info.vtRequestsPending = FALSE; mieqInit(); /* Initialize all configured input devices */ for (pInfo = xf86ConfigLayout.inputs; pInfo && *pInfo; pInfo++) { /* If one fails, the others will too */ if (NewInputDeviceRequest((*pInfo)->options, NULL, &dev) == BadAlloc) break; } config_init(); }
static void device_added(LibHalContext *hal_ctx, const char *udi) { char *path = NULL, *driver = NULL, *name = NULL, *config_info = NULL; InputOption *options = NULL, *tmpo = NULL; DeviceIntPtr dev = NULL; DBusError error; struct xkb_options xkb_opts = {0}; int rc; LibHalPropertySet *set = NULL; LibHalPropertySetIterator set_iter; char *psi_key = NULL, *tmp_val; dbus_error_init(&error); driver = get_prop_string(hal_ctx, udi, "input.x11_driver"); if (!driver){ /* verbose, don't tell the user unless they _want_ to see it */ LogMessageVerb(X_INFO,7,"config/hal: no driver specified for device %s\n", udi); goto unwind; } path = get_prop_string(hal_ctx, udi, "input.device"); if (!path) { LogMessage(X_WARNING,"config/hal: no driver or path specified for %s\n", udi); goto unwind; } name = get_prop_string(hal_ctx, udi, "info.product"); if (!name) name = xstrdup("(unnamed)"); options = xcalloc(sizeof(*options), 1); if (!options){ LogMessage(X_ERROR, "config/hal: couldn't allocate space for input options!\n"); goto unwind; } options->key = xstrdup("_source"); options->value = xstrdup("server/hal"); if (!options->key || !options->value) { LogMessage(X_ERROR, "config/hal: couldn't allocate first key/value pair\n"); goto unwind; } /* most drivers use device.. not path. evdev uses both however, but the * path version isn't documented apparently. support both for now. */ add_option(&options, "path", path); add_option(&options, "device", path); add_option(&options, "driver", driver); add_option(&options, "name", name); config_info = xalloc(strlen(udi) + 5); /* "hal:" and NULL */ if (!config_info) { LogMessage(X_ERROR, "config/hal: couldn't allocate name\n"); goto unwind; } sprintf(config_info, "hal:%s", udi); /* Check for duplicate devices */ if (device_is_duplicate(config_info)) { LogMessage(X_WARNING, "config/hal: device %s already added. Ignoring.\n", name); goto unwind; } /* ok, grab options from hal.. iterate through all properties * and lets see if any of them are options that we can add */ set = libhal_device_get_all_properties(hal_ctx, udi, &error); if (!set) { LogMessage(X_ERROR, "config/hal: couldn't get property list for %s: %s (%s)\n", udi, error.name, error.message); goto unwind; } libhal_psi_init(&set_iter,set); while (libhal_psi_has_more(&set_iter)) { /* we are looking for supported keys.. extract and add to options */ psi_key = libhal_psi_get_key(&set_iter); if (psi_key){ /* normal options first (input.x11_options.<propname>) */ if (!strncasecmp(psi_key, LIBHAL_PROP_KEY, sizeof(LIBHAL_PROP_KEY)-1)){ char* tmp; /* only support strings for all values */ tmp_val = get_prop_string(hal_ctx, udi, psi_key); if (tmp_val){ /* xkb needs special handling. HAL specs include * input.xkb.xyz options, but the x11-input.fdi specifies * input.x11_options.Xkbxyz options. By default, we use * the former, unless the specific X11 ones are specified. * Since we can't predict the order in which the keys * arrive, we need to store them. */ if ((tmp = strcasestr(psi_key, "xkb")) && strlen(tmp) >= 4) { if (!strcasecmp(&tmp[3], "layout")) { if (xkb_opts.layout) xfree(xkb_opts.layout); xkb_opts.layout = strdup(tmp_val); } else if (!strcasecmp(&tmp[3], "model")) { if (xkb_opts.model) xfree(xkb_opts.model); xkb_opts.model = strdup(tmp_val); } else if (!strcasecmp(&tmp[3], "rules")) { if (xkb_opts.rules) xfree(xkb_opts.rules); xkb_opts.rules = strdup(tmp_val); } else if (!strcasecmp(&tmp[3], "variant")) { if (xkb_opts.variant) xfree(xkb_opts.variant); xkb_opts.variant = strdup(tmp_val); } else if (!strcasecmp(&tmp[3], "options")) { if (xkb_opts.options) xfree(xkb_opts.options); xkb_opts.options = strdup(tmp_val); } } else { /* all others */ add_option(&options, psi_key + sizeof(LIBHAL_PROP_KEY)-1, tmp_val); xfree(tmp_val); } } else { /* server 1.4 had xkb_options as strlist. */ if ((tmp = strcasestr(psi_key, "xkb")) && (strlen(tmp) >= 4) && (!strcasecmp(&tmp[3], "options")) && (tmp_val = get_prop_string_array(hal_ctx, udi, psi_key))) { if (xkb_opts.options) xfree(xkb_opts.options); xkb_opts.options = strdup(tmp_val); } } } else if (!strncasecmp(psi_key, LIBHAL_XKB_PROP_KEY, sizeof(LIBHAL_XKB_PROP_KEY)-1)){ char* tmp; /* only support strings for all values */ tmp_val = get_prop_string(hal_ctx, udi, psi_key); if (tmp_val && strlen(psi_key) >= sizeof(LIBHAL_XKB_PROP_KEY)) { tmp = &psi_key[sizeof(LIBHAL_XKB_PROP_KEY) - 1]; if (!strcasecmp(tmp, "layout")) { if (!xkb_opts.layout) xkb_opts.layout = strdup(tmp_val); } else if (!strcasecmp(tmp, "rules")) { if (!xkb_opts.rules) xkb_opts.rules = strdup(tmp_val); } else if (!strcasecmp(tmp, "variant")) { if (!xkb_opts.variant) xkb_opts.variant = strdup(tmp_val); } else if (!strcasecmp(tmp, "model")) { if (!xkb_opts.model) xkb_opts.model = strdup(tmp_val); } else if (!strcasecmp(tmp, "options")) { if (!xkb_opts.options) xkb_opts.options = strdup(tmp_val); } xfree(tmp_val); } else { /* server 1.4 had xkb options as strlist */ tmp_val = get_prop_string_array(hal_ctx, udi, psi_key); if (tmp_val && strlen(psi_key) >= sizeof(LIBHAL_XKB_PROP_KEY)) { tmp = &psi_key[sizeof(LIBHAL_XKB_PROP_KEY) - 1]; if (!strcasecmp(tmp, ".options") && (!xkb_opts.options)) xkb_opts.options = strdup(tmp_val); } } } } /* psi_key doesn't need to be freed */ libhal_psi_next(&set_iter); } /* Now add xkb options */ if (xkb_opts.layout) add_option(&options, "xkb_layout", xkb_opts.layout); if (xkb_opts.rules) add_option(&options, "xkb_rules", xkb_opts.rules); if (xkb_opts.variant) add_option(&options, "xkb_variant", xkb_opts.variant); if (xkb_opts.model) add_option(&options, "xkb_model", xkb_opts.model); if (xkb_opts.options) add_option(&options, "xkb_options", xkb_opts.options); /* this isn't an error, but how else do you output something that the user can see? */ LogMessage(X_INFO, "config/hal: Adding input device %s\n", name); if ((rc = NewInputDeviceRequest(options, &dev)) != Success) { LogMessage(X_ERROR, "config/hal: NewInputDeviceRequest failed (%d)\n", rc); dev = NULL; goto unwind; } for (; dev; dev = dev->next){ if (dev->config_info) xfree(dev->config_info); dev->config_info = xstrdup(config_info); } unwind: if (set) libhal_free_property_set(set); if (path) xfree(path); if (driver) xfree(driver); if (name) xfree(name); if (config_info) xfree(config_info); while (!dev && (tmpo = options)) { options = tmpo->next; xfree(tmpo->key); xfree(tmpo->value); xfree(tmpo); } if (xkb_opts.layout) xfree(xkb_opts.layout); if (xkb_opts.rules) xfree(xkb_opts.rules); if (xkb_opts.model) xfree(xkb_opts.model); if (xkb_opts.variant) xfree(xkb_opts.variant); if (xkb_opts.options) xfree(xkb_opts.options); dbus_error_free(&error); return; }
static void wscons_add_keyboard(void) { InputAttributes attrs = { }; DeviceIntPtr dev = NULL; InputOption *input_options = NULL; char *config_info = NULL; int fd, i, rc; unsigned int type; kbd_t wsenc = 0; /* Find keyboard configuration */ fd = priv_open_device(WSCONS_KBD_DEVICE); if (fd == -1) { LogMessage(X_ERROR, "wskbd: open %s: %s\n", WSCONS_KBD_DEVICE, strerror(errno)); return; } if (ioctl(fd, WSKBDIO_GETENCODING, &wsenc) == -1) { LogMessage(X_WARNING, "wskbd: ioctl(WSKBDIO_GETENCODING) " "failed: %s\n", strerror(errno)); close(fd); return; } if (ioctl(fd, WSKBDIO_GTYPE, &type) == -1) { LogMessage(X_WARNING, "wskbd: ioctl(WSKBDIO_GTYPE) " "failed: %s\n", strerror(errno)); close(fd); return; } close (fd); input_options = input_option_new(input_options, "_source", "server/wscons"); if (input_options == NULL) return; LogMessage(X_INFO, "config/wscons: checking input device %s\n", WSCONS_KBD_DEVICE); input_options = input_option_new(input_options, "name", WSCONS_KBD_DEVICE); input_options = input_option_new(input_options, "driver", "kbd"); config_info = Xprintf("wscons:%s", WSCONS_KBD_DEVICE); if (!config_info) goto unwind; if (KB_ENCODING(wsenc) == KB_USER) { /* Ignore wscons "user" layout */ LogMessageVerb(X_INFO, 3, "wskbd: ignoring \"user\" layout\n"); goto kbd_config_done; } for (i = 0; kbdenc[i].val; i++) if (KB_ENCODING(wsenc) == kbdenc[i].val) { LogMessageVerb(X_INFO, 3, "wskbd: using layout %s\n", kbdenc[i].name); input_options = input_option_new(input_options, "xkb_layout", kbdenc[i].name); break; } for (i = 0; kbdvar[i].val; i++) if (wsenc == kbdvar[i].val || KB_VARIANT(wsenc) == kbdvar[i].val) { LogMessageVerb(X_INFO, 3, "wskbd: using variant %s\n", kbdvar[i].name); input_options = input_option_new(input_options, "xkb_variant", kbdvar[i].name); break; } for (i = 0; kbdopt[i].val; i++) if (KB_VARIANT(wsenc) == kbdopt[i].val) { LogMessageVerb(X_INFO, 3, "wskbd: using option %s\n", kbdopt[i].name); input_options = input_option_new(input_options, "xkb_options", kbdopt[i].name); break; } for (i = 0; kbdmodel[i].val; i++) if (type == kbdmodel[i].val) { LogMessageVerb(X_INFO, 3, "wskbd: using model %s\n", kbdmodel[i].name); input_options = input_option_new(input_options, "xkb_model", kbdmodel[i].name); break; } kbd_config_done: attrs.flags |= ATTR_KEYBOARD; rc = NewInputDeviceRequest(input_options, &attrs, &dev); if (rc != Success) goto unwind; for (; dev; dev = dev->next) { free(dev->config_info); dev->config_info = strdup(config_info); } unwind: input_option_free_list(&input_options); }
LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_TABLET; } else if (!strcmp(key, "ID_INPUT_TOUCHPAD")) { LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_TOUCHPAD; } else if (!strcmp(key, "ID_INPUT_TOUCHSCREEN")) { LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_TOUCHSCREEN; } } add_option(&options, "config_info", config_info); LogMessage(X_INFO, "config/udev: Adding input device %s (%s)\n", name, path); rc = NewInputDeviceRequest(options, &attrs, &dev); if (rc != Success) goto unwind; unwind: free(config_info); while ((tmpo = options)) { options = tmpo->next; free(tmpo->key); /* NULL if dev != NULL */ free(tmpo->value); /* NULL if dev != NULL */ free(tmpo); } free(attrs.usb_id); free(attrs.pnp_id); free(attrs.product);
static int add_device(DBusMessage *message, DBusMessage *reply, DBusError *error) { DBusMessageIter iter, reply_iter, subiter; InputOption *tmpo = NULL, *options = NULL; char *tmp = NULL; int ret, err; DeviceIntPtr dev = NULL; dbus_message_iter_init_append(reply, &reply_iter); if (!dbus_message_iter_init(message, &iter)) { ErrorF("[config/dbus] couldn't initialise iterator\n"); MALFORMED_MESSAGE(); } options = xcalloc(sizeof(*options), 1); if (!options) { ErrorF("[config/dbus] couldn't allocate option\n"); return BadAlloc; } options->key = xstrdup("_source"); options->value = xstrdup("client/dbus"); if (!options->key || !options->value) { ErrorF("[config/dbus] couldn't allocate first key/value pair\n"); ret = BadAlloc; goto unwind; } /* signature should be [ss][ss]... */ while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY) { tmpo = xcalloc(sizeof(*tmpo), 1); if (!tmpo) { ErrorF("[config/dbus] couldn't allocate option\n"); ret = BadAlloc; goto unwind; } tmpo->next = options; options = tmpo; dbus_message_iter_recurse(&iter, &subiter); if (dbus_message_iter_get_arg_type(&subiter) != DBUS_TYPE_STRING) MALFORMED_MESSAGE(); dbus_message_iter_get_basic(&subiter, &tmp); if (!tmp) MALFORMED_MESSAGE(); /* The _ prefix refers to internal settings, and may not be given by * the client. */ if (tmp[0] == '_') { ErrorF("[config/dbus] attempted subterfuge: option name %s given\n", tmp); MALFORMED_MESSAGE(); } options->key = xstrdup(tmp); if (!options->key) { ErrorF("[config/dbus] couldn't duplicate key!\n"); ret = BadAlloc; goto unwind; } if (!dbus_message_iter_has_next(&subiter)) MALFORMED_MESSAGE(); dbus_message_iter_next(&subiter); if (dbus_message_iter_get_arg_type(&subiter) != DBUS_TYPE_STRING) MALFORMED_MESSAGE(); dbus_message_iter_get_basic(&subiter, &tmp); if (!tmp) MALFORMED_MESSAGE(); options->value = xstrdup(tmp); if (!options->value) { ErrorF("[config/dbus] couldn't duplicate option!\n"); ret = BadAlloc; goto unwind; } dbus_message_iter_next(&iter); } ret = NewInputDeviceRequest(options, &dev); if (ret != Success) { DebugF("[config/dbus] NewInputDeviceRequest failed\n"); goto unwind; } if (!dev) { DebugF("[config/dbus] NewInputDeviceRequest provided no device\n"); ret = BadImplementation; goto unwind; } /* XXX: If we fail halfway through, we don't seem to have any way to * empty the iterator, so you'll end up with some device IDs, * plus an error. This seems to be a shortcoming in the D-Bus * API. */ for (; dev; dev = dev->next) { if (!dbus_message_iter_append_basic(&reply_iter, DBUS_TYPE_INT32, &dev->id)) { ErrorF("[config/dbus] couldn't append to iterator\n"); ret = BadAlloc; goto unwind; } } unwind: if (ret != Success) { if (dev) RemoveDevice(dev); err = -ret; dbus_message_iter_append_basic(&reply_iter, DBUS_TYPE_INT32, &err); } while (options) { tmpo = options; options = options->next; if (tmpo->key) xfree(tmpo->key); if (tmpo->value) xfree(tmpo->value); xfree(tmpo); } return ret; }
static void device_added(LibHalContext *hal_ctx, const char *udi) { char **props; /* Cleverly, these are currently all leaked. */ char *path = NULL, *driver = NULL, *name = NULL, *xkb_rules = NULL; char *xkb_model = NULL, *xkb_layout = NULL, *xkb_variant = NULL; char **xkb_options = NULL; DBusError error; struct xserver_option *options = NULL; int type = TYPE_NONE; int i; DeviceIntPtr dev = NULL; dbus_error_init(&error); props = libhal_device_get_property_strlist(hal_ctx, udi, "info.capabilities", &error); if (!props) { DebugF("[config/hal] couldn't get capabilities for %s: %s (%s)\n", udi, error.name, error.message); goto out_error; } for (i = 0; props[i]; i++) { /* input.keys is the new, of which input.keyboard is a subset, but * input.keyboard is the old 'we have keys', so we have to keep it * around. */ if (strcmp(props[i], "input.keys") == 0 || strcmp(props[i], "input.keyboard") == 0) type |= TYPE_KEYS; if (strcmp(props[i], "input.mouse") == 0) type |= TYPE_POINTER; } libhal_free_string_array(props); if (!type) goto out_error; driver = get_prop_string(hal_ctx, udi, "input.x11_driver"); path = get_prop_string(hal_ctx, udi, "input.device"); if (!driver || !path) { DebugF("[config/hal] no driver or path specified for %s\n", udi); goto unwind; } name = get_prop_string(hal_ctx, udi, "info.product"); if (!name) name = xstrdup("(unnamed)"); if (type & TYPE_KEYS) { xkb_rules = get_prop_string(hal_ctx, udi, "input.xkb.rules"); xkb_model = get_prop_string(hal_ctx, udi, "input.xkb.model"); xkb_layout = get_prop_string(hal_ctx, udi, "input.xkb.layout"); xkb_variant = get_prop_string(hal_ctx, udi, "input.xkb.variant"); xkb_options = get_prop_string_array(hal_ctx, udi, "input.xkb.options"); } options = xcalloc(sizeof(*options), 1); options->key = xstrdup("_source"); options->value = xstrdup("server/hal"); if (!options->key || !options->value) { ErrorF("[config] couldn't allocate first key/value pair\n"); goto unwind; } add_option(&options, "path", path); add_option(&options, "driver", driver); add_option(&options, "name", name); add_option(&options, "hal_udi", udi); if (xkb_model) add_option(&options, "xkb_model", xkb_model); if (xkb_layout) add_option(&options, "xkb_layout", xkb_layout); if (xkb_variant) add_option(&options, "xkb_variant", xkb_variant); #if 0 if (xkb_options) add_option(&options, "xkb_options", xkb_options); #endif /* Maemo-specific hack. Ugh. */ if (type & TYPE_KEYS) add_option(&options, "type", "keyboard"); else add_option(&options, "type", "pointer"); if (NewInputDeviceRequest(options, &dev) != Success) { DebugF("[config/hal] NewInputDeviceRequest failed\n"); goto unwind; } dbus_error_free(&error); return; unwind: if (path) xfree(path); if (driver) xfree(driver); if (name) xfree(name); if (xkb_rules) xfree(xkb_rules); if (xkb_model) xfree(xkb_model); if (xkb_layout) xfree(xkb_layout); if (xkb_options) { for (i = 0; xkb_options[i]; i++) xfree(xkb_options[i]); xfree(xkb_options); } out_error: dbus_error_free(&error); return; }