drivers/soundwire/sysfs_slave_dpn.c

Source file repositories/reference/linux-study-clean/drivers/soundwire/sysfs_slave_dpn.c

File Facts

System
Linux kernel
Corpus path
drivers/soundwire/sysfs_slave_dpn.c
Extension
.c
Size
7461 bytes
Lines
305
Domain
Driver Families
Bucket
drivers/soundwire
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct dpn_attribute {
	struct device_attribute	dev_attr;
	int N;
	int dir;
	const char *format_string;
};

/*
 * Since we can't use ARRAY_SIZE, hard-code number of dpN attributes.
 * This needs to be updated when adding new attributes - an error will be
 * flagged on a mismatch.
 */
#define SDW_DPN_ATTRIBUTES 15

#define sdw_dpn_attribute_alloc(field)					\
static int field##_attribute_alloc(struct device *dev,			\
				struct attribute **res,			\
				int N, int dir,				\
				const char *format_string)		\
{									\
	struct dpn_attribute *dpn_attr;					\
									\
	dpn_attr = devm_kzalloc(dev, sizeof(*dpn_attr), GFP_KERNEL);	\
	if (!dpn_attr)							\
		return -ENOMEM;						\
	dpn_attr->N = N;						\
	dpn_attr->dir = dir;						\
	sysfs_attr_init(&dpn_attr->dev_attr.attr);			\
	dpn_attr->format_string = format_string;			\
	dpn_attr->dev_attr.attr.name = __stringify(field);		\
	dpn_attr->dev_attr.attr.mode = 0444;				\
	dpn_attr->dev_attr.show = field##_show;				\
									\
	*res = &dpn_attr->dev_attr.attr;				\
									\
	return 0;							\
}

#define sdw_dpn_attr(field)						\
									\
static ssize_t field##_dpn_show(struct sdw_slave *slave,		\
				int N,					\
				int dir,				\
				const char *format_string,		\
				char *buf)				\
{									\
	struct sdw_dpn_prop *dpn;					\
	unsigned long mask;						\
	int bit;							\
	int i;								\
									\
	if (dir) {							\
		dpn = slave->prop.src_dpn_prop;				\
		mask = slave->prop.source_ports;			\
	} else {							\
		dpn = slave->prop.sink_dpn_prop;			\
		mask = slave->prop.sink_ports;				\
	}								\
									\
	i = 0;								\
	for_each_set_bit(bit, &mask, 32) {				\
		if (bit == N) {						\
			return sprintf(buf, format_string,		\
				       dpn[i].field);			\
		}							\
		i++;							\
	}								\
	return -EINVAL;							\
}									\
									\
static ssize_t field##_show(struct device *dev,				\
			    struct device_attribute *attr,		\
			    char *buf)					\
{									\
	struct sdw_slave *slave = dev_to_sdw_dev(dev);			\
	struct dpn_attribute *dpn_attr =				\
		container_of(attr, struct dpn_attribute, dev_attr);	\
									\
	return field##_dpn_show(slave,					\
				dpn_attr->N, dpn_attr->dir,		\
				dpn_attr->format_string,		\
				buf);					\
}									\
sdw_dpn_attribute_alloc(field)

sdw_dpn_attr(imp_def_interrupts);
sdw_dpn_attr(max_word);
sdw_dpn_attr(min_word);
sdw_dpn_attr(type);
sdw_dpn_attr(max_grouping);

Annotation

Implementation Notes