mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 17:07:16 +00:00
server: Add support for pending write flag to the serial device.
This commit is contained in:
parent
53e727ef95
commit
3b429e88ff
|
@ -943,7 +943,6 @@ static void test_waittxempty(void)
|
||||||
|
|
||||||
res = WaitForSingleObject(ovl_wait.hEvent, TIMEOUT);
|
res = WaitForSingleObject(ovl_wait.hEvent, TIMEOUT);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
todo_wine
|
|
||||||
ok(res == WAIT_OBJECT_0, "WaitCommEvent failed with a timeout\n");
|
ok(res == WAIT_OBJECT_0, "WaitCommEvent failed with a timeout\n");
|
||||||
else
|
else
|
||||||
ok(res == WAIT_TIMEOUT, "WaitCommEvent should fail with a timeout\n");
|
ok(res == WAIT_TIMEOUT, "WaitCommEvent should fail with a timeout\n");
|
||||||
|
|
|
@ -920,6 +920,20 @@ static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTAT
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS set_pending_write( HANDLE device )
|
||||||
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
SERVER_START_REQ( set_serial_info )
|
||||||
|
{
|
||||||
|
req->handle = wine_server_obj_handle( device );
|
||||||
|
req->flags = SERIALINFO_PENDING_WRITE;
|
||||||
|
status = wine_server_call( req );
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* NtWriteFile [NTDLL.@]
|
* NtWriteFile [NTDLL.@]
|
||||||
* ZwWriteFile [NTDLL.@]
|
* ZwWriteFile [NTDLL.@]
|
||||||
|
@ -1146,6 +1160,10 @@ done:
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (needs_close) close( unix_handle );
|
if (needs_close) close( unix_handle );
|
||||||
|
|
||||||
|
if (type == FD_TYPE_SERIAL && (status == STATUS_SUCCESS || status == STATUS_PENDING))
|
||||||
|
set_pending_write( hFile );
|
||||||
|
|
||||||
if (status == STATUS_SUCCESS)
|
if (status == STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
io_status->u.Status = status;
|
io_status->u.Status = status;
|
||||||
|
|
|
@ -367,6 +367,7 @@ static NTSTATUS get_timeouts(HANDLE handle, SERIAL_TIMEOUTS* st)
|
||||||
SERVER_START_REQ( get_serial_info )
|
SERVER_START_REQ( get_serial_info )
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( handle );
|
req->handle = wine_server_obj_handle( handle );
|
||||||
|
req->flags = 0;
|
||||||
if (!(status = wine_server_call( req )))
|
if (!(status = wine_server_call( req )))
|
||||||
{
|
{
|
||||||
st->ReadIntervalTimeout = reply->readinterval;
|
st->ReadIntervalTimeout = reply->readinterval;
|
||||||
|
@ -380,17 +381,19 @@ static NTSTATUS get_timeouts(HANDLE handle, SERIAL_TIMEOUTS* st)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS get_wait_mask(HANDLE hDevice, DWORD *mask, DWORD *cookie)
|
static NTSTATUS get_wait_mask(HANDLE hDevice, DWORD *mask, DWORD *cookie, DWORD *pending_write)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
|
||||||
SERVER_START_REQ( get_serial_info )
|
SERVER_START_REQ( get_serial_info )
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( hDevice );
|
req->handle = wine_server_obj_handle( hDevice );
|
||||||
|
req->flags = pending_write ? SERIALINFO_PENDING_WRITE : 0;
|
||||||
if (!(status = wine_server_call( req )))
|
if (!(status = wine_server_call( req )))
|
||||||
{
|
{
|
||||||
*mask = reply->eventmask;
|
*mask = reply->eventmask;
|
||||||
if (cookie) *cookie = reply->cookie;
|
if (cookie) *cookie = reply->cookie;
|
||||||
|
if (pending_write) *pending_write = reply->pending_write;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
@ -797,6 +800,7 @@ typedef struct async_commio
|
||||||
DWORD evtmask;
|
DWORD evtmask;
|
||||||
DWORD cookie;
|
DWORD cookie;
|
||||||
DWORD mstat;
|
DWORD mstat;
|
||||||
|
DWORD pending_write;
|
||||||
serial_irq_info irq_info;
|
serial_irq_info irq_info;
|
||||||
} async_commio;
|
} async_commio;
|
||||||
|
|
||||||
|
@ -855,7 +859,7 @@ static NTSTATUS get_irq_info(int fd, serial_irq_info *irq_info)
|
||||||
static DWORD check_events(int fd, DWORD mask,
|
static DWORD check_events(int fd, DWORD mask,
|
||||||
const serial_irq_info *new,
|
const serial_irq_info *new,
|
||||||
const serial_irq_info *old,
|
const serial_irq_info *old,
|
||||||
DWORD new_mstat, DWORD old_mstat)
|
DWORD new_mstat, DWORD old_mstat, DWORD pending_write)
|
||||||
{
|
{
|
||||||
DWORD ret = 0, queue;
|
DWORD ret = 0, queue;
|
||||||
|
|
||||||
|
@ -887,7 +891,7 @@ static DWORD check_events(int fd, DWORD mask,
|
||||||
}
|
}
|
||||||
if (mask & EV_TXEMPTY)
|
if (mask & EV_TXEMPTY)
|
||||||
{
|
{
|
||||||
if (!old->temt && new->temt)
|
if ((!old->temt || pending_write) && new->temt)
|
||||||
ret |= EV_TXEMPTY;
|
ret |= EV_TXEMPTY;
|
||||||
}
|
}
|
||||||
return ret & mask;
|
return ret & mask;
|
||||||
|
@ -934,9 +938,9 @@ static DWORD CALLBACK wait_for_event(LPVOID arg)
|
||||||
}
|
}
|
||||||
*commio->events = check_events(fd, commio->evtmask,
|
*commio->events = check_events(fd, commio->evtmask,
|
||||||
&new_irq_info, &commio->irq_info,
|
&new_irq_info, &commio->irq_info,
|
||||||
new_mstat, commio->mstat);
|
new_mstat, commio->mstat, commio->pending_write);
|
||||||
if (*commio->events) break;
|
if (*commio->events) break;
|
||||||
get_wait_mask(commio->hDevice, &dummy, &cookie);
|
get_wait_mask(commio->hDevice, &dummy, &cookie, (commio->evtmask & EV_TXEMPTY) ? &commio->pending_write : NULL);
|
||||||
if (commio->cookie != cookie)
|
if (commio->cookie != cookie)
|
||||||
{
|
{
|
||||||
*commio->events = 0;
|
*commio->events = 0;
|
||||||
|
@ -975,7 +979,8 @@ static NTSTATUS wait_on(HANDLE hDevice, int fd, HANDLE hEvent, PIO_STATUS_BLOCK
|
||||||
commio->events = events;
|
commio->events = events;
|
||||||
commio->iosb = piosb;
|
commio->iosb = piosb;
|
||||||
commio->hEvent = hEvent;
|
commio->hEvent = hEvent;
|
||||||
get_wait_mask(commio->hDevice, &commio->evtmask, &commio->cookie);
|
commio->pending_write = 0;
|
||||||
|
get_wait_mask(commio->hDevice, &commio->evtmask, &commio->cookie, (commio->evtmask & EV_TXEMPTY) ? &commio->pending_write : NULL);
|
||||||
|
|
||||||
/* We may never return, if some capabilities miss
|
/* We may never return, if some capabilities miss
|
||||||
* Return error in that case
|
* Return error in that case
|
||||||
|
@ -1022,7 +1027,7 @@ static NTSTATUS wait_on(HANDLE hDevice, int fd, HANDLE hEvent, PIO_STATUS_BLOCK
|
||||||
/* We might have received something or the TX buffer is delivered */
|
/* We might have received something or the TX buffer is delivered */
|
||||||
*events = check_events(fd, commio->evtmask,
|
*events = check_events(fd, commio->evtmask,
|
||||||
&commio->irq_info, &commio->irq_info,
|
&commio->irq_info, &commio->irq_info,
|
||||||
commio->mstat, commio->mstat);
|
commio->mstat, commio->mstat, commio->pending_write);
|
||||||
if (*events)
|
if (*events)
|
||||||
{
|
{
|
||||||
status = STATUS_SUCCESS;
|
status = STATUS_SUCCESS;
|
||||||
|
@ -1170,7 +1175,7 @@ static inline NTSTATUS io_control(HANDLE hDevice,
|
||||||
case IOCTL_SERIAL_GET_WAIT_MASK:
|
case IOCTL_SERIAL_GET_WAIT_MASK:
|
||||||
if (lpOutBuffer && nOutBufferSize == sizeof(DWORD))
|
if (lpOutBuffer && nOutBufferSize == sizeof(DWORD))
|
||||||
{
|
{
|
||||||
if (!(status = get_wait_mask(hDevice, lpOutBuffer, NULL)))
|
if (!(status = get_wait_mask(hDevice, lpOutBuffer, NULL, NULL)))
|
||||||
sz = sizeof(DWORD);
|
sz = sizeof(DWORD);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -3045,6 +3045,8 @@ struct get_serial_info_request
|
||||||
{
|
{
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
obj_handle_t handle;
|
obj_handle_t handle;
|
||||||
|
int flags;
|
||||||
|
char __pad_20[4];
|
||||||
};
|
};
|
||||||
struct get_serial_info_reply
|
struct get_serial_info_reply
|
||||||
{
|
{
|
||||||
|
@ -3056,7 +3058,7 @@ struct get_serial_info_reply
|
||||||
unsigned int writemult;
|
unsigned int writemult;
|
||||||
unsigned int eventmask;
|
unsigned int eventmask;
|
||||||
unsigned int cookie;
|
unsigned int cookie;
|
||||||
char __pad_36[4];
|
unsigned int pending_write;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -3080,6 +3082,7 @@ struct set_serial_info_reply
|
||||||
};
|
};
|
||||||
#define SERIALINFO_SET_TIMEOUTS 0x01
|
#define SERIALINFO_SET_TIMEOUTS 0x01
|
||||||
#define SERIALINFO_SET_MASK 0x02
|
#define SERIALINFO_SET_MASK 0x02
|
||||||
|
#define SERIALINFO_PENDING_WRITE 0x04
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -5823,6 +5826,6 @@ union generic_reply
|
||||||
struct set_suspend_context_reply set_suspend_context_reply;
|
struct set_suspend_context_reply set_suspend_context_reply;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 449
|
#define SERVER_PROTOCOL_VERSION 450
|
||||||
|
|
||||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
|
|
@ -2212,6 +2212,7 @@ enum message_type
|
||||||
/* Retrieve info about a serial port */
|
/* Retrieve info about a serial port */
|
||||||
@REQ(get_serial_info)
|
@REQ(get_serial_info)
|
||||||
obj_handle_t handle; /* handle to comm port */
|
obj_handle_t handle; /* handle to comm port */
|
||||||
|
int flags;
|
||||||
@REPLY
|
@REPLY
|
||||||
unsigned int readinterval;
|
unsigned int readinterval;
|
||||||
unsigned int readconst;
|
unsigned int readconst;
|
||||||
|
@ -2220,6 +2221,7 @@ enum message_type
|
||||||
unsigned int writemult;
|
unsigned int writemult;
|
||||||
unsigned int eventmask;
|
unsigned int eventmask;
|
||||||
unsigned int cookie;
|
unsigned int cookie;
|
||||||
|
unsigned int pending_write;
|
||||||
@END
|
@END
|
||||||
|
|
||||||
|
|
||||||
|
@ -2236,6 +2238,7 @@ enum message_type
|
||||||
@END
|
@END
|
||||||
#define SERIALINFO_SET_TIMEOUTS 0x01
|
#define SERIALINFO_SET_TIMEOUTS 0x01
|
||||||
#define SERIALINFO_SET_MASK 0x02
|
#define SERIALINFO_SET_MASK 0x02
|
||||||
|
#define SERIALINFO_PENDING_WRITE 0x04
|
||||||
|
|
||||||
|
|
||||||
/* Create an async I/O */
|
/* Create an async I/O */
|
||||||
|
|
|
@ -1470,7 +1470,8 @@ C_ASSERT( sizeof(struct is_window_hung_request) == 16 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct is_window_hung_reply, is_hung) == 8 );
|
C_ASSERT( FIELD_OFFSET(struct is_window_hung_reply, is_hung) == 8 );
|
||||||
C_ASSERT( sizeof(struct is_window_hung_reply) == 16 );
|
C_ASSERT( sizeof(struct is_window_hung_reply) == 16 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_serial_info_request, handle) == 12 );
|
C_ASSERT( FIELD_OFFSET(struct get_serial_info_request, handle) == 12 );
|
||||||
C_ASSERT( sizeof(struct get_serial_info_request) == 16 );
|
C_ASSERT( FIELD_OFFSET(struct get_serial_info_request, flags) == 16 );
|
||||||
|
C_ASSERT( sizeof(struct get_serial_info_request) == 24 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, readinterval) == 8 );
|
C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, readinterval) == 8 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, readconst) == 12 );
|
C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, readconst) == 12 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, readmult) == 16 );
|
C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, readmult) == 16 );
|
||||||
|
@ -1478,6 +1479,7 @@ C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, writeconst) == 20 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, writemult) == 24 );
|
C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, writemult) == 24 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, eventmask) == 28 );
|
C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, eventmask) == 28 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, cookie) == 32 );
|
C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, cookie) == 32 );
|
||||||
|
C_ASSERT( FIELD_OFFSET(struct get_serial_info_reply, pending_write) == 36 );
|
||||||
C_ASSERT( sizeof(struct get_serial_info_reply) == 40 );
|
C_ASSERT( sizeof(struct get_serial_info_reply) == 40 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct set_serial_info_request, handle) == 12 );
|
C_ASSERT( FIELD_OFFSET(struct set_serial_info_request, handle) == 12 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct set_serial_info_request, flags) == 16 );
|
C_ASSERT( FIELD_OFFSET(struct set_serial_info_request, flags) == 16 );
|
||||||
|
|
|
@ -77,6 +77,7 @@ struct serial
|
||||||
|
|
||||||
unsigned int eventmask;
|
unsigned int eventmask;
|
||||||
unsigned int generation; /* event mask change counter */
|
unsigned int generation; /* event mask change counter */
|
||||||
|
unsigned int pending_write;
|
||||||
|
|
||||||
struct termios original;
|
struct termios original;
|
||||||
|
|
||||||
|
@ -137,6 +138,7 @@ struct object *create_serial( struct fd *fd )
|
||||||
serial->writeconst = 0;
|
serial->writeconst = 0;
|
||||||
serial->eventmask = 0;
|
serial->eventmask = 0;
|
||||||
serial->generation = 0;
|
serial->generation = 0;
|
||||||
|
serial->pending_write = 0;
|
||||||
serial->fd = (struct fd *)grab_object( fd );
|
serial->fd = (struct fd *)grab_object( fd );
|
||||||
set_fd_user( fd, &serial_fd_ops, &serial->obj );
|
set_fd_user( fd, &serial_fd_ops, &serial->obj );
|
||||||
return &serial->obj;
|
return &serial->obj;
|
||||||
|
@ -214,6 +216,11 @@ DECL_HANDLER(get_serial_info)
|
||||||
reply->eventmask = serial->eventmask;
|
reply->eventmask = serial->eventmask;
|
||||||
reply->cookie = serial->generation;
|
reply->cookie = serial->generation;
|
||||||
|
|
||||||
|
/* pending write */
|
||||||
|
reply->pending_write = serial->pending_write;
|
||||||
|
if (req->flags & SERIALINFO_PENDING_WRITE)
|
||||||
|
serial->pending_write = 0;
|
||||||
|
|
||||||
release_object( serial );
|
release_object( serial );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,6 +241,10 @@ DECL_HANDLER(set_serial_info)
|
||||||
serial->writemult = req->writemult;
|
serial->writemult = req->writemult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* pending write */
|
||||||
|
if (req->flags & SERIALINFO_PENDING_WRITE)
|
||||||
|
serial->pending_write = 1;
|
||||||
|
|
||||||
/* event mask */
|
/* event mask */
|
||||||
if (req->flags & SERIALINFO_SET_MASK)
|
if (req->flags & SERIALINFO_SET_MASK)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2677,6 +2677,7 @@ static void dump_is_window_hung_reply( const struct is_window_hung_reply *req )
|
||||||
static void dump_get_serial_info_request( const struct get_serial_info_request *req )
|
static void dump_get_serial_info_request( const struct get_serial_info_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " handle=%04x", req->handle );
|
fprintf( stderr, " handle=%04x", req->handle );
|
||||||
|
fprintf( stderr, ", flags=%d", req->flags );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_get_serial_info_reply( const struct get_serial_info_reply *req )
|
static void dump_get_serial_info_reply( const struct get_serial_info_reply *req )
|
||||||
|
@ -2688,6 +2689,7 @@ static void dump_get_serial_info_reply( const struct get_serial_info_reply *req
|
||||||
fprintf( stderr, ", writemult=%08x", req->writemult );
|
fprintf( stderr, ", writemult=%08x", req->writemult );
|
||||||
fprintf( stderr, ", eventmask=%08x", req->eventmask );
|
fprintf( stderr, ", eventmask=%08x", req->eventmask );
|
||||||
fprintf( stderr, ", cookie=%08x", req->cookie );
|
fprintf( stderr, ", cookie=%08x", req->cookie );
|
||||||
|
fprintf( stderr, ", pending_write=%08x", req->pending_write );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_set_serial_info_request( const struct set_serial_info_request *req )
|
static void dump_set_serial_info_request( const struct set_serial_info_request *req )
|
||||||
|
|
Loading…
Reference in a new issue