Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

/*	$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_ */