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

📄 saa5246a.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (i2c_senddata(t, SAA5246A_REGISTER_R8,		dau_no |		R8_DO_NOT_CLEAR_MEMORY,		R9_CURSER_ROW_25,		R10_CURSER_COLUMN_0,		COMMAND_END) ||		i2c_getdata(t, 10, infobits))	{		return -EIO;	}	info->pagenum = saa5246a_extract_pagenum_from_infobits(infobits);	info->hour    = saa5246a_extract_hour_from_infobits(infobits);	info->minute  = saa5246a_extract_minutes_from_infobits(infobits);	info->charset = ((infobits[7] & ROW25_COLUMN7_CHARACTER_SET) >> 1);	info->delete = !!(infobits[3] & ROW25_COLUMN3_DELETE_PAGE);	info->headline = !!(infobits[5] & ROW25_COLUMN5_INSERT_HEADLINE);	info->subtitle = !!(infobits[5] & ROW25_COLUMN5_INSERT_SUBTITLE);	info->supp_header = !!(infobits[6] & ROW25_COLUMN6_SUPPRESS_HEADER);	info->update = !!(infobits[6] & ROW25_COLUMN6_UPDATE_PAGE);	info->inter_seq = !!(infobits[6] & ROW25_COLUMN6_INTERRUPTED_SEQUENCE);	info->dis_disp = !!(infobits[6] & ROW25_COLUMN6_SUPPRESS_DISPLAY);	info->serial = !!(infobits[7] & ROW25_COLUMN7_SERIAL_MODE);	info->notfound = !!(infobits[8] & ROW25_COLUMN8_PAGE_NOT_FOUND);	info->pblf = !!(infobits[9] & ROW25_COLUMN9_PAGE_BEING_LOOKED_FOR);	info->hamming = 0;	for (column = 0; column <= 7; column++) {		if (infobits[column] & ROW25_COLUMN0_TO_7_HAMMING_ERROR) {			info->hamming = 1;			break;		}	}	if (!info->hamming && !info->notfound)		t->is_searching[dau_no] = FALSE;	return 0;}/* Reads 1 videotext page buffer of the SAA5246A. * * req is used both as input and as output. It contains information which part * must be read. The videotext page is copied into req->buffer. * * Return value: 0 if successful */static inline int saa5246a_get_page(struct saa5246a_device *t,	vtx_pagereq_t *req){	int start, end, size;	char *buf;	int err;	if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS ||	    req->start < 0 || req->start > req->end || req->end >= VTX_PAGESIZE)		return -EINVAL;	buf = kmalloc(VTX_PAGESIZE, GFP_KERNEL);	if (!buf)		return -ENOMEM;	/* Read "normal" part of page */	err = -EIO;	end = min(req->end, VTX_PAGESIZE - 1);	if (i2c_senddata(t, SAA5246A_REGISTER_R8,			req->pgbuf | R8_DO_NOT_CLEAR_MEMORY,			ROW(req->start), COLUMN(req->start), COMMAND_END))		goto out;	if (i2c_getdata(t, end - req->start + 1, buf))		goto out;	err = -EFAULT;	if (copy_to_user(req->buffer, buf, end - req->start + 1))		goto out;	/* Always get the time from buffer 4, since this stupid SAA5246A only	 * updates the currently displayed buffer...	 */	if (REQ_CONTAINS_TIME(req)) {		start = max(req->start, POS_TIME_START);		end   = min(req->end,   POS_TIME_END);		size = end - start + 1;		err = -EINVAL;		if (size < 0)			goto out;		err = -EIO;		if (i2c_senddata(t, SAA5246A_REGISTER_R8,				R8_ACTIVE_CHAPTER_4 | R8_DO_NOT_CLEAR_MEMORY,				R9_CURSER_ROW_0, start, COMMAND_END))			goto out;		if (i2c_getdata(t, size, buf))			goto out;		err = -EFAULT;		if (copy_to_user(req->buffer + start - req->start, buf, size))			goto out;	}	/* Insert the header from buffer 4 only, if acquisition circuit is still searching for a page */	if (REQ_CONTAINS_HEADER(req) && t->is_searching[req->pgbuf]) {		start = max(req->start, POS_HEADER_START);		end   = min(req->end,   POS_HEADER_END);		size = end - start + 1;		err = -EINVAL;		if (size < 0)			goto out;		err = -EIO;		if (i2c_senddata(t, SAA5246A_REGISTER_R8,				R8_ACTIVE_CHAPTER_4 | R8_DO_NOT_CLEAR_MEMORY,				R9_CURSER_ROW_0, start, COMMAND_END))			goto out;		if (i2c_getdata(t, end - start + 1, buf))			goto out;		err = -EFAULT;		if (copy_to_user(req->buffer + start - req->start, buf, size))			goto out;	}	err = 0;out:	kfree(buf);	return err;}/* Stops the acquisition circuit given in dau_no. The page buffer associated * with this acquisition circuit will no more be updated. The other daus are * not affected. * * Return value: 0 if successful */static inline int saa5246a_stop_dau(struct saa5246a_device *t,    unsigned char dau_no){	if (dau_no >= NUM_DAUS)		return -EINVAL;	if (i2c_senddata(t, SAA5246A_REGISTER_R2,		R2_IN_R3_SELECT_PAGE_HUNDREDS |		dau_no << 4 |		R2_BANK_0 |		R2_HAMMING_CHECK_OFF,		R3_PAGE_HUNDREDS_0 |		R3_HOLD_PAGE |		R3_PAGE_HUNDREDS_DO_NOT_CARE,		COMMAND_END))	{		return -EIO;	}	t->is_searching[dau_no] = FALSE;	return 0;}/*  Handles ioctls defined in videotext.h * *  Returns 0 if successful */static int do_saa5246a_ioctl(struct inode *inode, struct file *file,			    unsigned int cmd, void *arg){	struct video_device *vd = video_devdata(file);	struct saa5246a_device *t=vd->priv;	switch(cmd)	{		case VTXIOCGETINFO:		{			vtx_info_t *info = arg;			info->version_major = MAJOR_VERSION;			info->version_minor = MINOR_VERSION;			info->numpages = NUM_DAUS;			return 0;		}		case VTXIOCCLRPAGE:		{			vtx_pagereq_t *req = arg;			if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)				return -EINVAL;			memset(t->pgbuf[req->pgbuf], ' ', sizeof(t->pgbuf[0]));			return 0;		}		case VTXIOCCLRFOUND:		{			vtx_pagereq_t *req = arg;			if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)				return -EINVAL;			return(saa5246a_clear_found_bit(t, req->pgbuf));		}		case VTXIOCPAGEREQ:		{			vtx_pagereq_t *req = arg;			return(saa5246a_request_page(t, req));		}		case VTXIOCGETSTAT:		{			vtx_pagereq_t *req = arg;			vtx_pageinfo_t info;			int rval;			if ((rval = saa5246a_get_status(t, &info, req->pgbuf)))				return rval;			if(copy_to_user(req->buffer, &info,				sizeof(vtx_pageinfo_t)))				return -EFAULT;			return 0;		}		case VTXIOCGETPAGE:		{			vtx_pagereq_t *req = arg;			return(saa5246a_get_page(t, req));		}		case VTXIOCSTOPDAU:		{			vtx_pagereq_t *req = arg;			return(saa5246a_stop_dau(t, req->pgbuf));		}		case VTXIOCPUTPAGE:		case VTXIOCSETDISP:		case VTXIOCPUTSTAT:			return 0;		case VTXIOCCLRCACHE:		{			return 0;		}		case VTXIOCSETVIRT:		{			/* I do not know what "virtual mode" means */			return 0;		}	}	return -EINVAL;}/* * Translates old vtx IOCTLs to new ones * * This keeps new kernel versions compatible with old userspace programs. */static inline unsigned int vtx_fix_command(unsigned int cmd){	switch (cmd) {	case VTXIOCGETINFO_OLD:		cmd = VTXIOCGETINFO;		break;	case VTXIOCCLRPAGE_OLD:		cmd = VTXIOCCLRPAGE;		break;	case VTXIOCCLRFOUND_OLD:		cmd = VTXIOCCLRFOUND;		break;	case VTXIOCPAGEREQ_OLD:		cmd = VTXIOCPAGEREQ;		break;	case VTXIOCGETSTAT_OLD:		cmd = VTXIOCGETSTAT;		break;	case VTXIOCGETPAGE_OLD:		cmd = VTXIOCGETPAGE;		break;	case VTXIOCSTOPDAU_OLD:		cmd = VTXIOCSTOPDAU;		break;	case VTXIOCPUTPAGE_OLD:		cmd = VTXIOCPUTPAGE;		break;	case VTXIOCSETDISP_OLD:		cmd = VTXIOCSETDISP;		break;	case VTXIOCPUTSTAT_OLD:		cmd = VTXIOCPUTSTAT;		break;	case VTXIOCCLRCACHE_OLD:		cmd = VTXIOCCLRCACHE;		break;	case VTXIOCSETVIRT_OLD:		cmd = VTXIOCSETVIRT;		break;	}	return cmd;}/* *	Handle the locking */static int saa5246a_ioctl(struct inode *inode, struct file *file,			 unsigned int cmd, unsigned long arg){	struct video_device *vd = video_devdata(file);	struct saa5246a_device *t = vd->priv;	int err;	cmd = vtx_fix_command(cmd);	down(&t->lock);	err = video_usercopy(inode, file, cmd, arg, do_saa5246a_ioctl);	up(&t->lock);	return err;}static int saa5246a_open(struct inode *inode, struct file *file){	struct video_device *vd = video_devdata(file);	struct saa5246a_device *t = vd->priv;	int err;	err = video_exclusive_open(inode,file);	if (err < 0)		return err;	if (t->client==NULL) {		err = -ENODEV;		goto fail;	}	if (i2c_senddata(t, SAA5246A_REGISTER_R0,		R0_SELECT_R11 |		R0_PLL_TIME_CONSTANT_LONG |		R0_ENABLE_nODD_EVEN_OUTPUT |		R0_ENABLE_HDR_POLL |		R0_DO_NOT_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED |		R0_NO_FREE_RUN_PLL |		R0_NO_AUTOMATIC_FASTEXT_PROMPT,		R1_NON_INTERLACED_312_312_LINES |		R1_DEW |		R1_EXTENDED_PACKET_DISABLE |		R1_DAUS_ALL_ON |		R1_8_BITS_NO_PARITY |		R1_VCS_TO_SCS,		COMMAND_END) ||		i2c_senddata(t, SAA5246A_REGISTER_R4,		/* We do not care much for the TV display but nevertheless we		 * need the currently displayed page later because only on that		 * page the time is updated. */		R4_DISPLAY_PAGE_4,		COMMAND_END))	{		err = -EIO;		goto fail;	}	return 0;fail:	video_exclusive_release(inode,file);	return err;}static int saa5246a_release(struct inode *inode, struct file *file){	struct video_device *vd = video_devdata(file);	struct saa5246a_device *t = vd->priv;	/* Stop all acquisition circuits. */	i2c_senddata(t, SAA5246A_REGISTER_R1,		R1_INTERLACED_312_AND_HALF_312_AND_HALF_LINES |		R1_DEW |		R1_EXTENDED_PACKET_DISABLE |		R1_DAUS_ALL_OFF |		R1_8_BITS_NO_PARITY |		R1_VCS_TO_SCS,		COMMAND_END);	video_exclusive_release(inode,file);	return 0;}static int __init init_saa_5246a (void){	printk(KERN_INFO		"SAA5246A (or compatible) Teletext decoder driver version %d.%d\n",		MAJOR_VERSION, MINOR_VERSION);	return i2c_add_driver(&i2c_driver_videotext);}static void __exit cleanup_saa_5246a (void){	i2c_del_driver(&i2c_driver_videotext);}module_init(init_saa_5246a);module_exit(cleanup_saa_5246a);static struct file_operations saa_fops = {	.owner	 = THIS_MODULE,	.open	 = saa5246a_open,	.release = saa5246a_release,	.ioctl	 = saa5246a_ioctl,	.llseek	 = no_llseek,};static struct video_device saa_template ={	.owner	  = THIS_MODULE,	.name	  = IF_NAME,	.type	  = VID_TYPE_TELETEXT,	.hardware = VID_HARDWARE_SAA5249,	.fops	  = &saa_fops,	.release  = video_device_release,	.minor    = -1,};

⌨️ 快捷键说明

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