Commit 36cb557a authored by Andrew de Quincey's avatar Andrew de Quincey Committed by Mauro Carvalho Chehab

DVB (2444): Implement frontend-specific tuning and the ability to disable zigzag

- Implement frontend-specific tuning and the ability to disable zigzag
Signed-off-by: default avatarAndrew de Quincey <adq_dvb@lidskialf.net>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@brturbo.com.br>
parent 47f36920
...@@ -1341,10 +1341,15 @@ static int dst_read_snr(struct dvb_frontend *fe, u16 *snr) ...@@ -1341,10 +1341,15 @@ static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
return 0; return 0;
} }
static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) static int dst_set_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters* p,
unsigned int mode_flags,
int *delay,
fe_status_t *status)
{ {
struct dst_state *state = fe->demodulator_priv; struct dst_state *state = fe->demodulator_priv;
if (p != NULL) {
dst_set_freq(state, p->frequency); dst_set_freq(state, p->frequency);
dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency); dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
...@@ -1364,7 +1369,12 @@ static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_paramet ...@@ -1364,7 +1369,12 @@ static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_paramet
dst_set_modulation(state, p->u.qam.modulation); dst_set_modulation(state, p->u.qam.modulation);
} }
dst_write_tuna(fe); dst_write_tuna(fe);
}
if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
dst_read_status(fe, status);
*delay = HZ/10;
return 0; return 0;
} }
...@@ -1445,7 +1455,7 @@ static struct dvb_frontend_ops dst_dvbt_ops = { ...@@ -1445,7 +1455,7 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
.release = dst_release, .release = dst_release,
.init = dst_init, .init = dst_init,
.set_frontend = dst_set_frontend, .tune = dst_set_frontend,
.get_frontend = dst_get_frontend, .get_frontend = dst_get_frontend,
.read_status = dst_read_status, .read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength, .read_signal_strength = dst_read_signal_strength,
...@@ -1469,7 +1479,7 @@ static struct dvb_frontend_ops dst_dvbs_ops = { ...@@ -1469,7 +1479,7 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
.release = dst_release, .release = dst_release,
.init = dst_init, .init = dst_init,
.set_frontend = dst_set_frontend, .tune = dst_set_frontend,
.get_frontend = dst_get_frontend, .get_frontend = dst_get_frontend,
.read_status = dst_read_status, .read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength, .read_signal_strength = dst_read_signal_strength,
...@@ -1496,7 +1506,7 @@ static struct dvb_frontend_ops dst_dvbc_ops = { ...@@ -1496,7 +1506,7 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
.release = dst_release, .release = dst_release,
.init = dst_init, .init = dst_init,
.set_frontend = dst_set_frontend, .tune = dst_set_frontend,
.get_frontend = dst_get_frontend, .get_frontend = dst_get_frontend,
.read_status = dst_read_status, .read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength, .read_signal_strength = dst_read_signal_strength,
......
...@@ -92,6 +92,7 @@ static DECLARE_MUTEX(frontend_mutex); ...@@ -92,6 +92,7 @@ static DECLARE_MUTEX(frontend_mutex);
struct dvb_frontend_private { struct dvb_frontend_private {
/* thread/frontend values */
struct dvb_device *dvbdev; struct dvb_device *dvbdev;
struct dvb_frontend_parameters parameters; struct dvb_frontend_parameters parameters;
struct dvb_fe_events events; struct dvb_fe_events events;
...@@ -100,20 +101,25 @@ struct dvb_frontend_private { ...@@ -100,20 +101,25 @@ struct dvb_frontend_private {
wait_queue_head_t wait_queue; wait_queue_head_t wait_queue;
pid_t thread_pid; pid_t thread_pid;
unsigned long release_jiffies; unsigned long release_jiffies;
int state; unsigned int exit;
int bending; unsigned int wakeup;
int lnb_drift;
int inversion;
int auto_step;
int auto_sub_step;
int started_auto_step;
int min_delay;
int max_drift;
int step_size;
int exit;
int wakeup;
fe_status_t status; fe_status_t status;
fe_sec_tone_mode_t tone; unsigned int tune_mode_flags;
unsigned int delay;
/* swzigzag values */
unsigned int state;
unsigned int bending;
int lnb_drift;
unsigned int inversion;
unsigned int auto_step;
unsigned int auto_sub_step;
unsigned int started_auto_step;
unsigned int min_delay;
unsigned int max_drift;
unsigned int step_size;
int quality;
unsigned int check_wrapped;
}; };
...@@ -208,21 +214,21 @@ static void dvb_frontend_init(struct dvb_frontend *fe) ...@@ -208,21 +214,21 @@ static void dvb_frontend_init(struct dvb_frontend *fe)
fe->ops->init(fe); fe->ops->init(fe);
} }
static void update_delay(int *quality, int *delay, int min_delay, int locked) static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked)
{ {
int q2; int q2;
dprintk ("%s\n", __FUNCTION__); dprintk ("%s\n", __FUNCTION__);
if (locked) if (locked)
(*quality) = (*quality * 220 + 36*256) / 256; (fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256;
else else
(*quality) = (*quality * 220 + 0) / 256; (fepriv->quality) = (fepriv->quality * 220 + 0) / 256;
q2 = *quality - 128; q2 = fepriv->quality - 128;
q2 *= q2; q2 *= q2;
*delay = min_delay + q2 * HZ / (128*128); fepriv->delay = fepriv->min_delay + q2 * HZ / (128*128);
} }
/** /**
...@@ -232,7 +238,7 @@ static void update_delay(int *quality, int *delay, int min_delay, int locked) ...@@ -232,7 +238,7 @@ static void update_delay(int *quality, int *delay, int min_delay, int locked)
* @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT * @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT
* @returns Number of complete iterations that have been performed. * @returns Number of complete iterations that have been performed.
*/ */
static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped) static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wrapped)
{ {
int autoinversion; int autoinversion;
int ready = 0; int ready = 0;
...@@ -321,87 +327,28 @@ static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped) ...@@ -321,87 +327,28 @@ static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped)
return 0; return 0;
} }
static int dvb_frontend_is_exiting(struct dvb_frontend *fe) static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
if (fepriv->exit)
return 1;
if (fepriv->dvbdev->writers == 1)
if (time_after(jiffies, fepriv->release_jiffies +
dvb_shutdown_timeout * HZ))
return 1;
return 0;
}
static int dvb_frontend_should_wakeup(struct dvb_frontend *fe)
{ {
fe_status_t s;
struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dvb_frontend_private *fepriv = fe->frontend_priv;
if (fepriv->wakeup) { /* if we've got no parameters, just keep idling */
fepriv->wakeup = 0; if (fepriv->state & FESTATE_IDLE) {
return 1; fepriv->delay = 3*HZ;
fepriv->quality = 0;
return;
} }
return dvb_frontend_is_exiting(fe);
}
static void dvb_frontend_wakeup(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
fepriv->wakeup = 1;
wake_up_interruptible(&fepriv->wait_queue);
}
/*
* FIXME: use linux/kthread.h
*/
static int dvb_frontend_thread(void *data)
{
struct dvb_frontend *fe = data;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
unsigned long timeout;
char name [15];
int quality = 0, delay = 3*HZ;
fe_status_t s;
int check_wrapped = 0;
dprintk("%s\n", __FUNCTION__);
snprintf (name, sizeof(name), "kdvb-fe-%i", fe->dvb->num);
lock_kernel();
daemonize(name);
sigfillset(&current->blocked);
unlock_kernel();
fepriv->status = 0;
dvb_frontend_init(fe);
fepriv->wakeup = 0;
while (1) { /* in SCAN mode, we just set the frontend when asked and leave it alone */
up(&fepriv->sem); /* is locked when we enter the thread... */ if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
if (fepriv->state & FESTATE_RETUNE) {
timeout = wait_event_interruptible_timeout(fepriv->wait_queue, if (fe->ops->set_frontend)
dvb_frontend_should_wakeup(fe), fe->ops->set_frontend(fe, &fepriv->parameters);
delay); fepriv->state = FESTATE_TUNED;
if (0 != dvb_frontend_is_exiting(fe)) {
/* got signal or quitting */
break;
} }
fepriv->delay = 3*HZ;
try_to_freeze(); fepriv->quality = 0;
return;
if (down_interruptible(&fepriv->sem))
break;
/* if we've got no parameters, just keep idling */
if (fepriv->state & FESTATE_IDLE) {
delay = 3*HZ;
quality = 0;
continue;
} }
/* get the frontend status */ /* get the frontend status */
...@@ -415,9 +362,10 @@ static int dvb_frontend_thread(void *data) ...@@ -415,9 +362,10 @@ static int dvb_frontend_thread(void *data)
fepriv->status = s; fepriv->status = s;
} }
} }
/* if we're not tuned, and we have a lock, move to the TUNED state */ /* if we're not tuned, and we have a lock, move to the TUNED state */
if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) { if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
fepriv->state = FESTATE_TUNED; fepriv->state = FESTATE_TUNED;
/* if we're tuned, then we have determined the correct inversion */ /* if we're tuned, then we have determined the correct inversion */
...@@ -425,20 +373,20 @@ static int dvb_frontend_thread(void *data) ...@@ -425,20 +373,20 @@ static int dvb_frontend_thread(void *data)
(fepriv->parameters.inversion == INVERSION_AUTO)) { (fepriv->parameters.inversion == INVERSION_AUTO)) {
fepriv->parameters.inversion = fepriv->inversion; fepriv->parameters.inversion = fepriv->inversion;
} }
continue; return;
} }
/* if we are tuned already, check we're still locked */ /* if we are tuned already, check we're still locked */
if (fepriv->state & FESTATE_TUNED) { if (fepriv->state & FESTATE_TUNED) {
update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
/* we're tuned, and the lock is still good... */ /* we're tuned, and the lock is still good... */
if (s & FE_HAS_LOCK) if (s & FE_HAS_LOCK) {
continue; return;
else { /* if we _WERE_ tuned, but now don't have a lock */ } else { /* if we _WERE_ tuned, but now don't have a lock */
fepriv->state = FESTATE_ZIGZAG_FAST; fepriv->state = FESTATE_ZIGZAG_FAST;
fepriv->started_auto_step = fepriv->auto_step; fepriv->started_auto_step = fepriv->auto_step;
check_wrapped = 0; fepriv->check_wrapped = 0;
} }
} }
...@@ -446,16 +394,16 @@ static int dvb_frontend_thread(void *data) ...@@ -446,16 +394,16 @@ static int dvb_frontend_thread(void *data)
* the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */ * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
if ((fepriv->state & FESTATE_LOSTLOCK) && if ((fepriv->state & FESTATE_LOSTLOCK) &&
(fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) { (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
continue; return;
} }
/* don't do anything if we're in the DISEQC state, since this /* don't do anything if we're in the DISEQC state, since this
* might be someone with a motorized dish controlled by DISEQC. * might be someone with a motorized dish controlled by DISEQC.
* If its actually a re-tune, there will be a SET_FRONTEND soon enough. */ * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */
if (fepriv->state & FESTATE_DISEQC) { if (fepriv->state & FESTATE_DISEQC) {
update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
continue; return;
} }
/* if we're in the RETUNE state, set everything up for a brand /* if we're in the RETUNE state, set everything up for a brand
...@@ -466,22 +414,22 @@ static int dvb_frontend_thread(void *data) ...@@ -466,22 +414,22 @@ static int dvb_frontend_thread(void *data)
fepriv->auto_step = 0; fepriv->auto_step = 0;
fepriv->auto_sub_step = 0; fepriv->auto_sub_step = 0;
fepriv->started_auto_step = 0; fepriv->started_auto_step = 0;
check_wrapped = 0; fepriv->check_wrapped = 0;
} }
/* fast zigzag. */ /* fast zigzag. */
if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) { if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) {
delay = fepriv->min_delay; fepriv->delay = fepriv->min_delay;
/* peform a tune */ /* peform a tune */
if (dvb_frontend_autotune(fe, check_wrapped)) { if (dvb_frontend_swzigzag_autotune(fe, fepriv->check_wrapped)) {
/* OK, if we've run out of trials at the fast speed. /* OK, if we've run out of trials at the fast speed.
* Drop back to slow for the _next_ attempt */ * Drop back to slow for the _next_ attempt */
fepriv->state = FESTATE_SEARCHING_SLOW; fepriv->state = FESTATE_SEARCHING_SLOW;
fepriv->started_auto_step = fepriv->auto_step; fepriv->started_auto_step = fepriv->auto_step;
continue; return;
} }
check_wrapped = 1; fepriv->check_wrapped = 1;
/* if we've just retuned, enter the ZIGZAG_FAST state. /* if we've just retuned, enter the ZIGZAG_FAST state.
* This ensures we cannot return from an * This ensures we cannot return from an
...@@ -494,11 +442,105 @@ static int dvb_frontend_thread(void *data) ...@@ -494,11 +442,105 @@ static int dvb_frontend_thread(void *data)
/* slow zigzag */ /* slow zigzag */
if (fepriv->state & FESTATE_SEARCHING_SLOW) { if (fepriv->state & FESTATE_SEARCHING_SLOW) {
update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
/* Note: don't bother checking for wrapping; we stay in this /* Note: don't bother checking for wrapping; we stay in this
* state until we get a lock */ * state until we get a lock */
dvb_frontend_autotune(fe, 0); dvb_frontend_swzigzag_autotune(fe, 0);
}
}
static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
if (fepriv->exit)
return 1;
if (fepriv->dvbdev->writers == 1)
if (time_after(jiffies, fepriv->release_jiffies +
dvb_shutdown_timeout * HZ))
return 1;
return 0;
}
static int dvb_frontend_should_wakeup(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
if (fepriv->wakeup) {
fepriv->wakeup = 0;
return 1;
}
return dvb_frontend_is_exiting(fe);
}
static void dvb_frontend_wakeup(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
fepriv->wakeup = 1;
wake_up_interruptible(&fepriv->wait_queue);
}
static int dvb_frontend_thread(void *data)
{
struct dvb_frontend *fe = data;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
unsigned long timeout;
char name [15];
fe_status_t s;
struct dvb_frontend_parameters *params;
dprintk("%s\n", __FUNCTION__);
snprintf (name, sizeof(name), "kdvb-fe-%i", fe->dvb->num);
lock_kernel();
daemonize(name);
sigfillset(&current->blocked);
unlock_kernel();
fepriv->check_wrapped = 0;
fepriv->quality = 0;
fepriv->delay = 3*HZ;
fepriv->status = 0;
dvb_frontend_init(fe);
fepriv->wakeup = 0;
while (1) {
up(&fepriv->sem); /* is locked when we enter the thread... */
timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
dvb_frontend_should_wakeup(fe),
fepriv->delay);
if (0 != dvb_frontend_is_exiting(fe)) {
/* got signal or quitting */
break;
}
try_to_freeze();
if (down_interruptible(&fepriv->sem))
break;
/* do an iteration of the tuning loop */
if (fe->ops->tune) {
/* have we been asked to retune? */
params = NULL;
if (fepriv->state & FESTATE_RETUNE) {
params = &fepriv->parameters;
fepriv->state = FESTATE_TUNED;
}
fe->ops->tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
if (s != fepriv->status) {
dvb_frontend_add_event(fe, s);
fepriv->status = s;
}
} else {
dvb_frontend_swzigzag(fe);
} }
} }
...@@ -733,7 +775,6 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, ...@@ -733,7 +775,6 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg); err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg);
fepriv->state = FESTATE_DISEQC; fepriv->state = FESTATE_DISEQC;
fepriv->status = 0; fepriv->status = 0;
fepriv->tone = (fe_sec_tone_mode_t) parg;
} }
break; break;
...@@ -891,6 +932,10 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, ...@@ -891,6 +932,10 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg); err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg);
} }
break; break;
case FE_SET_FRONTEND_TUNE_MODE:
fepriv->tune_mode_flags = (unsigned int) parg;
break;
}; };
up (&fepriv->sem); up (&fepriv->sem);
...@@ -932,6 +977,9 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) ...@@ -932,6 +977,9 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
/* empty event queue */ /* empty event queue */
fepriv->events.eventr = fepriv->events.eventw = 0; fepriv->events.eventr = fepriv->events.eventw = 0;
/* normal tune mode when opened R/W */
fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
} }
return ret; return ret;
...@@ -990,7 +1038,6 @@ int dvb_register_frontend(struct dvb_adapter* dvb, ...@@ -990,7 +1038,6 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
init_MUTEX (&fepriv->events.sem); init_MUTEX (&fepriv->events.sem);
fe->dvb = dvb; fe->dvb = dvb;
fepriv->inversion = INVERSION_OFF; fepriv->inversion = INVERSION_OFF;
fepriv->tone = SEC_TONE_OFF;
printk ("DVB: registering frontend %i (%s)...\n", printk ("DVB: registering frontend %i (%s)...\n",
fe->dvb->num, fe->dvb->num,
......
...@@ -58,10 +58,19 @@ struct dvb_frontend_ops { ...@@ -58,10 +58,19 @@ struct dvb_frontend_ops {
int (*init)(struct dvb_frontend* fe); int (*init)(struct dvb_frontend* fe);
int (*sleep)(struct dvb_frontend* fe); int (*sleep)(struct dvb_frontend* fe);
/* if this is set, it overrides the default swzigzag */
int (*tune)(struct dvb_frontend* fe,
struct dvb_frontend_parameters* params,
unsigned int mode_flags,
int *delay,
fe_status_t *status);
/* these two are only used for the swzigzag code */
int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings); int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings);
int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
int (*read_status)(struct dvb_frontend* fe, fe_status_t* status); int (*read_status)(struct dvb_frontend* fe, fe_status_t* status);
int (*read_ber)(struct dvb_frontend* fe, u32* ber); int (*read_ber)(struct dvb_frontend* fe, u32* ber);
int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength); int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength);
......
...@@ -240,6 +240,15 @@ struct dvb_frontend_event { ...@@ -240,6 +240,15 @@ struct dvb_frontend_event {
}; };
/**
* When set, this flag will disable any zigzagging or other "normal" tuning
* behaviour. Additionally, there will be no automatic monitoring of the lock
* status, and hence no frontend events will be generated. If a frontend device
* is closed, this flag will be automatically turned off when the device is
* reopened read-write.
*/
#define FE_TUNE_MODE_ONESHOT 0x01
#define FE_GET_INFO _IOR('o', 61, struct dvb_frontend_info) #define FE_GET_INFO _IOR('o', 61, struct dvb_frontend_info)
...@@ -260,6 +269,7 @@ struct dvb_frontend_event { ...@@ -260,6 +269,7 @@ struct dvb_frontend_event {
#define FE_SET_FRONTEND _IOW('o', 76, struct dvb_frontend_parameters) #define FE_SET_FRONTEND _IOW('o', 76, struct dvb_frontend_parameters)
#define FE_GET_FRONTEND _IOR('o', 77, struct dvb_frontend_parameters) #define FE_GET_FRONTEND _IOR('o', 77, struct dvb_frontend_parameters)
#define FE_SET_FRONTEND_TUNE_MODE _IO('o', 81) /* unsigned int */
#define FE_GET_EVENT _IOR('o', 78, struct dvb_frontend_event) #define FE_GET_EVENT _IOR('o', 78, struct dvb_frontend_event)
#define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80) /* unsigned int */ #define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80) /* unsigned int */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment