00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029
00030 #include <ctype.h>
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <getopt.h>
00035 #include <assert.h>
00036 #include <unistd.h>
00037 #include <stdarg.h>
00038
00039 #include "../logger.h"
00040 #include "../device_store.h"
00041 #include "linux_usb.h"
00042
00051 static char *usb_ids = NULL;
00052
00054 static unsigned int usb_ids_len;
00055
00057 static unsigned int usb_ids_iter_pos;
00058
00060 static void
00061 usb_ids_line_iter_init ()
00062 {
00063 usb_ids_iter_pos = 0;
00064 }
00065
00067 #define USB_IDS_MAX_LINE_LEN 512
00068
00076 static char *
00077 usb_ids_line_iter_get_line (unsigned int *line_len)
00078 {
00079 unsigned int i;
00080 static char line[USB_IDS_MAX_LINE_LEN];
00081
00082 for (i = 0;
00083 usb_ids_iter_pos < usb_ids_len &&
00084 i < USB_IDS_MAX_LINE_LEN - 1 &&
00085 usb_ids[usb_ids_iter_pos] != '\n'; i++, usb_ids_iter_pos++) {
00086 line[i] = usb_ids[usb_ids_iter_pos];
00087 }
00088
00089 line[i] = '\0';
00090 if (line_len != NULL)
00091 *line_len = i;
00092
00093 usb_ids_iter_pos++;
00094
00095 return line;
00096 }
00097
00102 static dbus_bool_t
00103 usb_ids_line_iter_has_more ()
00104 {
00105 return usb_ids_iter_pos < usb_ids_len;
00106 }
00107
00118 static void
00119 usb_ids_find (int vendor_id, int product_id,
00120 char **vendor_name, char **product_name)
00121 {
00122 char *line;
00123 unsigned int i;
00124 unsigned int line_len;
00125 unsigned int num_tabs;
00126 char rep_vi[8];
00127 char rep_pi[8];
00128 static char store_vn[USB_IDS_MAX_LINE_LEN];
00129 static char store_pn[USB_IDS_MAX_LINE_LEN];
00130 dbus_bool_t vendor_matched = FALSE;
00131
00132 snprintf (rep_vi, 8, "%04x", vendor_id);
00133 snprintf (rep_pi, 8, "%04x", product_id);
00134
00135 *vendor_name = NULL;
00136 *product_name = NULL;
00137
00138 for (usb_ids_line_iter_init (); usb_ids_line_iter_has_more ();) {
00139 line = usb_ids_line_iter_get_line (&line_len);
00140
00141
00142 if (line_len < 4)
00143 continue;
00144
00145
00146 if (line[0] == '#')
00147 continue;
00148
00149
00150 num_tabs = 0;
00151 for (i = 0; i < line_len; i++) {
00152 if (line[i] != '\t')
00153 break;
00154 num_tabs++;
00155 }
00156
00157 switch (num_tabs) {
00158 case 0:
00159
00160 vendor_matched = FALSE;
00161
00162
00163 if (vendor_id != 0) {
00164 if (memcmp (line, rep_vi, 4) == 0) {
00165
00166 vendor_matched = TRUE;
00167
00168 for (i = 4; i < line_len; i++) {
00169 if (!isspace (line[i]))
00170 break;
00171 }
00172 strncpy (store_vn, line + i,
00173 USB_IDS_MAX_LINE_LEN);
00174 *vendor_name = store_vn;
00175 }
00176 }
00177 break;
00178
00179 case 1:
00180
00181 if (!vendor_matched)
00182 continue;
00183
00184
00185 if (product_id != 0) {
00186 if (memcmp (line + 1, rep_pi, 4) == 0) {
00187
00188 for (i = 5; i < line_len; i++) {
00189 if (!isspace (line[i]))
00190 break;
00191 }
00192 strncpy (store_pn, line + i,
00193 USB_IDS_MAX_LINE_LEN);
00194 *product_name = store_pn;
00195
00196
00197 return;
00198 }
00199 }
00200 break;
00201
00202 default:
00203 break;
00204 }
00205
00206 }
00207 }
00208
00216 static dbus_bool_t
00217 usb_ids_load (const char *path)
00218 {
00219 FILE *fp;
00220 unsigned int num_read;
00221
00222 fp = fopen (path, "r");
00223 if (fp == NULL) {
00224 printf ("couldn't open USB database at %s,", path);
00225 return FALSE;
00226 }
00227
00228 fseek (fp, 0, SEEK_END);
00229 usb_ids_len = ftell (fp);
00230 fseek (fp, 0, SEEK_SET);
00231
00232 usb_ids = malloc (usb_ids_len);
00233 if (usb_ids == NULL) {
00234 printf
00235 ("Couldn't allocate %d bytes for USB database file\n",
00236 usb_ids_len);
00237 return FALSE;
00238 }
00239
00240 num_read = fread (usb_ids, sizeof (char), usb_ids_len, fp);
00241 if (usb_ids_len != num_read) {
00242 printf ("Error loading USB database file\n");
00243 free (usb_ids);
00244 usb_ids = NULL;
00245 return FALSE;
00246 }
00247
00248 return TRUE;
00249 }
00250
00255 static dbus_bool_t
00256 usb_ids_free ()
00257 {
00258 if (usb_ids != NULL) {
00259 free (usb_ids);
00260 usb_ids = NULL;
00261 return TRUE;
00262 }
00263 return FALSE;
00264 }
00265
00266
00270 typedef struct usb_proc_info_s {
00271 int t_bus;
00272 int t_level;
00273 int t_parent;
00274 int t_port;
00275 int t_count;
00276 int t_device;
00277 int t_speed_bcd;
00278 int t_max_children;
00279 int d_version_bcd;
00281 struct usb_proc_info_s *next;
00283 } usb_proc_info;
00284
00286 static usb_proc_info *usb_proc_head = NULL;
00287
00289 static usb_proc_info *usb_proc_cur_info = NULL;
00290
00297 static usb_proc_info *
00298 usb_proc_find_virtual_hub (int bus_number)
00299 {
00300 usb_proc_info *i;
00301 for (i = usb_proc_head; i != NULL; i = i->next) {
00302 if (i->t_bus == bus_number && i->t_level == 0)
00303 return i;
00304 }
00305
00306 return NULL;
00307 }
00308
00309
00317 static usb_proc_info *
00318 usb_proc_find_virtual_hub_child (int bus_number, int port_number)
00319 {
00320 usb_proc_info *i;
00321 for (i = usb_proc_head; i != NULL; i = i->next) {
00322
00323 if (i->t_bus == bus_number && i->t_level == 1 &&
00324 i->t_port == port_number - 1)
00325 return i;
00326 }
00327
00328 return NULL;
00329 }
00330
00339 static usb_proc_info *
00340 usb_proc_find_on_hub (int bus_number, int port_number,
00341 int parent_device_number)
00342 {
00343 usb_proc_info *i;
00344 for (i = usb_proc_head; i != NULL; i = i->next) {
00345
00346 if (i->t_bus == bus_number && i->t_port == port_number - 1
00347 && i->t_parent == parent_device_number)
00348 return i;
00349 }
00350
00351 return NULL;
00352 }
00353
00354
00361 static void
00362 usb_proc_handle_topology (usb_proc_info * info, char *s)
00363 {
00364 info->t_bus = find_num ("Bus=", s, 10);
00365 info->t_level = find_num ("Lev=", s, 10);
00366 info->t_parent = find_num ("Prnt=", s, 10);
00367 info->t_port = find_num ("Port=", s, 10);
00368 info->t_count = find_num ("Cnt=", s, 10);
00369 info->t_device = find_num ("Dev#=", s, 10);
00370 info->t_speed_bcd = find_bcd2 ("Spd=", s);
00371 info->t_max_children = find_num ("MxCh=", s, 10);
00372 }
00373
00380 static void
00381 usb_proc_handle_device_info (usb_proc_info * info, char *s)
00382 {
00383 info->d_version_bcd = find_bcd2 ("Ver=", s);
00384 }
00385
00386
00391 static void
00392 usb_proc_device_done (usb_proc_info * info)
00393 {
00394 info->next = usb_proc_head;
00395 usb_proc_head = info;
00396 }
00397
00398
00399
00404 static void
00405 usb_proc_parse_line (char *s)
00406 {
00407 switch (s[0]) {
00408 case 'T':
00409 if (usb_proc_cur_info != NULL) {
00410
00411 usb_proc_device_done (usb_proc_cur_info);
00412 }
00413
00414 usb_proc_cur_info = malloc (sizeof (usb_proc_info));
00415
00416 if (usb_proc_cur_info == NULL)
00417 DIE (("Cannot allocated memory"));
00418
00419 usb_proc_handle_topology (usb_proc_cur_info, s);
00420 break;
00421
00422 case 'B':
00423 break;
00424
00425 case 'D':
00426 usb_proc_handle_device_info (usb_proc_cur_info, s);
00427 break;
00428
00429 case 'P':
00430 break;
00431
00432 case 'S':
00433 break;
00434
00435 case 'C':
00436 break;
00437
00438 case 'I':
00439 break;
00440
00441 case 'E':
00442 break;
00443
00444 default:
00445 break;
00446 }
00447 }
00448
00451 static void
00452 usb_proc_parse ()
00453 {
00454 FILE *f;
00455 char buf[256];
00456
00457
00458
00459
00460 if (usb_proc_head != NULL) {
00461 usb_proc_info *i;
00462 usb_proc_info *next;
00463
00464 for (i = usb_proc_head; i != NULL; i = next) {
00465 next = i->next;
00466 free (i);
00467 }
00468 usb_proc_head = NULL;
00469 }
00470
00471 usb_proc_cur_info = NULL;
00472
00473 f = fopen ("/proc/bus/usb/devices", "r");
00474 if (f == NULL)
00475 f = fopen
00476 ("/proc/bus/usb/devices_please-use-sysfs-instead",
00477 "r");
00478 if (f == NULL) {
00479 return;
00480 }
00481
00482 while (!feof (f)) {
00483 fgets (buf, 256, f);
00484 usb_proc_parse_line (buf);
00485 }
00486 usb_proc_device_done (usb_proc_cur_info);
00487
00488 {
00489 usb_proc_info *i;
00490 for (i = usb_proc_head; i != NULL; i = i->next) {
00491 printf ("/p/b/u/d entry\n");
00492 printf (" bus %d\n", i->t_bus);
00493 printf (" level %d\n", i->t_level);
00494 printf (" parent %d\n", i->t_parent);
00495 printf (" port %d\n", i->t_port);
00496 printf (" count %d\n", i->t_count);
00497 printf (" device %d\n", i->t_device);
00498 printf (" speed_bcd %x.%x (0x%06x)\n",
00499 i->t_speed_bcd >> 8, i->t_speed_bcd & 0xff,
00500 i->t_speed_bcd);
00501 printf (" max_children %d\n",
00502 i->t_max_children);
00503 printf (" version_bcd %x.%x (0x%06x)\n",
00504 i->d_version_bcd >> 8,
00505 i->d_version_bcd & 0xff, i->d_version_bcd);
00506 printf ("\n");
00507 }
00508 }
00509 }
00510
00511
00521 static char *
00522 usbif_compute_udi (HalDevice * d, int append_num)
00523 {
00524 int i, len;
00525 const char *format;
00526 const char *pd;
00527 const char *name;
00528 static char buf[256];
00529
00530 if (append_num == -1)
00531 format = "/org/freedesktop/Hal/devices/usbif_%s_%d";
00532 else
00533 format = "/org/freedesktop/Hal/devices/usbif_%s_%d-%d";
00534
00535 pd = ds_property_get_string (d, "info.parent");
00536 len = strlen (pd);
00537 for (i = len - 1; pd[i] != '/' && i >= 0; i--);
00538 name = pd + i + 1;
00539
00540 snprintf (buf, 256, format,
00541 name,
00542 ds_property_get_int (d, "usbif.number"), append_num);
00543
00544 return buf;
00545 }
00546
00547
00567 static char *
00568 usb_compute_udi (HalDevice * d, int append_num)
00569 {
00570 const char *serial;
00571 const char *format;
00572 static char buf[256];
00573
00574 if (append_num == -1)
00575 format = "/org/freedesktop/Hal/devices/usb_%x_%x_%x_%d_%s";
00576 else
00577 format =
00578 "/org/freedesktop/Hal/devices/usb_%x_%x_%x_%d_%s-%d";
00579
00580 if (ds_property_exists (d, "usb.serial"))
00581 serial = ds_property_get_string (d, "usb.serial");
00582 else
00583 serial = "noserial";
00584
00585 snprintf (buf, 256, format,
00586 ds_property_get_int (d, "usb.vendor_id"),
00587 ds_property_get_int (d, "usb.product_id"),
00588 ds_property_get_int (d, "usb.device_revision_bcd"),
00589 ds_property_get_int (d, "usb.cfg_value"),
00590 serial, append_num);
00591
00592 return buf;
00593 }
00594
00595
00604 static void
00605 usb_add_caps_from_class (HalDevice * d,
00606 int if_class, int if_sub_class, int if_proto)
00607 {
00608 char *cat = NULL;
00609
00610 switch (if_class) {
00611 case 0x01:
00612 cat = "multimedia.audio";
00613 ds_add_capability (d, "multimedia.audio");
00614 break;
00615 case 0x02:
00616 if (if_sub_class == 0x06) {
00617 cat = "net";
00618 ds_add_capability (d, "net");
00619 ds_add_capability (d, "net.ethernet");
00620 } else if (if_sub_class == 0x02 && if_proto == 0x01) {
00621 cat = "modem";
00622 ds_add_capability (d, "modem");
00623 }
00624 break;
00625 case 0x03:
00626 cat = "input";
00627 ds_add_capability (d, "input");
00628 if (if_sub_class == 0x00 || if_sub_class == 0x01) {
00629 if (if_proto == 0x01) {
00630 cat = "input.keyboard";
00631 ds_add_capability (d, "input.keyboard");
00632 } else if (if_proto == 0x02) {
00633 cat = "input.mouse";
00634 ds_add_capability (d, "input.mouse");
00635 }
00636 }
00637 break;
00638 case 0x04:
00639 break;
00640 case 0x05:
00641 break;
00642 case 0x06:
00643 break;
00644 case 0x07:
00645 cat = "printer";
00646 ds_add_capability (d, "printer");
00647 break;
00648 case 0x08:
00649 cat = "storage_controller";
00650 ds_add_capability (d, "storage_controller");
00651 break;
00652 case 0x09:
00653 cat = "hub";
00654 ds_add_capability (d, "hub");
00655 break;
00656 case 0x0a:
00657 break;
00658 case 0xe0:
00659 if (if_sub_class == 0x01 && if_proto == 0x01) {
00660 cat = "bluetooth_adaptor";
00661 ds_add_capability (d, "bluetooth_adaptor");
00662 }
00663 break;
00664 }
00665
00666 if (cat != NULL)
00667 ds_property_set_string (d, "info.category", cat);
00668 }
00669
00670
00671
00672 static void visit_device_usbif_got_parent (HalDevice * parent,
00673 void *data1, void *data2);
00674
00680 static void
00681 visit_device_usb_interface (const char *path, struct sysfs_device *device)
00682 {
00683 int i;
00684 int len;
00685 struct sysfs_attribute *cur;
00686 HalDevice *d;
00687 const char *driver;
00688 char attr_name[SYSFS_NAME_LEN];
00689 char *parent_sysfs_path;
00690
00691
00692
00693
00694 d = ds_device_new ();
00695 ds_property_set_string (d, "info.bus", "usbif");
00696 ds_property_set_string (d, "linux.sysfs_path", path);
00697 ds_property_set_string (d, "linux.sysfs_path_device", path);
00702 ds_property_set_string (d, "usbif.linux.sysfs_path", path);
00703 ds_property_set_bool (d, "info.virtual", TRUE);
00704
00705
00706 driver = drivers_lookup (path);
00707 if (driver != NULL)
00708 ds_property_set_string (d, "linux.driver", driver);
00709
00710
00711 if (device->directory == NULL
00712 || device->directory->attributes == NULL)
00713 return;
00714
00715 dlist_for_each_data (sysfs_get_device_attributes (device), cur,
00716 struct sysfs_attribute) {
00717
00718 if (sysfs_get_name_from_path (cur->path,
00719 attr_name,
00720 SYSFS_NAME_LEN) != 0)
00721 continue;
00722
00723
00724 len = strlen (cur->value);
00725 for (i = len - 1; i > 0 && isspace (cur->value[i]); --i)
00726 cur->value[i] = '\0';
00727
00728
00729
00730 if (strcmp (attr_name, "bInterfaceClass") == 0)
00731 ds_property_set_int (d, "usbif.interface_class",
00732 parse_dec (cur->value));
00733 else if (strcmp (attr_name, "bInterfaceSubClass") == 0)
00734 ds_property_set_int (d, "usbif.interface_subclass",
00735 parse_dec (cur->value));
00736 else if (strcmp (attr_name, "bInterfaceProtocol") == 0)
00737 ds_property_set_int (d, "usbif.interface_protocol",
00738 parse_dec (cur->value));
00739 else if (strcmp (attr_name, "bInterfaceNumber") == 0)
00740 ds_property_set_int (d, "usbif.number",
00741 parse_dec (cur->value));
00742 }
00743
00744 parent_sysfs_path = get_parent_sysfs_path (path);
00745
00746
00747
00748
00749
00750 ds_device_async_find_by_key_value_string
00751 ("linux.sysfs_path_device", parent_sysfs_path, TRUE,
00752 visit_device_usbif_got_parent, (void *) d, NULL,
00753 is_probing ? 0 : HAL_LINUX_HOTPLUG_TIMEOUT);
00754
00755 free (parent_sysfs_path);
00756 }
00757
00765 static void
00766 visit_device_usbif_got_parent (HalDevice * parent,
00767 void *data1, void *data2)
00768 {
00769 char *new_udi = NULL;
00770 HalDevice *new_d = NULL;
00771 HalDevice *d = (HalDevice *) data1;
00772
00773 if (parent == NULL) {
00774
00775 HAL_ERROR (("No parent for USB interface!"));
00776 ds_device_destroy (d);
00777 return;
00778 }
00779
00780 ds_property_set_string (d, "info.parent", parent->udi);
00781
00782
00783
00784
00785 usb_add_caps_from_class (parent,
00786 ds_property_get_int (d,
00787 "usbif.interface_class"),
00788 ds_property_get_int (d,
00789 "usbif.interface_subclass"),
00790 ds_property_get_int (d,
00791 "usbif.interface_protocol"));
00792
00793 ds_property_set_string (d, "info.parent", parent->udi);
00794 ds_property_set_string (d, "info.physical_device", parent->udi);
00795 ds_property_set_int (d, "usbif.device_vendor_id",
00796 ds_property_get_int (parent,
00797 "usb.vendor_id"));
00798 ds_property_set_int (d, "usbif.device_product_id",
00799 ds_property_get_int (parent,
00800 "usb.product_id"));
00801
00802 new_udi = rename_and_merge (d, usbif_compute_udi, "usbif");
00803 if (new_udi != NULL) {
00804 new_d = ds_device_find (new_udi);
00805 if (new_d != NULL) {
00806 ds_gdl_add (new_d);
00807 }
00808 }
00809
00810 }
00811
00812
00813
00814 static void visit_device_usb_got_parent (HalDevice * parent,
00815 void *data1, void *data2);
00816
00825 void
00826 visit_device_usb (const char *path, struct sysfs_device *device)
00827 {
00828 int i;
00829 int len;
00830 dbus_bool_t is_interface;
00831 struct sysfs_attribute *cur;
00832 HalDevice *d;
00833 char attr_name[SYSFS_NAME_LEN];
00834 int vendor_id = 0;
00835 int product_id = 0;
00836 char *vendor_name;
00837 char *product_name;
00838 char *vendor_name_kernel = NULL;
00839 char *product_name_kernel = NULL;
00840 const char *driver;
00841 char *parent_sysfs_path;
00842 char numeric_name[32];
00843
00844
00845
00846 if (device->directory == NULL
00847 || device->directory->attributes == NULL)
00848 return;
00849
00850
00851 is_interface = FALSE;
00852 for (i = 0; device->bus_id[i] != 0; i++) {
00853 if (device->bus_id[i] == ':') {
00854 is_interface = TRUE;
00855 break;
00856 }
00857 }
00858
00859
00860 if (is_interface) {
00861 HAL_INFO (("usb device @ %s is an interface", path));
00862 visit_device_usb_interface (path, device);
00863 return;
00864 }
00865
00866
00867 d = ds_device_new ();
00868 ds_property_set_string (d, "info.bus", "usb");
00869 ds_property_set_string (d, "linux.sysfs_path", path);
00870 ds_property_set_string (d, "linux.sysfs_bus_id", device->bus_id);
00871 ds_property_set_string (d, "linux.sysfs_path_device", path);
00872
00880 ds_property_set_string (d, "usb.linux.sysfs_path", path);
00881
00882
00883
00884 driver = drivers_lookup (path);
00885 if (driver != NULL)
00886 ds_property_set_string (d, "linux.driver", driver);
00887
00888 dlist_for_each_data (sysfs_get_device_attributes (device), cur,
00889 struct sysfs_attribute) {
00890
00891 if (sysfs_get_name_from_path (cur->path,
00892 attr_name,
00893 SYSFS_NAME_LEN) != 0)
00894 continue;
00895
00896
00897 len = strlen (cur->value);
00898 for (i = len - 1; i >= 0 && isspace (cur->value[i]); --i)
00899 cur->value[i] = '\0';
00900
00901
00902
00903 if (strcmp (attr_name, "idProduct") == 0)
00904 product_id = parse_hex (cur->value);
00905 else if (strcmp (attr_name, "idVendor") == 0)
00906 vendor_id = parse_hex (cur->value);
00907 else if (strcmp (attr_name, "bcdDevice") == 0)
00908 ds_property_set_int (d, "usb.device_revision_bcd",
00909 parse_hex (cur->value));
00910 else if (strcmp (attr_name, "bMaxPower") == 0)
00911 ds_property_set_int (d, "usb.max_power",
00912 parse_dec (cur->value));
00913 else if (strcmp (attr_name, "serial") == 0
00914 && strlen (cur->value) > 0)
00915 ds_property_set_string (d, "usb.serial",
00916 cur->value);
00917 else if (strcmp (attr_name, "bmAttributes") == 0) {
00918 int bmAttributes = parse_hex (cur->value);
00919
00920
00921 ds_property_set_bool (d, "usb.is_self_powered",
00922 (bmAttributes & 0x40) != 0);
00923 ds_property_set_bool (d, "usb.can_wake_up",
00924 (bmAttributes & 0x20) != 0);
00925 }
00926
00927
00928
00929
00930
00931
00932 else if (strcmp (attr_name, "manufacturer") == 0)
00933 vendor_name_kernel = cur->value;
00934 else if (strcmp (attr_name, "product") == 0)
00935 product_name_kernel = cur->value;
00936 else if (strcmp (attr_name, "bDeviceClass") == 0)
00937 ds_property_set_int (d, "usb.device_class",
00938 parse_hex (cur->value));
00939 else if (strcmp (attr_name, "bDeviceSubClass") == 0)
00940 ds_property_set_int (d, "usb.device_subclass",
00941 parse_hex (cur->value));
00942 else if (strcmp (attr_name, "bDeviceProtocol") == 0)
00943 ds_property_set_int (d, "usb.device_protocol",
00944 parse_hex (cur->value));
00945
00946 else if (strcmp (attr_name, "bNumConfigurations") == 0)
00947 ds_property_set_int (d, "usb.num_configurations",
00948 parse_dec (cur->value));
00949 else if (strcmp (attr_name, "bConfigurationValue") == 0)
00950 ds_property_set_int (d, "usb.configuration_value",
00951 parse_dec (cur->value));
00952
00953 else if (strcmp (attr_name, "bNumInterfaces") == 0)
00954 ds_property_set_int (d, "usb.num_interfaces",
00955 parse_dec (cur->value));
00956
00957 }
00958
00959 ds_property_set_int (d, "usb.product_id", product_id);
00960 ds_property_set_int (d, "usb.vendor_id", vendor_id);
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970 usb_ids_find (vendor_id, product_id, &vendor_name, &product_name);
00971 if (vendor_name != NULL) {
00972 ds_property_set_string (d, "usb.vendor", vendor_name);
00973 ds_property_set_string (d, "info.vendor", vendor_name);
00974 } else if (vendor_name_kernel != NULL) {
00975
00976 ds_property_set_string (d, "usb.vendor",
00977 vendor_name_kernel);
00978 ds_property_set_string (d, "info.vendor",
00979 vendor_name_kernel);
00980 } else {
00981
00982 snprintf (numeric_name, 32, "Unknown (0x%04x)", vendor_id);
00983 ds_property_set_string (d, "usb.vendor", numeric_name);
00984 ds_property_set_string (d, "info.vendor", numeric_name);
00985 }
00986
00987 if (product_name != NULL) {
00988 ds_property_set_string (d, "usb.product", product_name);
00989 ds_property_set_string (d, "info.product", product_name);
00990 } else if (product_name_kernel != NULL) {
00991
00992 ds_property_set_string (d, "usb.product",
00993 product_name_kernel);
00994 ds_property_set_string (d, "info.product",
00995 product_name_kernel);
00996 } else {
00997
00998 snprintf (numeric_name, 32, "Unknown (0x%04x)",
00999 product_id);
01000 ds_property_set_string (d, "usb.product", numeric_name);
01001 ds_property_set_string (d, "info.product", numeric_name);
01002 }
01003
01004
01005
01006 usb_add_caps_from_class (d,
01007 ds_property_get_int (d,
01008 "usb.device_class"),
01009 ds_property_get_int (d,
01010 "usb.device_subclass"),
01011 ds_property_get_int (d,
01012 "usb.device_protocol"));
01013
01014 parent_sysfs_path = get_parent_sysfs_path (path);
01015
01016
01017
01018
01019
01020 ds_device_async_find_by_key_value_string
01021 ("linux.sysfs_path_device", parent_sysfs_path, TRUE,
01022 visit_device_usb_got_parent, (void *) d, NULL,
01023 is_probing ? 0 : HAL_LINUX_HOTPLUG_TIMEOUT);
01024
01025 free (parent_sysfs_path);
01026 }
01027
01035 static void
01036 visit_device_usb_got_parent (HalDevice * parent, void *data1, void *data2)
01037 {
01038 char *new_udi = NULL;
01039 HalDevice *new_d = NULL;
01040 int bus_number;
01041 const char *bus_id;
01042 usb_proc_info *proc_info;
01043 HalDevice *d = (HalDevice *) data1;
01044
01045 if (parent != NULL) {
01046 ds_property_set_string (d, "info.parent", parent->udi);
01047 } else {
01048
01049 HAL_WARNING (("No parent for USB device!"));
01050 }
01051
01052
01053 proc_info = NULL;
01054
01055 bus_id = ds_property_get_string (d, "linux.sysfs_bus_id");
01056
01057 if (!is_probing) {
01058
01059 usb_proc_parse ();
01060 }
01061
01062 if (sscanf (bus_id, "usb%d", &bus_number) == 1) {
01063
01064
01065
01066 ds_property_set_int (d, "usb.bus_number", bus_number);
01067
01068 proc_info = usb_proc_find_virtual_hub (bus_number);
01069 } else {
01070 int i;
01071 int len;
01072 int digit;
01073 int port_number;
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084 len = strlen (bus_id);
01085
01086
01087 bus_number = atoi (bus_id);
01088
01089 ds_property_set_int (d, "usb.bus_number", bus_number);
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099 for (i = 0; i < len; i++) {
01100 if (bus_id[i] == '.')
01101 break;
01102 }
01103
01104 if (i == len) {
01105
01106
01107
01108
01109 if (sscanf (bus_id, "%d-%d",
01110 &bus_number, &port_number) == 2) {
01111
01112 proc_info =
01113 usb_proc_find_virtual_hub_child
01114 (bus_number, port_number);
01115 ds_property_set_int (d, "usb.port_number",
01116 port_number);
01117 }
01118 } else {
01119 int parent_device_number;
01120
01121
01122
01123
01124 port_number = 0;
01125 for (i = len - 1; i > 0 && isdigit (bus_id[i]);
01126 --i) {
01127 digit = (int) (bus_id[i] - '0');
01128 port_number *= 10;
01129 port_number += digit;
01130 }
01131
01132 ds_property_set_int (d, "usb.port_number",
01133 port_number);
01134
01135
01136
01137
01138
01139 if (parent == NULL) {
01140 HAL_WARNING (("USB device is on a hub but "
01141 "no parent??"));
01142
01143 proc_info = NULL;
01144 } else {
01145 parent_device_number =
01146 ds_property_get_int (
01147 parent, "usb.linux.device_number");
01148
01149 proc_info =
01150 usb_proc_find_on_hub (bus_number,
01151 port_number,
01152 parent_device_number);
01153 }
01154
01155 }
01156 }
01157
01158
01159 if (proc_info != NULL) {
01160 char kernel_path[32 + 1];
01161
01162 ds_property_set_int (d, "usb.level_number",
01163 proc_info->t_level);
01164 ds_property_set_int (d, "usb.linux.device_number",
01165 proc_info->t_device);
01166 ds_property_set_int (d, "usb.linux.parent_number",
01167 proc_info->t_device);
01168 ds_property_set_int (d, "usb.num_ports",
01169 proc_info->t_max_children);
01170 ds_property_set_int (d, "usb.speed_bcd",
01171 proc_info->t_speed_bcd);
01172 ds_property_set_int (d, "usb.version_bcd",
01173 proc_info->d_version_bcd);
01174
01175
01176
01177
01178
01179 if (proc_info->t_level == 0) {
01180 snprintf (kernel_path, 32, "usb-%s",
01181 ds_property_get_string (d,
01182 "usb.serial"));
01183 ds_property_set_string (d, "linux.kernel_devname",
01184 kernel_path);
01185 } else {
01186 if (parent != NULL) {
01187 if (proc_info->t_level == 1) {
01188 snprintf (kernel_path, 32, "%s-%d",
01189 ds_property_get_string
01190 (parent,
01191 "linux.kernel_devname"),
01192 ds_property_get_int (
01193 d,
01194 "usb.port_number"));
01195 } else {
01196 snprintf (kernel_path, 32, "%s.%d",
01197 ds_property_get_string
01198 (parent,
01199 "linux.kernel_devname"),
01200 ds_property_get_int (
01201 d,
01202 "usb.port_number"));
01203 }
01204 ds_property_set_string (d,
01205 "linux.kernel_devname",
01206 kernel_path);
01207 }
01208 }
01209
01210 }
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222 new_udi = rename_and_merge (d, usb_compute_udi, "usb");
01223 if (new_udi != NULL) {
01224 new_d = ds_device_find (new_udi);
01225 if (new_d != NULL) {
01226 ds_gdl_add (new_d);
01227 }
01228 }
01229 }
01230
01231
01235 void
01236 linux_usb_init ()
01237 {
01238
01239
01240 drivers_collect ("usb");
01241
01242
01243 usb_ids_load (HWDATA_DIR "/usb.ids");
01244
01245
01246
01247 usb_proc_parse ();
01248 }
01249
01254 void
01255 linux_usb_detection_done ()
01256 {
01257 }
01258
01259
01263 void
01264 linux_usb_shutdown ()
01265 {
01266 usb_ids_free ();
01267 }
01268