Commit 3b429e88 authored by Dmitry Timoshkov's avatar Dmitry Timoshkov Committed by Alexandre Julliard

server: Add support for pending write flag to the serial device.

parent 53e727ef
...@@ -943,7 +943,6 @@ static void test_waittxempty(void) ...@@ -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 ...@@ -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: ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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 ...@@ -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 ...@@ -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, ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ); ...@@ -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 ); ...@@ -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 ...@@ -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 ) ...@@ -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) ...@@ -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) ...@@ -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 ) ...@@ -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 ...@@ -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 )
......
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