Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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.