xpp: Don't use create_proc_read_entry()

Don't use create_proc_read_entry() as that is deprecated, but rather use
proc_create_data() and seq_file instead.

This is needed to compile against Linux 3.10.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
[tzafrir.cohen@xorcom.com: fixed passing /proc/xpp/XPD/summary xbus number]
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Cc: Russ Meyerriecks <rmeyerriecks@digium.com>
Cc: Oron Peled <oron.peled@xorcom.com>
This commit is contained in:
Shaun Ruffell 2013-05-21 15:33:18 -05:00 committed by Tzafrir Cohen
parent ba2fdf2dac
commit 1f20b5f8fa
6 changed files with 393 additions and 415 deletions

View File

@ -26,6 +26,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/seq_file.h>
#include "xpd.h" #include "xpd.h"
#include "xproto.h" #include "xproto.h"
#include "xpp_dahdi.h" #include "xpp_dahdi.h"
@ -152,8 +153,7 @@ static int write_state_register(xpd_t *xpd, __u8 value);
static bool bri_packet_is_valid(xpacket_t *pack); static bool bri_packet_is_valid(xpacket_t *pack);
static void bri_packet_dump(const char *msg, xpacket_t *pack); static void bri_packet_dump(const char *msg, xpacket_t *pack);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int proc_bri_info_read(char *page, char **start, off_t off, int count, static const struct file_operations proc_bri_info_ops;
int *eof, void *data);
#endif #endif
static int bri_spanconfig(struct file *file, struct dahdi_span *span, static int bri_spanconfig(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc); struct dahdi_lineconfig *lc);
@ -673,9 +673,8 @@ static int bri_proc_create(xbus_t *xbus, xpd_t *xpd)
XPD_DBG(PROC, xpd, "\n"); XPD_DBG(PROC, xpd, "\n");
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
XPD_DBG(PROC, xpd, "Creating '%s'\n", PROC_BRI_INFO_FNAME); XPD_DBG(PROC, xpd, "Creating '%s'\n", PROC_BRI_INFO_FNAME);
priv->bri_info = priv->bri_info = proc_create_data(PROC_BRI_INFO_FNAME, 0444,
create_proc_read_entry(PROC_BRI_INFO_FNAME, 0444, xpd->proc_xpd_dir, xpd->proc_xpd_dir, &proc_bri_info_ops, xpd);
proc_bri_info_read, xpd);
if (!priv->bri_info) { if (!priv->bri_info) {
XPD_ERR(xpd, "Failed to create proc file '%s'\n", XPD_ERR(xpd, "Failed to create proc file '%s'\n",
PROC_BRI_INFO_FNAME); PROC_BRI_INFO_FNAME);
@ -1667,12 +1666,10 @@ static void bri_packet_dump(const char *msg, xpacket_t *pack)
/*------------------------- REGISTER Handling --------------------------*/ /*------------------------- REGISTER Handling --------------------------*/
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int proc_bri_info_read(char *page, char **start, off_t off, int count, static int proc_bri_info_show(struct seq_file *sfile, void *not_used)
int *eof, void *data)
{ {
int len = 0;
unsigned long flags; unsigned long flags;
xpd_t *xpd = data; xpd_t *xpd = sfile->private;
struct BRI_priv_data *priv; struct BRI_priv_data *priv;
DBG(PROC, "\n"); DBG(PROC, "\n");
@ -1681,13 +1678,10 @@ static int proc_bri_info_read(char *page, char **start, off_t off, int count,
spin_lock_irqsave(&xpd->lock, flags); spin_lock_irqsave(&xpd->lock, flags);
priv = xpd->priv; priv = xpd->priv;
BUG_ON(!priv); BUG_ON(!priv);
len += sprintf(page + len, "%05d Layer 1: ", priv->poll_counter); seq_printf(sfile, "%05d Layer 1: ", priv->poll_counter);
if (priv->reg30_good) { if (priv->reg30_good) {
len += seq_printf(sfile, "%-5s ", (priv->layer1_up) ? "UP" : "DOWN");
sprintf(page + len, "%-5s ", seq_printf(sfile,
(priv->layer1_up) ? "UP" : "DOWN");
len +=
sprintf(page + len,
"%c%d %-15s -- fr_sync=%d t2_exp=%d info0=%d g2_g3=%d\n", "%c%d %-15s -- fr_sync=%d t2_exp=%d info0=%d g2_g3=%d\n",
IS_NT(xpd) ? 'G' : 'F', IS_NT(xpd) ? 'G' : 'F',
priv->state_register.bits.v_su_sta, priv->state_register.bits.v_su_sta,
@ -1697,53 +1691,52 @@ static int proc_bri_info_read(char *page, char **start, off_t off, int count,
priv->state_register.bits.v_su_t2_exp, priv->state_register.bits.v_su_t2_exp,
priv->state_register.bits.v_su_info0, priv->state_register.bits.v_su_info0,
priv->state_register.bits.v_g2_g3); priv->state_register.bits.v_g2_g3);
} else } else {
len += sprintf(page + len, "Unknown\n"); seq_printf(sfile, "Unknown\n");
}
if (IS_NT(xpd)) if (IS_NT(xpd))
len += sprintf(page + len, "T1 Timer: %d\n", priv->t1); seq_printf(sfile, "T1 Timer: %d\n", priv->t1);
else else
len += sprintf(page + len, "T3 Timer: %d\n", priv->t3); seq_printf(sfile, "T3 Timer: %d\n", priv->t3);
len += sprintf(page + len, "Tick Counter: %d\n", priv->tick_counter); seq_printf(sfile, "Tick Counter: %d\n", priv->tick_counter);
len += seq_printf(sfile, "Last Poll Reply: %d ticks ago\n",
sprintf(page + len, "Last Poll Reply: %d ticks ago\n",
priv->reg30_ticks); priv->reg30_ticks);
len += sprintf(page + len, "reg30_good=%d\n", priv->reg30_good); seq_printf(sfile, "reg30_good=%d\n", priv->reg30_good);
len += seq_printf(sfile, "D-Channel: TX=[%5d] RX=[%5d] BAD=[%5d] ",
sprintf(page + len, "D-Channel: TX=[%5d] RX=[%5d] BAD=[%5d] ",
priv->dchan_tx_counter, priv->dchan_rx_counter, priv->dchan_tx_counter, priv->dchan_rx_counter,
priv->dchan_rx_drops); priv->dchan_rx_drops);
if (priv->dchan_alive) { if (priv->dchan_alive) {
len += seq_printf(sfile, "(alive %d K-ticks)\n",
sprintf(page + len, "(alive %d K-ticks)\n",
priv->dchan_alive_ticks / 1000); priv->dchan_alive_ticks / 1000);
} else { } else {
len += sprintf(page + len, "(dead)\n"); seq_printf(sfile, "(dead)\n");
} }
len += seq_printf(sfile, "dchan_notx_ticks: %d\n",
sprintf(page + len, "dchan_notx_ticks: %d\n",
priv->dchan_notx_ticks); priv->dchan_notx_ticks);
len += seq_printf(sfile, "dchan_norx_ticks: %d\n",
sprintf(page + len, "dchan_norx_ticks: %d\n",
priv->dchan_norx_ticks); priv->dchan_norx_ticks);
len += seq_printf(sfile, "LED: %-10s = %d\n", "GREEN",
sprintf(page + len, "LED: %-10s = %d\n", "GREEN",
priv->ledstate[GREEN_LED]); priv->ledstate[GREEN_LED]);
len += seq_printf(sfile, "LED: %-10s = %d\n", "RED",
sprintf(page + len, "LED: %-10s = %d\n", "RED",
priv->ledstate[RED_LED]); priv->ledstate[RED_LED]);
len += sprintf(page + len, "\nDCHAN:\n"); seq_printf(sfile, "\nDCHAN:\n");
len += sprintf(page + len, "\n"); seq_printf(sfile, "\n");
spin_unlock_irqrestore(&xpd->lock, flags); spin_unlock_irqrestore(&xpd->lock, flags);
if (len <= off + count) return 0;
*eof = 1;
*start = page + off;
len -= off;
if (len > count)
len = count;
if (len < 0)
len = 0;
return len;
} }
static int proc_bri_info_open(struct inode *inode, struct file *file)
{
return single_open(file, proc_bri_info_show, PDE_DATA(inode));
}
static const struct file_operations proc_bri_info_ops = {
.owner = THIS_MODULE,
.open = proc_bri_info_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#endif #endif
static int bri_xpd_probe(struct device *dev) static int bri_xpd_probe(struct device *dev)

View File

@ -24,6 +24,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include "xpd.h" #include "xpd.h"
#include "xproto.h" #include "xproto.h"
#include "xpp_dahdi.h" #include "xpp_dahdi.h"
@ -105,11 +107,9 @@ enum fxo_leds {
static bool fxo_packet_is_valid(xpacket_t *pack); static bool fxo_packet_is_valid(xpacket_t *pack);
static void fxo_packet_dump(const char *msg, xpacket_t *pack); static void fxo_packet_dump(const char *msg, xpacket_t *pack);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int proc_fxo_info_read(char *page, char **start, off_t off, int count, static const struct file_operations proc_fxo_info_ops;
int *eof, void *data);
#ifdef WITH_METERING #ifdef WITH_METERING
static int proc_xpd_metering_read(char *page, char **start, off_t off, static const struct file_operations proc_xpd_metering_ops;
int count, int *eof, void *data);
#endif #endif
#endif #endif
static void dahdi_report_battery(xpd_t *xpd, lineno_t chan); static void dahdi_report_battery(xpd_t *xpd, lineno_t chan);
@ -440,7 +440,6 @@ static void fxo_proc_remove(xbus_t *xbus, xpd_t *xpd)
#ifdef WITH_METERING #ifdef WITH_METERING
if (priv->meteringfile) { if (priv->meteringfile) {
XPD_DBG(PROC, xpd, "Removing xpd metering tone file\n"); XPD_DBG(PROC, xpd, "Removing xpd metering tone file\n");
priv->meteringfile->data = NULL;
remove_proc_entry(PROC_METERING_FNAME, xpd->proc_xpd_dir); remove_proc_entry(PROC_METERING_FNAME, xpd->proc_xpd_dir);
priv->meteringfile = NULL; priv->meteringfile = NULL;
} }
@ -461,9 +460,9 @@ static int fxo_proc_create(xbus_t *xbus, xpd_t *xpd)
priv = xpd->priv; priv = xpd->priv;
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
XPD_DBG(PROC, xpd, "Creating FXO_INFO file\n"); XPD_DBG(PROC, xpd, "Creating FXO_INFO file\n");
priv->fxo_info = priv->fxo_info = proc_create_data(PROC_FXO_INFO_FNAME, 0444,
create_proc_read_entry(PROC_FXO_INFO_FNAME, 0444, xpd->proc_xpd_dir, xpd->proc_xpd_dir,
proc_fxo_info_read, xpd); &proc_fxo_info_ops, xpd);
if (!priv->fxo_info) { if (!priv->fxo_info) {
XPD_ERR(xpd, "Failed to create proc file '%s'\n", XPD_ERR(xpd, "Failed to create proc file '%s'\n",
PROC_FXO_INFO_FNAME); PROC_FXO_INFO_FNAME);
@ -473,9 +472,9 @@ static int fxo_proc_create(xbus_t *xbus, xpd_t *xpd)
SET_PROC_DIRENTRY_OWNER(priv->fxo_info); SET_PROC_DIRENTRY_OWNER(priv->fxo_info);
#ifdef WITH_METERING #ifdef WITH_METERING
XPD_DBG(PROC, xpd, "Creating Metering tone file\n"); XPD_DBG(PROC, xpd, "Creating Metering tone file\n");
priv->meteringfile = priv->meteringfile = proc_create_data(PROC_METERING_FNAME, 0444,
create_proc_read_entry(PROC_METERING_FNAME, 0444, xpd->proc_xpd_dir, xpd->proc_xpd_dir,
proc_xpd_metering_read, xpd); &proc_xpd_metering_ops, xpd);
if (!priv->meteringfile) { if (!priv->meteringfile) {
XPD_ERR(xpd, "Failed to create proc file '%s'\n", XPD_ERR(xpd, "Failed to create proc file '%s'\n",
PROC_METERING_FNAME); PROC_METERING_FNAME);
@ -1347,12 +1346,10 @@ static void fxo_packet_dump(const char *msg, xpacket_t *pack)
/*------------------------- DAA Handling --------------------------*/ /*------------------------- DAA Handling --------------------------*/
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int proc_fxo_info_read(char *page, char **start, off_t off, int count, static int proc_fxo_info_show(struct seq_file *sfile, void *not_used)
int *eof, void *data)
{ {
int len = 0;
unsigned long flags; unsigned long flags;
xpd_t *xpd = data; xpd_t *xpd = sfile->private;
struct FXO_priv_data *priv; struct FXO_priv_data *priv;
int i; int i;
@ -1361,42 +1358,43 @@ static int proc_fxo_info_read(char *page, char **start, off_t off, int count,
spin_lock_irqsave(&xpd->lock, flags); spin_lock_irqsave(&xpd->lock, flags);
priv = xpd->priv; priv = xpd->priv;
BUG_ON(!priv); BUG_ON(!priv);
len += sprintf(page + len, "\t%-17s: ", "Channel"); seq_printf(sfile, "\t%-17s: ", "Channel");
for_each_line(xpd, i) { for_each_line(xpd, i) {
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
&& !IS_SET(PHONEDEV(xpd).digital_inputs, i)) && !IS_SET(PHONEDEV(xpd).digital_inputs, i)) {
len += sprintf(page + len, "%4d ", i % 10); seq_printf(sfile, "%4d ", i % 10);
} }
len += sprintf(page + len, "\nLeds:"); }
len += sprintf(page + len, "\n\t%-17s: ", "state"); seq_printf(sfile, "\nLeds:");
seq_printf(sfile, "\n\t%-17s: ", "state");
for_each_line(xpd, i) { for_each_line(xpd, i) {
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
&& !IS_SET(PHONEDEV(xpd).digital_inputs, i)) && !IS_SET(PHONEDEV(xpd).digital_inputs, i)) {
len += seq_printf(sfile, " %d%d ",
sprintf(page + len, " %d%d ",
IS_SET(priv->ledstate[LED_GREEN], i), IS_SET(priv->ledstate[LED_GREEN], i),
IS_SET(priv->ledstate[LED_RED], i)); IS_SET(priv->ledstate[LED_RED], i));
} }
len += sprintf(page + len, "\n\t%-17s: ", "blinking"); }
seq_printf(sfile, "\n\t%-17s: ", "blinking");
for_each_line(xpd, i) { for_each_line(xpd, i) {
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
&& !IS_SET(PHONEDEV(xpd).digital_inputs, i)) && !IS_SET(PHONEDEV(xpd).digital_inputs, i)) {
len += seq_printf(sfile, " %d%d ",
sprintf(page + len, " %d%d ",
IS_BLINKING(priv, i, LED_GREEN), IS_BLINKING(priv, i, LED_GREEN),
IS_BLINKING(priv, i, LED_RED)); IS_BLINKING(priv, i, LED_RED));
} }
len += sprintf(page + len, "\nBattery-Data:");
len += sprintf(page + len, "\n\t%-17s: ", "voltage");
for_each_line(xpd, i) {
len += sprintf(page + len, "%4d ", priv->battery_voltage[i]);
} }
len += sprintf(page + len, "\n\t%-17s: ", "current"); seq_printf(sfile, "\nBattery-Data:");
seq_printf(sfile, "\n\t%-17s: ", "voltage");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += sprintf(page + len, "%4d ", priv->battery_current[i]); seq_printf(sfile, "%4d ", priv->battery_voltage[i]);
} }
len += sprintf(page + len, "\nBattery:"); seq_printf(sfile, "\n\t%-17s: ", "current");
len += sprintf(page + len, "\n\t%-17s: ", "on"); for_each_line(xpd, i) {
seq_printf(sfile, "%4d ", priv->battery_current[i]);
}
seq_printf(sfile, "\nBattery:");
seq_printf(sfile, "\n\t%-17s: ", "on");
for_each_line(xpd, i) { for_each_line(xpd, i) {
char *bat; char *bat;
@ -1406,14 +1404,14 @@ static int proc_fxo_info_read(char *page, char **start, off_t off, int count,
bat = "-"; bat = "-";
else else
bat = "."; bat = ".";
len += sprintf(page + len, "%4s ", bat); seq_printf(sfile, "%4s ", bat);
} }
len += sprintf(page + len, "\n\t%-17s: ", "debounce"); seq_printf(sfile, "\n\t%-17s: ", "debounce");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += sprintf(page + len, "%4d ", priv->nobattery_debounce[i]); seq_printf(sfile, "%4d ", priv->nobattery_debounce[i]);
} }
len += sprintf(page + len, "\nPolarity-Reverse:"); seq_printf(sfile, "\nPolarity-Reverse:");
len += sprintf(page + len, "\n\t%-17s: ", "polarity"); seq_printf(sfile, "\n\t%-17s: ", "polarity");
for_each_line(xpd, i) { for_each_line(xpd, i) {
char *polname; char *polname;
@ -1423,14 +1421,14 @@ static int proc_fxo_info_read(char *page, char **start, off_t off, int count,
polname = "-"; polname = "-";
else else
polname = "."; polname = ".";
len += sprintf(page + len, "%4s ", polname); seq_printf(sfile, "%4s ", polname);
} }
len += sprintf(page + len, "\n\t%-17s: ", "debounce"); seq_printf(sfile, "\n\t%-17s: ", "debounce");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += sprintf(page + len, "%4d ", priv->polarity_debounce[i]); seq_printf(sfile, "%4d ", priv->polarity_debounce[i]);
} }
len += sprintf(page + len, "\nPower-Denial:"); seq_printf(sfile, "\nPower-Denial:");
len += sprintf(page + len, "\n\t%-17s: ", "power"); seq_printf(sfile, "\n\t%-17s: ", "power");
for_each_line(xpd, i) { for_each_line(xpd, i) {
char *curr; char *curr;
@ -1440,45 +1438,46 @@ static int proc_fxo_info_read(char *page, char **start, off_t off, int count,
curr = "-"; curr = "-";
else else
curr = "."; curr = ".";
len += sprintf(page + len, "%4s ", curr); seq_printf(sfile, "%4s ", curr);
} }
len += sprintf(page + len, "\n\t%-17s: ", "safezone"); seq_printf(sfile, "\n\t%-17s: ", "safezone");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += seq_printf(sfile, "%4d ", priv->power_denial_safezone[i]);
sprintf(page + len, "%4d ", priv->power_denial_safezone[i]);
} }
len += sprintf(page + len, "\n\t%-17s: ", "delay"); seq_printf(sfile, "\n\t%-17s: ", "delay");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += sprintf(page + len, "%4d ", priv->power_denial_delay[i]); seq_printf(sfile, "%4d ", priv->power_denial_delay[i]);
} }
#ifdef WITH_METERING #ifdef WITH_METERING
len += sprintf(page + len, "\nMetering:"); seq_printf(sfile, "\nMetering:");
len += sprintf(page + len, "\n\t%-17s: ", "count"); seq_printf(sfile, "\n\t%-17s: ", "count");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += sprintf(page + len, "%4d ", priv->metering_count[i]); seq_printf(sfile, "%4d ", priv->metering_count[i]);
} }
#endif #endif
len += sprintf(page + len, "\n"); seq_printf(sfile, "\n");
spin_unlock_irqrestore(&xpd->lock, flags); spin_unlock_irqrestore(&xpd->lock, flags);
if (len <= off + count) return 0;
*eof = 1;
*start = page + off;
len -= off;
if (len > count)
len = count;
if (len < 0)
len = 0;
return len;
} }
#endif
static int proc_fxo_info_open(struct inode *inode, struct file *file)
{
return single_open(file, proc_fxo_info_show, PDE_DATA(inode));
}
static const struct file_operations proc_fxo_info_ops = {
.owner = THIS_MODULE,
.open = proc_fxo_info_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#ifdef WITH_METERING #ifdef WITH_METERING
static int proc_xpd_metering_read(char *page, char **start, off_t off, static int proc_xpd_metering_show(struct seq_file *sfile, void *not_used)
int count, int *eof, void *data)
{ {
int len = 0;
unsigned long flags; unsigned long flags;
xpd_t *xpd = data; xpd_t *xpd = sfile->private;
struct FXO_priv_data *priv; struct FXO_priv_data *priv;
int i; int i;
@ -1487,25 +1486,31 @@ static int proc_xpd_metering_read(char *page, char **start, off_t off,
priv = xpd->priv; priv = xpd->priv;
BUG_ON(!priv); BUG_ON(!priv);
spin_lock_irqsave(&xpd->lock, flags); spin_lock_irqsave(&xpd->lock, flags);
len += sprintf(page + len, "# Chan\tMeter (since last read)\n"); seq_printf(sfile, "# Chan\tMeter (since last read)\n");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += seq_printf(sfile, "%d\t%d\n", i, priv->metering_count[i]);
sprintf(page + len, "%d\t%d\n", i, priv->metering_count[i]);
} }
spin_unlock_irqrestore(&xpd->lock, flags); spin_unlock_irqrestore(&xpd->lock, flags);
if (len <= off + count)
*eof = 1;
*start = page + off;
len -= off;
if (len > count)
len = count;
if (len < 0)
len = 0;
/* Zero meters */ /* Zero meters */
for_each_line(xpd, i) for_each_line(xpd, i)
priv->metering_count[i] = 0; priv->metering_count[i] = 0;
return len; return 0;
} }
static int proc_xpd_metering_open(struct inode *inode, struct file *file)
{
return single_open(file, proc_xpd_metering_show, PDE_DATA(inode));
}
static const struct file_operations proc_xpd_metering_ops = {
.owner = THIS_MODULE,
.open = proc_xpd_metering_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#endif
#endif #endif
static DEVICE_ATTR_READER(fxo_battery_show, dev, buf) static DEVICE_ATTR_READER(fxo_battery_show, dev, buf)

View File

@ -24,6 +24,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/seq_file.h>
#include "xpd.h" #include "xpd.h"
#include "xproto.h" #include "xproto.h"
#include "xpp_dahdi.h" #include "xpp_dahdi.h"
@ -120,11 +121,9 @@ enum fxs_state {
static bool fxs_packet_is_valid(xpacket_t *pack); static bool fxs_packet_is_valid(xpacket_t *pack);
static void fxs_packet_dump(const char *msg, xpacket_t *pack); static void fxs_packet_dump(const char *msg, xpacket_t *pack);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int proc_fxs_info_read(char *page, char **start, off_t off, int count, static const struct file_operations proc_fxs_info_ops;
int *eof, void *data);
#ifdef WITH_METERING #ifdef WITH_METERING
static int proc_xpd_metering_write(struct file *file, static const struct file_operations proc_xpd_metering_ops;
const char __user *buffer, unsigned long count, void *data);
#endif #endif
#endif #endif
static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos); static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos);
@ -399,7 +398,6 @@ static void fxs_proc_remove(xbus_t *xbus, xpd_t *xpd)
#ifdef WITH_METERING #ifdef WITH_METERING
if (priv->meteringfile) { if (priv->meteringfile) {
XPD_DBG(PROC, xpd, "Removing xpd metering tone file\n"); XPD_DBG(PROC, xpd, "Removing xpd metering tone file\n");
priv->meteringfile->data = NULL;
remove_proc_entry(PROC_METERING_FNAME, xpd->proc_xpd_dir); remove_proc_entry(PROC_METERING_FNAME, xpd->proc_xpd_dir);
priv->meteringfile = NULL; priv->meteringfile = NULL;
} }
@ -421,9 +419,9 @@ static int fxs_proc_create(xbus_t *xbus, xpd_t *xpd)
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
XPD_DBG(PROC, xpd, "Creating FXS_INFO file\n"); XPD_DBG(PROC, xpd, "Creating FXS_INFO file\n");
priv->fxs_info = priv->fxs_info = proc_create_data(PROC_FXS_INFO_FNAME, 0444,
create_proc_read_entry(PROC_FXS_INFO_FNAME, 0444, xpd->proc_xpd_dir, xpd->proc_xpd_dir,
proc_fxs_info_read, xpd); &proc_fxs_info_ops, xpd);
if (!priv->fxs_info) { if (!priv->fxs_info) {
XPD_ERR(xpd, "Failed to create proc file '%s'\n", XPD_ERR(xpd, "Failed to create proc file '%s'\n",
PROC_FXS_INFO_FNAME); PROC_FXS_INFO_FNAME);
@ -433,18 +431,15 @@ static int fxs_proc_create(xbus_t *xbus, xpd_t *xpd)
SET_PROC_DIRENTRY_OWNER(priv->fxs_info); SET_PROC_DIRENTRY_OWNER(priv->fxs_info);
#ifdef WITH_METERING #ifdef WITH_METERING
XPD_DBG(PROC, xpd, "Creating Metering tone file\n"); XPD_DBG(PROC, xpd, "Creating Metering tone file\n");
priv->meteringfile = priv->meteringfile = proc_create_data(PROC_METERING_FNAME, 0200,
create_proc_entry(PROC_METERING_FNAME, 0200, xpd->proc_xpd_dir); xpd->proc_xpd_dir,
&proc_xpd_metering_ops, xpd);
if (!priv->meteringfile) { if (!priv->meteringfile) {
XPD_ERR(xpd, "Failed to create proc file '%s'\n", XPD_ERR(xpd, "Failed to create proc file '%s'\n",
PROC_METERING_FNAME); PROC_METERING_FNAME);
fxs_proc_remove(xbus, xpd); fxs_proc_remove(xbus, xpd);
return -EINVAL; return -EINVAL;
} }
SET_PROC_DIRENTRY_OWNER(priv->meteringfile);
priv->meteringfile->write_proc = proc_xpd_metering_write;
priv->meteringfile->read_proc = NULL;
priv->meteringfile->data = xpd;
#endif #endif
#endif #endif
return 0; return 0;
@ -1691,12 +1686,10 @@ static void fxs_packet_dump(const char *msg, xpacket_t *pack)
/*------------------------- SLIC Handling --------------------------*/ /*------------------------- SLIC Handling --------------------------*/
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int proc_fxs_info_read(char *page, char **start, off_t off, int count, static int proc_fxs_info_show(struct seq_file *sfile, void *not_used)
int *eof, void *data)
{ {
int len = 0;
unsigned long flags; unsigned long flags;
xpd_t *xpd = data; xpd_t *xpd = sfile->private;
struct FXS_priv_data *priv; struct FXS_priv_data *priv;
int i; int i;
int led; int led;
@ -1706,11 +1699,11 @@ static int proc_fxs_info_read(char *page, char **start, off_t off, int count,
spin_lock_irqsave(&xpd->lock, flags); spin_lock_irqsave(&xpd->lock, flags);
priv = xpd->priv; priv = xpd->priv;
BUG_ON(!priv); BUG_ON(!priv);
len += sprintf(page + len, "%-12s", "Channel:"); seq_printf(sfile, "%-12s", "Channel:");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += sprintf(page + len, "%4d", i); seq_printf(sfile, "%4d", i);
} }
len += sprintf(page + len, "\n%-12s", ""); seq_printf(sfile, "\n%-12s", "");
for_each_line(xpd, i) { for_each_line(xpd, i) {
char *chan_type; char *chan_type;
@ -1720,84 +1713,85 @@ static int proc_fxs_info_read(char *page, char **start, off_t off, int count,
chan_type = "in"; chan_type = "in";
else else
chan_type = ""; chan_type = "";
len += sprintf(page + len, "%4s", chan_type); seq_printf(sfile, "%4s", chan_type);
} }
len += sprintf(page + len, "\n%-12s", "idletxhook:"); seq_printf(sfile, "\n%-12s", "idletxhook:");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += sprintf(page + len, "%4d", priv->idletxhookstate[i]); seq_printf(sfile, "%4d", priv->idletxhookstate[i]);
} }
len += sprintf(page + len, "\n%-12s", "lasttxhook:"); seq_printf(sfile, "\n%-12s", "lasttxhook:");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += sprintf(page + len, "%4d", priv->lasttxhook[i]); seq_printf(sfile, "%4d", priv->lasttxhook[i]);
} }
len += sprintf(page + len, "\n%-12s", "ohttimer:"); seq_printf(sfile, "\n%-12s", "ohttimer:");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += sprintf(page + len, "%4d", priv->ohttimer[i]); seq_printf(sfile, "%4d", priv->ohttimer[i]);
} }
len += sprintf(page + len, "\n%-12s", "neon_blink:"); seq_printf(sfile, "\n%-12s", "neon_blink:");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += sprintf(page + len, "%4d", seq_printf(sfile, "%4d",
IS_SET(priv->neon_blinking, i)); IS_SET(priv->neon_blinking, i));
} }
len += sprintf(page + len, "\n%-12s", "search_fsk:"); seq_printf(sfile, "\n%-12s", "search_fsk:");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += sprintf(page + len, "%4d", seq_printf(sfile, "%4d",
IS_SET(priv->search_fsk_pattern, i)); IS_SET(priv->search_fsk_pattern, i));
} }
len += sprintf(page + len, "\n%-12s", "vbat_h:"); seq_printf(sfile, "\n%-12s", "vbat_h:");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += sprintf(page + len, "%4d", seq_printf(sfile, "%4d",
test_bit(i, (unsigned long *)&priv->vbat_h)); test_bit(i, (unsigned long *)&priv->vbat_h));
} }
len += sprintf(page + len, "\n"); seq_printf(sfile, "\n");
for (led = 0; led < NUM_LEDS; led++) { for (led = 0; led < NUM_LEDS; led++) {
len += sprintf(page + len, "\nLED #%d\t%-12s: ", seq_printf(sfile, "\nLED #%d\t%-12s: ",
led, "ledstate"); led, "ledstate");
for_each_line(xpd, i) { for_each_line(xpd, i) {
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
&& !IS_SET(PHONEDEV(xpd).digital_inputs, i)) && !IS_SET(PHONEDEV(xpd).digital_inputs, i))
len += seq_printf(sfile, "%d ",
sprintf(page + len, "%d ",
IS_SET(priv->ledstate[led], i)); IS_SET(priv->ledstate[led], i));
} }
len += sprintf(page + len, "\nLED #%d\t%-12s: ", seq_printf(sfile, "\nLED #%d\t%-12s: ",
led, "ledcontrol"); led, "ledcontrol");
for_each_line(xpd, i) { for_each_line(xpd, i) {
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
&& !IS_SET(PHONEDEV(xpd).digital_inputs, i)) && !IS_SET(PHONEDEV(xpd).digital_inputs, i))
len += seq_printf(sfile, "%d ",
sprintf(page + len, "%d ",
IS_SET(priv->ledcontrol[led], i)); IS_SET(priv->ledcontrol[led], i));
} }
len += sprintf(page + len, "\nLED #%d\t%-12s: ", seq_printf(sfile, "\nLED #%d\t%-12s: ",
led, "led_counter"); led, "led_counter");
for_each_line(xpd, i) { for_each_line(xpd, i) {
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
&& !IS_SET(PHONEDEV(xpd).digital_inputs, i)) && !IS_SET(PHONEDEV(xpd).digital_inputs, i))
len += seq_printf(sfile, "%d ",
sprintf(page + len, "%d ",
LED_COUNTER(priv, i, led)); LED_COUNTER(priv, i, led));
} }
} }
len += sprintf(page + len, "\n"); seq_printf(sfile, "\n");
spin_unlock_irqrestore(&xpd->lock, flags); spin_unlock_irqrestore(&xpd->lock, flags);
if (len <= off + count) return 0;
*eof = 1;
*start = page + off;
len -= off;
if (len > count)
len = count;
if (len < 0)
len = 0;
return len;
} }
#endif
static int proc_fxs_info_open(struct inode *inode, struct file *file)
{
return single_open(file, proc_fxs_info_show, PDE_DATA(inode));
}
static const struct file_operations proc_fxs_info_ops = {
.owner = THIS_MODULE,
.open = proc_fxs_info_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#ifdef WITH_METERING #ifdef WITH_METERING
static int proc_xpd_metering_write(struct file *file, const char static ssize_t proc_xpd_metering_write(struct file *file,
__user *buffer, unsigned long count, void *data) const char __user *buffer, size_t count, loff_t *offset)
{ {
xpd_t *xpd = data; xpd_t *xpd = file->private_data;
char buf[MAX_PROC_WRITE]; char buf[MAX_PROC_WRITE];
lineno_t chan; lineno_t chan;
int num; int num;
@ -1806,7 +1800,7 @@ static int proc_xpd_metering_write(struct file *file, const char
if (!xpd) if (!xpd)
return -ENODEV; return -ENODEV;
if (count >= MAX_PROC_WRITE - 1) { if (count >= MAX_PROC_WRITE - 1) {
XPD_ERR(xpd, "Metering string too long (%lu)\n", count); XPD_ERR(xpd, "Metering string too long (%zu)\n", count);
return -EINVAL; return -EINVAL;
} }
if (copy_from_user(&buf, buffer, count)) if (copy_from_user(&buf, buffer, count))
@ -1829,6 +1823,19 @@ static int proc_xpd_metering_write(struct file *file, const char
} }
return count; return count;
} }
static int proc_xpd_metering_open(struct inode *inode, struct file *file)
{
file->private_data = PDE_DATA(inode);
}
static const struct file_operations proc_xpd_metering_ops = {
.owner = THIS_MODULE,
.open = proc_xpd_metering_open,
.write = proc_xpd_metering_write,
.release = single_release,
};
#endif
#endif #endif
static int fxs_xpd_probe(struct device *dev) static int fxs_xpd_probe(struct device *dev)

View File

@ -25,6 +25,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h>
#ifdef PROTOCOL_DEBUG #ifdef PROTOCOL_DEBUG
#include <linux/ctype.h> #include <linux/ctype.h>
#endif #endif
@ -47,8 +48,7 @@ static const char rcsid[] = "$Id$";
#ifdef PROTOCOL_DEBUG #ifdef PROTOCOL_DEBUG
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
#define PROC_XBUS_COMMAND "command" #define PROC_XBUS_COMMAND "command"
static int proc_xbus_command_write(struct file *file, static const struct file_operations proc_xbus_command_ops;
const char __user *buffer, unsigned long count, void *data);
#endif #endif
#endif #endif
@ -63,8 +63,7 @@ static DEF_PARM_BOOL(dahdi_autoreg, 0, 0644,
"Register devices automatically (1) or not (0)"); "Register devices automatically (1) or not (0)");
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int xbus_read_proc(char *page, char **start, off_t off, int count, static const struct file_operations xbus_read_proc_ops;
int *eof, void *data);
#endif #endif
static void transport_init(xbus_t *xbus, struct xbus_ops *ops, static void transport_init(xbus_t *xbus, struct xbus_ops *ops,
ushort max_send_size, ushort max_send_size,
@ -1532,29 +1531,26 @@ xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size,
err = -EIO; err = -EIO;
goto nobus; goto nobus;
} }
xbus->proc_xbus_summary = xbus->proc_xbus_summary = proc_create_data(PROC_XBUS_SUMMARY, 0444,
create_proc_read_entry(PROC_XBUS_SUMMARY, 0444, xbus->proc_xbus_dir, xbus->proc_xbus_dir,
xbus_read_proc, &xbus_read_proc_ops,
(void *)((unsigned long)(xbus->num))); (void *)((unsigned long)xbus->num));
if (!xbus->proc_xbus_summary) { if (!xbus->proc_xbus_summary) {
XBUS_ERR(xbus, "Failed to create proc file '%s'\n", XBUS_ERR(xbus, "Failed to create proc file '%s'\n",
PROC_XBUS_SUMMARY); PROC_XBUS_SUMMARY);
err = -EIO; err = -EIO;
goto nobus; goto nobus;
} }
SET_PROC_DIRENTRY_OWNER(xbus->proc_xbus_summary);
#ifdef PROTOCOL_DEBUG #ifdef PROTOCOL_DEBUG
xbus->proc_xbus_command = xbus->proc_xbus_command = proc_create_data(PROC_XBUS_COMMAND, 0200,
create_proc_entry(PROC_XBUS_COMMAND, 0200, xbus->proc_xbus_dir); xbus->proc_xbus_dir,
&proc_xbus_command_ops, xbus);
if (!xbus->proc_xbus_command) { if (!xbus->proc_xbus_command) {
XBUS_ERR(xbus, "Failed to create proc file '%s'\n", XBUS_ERR(xbus, "Failed to create proc file '%s'\n",
PROC_XBUS_COMMAND); PROC_XBUS_COMMAND);
err = -EIO; err = -EIO;
goto nobus; goto nobus;
} }
xbus->proc_xbus_command->write_proc = proc_xbus_command_write;
xbus->proc_xbus_command->data = xbus;
SET_PROC_DIRENTRY_OWNER(xbus->proc_xbus_command);
#endif #endif
#endif #endif
xframe_queue_init(&xbus->command_queue, 10, command_queue_length, xframe_queue_init(&xbus->command_queue, 10, command_queue_length,
@ -1668,106 +1664,96 @@ out:
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int xbus_fill_proc_queue(char *p, struct xframe_queue *q) static void xbus_fill_proc_queue(struct seq_file *sfile, struct xframe_queue *q)
{ {
int len; seq_printf(sfile,
len = sprintf(p,
"%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d " "%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d "
"worst_lag %02ld.%ld ms\n", "worst_lag %02ld.%ld ms\n",
q->name, q->steady_state_count, q->count, q->max_count, q->name, q->steady_state_count, q->count, q->max_count,
q->worst_count, q->overflows, q->worst_lag_usec / 1000, q->worst_count, q->overflows, q->worst_lag_usec / 1000,
q->worst_lag_usec % 1000); q->worst_lag_usec % 1000);
xframe_queue_clearstats(q); xframe_queue_clearstats(q);
return len;
} }
static int xbus_read_proc(char *page, char **start, off_t off, int count, static int xbus_proc_show(struct seq_file *sfile, void *data)
int *eof, void *data)
{ {
xbus_t *xbus; xbus_t *xbus;
unsigned long flags; unsigned long flags;
int len = 0; int len = 0;
int i = (int)((unsigned long)data); int i = (int)((unsigned long)sfile->private);
xbus = get_xbus(__func__, i); /* until end of xbus_read_proc */ xbus = get_xbus(__func__, i); /* until end of xbus_proc_show() */
if (!xbus) if (!xbus)
goto out; return -EINVAL;
spin_lock_irqsave(&xbus->lock, flags); spin_lock_irqsave(&xbus->lock, flags);
len += seq_printf(sfile, "%s: CONNECTOR=%s LABEL=[%s] STATUS=%s\n",
sprintf(page + len, "%s: CONNECTOR=%s LABEL=[%s] STATUS=%s\n",
xbus->busname, xbus->connector, xbus->label, xbus->busname, xbus->connector, xbus->label,
(XBUS_FLAGS(xbus, CONNECTED)) ? "connected" : "missing"); (XBUS_FLAGS(xbus, CONNECTED)) ? "connected" : "missing");
len += xbus_fill_proc_queue(page + len, &xbus->send_pool); xbus_fill_proc_queue(sfile, &xbus->send_pool);
len += xbus_fill_proc_queue(page + len, &xbus->receive_pool); xbus_fill_proc_queue(sfile, &xbus->receive_pool);
len += xbus_fill_proc_queue(page + len, &xbus->command_queue); xbus_fill_proc_queue(sfile, &xbus->command_queue);
len += xbus_fill_proc_queue(page + len, &xbus->receive_queue); xbus_fill_proc_queue(sfile, &xbus->receive_queue);
len += xbus_fill_proc_queue(page + len, &xbus->pcm_tospan); xbus_fill_proc_queue(sfile, &xbus->pcm_tospan);
if (rx_tasklet) { if (rx_tasklet) {
len += sprintf(page + len, "\ncpu_rcv_intr: "); seq_printf(sfile, "\ncpu_rcv_intr: ");
for_each_online_cpu(i) for_each_online_cpu(i)
len += sprintf(page + len, "%5d ", xbus->cpu_rcv_intr[i]); seq_printf(sfile, "%5d ", xbus->cpu_rcv_intr[i]);
len += sprintf(page + len, "\ncpu_rcv_tasklet: "); seq_printf(sfile, "\ncpu_rcv_tasklet: ");
for_each_online_cpu(i) for_each_online_cpu(i)
len += seq_printf(sfile, "%5d ", xbus->cpu_rcv_tasklet[i]);
sprintf(page + len, "%5d ", xbus->cpu_rcv_tasklet[i]); seq_printf(sfile, "\n");
len += sprintf(page + len, "\n");
} }
len += seq_printf(sfile, "self_ticking: %d (last_tick at %ld)\n",
sprintf(page + len, "self_ticking: %d (last_tick at %ld)\n",
xbus->self_ticking, xbus->ticker.last_sample.tv.tv_sec); xbus->self_ticking, xbus->ticker.last_sample.tv.tv_sec);
len += seq_printf(sfile, "command_tick: %d\n",
sprintf(page + len, "command_tick: %d\n",
xbus->command_tick_counter); xbus->command_tick_counter);
len += sprintf(page + len, "usec_nosend: %d\n", xbus->usec_nosend); seq_printf(sfile, "usec_nosend: %d\n", xbus->usec_nosend);
len += seq_printf(sfile, "xbus: pcm_rx_counter = %d, frag = %d\n",
sprintf(page + len, "xbus: pcm_rx_counter = %d, frag = %d\n",
atomic_read(&xbus->pcm_rx_counter), xbus->xbus_frag_count); atomic_read(&xbus->pcm_rx_counter), xbus->xbus_frag_count);
len += seq_printf(sfile, "max_rx_process = %2ld.%ld ms\n",
sprintf(page + len, "max_rx_process = %2ld.%ld ms\n",
xbus->max_rx_process / 1000, xbus->max_rx_process % 1000); xbus->max_rx_process / 1000, xbus->max_rx_process % 1000);
xbus->max_rx_process = 0; xbus->max_rx_process = 0;
len += seq_printf(sfile, "\nTRANSPORT: max_send_size=%d refcount=%d\n",
sprintf(page + len, "\nTRANSPORT: max_send_size=%d refcount=%d\n",
MAX_SEND_SIZE(xbus), MAX_SEND_SIZE(xbus),
atomic_read(&xbus->transport.transport_refcount) atomic_read(&xbus->transport.transport_refcount)
); );
len += sprintf(page + len, "PCM Metrices:\n"); seq_printf(sfile, "PCM Metrices:\n");
len += seq_printf(sfile, "\tPCM TX: min=%ld max=%ld\n",
sprintf(page + len, "\tPCM TX: min=%ld max=%ld\n",
xbus->min_tx_sync, xbus->max_tx_sync); xbus->min_tx_sync, xbus->max_tx_sync);
len += seq_printf(sfile, "\tPCM RX: min=%ld max=%ld\n",
sprintf(page + len, "\tPCM RX: min=%ld max=%ld\n",
xbus->min_rx_sync, xbus->max_rx_sync); xbus->min_rx_sync, xbus->max_rx_sync);
len += sprintf(page + len, "COUNTERS:\n"); seq_printf(sfile, "COUNTERS:\n");
for (i = 0; i < XBUS_COUNTER_MAX; i++) { for (i = 0; i < XBUS_COUNTER_MAX; i++) {
len += seq_printf(sfile, "\t%-15s = %d\n", xbus_counters[i].name,
sprintf(page + len, "\t%-15s = %d\n", xbus_counters[i].name,
xbus->counters[i]); xbus->counters[i]);
} }
len += sprintf(page + len, "<-- len=%d\n", len); seq_printf(sfile, "<-- len=%d\n", len);
spin_unlock_irqrestore(&xbus->lock, flags); spin_unlock_irqrestore(&xbus->lock, flags);
put_xbus(__func__, xbus); /* from xbus_read_proc() */ put_xbus(__func__, xbus); /* from xbus_proc_show() */
out: return 0;
if (len <= off + count)
*eof = 1;
*start = page + off;
len -= off;
if (len > count)
len = count;
if (len < 0)
len = 0;
return len;
} }
static int xbus_read_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, xbus_proc_show, PDE_DATA(inode));
}
static const struct file_operations xbus_read_proc_ops = {
.owner = THIS_MODULE,
.open = xbus_read_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#ifdef PROTOCOL_DEBUG #ifdef PROTOCOL_DEBUG
static int proc_xbus_command_write(struct file *file, static ssize_t proc_xbus_command_write(struct file *file,
const char __user *buffer, unsigned long count, void *data) const char __user *buffer, size_t count, loff_t *offset)
{ {
char *buf; char *buf;
xbus_t *xbus = data; xbus_t *xbus = file->private_data;
char *p; char *p;
__u8 *pack_start; __u8 *pack_start;
__u8 *q; __u8 *q;
@ -1777,7 +1763,7 @@ static int proc_xbus_command_write(struct file *file,
const size_t max_text = max_len * 3 + 10; const size_t max_text = max_len * 3 + 10;
if (count > max_text) { if (count > max_text) {
XBUS_ERR(xbus, "%s: line too long (%ld > %zd)\n", __func__, XBUS_ERR(xbus, "%s: line too long (%zd > %zd)\n", __func__,
count, max_len); count, max_len);
return -EFBIG; return -EFBIG;
} }
@ -1790,7 +1776,7 @@ static int proc_xbus_command_write(struct file *file,
goto out; goto out;
} }
buf[count] = '\0'; buf[count] = '\0';
XBUS_DBG(GENERAL, xbus, "count=%ld\n", count); XBUS_DBG(GENERAL, xbus, "count=%zd\n", count);
/* /*
* We replace the content of buf[] from * We replace the content of buf[] from
* ascii representation to packet content * ascii representation to packet content
@ -1846,20 +1832,29 @@ out:
kfree(buf); kfree(buf);
return count; return count;
} }
static int proc_xbus_command_open(struct inode *inode, struct file *file)
{
file->private_data = PDE_DATA(inode);
return 0;
}
static const struct file_operations proc_xbus_command_ops = {
.owner = THIS_MODULE,
.open = proc_xbus_command_open,
.write = proc_xbus_command_write,
};
#endif #endif
static int read_proc_xbuses(char *page, char **start, off_t off, int count, static int xpp_proc_read_show(struct seq_file *sfile, void *data)
int *eof, void *data)
{ {
int len = 0;
int i; int i;
for (i = 0; i < MAX_BUSES; i++) { for (i = 0; i < MAX_BUSES; i++) {
xbus_t *xbus = get_xbus(__func__, i); xbus_t *xbus = get_xbus(__func__, i);
if (xbus) { if (xbus) {
len += seq_printf(sfile,
sprintf(page + len,
"%s: CONNECTOR=%s LABEL=[%s] STATUS=%s\n", "%s: CONNECTOR=%s LABEL=[%s] STATUS=%s\n",
xbus->busname, xbus->connector, xbus->label, xbus->busname, xbus->connector, xbus->label,
(XBUS_FLAGS(xbus, CONNECTED)) ? "connected" (XBUS_FLAGS(xbus, CONNECTED)) ? "connected"
@ -1868,19 +1863,24 @@ static int read_proc_xbuses(char *page, char **start, off_t off, int count,
} }
} }
#if 0 #if 0
len += sprintf(page + len, "<-- len=%d\n", len); seq_printf(sfile, "<-- len=%d\n", len);
#endif #endif
if (len <= off + count) return 0;
*eof = 1;
*start = page + off;
len -= off;
if (len > count)
len = count;
if (len < 0)
len = 0;
return len;
} }
static int xpp_proc_read_open(struct inode *inode, struct file *file)
{
return single_open(file, xpp_proc_read_show, PDE_DATA(inode));
}
static const struct file_operations xpp_proc_read_ops = {
.owner = THIS_MODULE,
.open = xpp_proc_read_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#endif #endif
static void transport_init(xbus_t *xbus, struct xbus_ops *ops, static void transport_init(xbus_t *xbus, struct xbus_ops *ops,
@ -1971,15 +1971,13 @@ int __init xbus_core_init(void)
INFO("FEATURE: with PROTOCOL_DEBUG\n"); INFO("FEATURE: with PROTOCOL_DEBUG\n");
#endif #endif
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
proc_xbuses = proc_xbuses = proc_create_data(PROC_XBUSES, 0444, xpp_proc_toplevel,
create_proc_read_entry(PROC_XBUSES, 0444, xpp_proc_toplevel, &xpp_proc_read_ops, NULL);
read_proc_xbuses, NULL);
if (!proc_xbuses) { if (!proc_xbuses) {
ERR("Failed to create proc file %s\n", PROC_XBUSES); ERR("Failed to create proc file %s\n", PROC_XBUSES);
ret = -EFAULT; ret = -EFAULT;
goto err; goto err;
} }
SET_PROC_DIRENTRY_OWNER(proc_xbuses);
#endif #endif
if ((ret = xpp_driver_init()) < 0) if ((ret = xpp_driver_init()) < 0)
goto err; goto err;

View File

@ -34,6 +34,7 @@
#include <linux/delay.h> /* for udelay */ #include <linux/delay.h> /* for udelay */
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <dahdi/kernel.h> #include <dahdi/kernel.h>
#include "xbus-core.h" #include "xbus-core.h"
#include "xproto.h" #include "xproto.h"
@ -102,8 +103,7 @@ int total_registered_spans(void)
} }
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int xpd_read_proc(char *page, char **start, off_t off, int count, static const struct file_operations xpd_read_proc_ops;
int *eof, void *data);
#endif #endif
/*------------------------- XPD Management -------------------------*/ /*------------------------- XPD Management -------------------------*/
@ -169,9 +169,9 @@ static int xpd_proc_create(xbus_t *xbus, xpd_t *xpd)
XPD_ERR(xpd, "Failed to create proc directory\n"); XPD_ERR(xpd, "Failed to create proc directory\n");
goto err; goto err;
} }
xpd->proc_xpd_summary = xpd->proc_xpd_summary = proc_create_data(PROC_XPD_SUMMARY, 0444,
create_proc_read_entry(PROC_XPD_SUMMARY, 0444, xpd->proc_xpd_dir, xpd->proc_xpd_dir,
xpd_read_proc, xpd); &xpd_read_proc_ops, xpd);
if (!xpd->proc_xpd_summary) { if (!xpd->proc_xpd_summary) {
XPD_ERR(xpd, "Failed to create proc file '%s'\n", XPD_ERR(xpd, "Failed to create proc file '%s'\n",
PROC_XPD_SUMMARY); PROC_XPD_SUMMARY);
@ -254,89 +254,72 @@ EXPORT_SYMBOL(create_xpd);
/** /**
* Prints a general procfs entry for the bus, under xpp/BUSNAME/summary * Prints a general procfs entry for the bus, under xpp/BUSNAME/summary
* @page TODO: figure out procfs
* @start TODO: figure out procfs
* @off TODO: figure out procfs
* @count TODO: figure out procfs
* @eof TODO: figure out procfs
* @data an xbus_t pointer with the bus data.
*/ */
static int xpd_read_proc(char *page, char **start, off_t off, int count, static int xpd_read_proc_show(struct seq_file *sfile, void *data)
int *eof, void *data)
{ {
int len = 0; int len = 0;
xpd_t *xpd = data; xpd_t *xpd = sfile->private;
int i; int i;
if (!xpd) if (!xpd)
goto out; return -EINVAL;
len += seq_printf(sfile,
sprintf(page + len,
"%s (%s, card %s, span %d)\n" "timing_priority: %d\n" "%s (%s, card %s, span %d)\n" "timing_priority: %d\n"
"timer_count: %d span->mainttimer=%d\n", xpd->xpdname, "timer_count: %d span->mainttimer=%d\n", xpd->xpdname,
xpd->type_name, (xpd->card_present) ? "present" : "missing", xpd->type_name, (xpd->card_present) ? "present" : "missing",
(SPAN_REGISTERED(xpd)) ? PHONEDEV(xpd).span.spanno : 0, (SPAN_REGISTERED(xpd)) ? PHONEDEV(xpd).span.spanno : 0,
PHONEDEV(xpd).timing_priority, xpd->timer_count, PHONEDEV(xpd).timing_priority, xpd->timer_count,
PHONEDEV(xpd).span.mainttimer); PHONEDEV(xpd).span.mainttimer);
len += seq_printf(sfile, "xpd_state: %s (%d)\n",
sprintf(page + len, "xpd_state: %s (%d)\n",
xpd_statename(xpd->xpd_state), xpd->xpd_state); xpd_statename(xpd->xpd_state), xpd->xpd_state);
len += seq_printf(sfile, "open_counter=%d refcount=%d\n",
sprintf(page + len, "open_counter=%d refcount=%d\n",
atomic_read(&PHONEDEV(xpd).open_counter), atomic_read(&PHONEDEV(xpd).open_counter),
refcount_xpd(xpd)); refcount_xpd(xpd));
len += seq_printf(sfile, "Address: U=%d S=%d\n", xpd->addr.unit,
sprintf(page + len, "Address: U=%d S=%d\n", xpd->addr.unit,
xpd->addr.subunit); xpd->addr.subunit);
len += sprintf(page + len, "Subunits: %d\n", xpd->subunits); seq_printf(sfile, "Subunits: %d\n", xpd->subunits);
len += sprintf(page + len, "Type: %d.%d\n\n", xpd->type, xpd->subtype); seq_printf(sfile, "Type: %d.%d\n\n", xpd->type, xpd->subtype);
len += sprintf(page + len, "pcm_len=%d\n\n", PHONEDEV(xpd).pcm_len); seq_printf(sfile, "pcm_len=%d\n\n", PHONEDEV(xpd).pcm_len);
len += seq_printf(sfile, "wanted_pcm_mask=0x%04X\n\n",
sprintf(page + len, "wanted_pcm_mask=0x%04X\n\n",
PHONEDEV(xpd).wanted_pcm_mask); PHONEDEV(xpd).wanted_pcm_mask);
len += seq_printf(sfile, "mute_dtmf=0x%04X\n\n",
sprintf(page + len, "mute_dtmf=0x%04X\n\n",
PHONEDEV(xpd).mute_dtmf); PHONEDEV(xpd).mute_dtmf);
len += sprintf(page + len, "STATES:"); seq_printf(sfile, "STATES:");
len += sprintf(page + len, "\n\t%-17s: ", "output_relays"); seq_printf(sfile, "\n\t%-17s: ", "output_relays");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += seq_printf(sfile, "%d ",
sprintf(page + len, "%d ",
IS_SET(PHONEDEV(xpd).digital_outputs, i)); IS_SET(PHONEDEV(xpd).digital_outputs, i));
} }
len += sprintf(page + len, "\n\t%-17s: ", "input_relays"); seq_printf(sfile, "\n\t%-17s: ", "input_relays");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += seq_printf(sfile, "%d ",
sprintf(page + len, "%d ",
IS_SET(PHONEDEV(xpd).digital_inputs, i)); IS_SET(PHONEDEV(xpd).digital_inputs, i));
} }
len += sprintf(page + len, "\n\t%-17s: ", "offhook"); seq_printf(sfile, "\n\t%-17s: ", "offhook");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += sprintf(page + len, "%d ", IS_OFFHOOK(xpd, i)); seq_printf(sfile, "%d ", IS_OFFHOOK(xpd, i));
} }
len += sprintf(page + len, "\n\t%-17s: ", "oht_pcm_pass"); seq_printf(sfile, "\n\t%-17s: ", "oht_pcm_pass");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += seq_printf(sfile, "%d ",
sprintf(page + len, "%d ",
IS_SET(PHONEDEV(xpd).oht_pcm_pass, i)); IS_SET(PHONEDEV(xpd).oht_pcm_pass, i));
} }
len += sprintf(page + len, "\n\t%-17s: ", "msg_waiting"); seq_printf(sfile, "\n\t%-17s: ", "msg_waiting");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += sprintf(page + len, "%d ", PHONEDEV(xpd).msg_waiting[i]); seq_printf(sfile, "%d ", PHONEDEV(xpd).msg_waiting[i]);
} }
len += sprintf(page + len, "\n\t%-17s: ", "ringing"); seq_printf(sfile, "\n\t%-17s: ", "ringing");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += sprintf(page + len, "%d ", PHONEDEV(xpd).ringing[i]); seq_printf(sfile, "%d ", PHONEDEV(xpd).ringing[i]);
} }
len += sprintf(page + len, "\n\t%-17s: ", "no_pcm"); seq_printf(sfile, "\n\t%-17s: ", "no_pcm");
for_each_line(xpd, i) { for_each_line(xpd, i) {
len += seq_printf(sfile, "%d ", IS_SET(PHONEDEV(xpd).no_pcm, i));
sprintf(page + len, "%d ", IS_SET(PHONEDEV(xpd).no_pcm, i));
} }
#if 1 #if 1
if (SPAN_REGISTERED(xpd)) { if (SPAN_REGISTERED(xpd)) {
len += sprintf(page + len, seq_printf(sfile,
"\nPCM:\n |" "\nPCM:\n |"
" [readchunk] |" " [readchunk] |"
" [writechunk] | W D"); " [writechunk] | W D");
@ -358,16 +341,16 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count,
wp = chan->writechunk; wp = chan->writechunk;
memcpy(rchunk, rp, DAHDI_CHUNKSIZE); memcpy(rchunk, rp, DAHDI_CHUNKSIZE);
memcpy(wchunk, wp, DAHDI_CHUNKSIZE); memcpy(wchunk, wp, DAHDI_CHUNKSIZE);
len += sprintf(page + len, "\n port %2d> | ", i); seq_printf(sfile, "\n port %2d> | ", i);
for (j = 0; j < DAHDI_CHUNKSIZE; j++) for (j = 0; j < DAHDI_CHUNKSIZE; j++)
len += sprintf(page + len, "%02X ", rchunk[j]); seq_printf(sfile, "%02X ", rchunk[j]);
len += sprintf(page + len, " | "); seq_printf(sfile, " | ");
for (j = 0; j < DAHDI_CHUNKSIZE; j++) for (j = 0; j < DAHDI_CHUNKSIZE; j++)
len += sprintf(page + len, "%02X ", wchunk[j]); seq_printf(sfile, "%02X ", wchunk[j]);
len += sprintf(page + len, " | %c", seq_printf(sfile, " | %c",
(IS_SET(PHONEDEV(xpd).wanted_pcm_mask, i)) (IS_SET(PHONEDEV(xpd).wanted_pcm_mask, i))
? '+' : ' '); ? '+' : ' ');
len += sprintf(page + len, " %c", seq_printf(sfile, " %c",
(IS_SET(PHONEDEV(xpd).mute_dtmf, i)) (IS_SET(PHONEDEV(xpd).mute_dtmf, i))
? '-' : ' '); ? '-' : ' ');
} }
@ -375,36 +358,37 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count,
#endif #endif
#if 0 #if 0
if (SPAN_REGISTERED(xpd)) { if (SPAN_REGISTERED(xpd)) {
len += sprintf(page + len, "\nSignalling:\n"); seq_printf(sfile, "\nSignalling:\n");
for_each_line(xpd, i) { for_each_line(xpd, i) {
struct dahdi_chan *chan = XPD_CHAN(xpd, i); struct dahdi_chan *chan = XPD_CHAN(xpd, i);
len += seq_printf(sfile,
sprintf(page + len,
"\t%2d> sigcap=0x%04X sig=0x%04X\n", i, "\t%2d> sigcap=0x%04X sig=0x%04X\n", i,
chan->sigcap, chan->sig); chan->sigcap, chan->sig);
} }
} }
#endif #endif
len += sprintf(page + len, "\nCOUNTERS:\n"); seq_printf(sfile, "\nCOUNTERS:\n");
for (i = 0; i < XPD_COUNTER_MAX; i++) { for (i = 0; i < XPD_COUNTER_MAX; i++) {
len += seq_printf(sfile, "\t\t%-20s = %d\n",
sprintf(page + len, "\t\t%-20s = %d\n",
xpd_counters[i].name, xpd->counters[i]); xpd_counters[i].name, xpd->counters[i]);
} }
len += sprintf(page + len, "<-- len=%d\n", len); seq_printf(sfile, "<-- len=%d\n", len);
out: return 0;
if (len <= off + count)
*eof = 1;
*start = page + off;
len -= off;
if (len > count)
len = count;
if (len < 0)
len = 0;
return len;
} }
static int xpd_read_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, xpd_read_proc_show, PDE_DATA(inode));
}
static const struct file_operations xpd_read_proc_ops = {
.owner = THIS_MODULE,
.open = xpd_read_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#endif #endif
const char *xpd_statename(enum xpd_state st) const char *xpd_statename(enum xpd_state st)

View File

@ -231,8 +231,7 @@ static int xusb_probe(struct usb_interface *interface,
const struct usb_device_id *id); const struct usb_device_id *id);
static void xusb_disconnect(struct usb_interface *interface); static void xusb_disconnect(struct usb_interface *interface);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int xusb_read_proc(char *page, char **start, off_t off, int count, static const struct file_operations xusb_read_proc_ops;
int *eof, void *data);
#endif #endif
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
@ -743,9 +742,9 @@ static int xusb_probe(struct usb_interface *interface,
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
DBG(PROC, DBG(PROC,
"Creating proc entry " PROC_USBXPP_SUMMARY " in bus proc dir.\n"); "Creating proc entry " PROC_USBXPP_SUMMARY " in bus proc dir.\n");
procsummary = procsummary = proc_create_data(PROC_USBXPP_SUMMARY, 0444,
create_proc_read_entry(PROC_USBXPP_SUMMARY, 0444, xbus->proc_xbus_dir, &xusb_read_proc_ops,
xbus->proc_xbus_dir, xusb_read_proc, xusb); xusb);
if (!procsummary) { if (!procsummary) {
XBUS_ERR(xbus, "Failed to create proc file '%s'\n", XBUS_ERR(xbus, "Failed to create proc file '%s'\n",
PROC_USBXPP_SUMMARY); PROC_USBXPP_SUMMARY);
@ -753,7 +752,6 @@ static int xusb_probe(struct usb_interface *interface,
retval = -EIO; retval = -EIO;
goto probe_failed; goto probe_failed;
} }
SET_PROC_DIRENTRY_OWNER(procsummary);
#endif #endif
bus_count++; bus_count++;
xusb->xbus_num = xbus->num; xusb->xbus_num = xbus->num;
@ -1020,90 +1018,83 @@ static void __exit xpp_usb_shutdown(void)
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int xusb_read_proc(char *page, char **start, off_t off, int count, static int xusb_read_proc_show(struct seq_file *sfile, void *data)
int *eof, void *data)
{ {
int len = 0;
unsigned long flags; unsigned long flags;
int i; int i;
//unsigned long stamp = jiffies; //unsigned long stamp = jiffies;
xusb_t *xusb = data; xusb_t *xusb = sfile->private;
uint usb_tx_delay[NUM_BUCKETS]; uint usb_tx_delay[NUM_BUCKETS];
const int mark_limit = tx_sluggish / USEC_BUCKET; const int mark_limit = tx_sluggish / USEC_BUCKET;
if (!xusb) if (!xusb)
goto out; return 0;
// TODO: probably needs a per-xusb lock: // TODO: probably needs a per-xusb lock:
spin_lock_irqsave(&xusb_lock, flags); spin_lock_irqsave(&xusb_lock, flags);
len += seq_printf(sfile, "Device: %03d/%03d\n", xusb->udev->bus->busnum,
sprintf(page + len, "Device: %03d/%03d\n", xusb->udev->bus->busnum,
xusb->udev->devnum); xusb->udev->devnum);
len += seq_printf(sfile, "USB: manufacturer=%s\n", xusb->manufacturer);
sprintf(page + len, "USB: manufacturer=%s\n", xusb->manufacturer); seq_printf(sfile, "USB: product=%s\n", xusb->product);
len += sprintf(page + len, "USB: product=%s\n", xusb->product); seq_printf(sfile, "USB: serial=%s\n", xusb->serial);
len += sprintf(page + len, "USB: serial=%s\n", xusb->serial); seq_printf(sfile, "Minor: %d\nModel Info: %s\n", xusb->minor,
len +=
sprintf(page + len, "Minor: %d\nModel Info: %s\n", xusb->minor,
xusb->model_info->desc); xusb->model_info->desc);
len += seq_printf(sfile,
sprintf(page + len,
"Endpoints:\n" "\tIn: 0x%02X - Size: %d)\n" "Endpoints:\n" "\tIn: 0x%02X - Size: %d)\n"
"\tOut: 0x%02X - Size: %d)\n", "\tOut: 0x%02X - Size: %d)\n",
xusb->endpoints[XUSB_RECV].ep_addr, xusb->endpoints[XUSB_RECV].ep_addr,
xusb->endpoints[XUSB_RECV].max_size, xusb->endpoints[XUSB_RECV].max_size,
xusb->endpoints[XUSB_SEND].ep_addr, xusb->endpoints[XUSB_SEND].ep_addr,
xusb->endpoints[XUSB_SEND].max_size); xusb->endpoints[XUSB_SEND].max_size);
len += seq_printf(sfile, "\npending_writes=%d\n",
sprintf(page + len, "\npending_writes=%d\n",
atomic_read(&xusb->pending_writes)); atomic_read(&xusb->pending_writes));
len += seq_printf(sfile, "pending_reads=%d\n",
sprintf(page + len, "pending_reads=%d\n",
atomic_read(&xusb->pending_reads)); atomic_read(&xusb->pending_reads));
len += sprintf(page + len, "max_tx_delay=%d\n", xusb->max_tx_delay); seq_printf(sfile, "max_tx_delay=%d\n", xusb->max_tx_delay);
xusb->max_tx_delay = 0; xusb->max_tx_delay = 0;
#ifdef DEBUG_PCM_TIMING #ifdef DEBUG_PCM_TIMING
len += seq_printf(sfile,
sprintf(page + len,
"\nstamp_last_pcm_read=%lld accumulate_diff=%lld\n", "\nstamp_last_pcm_read=%lld accumulate_diff=%lld\n",
stamp_last_pcm_read, accumulate_diff); stamp_last_pcm_read, accumulate_diff);
#endif #endif
memcpy(usb_tx_delay, xusb->usb_tx_delay, sizeof(usb_tx_delay)); memcpy(usb_tx_delay, xusb->usb_tx_delay, sizeof(usb_tx_delay));
len += seq_printf(sfile, "usb_tx_delay[%d,%d,%d]: ", USEC_BUCKET,
sprintf(page + len, "usb_tx_delay[%d,%d,%d]: ", USEC_BUCKET,
BUCKET_START, NUM_BUCKETS); BUCKET_START, NUM_BUCKETS);
for (i = BUCKET_START; i < NUM_BUCKETS; i++) { for (i = BUCKET_START; i < NUM_BUCKETS; i++) {
len += sprintf(page + len, "%6d ", usb_tx_delay[i]); seq_printf(sfile, "%6d ", usb_tx_delay[i]);
if (i == mark_limit) if (i == mark_limit)
len += sprintf(page + len, "| "); seq_printf(sfile, "| ");
} }
len += seq_printf(sfile, "\nPCM_TX_DROPS: %5d (sluggish: %d)\n",
sprintf(page + len, "\nPCM_TX_DROPS: %5d (sluggish: %d)\n",
atomic_read(&xusb->pcm_tx_drops), atomic_read(&xusb->pcm_tx_drops),
atomic_read(&xusb->usb_sluggish_count) atomic_read(&xusb->usb_sluggish_count)
); );
len += sprintf(page + len, "\nCOUNTERS:\n"); seq_printf(sfile, "\nCOUNTERS:\n");
for (i = 0; i < XUSB_COUNTER_MAX; i++) { for (i = 0; i < XUSB_COUNTER_MAX; i++) {
len += seq_printf(sfile, "\t%-15s = %d\n", xusb_counters[i].name,
sprintf(page + len, "\t%-15s = %d\n", xusb_counters[i].name,
xusb->counters[i]); xusb->counters[i]);
} }
#if 0 #if 0
len += sprintf(page + len, "<-- len=%d\n", len); seq_printf(sfile, "<-- len=%d\n", len);
#endif #endif
spin_unlock_irqrestore(&xusb_lock, flags); spin_unlock_irqrestore(&xusb_lock, flags);
out: return 0;
if (len <= off + count)
*eof = 1;
*start = page + off;
len -= off;
if (len > count)
len = count;
if (len < 0)
len = 0;
return len;
} }
static int xusb_read_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, xusb_read_proc_show, PDE_DATA(inode));
}
static const struct file_operations xusb_read_proc_ops = {
.owner = THIS_MODULE,
.open = xusb_read_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#endif #endif
MODULE_DESCRIPTION("XPP USB Transport Driver"); MODULE_DESCRIPTION("XPP USB Transport Driver");