summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Marcus Clarke <marcus@FreeBSD.org>2009-08-18 13:05:39 -0400
committerJoe Marcus Clarke <marcus@FreeBSD.org>2009-08-18 13:05:39 -0400
commit4d92b1ca4f9343d62641c37f366e46e900a3aed3 (patch)
tree27ea4a7f12adaccf7fc950c579fd54428197ff80
parent407103432cec837cc21397c499630ad3b077e984 (diff)
downloadhal-4d92b1ca4f9343d62641c37f366e46e900a3aed3.tar.gz
add support for mouse device probing
Newer versions of X rely on hal to provide input device details. Add support for probing mouse devices in order to determine if they are controlled by sysmouse, or standalone.
-rw-r--r--hald/freebsd/hf-devtree.c33
-rw-r--r--hald/freebsd/probing/probe-mouse.c312
2 files changed, 342 insertions, 3 deletions
diff --git a/hald/freebsd/hf-devtree.c b/hald/freebsd/hf-devtree.c
index 01203f05..410f3c68 100644
--- a/hald/freebsd/hf-devtree.c
+++ b/hald/freebsd/hf-devtree.c
@@ -86,7 +86,11 @@ hf_devtree_cpu_can_throttle (int cpu)
gboolean can = FALSE;
char *levels;
+#ifdef notyet
levels = hf_get_string_sysctl(NULL, "dev.cpu.%i.freq_levels", cpu);
+#else
+ levels = hf_get_string_sysctl(NULL, "dev.cpu.0.freq_levels");
+#endif
if (levels)
{
char **toks;
@@ -109,7 +113,11 @@ hf_devtree_cpu_get_maxfreq (int cpu)
char *levels;
int freq = -1;
+#ifdef notyet
levels = hf_get_string_sysctl(NULL, "dev.cpu.%i.freq_levels", cpu);
+#else
+ levels = hf_get_string_sysctl(NULL, "dev.cpu.0.freq_levels");
+#endif
if (levels)
{
sscanf(levels, "%i/", &freq);
@@ -379,7 +387,8 @@ static Handler handlers[] = {
{ "pcm", NULL },
{ "psm", hf_devtree_psm_set_properties },
{ "sio", NULL },
- { "speaker", NULL }
+ { "speaker", NULL },
+ { "usbus", NULL }
};
static void
@@ -426,7 +435,13 @@ hf_devtree_probe (void)
HalDevice *device;
device = hf_devtree_device_new(parent, info->handler, info->unit);
- hf_device_preprobe_and_add(device);
+ if (hf_device_preprobe(device))
+ {
+ if (hal_device_has_capability(device, "input.mouse"))
+ hf_runner_run_sync(device, 0, "hald-probe-mouse", NULL);
+
+ hf_device_add(device);
+ }
}
devices = g_slist_delete_link(devices, root);
@@ -434,6 +449,17 @@ hf_devtree_probe (void)
}
}
+static gboolean
+hf_devtree_rescan (HalDevice *device)
+{
+ if (hal_device_has_capability(device, "input.mouse"))
+ {
+ hf_runner_run_sync(device, 0, "hald-probe-mouse", NULL);
+ return TRUE;
+ }
+ return FALSE;
+}
+
HalDevice *
hf_devtree_find_from_name (HalDeviceStore *store, const char *name)
{
@@ -597,5 +623,6 @@ hf_devtree_is_driver (const char *name, const char *driver)
}
HFHandler hf_devtree_handler = {
- .probe = hf_devtree_probe
+ .probe = hf_devtree_probe,
+ .device_rescan = hf_devtree_rescan
};
diff --git a/hald/freebsd/probing/probe-mouse.c b/hald/freebsd/probing/probe-mouse.c
new file mode 100644
index 00000000..a2cffc10
--- /dev/null
+++ b/hald/freebsd/probing/probe-mouse.c
@@ -0,0 +1,312 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * probe-hiddev.c : Mouse prober
+ *
+ * Copyright (C) 2008 Joe Marcus Clarke <marcus@FreeBSD.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/param.h>
+#if __FreeBSD_version >= 800058
+#include <sys/types.h>
+#include <sys/user.h>
+#include <sys/sysctl.h>
+#include <libutil.h>
+#endif
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <glib.h>
+
+#include "../libprobe/hfp.h"
+
+#if __FreeBSD_version < 800058
+#define CMD "/usr/bin/fstat %s"
+#endif
+
+#define MOUSE_DRIVER "mouse"
+#define MOUSED_DEVICE "/dev/sysmouse"
+#define MOUSED_PROC_NAME "moused"
+#define XORG_PROC_NAME "Xorg"
+
+#if __FreeBSD_version >= 800058
+static struct kinfo_proc *
+hfp_kinfo_getproc (int *cntp)
+{
+ int mib[3];
+ int error;
+ int cnt;
+ size_t len;
+ char *buf, *bp, *eb;
+ struct kinfo_proc *kip, *kp, *ki;
+
+ *cntp = 0;
+
+ len = 0;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PROC;
+
+ error = sysctl(mib, 3, NULL, &len, NULL, 0);
+ if (error)
+ return NULL;
+
+ len = len * 4 / 3;
+ buf = (char *) g_malloc(len);
+ if (buf == NULL)
+ return NULL;
+
+ error = sysctl(mib, 3, buf, &len, NULL, 0);
+ if (error)
+ {
+ g_free(buf);
+ return NULL;
+ }
+
+ cnt = 0;
+ bp = buf;
+ eb = buf + len;
+ while (bp < eb)
+ {
+ ki = (struct kinfo_proc *) (uintptr_t) bp;
+ bp += ki->ki_structsize;
+ cnt++;
+ }
+
+ kip = calloc(cnt, sizeof (*kip));
+ if (kip == NULL)
+ {
+ g_free(buf);
+ return NULL;
+ }
+
+ bp = buf;
+ eb = buf + len;
+ kp = kip;
+ while (bp < eb)
+ {
+ ki = (struct kinfo_proc *) (uintptr_t) bp;
+ memcpy(kp, ki, ki->ki_structsize);
+ bp += ki->ki_structsize;
+ kp->ki_structsize = sizeof(*kp);
+ kp++;
+ }
+
+ g_free(buf);
+ *cntp = cnt;
+ return kip;
+}
+
+static gboolean
+device_opened_by_proc (const char *device, const char *proc)
+{
+ struct kinfo_proc *kip, *pfreep;
+ int cnt, i;
+
+ pfreep = hfp_kinfo_getproc(&cnt);
+ if (pfreep == NULL)
+ return FALSE;
+
+ for (i = 0; i < cnt; i++)
+ {
+ kip = &pfreep[i];
+
+ if (! strcmp(kip->ki_comm, proc))
+ {
+ struct kinfo_file *kif, *ffreep;
+ int fcnt, j;
+
+ ffreep = kinfo_getfile(kip->ki_pid, &fcnt);
+ if (ffreep == NULL)
+ continue;
+ for (j = 0; j < fcnt; j++)
+ {
+ kif = &ffreep[j];
+
+ if (kif->kf_type == KF_TYPE_VNODE &&
+ ! strcmp(kif->kf_path, device))
+ {
+ g_free(ffreep);
+ g_free(pfreep);
+ return TRUE;
+ }
+ }
+ g_free(ffreep);
+ }
+ }
+ g_free(pfreep);
+
+ return FALSE;
+}
+#else
+static gboolean
+device_opened_by_proc (const char *device, const char *proc)
+{
+ char **lines;
+ char *output = NULL;
+ char *cmd;
+ int i;
+ gboolean found = FALSE;
+
+ cmd = g_strdup_printf(CMD, device);
+
+ if (! g_spawn_command_line_sync(cmd, &output, NULL, NULL, NULL))
+ {
+ g_free(cmd);
+ goto done;
+ }
+ g_free(cmd);
+
+ if (! output || strlen(output) == 0)
+ goto done;
+
+ lines = g_strsplit(output, "\n", 0);
+ if (g_strv_length(lines) < 2)
+ {
+ g_strfreev(lines);
+ goto done;
+ }
+
+ for (i = 1; lines[i]; i++)
+ {
+ char **fields;
+ guint len;
+ guint j;
+
+ fields = g_strsplit_set(lines[i], " ", 0);
+ len = g_strv_length(fields);
+ if (len < 3)
+ {
+ g_strfreev(fields);
+ continue;
+ }
+ for (j = 1; j < len && fields[j] && *fields[j] == '\0'; j++)
+ ;
+ if (j < len && fields[j] && ! strcmp(fields[j], proc))
+ {
+ found = TRUE;
+ g_strfreev(fields);
+ break;
+ }
+ g_strfreev(fields);
+ }
+
+ g_strfreev(lines);
+
+done:
+ g_free(output);
+
+ return found;
+}
+#endif
+
+static void
+probe_mouse (const char *device_file)
+{
+ gboolean found;
+ char **udis;
+ char *driver;
+ int num_udis;
+
+ driver = libhal_device_get_property_string(hfp_ctx, hfp_udi,
+ "input.x11_driver", &hfp_error);
+ dbus_error_free(&hfp_error);
+
+ found = device_opened_by_proc(device_file, XORG_PROC_NAME);
+ if (found)
+ {
+ if (driver)
+ {
+ libhal_device_remove_property(hfp_ctx, hfp_udi, "input.x11_driver",
+ &hfp_error);
+ dbus_error_free(&hfp_error);
+ g_free(driver);
+ }
+ return;
+ }
+
+ found = device_opened_by_proc(device_file, MOUSED_PROC_NAME);
+ if (found)
+ {
+ libhal_device_set_property_string(hfp_ctx, hfp_udi, "input.device",
+ MOUSED_DEVICE, &hfp_error);
+ dbus_error_free(&hfp_error);
+ found = device_opened_by_proc(MOUSED_DEVICE, XORG_PROC_NAME);
+ if (! found)
+ {
+ udis = libhal_manager_find_device_string_match(hfp_ctx,
+ "input.device",
+ MOUSED_DEVICE,
+ &num_udis,
+ &hfp_error);
+ dbus_error_free(&hfp_error);
+ if (num_udis > 0 && udis != NULL && !strcmp(udis[0], hfp_udi)) {
+ libhal_device_set_property_string(hfp_ctx, hfp_udi,
+ "input.x11_driver",
+ MOUSE_DRIVER, &hfp_error);
+ dbus_error_free(&hfp_error);
+ libhal_free_string_array(udis);
+ }
+ }
+ else if (driver)
+ {
+ libhal_device_remove_property(hfp_ctx, hfp_udi, "input.x11_driver",
+ &hfp_error);
+ dbus_error_free(&hfp_error);
+ }
+ }
+ else
+ {
+ libhal_device_set_property_string(hfp_ctx, hfp_udi, "input.device",
+ device_file, &hfp_error);
+ dbus_error_free(&hfp_error);
+ libhal_device_set_property_string(hfp_ctx, hfp_udi, "input.x11_driver",
+ MOUSE_DRIVER, &hfp_error);
+ dbus_error_free(&hfp_error);
+ }
+
+ g_free(driver);
+}
+
+int
+main (int argc, char **argv)
+{
+ char *device_file;
+
+ if (! hfp_init(argc, argv))
+ goto end;
+
+ device_file = getenv("HAL_PROP_FREEBSD_DEVICE_FILE");
+ if (! device_file)
+ goto end;
+
+ /* give a meaningful process title for ps(1) */
+ setproctitle("%s", device_file);
+
+ /* Sleep for a second to give moused a chance to connect. */
+ sleep(1);
+ probe_mouse(device_file);
+
+ end:
+ return 0;
+}