diff options
-rw-r--r-- | Makefile | 41 | ||||
-rw-r--r-- | generate_pciclass.pl | 26 | ||||
-rw-r--r-- | ldetect.spec | 50 | ||||
-rw-r--r-- | libldetect.h | 24 | ||||
-rw-r--r-- | lspcidrake.c | 24 | ||||
-rw-r--r-- | pci.c | 103 |
6 files changed, 268 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e2b5af3 --- /dev/null +++ b/Makefile @@ -0,0 +1,41 @@ +version = 0.2.0 + +project = ldetect +prefix = /usr +bindir = $(prefix)/bin +libdir = $(prefix)/lib +includedir = $(prefix)/include + +binaries = lspcidrake +libraries = libldetect.a +CFLAGS = -Wall -Wstrict-prototypes -g + +build: $(binaries) $(libraries) + +lspcidrake: lspcidrake.c libldetect.a + +libldetect.a: pci.o pciclass.o + ar rsc $@ $^ + +pciclass.c: /usr/include/linux/pci.h generate_pciclass.pl + rm -f $@ + perl generate_pciclass.pl < $< > $@ + chmod a-w $@ + +clean: + rm -f *~ *.o pciclass.c $(binaries) $(libraries) + +install: build + install -d $(bindir) $(libdir) $(includedir) + install $(binaries) $(bindir) + install $(libraries) $(libdir) + install libldetect.h $(includedir) + +rpm: clean $(RPM) + (echo "# !! DON'T MODIFY HERE, MODIFY IN THE CVS !!" ; \ + echo "%define version $(version)" ; \ + cat $(project).spec \ + ) > $(RPM)/SPECS/$(project).spec + + (cd .. ; tar cfj $(RPM)/SOURCES/$(project).tar.bz2 $(project)) + rpm -ba --clean --rmsource --rmspec $(RPM)/SPECS/$(project).spec diff --git a/generate_pciclass.pl b/generate_pciclass.pl new file mode 100644 index 0000000..c879615 --- /dev/null +++ b/generate_pciclass.pl @@ -0,0 +1,26 @@ +#!/usr/bin/perl + +print q(/* This auto-generated from <pci.h>, don't modify! */ + +struct { + unsigned short id; + const char *name; +} pciclasses[] = { +); + +/^#define PCI_CLASS_(\w+)\s+(0x\w{4})/ and print qq( { $2, "$1" },\n) while <>; + +print ' +}; + +int nb_pciclasses = sizeof(pciclasses) / sizeof(*pciclasses); + +extern const char *pci_class2text(unsigned short class) { + int i; + for (i = 0; i < nb_pciclasses; i++) + if (pciclasses[i].id == class) return pciclasses[i].name; + + return pci_class2text(0); +} + +'; diff --git a/ldetect.spec b/ldetect.spec new file mode 100644 index 0000000..e665a9c --- /dev/null +++ b/ldetect.spec @@ -0,0 +1,50 @@ +%define name ldetect +%define release 1mdk + +Name: %{name} +Version: %{version} +Release: %{release} +Summary: Light hardware detection library +Source: %{name}.tar.bz2 +Group: System/Libraries +BuildArchitectures: noarch +BuildRoot: %{_tmppath}/%{name}-buildroot +Copyright: GPL +Prefix: %{_prefix} + +%package devel +Summary: development package for ldetect +Group: Development/C + +%description +The hardware device lists provided by this package are used as lookup +table to get hardware autodetection + +%description devel +see %{name} + +%prep +%setup -n %{name} + +%build +%make + +%install +rm -rf $RPM_BUILD_ROOT +%makeinstall + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%{_bindir}/* + +%files devel +%defattr(-,root,root) +%{_includedir}/* +%{_libdir}/* + +%changelog +* Fri Dec 15 2000 Pixel <pixel@mandrakesoft.com> 0.1.0-1mdk +- first release diff --git a/libldetect.h b/libldetect.h new file mode 100644 index 0000000..a8d9053 --- /dev/null +++ b/libldetect.h @@ -0,0 +1,24 @@ +/******************************************************************************/ +/* pci ************************************************************************/ +/******************************************************************************/ +struct pci_entry { + unsigned short vendor; /* PCI vendor id */ + unsigned short device; + + unsigned short subvendor; /* 0xffff if not probe_type'd or no subid */ + unsigned short subdevice; /* 0xffff if not probe_type'd or no subid */ + unsigned short class; /* 0 if not probe_type'd */ + + char *module; + char *text; +}; +struct pci_entries { + struct pci_entry *entries; + int nb; +}; + + +extern struct pci_entries pci_probe(int probe_type); /* probe_type is boolean */ +extern void pci_free(struct pci_entries entries); + +extern const char *pci_class2text(unsigned short class); diff --git a/lspcidrake.c b/lspcidrake.c new file mode 100644 index 0000000..faec021 --- /dev/null +++ b/lspcidrake.c @@ -0,0 +1,24 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "libldetect.h" + +void pci_printit(struct pci_entries entries) { + int i; + for (i = 0; i < entries.nb; i++) { + struct pci_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); + if (strcmp(class, "NOT_DEFINED") != 0) printf(" [%s]", class); + } + printf("\n"); + } +} + +int main(int argc, char **argv) { + struct pci_entries entries = pci_probe(1); + pci_printit(entries); + pci_free(entries); + exit(0); +} @@ -0,0 +1,103 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "libldetect.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); + } + } + } + } +} + +extern struct pci_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; + + 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++) { + 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; + { + 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); + 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; + } + } + } + fclose(f); + r.entries = memdup(t, sizeof(struct pci_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); +} + |