^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Input device TTY line discipline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 1999-2002 Vojtech Pavlik
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This is a module that converts a tty line into a much simpler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * 'serial io port' abstraction that the input device drivers use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/serio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) MODULE_DESCRIPTION("Input device TTY line discipline");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) MODULE_ALIAS_LDISC(N_MOUSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define SERPORT_BUSY 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define SERPORT_ACTIVE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define SERPORT_DEAD 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct serport {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct tty_struct *tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) wait_queue_head_t wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct serio *serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct serio_device_id id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * Callback functions from the serio code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static int serport_serio_write(struct serio *serio, unsigned char data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct serport *serport = serio->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return -(serport->tty->ops->write(serport->tty, &data, 1) != 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static int serport_serio_open(struct serio *serio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct serport *serport = serio->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) spin_lock_irqsave(&serport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) set_bit(SERPORT_ACTIVE, &serport->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) spin_unlock_irqrestore(&serport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static void serport_serio_close(struct serio *serio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct serport *serport = serio->port_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) spin_lock_irqsave(&serport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) clear_bit(SERPORT_ACTIVE, &serport->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) spin_unlock_irqrestore(&serport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * serport_ldisc_open() is the routine that is called upon setting our line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * discipline on a tty. It prepares the serio struct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static int serport_ldisc_open(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct serport *serport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) serport = kzalloc(sizeof(struct serport), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (!serport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) serport->tty = tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) spin_lock_init(&serport->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) init_waitqueue_head(&serport->wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) tty->disc_data = serport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) tty->receive_room = 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * serport_ldisc_close() is the opposite of serport_ldisc_open()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static void serport_ldisc_close(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct serport *serport = (struct serport *) tty->disc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) kfree(serport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * serport_ldisc_receive() is called by the low level tty driver when characters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * are ready for us. We forward the characters and flags, one by one to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * 'interrupt' routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct serport *serport = (struct serport*) tty->disc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) unsigned int ch_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) spin_lock_irqsave(&serport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (!test_bit(SERPORT_ACTIVE, &serport->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (fp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) switch (fp[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) case TTY_FRAME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) ch_flags = SERIO_FRAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) case TTY_PARITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ch_flags = SERIO_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) ch_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) serio_interrupt(serport->serio, cp[i], ch_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) spin_unlock_irqrestore(&serport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * serport_ldisc_read() just waits indefinitely if everything goes well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * However, when the serio driver closes the serio port, it finishes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * returning 0 characters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) unsigned char *kbuf, size_t nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) void **cookie, unsigned long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct serport *serport = (struct serport*) tty->disc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct serio *serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (test_and_set_bit(SERPORT_BUSY, &serport->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) serport->serio = serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (!serio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) strlcpy(serio->name, "Serial port", sizeof(serio->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) serio->id = serport->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) serio->id.type = SERIO_RS232;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) serio->write = serport_serio_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) serio->open = serport_serio_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) serio->close = serport_serio_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) serio->port_data = serport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) serio->dev.parent = tty->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) serio_register_port(serport->serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) wait_event_interruptible(serport->wait, test_bit(SERPORT_DEAD, &serport->flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) serio_unregister_port(serport->serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) serport->serio = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) clear_bit(SERPORT_DEAD, &serport->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) clear_bit(SERPORT_BUSY, &serport->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static void serport_set_type(struct tty_struct *tty, unsigned long type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct serport *serport = tty->disc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) serport->id.proto = type & 0x000000ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) serport->id.id = (type & 0x0000ff00) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) serport->id.extra = (type & 0x00ff0000) >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * serport_ldisc_ioctl() allows to set the port protocol, and device ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static int serport_ldisc_ioctl(struct tty_struct *tty, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (cmd == SPIOCSTYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) unsigned long type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (get_user(type, (unsigned long __user *) arg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) serport_set_type(tty, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) #define COMPAT_SPIOCSTYPE _IOW('q', 0x01, compat_ulong_t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static int serport_ldisc_compat_ioctl(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (cmd == COMPAT_SPIOCSTYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) void __user *uarg = compat_ptr(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) compat_ulong_t compat_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (get_user(compat_type, (compat_ulong_t __user *)uarg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) serport_set_type(tty, compat_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static int serport_ldisc_hangup(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct serport *serport = (struct serport *) tty->disc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) spin_lock_irqsave(&serport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) set_bit(SERPORT_DEAD, &serport->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) spin_unlock_irqrestore(&serport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) wake_up_interruptible(&serport->wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static void serport_ldisc_write_wakeup(struct tty_struct * tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct serport *serport = (struct serport *) tty->disc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) spin_lock_irqsave(&serport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (test_bit(SERPORT_ACTIVE, &serport->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) serio_drv_write_wakeup(serport->serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) spin_unlock_irqrestore(&serport->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * The line discipline structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static struct tty_ldisc_ops serport_ldisc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) .name = "input",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) .open = serport_ldisc_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) .close = serport_ldisc_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) .read = serport_ldisc_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .ioctl = serport_ldisc_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) .compat_ioctl = serport_ldisc_compat_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) .receive_buf = serport_ldisc_receive,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) .hangup = serport_ldisc_hangup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) .write_wakeup = serport_ldisc_write_wakeup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * The functions for insering/removing us as a module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static int __init serport_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) retval = tty_register_ldisc(N_MOUSE, &serport_ldisc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) printk(KERN_ERR "serport.c: Error registering line discipline.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) static void __exit serport_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) tty_unregister_ldisc(N_MOUSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) module_init(serport_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) module_exit(serport_exit);