www.pudn.com > voipAutoDialer.rar > voip-proc.c, change:2002-05-31,size:9242b


/*
 * voipb-proc.c
 * (C) Copyright 2001 by Thomas Davis <tdavis@beeble.homelinux.net>
 *
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include <linux/init.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/usb.h>

#include "telephony.h"
#include "voip-ver.h"
#include "voip-config.h"
#include "phonedev.h"
#include "ixjuser.h"
#include "voipblaster.h"

extern int VOIPdebug;
extern char VOIPversion[];

extern void add_caps(struct usb_voipblaster *);
extern struct usb_voipblaster *voipblaster_table[];

static struct proc_dir_entry *voipblaster_proc_entry;

/* Use our own dbg macro */
#undef dbg
#define dbg(format, arg...) do { if (VOIPdebug) printk(KERN_DEBUG __FUNCTION__ ": " format "\n" , ## arg); } while (0)

#undef info
#define info(format, arg...) printk(KERN_INFO __FUNCTION__ ": " format "\n" , ## arg)

struct setup_entries {
	char *name;
	int (*get_info)(char *, struct usb_voipblaster *);
	struct usb_voipblaster *dev;
};

struct device_entries {
	unsigned char serial[10];
	int minor;
	int status;
};

static struct device_entries devices[VOIP_MAX];

/*
 *
 */
static ssize_t read_debug(struct file *file, char *buf,
			  size_t count, loff_t *ppos)
{
	unsigned long p = *ppos;
	int len;
	char debug[6];

	dbg("VOIPdebug = %d, count = %d", VOIPdebug, count);

	if (count > 6)
		count = 6;

	len = snprintf(debug, 6, "%d\n", VOIPdebug);

	if (p >= len)
		return 0;

	copy_to_user(buf,(void *)debug, len);

	*ppos += len;

	dbg("len = %d", len);

	return len;
}

/*
 * Writing to /proc/voipblaster/debug sets the debug level.
 *
 */

static ssize_t write_debug(struct file * file, const char * buf,
			   size_t count, loff_t *ppos)
{

	char mybuff[33];

	if (count > 32) 
		count = 32;

	if (copy_from_user(mybuff, buf, count))
		return -EFAULT;

	mybuff[count-1] = 0;

	sscanf(mybuff, "%d", &VOIPdebug);

	dbg("count = %d, what = %s, VOIPdebug = %d", count, mybuff, VOIPdebug);

	return count;
}

static struct file_operations proc_debug_operations = {
	read:		read_debug,
	write:		write_debug,
};

/*
 *
 */
static ssize_t read_devices(struct file *file, char *buf,
			    size_t count, loff_t *ppos)
{
	unsigned long p = *ppos;
	int len;
	char debug[6];

	dbg("VOIPdebug = %d, count = %d", VOIPdebug, count);

	len = sprintf(debug, "devices\n");

	if (p >= len)
		return 0;

	copy_to_user(buf,(void *)debug, len);

	*ppos += len;

	dbg("len = %d", len);

	return len;
}

/*
 * Writing to /proc/voipblaster/debug sets the debug level.
 *
 */

static ssize_t write_devices(struct file * file, const char * buf,
			     size_t count, loff_t *ppos)
{

	char mybuff[33];

	if (count > 32) 
		count = 32;

	if (copy_from_user(mybuff, buf, count))
		return -EFAULT;

#if 0
	mybuff[count-1] = 0;

	sscanf(mybuff, "%d", &VOIPdebug);
#endif

	dbg("count = %d, what = %s, VOIPdebug = %d", count, mybuff, VOIPdebug);

	return count;
}

static struct file_operations proc_devices_operations = {
	read:		read_devices,
	write:		write_devices,
};

static int api(char *page, struct usb_voipblaster *dev)
{
	return sprintf(page, "OLD\n");
}

static int revision(char *page, struct usb_voipblaster *dev)
{
	return sprintf(page, "%s\n", dev->revision);
}

static int version(char *page, struct usb_voipblaster *dev)
{
	dbg("version = %s", VOIPversion);

	return sprintf(page,"%s\n", VOIPversion);
}

static int type(char *page, struct usb_voipblaster *dev)
{
	return sprintf(page,"%s\n", "Creative USB VOIPBlaster");
}

static int hookstate(char *page, struct usb_voipblaster *dev)
{
	return sprintf(page, "%s-hook\n", dev->hookstate ? "off" : "on");
}

static int voipminor(char *page, struct usb_voipblaster *dev)
{
	return sprintf(page, "%d\n", dev->minor);
}

static int status(char *page, struct usb_voipblaster *dev)
{
	int len;
	len = sprintf(page, "Readers: %d\n", dev->readers);
	len += sprintf(page + len, "Writers: %d\n", dev->writers);
	len += sprintf(page + len, "open_count: %d\n", dev->open_count);
        return len;
}

static int caps(char *page, struct usb_voipblaster *dev)
{
	int len;

	add_caps(dev);

	len = sprintf(page, "Capabilities: %d\n", dev->caps);
	len += sprintf(page + len, "PlayCODEC: ");

	switch (dev->play_codec) {
	case G723_63:
		len += sprintf(page + len, "G.723.1_6.3");
		break;
	case G723_53:
		len += sprintf(page + len, "G.723.1_5.3");
		break;
	default:
		len += sprintf(page + len, "NO_CODEC_CHOSEN");
		break;
	}

	len += sprintf(page + len, "\nRecordCODEC: ");
	switch (dev->rec_codec) {
	case G723_63:
		len += sprintf(page + len, "G.723.1_6.3");
		break;
	case G723_53:
		len += sprintf(page + len, "G.723.1_5.3");
		break;
	default:
		len += sprintf(page + len, "NO_CODEC_CHOSEN");
		break;
	}

	len += sprintf(page + len, "\nAEC: ");
	switch (dev->aec_level) {
	case AEC_OFF:
		len += sprintf(page + len, "Off");
		break;
	case AEC_LOW:
		len += sprintf(page + len, "Low");
		break;
	case AEC_MED:
		len += sprintf(page + len, "Med");
		break;
	case AEC_HIGH:
		len += sprintf(page + len, "High");
		break;
	case AEC_AUTO:
		len += sprintf(page + len, "Auto");
		break;
	case AEC_AGC:
		len += sprintf(page + len, "AEC/AGC");
		break;
	default:
		len += sprintf(page + len, "unknown(%i)", dev->aec_level);
		break;
	}

        return len;
}

static int portinfo(char *page, struct usb_voipblaster *dev)
{
	int len = 0;

	switch (dev->port) {
	case PORT_POTS:
		len += sprintf(page, "POTS\n");
		break;
	case PORT_PSTN:
		len += sprintf(page, "PSTN\n");
		break;
	case PORT_SPEAKER:
		len += sprintf(page, "SPEAKER/MIC\n");
		break;
	case PORT_HANDSET:
		len += sprintf(page, "HANDSET\n");
		break;
	default:
		len += sprintf(page, "UNKNOWN\n");
		break;
	}

        return len;
}

static int read_proc(char *page, char **start, off_t off,
				 int count, int *eof, void *data)
{
	int len;

	struct setup_entries *p = (struct setup_entries *) data;

	struct usb_voipblaster *dev = p->dev;

	dbg("calling %s", p->name);

	len = p->get_info(page, dev);

	if (len <= off+count) 
		*eof = 1;

        *start = page + off;

        len -= off;

        if (len>count) 
		len = count;

        if (len<0) 
		len = 0;

	dbg("len = %d", len);

        return len;
}

static struct setup_entries *p, simple_ones[] = {
		{"version", &version},
		{"api", &api},
		{NULL,NULL, NULL},
}, device_files[]= {
		{"revision", &revision},
		{"status", &status},
		{"type", &type },
		{"capabilities", &caps},
		{"hookstate", &hookstate},
		{"port", &portinfo},
		{"minor", &voipminor},
		{NULL, NULL, NULL},
};

void voipblaster_register_device(struct usb_voipblaster *dev)
{
#if 0
	struct proc_dir_entry *entry;
#endif

	dbg("start");

	dev->dir = create_proc_entry(dev->serialnum, S_IFDIR, 
				     voipblaster_proc_entry);

	dbg("mkdir done");

	for (p = device_files; p->name; p++) {
		dbg("device_files: %s", p->name);
		p->dev = dev;
		create_proc_read_entry(p->name, 0, dev->dir, 
				       read_proc, p);
	}

#if 0
	entry = create_proc_entry("debug", S_IWUSR | S_IRUGO, dev->dir);
	if (entry) {
		entry->proc_fops = &proc_debug_operations;
		entry->size = 2;
	}
#endif

	dbg("registered device %s", dev->serialnum);
}

void voipblaster_deregister_device(struct usb_voipblaster *dev)
{
	for (p = device_files; p->name; p++) {
		dbg("removing device_files : %s", p->name);
		remove_proc_entry(p->name, dev->dir);
	}

	dbg("removing %s", dev->serialnum);

	remove_proc_entry(dev->serialnum, voipblaster_proc_entry);

	dbg("done");

}

void __init voipblaster_proc_init(void)
{
	struct proc_dir_entry *entry;

	dbg("start");

	voipblaster_proc_entry = create_proc_entry("voipblaster", 
						   S_IFDIR, NULL);

	dbg("mkdir done");

	for (p = simple_ones; p->name; p++) {
		dbg("simple one : %s", p->name);
		p->dev = NULL;
		create_proc_read_entry(p->name, 0, voipblaster_proc_entry, 
				       &read_proc, p);
	}

	entry = create_proc_entry("debug", S_IWUSR | S_IRUGO, 
				  voipblaster_proc_entry);
	if (entry) {
		entry->proc_fops = &proc_debug_operations;
		entry->size = 2;
	}

	entry = create_proc_entry("devices", S_IWUSR | S_IRUGO, 
				  voipblaster_proc_entry);
	if (entry) {
		entry->proc_fops = &proc_devices_operations;
		entry->size = 2;
	}

	dbg("registered simple ones!");
}

void __exit voipblaster_proc_destroy(void)
{
	for (p = simple_ones; p->name; p++) {
		dbg("simple one : %s", p->name);
		remove_proc_entry(p->name, voipblaster_proc_entry);
	}

	remove_proc_entry("debug", voipblaster_proc_entry);

	remove_proc_entry("voipblaster", 0);

	voipblaster_proc_entry = NULL;
}

/*
 * Local variables:
 *  c-indent-level: 8
 *  c-basic-offset: 8
 *  tab-width: 8
 * End:
 */