2 * This is IVTC ODM project to use Moxa CPU for keypad device driver.
3 * It is from misc interface. So the device node major number is 10.
4 * The device node minor number is following:
7 * There devices are mapping system memory is following:
8 * keypad: 0x04004000 write for out, read for in
12 * 12-05-2005 Victor Yu. Create it.
14 #include <linux/config.h>
15 #include <asm/arch/moxa.h>
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/types.h>
19 #include <linux/miscdevice.h>
20 #include <linux/fcntl.h>
21 #include <linux/init.h>
22 #include <linux/poll.h>
23 #include <linux/proc_fs.h>
24 #include <linux/spinlock.h>
25 #include <linux/delay.h>
26 #include <linux/rtc.h>
27 #include <linux/timer.h>
28 #include <linux/ioport.h>
31 #include <asm/uaccess.h>
32 #include <asm/system.h>
34 #define KEYPAD_OUT_ADDR 0x84008000
35 #define KEYPAD_IN_ADDR 0x84008000
36 #define KEYPAD_RAW_NO 4
37 #define KEYPAD_COL_NO 6
39 #define MOXA_KEYPAD_MINOR 103
41 static spinlock_t keypad_lock
= SPIN_LOCK_UNLOCKED
;
44 // keypad file operation function call
46 #define IOCTL_KEYPAD_HAS_PRESS 1
47 #define IOCTL_KEYPAD_GET_KEY 2
48 #define IOCTL_KEYPAD_PRESS_TWICE 3
50 #define KEYPAD_BUFFER_LENGTH 32
51 #define KEYPAD_BUFFER_MASK (KEYPAD_BUFFER_LENGTH-1)
52 #define KEYPAD_POLL_TIME (HZ/5)
54 static int keypad_wptr
=0, keypad_rptr
=0;
55 static unsigned int keypad_buffer
[KEYPAD_BUFFER_LENGTH
];
56 static unsigned int keypadold
;
57 static struct timer_list keypadtimer
;
58 static int keypadtimer_on
=0;
59 static int keypad_opened
=0;
61 static unsigned int keypad_scan(void)
63 unsigned int ret
=0, v
;
67 for ( col
=0; col
<KEYPAD_COL_NO
;) {
68 outw((1<<col
), KEYPAD_OUT_ADDR
);
70 v
= inw(KEYPAD_IN_ADDR
) & 0x0f;
71 ret
|= (v
<< (col
*4));
76 static int press_twice
= 0 ;
77 static void keypad_poll(unsigned long ingore
)
81 spin_lock(&keypad_lock
);
82 del_timer(&keypadtimer
);
84 if ( keypad_opened
<= 0 ) {
85 spin_unlock(&keypad_lock
);
91 if ( v
&& v1
&& (keypad_wptr
+1) != keypad_rptr
) {
93 unsigned char bits
= 0 ;
95 for(index
=0;index
<24;index
++)
105 keypad_buffer
[keypad_wptr
++] = v
;
106 keypad_wptr
&= KEYPAD_BUFFER_MASK
;
110 keypadtimer
.function
= keypad_poll
;
111 keypadtimer
.expires
= jiffies
+ KEYPAD_POLL_TIME
;
113 add_timer(&keypadtimer
);
114 spin_unlock(&keypad_lock
);
117 static int keypad_ioctl(struct inode
*inode
, struct file
*file
, unsigned int cmd
, unsigned long arg
)
122 case IOCTL_KEYPAD_PRESS_TWICE
:
123 if ( copy_to_user((void *)arg
, &press_twice
, sizeof(int)) )
126 case IOCTL_KEYPAD_HAS_PRESS
:
127 spin_lock(&keypad_lock
);
129 v
= (keypad_wptr
- keypad_rptr
) & KEYPAD_BUFFER_MASK
;
131 if ( keypad_wptr
== keypad_rptr
)
136 spin_unlock(&keypad_lock
);
137 if ( copy_to_user((void *)arg
, &v
, sizeof(int)) )
140 case IOCTL_KEYPAD_GET_KEY
:
141 spin_lock(&keypad_lock
);
142 if ( keypad_wptr
== keypad_rptr
)
145 v
= keypad_buffer
[keypad_rptr
++];
146 keypad_rptr
&= KEYPAD_BUFFER_MASK
;
148 spin_unlock(&keypad_lock
);
149 if ( copy_to_user((void *)arg
, &v
, sizeof(int)) )
159 static int keypad_open(struct inode
*inode
, struct file
*file
)
161 if ( MINOR(inode
->i_rdev
) != MOXA_KEYPAD_MINOR
)
163 spin_lock(&keypad_lock
);
164 if ( keypad_opened
== 0 ) {
165 keypad_wptr
= keypad_rptr
= 0;
166 keypadold
= keypad_scan();
167 keypadtimer
.function
= keypad_poll
;
168 keypadtimer
.expires
= jiffies
+ KEYPAD_POLL_TIME
;
170 add_timer(&keypadtimer
);
173 spin_unlock(&keypad_lock
);
177 static int keypad_release(struct inode
*inode
, struct file
*file
)
179 spin_lock(&keypad_lock
);
180 if ( keypad_opened
> 0 ) {
182 if ( keypad_opened
== 0 ) {
183 if ( keypadtimer_on
) {
184 del_timer(&keypadtimer
);
187 keypad_wptr
= keypad_rptr
= 0;
190 spin_unlock(&keypad_lock
);
194 static struct file_operations keypad_fops
= {
199 release
:keypad_release
,
201 static struct miscdevice keypad_dev
= {
207 static void __exit
ivtc_keypad_exit(void)
209 spin_lock(&keypad_lock
);
210 if ( keypadtimer_on
) {
211 del_timer(&keypadtimer
);
214 spin_unlock(&keypad_lock
);
215 misc_deregister(&keypad_dev
);
218 static int __init
ivtc_keypad_init(void)
220 printk("Moxa CPU misc: Register Keypad misc ver1.0 ");
221 if ( misc_register(&keypad_dev
) ) {
225 init_timer(&keypadtimer
);
231 module_init(ivtc_keypad_init
);
232 module_exit(ivtc_keypad_exit
);
234 MODULE_AUTHOR("Victor Yu");
235 MODULE_LICENSE("GPL");