Fixup fromcvs/togit conversion
[minix-pkgsrc.git] / sysutils / hal / files / hald-netbsd / drvctl.c
blob573aa27ad9f2d3cf2796ab3f4d45a2bbdfdfa445
1 /***************************************************************************
3 * drvctl.c : NetBSD drvctl events
5 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
6 * Use is subject to license terms.
8 * Licensed under the Academic Free License version 2.1
10 **************************************************************************/
12 #ifdef HAVE_CONFIG_H
13 # include <config.h>
14 #endif
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <sys/ioctl.h>
23 #include <sys/drvctlio.h>
24 #include <sys/dkio.h>
25 #include <sys/stat.h>
26 #include <sys/drvctlio.h>
27 #include <glib.h>
29 #include "../osspec.h"
30 #include "../logger.h"
31 #include "../hald.h"
32 #include "../hald_dbus.h"
33 #include "../device_info.h"
34 #include "../util.h"
35 #include "osspec_netbsd.h"
36 #include "hotplug.h"
37 #include "devinfo.h"
38 #include "devinfo_storage.h"
39 #include "drvctl.h"
41 static gboolean drvctl_iochannel_data(GIOChannel *, GIOCondition, gpointer);
42 static void drvctl_dev_add(gchar *);
43 static void drvctl_dev_remove(gchar *);
44 static void drvctl_dev_branch(gchar *);
46 static int drvctl_fd;
47 static GIOChannel *drvctl_iochannel;
49 gboolean
50 drvctl_init(void)
52 drvctl_fd = open (DRVCTLDEV, O_RDWR);
53 if (drvctl_fd == -1) {
54 HAL_INFO (("open(%s, O_RDWR) failed: %s", DRVCTLDEV, strerror(errno)));
55 return FALSE;
58 drvctl_iochannel = g_io_channel_unix_new (drvctl_fd);
59 if (drvctl_iochannel == NULL) {
60 HAL_INFO (("g_io_channel_unix_new failed"));
61 return FALSE;
63 g_io_add_watch (drvctl_iochannel, G_IO_IN, drvctl_iochannel_data, NULL);
65 return TRUE;
68 void
69 drvctl_fini(void)
71 HAL_INFO (("drvctl_fini"));
74 static gboolean
75 drvctl_iochannel_data (GIOChannel *source,
76 GIOCondition condition,
77 gpointer user_data)
79 prop_dictionary_t ev;
80 const char *event, *device;
81 int res;
83 HAL_INFO (("drvctl_iochannel_data"));
85 res = prop_dictionary_recv_ioctl (drvctl_fd, DRVGETEVENT, &ev);
86 if (res) {
87 HAL_WARNING (("DRVGETEVENT failed: %s", strerror(errno)));
88 return FALSE;
91 if (!prop_dictionary_get_cstring_nocopy (ev, "event", &event)) {
92 HAL_WARNING (("DRVGETEVENT missing \"event\" parameter"));
93 goto done;
95 if (!prop_dictionary_get_cstring_nocopy (ev, "device", &device)) {
96 HAL_WARNING (("DRVGETEVENT missing \"device\" parameter"));
97 goto done;
100 HAL_INFO (("DRVGETEVENT event=%s device=%s", event, device));
102 if (strcmp (event, "device-attach") == 0) {
103 drvctl_dev_add (device);
104 } else {
105 drvctl_dev_remove (device);
108 done:
109 prop_object_release(ev);
110 return TRUE;
113 static void
114 drvctl_dev_add(gchar *name)
116 HalDevice *parent, *d;
117 gchar pdevnode[512];
119 if (drvctl_find_parent (name, pdevnode) == FALSE) {
120 HAL_INFO (("dev_add: name=%s orphan", name));
121 parent = NULL;
122 } else {
123 parent = hal_device_store_match_key_value_string (
124 hald_get_gdl(), "netbsd.device", pdevnode);
125 if (parent == NULL)
126 HAL_INFO (("dev_add: name=%s but netbsd.device=%s not found", pdevnode));
129 d = devinfo_add_node (parent, name);
130 if (d == NULL)
131 HAL_WARNING (("dev_add: couldn't add %s node (parent=%p)", name, parent));
133 hotplug_event_process_queue ();
136 static void
137 drvctl_dev_remove(gchar *name)
139 HAL_INFO (("dev_remove: %s", name));
141 devinfo_remove_branch (name, NULL);
142 hotplug_event_process_queue ();
145 static void
146 drvctl_dev_branch(gchar *name)
148 HAL_INFO (("branch_remove: %s", name));
150 devinfo_remove_branch (name, NULL);
151 hotplug_event_process_queue ();
155 drvctl_list(const gchar *name, struct devlistargs *laa)
157 size_t children;
159 /* HAL_INFO (("drvctl_list: %s", name)); */
161 memset (laa, 0, sizeof (*laa));
162 strlcpy (laa->l_devname, name, sizeof (laa->l_devname));
163 if (ioctl (drvctl_fd, DRVLISTDEV, laa) == -1) {
164 HAL_INFO (("DRVLISTDEV/1 failed: %s", strerror(errno)));
165 return -1;
167 children = laa->l_children;
168 /* HAL_INFO (("%s: found %d children", name, children)); */
169 if (children == 0)
170 return -1;
171 laa->l_childname = malloc (children * sizeof (laa->l_childname[0]));
172 if (laa->l_childname == NULL) {
173 HAL_INFO (("drvctl_list couldn't allocate %d children: %s\n", children, strerror(errno)));
174 return -1;
176 if (ioctl (drvctl_fd, DRVLISTDEV, laa) == -1) {
177 HAL_INFO (("DRVLISTDEV/2 failed: %s", strerror(errno)));
178 return -1;
180 if (children != laa->l_children)
181 HAL_WARNING (("DRVLISTDEV/3 expected %d children, got %d", children, laa->l_childname));
184 gboolean
185 drvctl_find_device(const gchar *devnode, prop_dictionary_t *properties)
187 prop_dictionary_t command_dict;
188 prop_dictionary_t args_dict;
189 prop_dictionary_t results_dict;
190 int err;
192 command_dict = prop_dictionary_create ();
193 args_dict = prop_dictionary_create ();
195 prop_dictionary_set_cstring_nocopy (command_dict, "drvctl-command", "get-properties");
196 prop_dictionary_set_cstring_nocopy (args_dict, "device-name", devnode);
197 prop_dictionary_set (command_dict, "drvctl-arguments", args_dict);
198 prop_object_release (args_dict);
200 err = prop_dictionary_sendrecv_ioctl (command_dict, drvctl_fd,
201 DRVCTLCOMMAND, &results_dict);
202 prop_object_release (command_dict);
203 if (err)
204 return FALSE;
206 if (prop_dictionary_get_int8 (results_dict, "drvctl-error", &err) == false || err != 0) {
207 prop_object_release (results_dict);
208 return FALSE;
211 if (properties) {
212 prop_dictionary_t result_data;
213 result_data = prop_dictionary_get (results_dict, "drvctl-result-data");
214 if (result_data)
215 *properties = prop_dictionary_copy (result_data);
218 prop_object_release (results_dict);
220 return TRUE;
223 static gboolean
224 drvctl_find_device_with_child(const gchar *curnode, const gchar *devnode,
225 char *parent)
227 struct devlistargs laa;
228 u_int i;
230 if (drvctl_list (curnode, &laa) == -1)
231 return FALSE;
233 for (i = 0; i < laa.l_children; i++) {
234 if (strcmp (laa.l_childname[i], devnode) == 0) {
235 strlcpy(parent, curnode, 16);
236 free(laa.l_childname);
237 return TRUE;
239 if (drvctl_find_device_with_child (laa.l_childname[i], devnode, parent) == TRUE) {
240 free(laa.l_childname);
241 return TRUE;
245 if (laa.l_childname)
246 free(laa.l_childname);
248 /* HAL_INFO (("%s: couldn't find device with child %s", curnode, devnode)); */
249 return FALSE;
252 gboolean
253 drvctl_find_parent(const gchar *devnode, char *parent)
255 return drvctl_find_device_with_child("mainbus0", devnode, parent);
258 #if 0
259 static void
260 drvctl_lofi_add(gchar *devfs_path, gchar *name)
262 di_node_t node;
263 const char *parent_udi;
264 HalDevice *d, *parent;
266 HAL_INFO (("lofi_add: %s %s", name, devfs_path));
268 if ((d = hal_device_store_match_key_value_string (hald_get_gdl (),
269 "solaris.devfs_path", devfs_path)) == NULL) {
270 HAL_INFO (("device not found in GDL %s", devfs_path));
271 return;
273 parent_udi = hal_device_property_get_string (d, "info.parent");
274 if ((parent_udi == NULL) || (strlen(parent_udi) == 0)) {
275 HAL_INFO (("parent not found in GDL %s", parent_udi));
276 return;
278 if ((parent = hal_device_store_match_key_value_string (hald_get_gdl (),
279 "info.udi", parent_udi)) == NULL) {
280 HAL_INFO (("parent not found in GDL %s", parent_udi));
281 return;
284 if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) {
285 HAL_INFO (("device not found in devinfo %s", devfs_path));
286 return;
289 HAL_INFO (("device %s parent %s", hal_device_get_udi (d), parent_udi));
290 devinfo_lofi_add_major (parent, node, devfs_path, NULL, TRUE, d);
292 di_fini (node);
294 hotplug_event_process_queue ();
297 static void
298 drvctl_lofi_remove(gchar *parent_devfs_path, gchar *name)
300 devinfo_lofi_remove_minor(parent_devfs_path, name);
301 hotplug_event_process_queue ();
303 #endif