root/sys/dev/dev_verbose.h
/*      $NetBSD: dev_verbose.h,v 1.8 2021/06/29 21:03:36 pgoyette Exp $ */

/*
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _DEV_DEV_VERBOSE_H_
#define _DEV_DEV_VERBOSE_H_

#ifdef _KERNEL
#include <sys/module_hook.h>
#endif

const char *dev_findvendor(char *, size_t, const char *, size_t, 
        const uint32_t *, size_t, uint32_t, const char *);
const char *dev_findproduct(char *, size_t, const char *, size_t, 
        const uint32_t *, size_t, uint32_t, uint32_t, const char *);

#define DEV_VERBOSE_COMMON_DEFINE(tag)                                  \
static const char *                                                     \
tag ## _findvendor_real(char *buf, size_t len, uint32_t vendor)         \
{                                                                       \
        return dev_findvendor(buf, len, tag ## _words,                  \
            __arraycount(tag ## _words), tag ## _vendors,               \
            __arraycount(tag ## _vendors), vendor, tag ## _id1_format); \
}                                                                       \
                                                                        \
static const char *                                                     \
tag ## _findproduct_real(char *buf, size_t len, uint32_t vendor,        \
    uint32_t product)                                                   \
{                                                                       \
        return dev_findproduct(buf, len, tag ## _words,                 \
            __arraycount(tag ## _words), tag ## _products,              \
            __arraycount(tag ## _products), vendor, product,            \
            tag ## _id2_format);                                        \
}                                                                       \

#ifdef _KERNEL

#define DEV_VERBOSE_KERNEL_DECLARE(tag)                                 \
MODULE_HOOK(tag ## _findvendor_hook, const char *,                      \
        (char *, size_t, uint32_t));                                    \
MODULE_HOOK(tag ## _findproduct_hook, const char *,                     \
        (char *, size_t, uint32_t, uint32_t));                          \
extern int tag ## verbose_loaded;

#define DEV_VERBOSE_MODULE_DEFINE(tag, deps)                            \
DEV_VERBOSE_COMMON_DEFINE(tag)                                          \
DEV_VERBOSE_KERNEL_DECLARE(tag)                                         \
                                                                        \
static int                                                              \
tag ## verbose_modcmd(modcmd_t cmd, void *arg)                          \
{                                                                       \
                                                                        \
        switch (cmd) {                                                  \
        case MODULE_CMD_INIT:                                           \
                MODULE_HOOK_SET(tag ## _findvendor_hook,                \
                        tag ## _findvendor_real);                       \
                MODULE_HOOK_SET(tag ## _findproduct_hook,               \
                        tag ## _findproduct_real);                      \
                tag ## verbose_loaded = 1;                              \
                return 0;                                               \
        case MODULE_CMD_FINI:                                           \
                tag ## verbose_loaded = 0;                              \
                MODULE_HOOK_UNSET(tag ## _findproduct_hook);            \
                MODULE_HOOK_UNSET(tag ## _findvendor_hook);             \
                return 0;                                               \
        default:                                                        \
                return ENOTTY;                                          \
        }                                                               \
}                                                                       \
MODULE(MODULE_CLASS_DRIVER, tag ## verbose, deps)

#endif /* KERNEL */

#define DEV_VERBOSE_DECLARE(tag)                                        \
extern const char * tag ## _findvendor(char *, size_t, uint32_t);       \
extern const char * tag ## _findproduct(char *, size_t, uint32_t, uint32_t)

#if defined(_KERNEL)

#define DEV_VERBOSE_DEFINE(tag)                                         \
DEV_VERBOSE_KERNEL_DECLARE(tag)                                         \
struct tag ## _findvendor_hook_t tag ## _findvendor_hook;               \
struct tag ## _findproduct_hook_t tag ## _findproduct_hook;             \
int tag ## verbose_loaded = 0;                                          \
                                                                        \
static void                                                             \
tag ## _load_verbose(void)                                              \
{                                                                       \
                                                                        \
        if (tag ## verbose_loaded == 0)                                 \
                module_autoload(# tag "verbose", MODULE_CLASS_DRIVER);  \
}                                                                       \
                                                                        \
const char *                                                            \
tag ## _findvendor(char *buf, size_t len, uint32_t vendor)              \
{                                                                       \
        const char *retval = NULL;                                      \
                                                                        \
        tag ## _load_verbose();                                         \
        MODULE_HOOK_CALL(tag ## _findvendor_hook, (buf, len, vendor),   \
                (snprintf(buf, len, tag ## _id1_format, vendor), NULL), \
                retval);                                                \
        return retval;                                                  \
}                                                                       \
                                                                        \
const char *                                                            \
tag ## _findproduct(char *buf, size_t len, uint32_t vendor,             \
    uint32_t product)                                                   \
{                                                                       \
        const char *retval = NULL;                                      \
                                                                        \
        tag ## _load_verbose();                                         \
        MODULE_HOOK_CALL(tag ## _findproduct_hook,                      \
                (buf, len, vendor, product),                            \
                (snprintf(buf, len, tag ## _id2_format, product), NULL), \
                retval);                                                \
        return retval;                                                  \
}                                                                       \

#else   /* _KERNEL */

#define DEV_VERBOSE_DEFINE(tag)                                         \
DEV_VERBOSE_COMMON_DEFINE(tag)                                          \
const char *tag ## _findvendor(char *buf, size_t len, uint32_t vendor)  \
{                                                                       \
                                                                        \
        return tag ## _findvendor_real(buf, len, vendor);               \
}                                                                       \
                                                                        \
const char *tag ## _findproduct(char *buf, size_t len, uint32_t vendor, \
                uint32_t product)                                       \
{                                                                       \
                                                                        \
        return tag ## _findproduct_real(buf, len, vendor, product);     \
}

#endif /* _KERNEL */

#endif /* _DEV_DEV_VERBOSE_H_ */