[PATCH 09/11] [NtDll/Kernel32]: [SG]etCommTimeout,
SERIAL_[GS]ET_TIMEOUT
Eric Pouech
eric.pouech at wanadoo.fr
Sun May 7 07:10:58 CDT 2006
- implemented ntdll's COMM IOCTL GET_TIMEOUTS,
SET_TIMEOUTS
- implemented kernel32!GetCommTimeout and SetCommTimeout on top of them
A+
---
dlls/kernel/comm.c | 114 +++++++++++++++------------------------------------
dlls/ntdll/serial.c | 87 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 117 insertions(+), 84 deletions(-)
diff --git a/dlls/kernel/comm.c b/dlls/kernel/comm.c
index 7d8e6da..f12043d 100644
--- a/dlls/kernel/comm.c
+++ b/dlls/kernel/comm.c
@@ -1180,39 +1180,34 @@ BOOL WINAPI TransmitCommChar(HANDLE hCom
*
* 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;
+ SERIAL_TIMEOUTS st;
- TRACE("(%p,%p)\n",hComm,lptimeouts);
-
- 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);
}
/***********************************************************************
diff --git a/dlls/ntdll/serial.c b/dlls/ntdll/serial.c
index 9b56c6b..1b45a10 100644
--- a/dlls/ntdll/serial.c
+++ b/dlls/ntdll/serial.c
@@ -368,6 +368,25 @@ static NTSTATUS get_status(int fd, SERIA
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
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 hDe
{
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 hDe
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 hDe
}
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 hDe
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 hDe
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;
More information about the wine-patches
mailing list