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, &reg1, &reg5, &reg8, &reg9);
+	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