diff --git a/hwdb.d/60-autosuspend.hwdb b/hwdb.d/60-autosuspend.hwdb index 0de49afa6c..e742a33ea6 100644 --- a/hwdb.d/60-autosuspend.hwdb +++ b/hwdb.d/60-autosuspend.hwdb @@ -36,6 +36,16 @@ usb:v058Fp9540* ID_AUTOSUSPEND=1 +######################################### +# QEMU +######################################### + +# Emulated USB HID devices +usb:v0627p0001:*QEMU USB Keyboard* +usb:v0627p0001:*QEMU USB Mouse* +usb:v0627p0001:*QEMU USB Tablet* + ID_AUTOSUSPEND=1 + ######################################### # Wacom ######################################### diff --git a/hwdb.d/parse_hwdb.py b/hwdb.d/parse_hwdb.py index 8e1b5fdafa..025133416f 100755 --- a/hwdb.d/parse_hwdb.py +++ b/hwdb.d/parse_hwdb.py @@ -79,6 +79,9 @@ GENERAL_MATCHES = {'acpi', 'OUI', } +def upperhex_word(length): + return Word(nums + 'ABCDEF', exact=length) + @lru_cache() def hwdb_grammar(): ParserElement.setDefaultWhitespaceChars('') @@ -87,7 +90,7 @@ def hwdb_grammar(): for category, conn in TYPES.items()) matchline_typed = Combine(prefix + Word(printables + ' ' + '®')) - matchline_general = Combine(Or(GENERAL_MATCHES) + ':' + Word(printables)) + matchline_general = Combine(Or(GENERAL_MATCHES) + ':' + Word(printables + ' ' + '®')) matchline = (matchline_typed | matchline_general) + EOL propertyline = (White(' ', exact=1).suppress() + @@ -180,8 +183,27 @@ def parse(fname): return [] return [convert_properties(g) for g in parsed.GROUPS] -def check_match_uniqueness(groups): +def check_matches(groups): matches = sum((group[0] for group in groups), []) + + # This is a partial check. The other cases could be also done, but those + # two are most commonly wrong. + grammars = { 'usb' : 'v' + upperhex_word(4) + Optional('p' + upperhex_word(4)), + 'pci' : 'v' + upperhex_word(8) + Optional('d' + upperhex_word(8)), + } + + for match in matches: + prefix, rest = match.split(':', maxsplit=1) + gr = grammars.get(prefix) + if gr: + try: + gr.parseString(rest) + except ParseBaseException as e: + error('Pattern {!r} is invalid: {}', rest, e) + continue + if rest[-1] not in '*:': + error('pattern {} does not end with "*" or ":"', match) + matches.sort() prev = None for match in matches: @@ -256,7 +278,7 @@ if __name__ == '__main__': for fname in args: groups = parse(fname) print_summary(fname, groups) - check_match_uniqueness(groups) + check_matches(groups) check_properties(groups) sys.exit(ERROR) diff --git a/src/udev/udev-builtin-hwdb.c b/src/udev/udev-builtin-hwdb.c index 8e86d2f0d1..59ae6c7ad4 100644 --- a/src/udev/udev-builtin-hwdb.c +++ b/src/udev/udev-builtin-hwdb.c @@ -47,7 +47,7 @@ int udev_builtin_hwdb_lookup(sd_device *dev, } static const char *modalias_usb(sd_device *dev, char *s, size_t size) { - const char *v, *p; + const char *v, *p, *n = NULL; uint16_t vn, pn; if (sd_device_get_sysattr_value(dev, "idVendor", &v) < 0) @@ -58,15 +58,16 @@ static const char *modalias_usb(sd_device *dev, char *s, size_t size) { return NULL; if (safe_atoux16(p, &pn) < 0) return NULL; - snprintf(s, size, "usb:v%04Xp%04X*", vn, pn); + (void) sd_device_get_sysattr_value(dev, "product", &n); + + snprintf(s, size, "usb:v%04Xp%04X:%s", vn, pn, strempty(n)); return s; } static int udev_builtin_hwdb_search(sd_device *dev, sd_device *srcdev, const char *subsystem, const char *prefix, const char *filter, bool test) { - sd_device *d; - char s[16]; + char s[LINE_MAX]; bool last = false; int r = 0; @@ -75,7 +76,7 @@ static int udev_builtin_hwdb_search(sd_device *dev, sd_device *srcdev, if (!srcdev) srcdev = dev; - for (d = srcdev; d; ) { + for (sd_device *d = srcdev; d; ) { const char *dsubsys, *devtype, *modalias = NULL; if (sd_device_get_subsystem(d, &dsubsys) < 0) @@ -101,6 +102,8 @@ static int udev_builtin_hwdb_search(sd_device *dev, sd_device *srcdev, if (!modalias) goto next; + log_device_debug(dev, "hwdb modalias key: \"%s\"", modalias); + r = udev_builtin_hwdb_lookup(dev, prefix, modalias, filter, test); if (r > 0) break; diff --git a/tools/make-autosuspend-rules.py b/tools/make-autosuspend-rules.py index e13ca33f6f..a20edc0f34 100755 --- a/tools/make-autosuspend-rules.py +++ b/tools/make-autosuspend-rules.py @@ -14,7 +14,7 @@ for entry in chromiumos.gen_autosuspend_rules.PCI_IDS: device = int(device, 16) print('pci:v{:08X}d{:08X}*'.format(vendor, device)) -print('# usb:vp (4 uppercase hexadecimal digits twice') +print('# usb:vp (4 uppercase hexadecimal digits twice)') for entry in chromiumos.gen_autosuspend_rules.USB_IDS: vendor, product = entry.split(':') vendor = int(vendor, 16)