-
Notifications
You must be signed in to change notification settings - Fork 1
/
lunix-ldisc.c
143 lines (121 loc) · 3.29 KB
/
lunix-ldisc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
* lunix-ldisc.c
*
* TTY line discipline for Lunix:TNG
*
* Vangelis Koukis <[email protected]>
*
*/
#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/atomic.h>
#include <asm/uaccess.h>
#include "lunix.h"
#include "lunix-ldisc.h"
#include "lunix-protocol.h"
/*
* This line discipline can only be associated
* with a single TTY at any time.
*/
static atomic_t lunix_disc_available;
/*
* This function runs when the userspace helper
* sets the Lunix:TNG line discipline on a TTY.
*/
static int lunix_ldisc_open(struct tty_struct *tty)
{
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
/* Can only be associated with a single TTY */
if ( !atomic_add_unless(&lunix_disc_available, -1, 0))
return -EBUSY;
tty->receive_room = 65536; /* No flow control, FIXME */
debug("lunix ldisc associated with TTY %s\n", tty->name);
return 0;
}
/*
* Called called whenever the discipline
* is unregistered from a port.
*/
static void lunix_ldisc_close(struct tty_struct *tty)
{
atomic_inc(&lunix_disc_available);
/* FIXME */
/* Shouldn't we wake up all sleepers in all sensors here? */
debug("lunix ldisc being closed\n");
}
/*
* lunix_ldisc_receive() is called by the TTY layer when data have been
* received by the low level TTY driver and are ready for us. This function
* will not be re-entered while running.
*/
static void lunix_ldisc_receive(struct tty_struct *tty,
const unsigned char *cp, char *fp, int count)
{
#if 1
#if LUNIX_DEBUG
int i;
debug("called, %d characters have been received. Data at *cp: { ", count);
for (i = 0; i < count; i++)
printk("0x%02x%s", cp[i], (i == count - 1) ? "" : ", ");
printk(" }\n");
#endif
printk(KERN_INFO "lunix_ldisc_receive called\n");
#endif
/*
* Pass incoming characters to protocol processing code,
* which handle any necessary sensor updates.
*/
lunix_protocol_received_buf(&lunix_protocol_state, cp, count);
//debug("passed incoming bytes to state machine, leaving\n");
}
/*
* Userspace can no longer access a TTY using read()
* or write() calls after this discipline has been set to it.
*/
static ssize_t lunix_ldisc_read(struct tty_struct * tty, struct file * file,
unsigned char __user * buf, size_t cnt)
{
debug("called, returning -EIO\n");
return -EIO;
}
static ssize_t lunix_ldisc_write(struct tty_struct * tty, struct file * file,
const unsigned char __user * buf, size_t cnt)
{
debug("called, returning -EIO\n");
return -EIO;
}
/*
* The line discipline structure.
* Initialization and release functions.
*/
static struct tty_ldisc_ops lunix_ldisc_ops = {
.owner = THIS_MODULE,
.name = "lunix",
.open = lunix_ldisc_open,
.close = lunix_ldisc_close,
.read = lunix_ldisc_read,
.write = lunix_ldisc_write,
.receive_buf = lunix_ldisc_receive
};
int lunix_ldisc_init(void)
{
int ret;
debug("initializing lunix ldisc\n");
atomic_set(&lunix_disc_available, 1);
ret = tty_register_ldisc(N_LUNIX_LDISC, &lunix_ldisc_ops);
if (ret)
printk(KERN_ERR "%s: Error registering line discipline, ret = %d.\n", __FILE__, ret);
debug("leaving with ret = %d\n", ret);
return ret;
}
void lunix_ldisc_destroy(void)
{
debug("unregistering lunix ldisc\n");
tty_unregister_ldisc(N_LUNIX_LDISC);
debug("lunix ldisc unregistered\n");
}