/[soft]/ldetect/trunk/usb.c
ViewVC logotype

Annotation of /ldetect/trunk/usb.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1357 - (hide annotations) (download)
Tue May 17 09:21:22 2011 UTC (12 years, 10 months ago) by dmorgan
File MIME type: text/plain
File size: 4560 byte(s)
Import  ldetect
1 dmorgan 1357 #define _GNU_SOURCE
2     #include <stdio.h>
3     #include <stdlib.h>
4     #include <string.h>
5     #include <unistd.h>
6     #include "libldetect.h"
7     #include "common.h"
8     #include "names.h"
9    
10     static char *proc_usb_path_default = "/proc/bus/usb/devices";
11     char *proc_usb_path = NULL;
12    
13     static void build_text(struct pciusb_entry *e, char *vendor_text, char *product_text) {
14     if(e) {
15     if(!vendor_text) {
16     char const* vendorname;
17     vendorname = names_vendor(e->vendor);
18     if(vendorname) {
19     vendor_text = malloc(strlen(vendorname)+2);
20     sprintf(vendor_text, "%s|", vendorname);
21     } else
22     vendor_text = strdup("Unknown|");
23     }
24     if(!product_text) {
25     char const* productname;
26     productname = names_product(e->vendor, e->device);
27     if(productname) {
28     product_text = strdup(productname);
29     } else
30     product_text = strdup("Unknown");
31     }
32     vendor_text = realloc(vendor_text, strlen(vendor_text)+strlen(product_text)+1);
33     e->text = vendor_text;
34     strcat(e->text, product_text);
35     free(product_text);
36     }
37     }
38    
39    
40     extern struct pciusb_entries usb_probe(void) {
41     FILE *f;
42     char buf[BUF_SIZE];
43     int line;
44     struct pciusb_entries r;
45     struct pciusb_entry *e = NULL;
46     char *vendor_text = NULL, *product_text = NULL;
47     r.nb = 0;
48    
49     names_init("/usr/share/usb.ids");
50     if (!(f = fopen(proc_usb_path ? proc_usb_path : proc_usb_path_default, "r"))) {
51     if (proc_usb_path) {
52     char *err_msg;
53     asprintf(&err_msg, "unable to open \"%s\"\n"
54     "You may have passed a wrong argument to the \"-u\" option.\n"
55     "fopen() sets errno to", proc_usb_path);
56     perror(err_msg);
57     free(err_msg);
58     }
59     r.entries = NULL;
60     return r;
61     }
62    
63     r.entries = malloc(sizeof(struct pciusb_entry) * MAX_DEVICES);
64     /* for further information on the format parsed by this state machine,
65     * read /usr/share/doc/kernel-doc-X.Y.Z/usb/proc_usb_info.txt */
66     for(line = 1; fgets(buf, sizeof(buf) - 1, f) && r.nb < MAX_DEVICES; line++) {
67    
68     switch (buf[0]) {
69     case 'T': {
70     unsigned short pci_bus, pci_device, usb_port;
71     build_text(e, vendor_text, product_text);
72     vendor_text = NULL;
73     product_text = NULL;
74     e = &r.entries[r.nb++];
75     pciusb_initialize(e);
76    
77     if (sscanf(buf, "T: Bus=%02hd Lev=%*02d Prnt=%*04d Port=%02hd Cnt=%*02d Dev#=%3hd Spd=%*3s MxCh=%*2d", &pci_bus, &usb_port, &pci_device) == 3) {
78     e->pci_bus = pci_bus;
79     e->pci_device = pci_device;
80     e->usb_port = usb_port;
81     } else fprintf(stderr, "%s %d: unknown ``T'' line\n", proc_usb_path, line);
82     break;
83     }
84     case 'P': {
85     unsigned short vendor, device;
86     if (sscanf(buf, "P: Vendor=%hx ProdID=%hx", &vendor, &device) == 2) {
87     e->vendor = vendor;
88     e->device = device;
89     } else fprintf(stderr, "%s %d: unknown ``P'' line\n", proc_usb_path, line);
90     break;
91     }
92     case 'I': if (e->class_id == 0 || e->module == NULL) {
93     char driver[50];
94     int class_id, sub, prot = 0;
95     if (sscanf(buf, "I:* If#=%*2d Alt=%*2d #EPs=%*2d Cls=%02x(%*5c) Sub=%02x Prot=%02x Driver=%s", &class_id, &sub, &prot, driver) >= 3) {
96     unsigned long cid = (class_id * 0x100 + sub) * 0x100 + prot;
97     if (e->class_id == 0)
98     e->class_id = cid;
99     if (strncmp(driver, "(none)", 6)) {
100     char *p;
101     /* Get current class if we are on the first one having used by a driver */
102     e->class_id = cid;
103     e->module = strdup(driver);
104     /* replace '-' characters with '_' to be compliant with modnames from modaliases */
105     p = e->module;
106     while (p && *p) {
107     if (*p == '-') *p = '_';
108     p++;
109     }
110     }
111     /* see linux/sound/usb/usbaudio.c::usb_audio_ids */
112     if (e->class_id == (0x1*0x100+ 0x01)) /* USB_AUDIO_CLASS*0x100 + USB_SUBCLASS_AUDIO_CONTROL*/
113     e->module = strdup("snd_usb_audio");
114    
115     } else if (sscanf(buf, "I: If#=%*2d Alt=%*2d #EPs=%*2d Cls=%02x(%*5c) Sub=%02x Prot=%02x Driver=%s", &class_id, &sub, &prot, driver) >= 3) {
116     /* Ignore interfaces not active */
117     } else fprintf(stderr, "%s %d: unknown ``I'' line\n", proc_usb_path, line);
118     break;
119     }
120     case 'S': {
121     int offset;
122     char dummy;
123     size_t length = strlen(buf) -1;
124     if (sscanf(buf, "S: Manufacturer=%n%c", &offset, &dummy) == 1) {
125     buf[length] = '|'; /* replacing '\n' by '|' */
126     vendor_text = strdup(buf + offset);
127     } else if (sscanf(buf, "S: Product=%n%c", &offset, &dummy) == 1) {
128     buf[length] = 0; /* removing '\n' */
129     product_text = strdup(buf + offset);
130     }
131     }
132     }
133     }
134    
135     build_text(e, vendor_text, product_text);
136    
137     fclose(f);
138    
139     /* shrink to real size */
140     r.entries = realloc(r.entries, sizeof(struct pciusb_entry) * r.nb);
141    
142     pciusb_find_modules(&r, "usbtable", DO_NOT_LOAD, 0);
143     return r;
144     }
145    

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.30