Comments inline... Andrew de Quincey wrote: >On Tuesday 15 Nov 2005 20:22, Johannes Stezenbach wrote: > > >>On Tue, Nov 15, 2005 Andrew de Quincey wrote: >> >> >>>Hi, this patch allows frontends (and the user) to select from one of >>>several different tuning algorithms. The patch adds four possibilities: >>> >>>1) SW - the current dvb-kernel software zigzag code. >>>2) HW - the hardware supports zigzagging internally (e.g. DST), so use >>>that as it will be faster. >>>3) ADAPTIVE - frontend-specific code exploiting frontend-specific >>>features. 4) SIMPLE - just set the frontend once and do nothing else >>>(e.g. for frequency scanner apps). >>> >>>Frontends can specify which algorithms they support using >>>FE_CAPS_CAN_TUNE_ALGO_*. They can also specify the default algorithm to >>>use. Currently the default is SW for all frontends except the DST (which >>>has HW). >>> >>>ADAPTIVE is not implemented internally yet. Enough information to do this >>>for many frontends is provided on their datasheets - for example I know >>>roughly how to do it for the stv0299, stv0297, and sh1420 frontends. This >>>needs experimentation before any real adaptive code can be committed to >>>CVS however, but I thought it was better to change the API _once_ instead >>>of several times. None of the frontends currently set the >>>FE_CAN_TUNE_ALGO_ADAPTIVE flag, so it cannot be accidentally enabled. >>> >>>The userspace app can also choose an algorithm using an IOCTL. >>> >>>When a frontend device is opened read/write, the tuning algo will >>>automatically be set back to whatever the frontend specified as the >>>default - so that userspace apps don't have to care if something else >>>changed algos. >>> >>> >>I wanted to have a way to turn off zig-zag etc. for a long time. >> >>However, I would prefer to implement this via an >>FE_SET_FRONTEND_EXT (bad name, need a better one) ioctl, >>which is basically the same as FE_SET_FRONTEND plus an >>added flags field. This way you could have one flag >>for switching off zig-zag, one for switching band filters >>for analog tuning (some FE have IF output to feed an >>analog demod) etc. >> >>What do you think? >> >> > >Yeah! I've been thinking along those lines myself a bit... discuss in a bit. > >Anyway, here is the latest patch. This one is much better IMO: > >1) The userspace IOCTL only lets you choose between normal and scan. We can >think about doing this using FE_SET_FRONTEND_EXT in a bit. > >2) I've pulled all of the current tuning code in dvb_frontend_thread() out >into a seperate function dvb_frontend_swzigzag(). > >3) There is a new function pointer in the dvb_frontend_ops - tune(). If this >is nonzero, it will be called in the main tuning loop. The frontend is then >responsible for ALL of its own tuning maintenance. If is it NULL, >dvb_frontend_swzigzag() will be used. > >BTW: dvb_frontend_ops.set_frontend() and dvb_frontend_ops.get_tune_settings() >are only used by the dvb_frontend_swzigzag().. if the driver defines tune(), >those functions are superfluous. > > >------------------------------------------------------------------------ > >? tunealgo-2.patch >? tunealgo-3.patch >? tunealgo-4.patch >? tunealgo.patch >? build-2.6/.tmp_versions >Index: linux/drivers/media/dvb/bt8xx/dst.c >=================================================================== >RCS file: /cvs/linuxtv/dvb-kernel/linux/drivers/media/dvb/bt8xx/dst.c,v >retrieving revision 1.44 >diff -a -u -r1.44 dst.c >--- linux/drivers/media/dvb/bt8xx/dst.c 24 Oct 2005 00:10:35 -0000 1.44 >+++ linux/drivers/media/dvb/bt8xx/dst.c 15 Nov 2005 21:21:24 -0000 >@@ -1341,30 +1341,39 @@ > 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, >+ fe_tune_mode_t mode, >+ int *delay, >+ fe_status_t *status) > { > struct dst_state *state = fe->demodulator_priv; > >- dst_set_freq(state, p->frequency); >- dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency); >- >- if (state->dst_type == DST_TYPE_IS_SAT) { >- if (state->type_flags & DST_TYPE_HAS_OBS_REGS) >- dst_set_inversion(state, p->inversion); >- dst_set_fec(state, p->u.qpsk.fec_inner); >- dst_set_symbolrate(state, p->u.qpsk.symbol_rate); >- dst_set_polarization(state); >- dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate); >- >- } else if (state->dst_type == DST_TYPE_IS_TERR) >- dst_set_bandwidth(state, p->u.ofdm.bandwidth); >- else if (state->dst_type == DST_TYPE_IS_CABLE) { >- dst_set_fec(state, p->u.qam.fec_inner); >- dst_set_symbolrate(state, p->u.qam.symbol_rate); >- dst_set_modulation(state, p->u.qam.modulation); >+ if (p != NULL) { >+ dst_set_freq(state, p->frequency); >+ dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency); > > Can you test your patches by compiling with -Wformat -Wformat-signed? >+ >+ if (state->dst_type == DST_TYPE_IS_SAT) { >+ if (state->type_flags & DST_TYPE_HAS_OBS_REGS) >+ dst_set_inversion(state, p->inversion); >+ dst_set_fec(state, p->u.qpsk.fec_inner); >+ dst_set_symbolrate(state, p->u.qpsk.symbol_rate); >+ dst_set_polarization(state); >+ dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate); >+ >+ } else if (state->dst_type == DST_TYPE_IS_TERR) >+ dst_set_bandwidth(state, p->u.ofdm.bandwidth); >+ else if (state->dst_type == DST_TYPE_IS_CABLE) { >+ dst_set_fec(state, p->u.qam.fec_inner); >+ dst_set_symbolrate(state, p->u.qam.symbol_rate); >+ dst_set_modulation(state, p->u.qam.modulation); >+ } >+ dst_write_tuna(fe); > } >- dst_write_tuna(fe); > >+ dst_read_status(fe, status); >+ >+ *delay = HZ/10; > > Spaces around didatic (binary) operators? > return 0; > } > >@@ -1445,7 +1454,7 @@ > > .release = dst_release, > .init = dst_init, >- .set_frontend = dst_set_frontend, >+ .tune = dst_set_frontend, > .get_frontend = dst_get_frontend, > .read_status = dst_read_status, > .read_signal_strength = dst_read_signal_strength, >@@ -1469,7 +1478,7 @@ > > .release = dst_release, > .init = dst_init, >- .set_frontend = dst_set_frontend, >+ .tune = dst_set_frontend, > .get_frontend = dst_get_frontend, > .read_status = dst_read_status, > .read_signal_strength = dst_read_signal_strength, >@@ -1496,7 +1505,7 @@ > > .release = dst_release, > .init = dst_init, >- .set_frontend = dst_set_frontend, >+ .tune = dst_set_frontend, > .get_frontend = dst_get_frontend, > .read_status = dst_read_status, > .read_signal_strength = dst_read_signal_strength, >Index: linux/drivers/media/dvb/dvb-core/dvb_frontend.c >=================================================================== >RCS file: /cvs/linuxtv/dvb-kernel/linux/drivers/media/dvb/dvb-core/dvb_frontend.c,v >retrieving revision 1.114 >diff -a -u -r1.114 dvb_frontend.c >--- linux/drivers/media/dvb/dvb-core/dvb_frontend.c 3 Oct 2005 14:23:07 -0000 1.114 >+++ linux/drivers/media/dvb/dvb-core/dvb_frontend.c 15 Nov 2005 21:21:25 -0000 >@@ -92,6 +92,7 @@ > > struct dvb_frontend_private { > >+ /* thread/frontend values */ > struct dvb_device *dvbdev; > struct dvb_frontend_parameters parameters; > struct dvb_fe_events events; >@@ -100,6 +101,13 @@ > wait_queue_head_t wait_queue; > pid_t thread_pid; > unsigned long release_jiffies; >+ int exit; >+ int wakeup; > > Use commas to combine all variables of same type on same line? >+ fe_status_t status; >+ fe_tune_mode_t cur_tune_mode; >+ int delay; > > I wonder about using signed ints for values which will always be greater than or equal to zero... >+ >+ /* swzigzag values */ > int state; > int bending; > int lnb_drift; >@@ -110,13 +118,10 @@ > int min_delay; > int max_drift; > int step_size; >- int exit; >- int wakeup; >- fe_status_t status; >- fe_sec_tone_mode_t tone; >+ int quality; >+ int check_wrapped; > > Ditto. > }; > >- > > Whitespace change... > static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) > { > struct dvb_frontend_private *fepriv = fe->frontend_priv; >@@ -208,21 +213,21 @@ > 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__); > > Ditto... > >- if (locked) >- (*quality) = (*quality * 220 + 36*256) / 256; >- else >- (*quality) = (*quality * 220 + 0) / 256; >+ if (locked) >+ (fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256; >+ else >+ (fepriv->quality) = (fepriv->quality * 220 + 0) / 256; > >- q2 = *quality - 128; >- q2 *= q2; >+ q2 = fepriv->quality - 128; >+ q2 *= q2; > >- *delay = min_delay + q2 * HZ / (128*128); >+ fepriv->delay = fepriv->min_delay + q2 * HZ / (128*128); > } > > /** >@@ -232,7 +237,7 @@ > * @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. > */ >-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 ready = 0; >@@ -321,6 +326,129 @@ > return 0; > } > >+static void dvb_frontend_swzigzag(struct dvb_frontend *fe) >+{ >+ fe_status_t s; >+ struct dvb_frontend_private *fepriv = fe->frontend_priv; >+ >+ /* if we've got no parameters, just keep idling */ >+ if (fepriv->state & FESTATE_IDLE) { >+ fepriv->delay = 3*HZ; > > Spaces around "*" >+ fepriv->quality = 0; >+ return; >+ } >+ >+ /* in SCAN mode, we just set the frontend when asked and leave it alone */ >+ if (fepriv->cur_tune_mode == FE_TUNE_MODE_SCAN) { >+ if (fepriv->state & FESTATE_RETUNE) { >+ if (fe->ops->set_frontend) >+ fe->ops->set_frontend(fe, &fepriv->parameters); >+ fepriv->state = FESTATE_TUNED; >+ } >+ fepriv->delay = 3*HZ; > > Ditto. >+ fepriv->quality = 0; >+ return; >+ } >+ >+ /* get the frontend status */ >+ if (fepriv->state & FESTATE_RETUNE) { >+ s = 0; >+ } else { >+ if (fe->ops->read_status) >+ fe->ops->read_status(fe, &s); >+ if (s != fepriv->status) { >+ dvb_frontend_add_event(fe, s); >+ fepriv->status = s; >+ } >+ } >+ >+ /* if we're not tuned, and we have a lock, move to the TUNED state */ >+ if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) { >+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); >+ fepriv->state = FESTATE_TUNED; >+ >+ /* if we're tuned, then we have determined the correct inversion */ >+ if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) && >+ (fepriv->parameters.inversion == INVERSION_AUTO)) { >+ fepriv->parameters.inversion = fepriv->inversion; >+ } >+ return; >+ } >+ >+ /* if we are tuned already, check we're still locked */ >+ if (fepriv->state & FESTATE_TUNED) { >+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); >+ >+ /* we're tuned, and the lock is still good... */ >+ if (s & FE_HAS_LOCK) { >+ return; >+ } else { /* if we _WERE_ tuned, but now don't have a lock */ > > Don't need "else" because the "if" portion ends with a control-flow statement (i.e. "break", "goto", "continue", "return", etc...) >+ fepriv->state = FESTATE_ZIGZAG_FAST; >+ fepriv->started_auto_step = fepriv->auto_step; >+ fepriv->check_wrapped = 0; >+ } >+ } >+ >+ /* don't actually do anything if we're in the LOSTLOCK state, >+ * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */ >+ if ((fepriv->state & FESTATE_LOSTLOCK) && >+ (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) { >+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); >+ return; >+ } >+ >+ /* don't do anything if we're in the DISEQC state, since this >+ * 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 (fepriv->state & FESTATE_DISEQC) { >+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); >+ return; >+ } >+ >+ /* if we're in the RETUNE state, set everything up for a brand >+ * new scan, keeping the current inversion setting, as the next >+ * tune is _very_ likely to require the same */ >+ if (fepriv->state & FESTATE_RETUNE) { >+ fepriv->lnb_drift = 0; >+ fepriv->auto_step = 0; >+ fepriv->auto_sub_step = 0; >+ fepriv->started_auto_step = 0; >+ fepriv->check_wrapped = 0; >+ } >+ >+ /* fast zigzag. */ >+ if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) { > > How about: if ((fepriv->state & (X | Y))) { instead? Fewer cycles... >+ fepriv->delay = fepriv->min_delay; >+ >+ /* peform a tune */ >+ if (dvb_frontend_swzigzag_autotune(fe, fepriv->check_wrapped)) { >+ /* OK, if we've run out of trials at the fast speed. >+ * Drop back to slow for the _next_ attempt */ >+ fepriv->state = FESTATE_SEARCHING_SLOW; >+ fepriv->started_auto_step = fepriv->auto_step; >+ return; >+ } >+ fepriv->check_wrapped = 1; >+ >+ /* if we've just retuned, enter the ZIGZAG_FAST state. >+ * This ensures we cannot return from an >+ * FE_SET_FRONTEND ioctl before the first frontend tune >+ * occurs */ >+ if (fepriv->state & FESTATE_RETUNE) { >+ fepriv->state = FESTATE_TUNING_FAST; >+ } >+ } >+ >+ /* slow zigzag */ >+ if (fepriv->state & FESTATE_SEARCHING_SLOW) { >+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); >+ >+ /* Note: don't bother checking for wrapping; we stay in this >+ * state until we get a lock */ >+ dvb_frontend_swzigzag_autotune(fe, 0); >+ } >+} >+ > static int dvb_frontend_is_exiting(struct dvb_frontend *fe) > { > struct dvb_frontend_private *fepriv = fe->frontend_priv; >@@ -330,7 +458,7 @@ > > if (fepriv->dvbdev->writers == 1) > if (time_after(jiffies, fepriv->release_jiffies + >- dvb_shutdown_timeout * HZ)) >+ dvb_shutdown_timeout * HZ)) > > Whitespace... > return 1; > > return 0; >@@ -355,18 +483,14 @@ > 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; >+ struct dvb_frontend_parameters *params; > > dprintk("%s\n", __FUNCTION__); > >@@ -377,6 +501,9 @@ > sigfillset(¤t->blocked); > unlock_kernel(); > >+ fepriv->check_wrapped = 0; >+ fepriv->quality = 0; >+ fepriv->delay = 3*HZ; > > Spaces... > fepriv->status = 0; > dvb_frontend_init(fe); > fepriv->wakeup = 0; >@@ -386,7 +513,7 @@ > > timeout = wait_event_interruptible_timeout(fepriv->wait_queue, > dvb_frontend_should_wakeup(fe), >- delay); >+ fepriv->delay); > if (0 != dvb_frontend_is_exiting(fe)) { > /* got signal or quitting */ > break; >@@ -397,108 +524,22 @@ > 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; >- } >+ /* 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; >+ } > >- /* get the frontend status */ >- if (fepriv->state & FESTATE_RETUNE) { >- s = 0; >- } else { >- if (fe->ops->read_status) >- fe->ops->read_status(fe, &s); >+ fe->ops->tune(fe, params, fepriv->cur_tune_mode, &fepriv->delay, &s); > if (s != fepriv->status) { > dvb_frontend_add_event(fe, s); > fepriv->status = s; > } >- } >- /* if we're not tuned, and we have a lock, move to the TUNED state */ >- if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) { >- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); >- fepriv->state = FESTATE_TUNED; >- >- /* if we're tuned, then we have determined the correct inversion */ >- if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) && >- (fepriv->parameters.inversion == INVERSION_AUTO)) { >- fepriv->parameters.inversion = fepriv->inversion; >- } >- continue; >- } >- >- /* if we are tuned already, check we're still locked */ >- if (fepriv->state & FESTATE_TUNED) { >- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); >- >- /* we're tuned, and the lock is still good... */ >- if (s & FE_HAS_LOCK) >- continue; >- else { /* if we _WERE_ tuned, but now don't have a lock */ >- fepriv->state = FESTATE_ZIGZAG_FAST; >- fepriv->started_auto_step = fepriv->auto_step; >- check_wrapped = 0; >- } >- } >- >- /* don't actually do anything if we're in the LOSTLOCK state, >- * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */ >- if ((fepriv->state & FESTATE_LOSTLOCK) && >- (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) { >- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); >- continue; >- } >- >- /* don't do anything if we're in the DISEQC state, since this >- * 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 (fepriv->state & FESTATE_DISEQC) { >- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); >- continue; >- } >- >- /* if we're in the RETUNE state, set everything up for a brand >- * new scan, keeping the current inversion setting, as the next >- * tune is _very_ likely to require the same */ >- if (fepriv->state & FESTATE_RETUNE) { >- fepriv->lnb_drift = 0; >- fepriv->auto_step = 0; >- fepriv->auto_sub_step = 0; >- fepriv->started_auto_step = 0; >- check_wrapped = 0; >- } >- >- /* fast zigzag. */ >- if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) { >- delay = fepriv->min_delay; >- >- /* peform a tune */ >- if (dvb_frontend_autotune(fe, check_wrapped)) { >- /* OK, if we've run out of trials at the fast speed. >- * Drop back to slow for the _next_ attempt */ >- fepriv->state = FESTATE_SEARCHING_SLOW; >- fepriv->started_auto_step = fepriv->auto_step; >- continue; >- } >- check_wrapped = 1; >- >- /* if we've just retuned, enter the ZIGZAG_FAST state. >- * This ensures we cannot return from an >- * FE_SET_FRONTEND ioctl before the first frontend tune >- * occurs */ >- if (fepriv->state & FESTATE_RETUNE) { >- fepriv->state = FESTATE_TUNING_FAST; >- } >- } >- >- /* slow zigzag */ >- if (fepriv->state & FESTATE_SEARCHING_SLOW) { >- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK); >- >- /* Note: don't bother checking for wrapping; we stay in this >- * state until we get a lock */ >- dvb_frontend_autotune(fe, 0); >+ } else { >+ dvb_frontend_swzigzag(fe); > } > } > >@@ -733,7 +774,6 @@ > err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg); > fepriv->state = FESTATE_DISEQC; > fepriv->status = 0; >- fepriv->tone = (fe_sec_tone_mode_t) parg; > } > break; > >@@ -891,6 +931,21 @@ > err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg); > } > break; >+ >+ case FE_SET_FRONTEND_TUNE_MODE: >+ switch((fe_tune_mode_t) parg) { > > Space after keyword... >+ case FE_TUNE_MODE_NORMAL: >+ fepriv->cur_tune_mode = FE_TUNE_MODE_NORMAL; >+ break; >+ >+ case FE_TUNE_MODE_SCAN: >+ fepriv->cur_tune_mode = FE_TUNE_MODE_SCAN; >+ break; >+ >+ default: >+ return -EINVAL; >+ } >+ break; > }; > > up (&fepriv->sem); >@@ -932,6 +987,9 @@ > > /* empty event queue */ > fepriv->events.eventr = fepriv->events.eventw = 0; >+ >+ /* normal tune mode when opened R/W */ >+ fepriv->cur_tune_mode = FE_TUNE_MODE_NORMAL; > } > > return ret; >@@ -990,7 +1048,6 @@ > init_MUTEX (&fepriv->events.sem); > fe->dvb = dvb; > fepriv->inversion = INVERSION_OFF; >- fepriv->tone = SEC_TONE_OFF; > > printk ("DVB: registering frontend %i (%s)...\n", > fe->dvb->num, >Index: linux/drivers/media/dvb/dvb-core/dvb_frontend.h >=================================================================== >RCS file: /cvs/linuxtv/dvb-kernel/linux/drivers/media/dvb/dvb-core/dvb_frontend.h,v >retrieving revision 1.23 >diff -a -u -r1.23 dvb_frontend.h >--- linux/drivers/media/dvb/dvb-core/dvb_frontend.h 26 Sep 2005 21:58:15 -0000 1.23 >+++ linux/drivers/media/dvb/dvb-core/dvb_frontend.h 15 Nov 2005 21:21:25 -0000 >@@ -58,10 +58,19 @@ > int (*init)(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, >+ fe_tune_mode_t mode, >+ 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 (*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_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); >+ > int (*read_status)(struct dvb_frontend* fe, fe_status_t* status); > int (*read_ber)(struct dvb_frontend* fe, u32* ber); > int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength); >Index: linux/include/linux/dvb/frontend.h >=================================================================== >RCS file: /cvs/linuxtv/dvb-kernel/linux/include/linux/dvb/frontend.h,v >retrieving revision 1.18 >diff -a -u -r1.18 frontend.h >--- linux/include/linux/dvb/frontend.h 2 Mar 2005 21:42:01 -0000 1.18 >+++ linux/include/linux/dvb/frontend.h 15 Nov 2005 21:21:26 -0000 >@@ -67,6 +67,14 @@ > FE_CAN_MUTE_TS = 0x80000000 // frontend can stop spurious TS data output > } fe_caps_t; > >+/** >+ * FE_TUNE_MODE_NORMAL - "Normal" tune mode. >+ * FE_TUNE_MODE_SCAN - Special tune mode specifically for channel scanning. >+ */ >+typedef enum fe_tune_mode { >+ FE_TUNE_MODE_NORMAL = 0, >+ FE_TUNE_MODE_SCAN = 1, > > These are the default values, so... Why include them explicitly? -Philip >+} fe_tune_mode_t; > > struct dvb_frontend_info { > char name[128]; >@@ -260,6 +268,7 @@ > > #define FE_SET_FRONTEND _IOW('o', 76, struct dvb_frontend_parameters) > #define FE_GET_FRONTEND _IOR('o', 77, struct dvb_frontend_parameters) >+#define FE_SET_FRONTEND_TUNE_MODE _IO('o', 81 /* fe_tune_mode_t */) > #define FE_GET_EVENT _IOR('o', 78, struct dvb_frontend_event) > > #define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80) /* unsigned int */ > >