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