1 /*
2 * Tiny Serial driver
3 *
4 * Copyright (C) 2002-2004 Greg Kroah-Hartman (greg@kroah.com)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, version 2 of the License.
9 *
10 * This driver shows how to create a minimal serial driver. It does not rely on
11 * any backing hardware, but creates a timer that emulates data being received
12 * from some kind of hardware.
13 */
14
15 #include <linux/kernel.h>
16 #include <linux/errno.h>
17 #include <linux/init.h>
18 #include <linux/slab.h>
19 #include <linux/tty.h>
20 #include <linux/tty_flip.h>
21 #include <linux/serial.h>
22 #include <linux/serial_core.h>
23 #include <linux/module.h>
24
25
26 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
27 #define DRIVER_DESC "Tiny serial driver"
28
29 /* Module information */
30 MODULE_AUTHOR( DRIVER_AUTHOR );
31 MODULE_DESCRIPTION( DRIVER_DESC );
32 MODULE_LICENSE("GPL");
33
34 #define DELAY_TIME HZ * 2 /* 2 seconds per character */
35 #define TINY_DATA_CHARACTER 't'
36
37 #define TINY_SERIAL_MAJOR 240 /* experimental range */
38 #define TINY_SERIAL_MINORS 1 /* only have one minor */
39 #define UART_NR 1 /* only use one port */
40
41 #define TINY_SERIAL_NAME "ttytiny"
42
43 #define MY_NAME TINY_SERIAL_NAME
44
45 static struct timer_list *timer;
46
47 static void tiny_stop_tx(struct uart_port *port, unsigned int tty_stop)
48 {
49 }
50
51 static void tiny_stop_rx(struct uart_port *port)
52 {
53 }
54
55 static void tiny_enable_ms(struct uart_port *port)
56 {
57 }
58
59 static void tiny_tx_chars(struct uart_port *port)
60 {
61 struct circ_buf *xmit = &port->info->xmit;
62 int count;
63
64 if (port->x_char) {
65 pr_debug("wrote %2x", port->x_char);
66 port->icount.tx++;
67 port->x_char = 0;
68 return;
69 }
70 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
71 tiny_stop_tx(port, 0);
72 return;
73 }
74
75 count = port->fifosize >> 1;
76 do {
77 pr_debug("wrote %2x", xmit->buf[xmit->tail]);
78 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
79 port->icount.tx++;
80 if (uart_circ_empty(xmit))
81 break;
82 } while (--count > 0);
83
84 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
85 uart_write_wakeup(port);
86
87 if (uart_circ_empty(xmit))
88 tiny_stop_tx(port, 0);
89 }
90
91 static void tiny_start_tx(struct uart_port *port, unsigned int tty_start)
92 {
93 }
94
95 static void tiny_timer(unsigned long data)
96 {
97 struct uart_port *port;
98 struct tty_struct *tty;
99
100
101 port = (struct uart_port *)data;
102 if (!port)
103 return;
104 if (!port->info)
105 return;
106 tty = port->info->tty;
107 if (!tty)
108 return;
109
110 /* add one character to the tty port */
111 /* this doesn't actually push the data through unless tty->low_latency is set */
112 tty_insert_flip_char(tty, TINY_DATA_CHARACTER, 0);
113
114 tty_flip_buffer_push(tty);
115
116 /* resubmit the timer again */
117 timer->expires = jiffies + DELAY_TIME;
118 add_timer(timer);
119
120 /* see if we have any data to transmit */
121 tiny_tx_chars(port);
122 }
123
124 static unsigned int tiny_tx_empty(struct uart_port *port)
125 {
126 return 0;
127 }
128
129 static unsigned int tiny_get_mctrl(struct uart_port *port)
130 {
131 return 0;
132 }
133
134 static void tiny_set_mctrl(struct uart_port *port, unsigned int mctrl)
135 {
136 }
137
138 static void tiny_break_ctl(struct uart_port *port, int break_state)
139 {
140 }
141
142 static void tiny_set_termios(struct uart_port *port,
143 struct termios *new, struct termios *old)
144 {
145 int baud, quot, cflag = new->c_cflag;
146 /* get the byte size */
147 switch (cflag & CSIZE) {
148 case CS5:
149 printk(KERN_DEBUG " - data bits = 5\n");
150 break;
151 case CS6:
152 printk(KERN_DEBUG " - data bits = 6\n");
153 break;
154 case CS7:
155 printk(KERN_DEBUG " - data bits = 7\n");
156 break;
157 default: // CS8
158 printk(KERN_DEBUG " - data bits = 8\n");
159 break;
160 }
161
162 /* determine the parity */
163 if (cflag & PARENB)
164 if (cflag & PARODD)
165 pr_debug(" - parity = odd\n");
166 else
167 pr_debug(" - parity = even\n");
168 else
169 pr_debug(" - parity = none\n");
170
171 /* figure out the stop bits requested */
172 if (cflag & CSTOPB)
173 pr_debug(" - stop bits = 2\n");
174 else
175 pr_debug(" - stop bits = 1\n");
176
177 /* figure out the flow control settings */
178 if (cflag & CRTSCTS)
179 pr_debug(" - RTS/CTS is enabled\n");
180 else
181 pr_debug(" - RTS/CTS is disabled\n");
182
183 /* Set baud rate */
184 baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);
185 quot = uart_get_divisor(port, baud);
186
187 //UART_PUT_DIV_LO(port, (quot & 0xff));
188 //UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
189 }
190
191 static int tiny_startup(struct uart_port *port)
192 {
193 /* this is the first time this port is opened */
194 /* do any hardware initialization needed here */
195
196 /* create our timer and submit it */
197 if (!timer) {
198 timer = kmalloc(sizeof(*timer), GFP_KERNEL);
199 if (!timer)
200 return -ENOMEM;
201 }
202 timer->data = (unsigned long)port;
203 timer->expires = jiffies + DELAY_TIME;
204 timer->function = tiny_timer;
205 add_timer(timer);
206 return 0;
207 }
208
209 static void tiny_shutdown(struct uart_port *port)
210 {
211 /* The port is being closed by the last user. */
212 /* Do any hardware specific stuff here */
213
214 /* shut down our timer */
215 del_timer(timer);
216 }
217
218 static const char *tiny_type(struct uart_port *port)
219 {
220 return "tinytty";
221 }
222
223 static void tiny_release_port(struct uart_port *port)
224 {
225
226 }
227
228 static int tiny_request_port(struct uart_port *port)
229 {
230 return 0;
231 }
232
233 static void tiny_config_port(struct uart_port *port, int flags)
234 {
235 }
236
237 static int tiny_verify_port(struct uart_port *port, struct serial_struct *ser)
238 {
239 return 0;
240 }
241
242 static struct uart_ops tiny_ops = {
243 .tx_empty = tiny_tx_empty,
244 .set_mctrl = tiny_set_mctrl,
245 .get_mctrl = tiny_get_mctrl,
246 .stop_tx = tiny_stop_tx,
247 .start_tx = tiny_start_tx,
248 .stop_rx = tiny_stop_rx,
249 .enable_ms = tiny_enable_ms,
250 .break_ctl = tiny_break_ctl,
251 .startup = tiny_startup,
252 .shutdown = tiny_shutdown,
253 .set_termios = tiny_set_termios,
254 .type = tiny_type,
255 .release_port = tiny_release_port,
256 .request_port = tiny_request_port,
257 .config_port = tiny_config_port,
258 .verify_port = tiny_verify_port,
259 };
260
261 static struct uart_port tiny_port = {
262 .ops = &tiny_ops,
263 };
264
265 static struct uart_driver tiny_reg = {
266 .owner = THIS_MODULE,
267 .driver_name = TINY_SERIAL_NAME,
268 .dev_name = TINY_SERIAL_NAME,
269 .major = TINY_SERIAL_MAJOR,
270 .minor = TINY_SERIAL_MINORS,
271 .nr = UART_NR,
272 };
273
274 static int __init tiny_init(void)
275 {
276 int result;
277
278 printk(KERN_INFO "Tiny serial driver loaded\n");
279
280 result = uart_register_driver(&tiny_reg);
281 if (result)
282 return result;
283
284 result = uart_add_one_port(&tiny_reg, &tiny_port);
285 if (result)
286 uart_unregister_driver(&tiny_reg);
287
288 return result;
289 }
290
291 module_init(tiny_init);
292
|
This page was automatically generated by the
LXR engine.
|