diff options
-rw-r--r-- | .cvsignore | 3 | ||||
-rw-r--r-- | Makefile | 13 | ||||
-rw-r--r-- | common.h | 10 | ||||
-rwxr-xr-x | generate_usbclass.pl | 35 | ||||
-rw-r--r-- | ldetect.spec | 13 | ||||
-rw-r--r-- | libldetect-private.h | 2 | ||||
-rw-r--r-- | libldetect.h | 21 | ||||
-rw-r--r-- | lspcidrake.c | 27 | ||||
-rw-r--r-- | pci.c | 93 | ||||
-rw-r--r-- | pciusb.c | 64 | ||||
-rw-r--r-- | usb.c | 63 |
11 files changed, 256 insertions, 88 deletions
diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 0000000..f6b7b68 --- /dev/null +++ b/.cvsignore @@ -0,0 +1,3 @@ +pciclass.c +usbclass.c +lspcidrake @@ -12,16 +12,21 @@ build: $(binaries) $(libraries) lspcidrake: lspcidrake.c libldetect.a -libldetect.a: pci.o pciclass.o +libldetect.a: pciusb.o pci.o usb.o pciclass.o usbclass.o ar rsc $@ $^ -pciclass.c: /usr/include/linux/pci.h generate_pciclass.pl +pciclass.c: /usr/include/linux/pci.h /usr/include/linux/pci_ids.h rm -f $@ - perl generate_pciclass.pl < $< > $@ + perl generate_pciclass.pl $^ > $@ + chmod a-w $@ + +usbclass.c: /usr/share/usb.ids + rm -f $@ + perl generate_usbclass.pl $^ > $@ chmod a-w $@ clean: - rm -f *~ *.o pciclass.c $(binaries) $(libraries) + rm -f *~ *.o pciclass.c usbclass.c $(binaries) $(libraries) install: build install -d $(bindir) $(libdir) $(includedir) diff --git a/common.h b/common.h new file mode 100644 index 0000000..10fa22b --- /dev/null +++ b/common.h @@ -0,0 +1,10 @@ +#define psizeof(a) (sizeof(a) / sizeof(*(a))) + +static inline void *memdup(void *src, size_t size) { + void *r = malloc(size); + memcpy(r, src, size); + return r; +} +static inline void ifree(void *p) { + if (p) { free(p); p = NULL; } +} diff --git a/generate_usbclass.pl b/generate_usbclass.pl new file mode 100755 index 0000000..a503e85 --- /dev/null +++ b/generate_usbclass.pl @@ -0,0 +1,35 @@ +#!/usr/bin/perl + +print q(/* This auto-generated from <usb.h>, don't modify! */ + +struct { + unsigned short id; + const char *name; +} usbclasses[] = { +); + +while (<>) { + chomp; + if (/^C\s+(\d+)\s+(.*)/) { + ($cat, $descr) = ($1, $2); + } elsif (/^\t\t(\d+)\s+(.*)/ && defined $cat) { + print qq( { 0x$cat$1, "$descr|$2" },\n); + } elsif (/^\S/) { + undef $cat; + } +} + +print ' +}; + +int nb_usbclasses = sizeof(usbclasses) / sizeof(*usbclasses); + +extern const char *usb_class2text(unsigned short class) { + int i; + for (i = 0; i < nb_usbclasses; i++) + if (usbclasses[i].id == class) return usbclasses[i].name; + + return ""; +} + +'; diff --git a/ldetect.spec b/ldetect.spec index dcbf728..b26d35c 100644 --- a/ldetect.spec +++ b/ldetect.spec @@ -1,6 +1,6 @@ %define name ldetect -%define version 0.2.0 -%define release 2mdk +%define version 0.2.3 +%define release 1mdk Name: %{name} Version: %{version} @@ -47,6 +47,15 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/* %changelog +* Sat Dec 16 2000 Pixel <pixel@mandrakesoft.com> 0.2.3-1mdk +- now detect usb + +* Fri Dec 15 2000 Pixel <pixel@mandrakesoft.com> 0.2.2-1mdk +- fix pciprobe for subids + +* Fri Dec 15 2000 Pixel <pixel@mandrakesoft.com> 0.2.1-1mdk +- try with linux/pci_ids.h to generate pciclass.c (kernel 2.4) + * Fri Dec 15 2000 Pixel <pixel@mandrakesoft.com> 0.2.0-2mdk - add requires ldetect-lst diff --git a/libldetect-private.h b/libldetect-private.h new file mode 100644 index 0000000..6a27497 --- /dev/null +++ b/libldetect-private.h @@ -0,0 +1,2 @@ +extern void pciusb_find_modules(struct pciusb_entries entries, const char *fpciusbtable); +extern void pciusb_initialize(struct pciusb_entry *e); diff --git a/libldetect.h b/libldetect.h index a8d9053..5e43b1a 100644 --- a/libldetect.h +++ b/libldetect.h @@ -1,7 +1,7 @@ /******************************************************************************/ -/* pci ************************************************************************/ +/* pciusb *********************************************************************/ /******************************************************************************/ -struct pci_entry { +struct pciusb_entry { unsigned short vendor; /* PCI vendor id */ unsigned short device; @@ -12,13 +12,22 @@ struct pci_entry { char *module; char *text; }; -struct pci_entries { - struct pci_entry *entries; +struct pciusb_entries { + struct pciusb_entry *entries; int nb; }; +extern void pciusb_free(struct pciusb_entries entries); -extern struct pci_entries pci_probe(int probe_type); /* probe_type is boolean */ -extern void pci_free(struct pci_entries entries); +/******************************************************************************/ +/* pci ************************************************************************/ +/******************************************************************************/ +extern struct pciusb_entries pci_probe(int probe_type); /* probe_type is boolean */ extern const char *pci_class2text(unsigned short class); + +/******************************************************************************/ +/* usb ************************************************************************/ +/******************************************************************************/ +extern struct pciusb_entries usb_probe(void); +extern const char *usb_class2text(unsigned short class); diff --git a/lspcidrake.c b/lspcidrake.c index faec021..cb3b2da 100644 --- a/lspcidrake.c +++ b/lspcidrake.c @@ -3,10 +3,10 @@ #include <string.h> #include "libldetect.h" -void pci_printit(struct pci_entries entries) { +void pci_printit(struct pciusb_entries entries) { int i; for (i = 0; i < entries.nb; i++) { - struct pci_entry e = entries.entries[i]; + struct pciusb_entry e = entries.entries[i]; printf("%s:\t%s", e.module ? e.module : "unknown", e.text); if (e.class) { const char *class = pci_class2text(e.class); @@ -16,9 +16,26 @@ void pci_printit(struct pci_entries entries) { } } +void usb_printit(struct pciusb_entries entries) { + int i; + for (i = 0; i < entries.nb; i++) { + struct pciusb_entry e = entries.entries[i]; + printf("%s:\t%s", e.module ? e.module : "unknown", e.text); + if (e.class) printf(" [%s]", usb_class2text(e.class)); + printf("\n"); + } +} + int main(int argc, char **argv) { - struct pci_entries entries = pci_probe(1); - pci_printit(entries); - pci_free(entries); + { + struct pciusb_entries entries = pci_probe(1); + pci_printit(entries); + pciusb_free(entries); + } + { + struct pciusb_entries entries = usb_probe(); + usb_printit(entries); + pciusb_free(entries); + } exit(0); } @@ -2,102 +2,53 @@ #include <stdlib.h> #include <string.h> #include "libldetect.h" +#include "libldetect-private.h" +#include "common.h" -#define psizeof(a) (sizeof(a) / sizeof(*(a))) - -void *memdup(void *src, size_t size) { - void *r = malloc(size); - memcpy(r, src, size); - return r; -} -void ifree(void *p) { - if (p) { free(p); p = NULL; } -} - -static void pci_find_modules(struct pci_entries entries) { - FILE *f; - const char *fpcitable = "/usr/share/ldetect-lst/pcitable"; - char buf[2048]; - int line; - - if (!(f = fopen(fpcitable, "r"))) { - fprintf(stderr, "Missing pcitable (should be %s)\n", fpcitable); - exit(1); - } - for (line = 1; fgets(buf, sizeof(buf) - 1, f); line++) { - unsigned short vendor, device, subvendor, subdevice; - int offset, i; - int nb = sscanf(buf, "0x%hx\t0x%hx\t0x%hx\t0x%hx\t%n", &vendor, &device, &subvendor, &subdevice, &offset); - if (nb != 4) { - nb = sscanf(buf, "0x%hx\t0x%hx\t%n", &vendor, &device, &offset); - if (nb != 2 && buf[0] != '#') { - fprintf(stderr, "%s %d: bad line\n", fpcitable, line); - continue; - } - } - for (i = 0; i < entries.nb; i++) { - struct pci_entry *e = &entries.entries[i]; - if (vendor == e->vendor && device == e->device && - (nb != 4 || (subvendor == e->subvendor && subdevice == e->subdevice)) && !e->module) { - char *p = buf + offset + 1; - char *q = strchr(p, '\t'); - if (q) { - q[-1] = 0; - q[strlen(q)-1] = 0; - e->module = strcmp(p, "unknown") ? strdup(p) : NULL; - e->text = strdup(q+2); - } - } - } - } +static void pci_find_modules(struct pciusb_entries entries) { + pciusb_find_modules(entries, "/usr/share/ldetect-lst/pcitable"); } -extern struct pci_entries pci_probe(int probe_type) { +extern struct pciusb_entries pci_probe(int probe_type) { FILE *f; char buf[512]; unsigned short devbusfn; unsigned int id; - struct pci_entry t[100]; - struct pci_entries r; + struct pciusb_entry t[100]; + struct pciusb_entries r; if (!(f = fopen("/proc/bus/pci/devices", "r"))) exit(1); for (r.nb = 0; fgets(buf, sizeof(buf) - 1, f) && r.nb < psizeof(t); r.nb++) { + struct pciusb_entry e; + pciusb_initialize(&e); + sscanf(buf, "%hx %x", &devbusfn, &id); - t[r.nb].vendor = id >> 16; - t[r.nb].device = id & 0xffff; - t[r.nb].module = NULL; - t[r.nb].text = NULL; + e.vendor = id >> 16; + e.device = id & 0xffff; { char file[25]; FILE *f; snprintf(file, sizeof(file), "/proc/bus/pci/%02x/%02x.%d", devbusfn >> 8, (devbusfn & 0xff) >> 3, (devbusfn & 0xff) & 0x7); if (probe_type && (f = fopen(file, "r"))) { if (fseek(f, 10, SEEK_SET) == 0) - fread(&t[r.nb].class, 2, 1, f); + fread(&e.class, 2, 1, f); if (fseek(f, 0x2c, SEEK_SET) == 0) - fread(&t[r.nb].subvendor, 2, 1, f), fread(&t[r.nb].subdevice, 2, 1, f); - } else { - t[r.nb].subvendor = 0xffff; - t[r.nb].subdevice = 0xffff; - t[r.nb].class = 0; + fread(&e.subvendor, 2, 1, f), fread(&e.subdevice, 2, 1, f); + + if ((e.subvendor == 0 && e.subdevice == 0) || + (e.subvendor == e.vendor && e.subdevice == e.device)) { + e.subvendor = 0xffff; + e.subdevice = 0xffff; + } } } + t[r.nb] = e; } fclose(f); - r.entries = memdup(t, sizeof(struct pci_entry) * r.nb); + r.entries = memdup(t, sizeof(struct pciusb_entry) * r.nb); pci_find_modules(r); return r; } -extern void pci_free(struct pci_entries entries) { - int i; - for (i = 0; i < entries.nb; i++) { - struct pci_entry e = entries.entries[i]; - ifree(e.module); - ifree(e.text); - } - ifree(entries.entries); -} - diff --git a/pciusb.c b/pciusb.c new file mode 100644 index 0000000..b5de8d8 --- /dev/null +++ b/pciusb.c @@ -0,0 +1,64 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "libldetect.h" +#include "libldetect-private.h" +#include "common.h" + +extern void pciusb_find_modules(struct pciusb_entries entries, const char *fpciusbtable) { + FILE *f; + char buf[2048]; + int line; + + if (!(f = fopen(fpciusbtable, "r"))) { + fprintf(stderr, "Missing pciusbtable (should be %s)\n", fpciusbtable); + exit(1); + } + for (line = 1; fgets(buf, sizeof(buf) - 1, f); line++) { + unsigned short vendor, device, subvendor, subdevice; + int offset, i; + int nb = sscanf(buf, "0x%hx\t0x%hx\t0x%hx\t0x%hx\t%n", &vendor, &device, &subvendor, &subdevice, &offset); + if (nb != 4) { + nb = sscanf(buf, "0x%hx\t0x%hx\t%n", &vendor, &device, &offset); + if (nb != 2 && buf[0] != '#') { + fprintf(stderr, "%s %d: bad line\n", fpciusbtable, line); + continue; + } + } + for (i = 0; i < entries.nb; i++) { + struct pciusb_entry *e = &entries.entries[i]; + if (vendor == e->vendor && device == e->device && + (nb != 4 || (subvendor == e->subvendor && subdevice == e->subdevice)) && !e->module) { + char *p = buf + offset + 1; + char *q = strchr(p, '\t'); + if (q) { + q[-1] = 0; + q[strlen(q)-2] = 0; + e->module = strcmp(p, "unknown") ? strdup(p) : NULL; + e->text = strdup(q+2); + } + } + } + } +} + +extern void pciusb_initialize(struct pciusb_entry *e) { + e->vendor = 0xffff; + e->device = 0xffff; + e->subvendor = 0xffff; + e->subdevice = 0xffff; + e->class = 0; + e->module = NULL; + e->text = NULL; +} + +extern void pciusb_free(struct pciusb_entries entries) { + int i; + for (i = 0; i < entries.nb; i++) { + struct pciusb_entry e = entries.entries[i]; + ifree(e.module); + ifree(e.text); + } + ifree(entries.entries); +} + @@ -0,0 +1,63 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "libldetect.h" +#include "libldetect-private.h" +#include "common.h" + +static void usb_find_modules(struct pciusb_entries entries) { + pciusb_find_modules(entries, "/usr/share/ldetect-lst/usbtable"); +} + +extern struct pciusb_entries usb_probe(void) { + FILE *f; + char buf[512]; + int line; + const char *file = "/proc/bus/usb/devices"; + struct pciusb_entry t[100]; + struct pciusb_entries r; + struct pciusb_entry *e = NULL; + + if (!(f = fopen(file, "r"))) { + fprintf(stderr, "can't open %s\n", file); + exit(1); + } + + for(r.nb = line = 0; fgets(buf, sizeof(buf) - 1, f) && r.nb < psizeof(t); line++) { + if (buf[0] == 'P') { + e = &t[r.nb++]; + pciusb_initialize(e); + + if (sscanf(buf, "P: Vendor=%hx ProdID=%hx", &e->vendor, &e->device) != 2) { + fprintf(stderr, "%s %d: unknown ``P'' line\n", file, line); + pciusb_initialize(e); + } + } else if (e && buf[0] == 'I' && e->class == 0) { + int class, prot = 0; + if (sscanf(buf, "I: If#=%*2d Alt=%*2d #EPs=%*2d Cls=%02x(%*5c) Sub=%*02x Prot=%02x", &class, &prot) == 2) { + /* we fake a class based on class and proto, subclass unneeded? */ + e->class = class * 0x100 + prot; + } else { + fprintf(stderr, "%s %d: unknown ``I'' line\n", file, line); + } + } else if (e && buf[0] == 'S') { + int offset; + char dummy; + if (sscanf(buf, "S: Manufacturer=%n%c", &offset, &dummy) == 1) { + buf[strlen(buf) - 1] = '|'; /* replacing '\n' by '|' */ + e->text = strdup(buf + offset); + } else if (sscanf(buf, "S: Product=%n%c", &offset, &dummy) == 1) { + if (!e->text) e->text = strdup("Unknown|"); + buf[strlen(buf) - 1] = 0; /* removing '\n' */ + e->text = realloc(e->text, strlen(e->text) + strlen(buf + offset) + 1); + strcat(e->text, buf + offset); + } + } + } + fclose(f); + r.entries = memdup(t, sizeof(struct pciusb_entry) * r.nb); + + usb_find_modules(r); + return r; +} + |