📄 i2c_keyboard.c
字号:
/*
* ndvd9036 i2c keyboard driver
*
* Copyright (c) 2007-2008 zzvcom
*/
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
/*
* This driver can handle standard i2c keyboards connected over a one way i2c
* converter.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <asm/div64.h>
#include <linux/fs.h>
#include <linux/input.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/proc_fs.h>
#include <linux/poll.h>
#include <linux/delay.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/string.h>
#include <linux/rtc.h> /* get the user-level API */
#include <linux/bcd.h>
#include <linux/list.h>
#include <asm/mach-pnx8550/glb.h>
#include "vcomkeycode.h"
static int irq = 75;
static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END };
struct i2c_client *client;
I2C_CLIENT_INSMOD_1(infrared);
//struct i2c_client_address_data addr_data;
#define DRIVER_DESC "i2c keyboard driver"
MODULE_AUTHOR("huizuokui<huizuokui@zzvcom.com>");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#define I2CKBDVERSION 0x0101
#define PNX8950_MMIO_BASE 0xBBE00000
#define I2C3_BASE 0x00069000
#define I2C_CONTROL 0x00000000
#define I2C_DAT 0x00000004
#define I2C_STATUS 0x00000008
#define I2C_ADDRESS 0x0000000C
#define I2C_STOP 0x00000010
#define I2C_PD 0x00000014
#define I2C_SET_PINS 0x00000018
#define I2C_OBS_PINS 0x0000001C
#define I2C_INT_STATUS 0x00000FE0
#define I2C_INT_EN 0x00000FE4
#define I2C_INT_CLR 0x00000FE8
#define I2C_INT_SET 0x00000FEC
#define I2C_Powerdown 0x00000FF4
#define Module_ID 0x00000FFC
#define IP0105_AA (0x80) /* Bit in the register I2CCON */
#define IP0105_EN (0x40) /* Bit in the register I2CCON */
#define IP0105_STA (0x20) /* Bit in the register I2CCON */
#define IP0105_STO (0x10) /* Bit in the register I2CCON */
#define IP0105_CR2 (0x03) /* Bits in the register I2CCON */
#define IP0105_INTBIT (0x01) /* Bit in the register INT_STATUS */
static struct i2c_client *i2c_dev;
static struct i2c_driver i2c_driver_infrared;
static unsigned char atkbd_set2_keycode[512] = {
0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117,
0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0,
0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183,
0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185,
0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
0, 89, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 85,
0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0,
82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142,
157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0,
0, 0, 0, 65, 99,
};
struct i2ckbd_struct {
struct input_dev *dev;
long xp;
long yp;
int count;
int shift;
char phys[32];
};
static void i2ckbd_timer_fire(unsigned long data);
static int i2ckbd_probe(void);
int keydown_flag=1;
static char *i2ckbd_name = "i2ckbd mouse & keyboard";
static struct i2ckbd_struct i2ckbd;
static struct timer_list i2ckbd_timer = TIMER_INITIALIZER(i2ckbd_timer_fire, 0, 0);
int i2ckbd_open(struct inode * inode, struct file * file)
{
return 0;
}
int i2ckbd_close(struct inode * inode, struct file * file)
{
return 0;
}
static struct file_operations i2ckbd_fops = {
.owner = THIS_MODULE,
.open = i2ckbd_open,
.release = i2ckbd_close
};
static struct miscdevice i2ckbd_driver = {
MISC_DYNAMIC_MINOR,
"i2ckbd",
&i2ckbd_fops,
};
void dump_i2c_reg(void){
printk("-------------------------------------------------------------\r\n");
printk("i2c device id = 0x%08X\r\n",MMIO(I2C3_BASE + Module_ID));
printk("I2C_CONTROL = 0x%08X\r\n",MMIO(I2C3_BASE + I2C_CONTROL));
printk("I2C_I2C_DAT = 0x%08X\r\n",MMIO(I2C3_BASE + I2C_DAT));
printk("I2C_STATUS = 0x%08X\r\n",MMIO(I2C3_BASE + I2C_STATUS));
printk("I2C_ADDRESS = 0x%08X\r\n",MMIO(I2C3_BASE + I2C_ADDRESS));
printk("I2C_STOP = 0x%08X\r\n",MMIO(I2C3_BASE + I2C_STOP));
printk("I2C_PD = 0x%08X\r\n",MMIO(I2C3_BASE + I2C_PD));
printk("I2C_INT_STATUS = 0x%08X\r\n",MMIO(I2C3_BASE + I2C_INT_STATUS));
printk("I2C_INT_EN = 0x%08X\r\n",MMIO(I2C3_BASE + I2C_INT_EN));
printk("I2C_INT_SET = 0x%08X\r\n",MMIO(I2C3_BASE + I2C_INT_SET));
printk("I2C_Powerdown = 0x%08X\r\n",MMIO(I2C3_BASE + I2C_Powerdown));
printk("-------------------------------------------------------------\r\n");
}
static __inline void AAOUT(int p){
unsigned int val ;
val = MMIO(I2C3_BASE + I2C_CONTROL);
if (p) {
val |= 1<<7;
} else {
val &= ~(1<<7);
}
MMIO(I2C3_BASE + I2C_CONTROL) = val;
}
static __inline void STAOUT(int p){
unsigned int val ;
val = MMIO(I2C3_BASE + I2C_CONTROL);
if (p) { val |= IP0105_STA; } else { val &= ~IP0105_STA; }
MMIO(I2C3_BASE + I2C_CONTROL) = val;
}
static __inline void STOOUT(int p){
MMIO(I2C3_BASE + I2C_STOP) = p;
}
void i2c_hardware_error(void){
unsigned int val;
val = MMIO(I2C3_BASE + I2C_CONTROL) ;
MMIO(I2C3_BASE + I2C_CONTROL) = val & (~IP0105_EN);
STAOUT(0 ); /* Don't generate START condition */
STOOUT(1 ); /* Recover from error condition */
AAOUT(1 );
MMIO(I2C3_BASE + I2C_INT_CLR) = 0x01;
val = MMIO(I2C3_BASE + I2C_CONTROL) ;
MMIO(I2C3_BASE + I2C_CONTROL) = val | (IP0105_EN);
}
static irqreturn_t infrared_int(int irq, void *dev_id, struct pt_regs *regs){
static unsigned char key_buf[20],key_count ;
unsigned int uStatus ,uValue;
uStatus = MMIO(I2C3_BASE + I2C_STATUS);
udelay(1);
//printk("\r\nuStatus=0x%02X ",uStatus);
switch(uStatus){
case 0x80:{
uValue = MMIO(I2C3_BASE + I2C_DAT);
if((uValue==0x02)||(uValue==0x00)){ //收到红外键盘命令认为是数据的开始
key_count = 0;
}
#if 1
if((uValue!=0x02)&&((uValue!=0x00))&&((uValue!=0xf7))&&((uValue!=0x01))&&((uValue!=0xF9))){
#if 0
printk("0x%02X ",uValue);
#else
unsigned int i,uTemp;
key_buf[key_count] = uValue;
key_count += 1;
if(key_count>=2){
uTemp = (key_buf[0]<<8) | (key_buf[1]); //组合收到的红外编码数据
#if 0
printk("utemp=0x%04X\r\n",uTemp);
#endif
for(i=0;i<88;i++){
if(uTemp == i2ckbd_set_keycode[i][0]) break; //搜索键盘编码表格
}
if(i<88) { //搜索到对应的键盘编码
#if 0
printk("get a key pressed:%d\r\n",i2ckbd_set_keycode[i][1]);
printk("\r\n");
#endif
input_report_key(i2ckbd.dev, i2ckbd_set_keycode[i][1], 1);
input_report_key(i2ckbd.dev, i2ckbd_set_keycode[i][1], 0);
input_sync(i2ckbd.dev);
}
key_count = 0;
}
#endif
}
#endif
udelay(1);
AAOUT(1);
udelay(1);
MMIO(I2C3_BASE + I2C_INT_CLR) = 0x01;
break;
}
case 0x88:{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -