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

📄 if101_io.c

📁 cmmb if101 linux driver sample
💻 C
字号:
#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/sched.h>#include <linux/mm.h>#include <asm/page.h>#include <linux/poll.h>#include <linux/kdev_t.h>#include <asm/semaphore.h>#include <asm/arch/pxa-regs.h>#include <linux/slab.h>#include <linux/delay.h>#include <asm/uaccess.h>#include <linux/i2c.h>#include <linux/miscdevice.h>#include <linux/devfs_fs_kernel.h>#include "IF101_Operation.h"#include "IF101_Communication.h"#include "IF101_IO.h"#include <linux/interrupt.h>static char INNODEV_NAME[] = "if101";struct class *dev_class;static unsigned char if101_major = 254;int wq_status;wait_queue_head_t wq;unsigned char *g_buffer;#define BUFFER_SIZE 100*1024static irqreturn_t inno_intr_handler(int irq, void *device, struct pt_regs *regs){	wq_status = 1;	wake_up_interruptible(&wq);	//	printk("TV interrupt occured!!!!!");        return IRQ_RETVAL(1);}static int inno_open(struct inode* inode, struct file* filp){	INNO_RETURN_CODE ret;	printk("inno open\n");	g_buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);	if(g_buffer == NULL){		printk("malloc memory fail\n");		return -1;	}	memset(g_buffer, 0xFF, BUFFER_SIZE);	init_waitqueue_head(&wq);	INNO_I2C_Init(1);		printk("after inno_i2c_innit(1)\n"); //zc	ret = INNO_I2C_Test();	if(ret != INNO_NO_ERROR){		printk("INNO_I2C_Test fail. ret = %d\n", ret);		INNO_I2C_Init(0);		return -1;	}	printk("after inno_i2c_test\n");//zc	ret = INNO_SPI_Init(1);	if(ret != INNO_NO_ERROR)		printk("INNO_SPI_Init fail\n");	ret = INNO_SPI_Test();	if(ret != INNO_NO_ERROR){		printk("INNO_SPI_Test fail\n");		INNO_SPI_Init(0);		return -1;	}	printk("after spi init");	INNO_GPIO_INT_Init(1, inno_intr_handler);		return 0;}static int inno_close(struct inode* inode, struct file* filp){	printk("inno close\n");	INNO_I2C_Init(0);	INNO_SPI_Init(0);	INNO_GPIO_INT_Init(0, NULL);	kfree(g_buffer);	return 0;}static unsigned int inno_poll(struct file* filp, poll_table *wait){	printk("inno poll\n");	return 0;}static ssize_t inno_read(struct file* filp, char* buf, size_t count, loff_t* offset){	unsigned int lg0_channel_len, lg1_channel_len;	int ret ;	wq_status = 0;	ret = wait_event_interruptible_timeout(wq,wq_status == 1 ,5 * HZ);	if(ret <= 0){		printk("read cmmb data timeout or interrupted\n");		return -1;		}	//printk("after wake up \n");	ret = INNO_GetChannelLength(&lg0_channel_len, &lg1_channel_len);	if(ret != INNO_NO_ERROR){		printk("get channel length fail\n");	}	printk("lg0 channel length = 0x%X\n", lg0_channel_len);	printk("lg1 channel length = 0x%X\n", lg1_channel_len);	if(lg0_channel_len > 0){		ret = INNO_GetChannelData(LG0_CHANNEL, g_buffer, lg0_channel_len);			if(ret != INNO_NO_ERROR){			printk("get channel data fail\n");		}		copy_to_user(buf, g_buffer, lg0_channel_len);		return lg0_channel_len;	}	else if(lg1_channel_len > 0){		ret = INNO_GetChannelData(LG1_CHANNEL, g_buffer, lg1_channel_len);			if(ret != INNO_NO_ERROR){			printk("get channel data fail\n");		}		copy_to_user(buf, g_buffer, lg1_channel_len);		return lg1_channel_len;	}		return 0;}static int inno_ioctl(struct inode* inode, struct file* filp, unsigned int cmd, unsigned long arg){	INNO_RETURN_CODE ret = INNO_NO_ERROR;	switch(cmd){		case IOCTL_GET_FW_VERSION:		{			unsigned char version[2];			ret = INNO_GetFirmwareVersion(&version[0], &version[1]);			if(ret != INNO_NO_ERROR)				return ret;			copy_to_user((void *)arg, version, sizeof(unsigned char) * 2);			break;		}		case IOCTL_SET_RECEIVE_TS0:		{			ret = INNO_SetReceiveTs0();			if(ret != INNO_NO_ERROR)				return ret;			break;		}		case IOCTL_SET_RECEIVE_PROGRAM:		{			int ts_info[4];			copy_from_user(ts_info,(void *)arg, sizeof(int) * 4);			ret = INNO_SetReceiveProgram(ts_info[0],ts_info[1],ts_info[2],ts_info[3]);			if(ret != INNO_NO_ERROR)				return ret;			break;		}		case IOCTL_SET_FREQUENCY:		{			unsigned char freq;			copy_from_user(&freq, (void *)arg, sizeof(unsigned char));			printk("freq  ===  %d \n", freq);			ret = INNO_SetTunerFrequency(freq, CP_40TS); 			if(ret != INNO_NO_ERROR)				return ret;			break;		}		case IOCTL_SCAN_FREQUENCY:		{			unsigned char freq[2];			copy_from_user(&freq, (void *)arg, sizeof(unsigned char) * 2);			ret = INNO_ScanFrequency(freq[0], freq[1]);			if(ret != INNO_NO_ERROR)				return ret;			break;		}		case IOCTL_SET_PM:		{			PM_MODE pm;				copy_from_user(&pm, (void *)arg, sizeof(PM_MODE));			ret = INNO_SetPowerManagement(PM_MODE_RESUME); 			if(ret != INNO_NO_ERROR)				return ret;			break;		}		case IOCTL_SET_DEMOD_CONFIG:		{			DEMOD_CONFIG setting[2];			copy_from_user(&setting, (void *)arg, sizeof(DEMOD_CONFIG) * 2);			ret = INNO_SetDemodConfig(setting);			if(ret != INNO_NO_ERROR)				return ret;			break;		}		case IOCTL_GET_DEMOD_CONFIG:		{			DEMOD_CONFIG checking[2];			ret = INNO_GetDemodConfig(checking);			if(ret != INNO_NO_ERROR)				return ret;			copy_to_user((void *)arg, checking, sizeof(checking));			break;		}		case IOCTL_GET_SYS_STATUS:		{			SYS_STATUS status;			ret = INNO_GetSystemStatus(&status);			if(ret != INNO_NO_ERROR)				return ret;			copy_to_user((void *)arg, &status, sizeof(SYS_STATUS));			break;		}	}	return ret;}static struct file_operations if101_fops = {	.owner		= THIS_MODULE,	.open		= inno_open,	.read		= inno_read,	.poll		= inno_poll,	.ioctl		= inno_ioctl,	.release	= inno_close,};static int __init init_if101_module(void){	int res;	res = register_chrdev(if101_major, INNODEV_NAME, &if101_fops);	if (res < 0){ 		printk("failed to register device.\n"); 			return res; 	}	printk("major = %d\n", if101_major);	return 0;}static void __exit cleanup_if101_module(void){	unregister_chrdev(if101_major, INNODEV_NAME);	printk("cleanup_if101_module\n");	return;}module_init(init_if101_module);module_exit(cleanup_if101_module);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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