118c2aff7Sartem /***************************************************************************
218c2aff7Sartem *
318c2aff7Sartem * devinfo_usb.h : USB devices
418c2aff7Sartem *
5d5c32991SNorm Jacobs * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
618c2aff7Sartem * Use is subject to license terms.
718c2aff7Sartem *
818c2aff7Sartem * Licensed under the Academic Free License version 2.1
918c2aff7Sartem *
1018c2aff7Sartem **************************************************************************/
1118c2aff7Sartem
1200687e57Sartem #ifdef HAVE_CONFIG_H
1300687e57Sartem # include <config.h>
1400687e57Sartem #endif
1500687e57Sartem
1618c2aff7Sartem #include <stdio.h>
1718c2aff7Sartem #include <string.h>
1818c2aff7Sartem #include <libdevinfo.h>
19b453864fSLin Guo - Sun Microsystems #include <unistd.h>
20b453864fSLin Guo - Sun Microsystems #include <dirent.h>
2118c2aff7Sartem #include <sys/types.h>
2218c2aff7Sartem #include <sys/mkdev.h>
2318c2aff7Sartem #include <sys/stat.h>
24112cd14aSqz #include <sys/usb/usbai.h>
2518c2aff7Sartem
2618c2aff7Sartem #include "../osspec.h"
2718c2aff7Sartem #include "../logger.h"
2818c2aff7Sartem #include "../hald.h"
2918c2aff7Sartem #include "../hald_dbus.h"
3018c2aff7Sartem #include "../device_info.h"
3118c2aff7Sartem #include "../util.h"
3218c2aff7Sartem #include "../ids.h"
3318c2aff7Sartem #include "hotplug.h"
3418c2aff7Sartem #include "devinfo.h"
3518c2aff7Sartem #include "devinfo_usb.h"
3618c2aff7Sartem
37112cd14aSqz static HalDevice *devinfo_usb_if_add(HalDevice *d, di_node_t node, gchar *devfs_path,
38112cd14aSqz gchar *if_devfs_path, int ifnum);
39112cd14aSqz static HalDevice *devinfo_usb_scsa2usb_add(HalDevice *d, di_node_t node);
40112cd14aSqz static HalDevice *devinfo_usb_printer_add(HalDevice *usbd, di_node_t node);
41b453864fSLin Guo - Sun Microsystems static HalDevice *devinfo_usb_input_add(HalDevice *usbd, di_node_t node);
423622ad5aSLin Guo - Sun Microsystems static HalDevice *devinfo_usb_video4linux_add(HalDevice *usbd, di_node_t node);
43b453864fSLin Guo - Sun Microsystems const gchar *devinfo_printer_prnio_get_prober(HalDevice *d, int *timeout);
44b453864fSLin Guo - Sun Microsystems const gchar *devinfo_keyboard_get_prober(HalDevice *d, int *timeout);
45112cd14aSqz static void set_usb_properties(HalDevice *d, di_node_t node, gchar *devfs_path, char *driver_name);
4618c2aff7Sartem
4718c2aff7Sartem DevinfoDevHandler devinfo_usb_handler = {
48112cd14aSqz devinfo_usb_add,
4918c2aff7Sartem NULL,
5018c2aff7Sartem NULL,
5118c2aff7Sartem NULL,
5218c2aff7Sartem NULL,
53112cd14aSqz NULL
5418c2aff7Sartem };
5518c2aff7Sartem
5642a7bdedSjacobs DevinfoDevHandler devinfo_usb_printer_handler = {
57112cd14aSqz devinfo_usb_add,
5842a7bdedSjacobs NULL,
5942a7bdedSjacobs NULL,
6042a7bdedSjacobs NULL,
6142a7bdedSjacobs NULL,
62112cd14aSqz devinfo_printer_prnio_get_prober
6342a7bdedSjacobs };
6442a7bdedSjacobs
65b453864fSLin Guo - Sun Microsystems DevinfoDevHandler devinfo_usb_keyboard_handler = {
66b453864fSLin Guo - Sun Microsystems devinfo_usb_add,
67b453864fSLin Guo - Sun Microsystems NULL,
68b453864fSLin Guo - Sun Microsystems NULL,
69b453864fSLin Guo - Sun Microsystems NULL,
70b453864fSLin Guo - Sun Microsystems NULL,
71b453864fSLin Guo - Sun Microsystems devinfo_keyboard_get_prober
72b453864fSLin Guo - Sun Microsystems };
73b453864fSLin Guo - Sun Microsystems
74c74d5d46Sjacobs static gboolean
is_usb_node(di_node_t node)75c74d5d46Sjacobs is_usb_node(di_node_t node)
76c74d5d46Sjacobs {
77c74d5d46Sjacobs int rc;
78c74d5d46Sjacobs char *s;
79c74d5d46Sjacobs
80c74d5d46Sjacobs /*
81c74d5d46Sjacobs * USB device nodes will have "compatible" propety values that
82c74d5d46Sjacobs * begins with "usb".
83c74d5d46Sjacobs */
84112cd14aSqz rc = di_prop_lookup_strings(DDI_DEV_T_ANY, node, "compatible", &s);
85c74d5d46Sjacobs while (rc-- > 0) {
86c74d5d46Sjacobs if (strncmp(s, "usb", 3) == 0) {
87c74d5d46Sjacobs return (TRUE);
88c74d5d46Sjacobs }
89c74d5d46Sjacobs s += (strlen(s) + 1);
90c74d5d46Sjacobs }
91c74d5d46Sjacobs
92c74d5d46Sjacobs return (FALSE);
93c74d5d46Sjacobs }
94c74d5d46Sjacobs
95b453864fSLin Guo - Sun Microsystems static char *
get_usb_devlink(char * devfs_path,const char * dir_name)963622ad5aSLin Guo - Sun Microsystems get_usb_devlink(char *devfs_path, const char *dir_name)
97b453864fSLin Guo - Sun Microsystems {
98b453864fSLin Guo - Sun Microsystems char *result = NULL;
99b453864fSLin Guo - Sun Microsystems DIR *dp;
100b453864fSLin Guo - Sun Microsystems
1013622ad5aSLin Guo - Sun Microsystems if ((dp = opendir(dir_name)) != NULL) {
102b453864fSLin Guo - Sun Microsystems struct dirent *ep;
103b453864fSLin Guo - Sun Microsystems
104b453864fSLin Guo - Sun Microsystems while ((ep = readdir(dp)) != NULL) {
105b453864fSLin Guo - Sun Microsystems char path[MAXPATHLEN], lpath[MAXPATHLEN];
106b453864fSLin Guo - Sun Microsystems
1073622ad5aSLin Guo - Sun Microsystems strncpy(path, dir_name, strlen(dir_name));
1083622ad5aSLin Guo - Sun Microsystems strncat(path, ep->d_name, strlen(ep->d_name));
109b453864fSLin Guo - Sun Microsystems memset(lpath, 0, sizeof (lpath));
110b453864fSLin Guo - Sun Microsystems if ((readlink(path, lpath, sizeof (lpath)) > 0) &&
111b453864fSLin Guo - Sun Microsystems (strstr(lpath, devfs_path) != NULL)) {
112b453864fSLin Guo - Sun Microsystems result = strdup(path);
113b453864fSLin Guo - Sun Microsystems break;
114b453864fSLin Guo - Sun Microsystems }
1153622ad5aSLin Guo - Sun Microsystems memset(path, 0, sizeof (path));
116b453864fSLin Guo - Sun Microsystems }
117b453864fSLin Guo - Sun Microsystems closedir(dp);
118b453864fSLin Guo - Sun Microsystems }
119b453864fSLin Guo - Sun Microsystems
120b453864fSLin Guo - Sun Microsystems return (result);
121b453864fSLin Guo - Sun Microsystems }
122b453864fSLin Guo - Sun Microsystems
12318c2aff7Sartem HalDevice *
devinfo_usb_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)12418c2aff7Sartem devinfo_usb_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
12518c2aff7Sartem {
12618c2aff7Sartem HalDevice *d, *nd = NULL;
12718c2aff7Sartem char *s;
128c74d5d46Sjacobs int *i;
12918c2aff7Sartem char *driver_name, *binding_name;
130112cd14aSqz char if_devfs_path[HAL_PATH_MAX];
131112cd14aSqz di_devlink_handle_t hdl;
132112cd14aSqz double k;
13318c2aff7Sartem
134112cd14aSqz if (is_usb_node(node) == FALSE) {
13518c2aff7Sartem return (NULL);
13618c2aff7Sartem }
13718c2aff7Sartem
138112cd14aSqz driver_name = di_driver_name (node);
139112cd14aSqz
140112cd14aSqz if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "interface", &i) < 0) {
141112cd14aSqz /* It is a USB device node. */
142112cd14aSqz
143112cd14aSqz d = hal_device_new ();
144112cd14aSqz
145112cd14aSqz devinfo_set_default_properties (d, parent, node, devfs_path);
146112cd14aSqz hal_device_property_set_string (d, "info.subsystem", "usb_device");
147112cd14aSqz PROP_STR(d, node, s, "usb-product-name", "info.product");
148112cd14aSqz PROP_STR(d, node, s, "usb-product-name", "usb_device.product");
149112cd14aSqz PROP_STR(d, node, s, "usb-vendor-name", "usb_device.vendor");
150112cd14aSqz PROP_INT(d, node, i, "usb-vendor-id", "usb_device.vendor_id");
151112cd14aSqz PROP_INT(d, node, i, "usb-product-id", "usb_device.product_id");
152112cd14aSqz PROP_INT(d, node, i, "usb-revision-id", "usb_device.device_revision_bcd");
153112cd14aSqz PROP_STR(d, node, s, "usb-serialno", "usb_device.serial");
154112cd14aSqz PROP_INT(d, node, i, "usb-port-count", "usb_device.num_ports");
155112cd14aSqz PROP_INT(d, node, i, "usb-num-configs", "usb_device.num_configurations");
156112cd14aSqz PROP_INT(d, node, i, "assigned-address", "usb_device.bus_number");
157112cd14aSqz
158112cd14aSqz if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "usb-release", &i) > 0) {
159112cd14aSqz k = (double)bcd(*i);
160112cd14aSqz hal_device_property_set_double (d, "usb_device.version", k / 100);
161112cd14aSqz }
162112cd14aSqz
163112cd14aSqz if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "low-speed", &i) >= 0) {
164112cd14aSqz k = 1.5;
165112cd14aSqz } else if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "high-speed", &i) >= 0) {
166112cd14aSqz k = 480.0;
167112cd14aSqz } else {
168112cd14aSqz /* It is the full speed device. */
169112cd14aSqz k = 12.0;
170112cd14aSqz }
171112cd14aSqz hal_device_property_set_double (d, "usb_device.speed", k);
172112cd14aSqz
173112cd14aSqz set_usb_properties (d, node, devfs_path, driver_name);
174112cd14aSqz
175112cd14aSqz /* wait for the ugen node's creation */
176112cd14aSqz if ((driver_name != NULL) && (strcmp (driver_name, "usb_mid") == 0)) {
177112cd14aSqz if (hdl = di_devlink_init (devfs_path, DI_MAKE_LINK)) {
178112cd14aSqz di_devlink_fini (&hdl);
179112cd14aSqz }
180112cd14aSqz }
181112cd14aSqz
182112cd14aSqz devinfo_add_enqueue (d, devfs_path, &devinfo_usb_handler);
183112cd14aSqz
184112cd14aSqz /* add to TDL so preprobing callouts and prober can access it */
185112cd14aSqz hal_device_store_add (hald_get_tdl (), d);
18618c2aff7Sartem
187112cd14aSqz if (((binding_name = di_binding_name (node)) != NULL) &&
188112cd14aSqz (strncmp (binding_name, "usbif,", sizeof ("usbif,") - 1) == 0)) {
189112cd14aSqz
190112cd14aSqz snprintf (if_devfs_path, sizeof (if_devfs_path), "%s:if%d",
191b453864fSLin Guo - Sun Microsystems devfs_path, 0);
192112cd14aSqz if ((nd = devinfo_usb_if_add (d, node, if_devfs_path,
193b453864fSLin Guo - Sun Microsystems if_devfs_path, 0)) != NULL) {
194112cd14aSqz d = nd;
195112cd14aSqz nd = NULL;
196112cd14aSqz devfs_path = if_devfs_path;
197112cd14aSqz }
198112cd14aSqz }
199112cd14aSqz } else {
200112cd14aSqz /* It is a USB interface node or IA node. */
201112cd14aSqz int *j;
202112cd14aSqz
203112cd14aSqz if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "interface-count", &j) > 0) {
204112cd14aSqz /*
205112cd14aSqz * The USB IA node properties are not defined in
206112cd14aSqz * HAL spec so far. So IA node udi has "ia" sign
207112cd14aSqz * now, different from the IF node udi with "if".
208112cd14aSqz */
209112cd14aSqz snprintf (if_devfs_path, sizeof (if_devfs_path),
210112cd14aSqz "%s:ia%d", devfs_path, *i);
211112cd14aSqz } else {
212112cd14aSqz snprintf (if_devfs_path, sizeof (if_devfs_path),
213112cd14aSqz "%s:if%d", devfs_path, *i);
21418c2aff7Sartem }
215112cd14aSqz
216112cd14aSqz d = devinfo_usb_if_add (parent, node, devfs_path, if_devfs_path, *i);
21718c2aff7Sartem }
21818c2aff7Sartem
21918c2aff7Sartem /* driver specific */
220b453864fSLin Guo - Sun Microsystems if (driver_name != NULL) {
221b453864fSLin Guo - Sun Microsystems if (strcmp (driver_name, "scsa2usb") == 0) {
222b453864fSLin Guo - Sun Microsystems nd = devinfo_usb_scsa2usb_add (d, node);
223b453864fSLin Guo - Sun Microsystems } else if (strcmp (driver_name, "usbprn") == 0) {
224b453864fSLin Guo - Sun Microsystems nd = devinfo_usb_printer_add (d, node);
225b453864fSLin Guo - Sun Microsystems } else if (strcmp(driver_name, "hid") == 0) {
226b453864fSLin Guo - Sun Microsystems if (hdl = di_devlink_init(devfs_path, DI_MAKE_LINK)) {
227b453864fSLin Guo - Sun Microsystems di_devlink_fini(&hdl);
228b453864fSLin Guo - Sun Microsystems }
229b453864fSLin Guo - Sun Microsystems nd = devinfo_usb_input_add(d, node);
2303622ad5aSLin Guo - Sun Microsystems } else if (strcmp(driver_name, "usbvc") == 0) {
2313622ad5aSLin Guo - Sun Microsystems if (hdl = di_devlink_init(devfs_path, DI_MAKE_LINK)) {
2323622ad5aSLin Guo - Sun Microsystems di_devlink_fini(&hdl);
2333622ad5aSLin Guo - Sun Microsystems }
2343622ad5aSLin Guo - Sun Microsystems nd = devinfo_usb_video4linux_add(d, node);
235b453864fSLin Guo - Sun Microsystems }
23618c2aff7Sartem }
23718c2aff7Sartem
23818c2aff7Sartem out:
23918c2aff7Sartem if (nd != NULL) {
24018c2aff7Sartem return (nd);
24118c2aff7Sartem } else {
24218c2aff7Sartem return (d);
24318c2aff7Sartem }
24418c2aff7Sartem }
24518c2aff7Sartem
246112cd14aSqz
247112cd14aSqz static void
set_usb_properties(HalDevice * d,di_node_t node,gchar * devfs_path,char * driver_name)248112cd14aSqz set_usb_properties(HalDevice *d, di_node_t node, gchar *devfs_path, char *driver_name)
24918c2aff7Sartem {
250112cd14aSqz usb_dev_descr_t *dev_descrp = NULL; /* device descriptor */
251112cd14aSqz usb_cfg_descr_t *cfg_descrp = NULL; /* configuration descriptor */
252112cd14aSqz unsigned char *rdata = NULL;
253112cd14aSqz char *p;
254112cd14aSqz int i = 0;
255112cd14aSqz
256112cd14aSqz hal_device_property_set_int (d, "usb_device.port_number",
257112cd14aSqz atoi (devfs_path + strlen (devfs_path) -1));
258112cd14aSqz
259112cd14aSqz if (di_prop_lookup_bytes (DDI_DEV_T_ANY, node, "usb-dev-descriptor",
260112cd14aSqz &rdata) > 0) {
261112cd14aSqz dev_descrp = (usb_dev_descr_t *)rdata;
262112cd14aSqz
263112cd14aSqz if (dev_descrp != NULL) {
264112cd14aSqz hal_device_property_set_int (d, "usb_device.device_class",
265112cd14aSqz dev_descrp->bDeviceClass);
266112cd14aSqz hal_device_property_set_int (d, "usb_device.device_subclass",
267112cd14aSqz dev_descrp->bDeviceSubClass);
268112cd14aSqz hal_device_property_set_int (d, "usb_device.device_protocol",
269112cd14aSqz dev_descrp->bDeviceProtocol);
270112cd14aSqz }
271112cd14aSqz }
272112cd14aSqz
273112cd14aSqz if (di_prop_lookup_bytes (DDI_DEV_T_ANY, node, "usb-raw-cfg-descriptors",
274112cd14aSqz &rdata) > 0) {
275112cd14aSqz cfg_descrp = (usb_cfg_descr_t *)(rdata);
276112cd14aSqz
277112cd14aSqz if (cfg_descrp != NULL) {
278112cd14aSqz hal_device_property_set_int (d, "usb_device.configuration_value",
279112cd14aSqz cfg_descrp->bConfigurationValue);
280112cd14aSqz hal_device_property_set_int (d, "usb_device.max_power",
281112cd14aSqz cfg_descrp->bMaxPower);
282112cd14aSqz hal_device_property_set_int (d, "usb_device.num_interfaces",
283112cd14aSqz cfg_descrp->bNumInterfaces);
284112cd14aSqz hal_device_property_set_bool (d, "usb_device.can_wake_up",
285112cd14aSqz (cfg_descrp->bmAttributes & 0x20) ? TRUE : FALSE);
286112cd14aSqz hal_device_property_set_bool (d, "usb_device.is_self_powered",
287112cd14aSqz (cfg_descrp->bmAttributes & 0x40) ? TRUE : FALSE);
288112cd14aSqz }
289112cd14aSqz }
290112cd14aSqz
291112cd14aSqz /* get the node's usb tree level by counting hub numbers */
292112cd14aSqz do {
293112cd14aSqz if (p = strstr (devfs_path, "/hub@")) {
294112cd14aSqz devfs_path = p + strlen ("/hub@");
295112cd14aSqz i ++;
296112cd14aSqz }
297112cd14aSqz } while (p != NULL);
29818c2aff7Sartem
299112cd14aSqz if ((driver_name != NULL) && (strcmp (driver_name, "hubd") == 0) && (i > 0))
300112cd14aSqz i --;
301112cd14aSqz
302112cd14aSqz hal_device_property_set_int (d, "usb_device.level_number", i);
303112cd14aSqz }
304112cd14aSqz
305112cd14aSqz
306112cd14aSqz static usb_if_descr_t *
parse_usb_if_descr(di_node_t node,int ifnum)307112cd14aSqz parse_usb_if_descr(di_node_t node, int ifnum)
308112cd14aSqz {
309112cd14aSqz unsigned char *rdata = NULL;
310112cd14aSqz usb_if_descr_t *if_descrp=NULL; /* interface descriptor */
311b453864fSLin Guo - Sun Microsystems di_node_t tmp_node = DI_NODE_NIL;
312112cd14aSqz uint8_t num, length, type;
313112cd14aSqz int rlen;
314112cd14aSqz gchar *devpath = NULL;
315112cd14aSqz
316112cd14aSqz if ((rlen = di_prop_lookup_bytes (DDI_DEV_T_ANY, node,
317112cd14aSqz "usb-raw-cfg-descriptors", &rdata)) < 0) {
318112cd14aSqz
319112cd14aSqz char *p;
320112cd14aSqz int i;
321112cd14aSqz
322112cd14aSqz if ((devpath = di_devfs_path (node)) == NULL)
323112cd14aSqz goto out;
324112cd14aSqz
325112cd14aSqz /* Look up its parent that may be a USB IA or USB mid. */
326112cd14aSqz for (i = 0; i < 2; i++) {
327112cd14aSqz p = strrchr (devpath, '/');
328112cd14aSqz if (p == NULL)
329112cd14aSqz goto out;
330112cd14aSqz *p = '\0';
3313622ad5aSLin Guo - Sun Microsystems
332112cd14aSqz if ((tmp_node = di_init (devpath, DINFOCPYALL)) == DI_NODE_NIL)
333112cd14aSqz goto out;
334112cd14aSqz
335112cd14aSqz if ((rlen = di_prop_lookup_bytes (DDI_DEV_T_ANY, tmp_node,
336112cd14aSqz "usb-raw-cfg-descriptors", &rdata)) > 0)
337112cd14aSqz break;
338112cd14aSqz
339112cd14aSqz di_fini (tmp_node);
340112cd14aSqz }
341112cd14aSqz }
342112cd14aSqz
343112cd14aSqz if (rdata == NULL)
344112cd14aSqz goto out;
345112cd14aSqz
346112cd14aSqz do {
347112cd14aSqz length = (uint8_t)*rdata;
348112cd14aSqz type = (uint8_t)*(rdata + 1);
349112cd14aSqz if (type == USB_DESCR_TYPE_IF) {
350112cd14aSqz num = (uint8_t)*(rdata + 2);
351112cd14aSqz if (num == ifnum) {
352112cd14aSqz if_descrp = (usb_if_descr_t *)rdata;
353112cd14aSqz break;
354112cd14aSqz }
355112cd14aSqz }
356112cd14aSqz rdata += length;
357112cd14aSqz rlen -= length;
358112cd14aSqz } while ((length > 0 ) && (rlen > 0));
359112cd14aSqz
360112cd14aSqz out:
361112cd14aSqz if (devpath != NULL)
362112cd14aSqz di_devfs_path_free (devpath);
363112cd14aSqz if (tmp_node != DI_NODE_NIL)
364112cd14aSqz di_fini (tmp_node);
365112cd14aSqz return (if_descrp);
366112cd14aSqz }
367112cd14aSqz
368112cd14aSqz
369112cd14aSqz static HalDevice *
devinfo_usb_if_add(HalDevice * parent,di_node_t node,gchar * devfs_path,gchar * if_devfs_path,int ifnum)370112cd14aSqz devinfo_usb_if_add(HalDevice *parent, di_node_t node, gchar *devfs_path,
371112cd14aSqz gchar *if_devfs_path, int ifnum)
372112cd14aSqz {
373112cd14aSqz HalDevice *d = NULL;
374112cd14aSqz char udi[HAL_PATH_MAX];
375112cd14aSqz const char *parent_info;
376112cd14aSqz usb_if_descr_t *if_descrp=NULL; /* interface descriptor */
37718c2aff7Sartem
37818c2aff7Sartem d = hal_device_new ();
37918c2aff7Sartem
380112cd14aSqz devinfo_set_default_properties (d, parent, node, if_devfs_path);
381112cd14aSqz
382112cd14aSqz /* Set the existed physical device path. */
383112cd14aSqz hal_device_property_set_string (d, "solaris.devfs_path", devfs_path);
384112cd14aSqz hal_device_property_set_string (d, "info.subsystem", "usb");
385112cd14aSqz hal_device_property_set_string (d, "info.product", "USB Device Interface");
386112cd14aSqz
387112cd14aSqz /* Set usb interface properties to interface node. */
388112cd14aSqz if (strstr (if_devfs_path, ":ia") == NULL) {
389112cd14aSqz if_descrp = parse_usb_if_descr (node, ifnum);
390112cd14aSqz
391112cd14aSqz if (if_descrp != NULL) {
392112cd14aSqz hal_device_property_set_int (d, "usb.interface.class",
393112cd14aSqz if_descrp->bInterfaceClass);
394112cd14aSqz hal_device_property_set_int (d, "usb.interface.subclass",
395112cd14aSqz if_descrp->bInterfaceSubClass);
396112cd14aSqz hal_device_property_set_int (d, "usb.interface.protocol",
397112cd14aSqz if_descrp->bInterfaceProtocol);
398112cd14aSqz hal_device_property_set_int (d, "usb.interface.number",
399112cd14aSqz if_descrp->bInterfaceNumber);
400112cd14aSqz }
401112cd14aSqz }
40218c2aff7Sartem
40318c2aff7Sartem /* copy parent's usb_device.* properties */
404112cd14aSqz parent_info = hal_device_property_get_string (parent, "info.subsystem");
405112cd14aSqz if (parent_info != NULL) {
406112cd14aSqz if (strcmp (parent_info, "usb_device") == 0) {
407112cd14aSqz hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device.");
408112cd14aSqz } else if (strcmp (parent_info, "usb") == 0) {
409112cd14aSqz /* for the case that the parent is IA node */
410112cd14aSqz hal_device_merge_with_rewrite (d, parent, "usb.", "usb.");
411112cd14aSqz }
412112cd14aSqz }
413112cd14aSqz
414112cd14aSqz devinfo_add_enqueue (d, devfs_path, &devinfo_usb_handler);
415112cd14aSqz
416112cd14aSqz /* add to TDL so preprobing callouts and prober can access it */
417112cd14aSqz hal_device_store_add (hald_get_tdl (), d);
41818c2aff7Sartem
41918c2aff7Sartem return (d);
42018c2aff7Sartem }
42118c2aff7Sartem
42218c2aff7Sartem
42342a7bdedSjacobs static void
get_dev_link_path(di_node_t node,char * nodetype,char * re,char ** devlink,char ** minor_path,char ** minor_name)424b453864fSLin Guo - Sun Microsystems get_dev_link_path(di_node_t node, char *nodetype, char *re, char **devlink, char **minor_path, char **minor_name)
42518c2aff7Sartem {
42618c2aff7Sartem di_devlink_handle_t devlink_hdl;
427112cd14aSqz int major;
428112cd14aSqz di_minor_t minor;
429112cd14aSqz dev_t devt;
43018c2aff7Sartem
43142a7bdedSjacobs *devlink = NULL;
432112cd14aSqz *minor_path = NULL;
433b453864fSLin Guo - Sun Microsystems *minor_name = NULL;
43418c2aff7Sartem
435112cd14aSqz if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
436112cd14aSqz return;
437112cd14aSqz }
43818c2aff7Sartem
439112cd14aSqz major = di_driver_major(node);
440112cd14aSqz minor = DI_MINOR_NIL;
441112cd14aSqz while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
442112cd14aSqz devt = di_minor_devt(minor);
443112cd14aSqz if (major != major(devt)) {
444112cd14aSqz continue;
445112cd14aSqz }
44642a7bdedSjacobs
447112cd14aSqz if (di_minor_type(minor) != DDM_MINOR) {
448112cd14aSqz continue;
449112cd14aSqz }
45042a7bdedSjacobs
451112cd14aSqz if ((*minor_path = di_devfs_minor_path(minor)) == NULL) {
452112cd14aSqz continue;
453112cd14aSqz }
45442a7bdedSjacobs
455b453864fSLin Guo - Sun Microsystems if (strcmp(di_minor_nodetype(minor), nodetype) == 0) {
456b453864fSLin Guo - Sun Microsystems *devlink = get_devlink(devlink_hdl, re, *minor_path);
457b453864fSLin Guo - Sun Microsystems /*
4583622ad5aSLin Guo - Sun Microsystems * During hotplugging, devlink could be NULL for usb
459b453864fSLin Guo - Sun Microsystems * devices due to devlink database has not yet been
460b453864fSLin Guo - Sun Microsystems * updated when hal try to read from it although the
461b453864fSLin Guo - Sun Microsystems * actually dev link path has been created. In such a
462b453864fSLin Guo - Sun Microsystems * situation, we will read the devlink name from
463b453864fSLin Guo - Sun Microsystems * /dev/usb directory.
464b453864fSLin Guo - Sun Microsystems */
465*3fb52c73SRaymond Chen if ((*devlink == NULL) && (re != NULL) &&
4663622ad5aSLin Guo - Sun Microsystems ((strstr(re, "hid") != NULL) || (strstr(re, "video") != NULL))) {
4673622ad5aSLin Guo - Sun Microsystems *devlink = get_usb_devlink(*minor_path, "/dev/usb/");
468b453864fSLin Guo - Sun Microsystems }
469b453864fSLin Guo - Sun Microsystems
470b453864fSLin Guo - Sun Microsystems if (*devlink != NULL) {
471b453864fSLin Guo - Sun Microsystems *minor_name = di_minor_name(minor);
472b453864fSLin Guo - Sun Microsystems break;
473b453864fSLin Guo - Sun Microsystems }
47418c2aff7Sartem }
475b453864fSLin Guo - Sun Microsystems
47642a7bdedSjacobs di_devfs_path_free (*minor_path);
477c74d5d46Sjacobs *minor_path = NULL;
47842a7bdedSjacobs }
47918c2aff7Sartem di_devlink_fini (&devlink_hdl);
48042a7bdedSjacobs }
48142a7bdedSjacobs
4823622ad5aSLin Guo - Sun Microsystems static HalDevice *
devinfo_usb_video4linux_add(HalDevice * usbd,di_node_t node)4833622ad5aSLin Guo - Sun Microsystems devinfo_usb_video4linux_add(HalDevice *usbd, di_node_t node)
4843622ad5aSLin Guo - Sun Microsystems {
4853622ad5aSLin Guo - Sun Microsystems HalDevice *d = NULL;
4863622ad5aSLin Guo - Sun Microsystems int major;
4873622ad5aSLin Guo - Sun Microsystems di_minor_t minor;
4883622ad5aSLin Guo - Sun Microsystems dev_t devt;
4893622ad5aSLin Guo - Sun Microsystems char *devlink = NULL;
4903622ad5aSLin Guo - Sun Microsystems char *dev_videolink = NULL;
4913622ad5aSLin Guo - Sun Microsystems char *minor_path = NULL;
4923622ad5aSLin Guo - Sun Microsystems char *minor_name = NULL;
4933622ad5aSLin Guo - Sun Microsystems char udi[HAL_PATH_MAX];
4943622ad5aSLin Guo - Sun Microsystems char *s;
4953622ad5aSLin Guo - Sun Microsystems
4963622ad5aSLin Guo - Sun Microsystems get_dev_link_path(node, "usb_video",
497*3fb52c73SRaymond Chen "^usb/video[0-9]+", &devlink, &minor_path, &minor_name);
4983622ad5aSLin Guo - Sun Microsystems
4993622ad5aSLin Guo - Sun Microsystems if ((minor_path == NULL) || (devlink == NULL)) {
5003622ad5aSLin Guo - Sun Microsystems
5013622ad5aSLin Guo - Sun Microsystems goto out;
5023622ad5aSLin Guo - Sun Microsystems }
5033622ad5aSLin Guo - Sun Microsystems
5043622ad5aSLin Guo - Sun Microsystems HAL_DEBUG(("devlink %s, minor_name %s", devlink, minor_name));
5053622ad5aSLin Guo - Sun Microsystems if (strcmp(minor_name, "usbvc") != 0) {
5063622ad5aSLin Guo - Sun Microsystems
5073622ad5aSLin Guo - Sun Microsystems goto out;
5083622ad5aSLin Guo - Sun Microsystems }
5093622ad5aSLin Guo - Sun Microsystems
5103622ad5aSLin Guo - Sun Microsystems d = hal_device_new();
5113622ad5aSLin Guo - Sun Microsystems
5123622ad5aSLin Guo - Sun Microsystems devinfo_set_default_properties(d, usbd, node, minor_path);
5133622ad5aSLin Guo - Sun Microsystems hal_device_property_set_string(d, "info.subsystem", "video4linux");
5143622ad5aSLin Guo - Sun Microsystems hal_device_property_set_string(d, "info.category", "video4linux");
5153622ad5aSLin Guo - Sun Microsystems
5163622ad5aSLin Guo - Sun Microsystems hal_device_add_capability(d, "video4linux");
5173622ad5aSLin Guo - Sun Microsystems
5183622ad5aSLin Guo - Sun Microsystems /* Get logic link under /dev (/dev/video+) */
5193622ad5aSLin Guo - Sun Microsystems dev_videolink = get_usb_devlink(strstr(devlink, "usb"), "/dev/");
5203622ad5aSLin Guo - Sun Microsystems
5213622ad5aSLin Guo - Sun Microsystems hal_device_property_set_string(d, "video4linux.device", dev_videolink);
5223622ad5aSLin Guo - Sun Microsystems
5233622ad5aSLin Guo - Sun Microsystems hal_util_compute_udi(hald_get_gdl(), udi, sizeof (udi),
5243622ad5aSLin Guo - Sun Microsystems "%s_video4linux", hal_device_get_udi(usbd));
5253622ad5aSLin Guo - Sun Microsystems
5263622ad5aSLin Guo - Sun Microsystems hal_device_set_udi(d, udi);
5273622ad5aSLin Guo - Sun Microsystems hal_device_property_set_string(d, "info.udi", udi);
5283622ad5aSLin Guo - Sun Microsystems PROP_STR(d, node, s, "usb-product-name", "info.product");
5293622ad5aSLin Guo - Sun Microsystems
5303622ad5aSLin Guo - Sun Microsystems devinfo_add_enqueue(d, minor_path, &devinfo_usb_handler);
5313622ad5aSLin Guo - Sun Microsystems
5323622ad5aSLin Guo - Sun Microsystems
5333622ad5aSLin Guo - Sun Microsystems out:
5343622ad5aSLin Guo - Sun Microsystems if (devlink) {
5353622ad5aSLin Guo - Sun Microsystems free(devlink);
5363622ad5aSLin Guo - Sun Microsystems }
5373622ad5aSLin Guo - Sun Microsystems
5383622ad5aSLin Guo - Sun Microsystems if (minor_path) {
5393622ad5aSLin Guo - Sun Microsystems di_devfs_path_free(minor_path);
5403622ad5aSLin Guo - Sun Microsystems }
5413622ad5aSLin Guo - Sun Microsystems
5423622ad5aSLin Guo - Sun Microsystems return (d);
5433622ad5aSLin Guo - Sun Microsystems }
5443622ad5aSLin Guo - Sun Microsystems
545b453864fSLin Guo - Sun Microsystems static HalDevice *
devinfo_usb_input_add(HalDevice * usbd,di_node_t node)546b453864fSLin Guo - Sun Microsystems devinfo_usb_input_add(HalDevice *usbd, di_node_t node)
547b453864fSLin Guo - Sun Microsystems {
548b453864fSLin Guo - Sun Microsystems HalDevice *d = NULL;
549b453864fSLin Guo - Sun Microsystems int major;
550b453864fSLin Guo - Sun Microsystems di_minor_t minor;
551b453864fSLin Guo - Sun Microsystems dev_t devt;
552b453864fSLin Guo - Sun Microsystems char *devlink = NULL;
553b453864fSLin Guo - Sun Microsystems char *minor_path = NULL;
554b453864fSLin Guo - Sun Microsystems char *minor_name = NULL;
555b453864fSLin Guo - Sun Microsystems char udi[HAL_PATH_MAX];
556b453864fSLin Guo - Sun Microsystems
557b453864fSLin Guo - Sun Microsystems get_dev_link_path(node, "ddi_pseudo",
558*3fb52c73SRaymond Chen "^usb/hid[0-9]+", &devlink, &minor_path, &minor_name);
559b453864fSLin Guo - Sun Microsystems
560b453864fSLin Guo - Sun Microsystems if ((minor_path == NULL) || (devlink == NULL)) {
561b453864fSLin Guo - Sun Microsystems
562b453864fSLin Guo - Sun Microsystems goto out;
563b453864fSLin Guo - Sun Microsystems }
564b453864fSLin Guo - Sun Microsystems
565b453864fSLin Guo - Sun Microsystems HAL_DEBUG(("devlink %s, minor_name %s", devlink, minor_name));
566b453864fSLin Guo - Sun Microsystems if ((strcmp(minor_name, "keyboard") != 0) &&
567b453864fSLin Guo - Sun Microsystems (strcmp(minor_name, "mouse") != 0)) {
568b453864fSLin Guo - Sun Microsystems
569b453864fSLin Guo - Sun Microsystems goto out;
570b453864fSLin Guo - Sun Microsystems }
5713622ad5aSLin Guo - Sun Microsystems
572b453864fSLin Guo - Sun Microsystems d = hal_device_new();
573b453864fSLin Guo - Sun Microsystems
574b453864fSLin Guo - Sun Microsystems devinfo_set_default_properties(d, usbd, node, minor_path);
575b453864fSLin Guo - Sun Microsystems hal_device_property_set_string(d, "info.subsystem", "input");
576b453864fSLin Guo - Sun Microsystems hal_device_property_set_string(d, "info.category", "input");
577b453864fSLin Guo - Sun Microsystems
578b453864fSLin Guo - Sun Microsystems hal_device_add_capability(d, "input");
579b453864fSLin Guo - Sun Microsystems
580b453864fSLin Guo - Sun Microsystems if (strcmp(minor_name, "keyboard") == 0) {
581b453864fSLin Guo - Sun Microsystems hal_device_add_capability(d, "input.keyboard");
582b453864fSLin Guo - Sun Microsystems hal_device_add_capability(d, "input.keys");
583b453864fSLin Guo - Sun Microsystems hal_device_add_capability(d, "button");
584b453864fSLin Guo - Sun Microsystems } else if (strcmp(minor_name, "mouse") == 0) {
585b453864fSLin Guo - Sun Microsystems hal_device_add_capability (d, "input.mouse");
586b453864fSLin Guo - Sun Microsystems }
587b453864fSLin Guo - Sun Microsystems
588b453864fSLin Guo - Sun Microsystems hal_device_property_set_string(d, "input.device", devlink);
589b453864fSLin Guo - Sun Microsystems hal_device_property_set_string(d, "input.originating_device",
590b453864fSLin Guo - Sun Microsystems hal_device_get_udi(usbd));
591b453864fSLin Guo - Sun Microsystems
592b453864fSLin Guo - Sun Microsystems hal_util_compute_udi(hald_get_gdl(), udi, sizeof (udi),
593b453864fSLin Guo - Sun Microsystems "%s_logicaldev_input", hal_device_get_udi(usbd));
5943622ad5aSLin Guo - Sun Microsystems
595b453864fSLin Guo - Sun Microsystems hal_device_set_udi(d, udi);
596b453864fSLin Guo - Sun Microsystems hal_device_property_set_string(d, "info.udi", udi);
597b453864fSLin Guo - Sun Microsystems
598b453864fSLin Guo - Sun Microsystems if (strcmp(minor_name, "keyboard") == 0) {
599b453864fSLin Guo - Sun Microsystems devinfo_add_enqueue(d, minor_path, &devinfo_usb_keyboard_handler);
600b453864fSLin Guo - Sun Microsystems } else {
601b453864fSLin Guo - Sun Microsystems devinfo_add_enqueue(d, minor_path, &devinfo_usb_handler);
602b453864fSLin Guo - Sun Microsystems }
603b453864fSLin Guo - Sun Microsystems
604b453864fSLin Guo - Sun Microsystems /* add to TDL so preprobing callouts and prober can access it */
605b453864fSLin Guo - Sun Microsystems hal_device_store_add(hald_get_tdl(), d);
606b453864fSLin Guo - Sun Microsystems
607b453864fSLin Guo - Sun Microsystems out:
608b453864fSLin Guo - Sun Microsystems if (devlink) {
609b453864fSLin Guo - Sun Microsystems free(devlink);
610b453864fSLin Guo - Sun Microsystems }
611b453864fSLin Guo - Sun Microsystems
612b453864fSLin Guo - Sun Microsystems if (minor_path) {
613b453864fSLin Guo - Sun Microsystems di_devfs_path_free(minor_path);
614b453864fSLin Guo - Sun Microsystems }
615b453864fSLin Guo - Sun Microsystems
616b453864fSLin Guo - Sun Microsystems return (d);
617b453864fSLin Guo - Sun Microsystems }
618b453864fSLin Guo - Sun Microsystems
61942a7bdedSjacobs static HalDevice *
devinfo_usb_scsa2usb_add(HalDevice * usbd,di_node_t node)620112cd14aSqz devinfo_usb_scsa2usb_add(HalDevice *usbd, di_node_t node)
62142a7bdedSjacobs {
62242a7bdedSjacobs HalDevice *d = NULL;
62342a7bdedSjacobs di_devlink_handle_t devlink_hdl;
624112cd14aSqz int major;
625112cd14aSqz di_minor_t minor;
626112cd14aSqz dev_t devt;
627112cd14aSqz char *minor_path = NULL;
628b453864fSLin Guo - Sun Microsystems char *minor_name = NULL;
62942a7bdedSjacobs char *devlink = NULL;
630112cd14aSqz char udi[HAL_PATH_MAX];
63118c2aff7Sartem
632*3fb52c73SRaymond Chen get_dev_link_path(node, "ddi_ctl:devctl:scsi",
633*3fb52c73SRaymond Chen "^usb/mass-storage[0-9]+", &devlink, &minor_path, &minor_name);
63442a7bdedSjacobs
63542a7bdedSjacobs if ((devlink == NULL) || (minor_path == NULL)) {
63618c2aff7Sartem goto out;
63718c2aff7Sartem }
63818c2aff7Sartem
63918c2aff7Sartem d = hal_device_new ();
64018c2aff7Sartem
64118c2aff7Sartem devinfo_set_default_properties (d, usbd, node, minor_path);
642112cd14aSqz hal_device_property_set_string (d, "scsi_host.solaris.device", devlink);
643112cd14aSqz hal_device_property_set_string (d, "info.category", "scsi_host");
644112cd14aSqz hal_device_property_set_int (d, "scsi_host.host", 0);
64518c2aff7Sartem
646112cd14aSqz hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
647112cd14aSqz "%s/scsi_host%d", hal_device_get_udi (usbd),
648112cd14aSqz hal_device_property_get_int (d, "scsi_host.host"));
649112cd14aSqz hal_device_set_udi (d, udi);
650112cd14aSqz hal_device_property_set_string (d, "info.udi", udi);
651112cd14aSqz hal_device_property_set_string (d, "info.product", "SCSI Host Adapter");
65218c2aff7Sartem
65318c2aff7Sartem devinfo_add_enqueue (d, minor_path, &devinfo_usb_handler);
65418c2aff7Sartem
65518c2aff7Sartem out:
65618c2aff7Sartem if (devlink) {
65718c2aff7Sartem free(devlink);
65818c2aff7Sartem }
65918c2aff7Sartem if (minor_path) {
66018c2aff7Sartem di_devfs_path_free (minor_path);
66118c2aff7Sartem }
66218c2aff7Sartem
66318c2aff7Sartem return (d);
66418c2aff7Sartem }
66518c2aff7Sartem
66642a7bdedSjacobs static HalDevice *
devinfo_usb_printer_add(HalDevice * parent,di_node_t node)667112cd14aSqz devinfo_usb_printer_add(HalDevice *parent, di_node_t node)
66842a7bdedSjacobs {
669d5c32991SNorm Jacobs char *properties[] = { "vendor", "product", "serial", NULL };
670d5c32991SNorm Jacobs int i;
67142a7bdedSjacobs HalDevice *d = NULL;
672112cd14aSqz char udi[HAL_PATH_MAX];
67342a7bdedSjacobs char *s;
674b453864fSLin Guo - Sun Microsystems char *devlink = NULL, *minor_path = NULL, *minor_name = NULL;
675d5c32991SNorm Jacobs const char *subsystem;
67642a7bdedSjacobs
677b453864fSLin Guo - Sun Microsystems get_dev_link_path(node, "ddi_printer", "printers/.+", &devlink, &minor_path, &minor_name);
67842a7bdedSjacobs
67942a7bdedSjacobs if ((devlink == NULL) || (minor_path == NULL)) {
68042a7bdedSjacobs goto out;
68142a7bdedSjacobs }
68242a7bdedSjacobs
68342a7bdedSjacobs d = hal_device_new ();
68442a7bdedSjacobs
68542a7bdedSjacobs devinfo_set_default_properties (d, parent, node, minor_path);
686112cd14aSqz hal_device_property_set_string (d, "info.category", "printer");
68742a7bdedSjacobs hal_device_add_capability (d, "printer");
68842a7bdedSjacobs
68942a7bdedSjacobs /* add printer properties */
690112cd14aSqz hal_device_property_set_string (d, "printer.device", devlink);
691d5c32991SNorm Jacobs
692d5c32991SNorm Jacobs /* copy parent's selected usb* properties to printer properties */
693d5c32991SNorm Jacobs subsystem = hal_device_property_get_string (parent, "info.subsystem");
694d5c32991SNorm Jacobs for (i = 0; properties[i] != NULL; i++) {
695d5c32991SNorm Jacobs char src[32], dst[32]; /* "subsystem.property" names */
696d5c32991SNorm Jacobs
697d5c32991SNorm Jacobs snprintf(src, sizeof (src), "%s.%s", subsystem, properties[i]);
698d5c32991SNorm Jacobs snprintf(dst, sizeof (dst), "printer.%s", properties[i]);
699d5c32991SNorm Jacobs hal_device_copy_property(parent, src, d, dst);
700d5c32991SNorm Jacobs }
70142a7bdedSjacobs
70242a7bdedSjacobs devinfo_add_enqueue (d, minor_path, &devinfo_usb_printer_handler);
70342a7bdedSjacobs
70442a7bdedSjacobs out:
70542a7bdedSjacobs if (devlink) {
70642a7bdedSjacobs free(devlink);
70742a7bdedSjacobs }
70842a7bdedSjacobs if (minor_path) {
70942a7bdedSjacobs di_devfs_path_free (minor_path);
71042a7bdedSjacobs }
71142a7bdedSjacobs
71242a7bdedSjacobs return (d);
71342a7bdedSjacobs }
71442a7bdedSjacobs
71542a7bdedSjacobs const gchar *
devinfo_printer_prnio_get_prober(HalDevice * d,int * timeout)71642a7bdedSjacobs devinfo_printer_prnio_get_prober (HalDevice *d, int *timeout)
71742a7bdedSjacobs {
71842a7bdedSjacobs *timeout = 5 * 1000; /* 5 second timeout */
71942a7bdedSjacobs return ("hald-probe-printer");
72042a7bdedSjacobs }
721b453864fSLin Guo - Sun Microsystems
722b453864fSLin Guo - Sun Microsystems const gchar *
devinfo_keyboard_get_prober(HalDevice * d,int * timeout)723b453864fSLin Guo - Sun Microsystems devinfo_keyboard_get_prober(HalDevice *d, int *timeout)
724b453864fSLin Guo - Sun Microsystems {
725b453864fSLin Guo - Sun Microsystems *timeout = 5 * 1000; /* 5 second timeout */
726b453864fSLin Guo - Sun Microsystems return ("hald-probe-xkb");
727b453864fSLin Guo - Sun Microsystems }
728