]> git.ipfire.org Git - ipfire-2.x.git/blob - src/hwinfo/src/hd/braille.c
Kleiner netter neuer Versuch.
[ipfire-2.x.git] / src / hwinfo / src / hd / braille.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <termios.h>
7
8 #include "hd.h"
9 #include "hd_int.h"
10 #include "braille.h"
11
12 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
13 * braille displays
14 *
15 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
16 */
17
18 #if !defined(LIBHD_TINY) && !defined(__sparc__)
19
20 static unsigned do_alva(hd_data_t *hd_data, char *dev_name, int cnt);
21 static unsigned do_fhp(hd_data_t *hd_data, char *dev_name, unsigned baud, int cnt);
22 static unsigned do_ht(hd_data_t *hd_data, char *dev_name, int cnt);
23 static unsigned do_baum(hd_data_t *hd_data, char *dev_name, int cnt);
24
25 void hd_scan_braille(hd_data_t *hd_data)
26 {
27 hd_t *hd, *hd_tmp;
28 int cnt = 0;
29 unsigned dev, vend;
30
31 if(!hd_probe_feature(hd_data, pr_braille)) return;
32
33 hd_data->module = mod_braille;
34
35 /* some clean-up */
36 remove_hd_entries(hd_data);
37
38 for(hd = hd_data->hd; hd; hd = hd->next) {
39 if(
40 hd->base_class.id == bc_comm &&
41 hd->sub_class.id == sc_com_ser &&
42 hd->unix_dev_name &&
43 !hd->tag.ser_skip &&
44 !has_something_attached(hd_data, hd)
45 ) {
46 cnt++;
47 dev = vend = 0;
48
49 if(hd_probe_feature(hd_data, pr_braille_alva)) {
50 PROGRESS(1, cnt, "alva");
51 vend = MAKE_ID(TAG_SPECIAL, 0x5001);
52 dev = do_alva(hd_data, hd->unix_dev_name, cnt);
53 }
54
55 if(!dev && hd_probe_feature(hd_data, pr_braille_fhp)) {
56 PROGRESS(1, cnt, "fhp_old");
57 vend = MAKE_ID(TAG_SPECIAL, 0x5002);
58 dev = do_fhp(hd_data, hd->unix_dev_name, B19200, cnt);
59 if(!dev) {
60 PROGRESS(1, cnt, "fhp_el");
61 dev = do_fhp(hd_data, hd->unix_dev_name, B38400, cnt);
62 }
63 }
64
65 if(!dev && hd_probe_feature(hd_data, pr_braille_ht)) {
66 PROGRESS(1, cnt, "ht");
67 vend = MAKE_ID(TAG_SPECIAL, 0x5003);
68 dev = do_ht(hd_data, hd->unix_dev_name, cnt);
69 }
70
71 if(!dev && hd_probe_feature(hd_data, pr_braille_baum)) {
72 PROGRESS(1, cnt, "baum");
73 vend = MAKE_ID(TAG_SPECIAL, 0x5004);
74 dev = do_baum(hd_data, hd->unix_dev_name, cnt);
75 }
76
77 if(dev) {
78 hd_tmp = add_hd_entry(hd_data, __LINE__, 0);
79 hd_tmp->base_class.id = bc_braille;
80 hd_tmp->bus.id = bus_serial;
81 hd_tmp->unix_dev_name = new_str(hd->unix_dev_name);
82 hd_tmp->attached_to = hd->idx;
83 hd_tmp->vendor.id = vend;
84 hd_tmp->device.id = dev;
85 }
86 }
87 }
88 }
89
90
91 /*
92 * autodetect for Alva Braille-displays
93 * Author: marco Skambraks <marco@suse.de>
94 * Suse GmbH Nuernberg
95 *
96 * This is free software, placed under the terms of the
97 * GNU General Public License, as published by the Free Software
98 * Foundation. Please see the file COPYING for details.
99 */
100
101 /* Communication codes */
102 #define BRL_ID "\033ID="
103
104
105 #define WAIT_DTR 700000
106 #define WAIT_FLUSH 200
107
108 unsigned do_alva(hd_data_t *hd_data, char *dev_name, int cnt)
109 {
110 int fd, i, timeout = 100;
111 struct termios oldtio, newtio; /* old & new terminal settings */
112 int model = -1;
113 unsigned char buffer[sizeof BRL_ID];
114 unsigned dev = 0;
115
116 PROGRESS(2, cnt, "alva open");
117
118 /* Open the Braille display device for random access */
119 fd = open(dev_name, O_RDWR | O_NOCTTY);
120 if(fd < 0) return 0;
121
122 tcgetattr(fd, &oldtio); /* save current settings */
123
124 /* Set flow control and 8n1, enable reading */
125 memset(&newtio, 0, sizeof newtio);
126 newtio.c_cflag = CRTSCTS | CS8 | CLOCAL | CREAD;
127 /* Ignore bytes with parity errors and make terminal raw and dumb */
128 newtio.c_iflag = IGNPAR;
129 newtio.c_oflag = 0; /* raw output */
130 newtio.c_lflag = 0; /* don't echo or generate signals */
131 newtio.c_cc[VMIN] = 0; /* set nonblocking read */
132 newtio.c_cc[VTIME] = 0;
133
134 PROGRESS(3, cnt, "alva init ok");
135
136 PROGRESS(4, cnt, "alva read data");
137
138 /* autodetecting ABT model */
139 /* to force DTR off */
140 cfsetispeed(&newtio, B0);
141 cfsetospeed(&newtio, B0);
142 tcsetattr(fd, TCSANOW, &newtio); /* activate new settings */
143 usleep(WAIT_DTR);
144
145 tcflush(fd, TCIOFLUSH); /* clean line */
146 usleep(WAIT_FLUSH);
147
148 /* DTR back on */
149 cfsetispeed(&newtio, B9600);
150 cfsetospeed(&newtio, B9600);
151 tcsetattr(fd, TCSANOW, &newtio); /* activate new settings */
152 usleep(WAIT_DTR); /* give time to send ID string */
153
154 if((i = read(fd, buffer, sizeof buffer)) == sizeof buffer) {
155 if(!strncmp(buffer, BRL_ID, sizeof BRL_ID - 1)) {
156 /* Find out which model we are connected to... */
157 switch(model = buffer[sizeof buffer - 1])
158 {
159 case 1:
160 case 2:
161 case 3:
162 case 4:
163 case 0x0b:
164 case 0x0d:
165 case 0x0e:
166 dev = MAKE_ID(TAG_SPECIAL, model);
167 break;
168 }
169 }
170 }
171 ADD2LOG("alva.%d@%s[%d]: ", timeout, dev_name, i);
172 if(i > 0) hexdump(&hd_data->log, 1, i, buffer);
173 ADD2LOG("\n");
174
175 PROGRESS(5, cnt, "alva read done");
176
177 /* reset serial lines */
178 tcflush(fd, TCIOFLUSH);
179 tcsetattr(fd, TCSAFLUSH, &oldtio);
180 close(fd);
181
182 return dev;
183 }
184
185
186 /*
187 * autodetect for Papenmeier Braille-displays
188 * Author: marco Skambraks <marco@suse.de>
189 * Suse GmbH Nuernberg
190 *
191 * This is free software, placed under the terms of the
192 * GNU General Public License, as published by the Free Software
193 * Foundation. Please see the file COPYING for details.
194 */
195
196 unsigned do_fhp(hd_data_t *hd_data, char *dev_name, unsigned baud, int cnt)
197 {
198 int fd, i;
199 char crash[] = { 2, 'S', 0, 0, 0, 0 };
200 unsigned char buf[10];
201 struct termios oldtio, newtio; /* old & new terminal settings */
202 unsigned dev;
203
204 PROGRESS(2, cnt, "fhp open");
205
206 /* Now open the Braille display device for random access */
207 fd = open(dev_name, O_RDWR | O_NOCTTY);
208 if(fd < 0) return 0;
209
210 tcgetattr(fd, &oldtio); /* save current settings */
211
212 /* Set bps, flow control and 8n1, enable reading */
213 memset(&newtio, 0, sizeof newtio);
214 newtio.c_cflag = baud | CS8 | CLOCAL | CREAD;
215
216 /* Ignore bytes with parity errors and make terminal raw and dumb */
217 newtio.c_iflag = IGNPAR;
218 newtio.c_oflag = 0; /* raw output */
219 newtio.c_lflag = 0; /* don't echo or generate signals */
220 newtio.c_cc[VMIN] = 0; /* set nonblocking read */
221 newtio.c_cc[VTIME] = 0;
222 tcflush(fd, TCIFLUSH); /* clean line */
223 tcsetattr(fd, TCSANOW, &newtio); /* activate new settings */
224
225 PROGRESS(3, cnt, "fhp init ok");
226
227 crash[2] = 0x200 >> 8;
228 crash[3] = 0x200 & 0xff;
229 crash[5] = (7+10) & 0xff;
230
231 write(fd, crash, sizeof crash);
232 write(fd, "1111111111",10);
233 write(fd, "\03", 1);
234
235 crash[2] = 0x0 >> 8;
236 crash[3] = 0x0 & 0xff;
237 crash[5] = 5 & 0xff;
238
239 write(fd, crash, sizeof crash);
240 write(fd, "1111111111", 10);
241 write(fd, "\03", 1);
242
243 usleep(500000); /* 100000 should be enough */
244
245 PROGRESS(4, cnt, "fhp write ok");
246
247 i = read(fd, &buf, 10);
248
249 PROGRESS(5, cnt, "fhp read done");
250
251 ADD2LOG("fhp@%s[%d]: ", dev_name, i);
252 if(i > 0) hexdump(&hd_data->log, 1, i, buf);
253 ADD2LOG("\n");
254
255 dev = 0;
256 if(i == 10 && buf[0] == 0x02 && buf[1] == 0x49) {
257 switch(buf[2]) {
258 case 1:
259 case 2:
260 case 3:
261 case 64:
262 case 65:
263 case 66:
264 case 67:
265 case 68:
266 dev = buf[2];
267 dev = MAKE_ID(TAG_SPECIAL, dev);
268 break;
269 }
270 }
271 if(!dev) ADD2LOG("no fhp display: 0x%02x\n", i >= 2 ? buf[2] : 0);
272
273 /* reset serial lines */
274 tcflush(fd, TCIOFLUSH);
275 tcsetattr(fd, TCSAFLUSH, &oldtio);
276 close(fd);
277
278 return dev;
279 }
280
281
282 /*
283 * autodetect for Handy Tech Braille-displays
284 * Author: marco Skambraks <marco@suse.de>
285 * Suse GmbH Nuernberg
286 *
287 * This is free software, placed under the terms of the
288 * GNU General Public License, as published by the Free Software
289 * Foundation. Please see the file COPYING for details.
290 */
291
292 unsigned do_ht(hd_data_t *hd_data, char *dev_name, int cnt)
293 {
294 int fd, i;
295 unsigned char code = 0xff, buf[2] = { 0, 0 };
296 struct termios oldtio, newtio;
297 unsigned dev = 0;
298
299 PROGRESS(2, cnt, "ht open");
300
301 fd = open(dev_name, O_RDWR | O_NOCTTY);
302 if(fd < 0) return 0;
303
304 tcgetattr(fd, &oldtio);
305
306 newtio = oldtio;
307 newtio.c_cflag = CLOCAL | PARODD | PARENB | CREAD | CS8;
308 newtio.c_iflag = IGNPAR;
309 newtio.c_oflag = 0;
310 newtio.c_lflag = 0;
311 newtio.c_cc[VMIN] = 0;
312 newtio.c_cc[VTIME] = 0;
313
314 i = 0;
315 /*
316 * Force down DTR, flush any pending data and then the port to what we
317 * want it to be
318 */
319 if(
320 !(
321 cfsetispeed(&newtio, B0) ||
322 cfsetospeed(&newtio, B0) ||
323 tcsetattr(fd, TCSANOW, &newtio) ||
324 tcflush(fd, TCIOFLUSH) ||
325 cfsetispeed(&newtio, B19200) ||
326 cfsetospeed(&newtio, B19200) ||
327 tcsetattr(fd, TCSANOW, &newtio)
328 )
329 ) {
330 /* Pause to let them take effect */
331 usleep(500);
332
333 PROGRESS(3, cnt, "ht init ok");
334
335 write(fd, &code, 1); /* reset brl */
336 usleep(5000); /* wait for reset */
337
338 PROGRESS(4, cnt, "ht write ok");
339
340 read(fd, buf, 1);
341 i = 1;
342
343 PROGRESS(5, cnt, "ht read done");
344
345 if(buf[0] == 0xfe) { /* resetok now read id */
346 usleep(5000);
347 read(fd, buf + 1, 1);
348 i = 2;
349
350 PROGRESS(6, cnt, "ht read done");
351
352 switch(buf[1]) {
353 case 0x05:
354 case 0x09:
355 case 0x44:
356 case 0x74:
357 case 0x80:
358 case 0x84:
359 case 0x88:
360 case 0x89:
361 dev = buf[1];
362 dev = MAKE_ID(TAG_SPECIAL, dev);
363 break;
364 }
365 }
366 }
367
368 ADD2LOG("ht@%s[%d]: ", dev_name, i);
369 if(i > 0) hexdump(&hd_data->log, 1, i, buf);
370 ADD2LOG("\n");
371
372 if(!dev) ADD2LOG("no ht display: 0x%02x\n", buf[1]);
373
374 /* reset serial lines */
375 tcflush(fd, TCIOFLUSH);
376 tcsetattr(fd, TCSAFLUSH, &oldtio);
377 close(fd);
378
379 return dev;
380 }
381
382
383 /*
384 * autodetect for Baum Braille-displays
385 * Author: marco Skambraks <marco@suse.de>
386 * Suse GmbH Nuernberg
387 *
388 * This is free software, placed under the terms of the
389 * GNU General Public License, as published by the Free Software
390 * Foundation. Please see the file COPYING for details.
391 */
392
393 #define BAUDRATE B19200 /* But both run at 19k2 */
394 #define MAXREAD 18
395
396 unsigned do_baum(hd_data_t *hd_data, char *dev_name, int cnt)
397 {
398 static char device_id[] = { 0x1b, 0x84 };
399 int fd;
400 struct termios oldtio, curtio;
401 unsigned char buf[MAXREAD + 1];
402 int i;
403
404 PROGRESS(2, cnt, "baum open");
405
406 fd = open(dev_name, O_RDWR | O_NOCTTY);
407 if(fd < 0) return 0;
408
409 tcgetattr(fd, &curtio);
410
411 oldtio = curtio;
412 cfmakeraw(&curtio);
413
414 /* no SIGTTOU to backgrounded processes */
415 curtio.c_lflag &= ~TOSTOP;
416 curtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
417 /* no input parity check, no XON/XOFF */
418 curtio.c_iflag &= ~(INPCK | ~IXOFF);
419
420 curtio.c_cc[VTIME] = 1; /* 0.1s timeout between chars on input */
421 curtio.c_cc[VMIN] = 0; /* no minimum input */
422
423 tcsetattr(fd, TCSAFLUSH, &curtio);
424
425 /* write ID-request */
426 write(fd, device_id, sizeof device_id);
427
428 /* wait for response */
429 usleep(100000);
430
431 PROGRESS(3, cnt, "baum write ok");
432
433 i = read(fd, buf, sizeof buf - 1);
434 buf[sizeof buf - 1] = 0;
435
436 PROGRESS(4, cnt, "baum read done");
437
438 ADD2LOG("baum@%s[%d]: ", dev_name, i);
439 if(i > 0) hexdump(&hd_data->log, 1, i, buf);
440 ADD2LOG("\n");
441
442 /* reset serial lines */
443 tcflush(fd, TCIOFLUSH);
444 tcsetattr(fd, TCSAFLUSH, &oldtio);
445 close(fd);
446
447 if(!strcmp(buf + 2, "Baum Vario40")) return 1;
448 if(!strcmp(buf + 2, "Baum Vario80")) return 2;
449
450 return 0;
451 }
452
453
454 #endif /* !defined(LIBHD_TINY) && !defined(__sparc__) */
455