* use ENABLE_DIRECTIO to compile in direct I/O. Corrected the long

standing scan area origin detection bug. Improved parport mode
	  negociation.
DEVEL_2_0_BRANCH-1
Stéphane Voltz 2001-11-10 16:43:15 +00:00
rodzic 33ab575684
commit ab7dfb5804
3 zmienionych plików z 226 dodań i 50 usunięć

Wyświetl plik

@ -592,8 +592,7 @@ init_options (Umax_PP_Device * dev)
SANE_Status SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
{ {
char dev_name[512]; char dev_name[512];
const char *cp; const char *cp;
@ -815,7 +814,8 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
val); val);
green_highlight = val; green_highlight = val;
} }
else if (strncmp (cp, "blue-highlight", 14) == 0 && isspace (cp[14])) else if (strncmp (cp, "blue-highlight", 14) == 0
&& isspace (cp[14]))
{ {
char *end; char *end;
long int val; long int val;
@ -968,8 +968,7 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
} }
SANE_Status SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle)
sane_open (SANE_String_Const devicename, SANE_Handle * handle)
{ {
Umax_PP_Device *dev; Umax_PP_Device *dev;
Umax_PP_Descriptor *desc; Umax_PP_Descriptor *desc;
@ -1635,8 +1634,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
} }
SANE_Status SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
{ {
Umax_PP_Device *dev = handle; Umax_PP_Device *dev = handle;
int dpi, remain; int dpi, remain;
@ -1791,8 +1789,7 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
} }
SANE_Status SANE_Status sane_start (SANE_Handle handle)
sane_start (SANE_Handle handle)
{ {
Umax_PP_Device *dev = handle; Umax_PP_Device *dev = handle;
int rc; int rc;
@ -2043,8 +2040,7 @@ sane_cancel (SANE_Handle handle)
} }
} }
SANE_Status SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
{ {
DBG (129, "unused arg: handle = %p, non_blocking = %d\n", DBG (129, "unused arg: handle = %p, non_blocking = %d\n",
handle, (int) non_blocking); handle, (int) non_blocking);
@ -2054,8 +2050,7 @@ sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
return SANE_STATUS_UNSUPPORTED; return SANE_STATUS_UNSUPPORTED;
} }
SANE_Status SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
{ {
DBG (129, "unused arg: handle = %p, fd = %p\n", handle, fd); DBG (129, "unused arg: handle = %p, fd = %p\n", handle, fd);

Wyświetl plik

@ -65,9 +65,17 @@
#elif HAVE_SYS_HW_H #elif HAVE_SYS_HW_H
# include <sys/hw.h> /* OS/2 */ # include <sys/hw.h> /* OS/2 */
#else #else
#ifdef ENABLE_DIRECTIO
#undef ENABLE_DIRECTIO
#endif
#endif
/* we need either direct io or ppdev to function */
#if ! defined ENABLE_DIRECTIO && ! defined HAVE_LINUX_PPDEV_H
#define IO_SUPPORT_MISSING #define IO_SUPPORT_MISSING
#endif #endif
#include "umax_pp_low.h" #include "umax_pp_low.h"
#ifndef __IO__ #ifndef __IO__
@ -138,6 +146,7 @@ static int CmdGetBlockBuffer (int cmd, int len, int window,
static void Bloc2Decode (int *op); static void Bloc2Decode (int *op);
static void Bloc8Decode (int *op); static void Bloc8Decode (int *op);
void sanei_umax_pp_gamma (int *red, int *green, int *blue);
#define WRITESLOW(x,y) \ #define WRITESLOW(x,y) \
@ -394,7 +403,7 @@ sanei_umax_pp_InitPort (int port)
gPort = port; gPort = port;
#ifdef IO_SUPPORT_MISSING #ifdef IO_SUPPORT_MISSING
DBG (1, "*** Direct I/O unavailable, giving up ***\n"); DBG (1, "*** Direct I/O or ppdev unavailable, giving up ***\n");
return (0); return (0);
#else #else
@ -426,14 +435,18 @@ sanei_umax_pp_InitPort (int port)
else else
{ {
sprintf (strmodes, "\n"); sprintf (strmodes, "\n");
if (mode & PARPORT_MODE_COMPAT)
sprintf (strmodes, "%s\t\tPARPORT_MODE_COMPAT\n", strmodes);
if (mode & PARPORT_MODE_PCSPP) if (mode & PARPORT_MODE_PCSPP)
sprintf (strmodes, "%s\t\tPARPORT_MODE_PCSPP\n", strmodes); sprintf (strmodes, "%s\t\tPARPORT_MODE_PCSPP\n", strmodes);
if (mode & PARPORT_MODE_TRISTATE)
sprintf (strmodes, "%s\t\tPARPORT_MODE_TRISTATE\n", strmodes);
if (mode & PARPORT_MODE_EPP) if (mode & PARPORT_MODE_EPP)
sprintf (strmodes, "%s\t\tPARPORT_MODE_EPP\n", strmodes); sprintf (strmodes, "%s\t\tPARPORT_MODE_EPP\n", strmodes);
if (mode & PARPORT_MODE_ECP) if (mode & PARPORT_MODE_ECP)
sprintf (strmodes, "%s\t\tPARPORT_MODE_ECP\n", strmodes); sprintf (strmodes, "%s\t\tPARPORT_MODE_ECP\n", strmodes);
if (mode & PARPORT_MODE_COMPAT)
sprintf (strmodes, "%s\t\tPARPORT_MODE_COMPAT\n", strmodes);
if (mode & PARPORT_MODE_DMA)
sprintf (strmodes, "%s\t\tPARPORT_MODE_DMA\n", strmodes);
DBG (32, "parport modes: %X\n", mode); DBG (32, "parport modes: %X\n", mode);
DBG (32, "parport modes: %s\n", strmodes); DBG (32, "parport modes: %s\n", strmodes);
if (!(mode & PARPORT_MODE_EPP) && !(mode & PARPORT_MODE_ECP)) if (!(mode & PARPORT_MODE_EPP) && !(mode & PARPORT_MODE_ECP))
@ -455,6 +468,13 @@ sanei_umax_pp_InitPort (int port)
#endif #endif
/* prefered mode is EPP */ /* prefered mode is EPP */
mode = IEEE1284_MODE_EPP; mode = IEEE1284_MODE_EPP;
mode = ioctl (fd, PPNEGOT, &mode);
if (mode)
{
DBG (16,
"umax_pp: ppdev couldn't negociate mode IEEE1284_MODE_EPP for '%s'\n",
parport_name);
}
if (ioctl (fd, PPSETMODE, &mode)) if (ioctl (fd, PPSETMODE, &mode))
{ {
DBG (16, DBG (16,
@ -607,13 +627,8 @@ Outb (int port, int value)
#ifdef HAVE_LINUX_PPDEV_H #ifdef HAVE_LINUX_PPDEV_H
int fd, rc; int fd, rc;
unsigned char val; unsigned char val;
#endif
#ifdef HAVE_SYS_HW_H
_outp8 (port, value);
#else
#ifdef HAVE_LINUX_PPDEV_H
fd = sanei_umax_pp_getparport (); fd = sanei_umax_pp_getparport ();
val = (unsigned char) value; val = (unsigned char) value;
if (fd > 0) if (fd > 0)
@ -639,9 +654,14 @@ Outb (int port, int value)
} }
#endif /* HAVE_LINUX_PPDEV_H */ #endif /* HAVE_LINUX_PPDEV_H */
#ifdef ENABLE_DIRECTIO
#ifdef HAVE_SYS_HW_H
_outp8 (port, value);
#else
outb (value, port); outb (value, port);
#endif /* HAVE_SYS_HW_H */ #endif /* HAVE_SYS_HW_H */
#endif /* ENABLE_DIRECTIO */
#endif /* IO_SUPPORT_MISSING */ #endif /* IO_SUPPORT_MISSING */
} }
@ -653,18 +673,13 @@ static int
Inb (int port) Inb (int port)
{ {
int res = 0xFF; int res = 0xFF;
#ifndef IO_SUPPORT_MISSING
#ifdef HAVE_LINUX_PPDEV_H #ifdef HAVE_LINUX_PPDEV_H
int fd, rc; int fd, rc;
unsigned char val; unsigned char val;
#endif
#ifndef IO_SUPPORT_MISSING
#ifdef HAVE_SYS_HW_H
res = _inp8 (port) & 0xFF;
#else
#ifdef HAVE_LINUX_PPDEV_H
fd = sanei_umax_pp_getparport (); fd = sanei_umax_pp_getparport ();
if (fd > 0) if (fd > 0)
{ {
@ -696,9 +711,13 @@ Inb (int port)
} }
#endif /* HAVE_LINUX_PPDEV_H */ #endif /* HAVE_LINUX_PPDEV_H */
#ifdef ENABLE_DIRECTIO
#ifdef HAVE_SYS_HW_H
res = _inp8 (port) & 0xFF;
#else
res = inb (port) & 0xFF; res = inb (port) & 0xFF;
#endif /* HAVE_SYS_HW_H */ #endif /* HAVE_SYS_HW_H */
#endif /* ENABLE_DIRECTIO */
#endif /* IO_SUPPORT_MISSING */ #endif /* IO_SUPPORT_MISSING */
return res; return res;
@ -709,6 +728,7 @@ static void
Insb (int port, unsigned char *dest, int size) Insb (int port, unsigned char *dest, int size)
{ {
#ifndef IO_SUPPORT_MISSING #ifndef IO_SUPPORT_MISSING
#ifdef ENABLE_DIRECTIO
#ifndef __i386__ #ifndef __i386__
int i; int i;
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
@ -720,6 +740,7 @@ Insb (int port, unsigned char *dest, int size)
insb (port, dest, size); insb (port, dest, size);
#endif #endif
#endif #endif
#endif /* ENABLE_DIRECTIO */
#endif #endif
} }
@ -727,6 +748,7 @@ static void
Outsb (int port, unsigned char *source, int size) Outsb (int port, unsigned char *source, int size)
{ {
#ifndef IO_SUPPORT_MISSING #ifndef IO_SUPPORT_MISSING
#ifdef ENABLE_DIRECTIO
#ifndef __i386__ #ifndef __i386__
int i; int i;
@ -739,6 +761,7 @@ Outsb (int port, unsigned char *source, int size)
outsb (port, source, size); outsb (port, source, size);
#endif #endif
#endif #endif
#endif /* ENABLE_DIRECTIO */
#endif #endif
} }
@ -749,6 +772,7 @@ static void
Insw (int port, unsigned char *dest, int size) Insw (int port, unsigned char *dest, int size)
{ {
#ifndef IO_SUPPORT_MISSING #ifndef IO_SUPPORT_MISSING
#ifdef ENABLE_DIRECTIO
#ifndef __i386__ #ifndef __i386__
int i; int i;
@ -761,6 +785,7 @@ Insw (int port, unsigned char *dest, int size)
insl (port, dest, size); insl (port, dest, size);
#endif #endif
#endif #endif
#endif /* ENABLE_DIRECTIO */
#endif #endif
} }
@ -768,6 +793,7 @@ static void
Outsw (int port, unsigned char *source, int size) Outsw (int port, unsigned char *source, int size)
{ {
#ifndef IO_SUPPORT_MISSING #ifndef IO_SUPPORT_MISSING
#ifdef ENABLE_DIRECTIO
#ifndef __i386__ #ifndef __i386__
int i; int i;
@ -780,6 +806,7 @@ Outsw (int port, unsigned char *source, int size)
outsw (port, source, size); outsw (port, source, size);
#endif #endif
#endif #endif
#endif /* ENABLE_DIRECTIO */
#endif #endif
} }
@ -2998,7 +3025,7 @@ ReceiveData (int *cmd, int len)
DBG (16, "ReceiveData, reg1C=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__); DBG (16, "ReceiveData, reg1C=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__);
/* model 0x07 has always the last bit set to 1 */ /* model 0x07 has always the last bit set to 1 */
scannerStatus = reg & 0xFC; scannerStatus = reg & 0xF8;
reg = reg & 0x10; reg = reg & 0x10;
if (reg != 0x10) if (reg != 0x10)
{ {
@ -5927,6 +5954,24 @@ Bloc2Decode (int *op)
DBG (0, "\t->color scan \n"); DBG (0, "\t->color scan \n");
else else
DBG (0, "\t->no color scan \n"); DBG (0, "\t->no color scan \n");
/* byte 14 */
if (op[14] & 0x20)
{
DBG (0, "\t->lamp on \n");
}
else
{
DBG (0, "\t->lamp off \n");
}
if (op[14] & 0x04)
{
DBG (0, "\t->normal scan (head stops at each row) \n");
}
else
{
DBG (0, "\t->move and scan (head doesn't stop at each row) \n");
}
DBG (0, "\n"); DBG (0, "\n");
} }
@ -6070,6 +6115,9 @@ DumpNB (int width, int height, unsigned char *data, char *name)
fclose (fic); fclose (fic);
} }
/* dump data has received from scanner (red line/green line/blue line)
to a color pnm file */
static void static void
DumpRVB (int width, int height, unsigned char *data, char *name) DumpRVB (int width, int height, unsigned char *data, char *name)
{ {
@ -6105,6 +6153,42 @@ DumpRVB (int width, int height, unsigned char *data, char *name)
fclose (fic); fclose (fic);
} }
/* dump a color buffer in a color PNM */
static void
DumpRGB (int width, int height, unsigned char *data, char *name)
{
FILE *fic;
char titre[80];
int y, x;
if (name == NULL)
{
sprintf (titre, "dump%04d.pnm", num);
num++;
}
else
{
sprintf (titre, "%s", name);
}
fic = fopen (titre, "wb");
fprintf (fic, "P6\n%d %d\n255\n", width, height);
if (fic == NULL)
{
DBG (0, "could not open %s for writing\n", titre);
return;
}
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
fputc (data[3 * y * width + x * 3], fic);
fputc (data[3 * y * width + x * 3 + 1], fic);
fputc (data[3 * y * width + x * 3 + 2], fic);
}
}
fclose (fic);
}
@ -6352,7 +6436,6 @@ Move (int distance, int precision, unsigned char *buffer)
/* for each column, finds the row where white/black transition occurs /* for each column, finds the row where white/black transition occurs
then returns the average */ then returns the average */
static float static float
@ -6360,38 +6443,76 @@ EdgePosition (int width, int height, unsigned char *data)
{ {
int ecnt, x, y; int ecnt, x, y;
float epos; float epos;
int d, dmax, dpos; int d, dmax, dpos, i;
unsigned char *dbuffer = NULL;
if (DBG_LEVEL > 128)
{
dbuffer = (unsigned char *) malloc (3 * width * height);
memset (dbuffer, 0x00, 3 * width * height);
}
epos = 0; epos = 0;
ecnt = 0; ecnt = 0;
for (x = 0; x < width; x++) for (x = 0; x < width; x++)
{ {
/* first edge: white->black */ /* edge: white->black drop */
/* loop stops on black area */
dmax = 0; dmax = 0;
dpos = 0; dpos = 0;
for (y = 1; y < height; y++) d = 0;
i = 0;
for (y = 10; (y < height) && (data[i] > 10); y++)
{ {
d = data[x + (y - 1) * width] - data[x + y * width]; i = x + y * width;
d = data[i - width] - data[i];
if (d > dmax) if (d > dmax)
{ {
dmax = d; dmax = d;
dpos = y; dpos = y;
} }
} if ((DBG_LEVEL > 128) && (dbuffer != NULL))
if (dmax > 0)
{ {
dbuffer[i * 3] = data[i];
dbuffer[i * 3 + 1] = data[i];
dbuffer[i * 3 + 2] = data[i];
}
}
epos += dpos; epos += dpos;
ecnt++; ecnt++;
if ((DBG_LEVEL > 128) && (dbuffer != NULL))
{
dbuffer[(x + dpos * width) * 3] = 0xFF;
dbuffer[(x + dpos * width) * 3 + 1] = 0x00;
dbuffer[(x + dpos * width) * 3 + 2] = 0x00;
} }
} }
if (ecnt == 0) if (ecnt == 0)
epos = 70; epos = 70;
else else
epos = epos / ecnt; epos = epos / ecnt;
if ((DBG_LEVEL > 128) && (dbuffer != NULL))
{
i = ((int) epos) * width;
for (x = 0; x < width; x++)
{
dbuffer[(x + i) * 3] = 0x00;
dbuffer[(x + i) * 3 + 1] = 0xFF;
dbuffer[(x + i) * 3 + 2] = 0xFF;
}
for (y = 0; y < height; y++)
{
dbuffer[(width / 2 + y * width) * 3] = 0x00;
dbuffer[(width / 2 + y * width) * 3 + 1] = 0xFF;
dbuffer[(width / 2 + y * width) * 3 + 2] = 0x00;
}
DumpRGB (width, height, dbuffer, NULL);
free (dbuffer);
}
return (epos); return (epos);
} }
static int static int
MoveToOrigin (void) MoveToOrigin (void)
{ {
@ -6467,13 +6588,13 @@ MoveToOrigin (void)
} }
edge = EdgePosition (300, 180, buffer); edge = EdgePosition (300, 180, buffer);
/* rounded to lowest integer, since upping origin might lead */ /* rounded to lowest integer, since upping origin might lead */
/* to bump in the other side if doing a preview */ /* to bump in the other side if doing a full size preview */
val = (int) (edge); val = (int) (edge);
/* edge is 60 dots (at 600 dpi) from origin */ /* edge is 60 dots (at 600 dpi) from origin */
/* origin=current pos - 180 + edge + 60 */ /* origin=current pos - 180 + edge + 60 */
/* grumpf, there is an offset somewhere ... */ /* grumpf, there is an offset somewhere ... */
delta = -180 + edge - 8; delta = -188 + val;
DBG (64, "Edge=%f, val=%d, delta=%d\n", edge, val, delta); DBG (64, "Edge=%f, val=%d, delta=%d\n", edge, val, delta);
/* move back to y-coordinate origin */ /* move back to y-coordinate origin */
@ -7314,6 +7435,13 @@ sanei_umax_pp_StartScan (int x, int y, int width, int height, int dpi,
0x41, 0xA0, 0x0A, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x33, 0x1A, 0x00, 0x41, 0xA0, 0x0A, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x33, 0x1A, 0x00,
-1 -1
}; };
#ifdef UMAX_PP_DANGEROUS_EXPERIMENT
FILE *f = NULL;
char line[1024], *ptr;
int *base = NULL;
int channel;
int max = 0;
#endif
DBG (8, "StartScan(%d,%d,%d,%d,%d,%d,%X);\n", x, y, width, height, dpi, DBG (8, "StartScan(%d,%d,%d,%d,%d,%d,%X);\n", x, y, width, height, dpi,
color, gain); color, gain);
@ -7560,19 +7688,17 @@ sanei_umax_pp_StartScan (int x, int y, int width, int height, int dpi,
{ {
case 1200: case 1200:
opsc53[6] = 0x60; opsc53[6] = 0x60;
opsc53[8] = 0x5F; /* test value */ opsc53[8] = 0x5F;
opsc53[8] = 0x5E; /* old value */
opsc53[8] = 0x5C; /* new working value */
opsc53[9] = 0x05; opsc53[9] = 0x05;
opsc53[14] = opsc53[14] & 0xF0; /*opsc53[14] = opsc53[14] & 0xF0; ~ 0x08 -> scan AND move */
/*opsc53[14] = (opsc53[14] & 0xF0) | 0x04; -> 600 dpi ? */ /*opsc53[14] = (opsc53[14] & 0xF0) | 0x04; -> 600 dpi ? */
/*opsc53[14] = (opsc53[14] & 0xF0) | 0x0C; */
opsc53[14] = (opsc53[14] & 0xF0) | 0x0C; opsc53[14] = (opsc53[14] & 0xF0) | 0x0C;
break; break;
case 600: case 600:
opsc53[6] = 0x60; opsc53[6] = 0x60;
opsc53[8] = 0x2E; /* new working value */ opsc53[8] = 0x2F;
opsc53[8] = 0x2F; /* old value */
opsc53[9] = 0x05; opsc53[9] = 0x05;
opsc53[14] = (opsc53[14] & 0xF0) | 0x04; opsc53[14] = (opsc53[14] & 0xF0) | 0x04;
break; break;
@ -7672,12 +7798,64 @@ sanei_umax_pp_StartScan (int x, int y, int width, int height, int dpi,
CMDSYNC (0x00); CMDSYNC (0x00);
#ifdef UMAX_PP_DANGEROUS_EXPERIMENT
/*opsc53[13] = 0x80; B&W bit */ /*opsc53[13] = 0x80; B&W bit */
/*opsc53[13] = 0x40; green bit */ /*opsc53[13] = 0x40; green bit */
/*opsc53[13] = 0x20; red bit */ /*opsc53[13] = 0x20; red bit */
/*opsc53[13] = 0x10; blue bit */ /*opsc53[13] = 0x10; blue bit */
/* with cmd 01, may be use to do 3 pass scanning ? */ /* with cmd 01, may be use to do 3 pass scanning ? */
/* bits 0 to 3 seem related to sharpness */ /* bits 0 to 3 seem related to sharpness */
f = fopen ("dangerous.params", "rb");
if (f != NULL)
{
while (!feof (f))
{
fgets (line, 1024, f);
channel = 0;
if (sscanf (line, "CMD%1d", &channel) != 1)
channel = 0;
switch (channel)
{
case 0:
break;
case 1:
base = opsc04;
max = 8;
break;
case 2:
base = opsc53;
max = 16;
break;
case 8:
base = opscan;
max = 36;
break;
default:
printf ("WARNING: unknown channel %d\n", channel);
channel = 0;
}
if (channel > 0)
{
printf ("Channel %d:", channel);
ptr = line + 6;
for (i = 0; (i < max) && ((ptr - line) < strlen (line)); i++)
{
if (ptr[0] != '-')
{
sscanf (ptr, "%02X", base + i);
printf ("*");
}
else
printf (" ");
ptr += 3;
printf ("0x%02X ", base[i]);
}
printf ("\n");
}
}
fclose (f);
}
#endif
CMDSETGET (2, 0x10, opsc53); CMDSETGET (2, 0x10, opsc53);

Wyświetl plik

@ -81,6 +81,7 @@ lock_parport (void)
exflags = 0; exflags = 0;
#endif #endif
mode = IEEE1284_MODE_EPP; mode = IEEE1284_MODE_EPP;
ioctl (fd, PPNEGOT, &mode);
ioctl (fd, PPSETMODE, &mode); ioctl (fd, PPSETMODE, &mode);
if (ioctl (sanei_umax_pp_getparport (), PPCLAIM)) if (ioctl (sanei_umax_pp_getparport (), PPCLAIM))
{ {
@ -100,11 +101,13 @@ static int
unlock_parport (void) unlock_parport (void)
{ {
#ifdef HAVE_LINUX_PPDEV_H #ifdef HAVE_LINUX_PPDEV_H
int fd; int fd, mode;
fd = sanei_umax_pp_getparport (); fd = sanei_umax_pp_getparport ();
if ((fd > 0) && (locked)) if ((fd > 0) && (locked))
{ {
mode = IEEE1284_MODE_COMPAT;
ioctl (fd, PPNEGOT, &mode);
ioctl (fd, PPSETMODE, &exmode); ioctl (fd, PPSETMODE, &exmode);
#ifdef PPSETFLAGS #ifdef PPSETFLAGS
ioctl (fd, PPSETFLAGS, &exflags); ioctl (fd, PPSETFLAGS, &exflags);