239 lines
4.6 KiB
C
239 lines
4.6 KiB
C
/*
|
|
* $Id$
|
|
*
|
|
* Copyright(C) 2004 Frank A. Uepping
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
|
|
#include <linux/seq_file.h>
|
|
#include <linux/proc_fs.h>
|
|
#include <linux/isdn/capidevice.h>
|
|
|
|
|
|
#ifdef CONFIG_PROC_FS
|
|
extern struct list_head capi_appls_list;
|
|
extern struct semaphore capi_appls_list_sem;
|
|
|
|
|
|
static struct capi_appl*
|
|
get_capi_appl_by_idx(loff_t idx)
|
|
{
|
|
struct capi_appl* a;
|
|
|
|
list_for_each_entry(a, &capi_appls_list, entry)
|
|
if (!idx--)
|
|
return a;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
static inline struct capi_appl*
|
|
get_capi_appl_next(struct capi_appl* a)
|
|
{
|
|
struct list_head* n = a->entry.next;
|
|
|
|
return n != &capi_appls_list ? list_entry(n, struct capi_appl, entry) : NULL;
|
|
}
|
|
|
|
|
|
static void*
|
|
appl_start(struct seq_file* seq, loff_t* pos)
|
|
{
|
|
down(&capi_appls_list_sem);
|
|
|
|
return *pos ? get_capi_appl_by_idx(*pos - 1) : SEQ_START_TOKEN;
|
|
}
|
|
|
|
|
|
static void*
|
|
appl_next(struct seq_file* seq, void* v, loff_t* pos)
|
|
{
|
|
++*pos;
|
|
|
|
return v == SEQ_START_TOKEN ? get_capi_appl_by_idx(0) : get_capi_appl_next(v);
|
|
}
|
|
|
|
|
|
static void
|
|
appl_stop(struct seq_file* seq, void* v)
|
|
{
|
|
up(&capi_appls_list_sem);
|
|
}
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
|
|
static int
|
|
applparams_show(struct seq_file* seq, void* v)
|
|
{
|
|
if (v == SEQ_START_TOKEN)
|
|
seq_puts(seq, "id : log_conns data_packets data_len\n");
|
|
else {
|
|
const struct capi_appl* a = v;
|
|
|
|
seq_printf(seq, "%-5u: %-9d %-12d %-8d\n",
|
|
a->id,
|
|
a->params.level3cnt,
|
|
a->params.datablkcnt,
|
|
a->params.datablklen);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static struct seq_operations applparams_seq_ops = {
|
|
.start = appl_start,
|
|
.next = appl_next,
|
|
.stop = appl_stop,
|
|
.show = applparams_show
|
|
};
|
|
|
|
|
|
static int
|
|
applparams_open(struct inode* inode, struct file* file)
|
|
{
|
|
return seq_open(file, &applparams_seq_ops);
|
|
}
|
|
|
|
|
|
static struct file_operations applparams_file_ops = {
|
|
.owner = THIS_MODULE,
|
|
.open = applparams_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.release = seq_release
|
|
};
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
|
|
static int
|
|
applstats_show(struct seq_file* seq, void* v)
|
|
{
|
|
if (v == SEQ_START_TOKEN)
|
|
seq_puts(seq, "id : tx_packets tx_bytes | rx_packets rx_bytes rx_queue_len\n");
|
|
else {
|
|
const struct capi_appl* a = v;
|
|
|
|
seq_printf(seq, "%-5u: %-10lu %-8lu | %-10lu %-8lu %-8u\n",
|
|
a->id,
|
|
a->stats.tx_packets,
|
|
a->stats.tx_bytes,
|
|
a->stats.rx_packets,
|
|
a->stats.rx_bytes,
|
|
skb_queue_len(&a->msg_queue));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static struct seq_operations applstats_seq_ops = {
|
|
.start = appl_start,
|
|
.next = appl_next,
|
|
.stop = appl_stop,
|
|
.show = applstats_show
|
|
};
|
|
|
|
|
|
static int
|
|
applstats_open(struct inode* inode, struct file* file)
|
|
{
|
|
return seq_open(file, &applstats_seq_ops);
|
|
}
|
|
|
|
|
|
static struct file_operations applstats_file_ops = {
|
|
.owner = THIS_MODULE,
|
|
.open = applstats_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.release = seq_release
|
|
};
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
|
|
static struct proc_dir_entry* proc_capi;
|
|
|
|
|
|
static int
|
|
create_seq_entry(const char* name, struct file_operations* fops)
|
|
{
|
|
struct proc_dir_entry* p = create_proc_entry(name, 0444, proc_capi);
|
|
if (!p)
|
|
return -ENOMEM;
|
|
|
|
p->proc_fops = fops;
|
|
p->owner = THIS_MODULE;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int __init
|
|
capi_register_proc(void)
|
|
{
|
|
proc_capi = proc_mkdir("capi", NULL);
|
|
if (!proc_capi)
|
|
return -ENOMEM;
|
|
proc_capi->owner = THIS_MODULE;
|
|
|
|
if (create_seq_entry("applparams", &applparams_file_ops))
|
|
goto Err1;
|
|
|
|
if (create_seq_entry("applstats", &applstats_file_ops))
|
|
goto Err2;
|
|
|
|
return 0;
|
|
|
|
Err2: remove_proc_entry("applparams", proc_capi);
|
|
Err1: remove_proc_entry("capi", NULL);
|
|
|
|
return -ENOMEM;
|
|
}
|
|
|
|
|
|
void __exit
|
|
capi_unregister_proc(void)
|
|
{
|
|
remove_proc_entry("applstats", proc_capi);
|
|
remove_proc_entry("applparams", proc_capi);
|
|
|
|
remove_proc_entry("capi", NULL);
|
|
}
|
|
|
|
|
|
#else /* !CONFIG_PROC_FS */
|
|
int __init
|
|
capi_register_proc(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
void __exit
|
|
capi_unregister_proc(void)
|
|
{
|
|
}
|
|
#endif /* CONFIG_PROC_FS */
|