⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dvb_frontend.c

📁 h内核
💻 C
📖 第 1 页 / 共 2 页
字号:
		 * 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);		}	}	if (dvb_shutdown_timeout) {		if (dvb_powerdown_on_sleep)			if (fe->ops->set_voltage)				fe->ops->set_voltage(fe, SEC_VOLTAGE_OFF);		if (fe->ops->sleep)			fe->ops->sleep(fe);	}	fepriv->thread_pid = 0;	mb();	dvb_frontend_wakeup(fe);	return 0;}static void dvb_frontend_stop(struct dvb_frontend *fe){	unsigned long ret;	struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;	dprintk ("%s\n", __FUNCTION__);	fepriv->exit = 1;	mb();	if (!fepriv->thread_pid)		return;	/* check if the thread is really alive */	if (kill_proc(fepriv->thread_pid, 0, 1) == -ESRCH) {		printk("dvb_frontend_stop: thread PID %d already died\n",				fepriv->thread_pid);		/* make sure the mutex was not held by the thread */		init_MUTEX (&fepriv->sem);		return;	}	/* wake up the frontend thread, so it notices that fe->exit == 1 */	dvb_frontend_wakeup(fe);	/* wait until the frontend thread has exited */	ret = wait_event_interruptible(fepriv->wait_queue,0 == fepriv->thread_pid);	if (-ERESTARTSYS != ret) {		fepriv->state = FESTATE_IDLE;		return;	}	fepriv->state = FESTATE_IDLE;	/* paranoia check in case a signal arrived */	if (fepriv->thread_pid)		printk("dvb_frontend_stop: warning: thread PID %d won't exit\n",				fepriv->thread_pid);}static int dvb_frontend_start(struct dvb_frontend *fe){	int ret;	struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;	dprintk ("%s\n", __FUNCTION__);	if (fepriv->thread_pid) {		if (!fepriv->exit)			return 0;		else		dvb_frontend_stop (fe);	}	if (signal_pending(current))		return -EINTR;	if (down_interruptible (&fepriv->sem))		return -EINTR;	fepriv->state = FESTATE_IDLE;	fepriv->exit = 0;	fepriv->thread_pid = 0;	mb();	ret = kernel_thread (dvb_frontend_thread, fe, 0);	if (ret < 0) {		printk("dvb_frontend_start: failed to start kernel_thread (%d)\n", ret);		up(&fepriv->sem);		return ret;	}	fepriv->thread_pid = ret;	return 0;}static int dvb_frontend_ioctl (struct inode *inode, struct file *file,			unsigned int cmd, void *parg){	struct dvb_device *dvbdev = file->private_data;	struct dvb_frontend *fe = dvbdev->priv;	struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;	int err = -EOPNOTSUPP;	dprintk ("%s\n", __FUNCTION__);	if (!fe || fepriv->exit)		return -ENODEV;	if ((file->f_flags & O_ACCMODE) == O_RDONLY &&	    (_IOC_DIR(cmd) != _IOC_READ || cmd == FE_GET_EVENT ||	     cmd == FE_DISEQC_RECV_SLAVE_REPLY))		return -EPERM;	if (down_interruptible (&fepriv->sem))		return -ERESTARTSYS;	switch (cmd) {	case FE_GET_INFO: {		struct dvb_frontend_info* info = (struct dvb_frontend_info*) parg;		memcpy(info, &fe->ops->info, sizeof(struct dvb_frontend_info));		/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't		 * do it, it is done for it. */		info->caps |= FE_CAN_INVERSION_AUTO;		err = 0;		break;	}	case FE_READ_STATUS:		if (fe->ops->read_status)			err = fe->ops->read_status(fe, (fe_status_t*) parg);		break;	case FE_READ_BER:		if (fe->ops->read_ber)			err = fe->ops->read_ber(fe, (__u32*) parg);		break;	case FE_READ_SIGNAL_STRENGTH:		if (fe->ops->read_signal_strength)			err = fe->ops->read_signal_strength(fe, (__u16*) parg);		break;	case FE_READ_SNR:		if (fe->ops->read_snr)			err = fe->ops->read_snr(fe, (__u16*) parg);		break;	case FE_READ_UNCORRECTED_BLOCKS:		if (fe->ops->read_ucblocks)			err = fe->ops->read_ucblocks(fe, (__u32*) parg);		break;	case FE_DISEQC_RESET_OVERLOAD:		if (fe->ops->diseqc_reset_overload) {			err = fe->ops->diseqc_reset_overload(fe);			fepriv->state = FESTATE_DISEQC;			fepriv->status = 0;		}		break;	case FE_DISEQC_SEND_MASTER_CMD:		if (fe->ops->diseqc_send_master_cmd) {			err = fe->ops->diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg);			fepriv->state = FESTATE_DISEQC;			fepriv->status = 0;		}		break;	case FE_DISEQC_SEND_BURST:		if (fe->ops->diseqc_send_burst) {			err = fe->ops->diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg);			fepriv->state = FESTATE_DISEQC;			fepriv->status = 0;		}		break;	case FE_SET_TONE:		if (fe->ops->set_tone) {			err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg);			fepriv->state = FESTATE_DISEQC;			fepriv->status = 0;		}		break;	case FE_SET_VOLTAGE:		if (fe->ops->set_voltage) {			err = fe->ops->set_voltage(fe, (fe_sec_voltage_t) parg);			fepriv->state = FESTATE_DISEQC;			fepriv->status = 0;		}		break;	case FE_DISHNETWORK_SEND_LEGACY_CMD:		if (fe->ops->dishnetwork_send_legacy_command) {			err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned int) parg);			fepriv->state = FESTATE_DISEQC;			fepriv->status = 0;		}		break;	case FE_DISEQC_RECV_SLAVE_REPLY:		if (fe->ops->diseqc_recv_slave_reply)			err = fe->ops->diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg);		break;	case FE_ENABLE_HIGH_LNB_VOLTAGE:		if (fe->ops->enable_high_lnb_voltage)			err = fe->ops->enable_high_lnb_voltage(fe, (int) parg);		break;	case FE_SET_FRONTEND: {		struct dvb_frontend_tune_settings fetunesettings;	    		memcpy (&fepriv->parameters, parg,			sizeof (struct dvb_frontend_parameters));		memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));		memcpy(&fetunesettings.parameters, parg,		       sizeof (struct dvb_frontend_parameters));		    		/* force auto frequency inversion if requested */		if (dvb_force_auto_inversion) {			fepriv->parameters.inversion = INVERSION_AUTO;			fetunesettings.parameters.inversion = INVERSION_AUTO;		}		if (fe->ops->info.type == FE_OFDM) {			/* without hierachical coding code_rate_LP is irrelevant,			 * so we tolerate the otherwise invalid FEC_NONE setting */			if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&			    fepriv->parameters.u.ofdm.code_rate_LP == FEC_NONE)				fepriv->parameters.u.ofdm.code_rate_LP = FEC_AUTO;		}		/* get frontend-specific tuning settings */		if (fe->ops->get_tune_settings && (fe->ops->get_tune_settings(fe, &fetunesettings) == 0)) {			fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;			fepriv->max_drift = fetunesettings.max_drift;			fepriv->step_size = fetunesettings.step_size;		} else {			/* default values */			switch(fe->ops->info.type) {			case FE_QPSK:				fepriv->min_delay = HZ/20;				fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000;				fepriv->max_drift = fepriv->parameters.u.qpsk.symbol_rate / 2000;		break;			    			case FE_QAM:				fepriv->min_delay = HZ/20;				fepriv->step_size = 0; /* no zigzag */				fepriv->max_drift = 0;				break;			    			case FE_OFDM:				fepriv->min_delay = HZ/20;				fepriv->step_size = fe->ops->info.frequency_stepsize * 2;				fepriv->max_drift = (fe->ops->info.frequency_stepsize * 2) + 1;				break;			case FE_ATSC:				printk("dvb-core: FE_ATSC not handled yet.\n");				break;			}		}		if (dvb_override_tune_delay > 0)			fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;		fepriv->state = FESTATE_RETUNE;		dvb_frontend_wakeup(fe);		dvb_frontend_add_event (fe, 0);	    		fepriv->status = 0;		err = 0;		break;	}	case FE_GET_EVENT:		err = dvb_frontend_get_event (fe, parg, file->f_flags);		break;	case FE_GET_FRONTEND:		if (fe->ops->get_frontend) {			memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters));			err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg);		}		break;	};	up (&fepriv->sem);	return err;}static unsigned int dvb_frontend_poll (struct file *file, struct poll_table_struct *wait){	struct dvb_device *dvbdev = file->private_data;	struct dvb_frontend *fe = dvbdev->priv;	struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;	dprintk ("%s\n", __FUNCTION__);	poll_wait (file, &fepriv->events.wait_queue, wait);	if (fepriv->events.eventw != fepriv->events.eventr)		return (POLLIN | POLLRDNORM | POLLPRI);	return 0;}static int dvb_frontend_open (struct inode *inode, struct file *file){	struct dvb_device *dvbdev = file->private_data;	struct dvb_frontend *fe = dvbdev->priv;	struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;	int ret;	dprintk ("%s\n", __FUNCTION__);	if ((ret = dvb_generic_open (inode, file)) < 0)		return ret;	if ((file->f_flags & O_ACCMODE) != O_RDONLY) {		ret = dvb_frontend_start (fe);		if (ret)			dvb_generic_release (inode, file);		/*  empty event queue */		fepriv->events.eventr = fepriv->events.eventw = 0;	}		return ret;}static int dvb_frontend_release (struct inode *inode, struct file *file){	struct dvb_device *dvbdev = file->private_data;	struct dvb_frontend *fe = dvbdev->priv;	struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;	dprintk ("%s\n", __FUNCTION__);	if ((file->f_flags & O_ACCMODE) != O_RDONLY)		fepriv->release_jiffies = jiffies;	return dvb_generic_release (inode, file);}static struct file_operations dvb_frontend_fops = {	.owner		= THIS_MODULE,	.ioctl		= dvb_generic_ioctl,	.poll		= dvb_frontend_poll,	.open		= dvb_frontend_open,	.release	= dvb_frontend_release};int dvb_register_frontend(struct dvb_adapter* dvb,			  struct dvb_frontend* fe){	struct dvb_frontend_private *fepriv;	static const struct dvb_device dvbdev_template = {		.users = ~0,		.writers = 1,		.readers = (~0)-1,		.fops = &dvb_frontend_fops,		.kernel_ioctl = dvb_frontend_ioctl	};	dprintk ("%s\n", __FUNCTION__);	if (down_interruptible (&frontend_mutex))		return -ERESTARTSYS;	fe->frontend_priv = kmalloc(sizeof(struct dvb_frontend_private), GFP_KERNEL);	if (fe->frontend_priv == NULL) {		up(&frontend_mutex);		return -ENOMEM;	}	fepriv = (struct dvb_frontend_private*) fe->frontend_priv;	memset(fe->frontend_priv, 0, sizeof(struct dvb_frontend_private));	init_MUTEX (&fepriv->sem);	init_waitqueue_head (&fepriv->wait_queue);	init_waitqueue_head (&fepriv->events.wait_queue);	init_MUTEX (&fepriv->events.sem);	fe->dvb = dvb;	fepriv->inversion = INVERSION_OFF;	printk ("DVB: registering frontend %i (%s)...\n",		fe->dvb->num,		fe->ops->info.name);	dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,			     fe, DVB_DEVICE_FRONTEND);	up (&frontend_mutex);	return 0;}EXPORT_SYMBOL(dvb_register_frontend);int dvb_unregister_frontend(struct dvb_frontend* fe){	struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;	dprintk ("%s\n", __FUNCTION__);	down (&frontend_mutex);	dvb_unregister_device (fepriv->dvbdev);			dvb_frontend_stop (fe);	if (fe->ops->release)		fe->ops->release(fe);	else		printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops->info.name);	/* fe is invalid now */	if (fepriv)		kfree(fepriv);	up (&frontend_mutex);	return 0;}EXPORT_SYMBOL(dvb_unregister_frontend);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -