/*
 *
 * Copyright 1999-2000 Digi International (www.digi.com)
 *     James Puzzo <jamesp at digi dot com>
 *
 * 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, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

/*
 *
 *  Filename:
 *
 *     dgrp_ports_ops.c
 *
 *  Description:
 *
 *     Handle the file operations required for the /proc/dgrp/ports/...
 *     devices.  Basically gathers tty status for the node and returns it.
 *
 *  Author:
 *
 *     James A. Puzzo
 *
 */

#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/tty.h>
#include <linux/sched.h>
#include <linux/seq_file.h>

#include "dgrp_common.h"

/* File operation declarations */
static int dgrp_ports_open(struct inode *, struct file *);

const struct file_operations dgrp_ports_ops = {
	.owner   = THIS_MODULE,
	.open    = dgrp_ports_open,
	.read    = seq_read,
	.llseek	 = seq_lseek,
	.release = seq_release
};

static void *dgrp_ports_seq_start(struct seq_file *seq, loff_t *pos)
{
	if (*pos == 0)
		seq_puts(seq, "#num tty_open pr_open tot_wait MSTAT  IFLAG  OFLAG  CFLAG  BPS    DIGIFLAGS\n");

	return pos;
}

static void *dgrp_ports_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	struct nd_struct *nd = seq->private;

	if (*pos >= nd->nd_chan_count)
		return NULL;

	*pos += 1;

	return pos;
}

static void dgrp_ports_seq_stop(struct seq_file *seq, void *v)
{
}

static int dgrp_ports_seq_show(struct seq_file *seq, void *v)
{
	loff_t *pos = v;
	struct nd_struct *nd;
	struct ch_struct *ch;
	struct un_struct *tun, *pun;
	unsigned int totcnt;

	nd = seq->private;
	if (!nd)
		return 0;

	if (*pos >= nd->nd_chan_count)
		return 0;

	ch = &nd->nd_chan[*pos];
	tun = &ch->ch_tun;
	pun = &ch->ch_pun;

	/*
	 * If port is not open and no one is waiting to
	 * open it, the modem signal values can't be
	 * trusted, and will be zeroed.
	 */
	totcnt = tun->un_open_count +
		pun->un_open_count +
		ch->ch_wait_count[0] +
		ch->ch_wait_count[1] +
		ch->ch_wait_count[2];

	seq_printf(seq, "%02d      %02d      %02d      %02d     0x%04X 0x%04X 0x%04X 0x%04X %-6d 0x%04X\n",
		   (int) *pos,
		   tun->un_open_count,
		   pun->un_open_count,
		   ch->ch_wait_count[0] +
		   ch->ch_wait_count[1] +
		   ch->ch_wait_count[2],
		   (totcnt ? ch->ch_s_mlast : 0),
		   ch->ch_s_iflag,
		   ch->ch_s_oflag,
		   ch->ch_s_cflag,
		   (ch->ch_s_brate ? (1843200 / ch->ch_s_brate) : 0),
		   ch->ch_digi.digi_flags);

	return 0;
}

static const struct seq_operations ports_seq_ops = {
	.start = dgrp_ports_seq_start,
	.next  = dgrp_ports_seq_next,
	.stop  = dgrp_ports_seq_stop,
	.show  = dgrp_ports_seq_show,
};

/**
 * dgrp_ports_open -- open the /proc/dgrp/ports/... device
 * @inode: struct inode *
 * @file: struct file *
 *
 * Open function to open the /proc/dgrp/ports device for a PortServer.
 * This is the open function for struct file_operations
 */
static int dgrp_ports_open(struct inode *inode, struct file *file)
{
	struct seq_file *seq;
	int rtn;

	rtn = seq_open(file, &ports_seq_ops);
	if (!rtn) {
		seq = file->private_data;
		seq->private = PDE_DATA(inode);
	}

	return rtn;
}
