Linux-2.6.12-rc2
[cascardo/linux.git] / arch / um / drivers / fd.c
1 /* 
2  * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
3  * Licensed under the GPL
4  */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <termios.h>
10 #include <errno.h>
11 #include "user.h"
12 #include "user_util.h"
13 #include "chan_user.h"
14
15 struct fd_chan {
16         int fd;
17         int raw;
18         struct termios tt;
19         char str[sizeof("1234567890\0")];
20 };
21
22 static void *fd_init(char *str, int device, struct chan_opts *opts)
23 {
24         struct fd_chan *data;
25         char *end;
26         int n;
27
28         if(*str != ':'){
29                 printk("fd_init : channel type 'fd' must specify a file "
30                        "descriptor\n");
31                 return(NULL);
32         }
33         str++;
34         n = strtoul(str, &end, 0);
35         if((*end != '\0') || (end == str)){
36                 printk("fd_init : couldn't parse file descriptor '%s'\n", str);
37                 return(NULL);
38         }
39         data = um_kmalloc(sizeof(*data));
40         if(data == NULL) return(NULL);
41         *data = ((struct fd_chan) { .fd         = n,
42                                     .raw        = opts->raw });
43         return(data);
44 }
45
46 static int fd_open(int input, int output, int primary, void *d, char **dev_out)
47 {
48         struct fd_chan *data = d;
49         int err;
50
51         if(data->raw && isatty(data->fd)){
52                 CATCH_EINTR(err = tcgetattr(data->fd, &data->tt));
53                 if(err)
54                         return(err);
55
56                 err = raw(data->fd);
57                 if(err)
58                         return(err);
59         }
60         sprintf(data->str, "%d", data->fd);
61         *dev_out = data->str;
62         return(data->fd);
63 }
64
65 static void fd_close(int fd, void *d)
66 {
67         struct fd_chan *data = d;
68         int err;
69
70         if(data->raw && isatty(fd)){
71                 CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt));
72                 if(err)
73                         printk("Failed to restore terminal state - "
74                                "errno = %d\n", -err);
75                 data->raw = 0;
76         }
77 }
78
79 static int fd_console_write(int fd, const char *buf, int n, void *d)
80 {
81         struct fd_chan *data = d;
82
83         return(generic_console_write(fd, buf, n, &data->tt));
84 }
85
86 struct chan_ops fd_ops = {
87         .type           = "fd",
88         .init           = fd_init,
89         .open           = fd_open,
90         .close          = fd_close,
91         .read           = generic_read,
92         .write          = generic_write,
93         .console_write  = fd_console_write,
94         .window_size    = generic_window_size,
95         .free           = generic_free,
96         .winch          = 1,
97 };
98
99 /*
100  * Overrides for Emacs so that we follow Linus's tabbing style.
101  * Emacs will notice this stuff at the end of the file and automatically
102  * adjust the settings for this buffer only.  This must remain at the end
103  * of the file.
104  * ---------------------------------------------------------------------------
105  * Local variables:
106  * c-file-style: "linux"
107  * End:
108  */