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 "string-util.h"
31 #include "udev-util.h"
36 int udev_builtin_hwdb_lookup(struct udev_device
*dev
,
37 const char *prefix
, const char *modalias
,
38 const char *filter
, bool test
) {
39 _cleanup_free_
char *lookup
= NULL
;
40 const char *key
, *value
;
47 lookup
= strjoin(prefix
, modalias
);
53 SD_HWDB_FOREACH_PROPERTY(hwdb
, modalias
, key
, value
) {
54 if (filter
&& fnmatch(filter
, key
, FNM_NOESCAPE
) != 0)
57 if (udev_builtin_add_property(dev
, test
, key
, value
) < 0)
64 static const char *modalias_usb(struct udev_device
*dev
, char *s
, size_t size
) {
68 v
= udev_device_get_sysattr_value(dev
, "idVendor");
71 p
= udev_device_get_sysattr_value(dev
, "idProduct");
74 vn
= strtol(v
, NULL
, 16);
77 pn
= strtol(p
, NULL
, 16);
80 snprintf(s
, size
, "usb:v%04Xp%04X*", vn
, pn
);
84 static int udev_builtin_hwdb_search(struct udev_device
*dev
, struct udev_device
*srcdev
,
85 const char *subsystem
, const char *prefix
,
86 const char *filter
, bool test
) {
87 struct udev_device
*d
;
97 for (d
= srcdev
; d
&& !last
; d
= udev_device_get_parent(d
)) {
99 const char *modalias
= NULL
;
101 dsubsys
= udev_device_get_subsystem(d
);
105 /* look only at devices of a specific subsystem */
106 if (subsystem
&& !streq(dsubsys
, subsystem
))
109 modalias
= udev_device_get_property_value(d
, "MODALIAS");
111 if (streq(dsubsys
, "usb") && streq_ptr(udev_device_get_devtype(d
), "usb_device")) {
112 /* if the usb_device does not have a modalias, compose one */
114 modalias
= modalias_usb(d
, s
, sizeof(s
));
116 /* avoid looking at any parent device, they are usually just a USB hub */
123 r
= udev_builtin_hwdb_lookup(dev
, prefix
, modalias
, filter
, test
);
131 static int builtin_hwdb(struct udev_device
*dev
, int argc
, char *argv
[], bool test
) {
132 static const struct option options
[] = {
133 { "filter", required_argument
, NULL
, 'f' },
134 { "device", required_argument
, NULL
, 'd' },
135 { "subsystem", required_argument
, NULL
, 's' },
136 { "lookup-prefix", required_argument
, NULL
, 'p' },
139 const char *filter
= NULL
;
140 const char *device
= NULL
;
141 const char *subsystem
= NULL
;
142 const char *prefix
= NULL
;
143 _cleanup_udev_device_unref_
struct udev_device
*srcdev
= NULL
;
151 option
= getopt_long(argc
, argv
, "f:d:s:p:", options
, NULL
);
174 /* query a specific key given as argument */
176 if (udev_builtin_hwdb_lookup(dev
, prefix
, argv
[optind
], filter
, test
) > 0)
181 /* read data from another device than the device we will store the data */
183 srcdev
= udev_device_new_from_device_id(udev_device_get_udev(dev
), device
);
188 if (udev_builtin_hwdb_search(dev
, srcdev
, subsystem
, prefix
, filter
, test
) > 0)
193 /* called at udev startup and reload */
194 static int builtin_hwdb_init(struct udev
*udev
) {
200 r
= sd_hwdb_new(&hwdb
);
207 /* called on udev shutdown and reload request */
208 static void builtin_hwdb_exit(struct udev
*udev
) {
209 hwdb
= sd_hwdb_unref(hwdb
);
212 /* called every couple of seconds during event activity; 'true' if config has changed */
213 static bool builtin_hwdb_validate(struct udev
*udev
) {
214 return hwdb_validate(hwdb
);
217 const struct udev_builtin udev_builtin_hwdb
= {
220 .init
= builtin_hwdb_init
,
221 .exit
= builtin_hwdb_exit
,
222 .validate
= builtin_hwdb_validate
,
223 .help
= "Hardware database",