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

📄 i2c-tomega8.c

📁 linux下S3C2410的I2C总线的驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/*    i2c-tomega8.c - i2c-bus driver, comunicate to mega8 MCU      Written by Richard R.Zhang    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <linux/config.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/slab.h>#include <linux/version.h>#if LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0)#include <linux/smp_lock.h>#endif /* LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) */#ifdef CONFIG_DEVFS_FS#include <linux/devfs_fs_kernel.h>#endif/* If you want debugging uncomment: *//* #define DEBUG */#include <linux/init.h>#include <asm/uaccess.h>#include <linux/i2c.h>#include <linux/poll.h>#include <linux/delay.h>#include "dbg_msg.h"#include "i2c-tomega8.h"#include "cmd_kbd_mouse.h"/* debug macros */#undef DEBUG//#define DEBUG#ifdef DEBUG#define DPRINTK( x... )	printk("mcu: " ##x)#else#define DPRINTK( x... )#endifstatic void mega8_device_request (int devtype);static void mega8_device_release (int devtype);static int i2c_mega8_slvRcv( char *buf, int len, int begin);static int i2c_mega8_attach_adapter(struct i2c_adapter *adap);static int i2c_mega8_detach_client(struct i2c_client *client);static int i2c_mega8_command(struct i2c_client *client, unsigned int cmd, void *arg);static int __init i2c_mega8_init(void);static void i2c_mega8_cleanup(void);#define I2CDEV_ADAPS_MAX I2C_ADAP_MAXstatic struct i2c_adapter *i2cdev_adaps[I2CDEV_ADAPS_MAX];#ifdef CONFIG_DEVFS_FSstatic devfs_handle_t devfs_handle = NULL;#endifstatic struct i2c_driver i2c_mega8_driver = {	name:			"I2C Mega8 Driver",	id:				I2C_DRIVERID_I2CDEV,	flags:			I2C_DF_DUMMY,	attach_adapter:	i2c_mega8_attach_adapter,	detach_client:		i2c_mega8_detach_client,	command:		i2c_mega8_command,/*	inc_use:	NULL,	dec_use:	NULL, */};static struct i2c_client mega8_client = {	name:		"I2C Mega8",	id:			1,	flags:		0,	addr:		MEGA8_I2CADDRESS,	adapter:	NULL,	driver:		&i2c_mega8_driver,	slvRecvNotify:	i2c_mega8_slvRcv,	};#ifdef CONFIG_I2C_MEGA8_MATRIX_KEYBOARD/***************************//* Mega8 Keyboard Driver Start *//***************************/static void mega8_kbd_raw (I2C_kbd *kbdcode);static ssize_t mega8_kbd_read (struct file *file, unsigned char *buf, size_t count,  // +- modify                             loff_t *offset);static ssize_t mega8_kbd_write (struct file *file, const unsigned char *buf, size_t count,  //+-modify                             loff_t *offset);static int mega8_kbd_open (struct inode *inode, struct file *file);static int mega8_kbd_release (struct inode *inode, struct file *file);static unsigned int mega8_kbd_poll(struct file *filp, struct poll_table_struct *wait);#define KBD_MINOR	10#define KBD_NAME	"Mega8 Kbd"#define KEY_NULL	0#define KEY_DOWN	0x0#define KEY_UP		0x0080#define MAX_KBD_BUF	16	/* how many do we want to buffer */typedef unsigned char KBD_RET;typedef struct {	unsigned int kbdmode;		/*KEYSTATUS_UP KEYSTATUS_DOWN and KEYSTATUS_REPEAT*/	KBD_RET buf[MAX_KBD_BUF];		/* protect against overrun */	unsigned int head, tail;		/* head and tail for queued events */	wait_queue_head_t wq;	spinlock_t lock;	unsigned short key;} KBD_DEV;static int kbdmajor=0;static KBD_DEV kbddev;#ifdef  CONFIG_DEVFS_FSstatic devfs_handle_t kbd_devfs_handle;#endif#define BUF_HEAD	(kbddev.buf[kbddev.head])#define BUF_TAIL	(kbddev.buf[kbddev.tail])#define INCBUF(x,mod) 	((++(x)) & ((mod) - 1))static struct file_operations mega8_kbd_fops = {	owner:		THIS_MODULE,	read:		mega8_kbd_read,	write:		mega8_kbd_write,	open:		mega8_kbd_open,	release:		mega8_kbd_release,	poll:			mega8_kbd_poll,};typedef struct{	unsigned short keyraw;	unsigned short map2;}struct_KeyMap;static struct_KeyMap keycode_raw2map[]={/*F1*/		{0x30, 0x3b},/*F2*/		{0x28, 0x3c},/*F3*/		{0x20, 0x3d},/*F4*/		{0x18, 0x3e},/*F5*/		{0x10, 0x3f},/*F6*/		{0x08, 0x40},/*F7*/		{0x2f, 0x41},/*F8*/		{0x27, 0x42},/*F9*/		{0x1f, 0x43},/*F10*/		{0x17, 0x44},/*F11*/		{0x0f, 0x57},/*F12*/		{0x07, 0x58},/*1*/		{0x32, 0x02},/*2*/		{0x2a, 0x03},/*3*/		{0x22, 0x04},/*4*/		{0x35, 0x05},/*5*/		{0x2d, 0x06},/*6*/		{0x25, 0x07},/*7*/		{0x36, 0x08},/*8*/		{0x2e, 0x09},/*9*/		{0x26, 0x0a},/*0*/		{0x29, 0x0b},/*.*/		{0x31, 0x53},/*+*/		{0x19, 0x4e},/*-*/		{0x1a, 0x4a},/***/		{0x1d, 0x37},/* / */		{0x1e, 0xe035},/*=*/		{0x21, 0x0d},/*up*/		{0x0a, 0xe048},/*dwn*/		{0x09, 0xe050},/*lft*/		{0x11, 0xe04b},/*rgt*/		{0x01, 0xe04d},/*pgu*/		{0x16, 0xe049},/*pgd*/		{0x15, 0xe051},/*entr*/	{0x0d, 0x1c},/*BKSP*/	{0x0e, 0x0e},/*ESC*/		{0X06, 0X01},};static unsigned short keycode_map[64];#if 0={0x0000, 0x0000, 0x0000, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,	/*  0 -  7 */0x003b, 0x0000, 0x0000, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058,	/*  8 - 15 */0x0041, 0x0008, 0x0000, 0x000a, 0x0035, 0xe049, 0x000e, 0x0001,	/* 16 - 23 */0x0009, 0x0005, 0x0000, 0x0007, 0x0037, 0xe051, 0x001c, 0x0000,	/* 24 - 31 */0x0006, 0x0002, 0x0000, 0x0004, 0x000c, 0x0000, 0xe048, 0x0000,	/* 32 - 39 */0x0003, 0x0034, 0x0000, 0x000d, 0x004e, 0xe04b, 0xe050, 0xe04d,	/* 40 - 47 */0x000b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/* 48 - 50 */};#endif#define	CODE_MAP_SIZE (sizeof(keycode_map) / sizeof(unsigned short))static int mega8_kbd_convert (unsigned char originkey){	unsigned char pure = originkey & 0x7f;	unsigned short act = (originkey & 0x80) ? KEY_DOWN : KEY_UP;	if ( pure > CODE_MAP_SIZE)		return -1;	kbddev.key= keycode_map[pure] | act;	DPRINTK ("key code :%x\t%x\n",originkey,kbddev.key);	return 0;}static void mega8_kbd_raw (I2C_kbd *kbdcode){	int need = 1, empty;	unsigned char *pcode =(unsigned char *)&(kbddev.key);	if (!kbdcode)		return;	if (mega8_kbd_convert (kbdcode->key) < 0)		return ;	if (kbddev.key & 0xf000){		need = 2;	}	DPRINTK ("driver->code:0x%x\n", kbddev.key);	if (kbddev.head > kbddev.tail)		empty = MAX_KBD_BUF - (kbddev.head - kbddev.tail);	else if (kbddev.head < kbddev.tail)		empty = MAX_KBD_BUF - (kbddev.head + MAX_KBD_BUF - kbddev.tail);	else		empty = MAX_KBD_BUF;	DPRINTK ("need:%d\tempty:%d\n", need, empty);	if ( empty < need )		return;	DPRINTK ("push L:%x\n", pcode[0]);	DPRINTK ("push H:%x\n", pcode[1]);	if (kbddev.key & 0xf000){		BUF_HEAD = pcode[1];		kbddev.head = INCBUF(kbddev.head, MAX_KBD_BUF);	}	BUF_HEAD = pcode[0];	kbddev.head = INCBUF(kbddev.head, MAX_KBD_BUF);	DPRINTK ("head:%d\ttail:%d\n", kbddev.head, kbddev.tail);	wake_up_interruptible(&(kbddev.wq));}static KBD_RET kbdRead(void){	KBD_RET  kbd_ret;	spin_lock_irq(&(kbddev.lock));	kbd_ret= BUF_TAIL;	kbddev.tail = INCBUF(kbddev.tail, MAX_KBD_BUF);	spin_unlock_irq(&(kbddev.lock));	return kbd_ret;}static unsigned int mega8_kbd_poll(struct file *filp, struct poll_table_struct *wait){  poll_wait(filp, &(kbddev.wq), wait);  return (kbddev.head == kbddev.tail) ? 0 : (POLLIN | POLLRDNORM); }static ssize_t mega8_kbd_read (struct file *file, unsigned char *buf, size_t count,                            loff_t *offset){	KBD_RET kbd_ret;retry: 	if (kbddev.head != kbddev.tail) {		kbd_ret = kbdRead();		copy_to_user(buf, (char *)&kbd_ret, sizeof(KBD_RET));		return sizeof(KBD_RET);	} else {		if (file->f_flags & O_NONBLOCK)			return -EAGAIN;		interruptible_sleep_on(&(kbddev.wq));		if (signal_pending(current))			return -ERESTARTSYS;		goto retry;	}	return sizeof(KBD_RET);}static ssize_t mega8_kbd_write (struct file *file, const unsigned char *buf, size_t count,                             loff_t *offset){	return -1;}static int mega8_kbd_release (struct inode *inode, struct file *file){	mega8_device_release (DTYPE_MKEYB);	return 0;}static int mega8_kbd_open (struct inode *inode, struct file *file){/*	if (!mega8_kbd_client->adapter)		return -ENODEV;	if (mega8_kbd_client->adapter->inc_use)		mega8_kbd_client->adapter->inc_use (mega8_kbd_client->adapter);*/	kbddev.head = kbddev.tail = 0;	kbddev.kbdmode= KEY_NULL;	init_waitqueue_head(&(kbddev.wq));	DPRINTK( "opened\n");	mega8_device_request (DTYPE_MKEYB);	return 0;}#ifdef CONFIG_DEVFS_FSstatic devfs_handle_t mega8_kbd_init (devfs_handle_t i2c_root)#elsestatic int mega8_kbd_init ()#endif{	int ret, i;	for(i=0;i<sizeof(keycode_raw2map)/sizeof(keycode_raw2map[0]);i++){		keycode_map[keycode_raw2map[i].keyraw]=keycode_raw2map[i].map2;	}#ifdef  DEBUG	DPRINTK ( "key map \n");	for ( i = 0; i < 8; i ++){		int j;		for (j = 0; j < 8; j++){			int index = i * 8 + j;			DPRINTK ("%d,0x%x  ", index, keycode_map[index]);		}		DPRINTK ("\n");	}#endif		ret = register_chrdev(0, KBD_NAME, &mega8_kbd_fops);	if (ret < 0) {		DPRINTK(KBD_NAME" can't be registered\n");#ifdef CONFIG_DEVFS_FS		return NULL;#else		return ret;#endif	}	kbdmajor = ret;#ifdef CONFIG_DEVFS_FS	kbd_devfs_handle = devfs_register (i2c_root, "kbd",			DEVFS_FL_DEFAULT, kbdmajor, KBD_MINOR,			S_IFCHR | S_IRUSR | S_IWUSR,			&mega8_kbd_fops, NULL);#endif	DPRINTK("Registered '%s' as minor %d\n","kbd", KBD_MINOR);#ifdef CONFIG_DEVFS_FS	return kbd_devfs_handle;#else	return 0;#endif}static void mega8_kbd_exit (void){#ifdef	CONFIG_DEVFS_FS	devfs_unregister(kbd_devfs_handle);	kbd_devfs_handle = NULL;#endif	unregister_chrdev(kbdmajor, KBD_NAME);}#endif //#ifdef CONFIG_I2C_MEGA8_MATRIX_KEYBOARD#ifdef CONFIG_I2C_MEGA8_IC_CARD/***************************//* Mega8 ic card Driver Start *//***************************/static void mega8_iccard_raw (I2C_ICCard*iccardframe);#if 0static unsigned int mega8_iccard_poll(struct file *filp, struct poll_table_struct *wait);#endifstatic loff_t mega8_iccard_llseek (struct file *file, loff_t offset, int orig);static int mega8_iccard_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);static ssize_t mega8_iccard_read (struct file *file, char *buf, size_t count,  // +- modify                             loff_t *offset);static ssize_t mega8_iccard_write (struct file *file, const char *buf, size_t count,  //+-modify                             loff_t *offset);static int mega8_iccard_open (struct inode *inode, struct file *file);static int mega8_iccard_release (struct inode *inode, struct file *file);#define ICCARD_24C02_MINOR	ICCARD_TYPE_AT24C02#define ICCARD_24C04_MINOR	ICCARD_TYPE_AT24C04#define ICCARD_24C08_MINOR	ICCARD_TYPE_AT24C08#define ICCARD_24C16_MINOR	ICCARD_TYPE_AT24C16#define ICCARD_24C32_MINOR	ICCARD_TYPE_AT24C32#define ICCARD_24C64_MINOR	ICCARD_TYPE_AT24C64#define ICCARD_4442_MINOR	ICCARD_TYPE_SLE4442#define ICCARD_24C02_NAME	"iccard24c02"#define ICCARD_24C04_NAME	"iccard24c04"#define ICCARD_24C08_NAME	"iccard24c08"#define ICCARD_24C16_NAME	"iccard24c16"#define ICCARD_24C32_NAME	"iccard24c32"#define ICCARD_24C64_NAME	"iccard24c64"#define ICCARD_4442_NAME	"iccard4442"#define ICCARD_NAME	"iccard"typedef struct {	ICCARD_data iccard_data;	int lasterrcode;	wait_queue_head_t wq;	spinlock_t lock;}ICCARD_DEV;typedef struct _iccard_dev_info{	unsigned char minor;	char *devname;	loff_t memsize;}ICCARD_DEV_INFO;ICCARD_DEV_INFO iccarddevinfo[]={	{ICCARD_24C02_MINOR, ICCARD_24C02_NAME, 256},	{ICCARD_24C04_MINOR, ICCARD_24C04_NAME, 512},	{ICCARD_24C08_MINOR, ICCARD_24C08_NAME, 1024},	{ICCARD_24C16_MINOR, ICCARD_24C16_NAME, 2048},	{ICCARD_24C32_MINOR, ICCARD_24C32_NAME, 4096},	{ICCARD_24C64_MINOR, ICCARD_24C64_NAME, 8192},	{ICCARD_4442_MINOR, ICCARD_4442_NAME, 256},};#define	DEVNM_SIZE	(sizeof (iccarddevinfo) / sizeof (ICCARD_DEV_INFO))static devfs_handle_t iccard_devfs_handle[DEVNM_SIZE];static ICCARD_DEV iccarddev;atomic_t atom_cnt;static int iccardmajor=0;static struct file_operations mega8_iccard_fops = {	owner:		THIS_MODULE,	llseek:		mega8_iccard_llseek,	read:		mega8_iccard_read,	write:		mega8_iccard_write,	open:		mega8_iccard_open,	release:		mega8_iccard_release,#if 0	poll:			mega8_iccard_poll,#endif	ioctl:		mega8_iccard_ioctl,};static void mega8_iccard_raw (I2C_ICCard* iccardframe){	if (!iccardframe)		return;	DPRINTK ("iccardframe->cmd:0x%x\n", iccardframe->cmd);	if(iccardframe->cmd==CMD_ICC_FAILED){		iccarddev.lasterrcode=iccardframe->iccard_errcode;		DPRINTK ("iccard failed code:0x%x\n", iccarddev.lasterrcode);	}	else{		iccarddev.lasterrcode=ICC_FAILED_NULL;		if(iccardframe->cmd==CMD_ICC_WRITE){			if(iccarddev.iccard_data.address == iccardframe->iccard_addr				&& iccarddev.iccard_data.cnt == iccardframe->iccard_cnt){				DPRINTK ("iccard write ok:address=0x%x, count=%d\n", 					iccarddev.iccard_data.address, iccarddev.iccard_data.cnt);			}			else{				DPRINTK ("iccard write error: address=0x%x vs 0x%x\n", iccarddev.iccard_data.address, 					iccardframe->iccard_addr);				iccarddev.lasterrcode=ICC_FAILED_WRITEERR;			}		}		else if(iccardframe->cmd==CMD_ICC_READ){			if(iccarddev.iccard_data.address == iccardframe->iccard_addr				&& iccarddev.iccard_data.cnt == iccardframe->iccard_cnt){				DPRINTK ("iccard read ok:address=0x%x, count=%d\n", 					iccarddev.iccard_data.address, iccarddev.iccard_data.cnt);				memcpy(iccarddev.iccard_data.buffer, iccardframe->iccard_buf, iccarddev.iccard_data.cnt);			}			else{				DPRINTK ("iccard read error: address=0x%x vs 0x%x\n", iccarddev.iccard_data.address, 					iccardframe->iccard_addr);				iccarddev.lasterrcode=ICC_FAILED_READERR;			}		}		else if (iccardframe->cmd == CMD_ICC_VERIFY ){			unsigned char retcode = iccardframe->iccard_errcode;			if (retcode){				iccarddev.lasterrcode = ICC_FAILED_VERIFYERR;			}else{				iccarddev.lasterrcode = ICC_FAILED_NULL;			}		}	}	wake_up_interruptible(&(iccarddev.wq));}#if 0static unsigned int mega8_iccard_poll(struct file *filp, struct poll_table_struct *wait){	poll_wait(filp, &(iccarddev.wq), wait);	return iccarddev.lasterrcode; }#endifstatic loff_t mega8_iccard_llseek(struct file *file,loff_t offset, int orig){	ICCARD_DEV_INFO *iccd= (ICCARD_DEV_INFO*)file->private_data;	switch (orig) {	case 0:		/* SEEK_SET */		file->f_pos = offset;		break;	case 1:		/* SEEK_CUR */		file->f_pos += offset;		break;

⌨️ 快捷键说明

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