]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/hwinfo/src/hd/kbd.c
Kleiner netter neuer Versuch.
[people/pmueller/ipfire-2.x.git] / src / hwinfo / src / hd / kbd.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <errno.h>
7 #include <termios.h>
8 #include <sys/stat.h>
9 #include <sys/types.h>
10 #include <sys/time.h>
11 #include <sys/ioctl.h>
12 #include <linux/serial.h>
13
14 #ifdef __sparc__
15
16 struct serial_struct {
17 int type;
18 int line;
19 unsigned long port;
20 int irq;
21 int flags;
22 int xmit_fifo_size;
23 int custom_divisor;
24 int baud_base;
25 unsigned short close_delay;
26 char io_type;
27 char reserved_char[1];
28 int hub6;
29 unsigned short closing_wait; /* time to wait before closing */
30 unsigned short closing_wait2; /* no longer used... */
31 unsigned char *iomem_base;
32 unsigned short iomem_reg_shift;
33 int reserved[2];
34 };
35
36 #ifdef DIET
37 typedef unsigned int u_int;
38 #endif
39
40 #include <asm/kbio.h>
41 #include <asm/openpromio.h>
42 #endif
43
44 #include "hd.h"
45 #include "hd_int.h"
46 #include "kbd.h"
47
48 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
49 *
50 * Look for keyboards not covered by kernel input device driver, mainly
51 * some sort of serial consoles.
52 *
53 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
54 */
55
56 #ifdef __sparc__
57 static void add_sun_console(hd_data_t *hd_data);
58 #else
59 static void add_serial_console(hd_data_t *hd_data);
60 #endif
61
62
63 void hd_scan_kbd(hd_data_t *hd_data)
64 {
65 hd_t *hd;
66
67 if(!hd_probe_feature(hd_data, pr_kbd)) return;
68
69 hd_data->module = mod_kbd;
70
71 /* some clean-up */
72 remove_hd_entries(hd_data);
73
74 PROGRESS(2, 0, "uml");
75
76 if(hd_is_uml(hd_data)) {
77 hd = add_hd_entry(hd_data, __LINE__, 0);
78 hd->base_class.id = bc_keyboard;
79 hd->sub_class.id = sc_keyboard_kbd;
80 hd->bus.id = bus_none;
81 hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0201);
82 hd->device.id = MAKE_ID(TAG_SPECIAL, 2);
83 }
84
85 PROGRESS(3, 0, "serial console");
86
87 #ifdef __sparc__
88 add_sun_console(hd_data);
89 #else
90 add_serial_console(hd_data);
91 #endif
92 }
93
94
95 #ifndef __sparc__
96
97 void add_serial_console(hd_data_t *hd_data)
98 {
99 hd_t *hd;
100 hd_res_t *res = NULL;
101 int fd, i;
102 str_list_t *cmd, *cmd0, *sl;
103 unsigned u, u1;
104 struct serial_struct ser_info;
105 unsigned tty_major = 0, tty_minor = 0;
106 char c, *dev = NULL, *s;
107
108 /* first, try console= option */
109 cmd = cmd0 = get_cmdline(hd_data, "console");
110
111 /* use last console entry */
112 if(cmd) while(cmd->next) cmd = cmd->next;
113
114 if(
115 cmd &&
116 (
117 /* everything != "ttyN" */
118 strncmp(cmd->str, "tty", 3) ||
119 !(cmd->str[3] == 0 || (cmd->str[3] >= '0' && cmd->str[3] <= '9'))
120 )
121 ) {
122 sl = hd_split(',', cmd->str);
123 s = sl->str;
124 if(!strncmp(s, "/dev/", sizeof "/dev/" - 1)) s += sizeof "/dev/" - 1;
125 dev = new_str(s);
126 if(sl->next && (i = sscanf(sl->next->str, "%u%c%u", &u, &c, &u1)) >= 1) {
127 res = add_res_entry(&res, new_mem(sizeof *res));
128 res->baud.type = res_baud;
129 res->baud.speed = u;
130 if(i >= 2) res->baud.parity = c;
131 if(i >= 3) res->baud.bits = u1;
132 }
133 free_str_list(sl);
134 }
135
136 #ifdef __UCLIBC__
137 if(!dev && (fd = open(DEV_CONSOLE, O_RDWR | O_NONBLOCK | O_NOCTTY)) >= 0) {
138 /*
139 if(ioctl(fd, TIOCGDEV, &u) != -1) {
140 tty_major = (u >> 8) & 0xfff;
141 tty_minor = (u & 0xff) | ((u >> 12) & 0xfff00);
142 ADD2LOG(DEV_CONSOLE ": major %u, minor %u\n", tty_major, tty_minor);
143 }
144 */
145
146 if(tty_major == 229 /* iseries hvc */) {
147 if (tty_minor >= 128) {
148 str_printf(&dev, 0, "hvsi%u", tty_minor-128);
149 } else {
150 str_printf(&dev, 0, "hvc%u", tty_minor);
151 }
152 }
153 else if(!ioctl(fd, TIOCGSERIAL, &ser_info)) {
154 ADD2LOG("serial console at line %d\n", ser_info.line);
155 str_printf(&dev, 0, "ttyS%d", ser_info.line);
156 }
157 close(fd);
158 }
159 #endif
160
161 if(dev) {
162
163 hd = add_hd_entry(hd_data, __LINE__, 0);
164 hd->base_class.id = bc_keyboard;
165 hd->sub_class.id = sc_keyboard_console;
166 hd->bus.id = bus_serial;
167 hd->device.name = new_str("serial console");
168
169 if(*dev) str_printf(&hd->unix_dev_name, 0, "/dev/%s", dev);
170
171 hd->res = res;
172
173 free_mem(dev);
174 }
175
176 free_str_list(cmd0);
177 }
178
179
180 #else /* defined(__sparc__) */
181
182
183 void add_sun_console(hd_data_t *hd_data)
184 {
185 int fd, kid, kid2, klay, ser_cons, i;
186 unsigned u, u1, u2;
187 char c1, c2;
188 struct serial_struct ser_info;
189 unsigned char buf[OPROMMAXPARAM];
190 struct openpromio *opio = (struct openpromio *) buf;
191 hd_t *hd;
192 hd_res_t *res;
193
194 if((fd = open(DEV_CONSOLE, O_RDWR | O_NONBLOCK | O_NOCTTY)) >= 0)
195 {
196 if(ioctl(fd, TIOCGSERIAL, &ser_info))
197 {
198 ser_cons = -1;
199 }
200 else
201 {
202 ser_cons = ser_info.line;
203 ADD2LOG("serial console at line %d\n", ser_cons);
204 }
205 close(fd);
206
207 if(ser_cons >= 0 && (fd = open(DEV_OPENPROM, O_RDWR | O_NONBLOCK)) >= 0)
208 {
209 sprintf(opio->oprom_array, "tty%c-mode", (ser_cons & 1) + 'a');
210 opio->oprom_size = sizeof buf - 0x100;
211 if(!ioctl(fd, OPROMGETOPT, opio))
212 {
213 if(opio->oprom_size < 0x100)
214 {
215 opio->oprom_array[opio->oprom_size] = 0;
216 ADD2LOG(
217 "prom(tty%c-mode) = \"%s\" (%d bytes)\n",
218 (ser_cons & 1) + 'a', opio->oprom_array,
219 opio->oprom_size
220 );
221 hd = add_hd_entry(hd_data, __LINE__, 0);
222 hd->base_class.id = bc_keyboard;
223 hd->sub_class.id = sc_keyboard_console;
224 hd->bus.id = bus_serial;
225 hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0203);
226 hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0000);
227 str_printf(&hd->unix_dev_name, 0, "/dev/ttyS%d", ser_cons);
228 if((i = sscanf(opio->oprom_array, "%u,%u,%c,%u,%c",
229 &u, &u1, &c1, &u2, &c2)) >= 1)
230 {
231 res = add_res_entry(&hd->res, new_mem(sizeof *res));
232 res->baud.type = res_baud;
233 res->baud.speed = u;
234 if(i >= 2) res->baud.bits = u1;
235 if(i >= 3) res->baud.parity = c1;
236 if(i >= 4) res->baud.stopbits = u2;
237 if(i >= 5) res->baud.handshake = c2;
238 }
239 }
240 }
241 close(fd);
242 /* We have a serial console, so don't test for keyboard. Else
243 we will always find a PS/2 keyboard */
244 return;
245 }
246 }
247
248 PROGRESS(1, 0, "sun kbd");
249
250 if((fd = open(DEV_KBD, O_RDWR | O_NONBLOCK | O_NOCTTY)) >= 0)
251 {
252 if(ioctl(fd, KIOCTYPE, &kid)) kid = -1;
253 if(ioctl(fd, KIOCLAYOUT, &klay)) klay = -1;
254 close(fd);
255
256 if(kid != -1)
257 {
258 ADD2LOG("sun keyboard: type %d, layout %d\n", kid, klay);
259
260 hd = add_hd_entry(hd_data, __LINE__, 0);
261 hd->base_class.id = bc_keyboard;
262 hd->sub_class.id = sc_keyboard_kbd;
263 hd->bus.id = bus_serial;
264 if(kid == 4 && klay >= 0)
265 hd->prog_if.id = klay;
266
267 hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0202);
268 kid2 = kid;
269 if(kid == 4 && klay > 0x20)
270 kid2 = 5;
271 hd->device.id = MAKE_ID(TAG_SPECIAL, kid2);
272 if(kid2 == 5) {
273 if(klay == 0x22 || klay == 0x51)
274 {
275 hd->sub_vendor.id = MAKE_ID(TAG_SPECIAL, 0x0202);
276 hd->sub_device.id = MAKE_ID(TAG_SPECIAL, 0x0001);
277 }
278 else if(!(
279 klay == 0x21 || (klay >= 0x2f && klay <= 0x31) ||
280 klay == 0x50 || (klay >= 0x5e && klay <= 0x60)
281 ))
282 {
283 hd->sub_vendor.id = MAKE_ID(TAG_SPECIAL, 0x0202);
284 hd->sub_device.id = MAKE_ID(TAG_SPECIAL, 0x0002);
285 }
286 }
287 }
288 }
289 else
290 {
291 for(hd = hd_data->hd; hd; hd = hd->next) {
292 if(hd->base_class.id == bc_keyboard) break;
293 }
294 if(!hd) {
295 /* We must have a PS/2 Keyboard */
296 hd = add_hd_entry(hd_data, __LINE__, 0);
297 hd->base_class.id = bc_keyboard;
298 hd->sub_class.id = sc_keyboard_kbd;
299 hd->bus.id = bus_ps2;
300 hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0201);
301 hd->device.id = MAKE_ID(TAG_SPECIAL, 1);
302 }
303 }
304 }
305
306 #endif /* __sparc__ */
307
308