libudev-hwdb.c revision 8b516fdea74127327b0945bb50690bd70c6b6692
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer/***
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer This file is part of systemd.
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Copyright Tom Gundersen <teg@jklm.no>
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer systemd is free software; you can redistribute it and/or modify it
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer under the terms of the GNU Lesser General Public License as published by
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer the Free Software Foundation; either version 2.1 of the License, or
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer (at your option) any later version.
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt systemd is distributed in the hope that it will be useful, but
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt WITHOUT ANY WARRANTY; without even the implied warranty of
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt Lesser General Public License for more details.
4be4833ece2856e0cacc09f8f8b2c02b320751faMartin Pitt
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier You should have received a copy of the GNU Lesser General Public License
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier along with systemd; If not, see <http://www.gnu.org/licenses/>.
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier***/
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "libudev-private.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "sd-hwdb.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "hwdb-util.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier/**
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier * SECTION:libudev-hwdb
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier * @short_description: retrieve properties from the hardware database
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier *
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier * Libudev hardware database interface.
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier */
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier/**
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier * udev_hwdb:
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier *
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier * Opaque object representing the hardware database.
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier */
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalierstruct udev_hwdb {
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier struct udev *udev;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier int refcount;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier sd_hwdb *hwdb;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier struct udev_list properties_list;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier};
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier/**
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier * udev_hwdb_new:
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier * @udev: udev library context
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier *
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier * Create a hardware database context to query properties for devices.
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier *
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier * Returns: a hwdb context.
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier **/
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier_public_ struct udev_hwdb *udev_hwdb_new(struct udev *udev) {
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier _cleanup_hwdb_unref_ sd_hwdb *hwdb_internal = NULL;
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt struct udev_hwdb *hwdb;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier int r;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier assert_return(udev, NULL);
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier r = sd_hwdb_new(&hwdb_internal);
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier if (r < 0)
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier return NULL;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier hwdb = new0(struct udev_hwdb, 1);
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier if (!hwdb)
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier return NULL;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier hwdb->refcount = 1;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier hwdb->hwdb = hwdb_internal;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier hwdb_internal = NULL;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier udev_list_init(udev, &hwdb->properties_list, true);
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek return hwdb;
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier/**
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * udev_hwdb_ref:
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek * @hwdb: context
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt *
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * Take a reference of a hwdb context.
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier *
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * Returns: the passed enumeration context
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier **/
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier_public_ struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (!hwdb)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return NULL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier hwdb->refcount++;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return hwdb;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier/**
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * udev_hwdb_unref:
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * @hwdb: context
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier *
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * Drop a reference of a hwdb context. If the refcount reaches zero,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * all resources of the hwdb context will be released.
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier *
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * Returns: #NULL
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier **/
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier_public_ struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (!hwdb)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return NULL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier hwdb->refcount--;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (hwdb->refcount > 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return NULL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier sd_hwdb_unref(hwdb->hwdb);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier udev_list_cleanup(&hwdb->properties_list);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier free(hwdb);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return NULL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierbool udev_hwdb_validate(struct udev_hwdb *hwdb) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (!hwdb)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return false;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return hwdb_validate(hwdb->hwdb);
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier/**
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * udev_hwdb_get_properties_list_entry:
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * @hwdb: context
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * @modalias: modalias string
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * @flags: (unused)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier *
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * Lookup a matching device in the hardware database. The lookup key is a
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * modalias string, whose formats are defined for the Linux kernel modules.
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * Examples are: pci:v00008086d00001C2D*, usb:v04F2pB221*. The first entry
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * of a list of retrieved properties is returned.
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier *
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * Returns: a udev_list_entry.
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier_public_ struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags) {
739d81ddd005fae2bb82edce5b8a6173c7c48b34Zbigniew Jędrzejewski-Szmek const char *key, *value;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
b8667ee4162cd2510363602b417cecede9fd2ccaZbigniew Jędrzejewski-Szmek if (!hwdb || !modalias) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier errno = EINVAL;
739d81ddd005fae2bb82edce5b8a6173c7c48b34Zbigniew Jędrzejewski-Szmek return NULL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
b8667ee4162cd2510363602b417cecede9fd2ccaZbigniew Jędrzejewski-Szmek
b8667ee4162cd2510363602b417cecede9fd2ccaZbigniew Jędrzejewski-Szmek udev_list_cleanup(&hwdb->properties_list);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier FOREACH_HWDB_PROPERTY(hwdb->hwdb, modalias, key, value) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (udev_list_entry_add(&hwdb->properties_list, key, value) == NULL) {
739d81ddd005fae2bb82edce5b8a6173c7c48b34Zbigniew Jędrzejewski-Szmek errno = ENOMEM;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return NULL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return udev_list_get_entry(&hwdb->properties_list);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier