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

📄 pvrusb2-hdw.c

📁 V4l driver for DVB HD
💻 C
📖 第 1 页 / 共 5 页
字号:
	mutex_init(&hdw->big_lock_mutex);	return hdw; fail:	if (hdw) {		if (hdw->ctl_read_urb) usb_free_urb(hdw->ctl_read_urb);		if (hdw->ctl_write_urb) usb_free_urb(hdw->ctl_write_urb);		if (hdw->ctl_read_buffer) kfree(hdw->ctl_read_buffer);		if (hdw->ctl_write_buffer) kfree(hdw->ctl_write_buffer);		if (hdw->controls) kfree(hdw->controls);		kfree(hdw);	}	return 0;}/* Remove _all_ associations between this driver and the underlying USB   layer. */void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw){	if (hdw->flag_disconnected) return;	pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_remove_usb_stuff: hdw=%p",hdw);	if (hdw->ctl_read_urb) {		usb_kill_urb(hdw->ctl_read_urb);		usb_free_urb(hdw->ctl_read_urb);		hdw->ctl_read_urb = 0;	}	if (hdw->ctl_write_urb) {		usb_kill_urb(hdw->ctl_write_urb);		usb_free_urb(hdw->ctl_write_urb);		hdw->ctl_write_urb = 0;	}	if (hdw->ctl_read_buffer) {		kfree(hdw->ctl_read_buffer);		hdw->ctl_read_buffer = 0;	}	if (hdw->ctl_write_buffer) {		kfree(hdw->ctl_write_buffer);		hdw->ctl_write_buffer = 0;	}	pvr2_hdw_render_useless_unlocked(hdw);	hdw->flag_disconnected = !0;	hdw->usb_dev = 0;	hdw->usb_intf = 0;}/* Destroy hardware interaction structure */void pvr2_hdw_destroy(struct pvr2_hdw *hdw){	pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw);	if (hdw->fw_buffer) {		kfree(hdw->fw_buffer);		hdw->fw_buffer = 0;	}	if (hdw->vid_stream) {		pvr2_stream_destroy(hdw->vid_stream);		hdw->vid_stream = 0;	}	if (hdw->audio_stat) {		hdw->audio_stat->detach(hdw->audio_stat->ctxt);	}	if (hdw->decoder_ctrl) {		hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt);	}	pvr2_i2c_core_done(hdw);	pvr2_hdw_remove_usb_stuff(hdw);	down(&pvr2_unit_sem); do {		if ((hdw->unit_number >= 0) &&		    (hdw->unit_number < PVR_NUM) &&		    (unit_pointers[hdw->unit_number] == hdw)) {			unit_pointers[hdw->unit_number] = 0;		}	} while (0); up(&pvr2_unit_sem);	kfree(hdw->controls);	if (hdw->std_defs) kfree(hdw->std_defs);	if (hdw->video_std_names) kfree(hdw->video_std_names);	kfree(hdw);}int pvr2_hdw_init_ok(struct pvr2_hdw *hdw){	return hdw->flag_init_ok;}int pvr2_hdw_dev_ok(struct pvr2_hdw *hdw){	return (hdw && hdw->flag_ok);}/* Called when hardware has been unplugged */void pvr2_hdw_disconnect(struct pvr2_hdw *hdw){	pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_disconnect(hdw=%p)",hdw);	LOCK_TAKE(hdw->big_lock);	LOCK_TAKE(hdw->ctl_lock);	pvr2_hdw_remove_usb_stuff(hdw);	LOCK_GIVE(hdw->ctl_lock);	LOCK_GIVE(hdw->big_lock);}static int pvr2_ctl_set_chanprog_id(struct pvr2_ctrl *cptr,int value){	/* This is a special case; the value to store is to an array, and	   the element to select is determined by PVR_CID_CHANPROG_ID. */	struct pvr2_hdw *hdw = cptr->hdw;	int id = hdw->controls[PVR2_CID_CHANPROG_ID].value;	if ((id < 1) || (id > FREQTABLE_SIZE)) return 0;	hdw->freqTable[id-1] = value;	if (hdw->controls[PVR2_CID_CHANNEL].value == id) {		/* If the current channel happens to be the slot we just		   set, then act like the current channel just got changed		   so we'll update that too. */		hdw->controls[PVR2_CID_CHANNEL].dirty = !0;	}	return 0;}static int pvr2_ctl_get_chanprog_id(struct pvr2_ctrl *cptr){	/* This is a special case; the value to return is from an array,	   and the element to select is determined by	   PVR_CID_CHANPROG_ID. */	struct pvr2_hdw *hdw = cptr->hdw;	int id = hdw->controls[PVR2_CID_CHANPROG_ID].value;	if ((id < 1) || (id > FREQTABLE_SIZE)) return 0;	return hdw->freqTable[id-1];}// Template data for possible enumerated video standardsstatic struct v4l2_standard pvr_standards[] = {	{		.id             = V4L2_STD_PAL_BG,		.frameperiod    =		{			.numerator  = 1,			.denominator= 25		},		.framelines     = 625,		.reserved       = {0,0,0,0}	}, {		.id             = V4L2_STD_PAL_I,		.frameperiod    =		{			.numerator  = 1,			.denominator= 25		},		.framelines     = 625,		.reserved       = {0,0,0,0}	}, {		.id             = V4L2_STD_PAL_DK,		.frameperiod    =		{			.numerator  = 1,			.denominator= 25		},		.framelines     = 625,		.reserved       = {0,0,0,0}	}, {		.id             = V4L2_STD_SECAM,		.frameperiod    =		{			.numerator  = 1,			.denominator= 25		},		.framelines     = 625,		.reserved       = {0,0,0,0}	}, {		.id             = V4L2_STD_NTSC_M,		.frameperiod    =		{			.numerator =  1001,			.denominator= 30000		},		.framelines     = 525,		.reserved       = {0,0,0,0}	}, {		.id             = V4L2_STD_PAL_M,		.frameperiod    =		{			.numerator =  1001,			.denominator= 30000		},		.framelines     = 525,		.reserved       = {0,0,0,0}	}};#define pvr_standards_cnt (sizeof(pvr_standards)/sizeof(pvr_standards[0]))struct name_data {	struct v4l2_standard *std;	unsigned int bcnt;	unsigned int scnt;};static void name_build(struct name_data *dp,const char *str){	if (!dp->bcnt) {		dp->bcnt = scnprintf(dp->std->name,				     sizeof(dp->std->name)-1,"%s",str);		dp->scnt = 0;		return;	}	dp->bcnt += scnprintf(dp->std->name+dp->bcnt,			      sizeof(dp->std->name)-(1+dp->bcnt),			      "%s%s",			      (dp->scnt ? "/" : "-"),str);	(dp->scnt)++;}// Generate a descriptive name for a given standardstatic void name_bucket(struct v4l2_standard *std){	struct name_data nd;	nd.std = std;	nd.bcnt = 0;	if (std->id & (V4L2_STD_PAL_B|		       V4L2_STD_PAL_B1|		       V4L2_STD_PAL_G|		       V4L2_STD_PAL_H|		       V4L2_STD_PAL_I|		       V4L2_STD_PAL_D|		       V4L2_STD_PAL_D1|		       V4L2_STD_PAL_K)) {		name_build(&nd,"PAL");		if (std->id & V4L2_STD_PAL_B) name_build(&nd,"B");		if (std->id & V4L2_STD_PAL_B1) name_build(&nd,"B1");		if (std->id & V4L2_STD_PAL_D) name_build(&nd,"D");		if (std->id & V4L2_STD_PAL_D1) name_build(&nd,"D1");		if (std->id & V4L2_STD_PAL_G) name_build(&nd,"G");		if (std->id & V4L2_STD_PAL_H) name_build(&nd,"H");		if (std->id & V4L2_STD_PAL_I) name_build(&nd,"I");		if (std->id & V4L2_STD_PAL_K) name_build(&nd,"K");		if (std->id & V4L2_STD_PAL_M) name_build(&nd,"M");		if (std->id & V4L2_STD_PAL_N) name_build(&nd,"N");		if (std->id & V4L2_STD_PAL_Nc) name_build(&nd,"Nc");		if (std->id & V4L2_STD_PAL_60) name_build(&nd,"60");		std->name[nd.bcnt] = 0;		return;	}	if (std->id & (V4L2_STD_NTSC_M|		       V4L2_STD_NTSC_M_JP|		       V4L2_STD_NTSC_443)) {		name_build(&nd,"NTSC");		if (std->id & V4L2_STD_NTSC_M) name_build(&nd,"M");		if (std->id & V4L2_STD_NTSC_M_JP) name_build(&nd,"Mjp");		if (std->id & V4L2_STD_NTSC_443) name_build(&nd,"443");		std->name[nd.bcnt] = 0;		return;	}	if (std->id & (V4L2_STD_SECAM_B|		       V4L2_STD_SECAM_D|		       V4L2_STD_SECAM_G|		       V4L2_STD_SECAM_H|		       V4L2_STD_SECAM_K|		       V4L2_STD_SECAM_K1|		       V4L2_STD_SECAM_L|		       V4L2_STD_SECAM_LC)) {		name_build(&nd,"SECAM");		if (std->id & V4L2_STD_SECAM_B) name_build(&nd,"B");		if (std->id & V4L2_STD_SECAM_D) name_build(&nd,"D");		if (std->id & V4L2_STD_SECAM_G) name_build(&nd,"G");		if (std->id & V4L2_STD_SECAM_H) name_build(&nd,"H");		if (std->id & V4L2_STD_SECAM_K) name_build(&nd,"K");		if (std->id & V4L2_STD_SECAM_K1) name_build(&nd,"K1");		if (std->id & V4L2_STD_SECAM_L) name_build(&nd,"L");		if (std->id & V4L2_STD_SECAM_LC) name_build(&nd,"LC");		std->name[nd.bcnt] = 0;		return;	}	std->name[0] = 0;}// Given a mask of viable video standards to choose from, generate an// appropriate array of v4l2_standard data that corresponds to it and set// up related state in the driver to match.void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw,int arg){	v4l2_std_id buckets[pvr_standards_cnt];	unsigned int idx1,idx2,std_cnt;	v4l2_std_id mmsk,amsk;	amsk = (v4l2_std_id)arg;	// Figure out which standard groups we can work with	std_cnt = 0;	mmsk = 0;	for (idx1 = 0; idx1 < pvr_standards_cnt; idx1++) {		buckets[idx1] = pvr_standards[idx1].id & amsk;		if (!buckets[idx1]) continue;		mmsk |= buckets[idx1];		amsk &= ~buckets[idx1];		std_cnt++;	}	if (amsk) {		pvr2_trace(			PVR2_TRACE_ERROR_LEGS,			"Failed to bucketize the following standards: 0x%llx",			amsk);	}	if (hdw->std_defs) {		kfree(hdw->std_defs);		hdw->std_defs = 0;	}	if (hdw->video_std_names) {		kfree(hdw->video_std_names);		hdw->video_std_names = 0;	}	hdw->std_cnt = 0;	if (!std_cnt) {		pvr2_trace(			PVR2_TRACE_ERROR_LEGS,			"Failed to identify any viable standard groups");		hdw->video_std_avail = 0;		pvr2_hdw_internal_set_std_cur(hdw,0);		return;	}	if (std_cnt) {		// Allocate new video standard array		hdw->std_defs = kmalloc(sizeof(struct v4l2_standard) * std_cnt,					GFP_KERNEL);		hdw->std_cnt = std_cnt;		memset(hdw->std_defs,0,sizeof(struct v4l2_standard) * std_cnt);		hdw->video_std_names = kmalloc(sizeof(char *) * std_cnt,					       GFP_KERNEL);		memset(hdw->video_std_names,0,sizeof(char *) * std_cnt);		idx2 = 0;		// Initialize video standard array		for (idx1 = 0; idx1 < pvr_standards_cnt; idx1++) {			if (!buckets[idx1]) continue;			memcpy(hdw->std_defs + idx2,			       pvr_standards + idx1,			       sizeof(struct v4l2_standard));			hdw->std_defs[idx2].id = buckets[idx1];			idx2++;		}		// Generate a name for each known video standard		for (idx1 = 0; idx1 < std_cnt; idx1++) {			name_bucket(hdw->std_defs + idx1);			hdw->video_std_names[idx1] =				hdw->std_defs[idx1].name;		}		// Set up the dynamic control for this standard		hdw->video_std_enum.value_defs_ptr = hdw->video_std_names;		hdw->video_std_enum.value_defs_count = std_cnt;	}	hdw->video_std_avail = mmsk;	if (!(hdw->video_std_avail & hdw->video_std_cur)) {		// Reselect standard if there isn't one that matches...		pvr2_hdw_internal_set_stdenum_cur(hdw,0);	}}unsigned int pvr2_hdw_get_stdenum_count(struct pvr2_hdw *hdw){	return hdw->std_cnt;}const struct v4l2_standard *pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw,						       unsigned int idx){	if (idx >= hdw->std_cnt) return 0;	return hdw->std_defs + idx;}int pvr2_hdw_internal_set_stdenum_cur(struct pvr2_hdw *hdw,int val){	if (val < 0) return -EINVAL;	if (val >= hdw->std_cnt) return -EINVAL;	pvr2_hdw_internal_set_std_cur(hdw,hdw->std_defs[val].id);	return 0;}void pvr2_hdw_internal_set_std_cur(struct pvr2_hdw *hdw,int val){	unsigned int idx;	v4l2_std_id msk,id;	id = (v4l2_std_id)val;	// Only select from available standards	id &= hdw->video_std_avail;	// Only select a single bit	for (idx = 0, msk = 1; msk; idx++, msk <<= 1) {		if (!(id & msk)) continue;		id = msk;		break;	}	// Get out if nothing found	if (!msk) return;	// Fix up standard group now	hdw->video_std_cur = id;	hdw->controls[PVR2_CID_STDCUR].value = id;	hdw->controls[PVR2_CID_STDCUR].dirty = !0;	for (idx = 0; idx < hdw->std_cnt; idx++) {		if (hdw->std_defs[idx].id & id) {			hdw->std_id = idx;			return;		}	}	// Should never really get here, but just in case...	hdw->std_id = 0;}static int pvr2_ctl_set_stdcur(struct pvr2_ctrl *cptr,int val){	pvr2_hdw_internal_set_std_cur(cptr->hdw,val);	return 0;}static int pvr2_ctl_get_stdcur(struct pvr2_ctrl *cptr){	return (int)(cptr->hdw->video_std_cur);}static int pvr2_ctl_set_stdenumcur(struct pvr2_ctrl *cptr,int val){	if (val < 0) return -EINVAL;	if (val >= cptr->hdw->std_cnt) return -EINVAL;	cptr->hdw->std_id = val;	pvr2_hdw_internal_set_std_cur(cptr->hdw,				      cptr->hdw->std_id);	return 0;}static int pvr2_ctl_get_stdenumcur(struct pvr2_ctrl *cptr){	return cptr->hdw->std_id;}static int pvr2_ctl_get_stdavail(struct pvr2_ctrl *cptr){	return (int)(cptr->hdw->video_std_avail);}/* Get the number of defined controls */unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *hdw){	return CTRL_COUNT;}/* Retrieve a control handle given its index (0..count-1) */struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *hdw,					     unsigned int idx){	if (idx < 0) return 0;	if (idx >= CTRL_COUNT) return 0;	return hdw->controls + idx;}/* Given an ID, retrieve the control structure associated with it. */struct pvr2_ctrl *pvr2_hdw_get_ctrl(struct pvr2_hdw *hdw,unsigned int ctl_id){	struct pvr2_ctrl *cptr;	unsigned int idx;	int i;	/* This could be made a lot more efficient, but for now... */	for (idx = 0; idx < CTRL_COUNT; idx++) {		cptr = hdw->controls + idx;		i = cptr->ctl_def->id;		if (i && (i == ctl_id)) return cptr;

⌨️ 快捷键说明

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