1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2012 Kay Sievers <kay@vrfy.org>
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "alloc-util.h"
29 #include "hwdb-util.h"
30 #include "parse-util.h"
31 #include "string-util.h"
32 #include "udev-util.h"
37 int udev_builtin_hwdb_lookup(struct udev_device
*dev
,
38 const char *prefix
, const char *modalias
,
39 const char *filter
, bool test
) {
40 _cleanup_free_
char *lookup
= NULL
;
41 const char *key
, *value
;
48 lookup
= strjoin(prefix
, modalias
);
54 SD_HWDB_FOREACH_PROPERTY(hwdb
, modalias
, key
, value
) {
55 if (filter
&& fnmatch(filter
, key
, FNM_NOESCAPE
) != 0)
58 if (udev_builtin_add_property(dev
, test
, key
, value
) < 0)
65 static const char *modalias_usb(struct udev_device
*dev
, char *s
, size_t size
) {
69 v
= udev_device_get_sysattr_value(dev
, "idVendor");
72 p
= udev_device_get_sysattr_value(dev
, "idProduct");
75 if (safe_atoux16(v
, &vn
) < 0)
77 if (safe_atoux16(p
, &pn
) < 0)
79 snprintf(s
, size
, "usb:v%04Xp%04X*", vn
, pn
);
83 static int udev_builtin_hwdb_search(struct udev_device
*dev
, struct udev_device
*srcdev
,
84 const char *subsystem
, const char *prefix
,
85 const char *filter
, bool test
) {
86 struct udev_device
*d
;
96 for (d
= srcdev
; d
&& !last
; d
= udev_device_get_parent(d
)) {
98 const char *modalias
= NULL
;
100 dsubsys
= udev_device_get_subsystem(d
);
104 /* look only at devices of a specific subsystem */
105 if (subsystem
&& !streq(dsubsys
, subsystem
))
108 modalias
= udev_device_get_property_value(d
, "MODALIAS");
110 if (streq(dsubsys
, "usb") && streq_ptr(udev_device_get_devtype(d
), "usb_device")) {
111 /* if the usb_device does not have a modalias, compose one */
113 modalias
= modalias_usb(d
, s
, sizeof(s
));
115 /* avoid looking at any parent device, they are usually just a USB hub */
122 r
= udev_builtin_hwdb_lookup(dev
, prefix
, modalias
, filter
, test
);
130 static int builtin_hwdb(struct udev_device
*dev
, int argc
, char *argv
[], bool test
) {
131 static const struct option options
[] = {
132 { "filter", required_argument
, NULL
, 'f' },
133 { "device", required_argument
, NULL
, 'd' },
134 { "subsystem", required_argument
, NULL
, 's' },
135 { "lookup-prefix", required_argument
, NULL
, 'p' },
138 const char *filter
= NULL
;
139 const char *device
= NULL
;
140 const char *subsystem
= NULL
;
141 const char *prefix
= NULL
;
142 _cleanup_udev_device_unref_
struct udev_device
*srcdev
= NULL
;
150 option
= getopt_long(argc
, argv
, "f:d:s:p:", options
, NULL
);
173 /* query a specific key given as argument */
175 if (udev_builtin_hwdb_lookup(dev
, prefix
, argv
[optind
], filter
, test
) > 0)
180 /* read data from another device than the device we will store the data */
182 srcdev
= udev_device_new_from_device_id(udev_device_get_udev(dev
), device
);
187 if (udev_builtin_hwdb_search(dev
, srcdev
, subsystem
, prefix
, filter
, test
) > 0)
192 /* called at udev startup and reload */
193 static int builtin_hwdb_init(struct udev
*udev
) {
199 r
= sd_hwdb_new(&hwdb
);
206 /* called on udev shutdown and reload request */
207 static void builtin_hwdb_exit(struct udev
*udev
) {
208 hwdb
= sd_hwdb_unref(hwdb
);
211 /* called every couple of seconds during event activity; 'true' if config has changed */
212 static bool builtin_hwdb_validate(struct udev
*udev
) {
213 return hwdb_validate(hwdb
);
216 const struct udev_builtin udev_builtin_hwdb
= {
219 .init
= builtin_hwdb_init
,
220 .exit
= builtin_hwdb_exit
,
221 .validate
= builtin_hwdb_validate
,
222 .help
= "Hardware database",