📄 gc_keyb.c
字号:
ulong ret; // discard leading 0x00 and command echo 0 (command group value) while (ReadSSPByte() == 0); // discard command echo 1 (command code value) ReadSSPByte(); // data from SMARTIO // It assumes LSB first. // NOTE:Some command uses MSB first order ret = 0; for (i=0;i<num;i++) { ret |= ReadSSPByte() << (8*i); } return ret;}typedef struct t_SMARTIO_CMD { unchar Group; unchar Code; unchar Opt[2];} SMARTIO_CMD;static SMARTIO_CMD RD_INT_CMD = { 0x83, 0x01, { 0x00, 0x00 } };static SMARTIO_CMD RD_KBD_CMD = { 0x83, 0x02, { 0x00, 0x00 } };static SMARTIO_CMD RD_ADC_CMD = { 0x83, 0x28, { 0x00, 0x00 } };static SMARTIO_CMD RD_KPD_CMD = { 0x83, 0x04, { 0x00, 0x00 } };static volatile ushort adc_value;static volatile unchar kpd_value;static unsigned int kpd_timeout = 10000; // 10000 msecstatic ulong kbd_int, kpd_int, adc_int;static void smartio_interrupt_task(void *data);static struct tq_struct tq_smartio = { { NULL, NULL }, // struct list_head 0, // unsigned long sync smartio_interrupt_task, // void (*routine)(void *) NULL, // void *data};DECLARE_WAIT_QUEUE_HEAD(smartio_queue);DECLARE_WAIT_QUEUE_HEAD(smartio_adc_queue);DECLARE_WAIT_QUEUE_HEAD(smartio_kpd_queue);DECLARE_WAIT_QUEUE_HEAD(keyboard_done_queue);DECLARE_WAIT_QUEUE_HEAD(sniffer_queue);static spinlock_t smartio_busy_lock = SPIN_LOCK_UNLOCKED;static atomic_t smartio_busy = ATOMIC_INIT(0);static int f_five_pressed = 0;static int f_seven_pressed = 0;//static int e_null_counter = 0;//static int f_null_counter = 0;//static int keydown = 0;static unchar previous_code = 0;//static int e0 = 0;static void smartio_interrupt_task(void *arg){ unchar code; unsigned long flags; unchar dummy; spin_lock_irqsave(&smartio_busy_lock, flags); if (atomic_read(&smartio_busy) == 1) { spin_unlock_irqrestore(&smartio_busy_lock, flags); queue_task(&tq_smartio, &tq_timer); } else { atomic_set(&smartio_busy, 1); spin_unlock_irqrestore(&smartio_busy_lock, flags); } /* Read SMARTIO Interrupt Status to check which Interrupt is occurred * and Clear SMARTIO Interrupt */ send_SSP_msg((unchar *) &RD_INT_CMD, 2); code = (unchar) (read_SSP_response(1) & 0xFF);#ifdef CONFIG_VT if (code & 0x04) { // Keyboard Interrupt kbd_int++; /* Read Scan code */ send_SSP_msg((unchar *) &RD_KBD_CMD, 2); code = (unchar) (read_SSP_response(1) & 0xFF); dummy = code & 0x80; if ((code == 0xE0) || (code == 0xE1) || (code == 0xF0)) { // combined code if (code == 0xF0) { if (!previous_code) { code = 0xE0; previous_code = 0xF0; } else { code = mf_two_kbdmap[code & 0x7F] | dummy; previous_code = 0; } } else if (code == 0xE0) { if (previous_code != 0) { code = mf_two_kbdmap[code & 0x7F] | dummy; previous_code = 0; } else previous_code = code; } else { // 0xE1 if (!previous_code) { code = mf_two_kbdmap[code &0x7F] | dummy; previous_code = 0; } else { previous_code = code; } } } else { if (code == 0x03) { f_five_pressed = 1; } else if (code == 0x83) { if (f_five_pressed != 0) { f_five_pressed = 0; code = 0x03; } else if (f_seven_pressed == 0) { f_seven_pressed = 1; code = 2; dummy = 0; } else { f_seven_pressed = 0; code = 2; } } previous_code = 0; code &= 0x7F; code = mf_two_kbdmap[code] | dummy; } sniffed_value = (ushort)code; if (SNIFFER) wake_up_interruptible(&sniffer_queue); if (SNIFFMODE == PASSIVE) { handle_scancode( code, (code & 0x80) ? 0 : 1 ); if (code & 0x80) { wake_up_interruptible(&keyboard_done_queue); mdelay(10); // this makes the whole thing a bit more stable // keyboard handling can be corrupted when hitting // thousands of keys like crazy. kbd_translate might catch up // with irq routine? or there is simply a buffer overflow on // the serial device? somehow it looses some key sequences. // if a break code is lost or coruppted the keyboard starts // to autorepeat like crazy and appears to hang. // this needs further investigations! Thomas kbd_press_flag = 0; } else kbd_press_flag = 1; } code = 0; // prevent furthermore if ... then to react! }#endif // ADC resolution is 10bit (0x000 ~ 0x3FF) if (code & 0x02) { // ADC Complete Interrupt adc_int++; send_SSP_msg((unchar *) &RD_ADC_CMD, 2); adc_value = (ushort) (read_SSP_response(2) & 0x3FF); wake_up_interruptible(&smartio_adc_queue); } if (code & 0x08) { // Keypad interrupt kpd_int++; send_SSP_msg((unchar *) &RD_KPD_CMD, 2); kpd_value = (unchar) (read_SSP_response(1) & 0xFF); wake_up_interruptible(&smartio_kpd_queue); } spin_lock_irqsave(&smartio_busy_lock, flags); atomic_set(&smartio_busy, 0); spin_unlock_irqrestore(&smartio_busy_lock, flags); enable_irq(ADS_AVR_IRQ); wake_up_interruptible(&smartio_queue);}static void gc_sio_interrupt(int irq, void *dev_id, struct pt_regs *regs){#ifdef CONFIG_VT kbd_pt_regs = regs;#endif // *NOTE* // ADS SMARTIO interrupt is cleared after reading interrupt status // from smartio. // disable SMARTIO IRQ here and re-enable at samrtio_bh. // 11/13/00 Woojung disable_irq(ADS_AVR_IRQ); queue_task(&tq_smartio, &tq_immediate); mark_bh(IMMEDIATE_BH);}char gc_kbd_unexpected_up(unsigned char keycode){ return 0;}static inline void gc_sio_init(void){ GPDR |= (GPIO_GPIO10 | GPIO_GPIO12 | GPIO_GPIO13); // Output GPDR &= ~GPIO_GPIO11; // Alternative Function GAFR |= (GPIO_GPIO10 | GPIO_GPIO11 | GPIO_GPIO12 | GPIO_GPIO13); Ser4SSCR0 = 0xA707; Ser4SSSR = SSSR_ROR; Ser4SSCR1 = 0x0010; Ser4SSCR0 = 0xA787; // Reset SMARTIO ADS_AVR_REG &= 0xFE; mdelay(300); // 10 mSec ADS_AVR_REG |= 0x01; mdelay(10); // 10 mSec}void __init gc_kbd_init_hw(void){ printk (KERN_INFO "Graphics Client keyboard driver v1.0\n"); k_setkeycode = gc_kbd_setkeycode; k_getkeycode = gc_kbd_getkeycode; k_translate = gc_kbd_translate; k_unexpected_up = gc_kbd_unexpected_up;#ifdef CONFIG_MAGIC_SYSRQ k_sysrq_key = 0x54; /* sysrq table??? --rmk */#endif gc_sio_init(); if (request_irq(ADS_AVR_IRQ,gc_sio_interrupt,0,"smartio", NULL) != 0) printk("Could not allocate SMARTIO IRQ!\n"); sio_reset_flag = 1;}/* SMARTIO ADC Interface */#define SMARTIO_VERSION 0#define SMARTIO_PORT_A 1#define SMARTIO_PORT_B 2#define SMARTIO_PORT_C 3#define SMARTIO_PORT_D 4#define SMARTIO_SELECT_OPTION 5#define SMARTIO_BACKLITE 6#define SMARTIO_KEYPAD 7#define SMARTIO_ADC 8#define SMARTIO_VEE_PWM 9#define SMARTIO_SLEEP 11#define SMARTIO_KBD_SNIFFER 12static SMARTIO_CMD CONV_ADC_CMD = { 0x80, 0x28, { 0x00, 0x00 } };static SMARTIO_CMD READ_PORT_CMD = { 0x82, 0x00, { 0x00, 0x00 } };static SMARTIO_CMD READ_DEVVER_CMD = { 0x82, 0x05, { 0x00, 0x00 } };static SMARTIO_CMD READ_DEVTYPE_CMD = { 0x82, 0x06, { 0x00, 0x00 } };static SMARTIO_CMD READ_FWLEVEL_CMD = { 0x82, 0x07, { 0x00, 0x00 } };static int lock_smartio(unsigned long *flags){ spin_lock_irqsave(&smartio_busy_lock, *flags); if (atomic_read(&smartio_busy) == 1) { spin_unlock_irqrestore(&smartio_busy_lock, *flags); interruptible_sleep_on(&smartio_queue); } else { atomic_set(&smartio_busy, 1); spin_unlock_irqrestore(&smartio_busy_lock, *flags); } return 1;}static int unlock_smartio(unsigned long *flags){ spin_lock_irqsave(&smartio_busy_lock, *flags); atomic_set(&smartio_busy, 0); spin_unlock_irqrestore(&smartio_busy_lock, *flags); return 1;}static ushort read_sio_adc(int channel){ unsigned long flags; if ((channel < 0) || (channel > 7)) return 0xFFFF; CONV_ADC_CMD.Opt[0] = (unchar) channel; lock_smartio(&flags); send_SSP_msg((unchar *) &CONV_ADC_CMD, 3); unlock_smartio(&flags); interruptible_sleep_on(&smartio_adc_queue); return adc_value & 0x3FF;}static ushort read_sio_port(int port){ unsigned long flags; ushort ret; if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D)) return 0xFFFF; READ_PORT_CMD.Code = (unchar) port; lock_smartio(&flags); send_SSP_msg((unchar *) &READ_PORT_CMD, 2); ret = read_SSP_response(1); unlock_smartio(&flags); return ret;}static ushort read_sio_kpd(void){ long timeout; // kpd_timeout is mSec order // interrupt_sleep_on_timeout is based on 10msec timer tick if (kpd_timeout == -1) { interruptible_sleep_on(&smartio_kpd_queue); } else { timeout = interruptible_sleep_on_timeout(&smartio_kpd_queue, kpd_timeout/10); if (timeout == 0) { // timeout without keypad input return 0xFFFF; } } return kpd_value;}static ushort read_sio_sniff(void){ long timeout; // kpd_timeout is mSec order // interrupt_sleep_on_timeout is based on 10msec timer tick if (sniffer_timeout == -1) { interruptible_sleep_on(&sniffer_queue); } else { timeout = interruptible_sleep_on_timeout(&sniffer_queue, sniffer_timeout/10); if (timeout == 0) { // timeout without keypad input return -1; } } return (ushort)sniffed_value;}static struct sio_ver { uint DevVer; uint DevType; uint FwLevel;};static ushort read_sio_version(struct sio_ver *ptr){ unsigned long flags; ushort ret; // Read Device Version lock_smartio(&flags); send_SSP_msg((unchar *) &READ_DEVVER_CMD, 2); ret = read_SSP_response(1); unlock_smartio(&flags); ptr->DevVer = (uint)ret; // Read Device Type lock_smartio(&flags); send_SSP_msg((unchar *) &READ_DEVTYPE_CMD, 2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -