- move async activation into the server
- implement async queues
diff --git a/server/serial.c b/server/serial.c
index da682bf..5a55c80 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -2,10 +2,7 @@
* Server-side serial port communications management
*
* Copyright (C) 1998 Alexandre Julliard
- * Copyright (C) 2000 Mike McCormack
- *
- * TODO:
- * Add async read, write and WaitCommEvent handling.
+ * Copyright (C) 2000,2001 Mike McCormack
*
*/
@@ -34,11 +31,15 @@
#include "handle.h"
#include "thread.h"
#include "request.h"
+#include "async.h"
static void serial_dump( struct object *obj, int verbose );
static int serial_get_fd( struct object *obj );
static int serial_get_info( struct object *obj, struct get_file_info_reply *reply );
static int serial_get_poll_events( struct object *obj );
+static struct async_queue * serial_queue_async(struct object *obj, struct async* async, int type, int count);
+static void destroy_serial(struct object *obj);
+static void serial_poll_event( struct object *obj, int event );
struct serial
{
@@ -58,6 +59,10 @@
struct termios original;
+ struct async_queue read_q;
+ struct async_queue write_q;
+ struct async_queue wait_q;
+
/* FIXME: add dcb, comm status, handler module, sharing */
};
@@ -70,15 +75,14 @@
default_poll_signaled, /* signaled */
no_satisfied, /* satisfied */
serial_get_poll_events, /* get_poll_events */
- default_poll_event, /* poll_event */
+ serial_poll_event, /* poll_event */
serial_get_fd, /* get_fd */
no_flush, /* flush */
serial_get_info, /* get_file_info */
- no_destroy /* destroy */
+ serial_queue_async, /* queue_async */
+ destroy_serial /* destroy */
};
-/* SERIAL PORT functions */
-
static struct serial *create_serial( const char *nameptr, size_t len, unsigned int access, int attributes )
{
struct serial *serial;
@@ -132,10 +136,22 @@
serial->writeconst = 0;
serial->eventmask = 0;
serial->commerror = 0;
+ init_async_queue(&serial->read_q);
+ init_async_queue(&serial->write_q);
+ init_async_queue(&serial->wait_q);
}
return serial;
}
+static void destroy_serial( struct object *obj)
+{
+ struct serial *serial = (struct serial *)obj;
+
+ destroy_async_queue(&serial->read_q);
+ destroy_async_queue(&serial->write_q);
+ destroy_async_queue(&serial->wait_q);
+}
+
static void serial_dump( struct object *obj, int verbose )
{
struct serial *serial = (struct serial *)obj;
@@ -153,8 +169,16 @@
struct serial *serial = (struct serial *)obj;
int events = 0;
assert( obj->ops == &serial_ops );
- if (serial->access & GENERIC_READ) events |= POLLIN;
- if (serial->access & GENERIC_WRITE) events |= POLLOUT;
+
+ if(IS_READY(serial->read_q))
+ events |= POLLIN;
+ if(IS_READY(serial->write_q))
+ events |= POLLOUT;
+ if(IS_READY(serial->wait_q))
+ events |= POLLIN;
+
+ /* fprintf(stderr,"poll events are %04x\n",events); */
+
return events;
}
@@ -190,25 +214,76 @@
return FD_TYPE_TIMEOUT;
}
-/* these function calculates the timeout for an async operation
- on a serial port */
-int get_serial_async_timeout(struct object *obj, int type, int count)
+static void serial_poll_event(struct object *obj, int event)
{
struct serial *serial = (struct serial *)obj;
- if(obj->ops != &serial_ops)
- return 0;
+ /* fprintf(stderr,"Poll event %02x\n",event); */
+
+ if(IS_READY(serial->read_q) && (POLLIN & event) )
+ async_notify(serial->read_q.head,STATUS_ALERTED);
+
+ if(IS_READY(serial->write_q) && (POLLOUT & event) )
+ async_notify(serial->write_q.head,STATUS_ALERTED);
+
+ if(IS_READY(serial->wait_q) && (POLLIN & event) )
+ async_notify(serial->wait_q.head,STATUS_ALERTED);
+
+ set_select_events(obj,obj->ops->get_poll_events(obj));
+}
+
+/*
+ * This function is an abuse of overloading that deserves some explanation.
+ *
+ * It has three purposes:
+ *
+ * 1. get the queue for a type of async operation
+ * 2. requeue an async operation
+ * 3. queue a new async operation
+ *
+ * It is overloaded so that these three functions only take one function pointer
+ * in the object operations list.
+ *
+ * In all cases, it returns the async queue.
+ */
+static struct async_queue *serial_queue_async(struct object *obj, struct async *async, int type, int count)
+{
+ struct serial *serial = (struct serial *)obj;
+ struct async_queue *q;
+ int timeout;
+
+ assert(obj->ops == &serial_ops);
switch(type)
{
case ASYNC_TYPE_READ:
- return serial->readconst + serial->readmult*count;
+ q = &serial->read_q;
+ timeout = serial->readconst + serial->readmult*count;
+ break;
+ case ASYNC_TYPE_WAIT:
+ q = &serial->wait_q;
+ timeout = 0;
+ break;
case ASYNC_TYPE_WRITE:
- return serial->writeconst + serial->writemult*count;
+ q = &serial->write_q;
+ timeout = serial->writeconst + serial->writemult*count;
+ break;
+ default:
+ set_error(STATUS_INVALID_PARAMETER);
+ return NULL;
}
- return 0;
+
+ if(async)
+ {
+ if(!async->q)
+ {
+ async_add_timeout(async,timeout);
+ async_insert(q, async);
+ }
}
+ return q;
+}
/* create a serial */
DECL_HANDLER(create_serial)