Mailing List archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[linux-dvb] PROC_FS patch and other goodies
Hi,
I have made a patch to add procfs support to the DVB HEAD drivers, which gives
you something like:
/proc/dvb/
/proc/dvb/adapter1
/proc/dvb/adapter1/frontend0
/proc/dvb/adapter1/frontend0/inversion
/proc/dvb/adapter1/frontend0/symbol_rate
/proc/dvb/adapter1/frontend0/modulation
/proc/dvb/adapter1/frontend0/pwm
/proc/dvb/adapter1/frontend0/ves1820
/proc/dvb/adapter1/frontend0/ber
/proc/dvb/adapter1/frontend0/uncorrected_blocks
/proc/dvb/adapter1/frontend0/signal_strength
/proc/dvb/adapter1/frontend0/SNR
/proc/dvb/adapter1/frontend0/status
/proc/dvb/adapter1/frontend0/caps
/proc/dvb/adapter1/frontend0/type
/proc/dvb/adapter1/frontend0/identify
/proc/dvb/adapter1/frontend0/frequency
/proc/dvb/adapter1/identify
/proc/dvb/adapter0
/proc/dvb/adapter0/frontend0
/proc/dvb/adapter0/frontend0/inversion
/proc/dvb/adapter0/frontend0/symbol_rate
/proc/dvb/adapter0/frontend0/modulation
/proc/dvb/adapter0/frontend0/pwm
/proc/dvb/adapter0/frontend0/ves1820
/proc/dvb/adapter0/frontend0/ber
/proc/dvb/adapter0/frontend0/uncorrected_blocks
/proc/dvb/adapter0/frontend0/signal_strength
/proc/dvb/adapter0/frontend0/SNR
/proc/dvb/adapter0/frontend0/status
/proc/dvb/adapter0/frontend0/caps
/proc/dvb/adapter0/frontend0/type
/proc/dvb/adapter0/frontend0/identify
/proc/dvb/adapter0/frontend0/frequency
/proc/dvb/adapter0/identify
Most items will look familiar, all of them output the current value, and the
relevant ones allow you to echo in a new value.
So you can tune a card by:
echo "162000000" > /proc/dvb/adapter0/frontend0/frequency
echo "QAM_64" > /proc/dvb/adapter0/frontend0/modulation
echo "6900000" > /proc/dvb/adapter0/frontend0/symbol_rate
(NOTE: only DVB-C supported right now! But the DVB-C related proc entries are
only created if you have a DVB-C card, so if you try this with DVB-S or -T
you'll just get fewer proc entries).
and do:
cat /proc/dvb/adapter0/frontend0/status
FE_HAS_SIGNAL
FE_HAS_CARRIER
FE_HAS_VITERBI
FE_HAS_SYNC
FE_HAS_LOCK
Now, while a lot of fun can be had with this, my initial reason to write this
was to allow easy changing of the ves1820 register values, and the cards PWM
value, without recompiling the driver. This in order to find more optimal
values, and to be able to do it with a bash script :-)
Hence:
vdr driver # cat /proc/dvb/adapter0/frontend0/ves1820
VES1820 Register settings
(QAM type, Register 1, Register 5, Register 8, Register 9)
QAM_16 140 164 162 145
QAM_32 140 120 116 150
QAM_64 106 70 67 106
QAM_128 106 54 52 126
QAM_256 92 38 35 107
And you can change these by for example:
echo "QAM_16 111 222 333 444" > ./ves1820
Also the /proc/dvb/adapterX/frontend0/pwm value can be changed like this.
After a lot of playing with the register values, I got slight improvements in
BER value, but not much, and still a lot of block errors. For QAM_64, BER is
like 10,000, but for QAM_128, it is usually 600,000.
The PWM value however, I changed from 52 (other card default is 21?), to 40,
("echo 40 > /proc/dvb/adapter0/frontend0/pwm") and now have a QAM_128 BER of
10,000, and no block errors! Massive improvement, since before I used to
always have problems watching QAM_128 channels. The 40 value was a random
number I pulled out of an unnamed place :)
Anyways, this patch is probably nowhere near clean enough to add to the
drivers, but I think a lot of good things can be done with proc filesystem
support, and will happily take pointers from more knowledgable people on this
list in order to improve and add on this.
For example to add support of per-card register and PWM values I had to
shuffle a few things around. Some proc related functions should also be in
their own file.
So this is basically for the people who are interested in playing with the
ves1820 register and PWM values to find the optimal values. You can now do so
without recompiling, and the first one to write a nice Perl script (BASH is
OK too :-) to scan for the best values gets a free beer!
Cheers,
Dennis
PS - There are a few additional printk's etc I have added over time to play
with, which are not really part of anything, and which I'll take out for the
"proper" patch.
PS2 - If you have PROC_FS enabled in your kernel, this patch will build with
PROC_FS automatically. If you disable this in dvb_procfs.h, you should get
the normal, clean HEAD driver.
diff -c -b -u -N -r --exclude=CVS driver/dvb_frontend.c
driver_new/dvb_frontend.c
--- driver/dvb_frontend.c Mon Oct 21 12:43:04 2002
+++ driver_new/dvb_frontend.c Thu Oct 31 00:23:15 2002
@@ -33,7 +33,7 @@
#include "compat.h"
#include "dvb_frontend.h"
#include "dvbdev.h"
-
+#include "dvb_procfs.h"
static int dvb_frontend_debug = 0;
static int dvb_shutdown_timeout = 0;
@@ -78,6 +78,23 @@
int lost_sync_count;
int exit;
fe_status_t status;
+#ifdef USE_PROCFS
+ struct proc_dir_entry * proc_entry;
+ struct proc_dir_entry * proc_entry_frequency;
+ struct proc_dir_entry * proc_entry_identify;
+ struct proc_dir_entry * proc_entry_type;
+ struct proc_dir_entry * proc_entry_caps;
+ struct proc_dir_entry * proc_entry_status;
+ struct proc_dir_entry * proc_entry_inversion;
+ struct proc_dir_entry * proc_entry_modulation;
+ struct proc_dir_entry * proc_entry_symbol_rate;
+ struct proc_dir_entry * proc_entry_snr;
+ struct proc_dir_entry * proc_entry_signal_strength;
+ struct proc_dir_entry * proc_entry_ber;
+ struct proc_dir_entry * proc_entry_uncorrected_blocks;
+ struct proc_dir_entry * proc_entry_ves1820;
+ struct proc_dir_entry * proc_entry_pwm;
+#endif
};
@@ -91,12 +108,532 @@
void *before_after_data;
};
-
static LIST_HEAD(frontend_list);
static LIST_HEAD(frontend_ioctl_list);
static DECLARE_MUTEX(frontend_mutex);
+#ifdef USE_PROCFS
+
+#define SET_PWM(frontend,pwm) do { \
+ (int) frontend->data &= ~0xff; \
+ (int) frontend->data |= pwm; \
+} while (0)
+
+#define GET_PWM(frontend) ((u8) ((int) frontend->data & 0xff))
+
+
+#define PROC_READ_END \
+ len = out - page; \
+ len -= off; \
+ if (len < count) { \
+ *eof = 1; \
+ if (len <= 0) \
+ return 0; \
+ } else \
+ len = count; \
+ *start = page + off; \
+ return len; \
+
+
+static
+int dvb_frontend_internal_ioctl (struct dvb_frontend *frontend,
+ unsigned int cmd, void *arg);
+static
+
+int dvb_frontend_set_parameters (struct dvb_frontend_data *fe,
+ struct dvb_frontend_parameters *param,
+ int first_trial);
+
+static
+int dvb_frontend_read_proc_ves1820(char * page, char ** start, off_t off,
+ int count, int *eof, void *data)
+{
+ char * out = page;
+ struct dvb_frontend_data * fe = data;
+ struct dvb_frontend * frontend = &fe->frontend;
+ int len;
+
+ out += sprintf(out, "VES1820 Register settings\n");
+ out += sprintf(out, "(QAM type, Register 1, Register 5, Register 8, Register
9)\n");
+ out += sprintf(out, " QAM_16 %3d %3d %3d %3d\n",
+ frontend->QAM_Values[0].Reg1, frontend->QAM_Values[0].Reg5,
+ frontend->QAM_Values[0].Reg8, frontend->QAM_Values[0].Reg9);
+ out += sprintf(out, " QAM_32 %3d %3d %3d %3d\n",
+ frontend->QAM_Values[1].Reg1, frontend->QAM_Values[1].Reg5,
+ frontend->QAM_Values[1].Reg8, frontend->QAM_Values[1].Reg9);
+ out += sprintf(out, " QAM_64 %3d %3d %3d %3d\n",
+ frontend->QAM_Values[2].Reg1, frontend->QAM_Values[2].Reg5,
+ frontend->QAM_Values[2].Reg8, frontend->QAM_Values[2].Reg9);
+ out += sprintf(out, " QAM_128 %3d %3d %3d %3d\n",
+ frontend->QAM_Values[3].Reg1, frontend->QAM_Values[3].Reg5,
+ frontend->QAM_Values[3].Reg8, frontend->QAM_Values[3].Reg9);
+ out += sprintf(out, " QAM_256 %3d %3d %3d %3d\n\n",
+ frontend->QAM_Values[4].Reg1, frontend->QAM_Values[4].Reg5,
+ frontend->QAM_Values[4].Reg8, frontend->QAM_Values[4].Reg9);
+ out += sprintf(out, "(echo \"QAM_16 111 222 333 444 > ./ves1820\")\n");
+
+
+ PROC_READ_END;
+}
+
+static
+int dvb_frontend_write_proc_ves1820(struct file * file, const char * buffer,
+ unsigned long count, void *data)
+{
+ char buf[80];
+ struct dvb_frontend_data * fe = data;
+ struct dvb_frontend_parameters fp;
+ int res;
+ char qam[80];
+ int reg1;
+ int reg5;
+ int reg8;
+ int reg9;
+ int real_qam;
+
+ if (count == 0)
+ return -EINVAL;
+ if (count > 79)
+ return -EINVAL;
+
+ if (copy_from_user(buf, buffer, count-1)) return -EFAULT;
+ buf[count-1] = '\0';
+
+ res = sscanf(buf, "%s %d %d %d %d", &qam, ®1, ®5, ®8, ®9);
+ if (res != 5) {
+ printk("%s: Format error (got %d, expected 5)\n", __FUNCTION__, res);
+ return -EINVAL;
+ }
+
+ if (strcmp(qam, "QAM_16") == 0)
+ real_qam = 0;
+ else if (strcmp(qam, "QAM_32") == 0)
+ real_qam = 1;
+ else if (strcmp(qam, "QAM_64") == 0)
+ real_qam = 2;
+ else if (strcmp(qam, "QAM_128") == 0)
+ real_qam = 3;
+ else if (strcmp(qam, "QAM_256") == 0)
+ real_qam = 4;
+ else {
+ printk("Invalid QAM type (given: %s)\n", qam);
+ return -EINVAL;
+ }
+
+ printk("Setting '%s' %d %d %d %d\n", qam, reg1, reg5, reg8, reg9);
+ fe->frontend.QAM_Values[ real_qam ].Reg1 = reg1;
+ fe->frontend.QAM_Values[ real_qam ].Reg5 = reg5;
+ fe->frontend.QAM_Values[ real_qam ].Reg8 = reg8;
+ fe->frontend.QAM_Values[ real_qam ].Reg9 = reg9;
+
+ memcpy( &fp, &fe->parameters, sizeof(struct dvb_frontend_parameters));
+ dvb_frontend_set_parameters( fe, &fp, 1 );
+ file->f_pos += count;
+ return count;
+}
+
+static
+int dvb_frontend_read_proc_ber(char * page, char ** start, off_t off,
+ int count, int *eof, void *data)
+{
+ char * out = page;
+ struct dvb_frontend_data * fe = data;
+ int len;
+ u32 ber;
+
+ dvb_frontend_internal_ioctl( &fe->frontend, FE_READ_BER, &ber);
+ out += sprintf(out, "%d", ber);
+
+ PROC_READ_END;
+}
+
+static
+int dvb_frontend_read_proc_uncorrected_blocks(char * page, char ** start,
off_t
off,
+ int count, int *eof, void *data)
+{
+ char * out = page;
+ struct dvb_frontend_data * fe = data;
+ int len;
+ u32 ub;
+
+ dvb_frontend_internal_ioctl( &fe->frontend, FE_READ_UNCORRECTED_BLOCKS,
&ub);
+ out += sprintf(out, "%d", ub);
+
+ PROC_READ_END;
+}
+
+static
+int dvb_frontend_read_proc_signal_strength(char * page, char ** start, off_t
off,
+ int count, int *eof, void *data)
+{
+ char * out = page;
+ struct dvb_frontend_data * fe = data;
+ int len;
+ u16 ss;
+
+ dvb_frontend_internal_ioctl( &fe->frontend, FE_READ_SIGNAL_STRENGTH, &ss);
+ out += sprintf(out, "%d", ss);
+
+ PROC_READ_END;
+}
+
+static
+int dvb_frontend_read_proc_snr(char * page, char ** start, off_t off,
+ int count, int *eof, void *data)
+{
+ char * out = page;
+ struct dvb_frontend_data * fe = data;
+ int len;
+ u16 quality;
+
+ dvb_frontend_internal_ioctl( &fe->frontend, FE_READ_SNR, &quality);
+ out += sprintf(out, "%d", quality);
+
+ PROC_READ_END;
+}
+
+static
+int dvb_frontend_read_proc_symbol_rate(char * page, char ** start, off_t off,
+ int count, int *eof, void *data)
+{
+ char * out = page;
+ struct dvb_frontend_data * fe = data;
+ int len;
+
+ out += sprintf(out, "%d", fe->parameters.u.qam.symbol_rate);
+
+ PROC_READ_END;
+}
+
+static
+int dvb_frontend_write_proc_symbol_rate(struct file * file, const char *
buffer,
+ unsigned long count, void *data)
+{
+ char buf[15];
+ long new_sr;
+ struct dvb_frontend_data * fe = data;
+ struct dvb_frontend_parameters fp;
+
+ if (count == 0)
+ return -EINVAL;
+ if (count > 14)
+ return -EINVAL;
+
+ snprintf(buf, 14, buffer);
+
+ new_sr = simple_strtoul( buf, NULL, 10 );
+ if (new_sr < 1000000)
+ return EINVAL;
+
+ printk("%s New symbol rate %d\n", __FUNCTION__, new_sr);
+
+ memcpy( &fp, &fe->parameters, sizeof(struct dvb_frontend_parameters));
+
+ fp.u.qam.symbol_rate = new_sr;
+ dvb_frontend_set_parameters( fe, &fp, 1 );
+
+ file->f_pos += count;
+ return count;
+}
+
+static
+int dvb_frontend_read_proc_modulation(char * page, char ** start, off_t off,
+ int count, int *eof, void *data)
+{
+ char * out = page;
+ struct dvb_frontend_data * fe = data;
+ int len;
+
+ if (fe->parameters.u.qam.modulation == QPSK)
+ out += sprintf(out, "QPSK");
+ else if (fe->parameters.u.qam.modulation == QAM_16)
+ out += sprintf(out, "QAM_16");
+ else if (fe->parameters.u.qam.modulation == QAM_32)
+ out += sprintf(out, "QAM_32");
+ else if (fe->parameters.u.qam.modulation == QAM_64)
+ out += sprintf(out, "QAM_64");
+ else if (fe->parameters.u.qam.modulation == QAM_128)
+ out += sprintf(out, "QAM_128");
+ else if (fe->parameters.u.qam.modulation == QAM_256)
+ out += sprintf(out, "QAM_256");
+ else if (fe->parameters.u.qam.modulation == QAM_AUTO)
+ out += sprintf(out, "QAM_AUTO");
+
+ PROC_READ_END;
+}
+
+static
+int dvb_frontend_write_proc_modulation(struct file * file, const char *
buffer,
+ unsigned long count, void *data)
+{
+ char buf[15];
+ fe_modulation_t nm;
+ struct dvb_frontend_data * fe = data;
+ struct dvb_frontend_parameters fp;
+
+ if (count == 0)
+ return -EINVAL;
+ if (count > 14)
+ return -EINVAL;
+ if (copy_from_user(buf, buffer, count-1)) return -EFAULT;
+ buf[count-1] = '\0';
+
+ //printk("Buffer: --%s--\n", buffer);
+ //printk("Buf : --%s--\n", buf);
+ //printk("Match : (%s:QAM_128) --%d--\n", buf, strcmp(buf, "QAM_128"));
+
+ if (strncmp(buf, "QPSK", count) == 0)
+ nm = QPSK;
+ else if (strncmp(buf, "QAM_16", count) == 0)
+ nm = QAM_16;
+ else if (strncmp(buf, "QAM_32", count) == 0)
+ nm = QAM_32;
+ else if (strncmp(buf, "QAM_64", count) == 0)
+ nm = QAM_64;
+ else if (strncmp(buf, "QAM_128", count) == 0)
+ nm = QAM_128;
+ else if (strncmp(buf, "QAM_256", count) == 0)
+ nm = QAM_256;
+ else if (strncmp(buf, "QAM_AUTO", count) == 0)
+ nm = QAM_AUTO;
+ else
+ return -EINVAL;
+
+ printk("%s New modulation: %s\n", __FUNCTION__, buf);
+
+ memcpy(&fp, &fe->parameters, sizeof(struct dvb_frontend_parameters));
+
+ fp.u.qam.modulation = nm;
+ dvb_frontend_set_parameters( fe, &fp, 1 );
+
+ file->f_pos += count;
+ return count;
+}
+
+static
+int dvb_frontend_read_proc_inversion(char * page, char ** start, off_t off,
+ int count, int *eof, void *data)
+{
+ char * out = page;
+ struct dvb_frontend_data * fe = data;
+ int len;
+
+ if (fe->parameters.inversion == INVERSION_OFF)
+ out += sprintf(out, "INVERSION_OFF");
+ else if (fe->parameters.inversion == INVERSION_ON)
+ out += sprintf(out, "INVERSION_ON");
+ else if (fe->parameters.inversion == INVERSION_AUTO)
+ out += sprintf(out, "INVERSION_AUTO");
+
+ PROC_READ_END;
+}
+
+static
+int dvb_frontend_read_proc_status(char * page, char ** start, off_t off,
+ int count, int *eof, void *data)
+{
+ char * out = page;
+ struct dvb_frontend_data * fe = data;
+ int len;
+
+ if (fe->status & FE_HAS_SIGNAL)
+ out += sprintf(out, "FE_HAS_SIGNAL\n");
+ if (fe->status & FE_HAS_CARRIER)
+ out += sprintf(out, "FE_HAS_CARRIER\n");
+ if (fe->status & FE_HAS_VITERBI)
+ out += sprintf(out, "FE_HAS_VITERBI\n");
+ if (fe->status & FE_HAS_SYNC)
+ out += sprintf(out, "FE_HAS_SYNC\n");
+ if (fe->status & FE_HAS_LOCK)
+ out += sprintf(out, "FE_HAS_LOCK\n");
+ if (fe->status & FE_TIMEDOUT)
+ out += sprintf(out, "FE_TIMEDOUT\n");
+ if (fe->status & FE_REINIT)
+ out += sprintf(out, "FE_REINIT\n");
+
+ PROC_READ_END;
+}
+
+static
+int dvb_frontend_read_proc_caps(char * page, char ** start, off_t off,
+ int count, int *eof, void *data)
+{
+ char * out = page;
+ struct dvb_frontend_data * fe = data;
+ int len;
+
+ if (fe->info->caps == 0)
+ out += sprintf(out, "FE_IS_STUPID\n");
+ if (fe->info->caps & FE_CAN_INVERSION_AUTO)
+ out += sprintf(out, "FE_CAN_INVERSION_AUTO\n");
+ if (fe->info->caps & FE_CAN_FEC_1_2)
+ out += sprintf(out, "FE_CAN_FEC_1_2\n");
+ if (fe->info->caps & FE_CAN_FEC_2_3)
+ out += sprintf(out, "FE_CAN_FEC_2_3\n");
+ if (fe->info->caps & FE_CAN_FEC_3_4)
+ out += sprintf(out, "FE_CAN_FEC_3_4\n");
+ if (fe->info->caps & FE_CAN_FEC_4_5)
+ out += sprintf(out, "FE_CAN_FEC_4_5\n");
+ if (fe->info->caps & FE_CAN_FEC_5_6)
+ out += sprintf(out, "FE_CAN_FEC_5_6\n");
+ if (fe->info->caps & FE_CAN_FEC_6_7)
+ out += sprintf(out, "FE_CAN_FEC_6_7\n");
+ if (fe->info->caps & FE_CAN_FEC_7_8)
+ out += sprintf(out, "FE_CAN_FEC_7_8\n");
+ if (fe->info->caps & FE_CAN_FEC_8_9)
+ out += sprintf(out, "FE_CAN_FEC_8_9\n");
+ if (fe->info->caps & FE_CAN_FEC_AUTO)
+ out += sprintf(out, "FE_CAN_FEC_AUTO\n");
+ if (fe->info->caps & FE_CAN_QPSK)
+ out += sprintf(out, "FE_CAN_QPSK\n");
+ if (fe->info->caps & FE_CAN_QAM_16)
+ out += sprintf(out, "FE_CAN_QAM_16\n");
+ if (fe->info->caps & FE_CAN_QAM_32)
+ out += sprintf(out, "FE_CAN_QAM_32\n");
+ if (fe->info->caps & FE_CAN_QAM_64)
+ out += sprintf(out, "FE_CAN_QAM_64\n");
+ if (fe->info->caps & FE_CAN_QAM_128)
+ out += sprintf(out, "FE_CAN_QAM_128\n");
+ if (fe->info->caps & FE_CAN_QAM_256)
+ out += sprintf(out, "FE_CAN_QAM_256\n");
+ if (fe->info->caps & FE_CAN_TRANSMISSION_MODE_AUTO)
+ out += sprintf(out, "FE_CAN_TRANSMISSION_MODE_AUTO\n");
+ if (fe->info->caps & FE_CAN_BANDWIDTH_AUTO)
+ out += sprintf(out, "FE_CAN_BANDWIDTH_AUTO\n");
+ if (fe->info->caps & FE_CAN_GUARD_INTERVAL_AUTO)
+ out += sprintf(out, "FE_CAN_GUARD_INTERVAL_AUTO\n");
+ if (fe->info->caps & FE_CAN_HIERARCHY_AUTO)
+ out += sprintf(out, "FE_CAN_HIERARCHY_AUTO\n");
+ if (fe->info->caps & FE_CAN_MUTE_TS)
+ out += sprintf(out, "FE_CAN_MUTE_TS\n");
+
+ PROC_READ_END;
+}
+
+static
+int dvb_frontend_read_proc_frequency(char * page, char ** start, off_t off,
+ int count, int *eof, void *data)
+{
+ char * out = page;
+ struct dvb_frontend_data * fe = data;
+ int len;
+
+ out += sprintf(out, "%d", fe->parameters.frequency);
+
+ PROC_READ_END;
+}
+
+static
+int dvb_frontend_write_proc_frequency(struct file * file, const char *
buffer,
+ unsigned long count, void *data)
+{
+ char buf[15];
+ long new_freq;
+ struct dvb_frontend_data * fe = data;
+ struct dvb_frontend_parameters fp;
+
+ if (count == 0)
+ return -EINVAL;
+ if (count > 14)
+ return -EINVAL;
+
+ snprintf(buf, 14, buffer);
+
+ new_freq = simple_strtoul( buf, NULL, 10 );
+ if (new_freq < 1000000)
+ return -EINVAL;
+
+ printk("%s New frequency: %d Hz\n", __FUNCTION__, new_freq);
+
+ memcpy(&fp, &fe->parameters, sizeof(struct dvb_frontend_parameters));
+
+ fp.frequency = new_freq;
+ dvb_frontend_set_parameters( fe, &fp, 1 );
+
+
+ file->f_pos += count;
+ return count;
+}
+
+static
+int dvb_frontend_read_proc_pwm(char * page, char ** start, off_t off,
+ int count, int *eof, void *data)
+{
+ char * out = page;
+ struct dvb_frontend_data * fe = data;
+ struct dvb_frontend * frontend = &fe->frontend;
+ int len;
+
+ out += sprintf(out, "%d", GET_PWM(frontend));
+
+ PROC_READ_END;
+}
+
+static
+int dvb_frontend_write_proc_pwm(struct file * file, const char * buffer,
+ unsigned long count, void *data)
+{
+ char buf[15];
+ long new_pwm;
+ struct dvb_frontend_data * fe = data;
+ struct dvb_frontend * frontend = &fe->frontend;
+ struct dvb_frontend_parameters fp;
+
+ if (count == 0)
+ return -EINVAL;
+ if (count > 14)
+ return -EINVAL;
+
+ snprintf(buf, 14, buffer);
+
+ new_pwm = simple_strtoul(buf, NULL, 10);
+ if (new_pwm > 50000)
+ return -EINVAL;
+ printk("%s New PWM: %d\n", __FUNCTION__, new_pwm);
+
+ memcpy(&fp, &fe->parameters, sizeof(struct dvb_frontend_parameters));
+ SET_PWM(frontend, new_pwm);
+ dvb_frontend_set_parameters( fe, &fp, 1);
+
+ file->f_pos += count;
+ return count;
+}
+
+static
+int dvb_frontend_read_proc_identify(char * page, char ** start, off_t off,
+ int count, int *eof, void *data)
+{
+ char * out = page;
+ struct dvb_frontend_data * fe = data;
+ int len;
+
+ out += sprintf(out, "%s", fe->info->name);
+
+ PROC_READ_END;
+}
+
+static
+int dvb_frontend_read_proc_type(char * page, char ** start, off_t off,
+ int count, int *eof, void *data)
+{
+ char * out = page;
+ struct dvb_frontend_data * fe = data;
+ int len;
+
+ if (fe->info->type == FE_QPSK)
+ out += sprintf(out, "FE_QPSK");
+ else if (fe->info->type == FE_QAM)
+ out += sprintf(out, "FE_QAM");
+ else if (fe->info->type == FE_OFDM)
+ out += sprintf(out, "FE_OFDM");
+ else
+ out += sprintf(out, "Unknown (bug!)");
+
+ PROC_READ_END;
+}
+#endif
+
static
inline void ddelay (int ms)
@@ -371,6 +908,8 @@
frontend->i2c->adapter->num, frontend->i2c->id,
fe->info->name);
+
+
dvb_frontend_internal_ioctl (frontend, FE_INIT, NULL);
if (fe->info->type == FE_QPSK) {
@@ -842,6 +1381,18 @@
+#ifdef USE_PROCFS
+QAM_SETTING Default_QAM_Values[] = {
+ { QAM_16, 16, 140, 164, 162, 145 },
+ { QAM_32, 32, 140, 120, 116, 150 },
+ { QAM_64, 64, 106, 70, 67, 106 },
+ { QAM_128, 128, 106, 54, 52, 126 },
+ { QAM_256, 256, 92, 38, 35, 107 }
+};
+
+#endif
+
+
int
dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend,
unsigned int cmd, void *arg),
@@ -899,7 +1450,126 @@
dvb_register_device (i2c->adapter, &fe->dvbdev, &dvbdev_template,
fe, DVB_DEVICE_FRONTEND);
+#ifdef USE_PROCFS
+ {
+ struct proc_dir_entry * p = NULL;
+ p = create_proc_entry("frontend0", S_IFDIR,
fe->dvbdev->adapter->proc_entry);
+ if (!p)
+ goto proc_reg_fail;
+ p->data = fe;
+ fe->proc_entry = p;
+
+ p = create_proc_entry("frequency", S_IFREG|S_IRUGO|S_IWUSR,
fe->proc_entry);
+ if (!p)
+ goto proc_reg_fail;
+ p->data = fe;
+ p->read_proc = dvb_frontend_read_proc_frequency;
+ p->write_proc = dvb_frontend_write_proc_frequency;
+ fe->proc_entry_frequency = p;
+
+ p = create_proc_entry("identify", S_IFREG|S_IRUGO|S_IWUSR, fe->proc_entry);
+ if (!p)
+ goto proc_reg_fail;
+ p->data = fe;
+ p->read_proc = dvb_frontend_read_proc_identify;
+ fe->proc_entry_identify = p;
+
+ p = create_proc_entry("type", S_IFREG|S_IRUGO|S_IWUSR, fe->proc_entry);
+ if (!p)
+ goto proc_reg_fail;
+ p->data = fe;
+ p->read_proc = dvb_frontend_read_proc_type;
+ fe->proc_entry_type = p;
+
+ p = create_proc_entry("caps", S_IFREG|S_IRUGO|S_IWUSR, fe->proc_entry);
+ if (!p)
+ goto proc_reg_fail;
+ p->data = fe;
+ p->read_proc = dvb_frontend_read_proc_caps;
+ fe->proc_entry_caps = p;
+
+ p = create_proc_entry("status", S_IFREG|S_IRUGO|S_IWUSR, fe->proc_entry);
+ if (!p)
+ goto proc_reg_fail;
+ p->data = fe;
+ p->read_proc = dvb_frontend_read_proc_status;
+ fe->proc_entry_status = p;
+
+ p = create_proc_entry("SNR", S_IFREG|S_IRUGO|S_IWUSR, fe->proc_entry);
+ if (!p)
+ goto proc_reg_fail;
+ p->data = fe;
+ p->read_proc = dvb_frontend_read_proc_snr;
+ fe->proc_entry_snr = p;
+
+ p = create_proc_entry("signal_strength", S_IFREG|S_IRUGO|S_IWUSR,
fe->proc_entry);
+ if (!p)
+ goto proc_reg_fail;
+ p->data = fe;
+ p->read_proc = dvb_frontend_read_proc_signal_strength;
+ fe->proc_entry_signal_strength = p;
+
+ p = create_proc_entry("uncorrected_blocks", S_IFREG|S_IRUGO|S_IWUSR,
fe->proc_entry);
+ if (!p)
+ goto proc_reg_fail;
+ p->data = fe;
+ p->read_proc = dvb_frontend_read_proc_uncorrected_blocks;
+ fe->proc_entry_uncorrected_blocks = p;
+
+ p = create_proc_entry("ber", S_IFREG|S_IRUGO|S_IWUSR, fe->proc_entry);
+ if (!p)
+ goto proc_reg_fail;
+ p->data = fe;
+ p->read_proc = dvb_frontend_read_proc_ber;
+ fe->proc_entry_uncorrected_blocks = p;
+
+ p = create_proc_entry("ves1820", S_IFREG|S_IRUGO|S_IWUSR, fe->proc_entry);
+ if (!p)
+ goto proc_reg_fail;
+ p->data = fe;
+ p->read_proc = dvb_frontend_read_proc_ves1820;
+ p->write_proc = dvb_frontend_write_proc_ves1820;
+ fe->proc_entry_ves1820 = p;
+
+ p = create_proc_entry("pwm", S_IFREG|S_IRUGO|S_IWUSR, fe->proc_entry);
+ if (!p)
+ goto proc_reg_fail;
+ p->data = fe;
+ p->read_proc = dvb_frontend_read_proc_pwm;
+ p->write_proc = dvb_frontend_write_proc_pwm;
+ fe->proc_entry_pwm = p;
+
+ if (fe->info->type == FE_QAM) {
+ p = create_proc_entry("modulation", S_IFREG|S_IRUGO|S_IWUSR,
fe->proc_entry);
+ if (!p)
+ goto proc_reg_fail;
+ p->data = fe;
+ p->read_proc = dvb_frontend_read_proc_modulation;
+ p->write_proc = dvb_frontend_write_proc_modulation;
+ fe->proc_entry_modulation = p;
+
+ p = create_proc_entry("symbol_rate", S_IFREG|S_IRUGO|S_IWUSR,
fe->proc_entry);
+ if (!p)
+ goto proc_reg_fail;
+ p->data = fe;
+ p->read_proc = dvb_frontend_read_proc_symbol_rate;
+ p->write_proc = dvb_frontend_write_proc_symbol_rate;
+ fe->proc_entry_symbol_rate = p;
+
+ p = create_proc_entry("inversion", S_IFREG|S_IRUGO|S_IWUSR,
fe->proc_entry);
+ if (!p)
+ goto proc_reg_fail;
+ p->data = fe;
+ p->read_proc = dvb_frontend_read_proc_inversion;
+ fe->proc_entry_inversion = p;
+ }
+ }
+proc_reg_fail:
+
+ memcpy(&fe->frontend.QAM_Values, &Default_QAM_Values, sizeof(QAM_SETTING) *
5);
+
+#endif
up (&frontend_mutex);
return 0;
@@ -923,6 +1593,38 @@
fe = list_entry (entry, struct dvb_frontend_data, list_head);
if (fe->frontend.ioctl == ioctl && fe->frontend.i2c == i2c) {
+#ifdef USE_PROCFS
+ if (fe->proc_entry_ves1820)
+ remove_proc_entry("ves1820", fe->proc_entry);
+ if (fe->proc_entry_uncorrected_blocks)
+ remove_proc_entry("uncorrected_blocks", fe->proc_entry);
+ if (fe->proc_entry_pwm)
+ remove_proc_entry("pwm", fe->proc_entry);
+ if (fe->proc_entry_ber)
+ remove_proc_entry("ber", fe->proc_entry);
+ if (fe->proc_entry_status)
+ remove_proc_entry("status", fe->proc_entry);
+ if (fe->proc_entry_modulation)
+ remove_proc_entry("modulation", fe->proc_entry);
+ if (fe->proc_entry_caps)
+ remove_proc_entry("caps", fe->proc_entry);
+ if (fe->proc_entry_inversion)
+ remove_proc_entry("inversion", fe->proc_entry);
+ if (fe->proc_entry_symbol_rate)
+ remove_proc_entry("symbol_rate", fe->proc_entry);
+ if (fe->proc_entry_identify)
+ remove_proc_entry("identify", fe->proc_entry);
+ if (fe->proc_entry_frequency)
+ remove_proc_entry("frequency", fe->proc_entry);
+ if (fe->proc_entry_type)
+ remove_proc_entry("type", fe->proc_entry);
+ if (fe->proc_entry_snr)
+ remove_proc_entry("SNR", fe->proc_entry);
+ if (fe->proc_entry_signal_strength)
+ remove_proc_entry("signal_strength", fe->proc_entry);
+ if (fe->proc_entry)
+ remove_proc_entry("frontend0", fe->dvbdev->adapter->proc_entry);
+#endif
dvb_unregister_device (fe->dvbdev);
list_del (entry);
diff -c -b -u -N -r --exclude=CVS driver/dvb_frontend.h
driver_new/dvb_frontend.h
--- driver/dvb_frontend.h Thu Oct 10 22:22:28 2002
+++ driver_new/dvb_frontend.h Wed Oct 30 22:18:49 2002
@@ -48,6 +48,18 @@
* are not executed.
*/
+#ifdef USE_PROCFS
+typedef struct {
+ fe_modulation_t QAM_Mode;
+ int NoOfSym;
+ u8 Reg1;
+ u8 Reg5;
+ u8 Reg8;
+ u8 Reg9;
+} QAM_SETTING;
+#endif
+
+
struct dvb_frontend {
int (*before_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void
*arg);
int (*ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg);
@@ -55,7 +67,20 @@
struct dvb_i2c_bus *i2c;
void *before_after_data; /* can be used by hardware module... */
void *data; /* can be used by hardware module... */
+
+ QAM_SETTING QAM_Values[5];
};
+#if 0
+
+
+ QAM_SETTING QAM_Values[5] = {
+ { QAM_16, 16, 140, 164, 162, 145 },
+ { QAM_32, 32, 140, 120, 116, 150 },
+ { QAM_64, 64, 106, 70, 67, 106 },
+ { QAM_128, 128, 106, 54, 52, 126 },
+ { QAM_256, 256, 92, 38, 35, 107 }
+ };
+#endif
/**
diff -c -b -u -N -r --exclude=CVS driver/dvb_ksyms.c driver_new/dvb_ksyms.c
--- driver/dvb_ksyms.c Thu Oct 10 22:22:28 2002
+++ driver_new/dvb_ksyms.c Wed Oct 30 14:28:11 2002
@@ -8,6 +8,11 @@
#include "dvb_demux.h"
#include "dvb_net.h"
+#include "dvb_procfs.h"
+
+#ifdef USE_PROCFS
+EXPORT_SYMBOL(dvb_proc_entry);
+#endif
EXPORT_SYMBOL(DmxDevInit);
EXPORT_SYMBOL(DmxDevRelease);
diff -c -b -u -N -r --exclude=CVS driver/dvb_procfs.h driver_new/dvb_procfs.h
--- driver/dvb_procfs.h Thu Jan 1 02:00:00 1970
+++ driver_new/dvb_procfs.h Wed Oct 30 20:24:24 2002
@@ -0,0 +1,24 @@
+/*
+ * dvbprocfs.h
+ *
+ * Some stuff which is common for source files which have procfs support
+ * Contact Dennis Noordsij (dennis.noordsij@wiral.com)
+ *
+ * $Id$
+ */
+
+#ifndef DVB_PROC_FS_H
+#define DVB_PROC_FS_H
+
+#if defined(CONFIG_PROC_FS)
+#define USE_PROCFS
+#warning "Enabling /proc filesystem support"
+#include <linux/proc_fs.h>
+
+static struct proc_dir_entry * dvb_proc_entry = NULL;
+#endif
+
+#ifndef USE_PROCFS
+#warning "Not enabling /proc filesystem support"
+#endif
+
+#endif
diff -c -b -u -N -r --exclude=CVS driver/dvbdev.c driver_new/dvbdev.c
--- driver/dvbdev.c Thu Oct 17 12:29:39 2002
+++ driver_new/dvbdev.c Wed Oct 30 15:53:31 2002
@@ -41,6 +41,8 @@
#include "compat.h"
#include "dvbdev.h"
+#include "dvb_procfs.h"
+
static int dvbdev_debug = 0;
#define dprintk if (dvbdev_debug) printk
@@ -68,6 +70,35 @@
#define DVB_DEVFS_FLAGS (DEVFS_FL_DEFAULT)
+
+#ifdef USE_PROCFS
+static
+int dvb_proc_read_identify(char * page, char ** start, off_t off,
+ int count, int *eof, void *data)
+{
+ char * out = page;
+ dvb_adapter_t * adap = data;
+ int len;
+
+ out += sprintf(out, "%s", (char *)adap->proc_name);
+ //out += sprintf(out, "Some DVB card :-)");
+
+ len = out - page;
+ len -= off;
+ if (len < count) {
+ *eof = 1;
+ if (len <= 0)
+ return 0;
+ } else
+ len = count;
+
+ *start = page + off;
+
+ return len;
+}
+#endif
+
+
static
dvb_device_t* dvbdev_find_device (int minor)
{
@@ -375,6 +406,34 @@
list_add_tail (&adap->list_head, &dvb_adapter_list);
+#ifdef USE_PROCFS
+ {
+ struct proc_dir_entry * p;
+ struct proc_dir_entry * identify;
+
+ printk("Registering /proc/dvb/%s\n", dirname);
+
+ if (!dvb_proc_entry)
+ goto dvb_proc_reg_fail;
+
+ p = create_proc_entry(dirname, S_IFDIR, dvb_proc_entry);
+ if (!p)
+ goto dvb_proc_reg_fail;
+
+ adap->proc_entry = p;
+
+ printk("Registering /proc/dvb/%s/identify", dirname);
+ identify = create_proc_entry("identify", S_IFREG|S_IRUGO|S_IWUSR,
adap->proc_entry);
+ if (!identify)
+ goto dvb_proc_reg_fail;
+
+ identify->read_proc = dvb_proc_read_identify;
+ identify->data = adap;
+ adap->proc_entry_identify = identify;
+ snprintf(adap->proc_name, 49, "%s", name);
+ }
+dvb_proc_reg_fail:
+#endif
up (&dvbdev_register_lock);
return num;
@@ -387,6 +446,27 @@
if (down_interruptible (&dvbdev_register_lock))
return -ERESTARTSYS;
list_del (&adap->list_head);
+
+#ifdef USE_PROCFS
+ {
+ char dirname[20];
+
+ if (!dvb_proc_entry)
+ goto dvb_proc_unreg_fail;
+
+ if (adap->proc_entry_identify)
+ remove_proc_entry("identify", adap->proc_entry);
+
+ if (adap->proc_entry) {
+ sprintf(dirname, "adapter%d", adap->num);
+ remove_proc_entry(dirname, dvb_proc_entry);
+ }
+
+ printk("Unregistered /proc/dvb/%s\n", dirname);
+dvb_proc_unreg_fail:
+ }
+#endif
+
up (&dvbdev_register_lock);
kfree (adap);
MOD_DEC_USE_COUNT;
@@ -404,6 +484,15 @@
return -EIO;
}
#endif
+#ifdef USE_PROCFS
+ dvb_proc_entry = create_proc_entry("dvb", S_IFDIR, &proc_root);
+ if (dvb_proc_entry == NULL) {
+ printk("dvb: unable to initialize /proc/dvb\n");
+ return 0;
+ }
+ printk("Registered /proc/dvb\n");
+ dvb_proc_entry->owner = THIS_MODULE;
+#endif
return 0;
}
@@ -415,6 +504,12 @@
devfs_unregister_chrdev(DVB_MAJOR, "DVB");
#endif
devfs_unregister(dvb_devfs_handle);
+#ifdef USE_PROCFS
+ if (dvb_proc_entry != NULL) {
+ remove_proc_entry("dvb", &proc_root);
+ printk("Unregistered /proc/dvb\n");
+ }
+#endif
}
module_init(init_dvbdev);
diff -c -b -u -N -r --exclude=CVS driver/dvbdev.h driver_new/dvbdev.h
--- driver/dvbdev.h Thu Oct 10 22:22:28 2002
+++ driver_new/dvbdev.h Wed Oct 30 15:37:10 2002
@@ -30,6 +30,8 @@
#include <linux/devfs_fs_kernel.h>
#include <linux/list.h>
+#include "dvb_procfs.h"
+
#define DVB_MAJOR 250
#define DVB_DEVICE_VIDEO 0
@@ -49,6 +51,11 @@
devfs_handle_t devfs_handle;
struct list_head list_head;
struct list_head device_list;
+#ifdef USE_PROCFS
+ char proc_name[80];
+ struct proc_dir_entry * proc_entry;
+ struct proc_dir_entry * proc_entry_identify;
+#endif
} dvb_adapter_t;
Binary files driver/frontends/.ves1820.c.swp and
driver_new/frontends/.ves1820.c.swp differ
diff -c -b -u -N -r --exclude=CVS driver/frontends/ves1820.c
driver_new/frontends/ves1820.c
--- driver/frontends/ves1820.c Thu Oct 24 12:44:36 2002
+++ driver_new/frontends/ves1820.c Wed Oct 30 22:35:05 2002
@@ -344,7 +344,7 @@
ves1820_writereg (frontend->i2c, 0x34, pwm);
}
-
+#ifndef USE_PROCFS
typedef struct {
fe_modulation_t QAM_Mode;
int NoOfSym;
@@ -359,10 +359,10 @@
{ QAM_16, 16, 140, 164, 162, 145 },
{ QAM_32, 32, 140, 120, 116, 150 },
{ QAM_64, 64, 106, 70, 67, 106 },
- { QAM_128, 128, 120, 54, 52, 126 },
+ { QAM_128, 128, 106, 54, 52, 126 },
{ QAM_256, 256, 92, 38, 35, 107 }
};
-
+#endif
static
int ves1820_set_parameters (struct dvb_frontend *frontend,
@@ -381,17 +381,43 @@
return -EINVAL;
}
+
tuner_set_tv_freq (frontend, p->frequency);
+
+// if ((p->u.qam.modulation != p->u.qam.old_modulation) ||
+// (p->u.qam.symbol_rate != p->u.qam.old_symbol_rate)) {
+
+ printk("Reinitializing ves1820 with new parameters (%d:%d:%d)\n",
+ p->frequency, p->u.qam.symbol_rate, p->u.qam.modulation);
+
ves1820_set_symbolrate (i2c, p->u.qam.symbol_rate);
ves1820_reset_pwm (frontend);
+#ifdef USE_PROCFS
+ printk("0x%x 0x%x 0x%x 0x%x\n",
+ frontend->QAM_Values[real_qam].Reg1,
+ frontend->QAM_Values[real_qam].Reg5,
+ frontend->QAM_Values[real_qam].Reg8,
+ frontend->QAM_Values[real_qam].Reg9);
+ ves1820_writereg (i2c, 0x01, frontend->QAM_Values[real_qam].Reg1);
+ ves1820_writereg (i2c, 0x05, frontend->QAM_Values[real_qam].Reg5);
+ ves1820_writereg (i2c, 0x08, frontend->QAM_Values[real_qam].Reg8);
+ ves1820_writereg (i2c, 0x09, frontend->QAM_Values[real_qam].Reg9);
+#else
ves1820_writereg (i2c, 0x01, QAM_Values[real_qam].Reg1);
ves1820_writereg (i2c, 0x05, QAM_Values[real_qam].Reg5);
ves1820_writereg (i2c, 0x08, QAM_Values[real_qam].Reg8);
ves1820_writereg (i2c, 0x09, QAM_Values[real_qam].Reg9);
-
+#endif
ves1820_setup_reg0 (frontend, real_qam, p->inversion);
+// p->u.qam.old_symbol_rate = p->u.qam.symbol_rate;
+// p->u.qam.old_modulation = p->u.qam.modulation;
+
+// } else {
+// printk("Not resetting ves1820\n");
+// }
+
return 0;
}
--
Info:
To unsubscribe send a mail to listar@linuxtv.org with "unsubscribe linux-dvb" as subject.
Home |
Main Index |
Thread Index