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

📄 pvrusb2-hdw.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		}		pvr2_stream_setup(hdw->vid_stream,hdw->usb_dev,				  PVR2_VID_ENDPOINT,idx);	}	if (!pvr2_hdw_dev_ok(hdw)) return;	/* Make sure everything is up to date */	pvr2_i2c_core_sync(hdw);	if (!pvr2_hdw_dev_ok(hdw)) return;	hdw->flag_init_ok = !0;}int pvr2_hdw_setup(struct pvr2_hdw *hdw){	pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) begin",hdw);	LOCK_TAKE(hdw->big_lock); do {		pvr2_hdw_setup_low(hdw);		pvr2_trace(PVR2_TRACE_INIT,			   "pvr2_hdw_setup(hdw=%p) done, ok=%d init_ok=%d",			   hdw,hdw->flag_ok,hdw->flag_init_ok);		if (pvr2_hdw_dev_ok(hdw)) {			if (pvr2_hdw_init_ok(hdw)) {				pvr2_trace(					PVR2_TRACE_INFO,					"Device initialization"					" completed successfully.");				break;			}			if (hdw->fw1_state == FW1_STATE_RELOAD) {				pvr2_trace(					PVR2_TRACE_INFO,					"Device microcontroller firmware"					" (re)loaded; it should now reset"					" and reconnect.");				break;			}			pvr2_trace(				PVR2_TRACE_ERROR_LEGS,				"Device initialization was not successful.");			if (hdw->fw1_state == FW1_STATE_MISSING) {				pvr2_trace(					PVR2_TRACE_ERROR_LEGS,					"Giving up since device"					" microcontroller firmware"					" appears to be missing.");				break;			}		}		if (procreload) {			pvr2_trace(				PVR2_TRACE_ERROR_LEGS,				"Attempting pvrusb2 recovery by reloading"				" primary firmware.");			pvr2_trace(				PVR2_TRACE_ERROR_LEGS,				"If this works, device should disconnect"				" and reconnect in a sane state.");			hdw->fw1_state = FW1_STATE_UNKNOWN;			pvr2_upload_firmware1(hdw);		} else {			pvr2_trace(				PVR2_TRACE_ERROR_LEGS,				"***WARNING*** pvrusb2 device hardware"				" appears to be jammed"				" and I can't clear it.");			pvr2_trace(				PVR2_TRACE_ERROR_LEGS,				"You might need to power cycle"				" the pvrusb2 device"				" in order to recover.");		}	} while (0); LOCK_GIVE(hdw->big_lock);	pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) end",hdw);	return hdw->flag_init_ok;}/* Create and return a structure for interacting with the underlying   hardware */struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,				 const struct usb_device_id *devid){	unsigned int idx,cnt1,cnt2;	struct pvr2_hdw *hdw;	unsigned int hdw_type;	int valid_std_mask;	struct pvr2_ctrl *cptr;	__u8 ifnum;	struct v4l2_queryctrl qctrl;	struct pvr2_ctl_info *ciptr;	hdw_type = devid - pvr2_device_table;	if (hdw_type >= ARRAY_SIZE(pvr2_device_names)) {		pvr2_trace(PVR2_TRACE_ERROR_LEGS,			   "Bogus device type of %u reported",hdw_type);		return NULL;	}	hdw = kzalloc(sizeof(*hdw),GFP_KERNEL);	pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"",		   hdw,pvr2_device_names[hdw_type]);	if (!hdw) goto fail;	hdw->tuner_signal_stale = !0;	cx2341x_fill_defaults(&hdw->enc_ctl_state);	hdw->control_cnt = CTRLDEF_COUNT;	hdw->control_cnt += MPEGDEF_COUNT;	hdw->controls = kzalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt,				GFP_KERNEL);	if (!hdw->controls) goto fail;	hdw->hdw_type = hdw_type;	for (idx = 0; idx < hdw->control_cnt; idx++) {		cptr = hdw->controls + idx;		cptr->hdw = hdw;	}	for (idx = 0; idx < 32; idx++) {		hdw->std_mask_ptrs[idx] = hdw->std_mask_names[idx];	}	for (idx = 0; idx < CTRLDEF_COUNT; idx++) {		cptr = hdw->controls + idx;		cptr->info = control_defs+idx;	}	/* Define and configure additional controls from cx2341x module. */	hdw->mpeg_ctrl_info = kzalloc(		sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL);	if (!hdw->mpeg_ctrl_info) goto fail;	for (idx = 0; idx < MPEGDEF_COUNT; idx++) {		cptr = hdw->controls + idx + CTRLDEF_COUNT;		ciptr = &(hdw->mpeg_ctrl_info[idx].info);		ciptr->desc = hdw->mpeg_ctrl_info[idx].desc;		ciptr->name = mpeg_ids[idx].strid;		ciptr->v4l_id = mpeg_ids[idx].id;		ciptr->skip_init = !0;		ciptr->get_value = ctrl_cx2341x_get;		ciptr->get_v4lflags = ctrl_cx2341x_getv4lflags;		ciptr->is_dirty = ctrl_cx2341x_is_dirty;		if (!idx) ciptr->clear_dirty = ctrl_cx2341x_clear_dirty;		qctrl.id = ciptr->v4l_id;		cx2341x_ctrl_query(&hdw->enc_ctl_state,&qctrl);		if (!(qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY)) {			ciptr->set_value = ctrl_cx2341x_set;		}		strncpy(hdw->mpeg_ctrl_info[idx].desc,qctrl.name,			PVR2_CTLD_INFO_DESC_SIZE);		hdw->mpeg_ctrl_info[idx].desc[PVR2_CTLD_INFO_DESC_SIZE-1] = 0;		ciptr->default_value = qctrl.default_value;		switch (qctrl.type) {		default:		case V4L2_CTRL_TYPE_INTEGER:			ciptr->type = pvr2_ctl_int;			ciptr->def.type_int.min_value = qctrl.minimum;			ciptr->def.type_int.max_value = qctrl.maximum;			break;		case V4L2_CTRL_TYPE_BOOLEAN:			ciptr->type = pvr2_ctl_bool;			break;		case V4L2_CTRL_TYPE_MENU:			ciptr->type = pvr2_ctl_enum;			ciptr->def.type_enum.value_names =				cx2341x_ctrl_get_menu(ciptr->v4l_id);			for (cnt1 = 0;			     ciptr->def.type_enum.value_names[cnt1] != NULL;			     cnt1++) { }			ciptr->def.type_enum.count = cnt1;			break;		}		cptr->info = ciptr;	}	// Initialize video standard enum dynamic control	cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDENUM);	if (cptr) {		memcpy(&hdw->std_info_enum,cptr->info,		       sizeof(hdw->std_info_enum));		cptr->info = &hdw->std_info_enum;	}	// Initialize control data regarding video standard masks	valid_std_mask = pvr2_std_get_usable();	for (idx = 0; idx < 32; idx++) {		if (!(valid_std_mask & (1 << idx))) continue;		cnt1 = pvr2_std_id_to_str(			hdw->std_mask_names[idx],			sizeof(hdw->std_mask_names[idx])-1,			1 << idx);		hdw->std_mask_names[idx][cnt1] = 0;	}	cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDAVAIL);	if (cptr) {		memcpy(&hdw->std_info_avail,cptr->info,		       sizeof(hdw->std_info_avail));		cptr->info = &hdw->std_info_avail;		hdw->std_info_avail.def.type_bitmask.bit_names =			hdw->std_mask_ptrs;		hdw->std_info_avail.def.type_bitmask.valid_bits =			valid_std_mask;	}	cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR);	if (cptr) {		memcpy(&hdw->std_info_cur,cptr->info,		       sizeof(hdw->std_info_cur));		cptr->info = &hdw->std_info_cur;		hdw->std_info_cur.def.type_bitmask.bit_names =			hdw->std_mask_ptrs;		hdw->std_info_avail.def.type_bitmask.valid_bits =			valid_std_mask;	}	hdw->eeprom_addr = -1;	hdw->unit_number = -1;	hdw->v4l_minor_number_video = -1;	hdw->v4l_minor_number_vbi = -1;	hdw->v4l_minor_number_radio = -1;	hdw->ctl_write_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);	if (!hdw->ctl_write_buffer) goto fail;	hdw->ctl_read_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);	if (!hdw->ctl_read_buffer) goto fail;	hdw->ctl_write_urb = usb_alloc_urb(0,GFP_KERNEL);	if (!hdw->ctl_write_urb) goto fail;	hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL);	if (!hdw->ctl_read_urb) goto fail;	mutex_lock(&pvr2_unit_mtx); do {		for (idx = 0; idx < PVR_NUM; idx++) {			if (unit_pointers[idx]) continue;			hdw->unit_number = idx;			unit_pointers[idx] = hdw;			break;		}	} while (0); mutex_unlock(&pvr2_unit_mtx);	cnt1 = 0;	cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"pvrusb2");	cnt1 += cnt2;	if (hdw->unit_number >= 0) {		cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"_%c",				 ('a' + hdw->unit_number));		cnt1 += cnt2;	}	if (cnt1 >= sizeof(hdw->name)) cnt1 = sizeof(hdw->name)-1;	hdw->name[cnt1] = 0;	pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s",		   hdw->unit_number,hdw->name);	hdw->tuner_type = -1;	hdw->flag_ok = !0;	/* Initialize the mask of subsystems that we will shut down when we	   stop streaming. */	hdw->subsys_stream_mask = PVR2_SUBSYS_RUN_ALL;	hdw->subsys_stream_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);	pvr2_trace(PVR2_TRACE_INIT,"subsys_stream_mask: 0x%lx",		   hdw->subsys_stream_mask);	hdw->usb_intf = intf;	hdw->usb_dev = interface_to_usbdev(intf);	scnprintf(hdw->bus_info,sizeof(hdw->bus_info),		  "usb %s address %d",		  hdw->usb_dev->dev.bus_id,		  hdw->usb_dev->devnum);	ifnum = hdw->usb_intf->cur_altsetting->desc.bInterfaceNumber;	usb_set_interface(hdw->usb_dev,ifnum,0);	mutex_init(&hdw->ctl_lock_mutex);	mutex_init(&hdw->big_lock_mutex);	return hdw; fail:	if (hdw) {		usb_free_urb(hdw->ctl_read_urb);		usb_free_urb(hdw->ctl_write_urb);		kfree(hdw->ctl_read_buffer);		kfree(hdw->ctl_write_buffer);		kfree(hdw->controls);		kfree(hdw->mpeg_ctrl_info);		kfree(hdw);	}	return NULL;}/* Remove _all_ associations between this driver and the underlying USB   layer. */static 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 = NULL;	}	if (hdw->ctl_write_urb) {		usb_kill_urb(hdw->ctl_write_urb);		usb_free_urb(hdw->ctl_write_urb);		hdw->ctl_write_urb = NULL;	}	if (hdw->ctl_read_buffer) {		kfree(hdw->ctl_read_buffer);		hdw->ctl_read_buffer = NULL;	}	if (hdw->ctl_write_buffer) {		kfree(hdw->ctl_write_buffer);		hdw->ctl_write_buffer = NULL;	}	pvr2_hdw_render_useless_unlocked(hdw);	hdw->flag_disconnected = !0;	hdw->usb_dev = NULL;	hdw->usb_intf = NULL;}/* Destroy hardware interaction structure */void pvr2_hdw_destroy(struct pvr2_hdw *hdw){	if (!hdw) return;	pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw);	if (hdw->fw_buffer) {		kfree(hdw->fw_buffer);		hdw->fw_buffer = NULL;	}	if (hdw->vid_stream) {		pvr2_stream_destroy(hdw->vid_stream);		hdw->vid_stream = NULL;	}	if (hdw->decoder_ctrl) {		hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt);	}	pvr2_i2c_core_done(hdw);	pvr2_hdw_remove_usb_stuff(hdw);	mutex_lock(&pvr2_unit_mtx); do {		if ((hdw->unit_number >= 0) &&		    (hdw->unit_number < PVR_NUM) &&		    (unit_pointers[hdw->unit_number] == hdw)) {			unit_pointers[hdw->unit_number] = NULL;		}	} while (0); mutex_unlock(&pvr2_unit_mtx);	kfree(hdw->controls);	kfree(hdw->mpeg_ctrl_info);	kfree(hdw->std_defs);	kfree(hdw->std_enum_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);}// Attempt to autoselect an appropriate value for std_enum_cur given// whatever is currently in std_mask_curstatic void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw){	unsigned int idx;	for (idx = 1; idx < hdw->std_enum_cnt; idx++) {		if (hdw->std_defs[idx-1].id == hdw->std_mask_cur) {			hdw->std_enum_cur = idx;			return;		}	}	hdw->std_enum_cur = 0;}// Calculate correct set of enumerated standards based on currently known// set of available standards bits.static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw){	struct v4l2_standard *newstd;	unsigned int std_cnt;	unsigned int idx;	newstd = pvr2_std_create_enum(&std_cnt,hdw->std_mask_avail);	if (hdw->std_defs) {		kfree(hdw->std_defs);		hdw->std_defs = NULL;	}	hdw->std_enum_cnt = 0;	if (hdw->std_enum_names) {		kfree(hdw->std_enum_names);		hdw->std_enum_names = NULL;	}	if (!std_cnt) {		pvr2_trace(			PVR2_TRACE_ERROR_LEGS,			"WARNING: Failed to identify any viable standards");	}	hdw->std_enum_names = kmalloc(sizeof(char *)*(std_cnt+1),GFP_KERNEL);	hdw->std_enum_names[0] = "none";	for (idx = 0; idx < std_cnt; idx++) {		hdw->std_enum_names[idx+1] =			newstd[idx].name;	}	// Set up the dynamic control for this standard	hdw->std_info_enum.def.type_enum.value_names = hdw->std_enum_names;	hdw->std_info_enum.def.type_enum.count = std_cnt+1;	hdw->std_defs = newstd;	hdw->std_enum_cnt = std_cnt+1;	hdw->std_enum_cur = 0;	hdw->std_info_cur.def.type_bitmask.valid_bits = hdw->std_mask_avail;}int pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw,			       struct v4l2_standard *std,			       unsigned int idx){	int ret = -EINVAL;	if (!idx) return ret;	LOCK_TAKE(hdw->big_lock); do {		if (idx >= hdw->std_enum_cnt) break;		idx--;		memcpy(std,hdw->std_defs+idx,sizeof(*std));		ret = 0;	} while (0); LOCK_GIVE(hdw->big_lock);	return ret;}/* Get the number of defined controls */unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *hdw){	return hdw->control_cnt;}/* 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 >= hdw->control_cnt) return NULL;	return hdw->controls + idx;}/* Retrieve a control handle given its index (0..count-1) */struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(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 < hdw->control_cnt; idx++) {		cptr = hdw->controls + idx;		i = cptr->info->internal_id;		if (i && (i == ctl_id)) return cptr;	}	return NULL;}/* Given a V4L ID, retrieve the control structure associated with it. */struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *hdw,u

⌨️ 快捷键说明

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