X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Ffilter.c;h=573fb28103637f65d98411c9602bcb1899816471;hb=0547ded87cb2757044d4bcbdcafce32fc14c860f;hp=299af2994998338e3034cebc113c8d24ed845c5a;hpb=727ce158868ed101006ecc5d3dd3faede927165c;p=pciutils.git diff --git a/lib/filter.c b/lib/filter.c index 299af29..573fb28 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -1,9 +1,7 @@ /* - * $Id: filter.c,v 1.1 1999/01/22 21:05:22 mj Exp $ + * The PCI Library -- Device Filtering * - * Linux PCI Library -- Device Filtering - * - * Copyright (c) 1998--1999 Martin Mares + * Copyright (c) 1998--2014 Martin Mares * * Can be freely distributed and used under the terms of the GNU GPL. */ @@ -13,31 +11,51 @@ #include "internal.h" +void pci_filter_init_v33(struct pci_access *a UNUSED, struct pci_filter *f) VERSIONED_ABI; +char *pci_filter_parse_slot_v33(struct pci_filter *f, char *str) VERSIONED_ABI; +char *pci_filter_parse_id_v33(struct pci_filter *f, char *str) VERSIONED_ABI; +int pci_filter_match_v33(struct pci_filter *f, struct pci_dev *d) VERSIONED_ABI; + void -pci_filter_init(struct pci_access * UNUSED a, struct pci_filter *f) +pci_filter_init_v33(struct pci_access *a UNUSED, struct pci_filter *f) { - f->bus = f->slot = f->func = -1; - f->vendor = f->device = -1; + f->domain = f->bus = f->slot = f->func = -1; + f->vendor = f->device = f->device_class = -1; } -/* Slot filter syntax: [[bus]:][slot][.[func]] */ +/* Slot filter syntax: [[[domain]:][bus]:][slot][.[func]] */ char * -pci_filter_parse_slot(struct pci_filter *f, char *str) +pci_filter_parse_slot_v33(struct pci_filter *f, char *str) { - char *colon = strchr(str, ':'); + char *colon = strrchr(str, ':'); char *dot = strchr((colon ? colon + 1 : str), '.'); char *mid = str; - char *e; + char *e, *bus, *colon2; if (colon) { *colon++ = 0; mid = colon; - if (str[0] && strcmp(str, "*")) + colon2 = strchr(str, ':'); + if (colon2) + { + *colon2++ = 0; + bus = colon2; + if (str[0] && strcmp(str, "*")) + { + long int x = strtol(str, &e, 16); + if ((e && *e) || (x < 0 || x > 0x7fffffff)) + return "Invalid domain number"; + f->domain = x; + } + } + else + bus = str; + if (bus[0] && strcmp(bus, "*")) { - long int x = strtol(str, &e, 16); - if ((e && *e) || (x < 0 || x >= 0xff)) + long int x = strtol(bus, &e, 16); + if ((e && *e) || (x < 0 || x > 0xff)) return "Invalid bus number"; f->bus = x; } @@ -47,26 +65,26 @@ pci_filter_parse_slot(struct pci_filter *f, char *str) if (mid[0] && strcmp(mid, "*")) { long int x = strtol(mid, &e, 16); - if ((e && *e) || (x < 0 || x >= 0x1f)) + if ((e && *e) || (x < 0 || x > 0x1f)) return "Invalid slot number"; f->slot = x; } if (dot && dot[0] && strcmp(dot, "*")) { long int x = strtol(dot, &e, 16); - if ((e && *e) || (x < 0 || x >= 7)) + if ((e && *e) || (x < 0 || x > 7)) return "Invalid function number"; f->func = x; } return NULL; } -/* ID filter syntax: [vendor]:[device] */ +/* ID filter syntax: [vendor]:[device][:class] */ char * -pci_filter_parse_id(struct pci_filter *f, char *str) +pci_filter_parse_id_v33(struct pci_filter *f, char *str) { - char *s, *e; + char *s, *c, *e; if (!*str) return NULL; @@ -77,33 +95,146 @@ pci_filter_parse_id(struct pci_filter *f, char *str) if (str[0] && strcmp(str, "*")) { long int x = strtol(str, &e, 16); - if ((e && *e) || (x < 0 || x >= 0xffff)) + if ((e && *e) || (x < 0 || x > 0xffff)) return "Invalid vendor ID"; f->vendor = x; } + c = strchr(s, ':'); + if (c) + *c++ = 0; if (s[0] && strcmp(s, "*")) { long int x = strtol(s, &e, 16); - if ((e && *e) || (x < 0 || x >= 0xffff)) + if ((e && *e) || (x < 0 || x > 0xffff)) return "Invalid device ID"; f->device = x; } + if (c && c[0] && strcmp(s, "*")) + { + long int x = strtol(c, &e, 16); + if ((e && *e) || (x < 0 || x > 0xffff)) + return "Invalid class code"; + f->device_class = x; + } return NULL; } int -pci_filter_match(struct pci_filter *f, struct pci_dev *d) +pci_filter_match_v33(struct pci_filter *f, struct pci_dev *d) { - if ((f->bus >= 0 && f->bus != d->bus) || + if ((f->domain >= 0 && f->domain != d->domain) || + (f->bus >= 0 && f->bus != d->bus) || (f->slot >= 0 && f->slot != d->dev) || (f->func >= 0 && f->func != d->func)) return 0; if (f->device >= 0 || f->vendor >= 0) { - pci_fill_info(d, PCI_FILL_IDENT); + pci_fill_info_v35(d, PCI_FILL_IDENT); if ((f->device >= 0 && f->device != d->device_id) || (f->vendor >= 0 && f->vendor != d->vendor_id)) return 0; } + if (f->device_class >= 0) + { + pci_fill_info(d, PCI_FILL_CLASS); + if (f->device_class != d->device_class) + return 0; + } return 1; } + +/* + * Before pciutils v3.3, struct pci_filter had fewer fields, + * so we have to provide compatibility wrappers. + */ + +struct pci_filter_v30 { + int domain, bus, slot, func; /* -1 = ANY */ + int vendor, device; +}; + +void pci_filter_init_v30(struct pci_access *a, struct pci_filter_v30 *f) VERSIONED_ABI; +char *pci_filter_parse_slot_v30(struct pci_filter_v30 *f, char *str) VERSIONED_ABI; +char *pci_filter_parse_id_v30(struct pci_filter_v30 *f, char *str) VERSIONED_ABI; +int pci_filter_match_v30(struct pci_filter_v30 *f, struct pci_dev *d) VERSIONED_ABI; + +static void +pci_filter_import_v30(struct pci_filter_v30 *old, struct pci_filter *new) +{ + new->domain = old->domain; + new->bus = old->bus; + new->slot = old->slot; + new->func = old->func; + new->vendor = old->vendor; + new->device = old->device; + new->device_class = -1; +} + +static void +pci_filter_export_v30(struct pci_filter *new, struct pci_filter_v30 *old) +{ + old->domain = new->domain; + old->bus = new->bus; + old->slot = new->slot; + old->func = new->func; + old->vendor = new->vendor; + old->device = new->device; +} + +void +pci_filter_init_v30(struct pci_access *a, struct pci_filter_v30 *f) +{ + struct pci_filter new; + pci_filter_init_v33(a, &new); + pci_filter_export_v30(&new, f); +} + +char * +pci_filter_parse_slot_v30(struct pci_filter_v30 *f, char *str) +{ + struct pci_filter new; + char *err; + pci_filter_import_v30(f, &new); + if (err = pci_filter_parse_slot_v33(&new, str)) + return err; + pci_filter_export_v30(&new, f); + return NULL; +} + +char * +pci_filter_parse_id_v30(struct pci_filter_v30 *f, char *str) +{ + struct pci_filter new; + char *err; + pci_filter_import_v30(f, &new); + if (err = pci_filter_parse_id_v33(&new, str)) + return err; + if (new.device_class >= 0) + return "Filtering by class not supported in this program"; + pci_filter_export_v30(&new, f); + return NULL; +} + +int +pci_filter_match_v30(struct pci_filter_v30 *f, struct pci_dev *d) +{ + struct pci_filter new; + pci_filter_import_v30(f, &new); + return pci_filter_match_v33(&new, d); +} + +STATIC_ALIAS(void pci_filter_init(struct pci_access *a, struct pci_filter *f), pci_filter_init_v33(a, f)); +SYMBOL_VERSION(pci_filter_init_v30, pci_filter_init@LIBPCI_3.0); +SYMBOL_VERSION(pci_filter_init_v33, pci_filter_init@@LIBPCI_3.3); + +STATIC_ALIAS(char *pci_filter_parse_slot(struct pci_filter *f, char *str), pci_filter_parse_slot_v33(f, str)); +SYMBOL_VERSION(pci_filter_parse_slot_v30, pci_filter_parse_slot@LIBPCI_3.0); +SYMBOL_VERSION(pci_filter_parse_slot_v33, pci_filter_parse_slot@@LIBPCI_3.3); + +STATIC_ALIAS(char *pci_filter_parse_id(struct pci_filter *f, char *str), pci_filter_parse_id_v33(f, str)); +SYMBOL_VERSION(pci_filter_parse_id_v30, pci_filter_parse_id@LIBPCI_3.0); +SYMBOL_VERSION(pci_filter_parse_id_v33, pci_filter_parse_id@@LIBPCI_3.3); + +STATIC_ALIAS(int pci_filter_match(struct pci_filter *f, struct pci_dev *d), pci_filter_match_v33(f, d)); +SYMBOL_VERSION(pci_filter_match_v30, pci_filter_match@LIBPCI_3.0); +SYMBOL_VERSION(pci_filter_match_v33, pci_filter_match@@LIBPCI_3.3);