diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/Kconfig | 10 | ||||
-rw-r--r-- | drivers/char/Makefile | 1 | ||||
-rw-r--r-- | drivers/char/agp/generic.c | 2 | ||||
-rw-r--r-- | drivers/char/bsr.c | 2 | ||||
-rw-r--r-- | drivers/char/i8k.c | 21 | ||||
-rw-r--r-- | drivers/char/isicom.c | 8 | ||||
-rw-r--r-- | drivers/char/keyboard.c | 325 | ||||
-rw-r--r-- | drivers/char/n_gsm.c | 2763 | ||||
-rw-r--r-- | drivers/char/pcmcia/cm4000_cs.c | 9 | ||||
-rw-r--r-- | drivers/char/pcmcia/cm4040_cs.c | 5 | ||||
-rw-r--r-- | drivers/char/pcmcia/ipwireless/main.c | 19 | ||||
-rw-r--r-- | drivers/char/pcmcia/ipwireless/main.h | 1 | ||||
-rw-r--r-- | drivers/char/pcmcia/ipwireless/tty.c | 19 | ||||
-rw-r--r-- | drivers/char/pcmcia/ipwireless/tty.h | 3 | ||||
-rw-r--r-- | drivers/char/pcmcia/synclink_cs.c | 22 | ||||
-rw-r--r-- | drivers/char/serial167.c | 225 | ||||
-rw-r--r-- | drivers/char/sysrq.c | 245 | ||||
-rw-r--r-- | drivers/char/tpm/Kconfig | 6 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.c | 47 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis.c | 40 | ||||
-rw-r--r-- | drivers/char/tty_buffer.c | 2 | ||||
-rw-r--r-- | drivers/char/tty_io.c | 1 |
22 files changed, 3250 insertions, 526 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 3141dd3b6e5..e21175be25d 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -276,11 +276,19 @@ config N_HDLC Allows synchronous HDLC communications with tty device drivers that support synchronous HDLC such as the Microgate SyncLink adapter. - This driver can only be built as a module ( = code which can be + This driver can be built as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called n_hdlc. If you want to do that, say M here. +config N_GSM + tristate "GSM MUX line discipline support (EXPERIMENTAL)" + depends on EXPERIMENTAL + depends on NET + help + This line discipline provides support for the GSM MUX protocol and + presents the mux as a set of 61 individual tty devices. + config RISCOM8 tristate "SDL RISCom/8 card support" depends on SERIAL_NONSTANDARD diff --git a/drivers/char/Makefile b/drivers/char/Makefile index f957edf7e45..d39be4cf1f5 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_SYNCLINK) += synclink.o obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o obj-$(CONFIG_N_HDLC) += n_hdlc.o +obj-$(CONFIG_N_GSM) += n_gsm.o obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o obj-$(CONFIG_SX) += sx.o generic_serial.o obj-$(CONFIG_RIO) += rio/ generic_serial.o diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index fb86708e47e..4b51982fd23 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -1214,7 +1214,7 @@ struct agp_memory *agp_generic_alloc_user(size_t page_count, int type) return NULL; for (i = 0; i < page_count; i++) - new->pages[i] = 0; + new->pages[i] = NULL; new->page_count = 0; new->type = type; new->num_scratch_pages = pages; diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index 7fef305774d..89d871ef8c2 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c @@ -253,7 +253,7 @@ static int bsr_add_node(struct device_node *bn) cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev, cur, cur->bsr_name); - if (!cur->bsr_device) { + if (IS_ERR(cur->bsr_device)) { printk(KERN_ERR "device_create failed for %s\n", cur->bsr_name); cdev_del(&cur->bsr_cdev); diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index fc8cf7ac7f2..4cd8b227c11 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c @@ -23,6 +23,7 @@ #include <linux/seq_file.h> #include <linux/dmi.h> #include <linux/capability.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -82,8 +83,7 @@ module_param(fan_mult, int, 0); MODULE_PARM_DESC(fan_mult, "Factor to multiply fan speed with"); static int i8k_open_fs(struct inode *inode, struct file *file); -static int i8k_ioctl(struct inode *, struct file *, unsigned int, - unsigned long); +static long i8k_ioctl(struct file *, unsigned int, unsigned long); static const struct file_operations i8k_fops = { .owner = THIS_MODULE, @@ -91,7 +91,7 @@ static const struct file_operations i8k_fops = { .read = seq_read, .llseek = seq_lseek, .release = single_release, - .ioctl = i8k_ioctl, + .unlocked_ioctl = i8k_ioctl, }; struct smm_regs { @@ -307,8 +307,8 @@ static int i8k_get_dell_signature(int req_fn) return regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1; } -static int i8k_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, - unsigned long arg) +static int +i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg) { int val = 0; int speed; @@ -395,6 +395,17 @@ static int i8k_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, return 0; } +static long i8k_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) +{ + long ret; + + lock_kernel(); + ret = i8k_ioctl_unlocked(fp, cmd, arg); + unlock_kernel(); + + return ret; +} + /* * Print the information for /proc/i8k. */ diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index c1ab303455c..98310e1aae3 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -1573,11 +1573,16 @@ static int __devinit isicom_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device); /* allot the first empty slot in the array */ - for (index = 0; index < BOARD_COUNT; index++) + for (index = 0; index < BOARD_COUNT; index++) { if (isi_card[index].base == 0) { board = &isi_card[index]; break; } + } + if (index == BOARD_COUNT) { + retval = -ENODEV; + goto err_disable; + } board->index = index; board->base = pci_resource_start(pdev, 3); @@ -1624,6 +1629,7 @@ errunrr: errdec: board->base = 0; card_count--; +err_disable: pci_disable_device(pdev); err: return retval; diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index ada25bb8941..54109dc9240 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -24,6 +24,8 @@ * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik) */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/consolemap.h> #include <linux/module.h> #include <linux/sched.h> @@ -38,7 +40,6 @@ #include <linux/kbd_kern.h> #include <linux/kbd_diacr.h> #include <linux/vt_kern.h> -#include <linux/sysrq.h> #include <linux/input.h> #include <linux/reboot.h> #include <linux/notifier.h> @@ -82,8 +83,7 @@ void compute_shiftstate(void); typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value, char up_flag); static k_handler_fn K_HANDLERS; -k_handler_fn *k_handler[16] = { K_HANDLERS }; -EXPORT_SYMBOL_GPL(k_handler); +static k_handler_fn *k_handler[16] = { K_HANDLERS }; #define FN_HANDLERS\ fn_null, fn_enter, fn_show_ptregs, fn_show_mem,\ @@ -133,7 +133,7 @@ static struct input_handler kbd_handler; static DEFINE_SPINLOCK(kbd_event_lock); static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; /* keyboard key bitmap */ static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ -static int dead_key_next; +static bool dead_key_next; static int npadch = -1; /* -1 or number assembled on pad */ static unsigned int diacr; static char rep; /* flag telling character repeat */ @@ -147,22 +147,6 @@ static struct ledptr { unsigned char valid:1; } ledptrs[3]; -/* Simple translation table for the SysRq keys */ - -#ifdef CONFIG_MAGIC_SYSRQ -unsigned char kbd_sysrq_xlate[KEY_MAX + 1] = - "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ - "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ - "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ - "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ - "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ - "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ - "\r\000/"; /* 0x60 - 0x6f */ -static int sysrq_down; -static int sysrq_alt_use; -#endif -static int sysrq_alt; - /* * Notifier list for console keyboard events */ @@ -361,8 +345,8 @@ static void to_utf8(struct vc_data *vc, uint c) /* 110***** 10****** */ put_queue(vc, 0xc0 | (c >> 6)); put_queue(vc, 0x80 | (c & 0x3f)); - } else if (c < 0x10000) { - if (c >= 0xD800 && c < 0xE000) + } else if (c < 0x10000) { + if (c >= 0xD800 && c < 0xE000) return; if (c == 0xFFFF) return; @@ -370,7 +354,7 @@ static void to_utf8(struct vc_data *vc, uint c) put_queue(vc, 0xe0 | (c >> 12)); put_queue(vc, 0x80 | ((c >> 6) & 0x3f)); put_queue(vc, 0x80 | (c & 0x3f)); - } else if (c < 0x110000) { + } else if (c < 0x110000) { /* 11110*** 10****** 10****** 10****** */ put_queue(vc, 0xf0 | (c >> 18)); put_queue(vc, 0x80 | ((c >> 12) & 0x3f)); @@ -469,6 +453,7 @@ static void fn_enter(struct vc_data *vc) } diacr = 0; } + put_queue(vc, 13); if (vc_kbd_mode(kbd, VC_CRLF)) put_queue(vc, 10); @@ -478,6 +463,7 @@ static void fn_caps_toggle(struct vc_data *vc) { if (rep) return; + chg_vc_kbd_led(kbd, VC_CAPSLOCK); } @@ -485,12 +471,14 @@ static void fn_caps_on(struct vc_data *vc) { if (rep) return; + set_vc_kbd_led(kbd, VC_CAPSLOCK); } static void fn_show_ptregs(struct vc_data *vc) { struct pt_regs *regs = get_irq_regs(); + if (regs) show_regs(regs); } @@ -515,7 +503,7 @@ static void fn_hold(struct vc_data *vc) static void fn_num(struct vc_data *vc) { - if (vc_kbd_mode(kbd,VC_APPLIC)) + if (vc_kbd_mode(kbd, VC_APPLIC)) applkey(vc, 'P', 1); else fn_bare_num(vc); @@ -610,7 +598,7 @@ static void fn_boot_it(struct vc_data *vc) static void fn_compose(struct vc_data *vc) { - dead_key_next = 1; + dead_key_next = true; } static void fn_spawn_con(struct vc_data *vc) @@ -657,7 +645,7 @@ static void k_spec(struct vc_data *vc, unsigned char value, char up_flag) static void k_lowercase(struct vc_data *vc, unsigned char value, char up_flag) { - printk(KERN_ERR "keyboard.c: k_lowercase was called - impossible\n"); + pr_err("k_lowercase was called - impossible\n"); } static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag) @@ -669,7 +657,7 @@ static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag) value = handle_diacr(vc, value); if (dead_key_next) { - dead_key_next = 0; + dead_key_next = false; diacr = value; return; } @@ -691,6 +679,7 @@ static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag) { if (up_flag) return; + diacr = (diacr ? handle_diacr(vc, value) : value); } @@ -710,29 +699,28 @@ static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag) static void k_dead(struct vc_data *vc, unsigned char value, char up_flag) { static const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' }; - value = ret_diacr[value]; - k_deadunicode(vc, value, up_flag); + + k_deadunicode(vc, ret_diacr[value], up_flag); } static void k_cons(struct vc_data *vc, unsigned char value, char up_flag) { if (up_flag) return; + set_console(value); } static void k_fn(struct vc_data *vc, unsigned char value, char up_flag) { - unsigned v; - if (up_flag) return; - v = value; - if (v < ARRAY_SIZE(func_table)) { + + if ((unsigned)value < ARRAY_SIZE(func_table)) { if (func_table[value]) puts_queue(vc, func_table[value]); } else - printk(KERN_ERR "k_fn called with value=%d\n", value); + pr_err("k_fn called with value=%d\n", value); } static void k_cur(struct vc_data *vc, unsigned char value, char up_flag) @@ -741,6 +729,7 @@ static void k_cur(struct vc_data *vc, unsigned char value, char up_flag) if (up_flag) return; + applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE)); } @@ -758,43 +747,45 @@ static void k_pad(struct vc_data *vc, unsigned char value, char up_flag) return; } - if (!vc_kbd_led(kbd, VC_NUMLOCK)) + if (!vc_kbd_led(kbd, VC_NUMLOCK)) { + switch (value) { - case KVAL(K_PCOMMA): - case KVAL(K_PDOT): - k_fn(vc, KVAL(K_REMOVE), 0); - return; - case KVAL(K_P0): - k_fn(vc, KVAL(K_INSERT), 0); - return; - case KVAL(K_P1): - k_fn(vc, KVAL(K_SELECT), 0); - return; - case KVAL(K_P2): - k_cur(vc, KVAL(K_DOWN), 0); - return; - case KVAL(K_P3): - k_fn(vc, KVAL(K_PGDN), 0); - return; - case KVAL(K_P4): - k_cur(vc, KVAL(K_LEFT), 0); - return; - case KVAL(K_P6): - k_cur(vc, KVAL(K_RIGHT), 0); - return; - case KVAL(K_P7): - k_fn(vc, KVAL(K_FIND), 0); - return; - case KVAL(K_P8): - k_cur(vc, KVAL(K_UP), 0); - return; - case KVAL(K_P9): - k_fn(vc, KVAL(K_PGUP), 0); - return; - case KVAL(K_P5): - applkey(vc, 'G', vc_kbd_mode(kbd, VC_APPLIC)); - return; + case KVAL(K_PCOMMA): + case KVAL(K_PDOT): + k_fn(vc, KVAL(K_REMOVE), 0); + return; + case KVAL(K_P0): + k_fn(vc, KVAL(K_INSERT), 0); + return; + case KVAL(K_P1): + k_fn(vc, KVAL(K_SELECT), 0); + return; + case KVAL(K_P2): + k_cur(vc, KVAL(K_DOWN), 0); + return; + case KVAL(K_P3): + k_fn(vc, KVAL(K_PGDN), 0); + return; + case KVAL(K_P4): + k_cur(vc, KVAL(K_LEFT), 0); + return; + case KVAL(K_P6): + k_cur(vc, KVAL(K_RIGHT), 0); + return; + case KVAL(K_P7): + k_fn(vc, KVAL(K_FIND), 0); + return; + case KVAL(K_P8): + k_cur(vc, KVAL(K_UP), 0); + return; + case KVAL(K_P9): + k_fn(vc, KVAL(K_PGUP), 0); + return; + case KVAL(K_P5): + applkey(vc, 'G', vc_kbd_mode(kbd, VC_APPLIC)); + return; } + } put_queue(vc, pad_chars[value]); if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF)) @@ -880,6 +871,7 @@ static void k_lock(struct vc_data *vc, unsigned char value, char up_flag) { if (up_flag || rep) return; + chg_vc_kbd_lock(kbd, value); } @@ -888,6 +880,7 @@ static void k_slock(struct vc_data *vc, unsigned char value, char up_flag) k_shift(vc, value, up_flag); if (up_flag || rep) return; + chg_vc_kbd_slock(kbd, value); /* try to make Alt, oops, AltGr and such work */ if (!key_maps[kbd->lockstate ^ kbd->slockstate]) { @@ -925,12 +918,12 @@ static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag) static void k_brl(struct vc_data *vc, unsigned char value, char up_flag) { - static unsigned pressed,committing; + static unsigned pressed, committing; static unsigned long releasestart; if (kbd->kbdmode != VC_UNICODE) { if (!up_flag) - printk("keyboard mode must be unicode for braille patterns\n"); + pr_warning("keyboard mode must be unicode for braille patterns\n"); return; } @@ -942,32 +935,28 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag) if (value > 8) return; - if (up_flag) { - if (brl_timeout) { - if (!committing || - time_after(jiffies, - releasestart + msecs_to_jiffies(brl_timeout))) { - committing = pressed; - releasestart = jiffies; - } - pressed &= ~(1 << (value - 1)); - if (!pressed) { - if (committing) { - k_brlcommit(vc, committing, 0); - committing = 0; - } - } - } else { - if (committing) { - k_brlcommit(vc, committing, 0); - committing = 0; - } - pressed &= ~(1 << (value - 1)); - } - } else { + if (!up_flag) { pressed |= 1 << (value - 1); if (!brl_timeout) committing = pressed; + } else if (brl_timeout) { + if (!committing || + time_after(jiffies, + releasestart + msecs_to_jiffies(brl_timeout))) { + committing = pressed; + releasestart = jiffies; + } + pressed &= ~(1 << (value - 1)); + if (!pressed && committing) { + k_brlcommit(vc, committing, 0); + committing = 0; + } + } else { + if (committing) { + k_brlcommit(vc, committing, 0); + committing = 0; + } + pressed &= ~(1 << (value - 1)); } } @@ -988,6 +977,7 @@ void setledstate(struct kbd_struct *kbd, unsigned int led) kbd->ledmode = LED_SHOW_IOCTL; } else kbd->ledmode = LED_SHOW_FLAGS; + set_leds(); } @@ -1075,7 +1065,7 @@ static const unsigned short x86_keycodes[256] = 332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 }; #ifdef CONFIG_SPARC -static int sparc_l1_a_state = 0; +static int sparc_l1_a_state; extern void sun_do_break(void); #endif @@ -1085,52 +1075,54 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, int code; switch (keycode) { - case KEY_PAUSE: - put_queue(vc, 0xe1); - put_queue(vc, 0x1d | up_flag); - put_queue(vc, 0x45 | up_flag); - break; - case KEY_HANGEUL: - if (!up_flag) - put_queue(vc, 0xf2); - break; + case KEY_PAUSE: + put_queue(vc, 0xe1); + put_queue(vc, 0x1d | up_flag); + put_queue(vc, 0x45 | up_flag); + break; - case KEY_HANJA: - if (!up_flag) - put_queue(vc, 0xf1); - break; + case KEY_HANGEUL: + if (!up_flag) + put_queue(vc, 0xf2); + break; - case KEY_SYSRQ: - /* - * Real AT keyboards (that's what we're trying - * to emulate here emit 0xe0 0x2a 0xe0 0x37 when - * pressing PrtSc/SysRq alone, but simply 0x54 - * when pressing Alt+PrtSc/SysRq. - */ - if (sysrq_alt) { - put_queue(vc, 0x54 | up_flag); - } else { - put_queue(vc, 0xe0); - put_queue(vc, 0x2a | up_flag); - put_queue(vc, 0xe0); - put_queue(vc, 0x37 | up_flag); - } - break; + case KEY_HANJA: + if (!up_flag) + put_queue(vc, 0xf1); + break; - default: - if (keycode > 255) - return -1; + case KEY_SYSRQ: + /* + * Real AT keyboards (that's what we're trying + * to emulate here emit 0xe0 0x2a 0xe0 0x37 when + * pressing PrtSc/SysRq alone, but simply 0x54 + * when pressing Alt+PrtSc/SysRq. + */ + if (test_bit(KEY_LEFTALT, key_down) || + test_bit(KEY_RIGHTALT, key_down)) { + put_queue(vc, 0x54 | up_flag); + } else { + put_queue(vc, 0xe0); + put_queue(vc, 0x2a | up_flag); + put_queue(vc, 0xe0); + put_queue(vc, 0x37 | up_flag); + } + break; - code = x86_keycodes[keycode]; - if (!code) - return -1; + default: + if (keycode > 255) + return -1; - if (code & 0x100) - put_queue(vc, 0xe0); - put_queue(vc, (code & 0x7f) | up_flag); + code = x86_keycodes[keycode]; + if (!code) + return -1; - break; + if (code & 0x100) + put_queue(vc, 0xe0); + put_queue(vc, (code & 0x7f) | up_flag); + + break; } return 0; @@ -1153,6 +1145,7 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char u static void kbd_rawcode(unsigned char data) { struct vc_data *vc = vc_cons[fg_console].d; + kbd = kbd_table + vc->vc_num; if (kbd->kbdmode == VC_RAW) put_queue(vc, data); @@ -1162,10 +1155,12 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) { struct vc_data *vc = vc_cons[fg_console].d; unsigned short keysym, *key_map; - unsigned char type, raw_mode; + unsigned char type; + bool raw_mode; struct tty_struct *tty; int shift_final; struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down }; + int rc; tty = vc->vc_tty; @@ -1176,8 +1171,6 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) kbd = kbd_table + vc->vc_num; - if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT) - sysrq_alt = down ? keycode : 0; #ifdef CONFIG_SPARC if (keycode == KEY_STOP) sparc_l1_a_state = down; @@ -1185,29 +1178,16 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) rep = (down == 2); - if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw) + raw_mode = (kbd->kbdmode == VC_RAW); + if (raw_mode && !hw_raw) if (emulate_raw(vc, keycode, !down << 7)) if (keycode < BTN_MISC && printk_ratelimit()) - printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode); + pr_warning("can't emulate rawmode for keycode %d\n", + keycode); -#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ - if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) { - if (!sysrq_down) { - sysrq_down = down; - sysrq_alt_use = sysrq_alt; - } - return; - } - if (sysrq_down && !down && keycode == sysrq_alt_use) - sysrq_down = 0; - if (sysrq_down && down && !rep) { - handle_sysrq(kbd_sysrq_xlate[keycode], tty); - return; - } -#endif #ifdef CONFIG_SPARC if (keycode == KEY_A && sparc_l1_a_state) { - sparc_l1_a_state = 0; + sparc_l1_a_state = false; sun_do_break(); } #endif @@ -1229,7 +1209,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) put_queue(vc, (keycode >> 7) | 0x80); put_queue(vc, keycode | 0x80); } - raw_mode = 1; + raw_mode = true; } if (down) @@ -1252,29 +1232,32 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) param.ledstate = kbd->ledflagstate; key_map = key_maps[shift_final]; - if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYCODE, ¶m) == NOTIFY_STOP || !key_map) { - atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNBOUND_KEYCODE, ¶m); + rc = atomic_notifier_call_chain(&keyboard_notifier_list, + KBD_KEYCODE, ¶m); + if (rc == NOTIFY_STOP || !key_map) { + atomic_notifier_call_chain(&keyboard_notifier_list, + KBD_UNBOUND_KEYCODE, ¶m); compute_shiftstate(); kbd->slockstate = 0; return; } - if (keycode >= NR_KEYS) - if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8) - keysym = U(K(KT_BRL, keycode - KEY_BRL_DOT1 + 1)); - else - return; - else + if (keycode < NR_KEYS) keysym = key_map[keycode]; + else if (keycode >= KEY_BRL_DOT1 && keycode <= KEY_BRL_DOT8) + keysym = U(K(KT_BRL, keycode - KEY_BRL_DOT1 + 1)); + else + return; type = KTYP(keysym); if (type < 0xf0) { param.value = keysym; - if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_UNICODE, ¶m) == NOTIFY_STOP) - return; - if (down && !raw_mode) - to_utf8(vc, keysym); + rc = atomic_notifier_call_chain(&keyboard_notifier_list, + KBD_UNICODE, ¶m); + if (rc != NOTIFY_STOP) + if (down && !raw_mode) + to_utf8(vc, keysym); return; } @@ -1288,9 +1271,11 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) keysym = key_map[keycode]; } } - param.value = keysym; - if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYSYM, ¶m) == NOTIFY_STOP) + param.value = keysym; + rc = atomic_notifier_call_chain(&keyboard_notifier_list, + KBD_KEYSYM, ¶m); + if (rc == NOTIFY_STOP) return; if (raw_mode && type != KT_SPEC && type != KT_SHIFT) diff --git a/drivers/char/n_gsm.c b/drivers/char/n_gsm.c new file mode 100644 index 00000000000..c4161d5e053 --- /dev/null +++ b/drivers/char/n_gsm.c @@ -0,0 +1,2763 @@ +/* + * n_gsm.c GSM 0710 tty multiplexor + * Copyright (c) 2009/10 Intel Corporation + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * * THIS IS A DEVELOPMENT SNAPSHOT IT IS NOT A FINAL RELEASE * + * + * TO DO: + * Mostly done: ioctls for setting modes/timing + * Partly done: hooks so you can pull off frames to non tty devs + * Restart DLCI 0 when it closes ? + * Test basic encoding + * Improve the tx engine + * Resolve tx side locking by adding a queue_head and routing + * all control traffic via it + * General tidy/document + * Review the locking/move to refcounts more (mux now moved to an + * alloc/free model ready) + * Use newest tty open/close port helpers and install hooks + * What to do about power functions ? + * Termios setting and negotiation + * Do we need a 'which mux are you' ioctl to correlate mux and tty sets + * + */ + +#include <linux/types.h> +#include <linux/major.h> +#include <linux/errno.h> +#include <linux/signal.h> +#include <linux/fcntl.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/tty.h> +#include <linux/timer.h> +#include <linux/ctype.h> +#include <linux/mm.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/poll.h> +#include <linux/bitops.h> +#include <linux/file.h> +#include <linux/uaccess.h> +#include <linux/module.h> +#include <linux/timer.h> +#include <linux/tty_flip.h> +#include <linux/tty_driver.h> +#include <linux/serial.h> +#include <linux/kfifo.h> +#include <linux/skbuff.h> +#include <linux/gsmmux.h> + +static int debug; +module_param(debug, int, 0600); + +#define T1 (HZ/10) +#define T2 (HZ/3) +#define N2 3 + +/* Use long timers for testing at low speed with debug on */ +#ifdef DEBUG_TIMING +#define T1 HZ +#define T2 (2 * HZ) +#endif + +/* Semi-arbitary buffer size limits. 0710 is normally run with 32-64 byte + limits so this is plenty */ +#define MAX_MRU 512 +#define MAX_MTU 512 + +/* + * Each block of data we have queued to go out is in the form of + * a gsm_msg which holds everything we need in a link layer independant + * format + */ + +struct gsm_msg { + struct gsm_msg *next; + u8 addr; /* DLCI address + flags */ + u8 ctrl; /* Control byte + flags */ + unsigned int len; /* Length of data block (can be zero) */ + unsigned char *data; /* Points into buffer but not at the start */ + unsigned char buffer[0]; +}; + +/* + * Each active data link has a gsm_dlci structure associated which ties + * the link layer to an optional tty (if the tty side is open). To avoid + * complexity right now these are only ever freed up when the mux is + * shut down. + * + * At the moment we don't free DLCI objects until the mux is torn down + * this avoid object life time issues but might be worth review later. + */ + +struct gsm_dlci { + struct gsm_mux *gsm; + int addr; + int state; +#define DLCI_CLOSED 0 +#define DLCI_OPENING 1 /* Sending SABM not seen UA */ +#define DLCI_OPEN 2 /* SABM/UA complete */ +#define DLCI_CLOSING 3 /* Sending DISC not seen UA/DM */ + + /* Link layer */ + spinlock_t lock; /* Protects the internal state */ + struct timer_list t1; /* Retransmit timer for SABM and UA */ + int retries; + /* Uplink tty if active */ + struct tty_port port; /* The tty bound to this DLCI if there is one */ + struct kfifo *fifo; /* Queue fifo for the DLCI */ + struct kfifo _fifo; /* For new fifo API porting only */ + int adaption; /* Adaption layer in use */ + u32 modem_rx; /* Our incoming virtual modem lines */ + u32 modem_tx; /* Our outgoing modem lines */ + int dead; /* Refuse re-open */ + /* Flow control */ + int throttled; /* Private copy of throttle state */ + int constipated; /* Throttle status for outgoing */ + /* Packetised I/O */ + struct sk_buff *skb; /* Frame being sent */ + struct sk_buff_head skb_list; /* Queued frames */ + /* Data handling callback */ + void (*data)(struct gsm_dlci *dlci, u8 *data, int len); +}; + +/* DLCI 0, 62/63 are special or reseved see gsmtty_open */ + +#define NUM_DLCI 64 + +/* + * DLCI 0 is used to pass control blocks out of band of the data + * flow (and with a higher link priority). One command can be outstanding + * at a time and we use this structure to manage them. They are created + * and destroyed by the user context, and updated by the receive paths + * and timers + */ + +struct gsm_control { + u8 cmd; /* Command we are issuing */ + u8 *data; /* Data for the command in case we retransmit */ + int len; /* Length of block for retransmission */ + int done; /* Done flag */ + int error; /* Error if any */ +}; + +/* + * Each GSM mux we have is represented by this structure. If we are + * operating as an ldisc then we use this structure as our ldisc + * state. We need to sort out lifetimes and locking with respect + * to the gsm mux array. For now we don't free DLCI objects that + * have been instantiated until the mux itself is terminated. + * + * To consider further: tty open versus mux shutdown. + */ + +struct gsm_mux { + struct tty_struct *tty; /* The tty our ldisc is bound to */ + spinlock_t lock; + + /* Events on the GSM channel */ + wait_queue_head_t event; +< |