Create platform_device.h to contain all the platform device details.
[deliverable/linux.git] / arch / um / drivers / pty.c
1 /*
2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6 #include <stdio.h>
7 #include <unistd.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <termios.h>
11 #include "chan_user.h"
12 #include "user.h"
13 #include "user_util.h"
14 #include "kern_util.h"
15 #include "os.h"
16
17 struct pty_chan {
18 void (*announce)(char *dev_name, int dev);
19 int dev;
20 int raw;
21 struct termios tt;
22 char dev_name[sizeof("/dev/pts/0123456\0")];
23 };
24
25 static void *pty_chan_init(char *str, int device, struct chan_opts *opts)
26 {
27 struct pty_chan *data;
28
29 data = um_kmalloc(sizeof(*data));
30 if(data == NULL) return(NULL);
31 *data = ((struct pty_chan) { .announce = opts->announce,
32 .dev = device,
33 .raw = opts->raw });
34 return(data);
35 }
36
37 static int pts_open(int input, int output, int primary, void *d,
38 char **dev_out)
39 {
40 struct pty_chan *data = d;
41 char *dev;
42 int fd, err;
43
44 fd = get_pty();
45 if(fd < 0){
46 err = -errno;
47 printk("open_pts : Failed to open pts\n");
48 return err;
49 }
50 if(data->raw){
51 CATCH_EINTR(err = tcgetattr(fd, &data->tt));
52 if(err)
53 return(err);
54
55 err = raw(fd);
56 if(err)
57 return(err);
58 }
59
60 dev = ptsname(fd);
61 sprintf(data->dev_name, "%s", dev);
62 *dev_out = data->dev_name;
63 if (data->announce)
64 (*data->announce)(dev, data->dev);
65 return(fd);
66 }
67
68 static int getmaster(char *line)
69 {
70 char *pty, *bank, *cp;
71 int master, err;
72
73 pty = &line[strlen("/dev/ptyp")];
74 for (bank = "pqrs"; *bank; bank++) {
75 line[strlen("/dev/pty")] = *bank;
76 *pty = '0';
77 if (os_stat_file(line, NULL) < 0)
78 break;
79 for (cp = "0123456789abcdef"; *cp; cp++) {
80 *pty = *cp;
81 master = os_open_file(line, of_rdwr(OPENFLAGS()), 0);
82 if (master >= 0) {
83 char *tp = &line[strlen("/dev/")];
84
85 /* verify slave side is usable */
86 *tp = 't';
87 err = os_access(line, OS_ACC_RW_OK);
88 *tp = 'p';
89 if(err == 0) return(master);
90 (void) os_close_file(master);
91 }
92 }
93 }
94 return(-1);
95 }
96
97 static int pty_open(int input, int output, int primary, void *d,
98 char **dev_out)
99 {
100 struct pty_chan *data = d;
101 int fd, err;
102 char dev[sizeof("/dev/ptyxx\0")] = "/dev/ptyxx";
103
104 fd = getmaster(dev);
105 if(fd < 0)
106 return(-errno);
107
108 if(data->raw){
109 err = raw(fd);
110 if(err)
111 return(err);
112 }
113
114 if(data->announce) (*data->announce)(dev, data->dev);
115
116 sprintf(data->dev_name, "%s", dev);
117 *dev_out = data->dev_name;
118 return(fd);
119 }
120
121 static int pty_console_write(int fd, const char *buf, int n, void *d)
122 {
123 struct pty_chan *data = d;
124
125 return(generic_console_write(fd, buf, n, &data->tt));
126 }
127
128 struct chan_ops pty_ops = {
129 .type = "pty",
130 .init = pty_chan_init,
131 .open = pty_open,
132 .close = generic_close,
133 .read = generic_read,
134 .write = generic_write,
135 .console_write = pty_console_write,
136 .window_size = generic_window_size,
137 .free = generic_free,
138 .winch = 0,
139 };
140
141 struct chan_ops pts_ops = {
142 .type = "pts",
143 .init = pty_chan_init,
144 .open = pts_open,
145 .close = generic_close,
146 .read = generic_read,
147 .write = generic_write,
148 .console_write = pty_console_write,
149 .window_size = generic_window_size,
150 .free = generic_free,
151 .winch = 0,
152 };
153
154 /*
155 * Overrides for Emacs so that we follow Linus's tabbing style.
156 * Emacs will notice this stuff at the end of the file and automatically
157 * adjust the settings for this buffer only. This must remain at the end
158 * of the file.
159 * ---------------------------------------------------------------------------
160 * Local variables:
161 * c-file-style: "linux"
162 * End:
163 */
This page took 0.03419 seconds and 5 git commands to generate.