📄 if101_io.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 + -