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 **************************************************************************/
22 #include <sys/ioctl.h>
23 #include <sys/drvctlio.h>
26 #include <sys/drvctlio.h>
29 #include "../osspec.h"
30 #include "../logger.h"
32 #include "../hald_dbus.h"
33 #include "../device_info.h"
35 #include "osspec_netbsd.h"
38 #include "devinfo_storage.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
*);
47 static GIOChannel
*drvctl_iochannel
;
52 drvctl_fd
= open (DRVCTLDEV
, O_RDWR
);
53 if (drvctl_fd
== -1) {
54 HAL_INFO (("open(%s, O_RDWR) failed: %s", DRVCTLDEV
, strerror(errno
)));
58 drvctl_iochannel
= g_io_channel_unix_new (drvctl_fd
);
59 if (drvctl_iochannel
== NULL
) {
60 HAL_INFO (("g_io_channel_unix_new failed"));
63 g_io_add_watch (drvctl_iochannel
, G_IO_IN
, drvctl_iochannel_data
, NULL
);
71 HAL_INFO (("drvctl_fini"));
75 drvctl_iochannel_data (GIOChannel
*source
,
76 GIOCondition condition
,
80 const char *event
, *device
;
83 HAL_INFO (("drvctl_iochannel_data"));
85 res
= prop_dictionary_recv_ioctl (drvctl_fd
, DRVGETEVENT
, &ev
);
87 HAL_WARNING (("DRVGETEVENT failed: %s", strerror(errno
)));
91 if (!prop_dictionary_get_cstring_nocopy (ev
, "event", &event
)) {
92 HAL_WARNING (("DRVGETEVENT missing \"event\" parameter"));
95 if (!prop_dictionary_get_cstring_nocopy (ev
, "device", &device
)) {
96 HAL_WARNING (("DRVGETEVENT missing \"device\" parameter"));
100 HAL_INFO (("DRVGETEVENT event=%s device=%s", event
, device
));
102 if (strcmp (event
, "device-attach") == 0) {
103 drvctl_dev_add (device
);
105 drvctl_dev_remove (device
);
109 prop_object_release(ev
);
114 drvctl_dev_add(gchar
*name
)
116 HalDevice
*parent
, *d
;
119 if (drvctl_find_parent (name
, pdevnode
) == FALSE
) {
120 HAL_INFO (("dev_add: name=%s orphan", name
));
123 parent
= hal_device_store_match_key_value_string (
124 hald_get_gdl(), "netbsd.device", pdevnode
);
126 HAL_INFO (("dev_add: name=%s but netbsd.device=%s not found", pdevnode
));
129 d
= devinfo_add_node (parent
, name
);
131 HAL_WARNING (("dev_add: couldn't add %s node (parent=%p)", name
, parent
));
133 hotplug_event_process_queue ();
137 drvctl_dev_remove(gchar
*name
)
139 HAL_INFO (("dev_remove: %s", name
));
141 devinfo_remove_branch (name
, NULL
);
142 hotplug_event_process_queue ();
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
)
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
)));
167 children
= laa
->l_children
;
168 /* HAL_INFO (("%s: found %d children", name, children)); */
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
)));
176 if (ioctl (drvctl_fd
, DRVLISTDEV
, laa
) == -1) {
177 HAL_INFO (("DRVLISTDEV/2 failed: %s", strerror(errno
)));
180 if (children
!= laa
->l_children
)
181 HAL_WARNING (("DRVLISTDEV/3 expected %d children, got %d", children
, laa
->l_childname
));
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
;
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
);
206 if (prop_dictionary_get_int8 (results_dict
, "drvctl-error", &err
) == false || err
!= 0) {
207 prop_object_release (results_dict
);
212 prop_dictionary_t result_data
;
213 result_data
= prop_dictionary_get (results_dict
, "drvctl-result-data");
215 *properties
= prop_dictionary_copy (result_data
);
218 prop_object_release (results_dict
);
224 drvctl_find_device_with_child(const gchar
*curnode
, const gchar
*devnode
,
227 struct devlistargs laa
;
230 if (drvctl_list (curnode
, &laa
) == -1)
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
);
239 if (drvctl_find_device_with_child (laa
.l_childname
[i
], devnode
, parent
) == TRUE
) {
240 free(laa
.l_childname
);
246 free(laa
.l_childname
);
248 /* HAL_INFO (("%s: couldn't find device with child %s", curnode, devnode)); */
253 drvctl_find_parent(const gchar
*devnode
, char *parent
)
255 return drvctl_find_device_with_child("mainbus0", devnode
, parent
);
260 drvctl_lofi_add(gchar
*devfs_path
, gchar
*name
)
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
));
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
));
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
));
284 if ((node
= di_init (devfs_path
, DINFOCPYALL
)) == DI_NODE_NIL
) {
285 HAL_INFO (("device not found in devinfo %s", devfs_path
));
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
);
294 hotplug_event_process_queue ();
298 drvctl_lofi_remove(gchar
*parent_devfs_path
, gchar
*name
)
300 devinfo_lofi_remove_minor(parent_devfs_path
, name
);
301 hotplug_event_process_queue ();