Commit b53e0169 authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

ntdll/kernel32: [SG]etCommTimeout, SERIAL_[GS]ET_TIMEOUT

- implemented ntdll's COMM IOCTL GET_TIMEOUTS, SET_TIMEOUTS - implemented kernel32.GetCommTimeout and SetCommTimeout on top of them
parent 28cd4fae
......@@ -1180,39 +1180,34 @@ BOOL WINAPI TransmitCommChar(HANDLE hComm, CHAR chTransmit)
*
* Obtains the request timeout values for the communications device.
*
* PARAMS
* hComm [in] The communications device
* lptimeouts [out] The struct of request timeouts
*
* RETURNS
*
* True on success, false if communications device handle is bad
* or the target structure is null.
*/
BOOL WINAPI GetCommTimeouts(
HANDLE hComm, /* [in] The communications device. */
LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
BOOL WINAPI GetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts)
{
BOOL ret;
TRACE("(%p,%p)\n",hComm,lptimeouts);
SERIAL_TIMEOUTS st;
if(!lptimeouts)
TRACE("(%p, %p)\n", hComm, lptimeouts);
if (!lptimeouts)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
SERVER_START_REQ( get_serial_info )
{
req->handle = hComm;
if ((ret = !wine_server_call_err( req )))
{
lptimeouts->ReadIntervalTimeout = reply->readinterval;
lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
}
}
SERVER_END_REQ;
return ret;
if (!DeviceIoControl(hComm, IOCTL_SERIAL_GET_TIMEOUTS,
NULL, 0, &st, sizeof(st), NULL, NULL))
return FALSE;
lptimeouts->ReadIntervalTimeout = st.ReadIntervalTimeout;
lptimeouts->ReadTotalTimeoutMultiplier = st.ReadTotalTimeoutMultiplier;
lptimeouts->ReadTotalTimeoutConstant = st.ReadTotalTimeoutConstant;
lptimeouts->WriteTotalTimeoutMultiplier = st.WriteTotalTimeoutMultiplier;
lptimeouts->WriteTotalTimeoutConstant = st.WriteTotalTimeoutConstant;
return TRUE;
}
/*****************************************************************************
......@@ -1220,6 +1215,10 @@ BOOL WINAPI GetCommTimeouts(
*
* Sets the timeouts used when reading and writing data to/from COMM ports.
*
* PARAMS
* hComm [in] handle of COMM device
* lptimeouts [in] pointer to COMMTIMEOUTS structure
*
* ReadIntervalTimeout
* - converted and passes to linux kernel as c_cc[VTIME]
* ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
......@@ -1231,72 +1230,25 @@ BOOL WINAPI GetCommTimeouts(
*
* True if the timeouts were set, false otherwise.
*/
BOOL WINAPI SetCommTimeouts(
HANDLE hComm, /* [in] handle of COMM device */
LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
BOOL WINAPI SetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts)
{
BOOL ret;
int fd;
struct termios tios;
SERIAL_TIMEOUTS st;
TRACE("(%p,%p)\n",hComm,lptimeouts);
TRACE("(%p, %p)\n", hComm, lptimeouts);
if(!lptimeouts)
if (lptimeouts == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
SERVER_START_REQ( set_serial_info )
{
req->handle = hComm;
req->flags = SERIALINFO_SET_TIMEOUTS;
req->readinterval = lptimeouts->ReadIntervalTimeout ;
req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
ret = !wine_server_call_err( req );
}
SERVER_END_REQ;
if (!ret) return FALSE;
/* FIXME: move this stuff to the server */
fd = get_comm_fd( hComm, FILE_READ_DATA );
if (fd < 0) return FALSE;
if (-1==tcgetattr(fd,&tios)) {
FIXME("tcgetattr on fd %d failed!\n",fd);
release_comm_fd( hComm, fd );
return FALSE;
}
/* VTIME is in 1/10 seconds */
{
unsigned int ux_timeout;
if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
{
ux_timeout = 0;
}
else
{
ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
if(ux_timeout == 0)
{
ux_timeout = 1; /* must be at least some timeout */
}
}
tios.c_cc[VTIME] = ux_timeout;
}
if (-1==tcsetattr(fd,0,&tios)) {
FIXME("tcsetattr on fd %d failed!\n",fd);
release_comm_fd( hComm, fd );
return FALSE;
}
release_comm_fd( hComm, fd );
return TRUE;
st.ReadIntervalTimeout = lptimeouts->ReadIntervalTimeout;
st.ReadTotalTimeoutMultiplier = lptimeouts->ReadTotalTimeoutMultiplier;
st.ReadTotalTimeoutConstant = lptimeouts->ReadTotalTimeoutConstant;
st.WriteTotalTimeoutMultiplier = lptimeouts->WriteTotalTimeoutMultiplier;
st.WriteTotalTimeoutConstant = lptimeouts->WriteTotalTimeoutConstant;
return DeviceIoControl(hComm, IOCTL_SERIAL_SET_TIMEOUTS,
&st, sizeof(st), NULL, 0, NULL, NULL);
}
/***********************************************************************
......
......@@ -368,6 +368,25 @@ static NTSTATUS get_status(int fd, SERIAL_STATUS* ss)
return status;
}
static NTSTATUS get_timeouts(HANDLE handle, SERIAL_TIMEOUTS* st)
{
NTSTATUS status;
SERVER_START_REQ( get_serial_info )
{
req->handle = handle;
if (!(status = wine_server_call( req )))
{
st->ReadIntervalTimeout = reply->readinterval;
st->ReadTotalTimeoutMultiplier = reply->readmult;
st->ReadTotalTimeoutConstant = reply->readconst;
st->WriteTotalTimeoutMultiplier = reply->writemult;
st->WriteTotalTimeoutConstant = reply->writeconst;
}
}
SERVER_END_REQ;
return status;
}
static NTSTATUS get_wait_mask(HANDLE hDevice, DWORD* mask)
{
NTSTATUS status;
......@@ -738,6 +757,51 @@ static NTSTATUS set_special_chars(int fd, const SERIAL_CHARS* sc)
return STATUS_SUCCESS;
}
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;
}
static NTSTATUS set_wait_mask(HANDLE hDevice, DWORD mask)
{
NTSTATUS status;
......@@ -777,7 +841,7 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDevice,
{
DWORD sz = 0, access = FILE_READ_DATA;
NTSTATUS status = STATUS_SUCCESS;
int fd;
int fd = -1;
TRACE("%p %s %p %ld %p %ld %p\n",
hDevice, iocode2str(dwIoControlCode), lpInBuffer, nInBufferSize,
......@@ -785,7 +849,9 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDevice,
piosb->Information = 0;
if ((status = wine_server_handle_to_fd( hDevice, access, &fd, NULL ))) goto error;
if (dwIoControlCode != IOCTL_SERIAL_GET_TIMEOUTS)
if ((status = wine_server_handle_to_fd( hDevice, access, &fd, NULL )))
goto error;
switch (dwIoControlCode)
{
......@@ -841,6 +907,15 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDevice,
}
else status = STATUS_INVALID_PARAMETER;
break;
case IOCTL_SERIAL_GET_TIMEOUTS:
if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_TIMEOUTS))
{
if (!(status = get_timeouts(hDevice, (SERIAL_TIMEOUTS*)lpInBuffer)))
sz = sizeof(SERIAL_TIMEOUTS);
}
else
status = STATUS_INVALID_PARAMETER;
break;
case IOCTL_SERIAL_GET_WAIT_MASK:
if (lpOutBuffer && nOutBufferSize == sizeof(DWORD))
{
......@@ -910,6 +985,12 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDevice,
else
status = STATUS_INVALID_PARAMETER;
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))
{
......@@ -925,7 +1006,7 @@ NTSTATUS COMM_DeviceIoControl(HANDLE hDevice,
status = STATUS_INVALID_PARAMETER;
break;
}
wine_server_release_fd( hDevice, fd );
if (fd != -1) wine_server_release_fd( hDevice, fd );
error:
piosb->u.Status = status;
piosb->Information = sz;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment