Beispiel #1
0
static NTSTATUS xmit_immediate(HANDLE hDevice, int fd, char* ptr)
{
    /* FIXME: not perfect as it should bypass the in-queue */
    WARN("(%p,'%c') not perfect!\n", hDevice, *ptr);
    if (write(fd, ptr, 1) != 1)
        return FILE_GetNtStatus();
    return STATUS_SUCCESS;
}
Beispiel #2
0
static NTSTATUS set_XOn(int fd)
{
    struct termios      port;

    if (tcgetattr(fd,&port) == -1)
    {
        FIXME("tcgetattr on fd %d failed (%s)!\n", fd, strerror(errno));
        return FILE_GetNtStatus();
    }
    port.c_iflag |= IXON;
    if (tcsetattr(fd, TCSADRAIN, &port) == -1)
    {
        FIXME("tcsetattr on fd %d failed (%s)!\n", fd, strerror(errno));
        return FILE_GetNtStatus();
    }
    return STATUS_SUCCESS;
}
Beispiel #3
0
/*
 * does not change IXON but simulates that IXON has been received:
 */
static NTSTATUS set_XOn(int fd)
{
    if (tcflow(fd, TCOON))
    {
        return FILE_GetNtStatus();
    }
    return STATUS_SUCCESS;
}
Beispiel #4
0
static NTSTATUS set_timeouts(HANDLE handle, int fd, const SERIAL_TIMEOUTS* st)
{
    NTSTATUS            status;
    struct termios      port;
    unsigned int        ux_timeout;

    SERVER_START_REQ( set_serial_info )
    {
        req->handle       = handle;
        req->flags        = SERIALINFO_SET_TIMEOUTS;
        req->readinterval = st->ReadIntervalTimeout ;
        req->readmult     = st->ReadTotalTimeoutMultiplier ;
        req->readconst    = st->ReadTotalTimeoutConstant ;
        req->writemult    = st->WriteTotalTimeoutMultiplier ;
        req->writeconst   = st->WriteTotalTimeoutConstant ;
        status = wine_server_call( req );
    }
    SERVER_END_REQ;
    if (status) return status;

    if (tcgetattr(fd, &port) == -1)
    {
        FIXME("tcgetattr on fd %d failed (%s)!\n", fd, strerror(errno));
        return FILE_GetNtStatus();
    }

    /* VTIME is in 1/10 seconds */
    if (st->ReadIntervalTimeout == 0) /* 0 means no timeout */
        ux_timeout = 0;
    else
    {
        ux_timeout = (st->ReadIntervalTimeout + 99) / 100;
        if (ux_timeout == 0)
            ux_timeout = 1; /* must be at least some timeout */
    }
    port.c_cc[VTIME] = ux_timeout;

    if (tcsetattr(fd, 0, &port) == -1)
    {
        FIXME("tcsetattr on fd %d failed (%s)!\n", fd, strerror(errno));
        return FILE_GetNtStatus();
    }
    return STATUS_SUCCESS;
}
Beispiel #5
0
static NTSTATUS get_baud_rate(int fd, SERIAL_BAUD_RATE* sbr)
{
    struct termios port;
    int speed;
    
    if (tcgetattr(fd, &port) == -1)
    {
        ERR("tcgetattr error '%s'\n", strerror(errno));
        return FILE_GetNtStatus();
    }
#ifndef __EMX__
#ifdef CBAUD
    speed = port.c_cflag & CBAUD;
#else
    speed = cfgetospeed(&port);
#endif
    switch (speed)
    {
    case B0:            sbr->BaudRate = 0;      break;
    case B50:           sbr->BaudRate = 50;	break;
    case B75:		sbr->BaudRate = 75;	break;
    case B110:		sbr->BaudRate = 110;	break;
    case B134:		sbr->BaudRate = 134;	break;
    case B150:		sbr->BaudRate = 150;	break;
    case B200:		sbr->BaudRate = 200;	break;
    case B300:		sbr->BaudRate = 300;	break;
    case B600:		sbr->BaudRate = 600;	break;
    case B1200:		sbr->BaudRate = 1200;	break;
    case B1800:		sbr->BaudRate = 1800;	break;
    case B2400:		sbr->BaudRate = 2400;	break;
    case B4800:		sbr->BaudRate = 4800;	break;
    case B9600:		sbr->BaudRate = 9600;	break;
    case B19200:	sbr->BaudRate = 19200;	break;
    case B38400:	sbr->BaudRate = 38400;	break;
#ifdef B57600
    case B57600:	sbr->BaudRate = 57600;	break;
#endif
#ifdef B115200
    case B115200:	sbr->BaudRate = 115200;	break;
#endif
#ifdef B230400
    case B230400:	sbr->BaudRate = 230400;	break;
#endif
#ifdef B460800
    case B460800:	sbr->BaudRate = 460800;	break;
#endif
    default:
        ERR("unknown speed %x\n", speed);
        return STATUS_INVALID_PARAMETER;
    }
#else
    return STATUS_INVALID_PARAMETER;
#endif
    return STATUS_SUCCESS;
}
Beispiel #6
0
/***********************************************************************
 *           wine_server_handle_to_fd   (NTDLL.@)
 *
 * Retrieve the file descriptor corresponding to a file handle.
 *
 * PARAMS
 *     handle  [I] Wine file handle.
 *     access  [I] Win32 file access rights requested.
 *     unix_fd [O] Address where Unix file descriptor will be stored.
 *     options [O] Address where the file open options will be stored. Optional.
 *
 * RETURNS
 *     NTSTATUS code
 */
int CDECL wine_server_handle_to_fd( HANDLE handle, unsigned int access, int *unix_fd,
                              unsigned int *options )
{
    int needs_close, ret = server_get_unix_fd( handle, access, unix_fd, &needs_close, NULL, options );

    if (!ret && !needs_close)
    {
        if ((*unix_fd = dup(*unix_fd)) == -1) ret = FILE_GetNtStatus();
    }
    return ret;
}
Beispiel #7
0
static NTSTATUS get_hand_flow(int fd, SERIAL_HANDFLOW* shf)
{
    int stat = 0;
    struct termios port;

    if (tcgetattr(fd, &port) == -1)
    {
        ERR("tcgetattr error '%s'\n", strerror(errno));
        return FILE_GetNtStatus();
    }
    /* termios does not support DTR/DSR flow control */
    shf->ControlHandShake = 0;
    shf->FlowReplace = 0;
#ifdef TIOCMGET
    if (ioctl(fd, TIOCMGET, &stat) == -1)
    {
        WARN("ioctl error '%s'\n", strerror(errno));
        shf->ControlHandShake |= SERIAL_DTR_CONTROL;
        shf->FlowReplace |= SERIAL_RTS_CONTROL;
    }
#else
    WARN("Setting DTR/RTS to enabled by default\n");
    shf->ControlHandShake |= SERIAL_DTR_CONTROL;
    shf->FlowReplace |= SERIAL_RTS_CONTROL;
#endif
#ifdef TIOCM_DTR
    if (stat & TIOCM_DTR)
#endif
        shf->ControlHandShake |= SERIAL_DTR_CONTROL;
#ifdef CRTSCTS
    if (port.c_cflag & CRTSCTS)
    {
        shf->FlowReplace |= SERIAL_RTS_CONTROL;
        shf->ControlHandShake |= SERIAL_CTS_HANDSHAKE;
    }
    else
#endif
    {
#ifdef TIOCM_RTS
        if (stat & TIOCM_RTS)
#endif
            shf->FlowReplace |= SERIAL_RTS_CONTROL;
    }
    if (port.c_iflag & IXOFF)
        shf->FlowReplace |= SERIAL_AUTO_RECEIVE;
    if (port.c_iflag & IXON)
        shf->FlowReplace |= SERIAL_AUTO_TRANSMIT;

    shf->XonLimit = 10;
    shf->XoffLimit = 10;
    return STATUS_SUCCESS;
}
Beispiel #8
0
static NTSTATUS set_special_chars(int fd, const SERIAL_CHARS* sc)
{
    struct termios port;
    
    if (tcgetattr(fd, &port) == -1)
    {
        ERR("tcgetattr error '%s'\n", strerror(errno));
        return FILE_GetNtStatus();
    }
    
    port.c_cc[VEOF  ] = sc->EofChar;
    /* FIXME: sc->ErrorChar is not supported */
    /* FIXME: sc->BreakChar is not supported */
    /* FIXME: sc->EventChar is not supported */
    port.c_cc[VSTART] = sc->XonChar;
    port.c_cc[VSTOP ] = sc->XoffChar;
    
    if (tcsetattr(fd, TCSANOW, &port) == -1)
    {
        ERR("tcsetattr error '%s'\n", strerror(errno));
        return FILE_GetNtStatus();
    }
    return STATUS_SUCCESS;
}
Beispiel #9
0
/***********************************************************************
 *   Get extended interrupt count info, needed for wait_on
 */
static NTSTATUS get_irq_info(int fd, serial_irq_info *irq_info)
{
    int out;

#if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCGICOUNT)
    struct serial_icounter_struct einfo;
    if (!ioctl(fd, TIOCGICOUNT, &einfo))
    {
        irq_info->rx          = einfo.rx;
        irq_info->tx          = einfo.tx;
        irq_info->frame       = einfo.frame;
        irq_info->overrun     = einfo.overrun;
        irq_info->parity      = einfo.parity;
        irq_info->brk         = einfo.brk;
        irq_info->buf_overrun = einfo.buf_overrun;
    }
    else
    {
        TRACE("TIOCGICOUNT err %s\n", strerror(errno));
        memset(irq_info,0, sizeof(serial_irq_info));
    }
#else
    memset(irq_info,0, sizeof(serial_irq_info));
#endif

    irq_info->temt = 0;
    /* Generate a single TX_TXEMPTY event when the TX Buffer turns empty*/
#ifdef TIOCSERGETLSR  /* prefer to log the state TIOCSERGETLSR */
    if (!ioctl(fd, TIOCSERGETLSR, &out))
    {
        irq_info->temt = (out & TIOCSER_TEMT) != 0;
        return STATUS_SUCCESS;
    }

    TRACE("TIOCSERGETLSR err %s\n", strerror(errno));
#endif
#ifdef TIOCOUTQ  /* otherwise we log when the out queue gets empty */
    if (!ioctl(fd, TIOCOUTQ, &out))
    {
        irq_info->temt = out == 0;
        return STATUS_SUCCESS;
    }
    TRACE("TIOCOUTQ err %s\n", strerror(errno));
    return FILE_GetNtStatus();
#endif
    return STATUS_SUCCESS;
}
Beispiel #10
0
static NTSTATUS get_line_control(int fd, SERIAL_LINE_CONTROL* slc)
{
    struct termios port;
    
    if (tcgetattr(fd, &port) == -1)
    {
        ERR("tcgetattr error '%s'\n", strerror(errno));
        return FILE_GetNtStatus();
    }
    
#ifdef CMSPAR
    switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
#else
    switch (port.c_cflag & (PARENB | PARODD))
#endif
    {
    case 0:                     slc->Parity = NOPARITY;         break;
    case PARENB:                slc->Parity = EVENPARITY;       break;
    case PARENB|PARODD:         slc->Parity = ODDPARITY;        break;
#ifdef CMSPAR
    case PARENB|CMSPAR:         slc->Parity = MARKPARITY;       break;
    case PARENB|PARODD|CMSPAR:  slc->Parity = SPACEPARITY;      break;
        break;
#endif
    }
    switch (port.c_cflag & CSIZE)
    {
    case CS5:   slc->WordLength = 5;    break;
    case CS6:   slc->WordLength = 6;    break;
    case CS7:   slc->WordLength = 7;	break;
    case CS8:	slc->WordLength = 8;	break;
    default: ERR("unknown size %x\n", (UINT)(port.c_cflag & CSIZE));
    }
    
    if (port.c_cflag & CSTOPB)
    {
        if (slc->WordLength == 5)
            slc->StopBits = ONE5STOPBITS;
        else
            slc->StopBits = TWOSTOPBITS;
    }
    else
        slc->StopBits = ONESTOPBIT;

    return STATUS_SUCCESS;
}
Beispiel #11
0
static NTSTATUS get_special_chars(int fd, SERIAL_CHARS* sc)
{
    struct termios port;
    
    if (tcgetattr(fd, &port) == -1)
    {
        ERR("tcgetattr error '%s'\n", strerror(errno));
        return FILE_GetNtStatus();
    }
    sc->EofChar   = port.c_cc[VEOF];
    sc->ErrorChar = 0xFF;
    sc->BreakChar = 0; /* FIXME */
    sc->EventChar = 0; /* FIXME */
    sc->XonChar   = port.c_cc[VSTART];
    sc->XoffChar  = port.c_cc[VSTOP];

    return STATUS_SUCCESS;
}
Beispiel #12
0
/***********************************************************************
 *   Get extended interrupt count info, needed for wait_on
 */
static NTSTATUS get_irq_info(int fd, serial_irq_info *irq_info)
{
    NTSTATUS status = STATUS_NOT_IMPLEMENTED;
#ifdef TIOCGICOUNT
    struct serial_icounter_struct einfo;
    if (!ioctl(fd, TIOCGICOUNT, &einfo))
    {
        irq_info->rx          = einfo.rx;
        irq_info->tx          = einfo.tx;
        irq_info->frame       = einfo.frame;
        irq_info->overrun     = einfo.overrun;
        irq_info->parity      = einfo.parity;
        irq_info->brk         = einfo.brk;
        irq_info->buf_overrun = einfo.buf_overrun;
        return STATUS_SUCCESS;
    }
    TRACE("TIOCGICOUNT err %s\n", strerror(errno));
    status = FILE_GetNtStatus();
#endif
    memset(irq_info,0, sizeof(serial_irq_info));
    return status;
}
Beispiel #13
0
static NTSTATUS get_modem_status(int fd, DWORD* lpModemStat)
{
    NTSTATUS    status = STATUS_SUCCESS;
    int         mstat;

#ifdef TIOCMGET
    if (ioctl(fd, TIOCMGET, &mstat) == -1)
    {
        WARN("ioctl failed\n");
        status = FILE_GetNtStatus();
    }
    else
    {
        *lpModemStat = 0;
#ifdef TIOCM_CTS
        if (mstat & TIOCM_CTS)  *lpModemStat |= MS_CTS_ON;
#endif
#ifdef TIOCM_DSR
        if (mstat & TIOCM_DSR)  *lpModemStat |= MS_DSR_ON;
#endif
#ifdef TIOCM_RNG
        if (mstat & TIOCM_RNG)  *lpModemStat |= MS_RING_ON;
#endif
#ifdef TIOCM_CAR
        /* FIXME: Not really sure about RLSD UB 990810 */
        if (mstat & TIOCM_CAR)  *lpModemStat |= MS_RLSD_ON;
#endif
        TRACE("%04x -> %s%s%s%s\n", mstat,
              (*lpModemStat & MS_RLSD_ON) ? "MS_RLSD_ON " : "",
              (*lpModemStat & MS_RING_ON) ? "MS_RING_ON " : "",
              (*lpModemStat & MS_DSR_ON)  ? "MS_DSR_ON  " : "",
              (*lpModemStat & MS_CTS_ON)  ? "MS_CTS_ON  " : "");
    }
#else
    status = STATUS_NOT_SUPPORTED;
#endif
    return status;
}
Beispiel #14
0
static NTSTATUS set_line_control(int fd, const SERIAL_LINE_CONTROL* slc)
{
    struct termios port;
    unsigned bytesize, stopbits;

    if (tcgetattr(fd, &port) == -1)
    {
        ERR("tcgetattr error '%s'\n", strerror(errno));
        return FILE_GetNtStatus();
    }

#ifdef IMAXBEL
    port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|PARMRK|IMAXBEL);
#else
    port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|PARMRK);
#endif
    port.c_iflag |= IGNBRK | INPCK;
    port.c_oflag &= ~(OPOST);
    port.c_cflag &= ~(HUPCL);
    port.c_cflag |= CLOCAL | CREAD;

    /*
     * on FreeBSD, turning off ICANON does not disable IEXTEN,
     * so we must turn it off explicitly. No harm done on Linux.
     */
    port.c_lflag &= ~(ICANON|ECHO|ISIG|IEXTEN);
    port.c_lflag |= NOFLSH;

    bytesize = slc->WordLength;
    stopbits = slc->StopBits;

#ifdef CMSPAR
    port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
#else
    port.c_cflag &= ~(PARENB | PARODD);
#endif

    /* make sure that reads don't block */
    port.c_cc[VMIN] = 0;
    port.c_cc[VTIME] = 0;

    switch (slc->Parity)
    {
    case NOPARITY:      port.c_iflag &= ~INPCK;                         break;
    case ODDPARITY:     port.c_cflag |= PARENB | PARODD;                break;
    case EVENPARITY:    port.c_cflag |= PARENB;                         break;
#ifdef CMSPAR
        /* Linux defines mark/space (stick) parity */
    case MARKPARITY:    port.c_cflag |= PARENB | CMSPAR;                break;
    case SPACEPARITY:   port.c_cflag |= PARENB | PARODD |  CMSPAR;      break;
#else
        /* try the POSIX way */
    case MARKPARITY:
        if (slc->StopBits == ONESTOPBIT)
        {
            stopbits = TWOSTOPBITS;
            port.c_iflag &= ~INPCK;
        }
        else
        {
            FIXME("Cannot set MARK Parity\n");
            return STATUS_NOT_SUPPORTED;
        }
        break;
    case SPACEPARITY:
        if (slc->WordLength < 8)
        {
            bytesize +=1;
            port.c_iflag &= ~INPCK;
        }
        else
        {
            FIXME("Cannot set SPACE Parity\n");
            return STATUS_NOT_SUPPORTED;
        }
        break;
#endif
    default:
        FIXME("Parity %d is not supported\n", slc->Parity);
        return STATUS_NOT_SUPPORTED;
    }

    port.c_cflag &= ~CSIZE;
    switch (bytesize)
    {
    case 5:     port.c_cflag |= CS5;    break;
    case 6:     port.c_cflag |= CS6;    break;
    case 7:	port.c_cflag |= CS7;	break;
    case 8:	port.c_cflag |= CS8;	break;
    default:
        FIXME("ByteSize %d is not supported\n", bytesize);
        return STATUS_NOT_SUPPORTED;
    }

    switch (stopbits)
    {
    case ONESTOPBIT:    port.c_cflag &= ~CSTOPB;        break;
    case ONE5STOPBITS: /* will be selected if bytesize is 5 */
    case TWOSTOPBITS:	port.c_cflag |= CSTOPB;		break;
    default:
        FIXME("StopBits %d is not supported\n", stopbits);
        return STATUS_NOT_SUPPORTED;
    }
    /* otherwise it hangs with pending input*/
    if (tcsetattr(fd, TCSANOW, &port) == -1)
    {
        ERR("tcsetattr error '%s'\n", strerror(errno));
        return FILE_GetNtStatus();
    }
    return STATUS_SUCCESS;
}
Beispiel #15
0
static NTSTATUS set_baud_rate(int fd, const SERIAL_BAUD_RATE* sbr)
{
    struct termios port;

    if (tcgetattr(fd, &port) == -1)
    {
        ERR("tcgetattr error '%s'\n", strerror(errno));
        return FILE_GetNtStatus();
    }

    switch (sbr->BaudRate)
    {
    case 0:         cfsetospeed( &port, B0 ); break;
    case 50:        cfsetospeed( &port, B50 ); break;
    case 75:        cfsetospeed( &port, B75 ); break;
    case 110:
    case CBR_110:   cfsetospeed( &port, B110 ); break;
    case 134:       cfsetospeed( &port, B134 ); break;
    case 150:       cfsetospeed( &port, B150 ); break;
    case 200:       cfsetospeed( &port, B200 ); break;
    case 300:
    case CBR_300:   cfsetospeed( &port, B300 ); break;
    case 600:
    case CBR_600:   cfsetospeed( &port, B600 ); break;
    case 1200:
    case CBR_1200:  cfsetospeed( &port, B1200 ); break;
    case 1800:      cfsetospeed( &port, B1800 ); break;
    case 2400:
    case CBR_2400:  cfsetospeed( &port, B2400 ); break;
    case 4800:
    case CBR_4800:  cfsetospeed( &port, B4800 ); break;
    case 9600:
    case CBR_9600:  cfsetospeed( &port, B9600 ); break;
    case 19200:
    case CBR_19200: cfsetospeed( &port, B19200 ); break;
    case 38400:
    case CBR_38400: cfsetospeed( &port, B38400 ); break;
#ifdef B57600
    case 57600: cfsetospeed( &port, B57600 ); break;
#endif
#ifdef B115200
    case 115200: cfsetospeed( &port, B115200 ); break;
#endif
#ifdef B230400
    case 230400: cfsetospeed( &port, B230400 ); break;
#endif
#ifdef B460800
    case 460800: cfsetospeed( &port, B460800 ); break;
#endif
#ifdef B500000
    case 500000: cfsetospeed( &port, B500000 ); break;
#endif
#ifdef B921600
    case 921600: cfsetospeed( &port, B921600 ); break;
#endif
#ifdef B1000000
    case 1000000: cfsetospeed( &port, B1000000 ); break;
#endif
#ifdef B1152000
    case 1152000: cfsetospeed( &port, B1152000 ); break;
#endif
#ifdef B1500000
    case 1500000: cfsetospeed( &port, B1500000 ); break;
#endif
#ifdef B2000000
    case 2000000: cfsetospeed( &port, B2000000 ); break;
#endif
#ifdef B2500000
    case 2500000: cfsetospeed( &port, B2500000 ); break;
#endif
#ifdef B3000000
    case 3000000: cfsetospeed( &port, B3000000 ); break;
#endif
#ifdef B3500000
    case 3500000: cfsetospeed( &port, B3500000 ); break;
#endif
#ifdef B4000000
    case 4000000: cfsetospeed( &port, B4000000 ); break;
#endif
    default:
#if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
        {
            struct serial_struct nuts;
            int arby;
	
            ioctl(fd, TIOCGSERIAL, &nuts);
            nuts.custom_divisor = nuts.baud_base / sbr->BaudRate;
            if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
            arby = nuts.baud_base / nuts.custom_divisor;
            nuts.flags &= ~ASYNC_SPD_MASK;
            nuts.flags |= ASYNC_SPD_CUST;
            WARN("You (or a program acting at your behest) have specified\n"
                 "a non-standard baud rate %d.  Wine will set the rate to %d,\n"
                 "which is as close as we can get by our present understanding of your\n"
                 "hardware. I hope you know what you are doing.  Any disruption Wine\n"
                 "has caused to your linux system can be undone with setserial\n"
                 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
                 "reset it and it will probably recover.\n", sbr->BaudRate, arby);
            ioctl(fd, TIOCSSERIAL, &nuts);
            cfsetospeed( &port, B38400 );
        }
        break;
#else     /* Don't have linux/serial.h or lack TIOCSSERIAL */
        ERR("baudrate %d\n", sbr->BaudRate);
        return STATUS_NOT_SUPPORTED;
#endif    /* Don't have linux/serial.h or lack TIOCSSERIAL */
    }
    cfsetispeed( &port, cfgetospeed(&port) );
    if (tcsetattr(fd, TCSANOW, &port) == -1)
    {
        ERR("tcsetattr error '%s'\n", strerror(errno));
        return FILE_GetNtStatus();
    }
    return STATUS_SUCCESS;
}
Beispiel #16
0
/******************************************************************
 *		COMM_DeviceIoControl
 *
 *
 */
NTSTATUS COMM_DeviceIoControl(HANDLE hDevice, 
                              HANDLE hEvent, PIO_APC_ROUTINE UserApcRoutine,
                              PVOID UserApcContext, 
                              PIO_STATUS_BLOCK piosb, 
                              ULONG dwIoControlCode,
                              LPVOID lpInBuffer, DWORD nInBufferSize,
                              LPVOID lpOutBuffer, DWORD nOutBufferSize)
{
    DWORD       sz = 0, access = FILE_READ_DATA;
    NTSTATUS    status = STATUS_SUCCESS;
    int         fd = -1;

    TRACE("%p %s %p %ld %p %ld %p\n",
          hDevice, iocode2str(dwIoControlCode), lpInBuffer, nInBufferSize,
          lpOutBuffer, nOutBufferSize, piosb);

    piosb->Information = 0;

    if (dwIoControlCode != IOCTL_SERIAL_GET_TIMEOUTS)
        if ((status = wine_server_handle_to_fd( hDevice, access, &fd, NULL )))
            goto error;

    switch (dwIoControlCode)
    {
    case IOCTL_SERIAL_CLR_DTR:
#ifdef TIOCM_DTR
        if (whack_modem(fd, ~TIOCM_DTR, 0) == -1) status = FILE_GetNtStatus();
#else
        status = STATUS_NOT_SUPPORTED;
#endif
        break;
    case IOCTL_SERIAL_CLR_RTS:
#ifdef TIOCM_RTS
        if (whack_modem(fd, ~TIOCM_RTS, 0) == -1) status = FILE_GetNtStatus();
#else
        status = STATUS_NOT_SUPPORTED;
#endif
        break;
    case IOCTL_SERIAL_GET_BAUD_RATE:
        if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_BAUD_RATE))
        {
            if (!(status = get_baud_rate(fd, (SERIAL_BAUD_RATE*)lpOutBuffer)))
                sz = sizeof(SERIAL_BAUD_RATE);
        }
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_GET_CHARS:
        if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_CHARS))
        {
            if (!(status = get_special_chars(fd, (SERIAL_CHARS*)lpOutBuffer)))
                sz = sizeof(SERIAL_CHARS);
        }
        else
            status = STATUS_INVALID_PARAMETER;
        break;
     case IOCTL_SERIAL_GET_COMMSTATUS:
        if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_STATUS))
        {
            if (!(status = get_status(fd, (SERIAL_STATUS*)lpOutBuffer)))
                sz = sizeof(SERIAL_STATUS);
        }
        else status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_GET_HANDFLOW:
        if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_HANDFLOW))
        {
            if (!(status = get_hand_flow(fd, (SERIAL_HANDFLOW*)lpOutBuffer)))
                sz = sizeof(SERIAL_HANDFLOW);
        }
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_GET_LINE_CONTROL:
        if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_LINE_CONTROL))
        {
            if (!(status = get_line_control(fd, (SERIAL_LINE_CONTROL*)lpOutBuffer)))
                sz = sizeof(SERIAL_LINE_CONTROL);
        }
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_GET_MODEMSTATUS:
        if (lpOutBuffer && nOutBufferSize == sizeof(DWORD))
        {
            if (!(status = get_modem_status(fd, (DWORD*)lpOutBuffer)))
                sz = sizeof(DWORD);
        }
        else status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_GET_TIMEOUTS:
        if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_TIMEOUTS))
        {
            if (!(status = get_timeouts(hDevice, (SERIAL_TIMEOUTS*)lpOutBuffer)))
                sz = sizeof(SERIAL_TIMEOUTS);
        }
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_GET_WAIT_MASK:
        if (lpOutBuffer && nOutBufferSize == sizeof(DWORD))
        {
            if (!(status = get_wait_mask(hDevice, (DWORD*)lpOutBuffer)))
                sz = sizeof(DWORD);
        }
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_IMMEDIATE_CHAR:
        if (lpInBuffer && nInBufferSize == sizeof(CHAR))
            status = xmit_immediate(hDevice, fd, lpInBuffer);
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_PURGE:
        if (lpInBuffer && nInBufferSize == sizeof(DWORD))
            status = purge(fd, *(DWORD*)lpInBuffer);
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_RESET_DEVICE:
        FIXME("Unsupported\n");
        break;
    case IOCTL_SERIAL_SET_BAUD_RATE:
        if (lpInBuffer && nInBufferSize == sizeof(SERIAL_BAUD_RATE))
            status = set_baud_rate(fd, (const SERIAL_BAUD_RATE*)lpInBuffer);
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_SET_BREAK_OFF:
#if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
	if (ioctl(fd, TIOCCBRK, 0) == -1)
        {
            TRACE("ioctl failed\n");
            status = FILE_GetNtStatus();
        }
#else
	FIXME("ioctl not available\n");
	status = STATUS_NOT_SUPPORTED;
#endif
        break;
    case IOCTL_SERIAL_SET_BREAK_ON:
#if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
	if (ioctl(fd, TIOCSBRK, 0) == -1)
        {
            TRACE("ioctl failed\n");
            status = FILE_GetNtStatus();
        }
#else
	FIXME("ioctl not available\n");
	status = STATUS_NOT_SUPPORTED;
#endif
        break;
    case IOCTL_SERIAL_SET_CHARS:
        if (lpInBuffer && nInBufferSize == sizeof(SERIAL_CHARS))
            status = set_special_chars(fd, (const SERIAL_CHARS*)lpInBuffer);
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_SET_DTR:
#ifdef TIOCM_DTR
        if (whack_modem(fd, 0, TIOCM_DTR) == -1) status = FILE_GetNtStatus();
#else
        status = STATUS_NOT_SUPPORTED;
#endif
        break;
    case IOCTL_SERIAL_SET_HANDFLOW:
        if (lpInBuffer && nInBufferSize == sizeof(SERIAL_HANDFLOW))
            status = set_handflow(fd, (const SERIAL_HANDFLOW*)lpInBuffer);
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_SET_LINE_CONTROL:
        if (lpInBuffer && nInBufferSize == sizeof(SERIAL_LINE_CONTROL))
            status = set_line_control(fd, (const SERIAL_LINE_CONTROL*)lpInBuffer);
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_SET_QUEUE_SIZE:
        if (lpInBuffer && nInBufferSize == sizeof(SERIAL_QUEUE_SIZE))
            status = set_queue_size(fd, (const SERIAL_QUEUE_SIZE*)lpInBuffer);
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_SET_RTS:
#ifdef TIOCM_RTS
        if (whack_modem(fd, 0, TIOCM_RTS) == -1) status = FILE_GetNtStatus();
#else
        status = STATUS_NOT_SUPPORTED;
#endif
        break;
    case IOCTL_SERIAL_SET_TIMEOUTS:
        if (lpInBuffer && nInBufferSize == sizeof(SERIAL_TIMEOUTS))
            status = set_timeouts(hDevice, fd, (const SERIAL_TIMEOUTS*)lpInBuffer);
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_SET_WAIT_MASK:
        if (lpInBuffer && nInBufferSize == sizeof(DWORD))
        {
            status = set_wait_mask(hDevice, *(DWORD*)lpInBuffer);
        }
        else status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_SET_XOFF:
        status = set_XOff(fd);
        break;
    case IOCTL_SERIAL_SET_XON:
        status = set_XOn(fd);
        break;
    default:
        FIXME("Unsupported IOCTL %lx (type=%lx access=%lx func=%lx meth=%lx)\n", 
              dwIoControlCode, dwIoControlCode >> 16, (dwIoControlCode >> 14) & 3,
              (dwIoControlCode >> 2) & 0xFFF, dwIoControlCode & 3);
        sz = 0;
        status = STATUS_INVALID_PARAMETER;
        break;
    }
    if (fd != -1) wine_server_release_fd( hDevice, fd );
 error:
    piosb->u.Status = status;
    piosb->Information = sz;
    if (hEvent) NtSetEvent(hEvent, NULL);
    return status;
}
Beispiel #17
0
static inline NTSTATUS TAPE_GetStatus( int error )
{
    if (!error) return STATUS_SUCCESS;
    return FILE_GetNtStatus();
}
Beispiel #18
0
/******************************************************************
 *		TAPE_DeviceIoControl
 *
 * SEE ALSO
 *   NtDeviceIoControl.
 */
NTSTATUS TAPE_DeviceIoControl( HANDLE device, HANDLE event,
    PIO_APC_ROUTINE apc, PVOID apc_user, PIO_STATUS_BLOCK io_status,
    ULONG io_control, LPVOID in_buffer, DWORD in_size,
    LPVOID out_buffer, DWORD out_size )
{
    DWORD sz = 0;
    NTSTATUS status = STATUS_INVALID_PARAMETER;
    int fd, needs_close;

    TRACE( "%p %s %p %d %p %d %p\n", device, io2str(io_control),
           in_buffer, in_size, out_buffer, out_size, io_status );

    io_status->Information = 0;

    if ((status = server_get_unix_fd( device, 0, &fd, &needs_close, NULL, NULL )))
        goto error;

    switch (io_control)
    {
    case IOCTL_TAPE_CREATE_PARTITION:
        status = TAPE_CreatePartition( fd, in_buffer );
        break;
    case IOCTL_TAPE_ERASE:
        status = TAPE_Erase( fd, in_buffer );
        break;
    case IOCTL_TAPE_GET_DRIVE_PARAMS:
        status = TAPE_GetDriveParams( fd, out_buffer );
        break;
    case IOCTL_TAPE_GET_MEDIA_PARAMS:
        status = TAPE_GetMediaParams( fd, out_buffer );
        break;
    case IOCTL_TAPE_GET_POSITION:
        status = TAPE_GetPosition( fd, ((TAPE_GET_POSITION *)in_buffer)->Type,
                                   out_buffer );
        break;
    case IOCTL_TAPE_GET_STATUS:
        status = FILE_GetNtStatus();
        break;
    case IOCTL_TAPE_PREPARE:
        status = TAPE_Prepare( fd, in_buffer );
        break;
    case IOCTL_TAPE_SET_DRIVE_PARAMS:
        status = TAPE_SetDriveParams( fd, in_buffer );
        break;
    case IOCTL_TAPE_SET_MEDIA_PARAMS:
        status = TAPE_SetMediaParams( fd, in_buffer );
        break;
    case IOCTL_TAPE_SET_POSITION:
        status = TAPE_SetPosition( fd, in_buffer );
        break;
    case IOCTL_TAPE_WRITE_MARKS:
        status = TAPE_WriteMarks( fd, in_buffer );
        break;

    case IOCTL_TAPE_CHECK_VERIFY:
    case IOCTL_TAPE_FIND_NEW_DEVICES:
        break;
    default:
        FIXME( "Unsupported IOCTL %x (type=%x access=%x func=%x meth=%x)\n",
               io_control, io_control >> 16, (io_control >> 14) & 3,
               (io_control >> 2) & 0xfff, io_control & 3 );
        break;
    }

    if (needs_close) close( fd );

error:
    io_status->u.Status = status;
    io_status->Information = sz;
    if (event) NtSetEvent( event, NULL );
    return status;
}