📄 k.c
字号:
/* * Keyboard driver for Sharp Corgi models (SL-C7xx) * * Copyright (c) 2004-2005 Richard Purdie * * Based on xtkbd.c/locomkbd.c * * 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. *1 射频卡数据 R W2 4442卡数据 R W3 顾显显示数据 - W4 矩阵键盘KM62数据 R -5 PS2键盘数据 R W6 Cash_drawer - W7 磁卡数据 R -8 FM 收音机 R W9 E2PROM R W跟上层用户程序间:W: DEV_TYPE Para1 Para2 Para3 Data 1 1 1 1 ***#include <linux/delay.h>#include <linux/platform_device.h>#include <linux/init.h>#include <linux/input.h>#include <linux/irq.h>#include <linux/interrupt.h>#include <linux/jiffies.h>#include <linux/module.h>#include <linux/slab.h>#include <asm/irq.h>#include <asm/hardware.h>#include <asm/arch/regs-gpio.h> */#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/input.h>#include <linux/platform_device.h>#include <linux/fs.h>#include <linux/slab.h>#include <linux/smp_lock.h>#include <linux/list.h>#include <linux/completion.h>#include <linux/interrupt.h>#include <linux/jiffies.h>#include <linux/delay.h>#include <linux/irq.h>#include <asm/uaccess.h>#include <asm/hardware.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/arch/regs-gpio.h>#include <asm/arch/regs-iic.h>#define PHERIAL_MAJOR 252typedef unsigned char BYTE;typedef unsigned short WORD;typedef unsigned long DWORD;/*#define IIC_TPUR 1000 // 上电到读操作#define IIC_FSCL 1000 #define IIC_TAA 1#define IIC_TBUF 1#define IIC_THD_STA 1#define IIC_TLOW 1#define IIC_THIGH 1#define IIC_TSU_STA 1#define IIC_THD_DAT 0#define IIC_TSU_DAT 1#define IIC_TR 1#define IIC_TF 1#define IIC_TSU_STO 1#define IIC_TDH 1#define IIC_TWR 10000*/#define IIC_TPUR 1000 // 上电到读操作#define IIC_FSCL 400 #define IIC_TAA 1#define IIC_TBUF 1#define IIC_THD_STA 1#define IIC_TLOW 1#define IIC_THIGH 1#define IIC_TSU_STA 1#define IIC_THD_DAT 0#define IIC_TSU_DAT 1#define IIC_TR 1#define IIC_TF 1#define IIC_TSU_STO 1#define IIC_TDH 1#define IIC_TWR 10000///////////////// 器件寻址控制字#define IIC_ADDR_EEPROM 0xA0 // CAT24C02#define IIC_ADDR_RADIO 0xC0 // FM RADIO#define IIC_ADDR_NEC 0x60 // NEC 单片机#define IIC_CTL_BYTE_W 0 #define IIC_CTL_BYTE_R 1#define IIC_PAGE_SIZE 16 // 写的时候,一页的大小#define IIC_MAX_ERROR 10 // 最多允许出错次数#define iic_debug 1#define dpk_iic(msg...) if (iic_debug) { printk( " s3c2410-iic: " msg); }#define SCL(x) s3c2410_gpio_setpin(S3C2410_GPE14,x)#define SDA(x) s3c2410_gpio_setpin(S3C2410_GPE15,x)#define OUTP_SCL s3c2410_gpio_cfgpin(S3C2410_GPE14, S3C2410_GPE14_OUTP)#define OUTP_SDA s3c2410_gpio_cfgpin(S3C2410_GPE15, S3C2410_GPE15_OUTP)#define INP_SCL s3c2410_gpio_cfgpin(S3C2410_GPE14, S3C2410_GPE14_INP)#define INP_SDA s3c2410_gpio_cfgpin(S3C2410_GPE15, S3C2410_GPE15_INP)#define DEV_RF 1#define DEV_4442 2#define DEV_DSP 3#define DEV_KM62 4#define DEV_PS2 5#define DEV_CASH 6#define DEV_MAG 7#define DEV_FM 8#define DEV_E2PROM 9#define CASH_PORT S3C2410_GPB9static int CASH_MS = 200; //开钱箱通电保持几毫秒static int OPERATING_PHERIAL = DEV_RF; //当前操作的设备static char fm_rx[5];//static char fm_tx[5]={0x2b,0xe1,0x10,0x16,0}; //99.6Mhz -> PLL=0x2f99, 96.8Mhz -> PLL=0x2e43 ,91.8Mhz -> PLL=0x2be1static char fm_tx[5]={0x2b,0xe1,0x10,0x16,0}; //99.6Mhz -> PLL=0x2f99, 96.8Mhz -> PLL=0x2e43 ,91.8Mhz -> PLL=0x2be1static char dsp_digi_data[10]={0x3f,6,0x5b,0x4f,0x66,0x5d,0x7d,7,0x7f,0x6f}; //数码管数字0-9段位的值static char dsp_tx[9] = {03,06,0,0,0,0x80,0,0,0}; //0x80是第4位的小数点值static unsigned char km62kbd_keycode[64] = { 0x1e,0x17,0x10,0x2f,KEY_DELETE,0x0b,0x1c,0x00, 0x30,0x24,0x13,0x11,KEY_KPPLUS,0x0b,0x1c,0x00, 0x2e,0x25,0x1f,0x2d,0x34,0x42,0x00,0x3f, 0x20,0x26,0x14,0x15,0x04,0x07,0x0a,0x3e, 0x12,0x32,0x16,0x2c,0x03,0x06,0x09,0x3d, 0x21,0x31,KEY_PAGEUP,KEY_LEFT,0x02,0x05,0x08,0x3c, 0x22,0x18,KEY_UP,KEY_DOWN,KEY_MINUS,0x37,KEY_SLASH,0x3b, 0x23,0x19,KEY_PAGEDOWN,KEY_RIGHT,0x0e,0x39,0x0f,0x01};struct km62kbd { unsigned char keycode[ARRAY_SIZE(km62kbd_keycode)]; struct input_dev *input; spinlock_t lock; struct timer_list timer; unsigned int suspended; unsigned long suspend_jiffies;};struct km62kbd *km62kbd;// 发送开始信号void IICStart(){ dpk_iic("IICStart\n"); ////////////////// // 函数的功能:给出如下时序 // SCL __--------_ // SDA x-----_____ // 并且SDA需要一定的建立和保持时间 // 首先要置SCL为0,否则当SCL置为1,此时如果SDA为0,则必须 // 在SCL为1时给出SDA的下跳沿,这就成了STOP信号 OUTP_SDA; SCL(0); SDA(1); SCL(1); // tSU: STA 起始信号建立时间,有一个最小值。需要一定的建立时间。 udelay(IIC_TSU_STA); // 给出下跳沿 SDA(0); // Thd:sta起始信号保持时间,有个最小值。起始信号不能太快。 udelay(IIC_THD_STA); // 结束 SCL(0);}// 发送停止信号void IICStop(){ dpk_iic("IICStop\n"); ////////////////// // 函数的功能:给出如下时序 // SCL __--------_ // SDA x_____----- // 需要一定的建立时间,之后就是总线空闲时间。 OUTP_SDA; SCL(0); SDA(0); SCL(1); // tSU: STO 停止信号建立时间。有最小时间。不能太快。 udelay(IIC_TSU_STO); // 给出上升沿 SDA(1); // 文档上没说多少保持时间,这里定为tSU: STO udelay(IIC_TSU_STO); // 结束// SCL(0); SCL(1);}// 向IIC发送一个字节void IICSendByte(BYTE value){ BYTE count; dpk_iic("IICSendByte: 0x%x\n",value); OUTP_SDA; // 从高位开始发 for(count = 8; count > 0; count--,value <<= 1) { //写bit:在SCL低电平时置SDA,等待Tsu:DAT时间,然后 //是SCL高电平,SCL低电平之后需要SDA保持THD:DAT时间。 SCL(0); udelay(IIC_THD_DAT); if(value & 0x80) SDA(1); else SDA(0); udelay(IIC_TSU_DAT); udelay(IIC_TLOW); // SCL的低电平至少保持这么长时间 SCL(1); udelay(IIC_THIGH); // SCL的高电平至少保持这么长时间 } SCL(0);}// 从IIC接受一个字节unsigned char IICRecvByte(){ BYTE count; BYTE value; dpk_iic("IICRecvByte :"); // 从高位开始接收 OUTP_SDA; SDA(1); // 在读取SDA的电平时先要置其为1 udelay(1); INP_SDA; for(count = 8,value = 0; count > 0; count--) { value <<= 1; // 读bit:SCL低电平以后在规定的时间TAA内数据在SDA上出现 // ,然后置SCL高,读取这个bit,然后置为低,数据还会保持 // TDH时间。 SCL(0); udelay(IIC_TAA); udelay(IIC_TLOW); // SCL的低电平至少保持这么长时间 SCL(1);//printk(" %x ",s3c2410_gpio_getpin(S3C2410_GPE15) >> 15); if (s3c2410_gpio_getpin(S3C2410_GPE15) >> 15) { value |= 1; } udelay(IIC_THIGH); // SCL的高电平至少保持这么长时间 } SCL(0); dpk_iic(" 0x%x\n",value); return value;}// 是否可以接收到一个应答信号unsigned char IICHasRecvAck(){ BYTE RetValue = 0; dpk_iic("IICHasRecvAck?"); OUTP_SDA; SDA(1); // 在读取SDA的电平时先要置其为1 // 读bit:SCL低电平以后在规定的时间TAA内数据在SDA上出现 // ,然后置SCL高,读取这个bit,然后置为低,数据还会保持 // TDH时间。 SCL(0); udelay(IIC_TAA); udelay(IIC_TLOW); // SCL的低电平至少保持这么长时间 SCL(1); INP_SDA; RetValue = s3c2410_gpio_getpin(S3C2410_GPE15) >> 15; udelay(IIC_THIGH); // SCL的高电平至少保持这么长时间 SCL(0); if(RetValue == 0) { printk(" - Y \n"); return 1; } else { printk(" - N \n"); return 0; }}// 发送一个应答信号给IICvoid IICSendAck(){ dpk_iic("IICSendAck\n"); //写bit:在SCL低电平时置SDA,等待Tsu:DAT时间,然后 //是SCL高电平,SCL低电平之后需要SDA保持THD:DAT时间。 OUTP_SDA; SCL(0); udelay(IIC_THD_DAT); SDA(0); udelay(IIC_TSU_DAT); udelay(IIC_TLOW); // SCL的低电平至少保持这么长时间 SCL(1); udelay(IIC_THIGH); // SCL的高电平至少保持这么长时间 SCL(0);}// 不发送应答信号,但是给出一个时钟void IICSendNoAck(){ dpk_iic("IICSendNoAck\n"); //写bit:在SCL低电平时置SDA,等待Tsu:DAT时间,然后 //是SCL高电平,SCL低电平之后需要SDA保持THD:DAT时间。 SCL(0); udelay(IIC_THD_DAT); OUTP_SDA; SDA(1); udelay(IIC_TSU_DAT); udelay(IIC_TLOW); // SCL的低电平至少保持这么长时间 SCL(1); udelay(IIC_THIGH); // SCL的高电平至少保持这么长时间 SCL(0);}// 检测IIC是否擦写完毕。// 在擦写过程中IIC不会相应总线。当IIC响应总线以后说明擦写完毕unsigned char IICCompleteBuf(BYTE SlaveAddr){ dpk_iic("IICCompleteBuf?\n\n"); IICStart(); IICSendByte(SlaveAddr | IIC_CTL_BYTE_W); return IICHasRecvAck();}/////////////////// 初始化函数// 上电以后需要等待TPURvoid IICInitial(){ udelay(IIC_TPUR);}//EEPROM写一个字节unsigned char IICWRITE_EEPROM_BYTE(BYTE * buf,BYTE addr){ dpk_iic("IICWRITE_EEPROM\n"); // 给一个起始信号 IICStart(); // 发送控制字 // 发送从器件地址,高5位为10100,然后是A2,A1,A0(如果和器 // 件的地址相同则那个器件会应答),读写控制(0为读)。 IICSendByte(IIC_ADDR_EEPROM | IIC_CTL_BYTE_W); // 器件是否应答 if(IICHasRecvAck()) { IICSendByte((BYTE)addr); // 应答 if(IICHasRecvAck()) { IICSendByte(*buf); // 应答,如果没有应答则退出 if(!IICHasRecvAck()) return 0; // 停止 IICStop(); // 等待写完毕 while(!IICCompleteBuf(IIC_ADDR_EEPROM)); } } return 1;}//EEPROM写一个字符串unsigned char IICWRITE_EEPROM_STR(BYTE * buf,BYTE addr,BYTE count){ int i; dpk_iic("IICWRITE_EEPROM_STR\n"); if (addr > 255) return 0; if (count > 255) return 0; if ((addr + count) > 255) count = 256 - addr; for(i=0;i<count;i++) { if ( IICWRITE_EEPROM_BYTE(buf,addr + i) == 0 ) return 0; buf ++; } return 1;}//EEPROM读一个字节unsigned char IICREAD_EEPROM_BYTE(BYTE * buf,BYTE addr){ dpk_iic("IICREAD_EEPROM\n"); ///////////////////// // 器件寻址 // 给一个起始信号 IICStart(); // 发送控制字 // 发送从器件地址,高5位为10100,然后是A2,A1,A0(如果和器 // 件的地址相同则那个器件会应答),读写控制(0为读)。 IICSendByte(IIC_ADDR_EEPROM | IIC_CTL_BYTE_W); // 器件是否应答 if(IICHasRecvAck()) { IICSendByte((BYTE)addr); // 应答 if(IICHasRecvAck()) { // 发送Start IICStart(); // 器件选择 IICSendByte(IIC_ADDR_EEPROM | IIC_CTL_BYTE_R); // 接收 if(IICHasRecvAck()) { *buf = IICRecvByte(); IICSendNoAck(); IICStop(); } } } return 1;}//EEPROM读一个字符串unsigned char IICREAD_EEPROM_STR(BYTE * buf,BYTE addr,BYTE count){ BYTE i; dpk_iic("IICREAD_EEPROM STRING\n"); ///////////////////// // 器件寻址 // 给一个起始信号 IICStart(); // 发送控制字 // 发送从器件地址,高5位为10100,然后是A2,A1,A0(如果和器 // 件的地址相同则那个器件会应答),读写控制(0为读)。 IICSendByte(IIC_ADDR_EEPROM | IIC_CTL_BYTE_W); // 器件是否应答 if(IICHasRecvAck()) { IICSendByte((BYTE)addr); // 应答 if(IICHasRecvAck()) { // 发送Start IICStart(); // 器件选择 IICSendByte(IIC_ADDR_EEPROM | IIC_CTL_BYTE_R); // 接收 if(IICHasRecvAck()) { for (i=0;i<count;i++) { *buf = IICRecvByte(); IICSendAck(); buf++; } IICSendNoAck(); IICStop(); } } } return 1;}//写FM五个字节unsigned char IICWRITE_FM(void){ int i; dpk_iic("IICWRITE_FM\n"); // 给一个起始信号 IICStart(); IICSendByte(IIC_ADDR_RADIO | IIC_CTL_BYTE_W); // 器件是否应答 if(IICHasRecvAck()) { // IICSendByte(IIC_ADDR_RADIO); // 应答// if(IICHasRecvAck()) { for(i=0;i<5;i++) { IICSendByte(fm_tx[i]); // 应答,如果没有应答则退出 if(!IICHasRecvAck()) return 0; } // 停止
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -