📄 gc_keyb.c
字号:
ret = read_SSP_response(2); unlock_smartio(&flags); // swap MSB & LSB ret = ((ret & 0xFF) << 8) | ((ret & 0xFF00) >> 8); ptr->DevType = (uint)ret; // Read Firmware Level lock_smartio(&flags); send_SSP_msg((unchar *) &READ_FWLEVEL_CMD, 2); ret = read_SSP_response(2); unlock_smartio(&flags); // swap MSB & LSB ret = ((ret & 0xFF) << 8) | ((ret & 0xFF00) >> 8); ptr->FwLevel = (uint)ret; return 0;}static ssize_t sio_read(struct file *file, char *buf, size_t count, loff_t *ppos){ struct inode *inode = file->f_dentry->d_inode; unsigned int minor = MINOR(inode->i_rdev); ushort *ret = (ushort *)buf; switch (minor) { case SMARTIO_ADC: if ((*ret = read_sio_adc(buf[0])) != 0xFFFF) return sizeof(ushort); // 2 bytes case SMARTIO_PORT_B: case SMARTIO_PORT_C: case SMARTIO_PORT_D: if ((*ret = read_sio_port(minor)) != 0xFFFF) return sizeof(ushort); case SMARTIO_VERSION: if ((read_sio_version((struct sio_ver *)buf)) != 0xFFFF) return sizeof(struct sio_ver); case SMARTIO_KEYPAD: if ((*ret = read_sio_kpd()) != 0xFFFF) return sizeof(ushort); case SMARTIO_KBD_SNIFFER: if ((*ret = read_sio_sniff()) != (ushort)-1) return 1; default : return -ENXIO; }}static SMARTIO_CMD WRITE_PORT_CMD = { 0x81, 0x00, { 0x00, 0x00 } };static SMARTIO_CMD SELECT_OPT_CMD = { 0x80, 0x00, { 0x00, 0x00 } };static SMARTIO_CMD CONTROL_BL_CMD = { 0x80, 0x00, { 0x00, 0x00 } };static SMARTIO_CMD CONTRAST_BL_CMD = { 0x80, 0x21, { 0x00, 0x00 } };static SMARTIO_CMD CONTROL_KPD_CMD = { 0x80, 0x27, { 0x00, 0x00 } };static SMARTIO_CMD CONTROL_VEE_CMD = { 0x80, 0x22, { 0x00, 0x00 } };static ushort write_sio_port(int port, unchar value){ unsigned long flags; if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D)) return 0xFFFF; WRITE_PORT_CMD.Code = (unchar) port; WRITE_PORT_CMD.Opt[0] = (unchar) value; lock_smartio(&flags); send_SSP_msg((unchar *) &WRITE_PORT_CMD, 3); unlock_smartio(&flags); return 0;}static ushort write_sio_select(unchar select){ unsigned long flags; if ((select < 1) || (select > 2)) return 0xFFFF; SELECT_OPT_CMD.Code = (unchar) (select + 0x28); lock_smartio(&flags); send_SSP_msg((unchar *) &SELECT_OPT_CMD, 2); unlock_smartio(&flags); return 0;}static ushort control_sio_backlite(int cmd, int value){ unsigned long flags; if (cmd == SMARTIO_BL_CONTRAST) { value &= 0xFF; CONTRAST_BL_CMD.Opt[0] = (unchar) value; lock_smartio(&flags); send_SSP_msg((unchar *) &CONTRAST_BL_CMD, 3); unlock_smartio(&flags); } else if (cmd == SMARTIO_BL_CONTROL) { if (value == 0x00) { // Backlite OFF CONTROL_BL_CMD.Code = 0x24; } else { // Backlite ON CONTROL_BL_CMD.Code = 0x23; } lock_smartio(&flags); send_SSP_msg((unchar *) &CONTROL_BL_CMD, 2); unlock_smartio(&flags); } else return 0xFFFF; return 0;}static ushort control_sio_keypad(int x, int y){ unsigned long flags; if ( (x<1) || (x>8) || (y<1) || (y>8)) { return 0xFFFF; } CONTROL_KPD_CMD.Opt[0] = (unchar) x; CONTROL_KPD_CMD.Opt[1] = (unchar) y; lock_smartio(&flags); send_SSP_msg((unchar *) &CONTROL_KPD_CMD, 4); unlock_smartio(&flags); return 0;}static ushort control_sio_vee(int value){ unsigned long flags; value &= 0xFF; CONTROL_VEE_CMD.Opt[0] = (unchar) value; lock_smartio(&flags); send_SSP_msg((unchar *) &CONTROL_VEE_CMD, 3); unlock_smartio(&flags); return 0;}static ssize_t sio_write(struct file *file, const char *buf, size_t cont, loff_t *ppos){ struct inode *inode = file->f_dentry->d_inode; unsigned int minor = MINOR(inode->i_rdev); switch (minor) { case SMARTIO_PORT_B: case SMARTIO_PORT_C: case SMARTIO_PORT_D: if (write_sio_port(minor, buf[0]) != 0xFFFF) return 1; case SMARTIO_SELECT_OPTION: if (write_sio_select(buf[0]) != 0xFFFF) return 1; case SMARTIO_BACKLITE: if (control_sio_backlite(SMARTIO_BL_CONTROL, buf[0]) != 0xFFFF) return 1; case SMARTIO_KEYPAD: if (control_sio_keypad(buf[0], buf[1]) != 0xFFFF) return 2; case SMARTIO_VEE_PWM: if (control_sio_vee(buf[0]) != 0xFFFF) return 1; case SMARTIO_KBD_SNIFFER: // here are the scancodes injected handle_scancode((unchar)buf[0], (buf[0] & 0x80) ? 0 : 1); wake_up_interruptible(&keyboard_done_queue); // give some time to process! File IO is a bit faster than manual typing ;-) udelay(10000); return 1; default: return -ENXIO; }}static unsigned int sio_poll(struct file *file, struct poll_table_struct *wait){ return 0;}static SMARTIO_CMD IOCTL_PORT_CMD = { 0x81, 0x00, { 0x00, 0x00 } };static ushort ioctl_sio_port(int port, unchar value){ unsigned long flags; if ((port < SMARTIO_PORT_B) || (port > SMARTIO_PORT_D)) return 0xFFFF; IOCTL_PORT_CMD.Code = (unchar) port + 0x04; // 0x05 ~ 0x08 if (port == SMARTIO_PORT_B) { // Port B has 4 bits only IOCTL_PORT_CMD.Opt[0] = (unchar) value & 0x0F; } else IOCTL_PORT_CMD.Opt[0] = (unchar) value; lock_smartio(&flags); send_SSP_msg((unchar *) &IOCTL_PORT_CMD, 3); unlock_smartio(&flags); return 0;}static int sio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ unsigned int minor = MINOR(inode->i_rdev); unchar *buf = (unchar *)arg; switch (minor) { case SMARTIO_PORT_B: case SMARTIO_PORT_C: case SMARTIO_PORT_D: if (cmd == SMARTIO_PORT_CONFIG) { if (ioctl_sio_port(minor, buf[0]) != 0xFFFF) return 0; } return -EINVAL; case SMARTIO_SELECT_OPTION: if (write_sio_select(buf[0]) != 0xFFFF) return 0; return -EINVAL; case SMARTIO_BACKLITE: if (cmd == SMARTIO_BL_CONTROL) { if (control_sio_backlite(SMARTIO_BL_CONTROL, buf[0]) != 0xFFFF) return 0; } else if (cmd == SMARTIO_BL_CONTRAST) { if (control_sio_backlite(SMARTIO_BL_CONTRAST, buf[0]) != 0xFFFF) return 0; } else return -EINVAL; case SMARTIO_KEYPAD: if (cmd == SMARTIO_KPD_TIMEOUT) { kpd_timeout = *(long*)buf; return 0; } else if (cmd == SMARTIO_KPD_SETUP) { if (control_sio_keypad(buf[0], buf[1]) != 0xFFFF) return 0; } return -EINVAL; case SMARTIO_VEE_PWM: if (control_sio_vee(buf[0]) != 0xFFFF) return 0; return -EINVAL; case SMARTIO_KBD_SNIFFER: if (cmd == SMARTIO_SNIFFER_TIMEOUT) { sniffer_timeout = *(long*)buf; if (sniffer_timeout < 0) sniffer_timeout = -1; // the value will be devided by 10 later on if (!sniffer_timeout) sniffer_timeout = 10; return 0; } return -EINVAL; default: return -ENXIO; }}static int sio_open(struct inode *inode, struct file *file){ unsigned int minor = MINOR(inode->i_rdev); // we open all by default. we only have a special handler for the kbd sniffer switch (minor) { case SMARTIO_KBD_SNIFFER: if (sniffer_in_use) return -EBUSY; sniffer_in_use = 1; SNIFFER = 1; // sniff in active or passive mode if ((file->f_flags & O_RDWR) == O_RDWR) SNIFFMODE = 1; else SNIFFMODE = 0; // do we have a blocking or non blocking sniffer? if ((file->f_flags & O_NONBLOCK) == O_NONBLOCK) sniffer_timeout = 100; else sniffer_timeout = -1; break; default: break; } return 0;}static int sio_close(struct inode *inode, struct file *file){ unsigned int minor = MINOR(inode->i_rdev); switch (minor) { case SMARTIO_KBD_SNIFFER: SNIFFER = 0; SNIFFMODE = 0; sniffer_in_use = 0; break; default: break; } return 0;}static struct file_operations sio_fops = { read: sio_read, write: sio_write, poll: sio_poll, ioctl: sio_ioctl, open: sio_open, release: sio_close,};static struct proc_dir_entry *sio_dir, *parent_dir = NULL;#define SMARTIO_MAJOR 58#define MAJOR_NR SMARTIO_MAJOR#define PROC_NAME "sio"static int sio_read_proc(char *buf, char **start, off_t pos, int count, int *eof, void *data){ char *p = buf; p += sprintf(p, "ADS SMARTIO Status: \n"); p += sprintf(p, "\t Keyboard Interrupt : %lu\n", kbd_int); p += sprintf(p, "\t Keypad Interrupt : %lu\n", kpd_int); p += sprintf(p, "\t ADC Interrupt : %lu\n", adc_int); p += sprintf(p, "\t Keyboard Sniffer : %s mode : %s\n", kbd_sniff[ SNIFFER ], kbd_sniff_mode [ SNIFFMODE ]); return (p-buf);}#ifdef CONFIG_PMstatic int pm_smartio_callback(struct pm_dev *dev, pm_request_t rqst, void *data){ switch (rqst) { case PM_RESUME: gc_sio_init(); break; case PM_SUSPEND: // 4/5/01 Woojung // It checks Keybard received pair of press/release code. // System can sleep before receiving release code if (kbd_press_flag) { interruptible_sleep_on(&keyboard_done_queue); } break; } return 0;}#endifvoid __init sio_init(void){ if (register_chrdev(MAJOR_NR, "sio", &sio_fops)) { printk("smartio : unable to get major %d\n", MAJOR_NR); return; } else { printk("smartio driver initialized. version %s, date:%s\n", smartio_version, smartio_date); if (sio_reset_flag != 1) { gc_sio_init(); if (request_irq(ADS_AVR_IRQ, gc_sio_interrupt,0,"sio",NULL) != 0){ printk("smartio : Could not allocate IRQ!\n"); return; } } if ((sio_dir = create_proc_entry(PROC_NAME, 0, parent_dir)) == NULL) { printk("smartio : Unable to create /proc entry\n"); return; } else { sio_dir->read_proc = sio_read_proc;#ifdef CONFIG_PM pm_register(PM_SYS_DEV, PM_SYS_KBC, pm_smartio_callback);#endif } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -