Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

usb_bus_device.c

00001 /***************************************************************************
00002  * CVSID: $Id: usb_bus_device.c,v 1.8 2004/04/22 21:52:06 david Exp $
00003  *
00004  * USB bus device
00005  *
00006  * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
00007  *
00008  * Licensed under the Academic Free License version 2.0
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 "../hald.h"
00042 
00043 #include "bus_device.h"
00044 #include "common.h"
00045 
00054 static char *usb_ids = NULL;
00055 
00057 static unsigned int usb_ids_len;
00058 
00060 static unsigned int usb_ids_iter_pos;
00061 
00063 static void
00064 usb_ids_line_iter_init ()
00065 {
00066     usb_ids_iter_pos = 0;
00067 }
00068 
00070 #define USB_IDS_MAX_LINE_LEN 512
00071 
00079 static char *
00080 usb_ids_line_iter_get_line (unsigned int *line_len)
00081 {
00082     unsigned int i;
00083     static char line[USB_IDS_MAX_LINE_LEN];
00084 
00085     for (i = 0;
00086          usb_ids_iter_pos < usb_ids_len &&
00087          i < USB_IDS_MAX_LINE_LEN - 1 &&
00088          usb_ids[usb_ids_iter_pos] != '\n'; i++, usb_ids_iter_pos++) {
00089         line[i] = usb_ids[usb_ids_iter_pos];
00090     }
00091 
00092     line[i] = '\0';
00093     if (line_len != NULL)
00094         *line_len = i;
00095 
00096     usb_ids_iter_pos++;
00097 
00098     return line;
00099 }
00100 
00105 static dbus_bool_t
00106 usb_ids_line_iter_has_more ()
00107 {
00108     return usb_ids_iter_pos < usb_ids_len;
00109 }
00110 
00121 static void
00122 usb_ids_find (int vendor_id, int product_id,
00123           char **vendor_name, char **product_name)
00124 {
00125     char *line;
00126     unsigned int i;
00127     unsigned int line_len;
00128     unsigned int num_tabs;
00129     char rep_vi[8];
00130     char rep_pi[8];
00131     static char store_vn[USB_IDS_MAX_LINE_LEN];
00132     static char store_pn[USB_IDS_MAX_LINE_LEN];
00133     dbus_bool_t vendor_matched = FALSE;
00134 
00135     snprintf (rep_vi, 8, "%04x", vendor_id);
00136     snprintf (rep_pi, 8, "%04x", product_id);
00137 
00138     *vendor_name = NULL;
00139     *product_name = NULL;
00140 
00141     for (usb_ids_line_iter_init (); usb_ids_line_iter_has_more ();) {
00142         line = usb_ids_line_iter_get_line (&line_len);
00143 
00144         /* skip lines with no content */
00145         if (line_len < 4)
00146             continue;
00147 
00148         /* skip comments */
00149         if (line[0] == '#')
00150             continue;
00151 
00152         /* count number of tabs */
00153         num_tabs = 0;
00154         for (i = 0; i < line_len; i++) {
00155             if (line[i] != '\t')
00156                 break;
00157             num_tabs++;
00158         }
00159 
00160         switch (num_tabs) {
00161         case 0:
00162             /* vendor names */
00163             vendor_matched = FALSE;
00164 
00165             /* check vendor_id */
00166             if (vendor_id != 0) {
00167                 if (memcmp (line, rep_vi, 4) == 0) {
00168                     /* found it */
00169                     vendor_matched = TRUE;
00170 
00171                     for (i = 4; i < line_len; i++) {
00172                         if (!isspace (line[i]))
00173                             break;
00174                     }
00175                     strncpy (store_vn, line + i,
00176                          USB_IDS_MAX_LINE_LEN);
00177                     *vendor_name = store_vn;
00178                 }
00179             }
00180             break;
00181 
00182         case 1:
00183             /* product names */
00184             if (!vendor_matched)
00185                 continue;
00186 
00187             /* check product_id */
00188             if (product_id != 0) {
00189                 if (memcmp (line + 1, rep_pi, 4) == 0) {
00190                     /* found it */
00191                     for (i = 5; i < line_len; i++) {
00192                         if (!isspace (line[i]))
00193                             break;
00194                     }
00195                     strncpy (store_pn, line + i,
00196                          USB_IDS_MAX_LINE_LEN);
00197                     *product_name = store_pn;
00198 
00199                     /* no need to continue the search */
00200                     return;
00201                 }
00202             }
00203             break;
00204 
00205         default:
00206             break;
00207         }
00208 
00209     }
00210 }
00211 
00219 static dbus_bool_t
00220 usb_ids_load (const char *path)
00221 {
00222     FILE *fp;
00223     unsigned int num_read;
00224 
00225     fp = fopen (path, "r");
00226     if (fp == NULL) {
00227         printf ("couldn't open USB database at %s,", path);
00228         return FALSE;
00229     }
00230 
00231     fseek (fp, 0, SEEK_END);
00232     usb_ids_len = ftell (fp);
00233     fseek (fp, 0, SEEK_SET);
00234 
00235     usb_ids = malloc (usb_ids_len);
00236     if (usb_ids == NULL) {
00237         printf
00238             ("Couldn't allocate %d bytes for USB database file\n",
00239              usb_ids_len);
00240         return FALSE;
00241     }
00242 
00243     num_read = fread (usb_ids, sizeof (char), usb_ids_len, fp);
00244     if (usb_ids_len != num_read) {
00245         printf ("Error loading USB database file\n");
00246         free (usb_ids);
00247         usb_ids = NULL;
00248         return FALSE;
00249     }
00250 
00251     return TRUE;
00252 }
00253 
00258 static dbus_bool_t
00259 usb_ids_free ()
00260 {
00261     if (usb_ids != NULL) {
00262         free (usb_ids);
00263         usb_ids = NULL;
00264         return TRUE;
00265     }
00266     return FALSE;
00267 }
00268 
00269 
00273 typedef struct usb_proc_info_s {
00274     int t_bus;       
00275     int t_level;         
00276     int t_parent;        
00277     int t_port;      
00278     int t_count;         
00279     int t_device;        
00280     int t_speed_bcd;     
00281     int t_max_children;  
00282     int d_version_bcd;   
00284     struct usb_proc_info_s *next;
00286 } usb_proc_info;
00287 
00289 static usb_proc_info *usb_proc_head = NULL;
00290 
00292 static usb_proc_info *usb_proc_cur_info = NULL;
00293 
00300 static usb_proc_info *
00301 usb_proc_find_virtual_hub (int bus_number)
00302 {
00303     usb_proc_info *i;
00304     for (i = usb_proc_head; i != NULL; i = i->next) {
00305         if (i->t_bus == bus_number && i->t_level == 0)
00306             return i;
00307     }
00308 
00309     return NULL;
00310 }
00311 
00312 
00320 static usb_proc_info *
00321 usb_proc_find_virtual_hub_child (int bus_number, int port_number)
00322 {
00323     usb_proc_info *i;
00324     for (i = usb_proc_head; i != NULL; i = i->next) {
00325         /* Note that /proc counts port starting from zero */
00326         if (i->t_bus == bus_number && i->t_level == 1 &&
00327             i->t_port == port_number - 1)
00328             return i;
00329     }
00330 
00331     return NULL;
00332 }
00333 
00342 static usb_proc_info *
00343 usb_proc_find_on_hub (int bus_number, int port_number,
00344               int parent_device_number)
00345 {
00346     usb_proc_info *i;
00347     for (i = usb_proc_head; i != NULL; i = i->next) {
00348         /* Note that /proc counts port starting from zero */
00349         if (i->t_bus == bus_number && i->t_port == port_number - 1
00350             && i->t_parent == parent_device_number)
00351             return i;
00352     }
00353 
00354     return NULL;
00355 }
00356 
00357 
00364 static void
00365 usb_proc_handle_topology (usb_proc_info * info, char *s)
00366 {
00367     info->t_bus = find_num ("Bus=", s, 10);
00368     info->t_level = find_num ("Lev=", s, 10);
00369     info->t_parent = find_num ("Prnt=", s, 10);
00370     info->t_port = find_num ("Port=", s, 10);
00371     info->t_count = find_num ("Cnt=", s, 10);
00372     info->t_device = find_num ("Dev#=", s, 10);
00373     info->t_speed_bcd = find_bcd2 ("Spd=", s);
00374     info->t_max_children = find_num ("MxCh=", s, 10);
00375 }
00376 
00383 static void
00384 usb_proc_handle_device_info (usb_proc_info * info, char *s)
00385 {
00386     info->d_version_bcd = find_bcd2 ("Ver=", s);
00387 }
00388 
00389 
00394 static void
00395 usb_proc_device_done (usb_proc_info * info)
00396 {
00397     info->next = usb_proc_head;
00398     usb_proc_head = info;
00399 }
00400 
00401 
00402 
00407 static void
00408 usb_proc_parse_line (char *s)
00409 {
00410     switch (s[0]) {
00411     case 'T':  /* topology; always present, indicates a new device */
00412         if (usb_proc_cur_info != NULL) {
00413             // beginning of a new device, done with current
00414             usb_proc_device_done (usb_proc_cur_info);
00415         }
00416 
00417         usb_proc_cur_info = malloc (sizeof (usb_proc_info));
00418 
00419         if (usb_proc_cur_info == NULL)
00420             DIE (("Cannot allocated memory"));
00421 
00422         usb_proc_handle_topology (usb_proc_cur_info, s);
00423         break;
00424 
00425     case 'B':       /* bandwidth */
00426         break;
00427 
00428     case 'D':       /* device information */
00429         usb_proc_handle_device_info (usb_proc_cur_info, s);
00430         break;
00431 
00432     case 'P':       /* more device information */
00433         break;
00434 
00435     case 'S':       /* device string information */
00436         break;
00437 
00438     case 'C':       /* config descriptor info */
00439         break;
00440 
00441     case 'I':       /* interface descriptor info */
00442         break;
00443 
00444     case 'E':       /* endpoint descriptor info */
00445         break;
00446 
00447     default:
00448         break;
00449     }
00450 }
00451 
00454 static void
00455 usb_proc_parse ()
00456 {
00457     FILE *f;
00458     char buf[256];
00459 
00460     /* We may be called multiple times; in fact we are called on every
00461      * hotplug.. so clean up old info
00462      */
00463     if (usb_proc_head != NULL) {
00464         usb_proc_info *i;
00465         usb_proc_info *next;
00466 
00467         for (i = usb_proc_head; i != NULL; i = next) {
00468             next = i->next;
00469             free (i);
00470         }
00471         usb_proc_head = NULL;
00472     }
00473 
00474     usb_proc_cur_info = NULL;
00475 
00476     f = fopen ("/proc/bus/usb/devices", "r");
00477     if (f == NULL)
00478         f = fopen
00479             ("/proc/bus/usb/devices_please-use-sysfs-instead",
00480              "r");
00481     if (f == NULL) {
00482         /*DIE (("Couldn't open /proc/bus/usb/devices"));*/
00483         return;
00484     }
00485 
00486     while (!feof (f)) {
00487         fgets (buf, 256, f);
00488         usb_proc_parse_line (buf);
00489     }
00490     usb_proc_device_done (usb_proc_cur_info);
00491 
00492 /*
00493     {
00494         usb_proc_info *i;
00495         for (i = usb_proc_head; i != NULL; i = i->next) {
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",
00504                 i->t_speed_bcd >> 8, i->t_speed_bcd & 0xff,
00505                 i->t_speed_bcd);
00506             printf ("  max_children      %d\n",
00507                 i->t_max_children);
00508             printf ("  version_bcd       %x.%x (0x%06x)\n",
00509                 i->d_version_bcd >> 8,
00510                 i->d_version_bcd & 0xff, i->d_version_bcd);
00511             printf ("\n");
00512         }
00513     }
00514 */
00515 }
00516 
00523 static void
00524 usb_add_caps_from_class (HalDevice * d,
00525              int if_class, int if_sub_class, int if_proto)
00526 {
00527     char *cat = NULL;
00528 
00529     switch (if_class) {
00530     case 0x09:
00531         cat = "usbhub";
00532         hal_device_add_capability (d, "usbhub");
00533         break;
00534     }
00535 
00536     if (cat != NULL)
00537         hal_device_property_set_string (d, "info.category", cat);
00538 }
00539 
00540 
00541 
00545 static void
00546 usb_device_init ()
00547 {
00548 
00549     /* get all drivers under /sys/bus/usb/drivers */
00550     drivers_collect ("usb");
00551 
00552     /* Load /usr/share/hwdata/usb.ids */
00553     usb_ids_load (HWDATA_DIR "/usb.ids");
00554 
00555     /* Parse /proc/bus/usb/devices */
00556 
00557     usb_proc_parse ();
00558 }
00559 
00560 
00564 static void
00565 usb_device_shutdown ()
00566 {
00567     usb_ids_free ();
00568 }
00569 
00578 static dbus_bool_t
00579 usb_device_accept (BusDeviceHandler *self, const char *path, 
00580            struct sysfs_device *device, dbus_bool_t is_probing)
00581 {
00582     unsigned int i;
00583 
00584     if (strcmp (device->bus, "usb") != 0)
00585         return FALSE;
00586 
00587     /* only USB interfaces got a : in the bus_id */
00588     for (i = 0; device->bus_id[i] != 0; i++) {
00589         if (device->bus_id[i] == ':') {
00590             return FALSE;
00591         }
00592     }
00593 
00594     return TRUE;
00595 }
00596 
00597 static char *
00598 usb_device_compute_udi (HalDevice *d, int append_num)
00599 {
00600     const char *serial;
00601     const char *format;
00602     static char buf[256];
00603 
00604     if (append_num == -1)
00605         format = "/org/freedesktop/Hal/devices/usb_%x_%x_%x_%d_%s";
00606     else
00607         format =
00608             "/org/freedesktop/Hal/devices/usb_%x_%x_%x_%d_%s-%d";
00609 
00610     if (hal_device_has_property (d, "usb.serial"))
00611         serial = hal_device_property_get_string (d, "usb.serial");
00612     else
00613         serial = "noserial";
00614 
00615     snprintf (buf, 256, format,
00616           hal_device_property_get_int (d, "usb.vendor_id"),
00617           hal_device_property_get_int (d, "usb.product_id"),
00618           hal_device_property_get_int (d, "usb.device_revision_bcd"),
00619           hal_device_property_get_int (d, "usb.cfg_value"),
00620           serial, append_num);
00621 
00622     return buf;
00623 }
00624 
00625 
00626 static void 
00627 usb_merge_info_from_proc (HalDevice* d)
00628 {
00629     int bus_number;
00630     const char *bus_id;
00631     usb_proc_info *proc_info;
00632     const char *parent_udi;
00633     HalDevice* parent;
00634 
00635     parent_udi = hal_device_property_get_string (d, "info.parent");
00636     parent = hal_device_store_find (hald_get_gdl (), parent_udi);
00637 
00638     /* Merge information from /proc/bus/usb/devices */
00639     proc_info = NULL;
00640     usb_proc_parse ();
00641 
00642     bus_id = get_last_element (hal_device_property_get_string (d, "linux.sysfs_path"));
00643 
00644     if (sscanf (bus_id, "usb%d", &bus_number) == 1) {
00645         /* Is of form "usb%d" which means that this is a USB virtual 
00646          * root hub, cf. drivers/usb/hcd.c in kernel 2.6
00647          */
00648         hal_device_property_set_int (d, "usb.bus_number", bus_number);
00649 
00650         proc_info = usb_proc_find_virtual_hub (bus_number);
00651     } else {
00652         int i;
00653         int len;
00654         int digit;
00655         int port_number;
00656         /* Not a root hub; According to the Linux kernel sources,
00657          * the name is of the form
00658          *
00659          *  "%d-%s[.%d]"
00660          *
00661          * where the first number is the bus-number, the middle string 
00662          * is the parent device and the last, optional, number is the 
00663          * port number in the event that the USB device is a hub.
00664          */
00665 
00666         len = strlen (bus_id);
00667 
00668         /* the first part is easy */
00669         bus_number = atoi (bus_id);
00670 
00671         hal_device_property_set_int (d, "usb.bus_number", bus_number);
00672 
00673         /* The naming convention also guarantees that
00674          *
00675          *   device is on a (non-virtual) hub    
00676          *
00677          *            IF AND ONLY IF  
00678          *
00679          *   the bus_id contains a "."
00680          */
00681         for (i = 0; i < len; i++) {
00682             if (bus_id[i] == '.')
00683                 break;
00684         }
00685 
00686         if (i == len) {
00687             /* Not on a hub; this means we must be a child of the 
00688              * root hub... Thus the name must is of the 
00689              * form "%d-%d"
00690              */
00691             if (sscanf (bus_id, "%d-%d",
00692                     &bus_number, &port_number) == 2) {
00693 
00694                 proc_info =
00695                     usb_proc_find_virtual_hub_child
00696                     (bus_number, port_number);
00697                 hal_device_property_set_int (d, "usb.port_number",
00698                              port_number);
00699             }
00700         } else {
00701             int parent_device_number;
00702 
00703             /* On a hub */
00704 
00705             /* This is quite a hack */
00706             port_number = 0;
00707             for (i = len - 1; i > 0 && isdigit (bus_id[i]);
00708                  --i) {
00709                 digit = (int) (bus_id[i] - '0');
00710                 port_number *= 10;
00711                 port_number += digit;
00712             }
00713 
00714             hal_device_property_set_int (d, "usb.port_number",
00715                          port_number);
00716 
00717             /* Ok, got the port number and bus number; this is 
00718              * not quite enough though.. We take the 
00719              * usb.linux.device_number from our parent and then
00720              *  we are set.. */
00721             if (parent == NULL) {
00722                 HAL_WARNING (("USB device is on a hub but "
00723                           "no parent??"));
00724                 /* have to give up then */
00725                 proc_info = NULL;
00726             } else {
00727                 parent_device_number =
00728                     hal_device_property_get_int (
00729                         parent, "usb.linux.device_number");
00730                 //printf("parent_device_number = %d\n", parent_device_number);
00731                 proc_info =
00732                     usb_proc_find_on_hub (bus_number,
00733                               port_number,
00734                              parent_device_number);
00735             }
00736 
00737         }
00738     }
00739 
00740 
00741     if (proc_info != NULL) {
00742         char kernel_path[32 + 1];
00743 
00744         hal_device_property_set_int (d, "usb.level_number",
00745                      proc_info->t_level);
00746         hal_device_property_set_int (d, "usb.linux.device_number",
00747                      proc_info->t_device);
00748         hal_device_property_set_int (d, "usb.linux.parent_number",
00749                      proc_info->t_device);
00750         hal_device_property_set_int (d, "usb.num_ports",
00751                      proc_info->t_max_children);
00752         hal_device_property_set_int (d, "usb.speed_bcd",
00753                      proc_info->t_speed_bcd);
00754         hal_device_property_set_int (d, "usb.version_bcd",
00755                      proc_info->d_version_bcd);
00756 
00757         /* Ok, now compute the unique name that the kernel sometimes 
00758          * use to refer to the device; it's #usb_make_path() as 
00759          * defined in include/linux/usb.h
00760          */
00761         if (proc_info->t_level == 0) {
00762             snprintf (kernel_path, 32, "usb-%s",
00763                   hal_device_property_get_string (d,
00764                               "usb.serial"));
00765             hal_device_property_set_string (d, "linux.kernel_devname",
00766                         kernel_path);
00767         } else {
00768             if (parent != NULL) {
00769                 if (proc_info->t_level == 1) {
00770                     snprintf (kernel_path, 32, "%s-%d",
00771                           hal_device_property_get_string
00772                           (parent,
00773                            "linux.kernel_devname"),
00774                           hal_device_property_get_int (
00775                               d,
00776                               "usb.port_number"));
00777                 } else {
00778                     snprintf (kernel_path, 32, "%s.%d",
00779                           hal_device_property_get_string
00780                           (parent,
00781                            "linux.kernel_devname"),
00782                           hal_device_property_get_int (
00783                               d,
00784                               "usb.port_number"));
00785                 }
00786                 hal_device_property_set_string (d,
00787                             "linux.kernel_devname",
00788                             kernel_path);
00789             }
00790         }
00791 
00792     }
00793 
00794 }
00795 
00796 
00797 static void 
00798 usb_device_pre_process (BusDeviceHandler *self,
00799             HalDevice *d,
00800             const char *sysfs_path,
00801             struct sysfs_device *device)
00802 {
00803     int i;
00804     char attr_name[SYSFS_NAME_LEN];
00805     int vendor_id = 0;
00806     int product_id = 0;
00807     char *vendor_name;
00808     char *product_name;
00809     char *vendor_name_kernel = NULL;
00810     char *product_name_kernel = NULL;
00811     char numeric_name[32];
00812     struct sysfs_attribute *cur;
00813     int len;
00814 
00815     dlist_for_each_data (sysfs_get_device_attributes (device), cur,
00816                  struct sysfs_attribute) {
00817 
00818         if (sysfs_get_name_from_path (cur->path,
00819                           attr_name,
00820                           SYSFS_NAME_LEN) != 0)
00821             continue;
00822 
00823         /* strip whitespace */
00824         len = strlen (cur->value);
00825         for (i = len - 1; i >= 0 && isspace (cur->value[i]); --i)
00826             cur->value[i] = '\0';
00827 
00828         /*printf("attr_name=%s -> '%s'\n", attr_name, cur->value); */
00829 
00830         if (strcmp (attr_name, "idProduct") == 0)
00831             product_id = parse_hex (cur->value);
00832         else if (strcmp (attr_name, "idVendor") == 0)
00833             vendor_id = parse_hex (cur->value);
00834         else if (strcmp (attr_name, "bcdDevice") == 0)
00835             hal_device_property_set_int (d, "usb.device_revision_bcd",
00836                          parse_hex (cur->value));
00837         else if (strcmp (attr_name, "bMaxPower") == 0)
00838             hal_device_property_set_int (d, "usb.max_power",
00839                          parse_dec (cur->value));
00840         else if (strcmp (attr_name, "serial") == 0
00841              && strlen (cur->value) > 0)
00842             hal_device_property_set_string (d, "usb.serial",
00843                         cur->value);
00844         else if (strcmp (attr_name, "bmAttributes") == 0) {
00845             int bmAttributes = parse_hex (cur->value);
00846 
00847             /* USB_CONFIG_ATT_SELFPOWER */
00848             hal_device_property_set_bool (d, "usb.is_self_powered",
00849                           (bmAttributes & 0x40) != 0);
00850             hal_device_property_set_bool (d, "usb.can_wake_up",
00851                           (bmAttributes & 0x20) != 0);
00852         }
00853 /*
00854         else if( strcmp(attr_name, "speed")==0 )
00855             hal_device_set_property_double(d, "usb.speed", 
00856                                            parse_double(cur->value));
00857 */
00858 
00859         else if (strcmp (attr_name, "manufacturer") == 0)
00860             vendor_name_kernel = cur->value;
00861         else if (strcmp (attr_name, "product") == 0)
00862             product_name_kernel = cur->value;
00863         else if (strcmp (attr_name, "bDeviceClass") == 0)
00864             hal_device_property_set_int (d, "usb.device_class",
00865                          parse_hex (cur->value));
00866         else if (strcmp (attr_name, "bDeviceSubClass") == 0)
00867             hal_device_property_set_int (d, "usb.device_subclass",
00868                          parse_hex (cur->value));
00869         else if (strcmp (attr_name, "bDeviceProtocol") == 0)
00870             hal_device_property_set_int (d, "usb.device_protocol",
00871                          parse_hex (cur->value));
00872 
00873         else if (strcmp (attr_name, "bNumConfigurations") == 0)
00874             hal_device_property_set_int (d, "usb.num_configurations",
00875                          parse_dec (cur->value));
00876         else if (strcmp (attr_name, "bConfigurationValue") == 0)
00877             hal_device_property_set_int (d, "usb.configuration_value",
00878                          parse_dec (cur->value));
00879 
00880         else if (strcmp (attr_name, "bNumInterfaces") == 0)
00881             hal_device_property_set_int (d, "usb.num_interfaces",
00882                          parse_dec (cur->value));
00883 
00884     }           /* for all attributes */
00885 
00886     hal_device_property_set_int (d, "usb.product_id", product_id);
00887     hal_device_property_set_int (d, "usb.vendor_id", vendor_id);
00888 
00889     /* Lookup names in usb.ids; these may override what the kernel told
00890      * us, but, hey, it's only a name; it's not something we are going
00891      * to match a device on... We prefer names from usb.ids as the kernel
00892      * name sometimes is just a hexnumber :-/
00893      *
00894      * Also provide best guess on name, Product and Vendor properties;
00895      * these can both be overridden in .fdi files.
00896      */
00897     usb_ids_find (vendor_id, product_id, &vendor_name, &product_name);
00898     if (vendor_name != NULL) {
00899         hal_device_property_set_string (d, "usb.vendor", vendor_name);
00900         hal_device_property_set_string (d, "info.vendor", vendor_name);
00901     } else if (vendor_name_kernel != NULL) {
00902         /* fallback on name supplied from kernel */
00903         hal_device_property_set_string (d, "usb.vendor",
00904                     vendor_name_kernel);
00905         hal_device_property_set_string (d, "info.vendor",
00906                     vendor_name_kernel);
00907     } else {
00908         /* last resort; use numeric name */
00909         snprintf (numeric_name, sizeof(numeric_name), "Unknown (0x%04x)", vendor_id);
00910         hal_device_property_set_string (d, "usb.vendor", numeric_name);
00911         hal_device_property_set_string (d, "info.vendor", numeric_name);
00912     }
00913 
00914     if (product_name != NULL) {
00915         hal_device_property_set_string (d, "usb.product", product_name);
00916         hal_device_property_set_string (d, "info.product", product_name);
00917     } else if (product_name_kernel != NULL) {
00918         /* name supplied from kernel (if available) */
00919         hal_device_property_set_string (d, "usb.product",
00920                     product_name_kernel);
00921         hal_device_property_set_string (d, "info.product",
00922                     product_name_kernel);
00923     } else {
00924         /* last resort; use numeric name */
00925         snprintf (numeric_name, sizeof(numeric_name), "Unknown (0x%04x)",
00926               product_id);
00927         hal_device_property_set_string (d, "usb.product", numeric_name);
00928         hal_device_property_set_string (d, "info.product", numeric_name);
00929     }
00930 
00931 
00932     /* Check device class */
00933     usb_add_caps_from_class (d, hal_device_property_get_int (d, "usb.device_class"),
00934                  hal_device_property_get_int (d, "usb.device_subclass"),
00935                  hal_device_property_get_int (d, "usb.device_protocol"));
00936 
00937     usb_merge_info_from_proc (d);
00938 }
00939 
00940 
00942 BusDeviceHandler usb_bus_handler = {
00943     usb_device_init,           
00944     bus_device_detection_done, 
00945     usb_device_shutdown,       
00946     bus_device_tick,           
00947     usb_device_accept,         
00948     bus_device_visit,          
00949     bus_device_removed,        
00950     usb_device_compute_udi,    
00951     usb_device_pre_process,    
00952     bus_device_got_udi,        
00953     "usb",                     
00954     "usb"                      
00955 };
00956 
00957 

Generated on Sat Apr 24 19:57:45 2004 for HAL by doxygen 1.3.6-20040222