winpr-comm: got IOCTL_SERIAL_SET_QUEUE_SIZE

This commit is contained in:
Emmanuel Ledoux 2014-05-14 17:30:29 +02:00 committed by Emmanuel Ledoux
parent 4243928c2e
commit 6cc44ff112
8 changed files with 95 additions and 24 deletions

View File

@ -376,7 +376,7 @@ static void serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
DEBUG_SVC("CommDeviceIoControl failure: IoControlCode=[0x%0.8x] %s, last-error: 0x%x",
IoControlCode, _comm_serial_ioctl_name(IoControlCode), GetLastError());
// TMP: TODO: Status code to be reviewed according: http://msdn.microsoft.com/en-us/library/ff547466%28v=vs.85%29.aspx#generic_status_values_for_serial_device_control_requests
// TMP: TODO: Status codes to be reviewed according: http://msdn.microsoft.com/en-us/library/ff547466%28v=vs.85%29.aspx#generic_status_values_for_serial_device_control_requests
switch(GetLastError())
{

View File

@ -421,7 +421,7 @@ WINPR_API HANDLE CommCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD
/* IOCTL_SERIAL_SET_XON 0x001B003C */
/* IOCTL_SERIAL_SET_BREAK_ON 0x001B0010 */
/* IOCTL_SERIAL_SET_BREAK_OFF 0x001B0014 */
/* IOCTL_SERIAL_SET_QUEUE_SIZE 0x001B0008 */
#define IOCTL_SERIAL_SET_QUEUE_SIZE 0x001B0008
#define IOCTL_SERIAL_GET_WAIT_MASK 0x001B0040
#define IOCTL_SERIAL_SET_WAIT_MASK 0x001B0044
#define IOCTL_SERIAL_WAIT_ON_MASK 0x001B0048
@ -481,7 +481,7 @@ static const _SERIAL_IOCTL_NAME _SERIAL_IOCTL_NAMES[] =
// {IOCTL_SERIAL_SET_XON, "IOCTL_SERIAL_SET_XON"},
// {IOCTL_SERIAL_SET_BREAK_ON, "IOCTL_SERIAL_SET_BREAK_ON"},
// {IOCTL_SERIAL_SET_BREAK_OFF, "IOCTL_SERIAL_SET_BREAK_OFF"},
// {IOCTL_SERIAL_SET_QUEUE_SIZE, "IOCTL_SERIAL_SET_QUEUE_SIZE"},
{IOCTL_SERIAL_SET_QUEUE_SIZE, "IOCTL_SERIAL_SET_QUEUE_SIZE"},
{IOCTL_SERIAL_GET_WAIT_MASK, "IOCTL_SERIAL_GET_WAIT_MASK"},
{IOCTL_SERIAL_SET_WAIT_MASK, "IOCTL_SERIAL_SET_WAIT_MASK"},
{IOCTL_SERIAL_WAIT_ON_MASK, "IOCTL_SERIAL_WAIT_ON_MASK"},

View File

@ -679,18 +679,23 @@ BOOL PurgeComm(HANDLE hFile, DWORD dwFlags)
BOOL SetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue)
{
WINPR_COMM* pComm = (WINPR_COMM*) hFile;
SERIAL_QUEUE_SIZE queueSize;
DWORD bytesReturned = 0;
if (!pComm)
if (!pComm || pComm->Type != HANDLE_TYPE_COMM || !pComm->fd )
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa363423%28v=vs.85%29.aspx */
/* A process reinitializes a communications resource by using the SetupComm function, which performs the following tasks: */
queueSize.InSize = dwInQueue;
queueSize.OutSize = dwOutQueue;
/* Terminates pending read and write operations, even if they have not been completed. */
/* Discards unread characters and frees the internal output and input buffers of the driver associated with the specified resource. */
/* Reallocates the internal output and input buffers. */
/* A process is not required to call SetupComm. If it does not, the resource's driver initializes the device with the default settings the first time that the communications resource handle is used. */
if (!CommDeviceIoControl(pComm, IOCTL_SERIAL_SET_QUEUE_SIZE, &queueSize, sizeof(SERIAL_QUEUE_SIZE), NULL, 0, &bytesReturned, NULL))
{
DEBUG_WARN("SetCommTimeouts failure.");
return FALSE;
}
return TRUE;
}

View File

@ -474,6 +474,24 @@ BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffe
}
break;
}
case IOCTL_SERIAL_SET_QUEUE_SIZE:
{
if (pRemoteSerialDriver->set_queue_size)
{
SERIAL_QUEUE_SIZE *pQueueSize = (SERIAL_QUEUE_SIZE*)lpInBuffer;
assert(nInBufferSize >= sizeof(SERIAL_QUEUE_SIZE));
if (nInBufferSize < sizeof(SERIAL_QUEUE_SIZE))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pRemoteSerialDriver->set_queue_size(pComm, pQueueSize);
}
break;
}
}
DEBUG_WARN(_T("unsupported IoControlCode=[Ox%0.8x] %s (remote serial driver: %s)"),

View File

@ -161,6 +161,14 @@ typedef struct _SERIAL_TIMEOUTS
#define SERIAL_EV_EVENT1 0x0800
#define SERIAL_EV_EVENT2 0x1000
typedef struct _SERIAL_QUEUE_SIZE
{
ULONG InSize;
ULONG OutSize;
} SERIAL_QUEUE_SIZE, *PSERIAL_QUEUE_SIZE;
/**
* A function might be NULL if not supported by the underlying remote driver.
*
@ -189,6 +197,7 @@ typedef struct _REMOTE_SERIAL_DRIVER
BOOL (*set_wait_mask)(WINPR_COMM *pComm, const ULONG *pWaitMask);
BOOL (*get_wait_mask)(WINPR_COMM *pComm, ULONG *pWaitMask);
BOOL (*wait_on_mask)(WINPR_COMM *pComm, ULONG *pOutputMask);
BOOL (*set_queue_size)(WINPR_COMM *pComm, const SERIAL_QUEUE_SIZE *pQueueSize);
} REMOTE_SERIAL_DRIVER;

View File

@ -117,6 +117,7 @@ static REMOTE_SERIAL_DRIVER _SerCx2Sys =
.set_wait_mask = _set_wait_mask,
.get_wait_mask = NULL,
.wait_on_mask = NULL,
.set_queue_size = NULL,
};
@ -155,6 +156,8 @@ REMOTE_SERIAL_DRIVER* SerCx2Sys_s()
_SerCx2Sys.get_wait_mask = pSerialSys->get_wait_mask;
_SerCx2Sys.wait_on_mask = pSerialSys->wait_on_mask;
_SerCx2Sys.set_queue_size = pSerialSys->set_queue_size;
return &_SerCx2Sys;
}

View File

@ -554,6 +554,7 @@ static REMOTE_SERIAL_DRIVER _SerCxSys =
.set_wait_mask = _set_wait_mask,
.get_wait_mask = NULL,
.wait_on_mask = NULL,
.set_queue_size = NULL,
};
@ -583,6 +584,8 @@ REMOTE_SERIAL_DRIVER* SerCxSys_s()
_SerCxSys.get_wait_mask = pSerialSys->get_wait_mask;
_SerCxSys.wait_on_mask = pSerialSys->wait_on_mask;
_SerCxSys.set_queue_size = pSerialSys->set_queue_size;
return &_SerCxSys;
}

View File

@ -33,6 +33,13 @@
#include <winpr/crt.h>
/* hard-coded in N_TTY */
#define TTY_THRESHOLD_THROTTLE 128 /* now based on remaining room */
#define TTY_THRESHOLD_UNTHROTTLE 128
#define N_TTY_BUF_SIZE 4096
/*
* Linux, Windows speeds
*
@ -150,7 +157,7 @@ static BOOL _get_properties(WINPR_COMM *pComm, COMMPROP *pProperties)
* http://msdn.microsoft.com/en-us/library/windows/desktop/aa363189%28v=vs.85%29.aspx
*/
/* FIXME: properties should be better probe. The current
/* FIXME: properties should be better probed. The current
* implementation just relies on the Linux' implementation.
*/
@ -169,9 +176,9 @@ static BOOL _get_properties(WINPR_COMM *pComm, COMMPROP *pProperties)
/* pProperties->Reserved1; not used */
// TMP: FIXME: related to the UART's FIFO ?
/* pProperties->MaxTxQueue; */
/* pProperties->MaxRxQueue; */
/* FIXME: could be implemented on top of N_TTY */
pProperties->dwMaxTxQueue = N_TTY_BUF_SIZE;
pProperties->dwMaxRxQueue = N_TTY_BUF_SIZE;
pProperties->dwMaxBaud = SERIAL_BAUD_115200; /* _SERIAL_MAX_BAUD */
@ -180,7 +187,7 @@ static BOOL _get_properties(WINPR_COMM *pComm, COMMPROP *pProperties)
/* TMP: TODO: to be finalized */
pProperties->dwProvCapabilities =
/*PCF_16BITMODE | PCF_DTRDSR | PCF_INTTIMEOUTS |*/ PCF_PARITY_CHECK | /*PCF_RLSD | */
/*PCF_16BITMODE | PCF_DTRDSR |*/ PCF_INTTIMEOUTS | PCF_PARITY_CHECK | /*PCF_RLSD | */
PCF_RTSCTS | PCF_SETXCHAR | /*PCF_SPECIALCHARS | PCF_TOTALTIMEOUTS |*/ PCF_XONXOFF;
/* TMP: TODO: double check SP_RLSD */
@ -196,9 +203,9 @@ static BOOL _get_properties(WINPR_COMM *pComm, COMMPROP *pProperties)
pProperties->wSettableStopParity = STOPBITS_10 | /*STOPBITS_15 |*/ STOPBITS_20 | PARITY_NONE | PARITY_ODD | PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
// TMP: FIXME: related to the UART's FIFO ?
/* pProperties->CurrentTxQueue; */
/* pProperties->CurrentRxQueue; */
/* FIXME: could be implemented on top of N_TTY */
pProperties->dwCurrentTxQueue = N_TTY_BUF_SIZE;
pProperties->dwCurrentRxQueue = N_TTY_BUF_SIZE;
/* pProperties->ProvSpec1; see above */
/* pProperties->ProvSpec2; ignored */
@ -558,11 +565,6 @@ static BOOL _get_line_control(WINPR_COMM *pComm, SERIAL_LINE_CONTROL *pLineContr
}
/* hard-coded in N_TTY */
#define TTY_THRESHOLD_THROTTLE 128 /* now based on remaining room */
#define TTY_THRESHOLD_UNTHROTTLE 128
#define N_TTY_BUF_SIZE 4096
static BOOL _set_handflow(WINPR_COMM *pComm, const SERIAL_HANDFLOW *pHandflow)
{
BOOL result = TRUE;
@ -1246,6 +1248,36 @@ static BOOL _wait_on_mask(WINPR_COMM *pComm, ULONG *pOutputMask)
}
static BOOL _set_queue_size(WINPR_COMM *pComm, const SERIAL_QUEUE_SIZE *pQueueSize)
{
/* TMP: FIXME: do at least a purge/reset ? */
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa363423%28v=vs.85%29.aspx */
/* A process reinitializes a communications resource by using the SetupComm function, which performs the following tasks: */
/* Terminates pending read and write operations, even if they have not been completed. */
/* Discards unread characters and frees the internal output and input buffers of the driver associated with the specified resource. */
/* Reallocates the internal output and input buffers. */
/* A process is not required to call SetupComm. If it does not, the resource's driver initializes the device with the default settings the first time that the communications resource handle is used. */
if ((pQueueSize->InSize <= N_TTY_BUF_SIZE) && (pQueueSize->OutSize <= N_TTY_BUF_SIZE))
return TRUE; /* nothing to do */
/* FIXME: could be implemented on top of N_TTY */
if (pQueueSize->InSize > N_TTY_BUF_SIZE)
DEBUG_WARN("Requested an incompatible input buffer size: %d", pQueueSize->InSize);
if (pQueueSize->OutSize > N_TTY_BUF_SIZE)
DEBUG_WARN("Requested an incompatible output buffer size: %d", pQueueSize->OutSize);
SetLastError(ERROR_CANCELLED);
return FALSE;
}
static REMOTE_SERIAL_DRIVER _SerialSys =
{
.id = RemoteSerialDriverSerialSys,
@ -1269,6 +1301,7 @@ static REMOTE_SERIAL_DRIVER _SerialSys =
.set_wait_mask = _set_wait_mask,
.get_wait_mask = _get_wait_mask,
.wait_on_mask = _wait_on_mask,
.set_queue_size = _set_queue_size,
};