source: vendor/emx/current/src/os2/xf86sup.c

Last change on this file was 18, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 14.3 KB
Line 
1/* xf86sup.c -- Support for Holger Veit's xf86sup device driver
2 Copyright (c) 1995-1996 by Eberhard Mattes
3
4This file is part of emx.
5
6emx is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11emx is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with emx; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA.
20
21As special exception, emx.dll can be distributed without source code
22unless it has been changed. If you modify emx.dll, this exception
23no longer applies and you must remove this paragraph from all source
24files for emx.dll. */
25
26
27#define INCL_DOSDEVICES
28#define INCL_DOSDEVIOCTL
29#define INCL_DOSERRORS
30#define INCL_DOSSEMAPHORES
31#include <os2emx.h>
32#include <sys/errno.h>
33#include <sys/types.h>
34#include <sys/fcntl.h>
35#include <sys/ioctl.h>
36#include <sys/so_ioctl.h>
37#include <sys/termio.h> /* SysV */
38#include <termios.h> /* POSIX.1 */
39#include "emxdll.h"
40#include "files.h"
41#include "select.h"
42#include "xf86sup.h"
43#include "clib.h"
44
45
46ULONG xf86sup_query (ULONG handle, ULONG *pflags)
47{
48 struct xf86sup_drvid drvid;
49 ULONG rc, data_length;
50 my_file *d;
51
52 memset (&drvid, 0, sizeof (drvid));
53 data_length = sizeof (drvid);
54 rc = DosDevIOCtl (handle, IOCTL_XF86SUP, XF86SUP_DRVID,
55 NULL, 0, NULL,
56 &drvid, data_length, &data_length);
57 if (rc != 0) return rc;
58 if (data_length != sizeof (drvid)
59 || drvid.magic != XF86SUP_MAGIC)
60 return ERROR_BAD_DEV_TYPE;
61 switch (drvid.id)
62 {
63 case XF86SUP_ID_PTY:
64 case XF86SUP_ID_TTY:
65 case XF86SUP_ID_CONSOLE:
66 case XF86SUP_ID_PMAP:
67 case XF86SUP_ID_FASTIO:
68 case XF86SUP_ID_PTMS:
69 break;
70 default:
71 return ERROR_BAD_DEV_TYPE;
72 }
73 *pflags = HF_XF86SUP;
74 d = GET_FILE (handle);
75 d->x.xf86sup.id = drvid.id;
76 d->x.xf86sup.sem_open = FALSE;
77 d->x.xf86sup.sem = 0;
78 return 0;
79}
80
81
82int xf86sup_avail (ULONG handle, int *errnop)
83{
84 ULONG rc, data_length, avail;
85
86 data_length = sizeof (avail);
87 rc = DosDevIOCtl (handle, IOCTL_XF86SUP, XF86SUP_FIONREAD,
88 NULL, 0, NULL,
89 &avail, data_length, &data_length);
90 if (rc != 0)
91 {
92 *errnop = set_error (rc);
93 return -1;
94 }
95 if (data_length != sizeof (avail))
96 {
97 *errnop = EINVAL;
98 return -1;
99 }
100 *errnop = 0;
101 return (int)avail;
102}
103
104
105/* __fcntl() for a tty or pty handle. This function is called for
106 F_SETFL only, and only if O_NDELAY was changed. */
107
108
109int xf86sup_fcntl (ULONG handle, ULONG request, ULONG arg, int *errnop)
110{
111 int on;
112
113 on = arg & O_NDELAY;
114 return xf86sup_ioctl (handle, FIONBIO, (ULONG)&on, errnop);
115}
116
117
118
119/* Common code for xf86sup_termio_get() and xf86sup_termios_get().
120 Returns 0 on success, -1 on error. Always sets *ERRNOP. */
121
122static int xf86sup_tiocgeta (ULONG handle, struct xf86sup_termios *p,
123 int *errnop)
124{
125 ULONG rc, data_length;
126
127 data_length = sizeof (*p);
128 rc = DosDevIOCtl (handle, IOCTL_XF86SUP, XF86SUP_TIOCGETA,
129 NULL, 0, NULL,
130 p, data_length, &data_length);
131 if (rc != 0)
132 {
133 *errnop = set_error (rc);
134 return -1;
135 }
136 *errnop = 0;
137 return 0;
138}
139
140
141/* Handle the TCGETA ioctl. Returns 0 on success, -1 on error.
142 Always sets *ERRNOP.*/
143
144static int xf86sup_termio_get (ULONG handle, struct termio *p, int *errnop)
145{
146 struct xf86sup_termios xtio;
147
148 if (xf86sup_tiocgeta (handle, &xtio, errnop) != 0)
149 return -1;
150 p->c_iflag = xtio.c_iflag;
151 p->c_oflag = xtio.c_oflag;
152 p->c_cflag = xtio.c_cflag;
153 p->c_lflag = xtio.c_lflag;
154 p->c_line = 0;
155 /* Note that this drops three characters! */
156 memcpy (p->c_cc, xtio.c_cc, NCC);
157 return 0;
158}
159
160
161/* Handle the _TCGA ioctl for tcgetattr(). Returns 0 on success, -1
162 on error. Always sets *ERRNOP. */
163
164static int xf86sup_termios_get (ULONG handle, struct termios *p, int *errnop)
165{
166 struct xf86sup_termios xtio;
167
168 if (xf86sup_tiocgeta (handle, &xtio, errnop) != 0)
169 return -1;
170 p->c_iflag = xtio.c_iflag;
171 p->c_oflag = xtio.c_oflag;
172 p->c_cflag = xtio.c_cflag;
173 p->c_lflag = xtio.c_lflag;
174 memcpy (p->c_cc, xtio.c_cc, NCCS);
175 return 0;
176}
177
178
179/* Common code for xf86sup_termio_set() and xf86sup_termios_set().
180 Returns 0 on success, -1 on error. Always sets *ERRNOP. */
181
182static int xf86sup_tiocseta (ULONG handle, struct xf86sup_termios *p,
183 ULONG request, int *errnop)
184{
185 ULONG rc, data_length;
186
187 data_length = sizeof (*p);
188 rc = DosDevIOCtl (handle, IOCTL_XF86SUP, request,
189 p, data_length, &data_length,
190 NULL, 0, NULL);
191 if (rc != 0)
192 {
193 *errnop = set_error (rc);
194 return -1;
195 }
196 *errnop = 0;
197 return 0;
198}
199
200
201/* Handle the TCSETA, TCSETAF, and TCSETAW ioctls. Returns 0 on
202 success, -1 on error. Always sets *ERRNOP. */
203
204static int xf86sup_termio_set (ULONG handle, const struct termio *p,
205 ULONG request, int *errnop)
206{
207 struct xf86sup_termios xtio;
208
209 /* Get the current settings. This is required for VSUSP, VSTOP, and
210 VSTART, which are not provided in `struct termio'. */
211
212 if (xf86sup_tiocgeta (handle, &xtio, errnop) != 0)
213 return -1;
214 xtio.c_iflag = p->c_iflag;
215 xtio.c_oflag = p->c_oflag;
216 xtio.c_cflag = p->c_cflag;
217 xtio.c_lflag = p->c_lflag;
218 /* This leaves alone the last three characters! */
219 memcpy (xtio.c_cc, p->c_cc, NCC);
220 return xf86sup_tiocseta (handle, &xtio, request, errnop);
221}
222
223
224/* Handle the _TCSANOW, _TCSADRAIN, and _TCSAFLUSH ioctls for
225 tcsetattr(). Returns 0 on success, -1 on error. Always sets
226 *ERRNOP. */
227
228static int xf86sup_termios_set (ULONG handle, const struct termios *p,
229 ULONG request, int *errnop)
230{
231 struct xf86sup_termios xtio;
232
233 memset (&xtio, 0, sizeof (xtio)); /* Clear reserved fields */
234 xtio.c_iflag = p->c_iflag;
235 xtio.c_oflag = p->c_oflag;
236 xtio.c_cflag = p->c_cflag;
237 xtio.c_lflag = p->c_lflag;
238 memcpy (xtio.c_cc, p->c_cc, NCCS);
239 return xf86sup_tiocseta (handle, &xtio, request, errnop);
240}
241
242
243/* __ioct2l() for a tty or pty handle. */
244
245int xf86sup_ioctl (ULONG handle, ULONG request, ULONG arg, int *errnop)
246{
247 int n;
248 ULONG rc, parm_length;
249
250 switch (request)
251 {
252 case FGETHTYPE:
253 *(int *)arg = HT_DEV_OTHER; /* TODO */
254 break;
255
256 case FIONREAD:
257 n = xf86sup_avail (handle, errnop);
258 if (n == -1)
259 return -1;
260 *(int *)arg = n;
261 break;
262
263 case FIONBIO:
264 parm_length = sizeof (int);
265 rc = DosDevIOCtl (handle, IOCTL_XF86SUP, XF86SUP_FIONBIO,
266 (PVOID)arg, parm_length, &parm_length,
267 NULL, 0, NULL);
268 if (rc != 0)
269 {
270 *errnop = set_error (rc);
271 return -1;
272 }
273 if (*(int *)arg)
274 handle_flags[handle] |= HF_NDELAY;
275 else
276 handle_flags[handle] &= ~HF_NDELAY;
277 break;
278
279 case TCGETA:
280 return xf86sup_termio_get (handle, (struct termio *)arg, errnop);
281
282 case TCSETA:
283 return xf86sup_termio_set (handle, (const struct termio *)arg,
284 XF86SUP_TIOCSETA, errnop);
285
286 case TCSETAF:
287 return xf86sup_termio_set (handle, (const struct termio *)arg,
288 XF86SUP_TIOCSETAF, errnop);
289
290 case TCSETAW:
291 return xf86sup_termio_set (handle, (const struct termio *)arg,
292 XF86SUP_TIOCSETAW, errnop);
293
294 case TCFLSH:
295 parm_length = sizeof (int);
296 rc = DosDevIOCtl (handle, IOCTL_XF86SUP, XF86SUP_TIOCFLUSH,
297 &arg, parm_length, &parm_length,
298 NULL, 0, NULL);
299 if (rc != 0)
300 {
301 *errnop = set_error (rc);
302 return -1;
303 }
304 break;
305
306 case TCSBRK:
307 rc = DosDevIOCtl (handle, IOCTL_XF86SUP, XF86SUP_TIOCDRAIN,
308 NULL, 0, NULL,
309 NULL, 0, NULL);
310 if (rc != 0)
311 {
312 *errnop = set_error (rc);
313 return -1;
314 }
315 break;
316
317 case TCXONC:
318 /* Flow control. */
319 break;
320
321 case _TCGA:
322 return xf86sup_termios_get (handle, (struct termios *)arg, errnop);
323
324 case _TCSANOW:
325 return xf86sup_termios_set (handle, (const struct termios *)arg,
326 XF86SUP_TIOCSETA, errnop);
327
328 case _TCSADRAIN:
329 return xf86sup_termios_set (handle, (const struct termios *)arg,
330 XF86SUP_TIOCSETAW, errnop);
331
332 case _TCSAFLUSH:
333 return xf86sup_termios_set (handle, (const struct termios *)arg,
334 XF86SUP_TIOCSETAF, errnop);
335
336 default:
337 *errnop = EINVAL;
338 return -1;
339 }
340
341 /* Function successfully completed. */
342
343 *errnop = 0;
344 return 0;
345}
346
347
348/* __select(): Add a semaphore for a pty, tty, or /dev/console$ handle,
349 to be posted when data becomes ready for reading. */
350
351int xf86sup_select_add_read (struct select_data *d, int fd)
352{
353 HEV sem;
354 my_file *f;
355 int i;
356 ULONG rc, parm_length, data_length, arm_on;
357 struct xf86sup_selreg selreg;
358
359 if (!IS_VALID_FILE (fd))
360 return EBADF;
361
362 f = GET_FILE (fd);
363 if (f->x.xf86sup.id != XF86SUP_ID_PTY && f->x.xf86sup.id != XF86SUP_ID_TTY
364 && f->x.xf86sup.id != XF86SUP_ID_CONSOLE)
365 return 0; /* Silently ignore */
366 if (f->x.xf86sup.sem_open)
367 sem = f->x.xf86sup.sem;
368 else
369 {
370 /* Check whether a semaphore is already registered. As the
371 semaphore handles to be registered are null (invalid) and
372 xf86sup.sys tries to open the new semaphore handles, we'll
373 get ERROR_INVALID_PARAMETER if there are no semaphores
374 registered. */
375
376 selreg.rsel = selreg.xsel = 0;
377 selreg.code = 0;
378 parm_length = sizeof (selreg);
379 data_length = sizeof (selreg);
380 rc = DosDevIOCtl (fd, IOCTL_XF86SUP, XF86SUP_SELREG,
381 &selreg, parm_length, &parm_length,
382 &selreg, data_length, &data_length);
383 if (rc == 0 && selreg.rsel != 0)
384 {
385 /* There is a semaphore registered. Open it. */
386
387 sem = (HEV)selreg.rsel;
388 rc = DosOpenEventSem (NULL, &sem);
389 if (rc != 0) return set_error (rc);
390 f->x.xf86sup.sem = sem;
391 f->x.xf86sup.sem_open = TRUE;
392 }
393 else
394 {
395 /* Create a semaphore which will be registered with
396 xf86sup.sys. Don't use create_event_sem() as the
397 semaphore will stick forever (and to avoid overflowing
398 the semaphore table). */
399
400 if (DosCreateEventSem (NULL, &sem, DC_SEM_SHARED, FALSE) != 0)
401 return EINVAL;
402
403 /* Register the semaphore with xf86sup.sys. Unfortunately,
404 xf86sup.sys does not accept null handles, therefore we
405 use the semaphore also for xsel. TODO: This will cause
406 problems with other processes trying to register two
407 distinct semaphores with this pty/tty pair in the
408 future. */
409
410 selreg.rsel = (ULONG)sem; selreg.xsel = (ULONG)sem;
411 selreg.code = 0;
412 parm_length = sizeof (selreg);
413 data_length = sizeof (selreg);
414 rc = DosDevIOCtl (fd, IOCTL_XF86SUP, XF86SUP_SELREG,
415 &selreg, parm_length, &parm_length,
416 &selreg, data_length, &data_length);
417 if (rc != 0)
418 {
419 DosCloseEventSem (sem);
420 return set_error (rc);
421 }
422
423 /* If someone else has registered a semaphore in the
424 meantime, use that semaphore. */
425
426 if (selreg.code & XF86SUP_SEL_READ)
427 {
428 DosCloseEventSem (sem);
429 sem = (HEV)selreg.rsel;
430 }
431 f->x.xf86sup.sem = sem;
432 f->x.xf86sup.sem_open = TRUE;
433 }
434 }
435
436 /* The semaphore handle is now in SEM. Add the semaphore to the
437 MuxWait list, unless it's already in the list. */
438
439 for (i = 0; i < d->sem_count; ++i)
440 if (d->list[i].hsemCur == (HSEM)sem)
441 break;
442 if (i >= d->sem_count)
443 {
444 /* The semaphore is not yet in the list. Add it. */
445
446 if (d->sem_count >= d->max_sem)
447 return EINVAL;
448 else
449 {
450 d->list[d->sem_count].hsemCur = (HSEM)sem;
451 d->list[d->sem_count].ulUser = 0;
452 ++d->sem_count;
453 }
454 }
455
456 /* Arm the semaphore. Arming a semaphore multiple times doesn't
457 hurt as we first arm all semaphores, then poll all handles. */
458
459 parm_length = sizeof (arm_on);
460 arm_on = XF86SUP_SEL_READ;
461 rc = DosDevIOCtl (fd, IOCTL_XF86SUP, XF86SUP_SELARM,
462 &arm_on, parm_length, &parm_length,
463 NULL, 0, NULL);
464 if (rc != 0)
465 return set_error (rc);
466 return 0;
467}
468
469
470int xf86sup_ttyname (char *dst, ULONG dst_size, ULONG handle, int *errnop)
471{
472 ULONG rc, parm_length, data_length;
473 char buf[14], *p;
474
475 parm_length = 0;
476 data_length = sizeof (buf);
477 rc = DosDevIOCtl (handle, IOCTL_XF86SUP, XF86SUP_NAME,
478 NULL, parm_length, &parm_length,
479 buf, data_length, &data_length);
480 if (rc != 0)
481 {
482 *errnop = set_error (rc);
483 return -1;
484 }
485
486 /* There's no point in handling DBCS characters here. */
487
488 for (p = buf; *p != 0; ++p)
489 if (*p == '\\')
490 *p = '/';
491 return set_ttyname (dst, dst_size, buf, errnop);
492}
493
494
495ULONG xf86sup_uncond_enadup (ULONG handle, ULONG on)
496{
497 ULONG data_length;
498
499 data_length = sizeof (on);
500 return DosDevIOCtl (handle, IOCTL_XF86SUP, XF86SUP_ENADUP,
501 &on, data_length, &data_length,
502 NULL, 0, NULL);
503}
504
505
506ULONG xf86sup_maybe_enadup (ULONG handle, ULONG on)
507{
508 if (handle < handle_count
509 && (handle_flags[handle] & (HF_OPEN|HF_XF86SUP))
510 && IS_VALID_FILE (handle)
511 && GET_FILE (handle)->x.xf86sup.id == XF86SUP_ID_PTY)
512 return xf86sup_uncond_enadup (handle, on);
513 else
514 return 0;
515}
516
517
518void xf86sup_all_enadup (ULONG on)
519{
520 ULONG i;
521
522 for (i = 0; i < handle_count; ++i)
523 if ((handle_flags[i] & (HF_OPEN|HF_XF86SUP))
524 && IS_VALID_FILE (i)
525 && GET_FILE (i)->x.xf86sup.id == XF86SUP_ID_PTY)
526 xf86sup_uncond_enadup (i, on);
527}
Note: See TracBrowser for help on using the repository browser.