162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * /proc interface for comedi
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * COMEDI - Linux Control and Measurement Device Interface
662306a36Sopenharmony_ci * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci/*
1062306a36Sopenharmony_ci * This is some serious bloatware.
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * Taken from Dave A.'s PCL-711 driver, 'cuz I thought it
1362306a36Sopenharmony_ci * was cool.
1462306a36Sopenharmony_ci */
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include <linux/comedi/comedidev.h>
1762306a36Sopenharmony_ci#include "comedi_internal.h"
1862306a36Sopenharmony_ci#include <linux/proc_fs.h>
1962306a36Sopenharmony_ci#include <linux/seq_file.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cistatic int comedi_read(struct seq_file *m, void *v)
2262306a36Sopenharmony_ci{
2362306a36Sopenharmony_ci	int i;
2462306a36Sopenharmony_ci	int devices_q = 0;
2562306a36Sopenharmony_ci	struct comedi_driver *driv;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	seq_printf(m, "comedi version " COMEDI_RELEASE "\nformat string: %s\n",
2862306a36Sopenharmony_ci		   "\"%2d: %-20s %-20s %4d\", i, driver_name, board_name, n_subdevices");
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
3162306a36Sopenharmony_ci		struct comedi_device *dev = comedi_dev_get_from_minor(i);
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci		if (!dev)
3462306a36Sopenharmony_ci			continue;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci		down_read(&dev->attach_lock);
3762306a36Sopenharmony_ci		if (dev->attached) {
3862306a36Sopenharmony_ci			devices_q = 1;
3962306a36Sopenharmony_ci			seq_printf(m, "%2d: %-20s %-20s %4d\n",
4062306a36Sopenharmony_ci				   i, dev->driver->driver_name,
4162306a36Sopenharmony_ci				   dev->board_name, dev->n_subdevices);
4262306a36Sopenharmony_ci		}
4362306a36Sopenharmony_ci		up_read(&dev->attach_lock);
4462306a36Sopenharmony_ci		comedi_dev_put(dev);
4562306a36Sopenharmony_ci	}
4662306a36Sopenharmony_ci	if (!devices_q)
4762306a36Sopenharmony_ci		seq_puts(m, "no devices\n");
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	mutex_lock(&comedi_drivers_list_lock);
5062306a36Sopenharmony_ci	for (driv = comedi_drivers; driv; driv = driv->next) {
5162306a36Sopenharmony_ci		seq_printf(m, "%s:\n", driv->driver_name);
5262306a36Sopenharmony_ci		for (i = 0; i < driv->num_names; i++)
5362306a36Sopenharmony_ci			seq_printf(m, " %s\n",
5462306a36Sopenharmony_ci				   *(char **)((char *)driv->board_name +
5562306a36Sopenharmony_ci					      i * driv->offset));
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci		if (!driv->num_names)
5862306a36Sopenharmony_ci			seq_printf(m, " %s\n", driv->driver_name);
5962306a36Sopenharmony_ci	}
6062306a36Sopenharmony_ci	mutex_unlock(&comedi_drivers_list_lock);
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	return 0;
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_civoid __init comedi_proc_init(void)
6662306a36Sopenharmony_ci{
6762306a36Sopenharmony_ci	if (!proc_create_single("comedi", 0444, NULL, comedi_read))
6862306a36Sopenharmony_ci		pr_warn("comedi: unable to create proc entry\n");
6962306a36Sopenharmony_ci}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_civoid comedi_proc_cleanup(void)
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci	remove_proc_entry("comedi", NULL);
7462306a36Sopenharmony_ci}
75