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

📄 bttv.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
			}			else v.mode = VIDEO_SOUND_MONO;			if(copy_to_user(arg,&v,sizeof(v)))				return -EFAULT;			return 0;		}		case VIDIOCSAUDIO:		{			struct video_audio v;			if(copy_from_user(&v,arg, sizeof(v)))				return -EFAULT;			if(v.flags&VIDEO_AUDIO_MUTE)				audio(btv, AUDIO_MUTE); 			/* One audio source per tuner */ 			/* if(v.audio!=0) */			/* ADSTech TV card has more than one */			if(v.audio<0 || v.audio >= tvcards[btv->type].audio_inputs)				return -EINVAL;			bt848_muxsel(btv,v.audio);			if(!(v.flags&VIDEO_AUDIO_MUTE))				audio(btv, AUDIO_UNMUTE);			if (btv->audio_chip == TDA9850) {				unsigned char con3 = 0;				if (v.mode & VIDEO_SOUND_LANG1)					con3 = 0x80;	/* sap */				if (v.mode & VIDEO_SOUND_STEREO)					con3 = 0x40;	/* stereo */				I2CWrite(&(btv->i2c), I2C_TDA9850,					TDA9850_CON3, con3, 1);			}			if (btv->have_msp3400) 			{                                i2c_control_device(&(btv->i2c),                                                I2C_DRIVERID_MSP3400,                                                MSP_SET_VOLUME,&(v.volume));                                i2c_control_device(&(btv->i2c),                                                I2C_DRIVERID_MSP3400,                                                MSP_SET_BASS,&(v.bass));                                i2c_control_device(&(btv->i2c),                                                I2C_DRIVERID_MSP3400,                                                MSP_SET_TREBLE,&(v.treble));                        	i2c_control_device(&(btv->i2c),                                		I2C_DRIVERID_MSP3400,                                		MSP_SET_STEREO,&(v.mode));			}			btv->audio_dev=v;			return 0;		}	        case VIDIOCSYNC:			if(copy_from_user((void *)&i,arg,sizeof(int)))				return -EFAULT;/*                        if(i>1 || i<0)                                return -EINVAL;*/                        switch (btv->frame_stat[i]) {                        case GBUFFER_UNUSED:                                return -EINVAL;                        case GBUFFER_GRABBING:                        	while(btv->frame_stat[i]==GBUFFER_GRABBING) { 			        	interruptible_sleep_on(&btv->capq); 			        	if(signal_pending(current)) 			        		return -EINTR; 			        }                                /* fall */                        case GBUFFER_DONE:                                btv->frame_stat[i] = GBUFFER_UNUSED;                                break;                        }                        return 0;		case BTTV_WRITEE:#if LINUX_VERSION_CODE >= 0x020100			if(!capable(CAP_SYS_ADMIN))#else			if(!suser())#endif				return -EPERM;			if(copy_from_user((void *) eedata, (void *) arg, 256))				return -EFAULT;			writeee(&(btv->i2c), eedata);			return 0;		case BTTV_READEE:#if LINUX_VERSION_CODE >= 0x020100			if(!capable(CAP_SYS_ADMIN))#else			if(!suser())#endif				return -EPERM;			readee(&(btv->i2c), eedata);			if(copy_to_user((void *) arg, (void *) eedata, 256))				return -EFAULT;			break;                case BTTV_FIELDNR: 			if(copy_to_user((void *) arg, (void *) &btv->last_field,                                         sizeof(btv->last_field)))				return -EFAULT;                        break;                      case BTTV_PLLSET: {                        struct bttv_pll_info p;#if LINUX_VERSION_CODE >= 0x020100			if(!capable(CAP_SYS_ADMIN))#else			if(!suser())#endif                                return -EPERM;                        if(copy_from_user(&p , (void *) arg, sizeof(btv->pll)))				return -EFAULT;                        btv->pll.pll_ifreq = p.pll_ifreq;                        btv->pll.pll_ofreq = p.pll_ofreq;                        btv->pll.pll_crystal = p.pll_crystal;			break;                }							        case VIDIOCMCAPTURE:		{                        struct video_mmap vm;			if(copy_from_user((void *) &vm, (void *) arg, sizeof(vm)))				return -EFAULT;                        if (btv->frame_stat[vm.frame] == GBUFFER_GRABBING)                                return -EBUSY;		        return vgrab(btv, &vm);		}				case VIDIOCGMBUF:		{			struct video_mbuf vm;			memset(&vm, 0 , sizeof(vm));			vm.size=BTTV_MAX_FBUF*2;			vm.frames=2;			vm.offsets[0]=0;			vm.offsets[1]=BTTV_MAX_FBUF;			if(copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))				return -EFAULT;			return 0;		}				case VIDIOCGUNIT:		{			struct video_unit vu;			vu.video=btv->video_dev.minor;			vu.vbi=btv->vbi_dev.minor;			if(btv->radio_dev.minor!=-1)				vu.radio=btv->radio_dev.minor;			else				vu.radio=VIDEO_NO_UNIT;			vu.audio=VIDEO_NO_UNIT;			if(btv->have_msp3400)			{				i2c_control_device(&(btv->i2c), I2C_DRIVERID_MSP3400,					MSP_GET_UNIT, &vu.audio);			}			vu.teletext=VIDEO_NO_UNIT;			if(copy_to_user((void *)arg, (void *)&vu, sizeof(vu)))				return -EFAULT;			return 0;		}			        case BTTV_BURST_ON:		{			tvnorms[0].scaledtwidth=1135-BURSTOFFSET-2;			tvnorms[0].hdelayx1=186-BURSTOFFSET;			return 0;		}		case BTTV_BURST_OFF:		{			tvnorms[0].scaledtwidth=1135;			tvnorms[0].hdelayx1=186;			return 0;		}		case BTTV_VERSION:		{			return BTTV_VERSION_CODE;		}                        		case BTTV_PICNR:		{			/* return picture;*/			return  0;		}                        		default:			return -ENOIOCTLCMD;	}	return 0;}static int bttv_init_done(struct video_device *dev){	return 0;}/* *	This maps the vmalloced and reserved fbuffer to user space. * *  FIXME:  *  - PAGE_READONLY should suffice!? *  - remap_page_range is kind of inefficient for page by page remapping. *    But e.g. pte_alloc() does not work in modules ... :-( */ static int bttv_mmap(struct video_device *dev, const char *adr, unsigned long size){	struct bttv *btv=(struct bttv *)dev;        unsigned long start=(unsigned long) adr;	unsigned long page,pos;	if (size>2*BTTV_MAX_FBUF)	        return -EINVAL;	if (!btv->fbuffer)	{		if(fbuffer_alloc(btv))			return -EINVAL;	}	pos=(unsigned long) btv->fbuffer;	while (size > 0) 	{	        page = kvirt_to_phys(pos);		if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))		        return -EAGAIN;		start+=PAGE_SIZE;		pos+=PAGE_SIZE;		size-=PAGE_SIZE;    	}	return 0;}static struct video_device bttv_template={	"UNSET",	VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY|VID_TYPE_TELETEXT,	VID_HARDWARE_BT848,	bttv_open,	bttv_close,	bttv_read,	bttv_write,#if LINUX_VERSION_CODE >= 0x020100	NULL,			/* poll */#endif	bttv_ioctl,	bttv_mmap,	bttv_init_done,	NULL,	0,	-1};static long vbi_read(struct video_device *v, char *buf, unsigned long count,		     int nonblock){	struct bttv *btv=(struct bttv *)(v-2);	int q,todo;	todo=count;	while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) 	{		if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, q))			return -EFAULT;		todo-=q;		buf+=q;		cli();		if (todo && q==VBIBUF_SIZE-btv->vbip) 		{			if(nonblock)			{				sti();				if(count==todo)					return -EWOULDBLOCK;				return count-todo;			}			interruptible_sleep_on(&btv->vbiq);			sti();			if(signal_pending(current))			{				if(todo==count)					return -EINTR;				else					return count-todo;			}		}	}	if (todo) 	{		if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, todo))			return -EFAULT;		btv->vbip+=todo;	}	return count;}#if LINUX_VERSION_CODE >= 0x020100static unsigned int vbi_poll(struct video_device *dev, struct file *file,	poll_table *wait){	struct bttv *btv=(struct bttv *)(dev-2);	unsigned int mask = 0;	poll_wait(file, &btv->vbiq, wait);	if (btv->vbip < VBIBUF_SIZE)		mask |= (POLLIN | POLLRDNORM);	return mask;}#endifstatic int vbi_open(struct video_device *dev, int flags){	struct bttv *btv=(struct bttv *)(dev-2);	btv->vbip=VBIBUF_SIZE;	btv->cap|=0x0c;	bt848_set_risc_jmps(btv);	MOD_INC_USE_COUNT;	return 0;   }static void vbi_close(struct video_device *dev){	struct bttv *btv=(struct bttv *)(dev-2);  	btv->cap&=~0x0c;	bt848_set_risc_jmps(btv);	MOD_DEC_USE_COUNT;  }static int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg){	return -EINVAL;}static struct video_device vbi_template={	"bttv vbi",	VID_TYPE_CAPTURE|VID_TYPE_TELETEXT,	VID_HARDWARE_BT848,	vbi_open,	vbi_close,	vbi_read,	bttv_write,#if LINUX_VERSION_CODE >= 0x020100	vbi_poll,#endif	vbi_ioctl,	NULL,	/* no mmap yet */	bttv_init_done,	NULL,	0,	-1};static int radio_open(struct video_device *dev, int flags){	struct bttv *btv = (struct bttv *)(dev-1);	if (btv->user)		return -EBUSY;	btv->user++;	set_freq(btv,400*16);	btv->radio = 1;	bt848_muxsel(btv,0);	audio(btv, AUDIO_UNMUTE);		MOD_INC_USE_COUNT;	return 0;   }static void radio_close(struct video_device *dev){	struct bttv *btv=(struct bttv *)(dev-1);  	btv->user--;	btv->radio = 0;	/*audio(btv, AUDIO_MUTE);*/	MOD_DEC_USE_COUNT;  }static long radio_read(struct video_device *v, char *buf, unsigned long count, int nonblock){	return -EINVAL;}static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg){        struct bttv *btv=(struct bttv *)(dev-1);	switch (cmd) {		case VIDIOCGCAP:	{		struct video_capability v;		strcpy(v.name,btv->video_dev.name);		v.type = VID_TYPE_TUNER;		v.channels = 1;		v.audios = 1;		/* No we don't do pictures */		v.maxwidth = 0;		v.maxheight = 0;		v.minwidth = 0;		v.minheight = 0;		if (copy_to_user(arg, &v, sizeof(v)))			return -EFAULT;		return 0;		break;	}	case VIDIOCGTUNER:	{		struct video_tuner v;		if(copy_from_user(&v,arg,sizeof(v))!=0)			return -EFAULT;		if(v.tuner||btv->channel)	/* Only tuner 0 */			return -EINVAL;		strcpy(v.name, "Radio");		v.rangelow=(int)(87.5*16);		v.rangehigh=(int)(108*16);		v.flags= 0; /* XXX */		v.mode = 0; /* XXX */		if(copy_to_user(arg,&v,sizeof(v)))			return -EFAULT;		return 0;	}	case VIDIOCSTUNER:	{		struct video_tuner v;		if(copy_from_user(&v, arg, sizeof(v)))			return -EFAULT;		/* Only channel 0 has a tuner */		if(v.tuner!=0 || btv->channel)			return -EINVAL;		/* XXX anything to do ??? */		return 0;	}	case VIDIOCGFREQ:	case VIDIOCSFREQ:	case VIDIOCGAUDIO:	case VIDIOCSAUDIO:		bttv_ioctl((struct video_device *)btv,cmd,arg);		break;	default:		return -ENOIOCTLCMD;	}	return 0;}static struct video_device radio_template={	"bttv radio",	VID_TYPE_TUNER,	VID_HARDWARE_BT848,	radio_open,	radio_close,	radio_read,          /* just returns -EINVAL */	bttv_write,          /* just returns -EINVAL */#if LINUX_VERSION_CODE >= 0x020100	NULL,                /* no poll */#endif	radio_ioctl,	NULL,	             /* no mmap */	bttv_init_done,      /* just returns 0 */	NULL,	0,	-1};struct vidbases {	unsigned short vendor, device;	char *name;	uint badr;};static struct vidbases vbs[] = {        { PCI_VENDOR_ID_ALLIANCE, PCI_DEVICE_ID_ALLIANCE_AT3D,                "Alliance AT3D", PCI_BASE_ADDRESS_0},	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_215CT222,                "ATI MACH64 CT", PCI_BASE_ADDRESS_0},	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_210888GX,		"ATI MACH64 Winturbo", PCI_BASE_ADDRESS_0}, 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_215GT,                "ATI MACH64 GT", PCI_BASE_ADDRESS_0},	{ PCI_VENDOR_ID_CIRRUS, 0, "Cirrus Logic", PCI_BASE_ADDRESS_0},	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA,		"DEC DC21030", PCI_BASE_ADDRESS_0},	{ PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL,		"Matrox Millennium", PCI_BASE_ADDRESS_1},	{ PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2,		"Matrox Millennium II", PCI_BASE_ADDRESS_0},	{ PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2_AGP,		"Matrox Millennium II AGP", PCI_BASE_ADDRESS_0},	{ PCI_VEN

⌨️ 快捷键说明

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