| 1 | /* xf86sup.c -- Support for Holger Veit's xf86sup device driver
|
|---|
| 2 | Copyright (c) 1995-1996 by Eberhard Mattes
|
|---|
| 3 |
|
|---|
| 4 | This file is part of emx.
|
|---|
| 5 |
|
|---|
| 6 | emx is free software; you can redistribute it and/or modify it
|
|---|
| 7 | under the terms of the GNU General Public License as published by
|
|---|
| 8 | the Free Software Foundation; either version 2, or (at your option)
|
|---|
| 9 | any later version.
|
|---|
| 10 |
|
|---|
| 11 | emx is distributed in the hope that it will be useful,
|
|---|
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|---|
| 14 | GNU General Public License for more details.
|
|---|
| 15 |
|
|---|
| 16 | You should have received a copy of the GNU General Public License
|
|---|
| 17 | along with emx; see the file COPYING. If not, write to
|
|---|
| 18 | the Free Software Foundation, 59 Temple Place - Suite 330,
|
|---|
| 19 | Boston, MA 02111-1307, USA.
|
|---|
| 20 |
|
|---|
| 21 | As special exception, emx.dll can be distributed without source code
|
|---|
| 22 | unless it has been changed. If you modify emx.dll, this exception
|
|---|
| 23 | no longer applies and you must remove this paragraph from all source
|
|---|
| 24 | files 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 |
|
|---|
| 46 | ULONG 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 |
|
|---|
| 82 | int 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 |
|
|---|
| 109 | int 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 |
|
|---|
| 122 | static 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 |
|
|---|
| 144 | static 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 |
|
|---|
| 164 | static 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 |
|
|---|
| 182 | static 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 |
|
|---|
| 204 | static 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 |
|
|---|
| 228 | static 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 |
|
|---|
| 245 | int 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 |
|
|---|
| 351 | int 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 |
|
|---|
| 470 | int 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 |
|
|---|
| 495 | ULONG 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 |
|
|---|
| 506 | ULONG 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 |
|
|---|
| 518 | void 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 | }
|
|---|