Use poll() on the client-side during server waits to implement
[wine] / server / serial.c
1 /*
2  * Server-side serial port communications management
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  * Copyright (C) 2000 Mike McCormack
6  *
7  * TODO:
8  *  Add async read, write and WaitCommEvent handling.
9  *
10  */
11
12 #include "config.h"
13
14 #include <assert.h>
15 #include <fcntl.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <errno.h>
20 #ifdef HAVE_SYS_ERRNO_H
21 #include <sys/errno.h>
22 #endif
23 #include <sys/stat.h>
24 #include <sys/time.h>
25 #include <sys/types.h>
26 #include <time.h>
27 #include <unistd.h>
28 #include <utime.h>
29 #include <termios.h>
30 #include <sys/ioctl.h>
31
32 #include "winerror.h"
33 #include "winbase.h"
34
35 #include "handle.h"
36 #include "thread.h"
37 #include "request.h"
38
39 static void serial_dump( struct object *obj, int verbose );
40 static int serial_get_fd( struct object *obj );
41 static int serial_get_info( struct object *obj, struct get_file_info_request *req );
42 static int serial_get_poll_events( struct object *obj );
43
44 struct serial
45 {
46     struct object       obj;
47     unsigned int        access;
48
49     /* timeout values */
50     unsigned int        readinterval;
51     unsigned int        readconst;
52     unsigned int        readmult;
53     unsigned int        writeconst;
54     unsigned int        writemult;
55
56     unsigned int        eventmask;
57     unsigned int        commerror;
58
59     struct termios      original;
60
61     /* FIXME: add dcb, comm status, handler module, sharing */
62 };
63
64 static const struct object_ops serial_ops =
65 {
66     sizeof(struct serial),        /* size */
67     serial_dump,                  /* dump */
68     default_poll_add_queue,       /* add_queue */
69     default_poll_remove_queue,    /* remove_queue */
70     default_poll_signaled,        /* signaled */
71     no_satisfied,                 /* satisfied */
72     serial_get_poll_events,       /* get_poll_events */
73     default_poll_event,           /* poll_event */
74     serial_get_fd,                /* get_fd */
75     no_flush,                     /* flush */
76     serial_get_info,              /* get_file_info */
77     no_destroy                    /* destroy */
78 };
79
80 /* SERIAL PORT functions */
81
82 static struct serial *create_serial( const char *nameptr, size_t len, unsigned int access )
83 {
84     struct serial *serial;
85     struct termios tios;
86     int fd, flags = 0;
87     char *name;
88
89     if (!(name = mem_alloc( len + 1 ))) return NULL;
90     memcpy( name, nameptr, len );
91     name[len] = 0;
92
93     switch(access & (GENERIC_READ | GENERIC_WRITE))
94     {
95     case GENERIC_READ:  flags |= O_RDONLY; break;
96     case GENERIC_WRITE: flags |= O_WRONLY; break;
97     case GENERIC_READ|GENERIC_WRITE: flags |= O_RDWR; break;
98     default: break;
99     }
100
101     fd = open( name, flags );
102     free( name );
103     if (fd < 0)
104     {
105         file_set_error();
106         return NULL;
107     }
108
109     /* check its really a serial port */
110     if (tcgetattr(fd,&tios))
111     {
112         file_set_error();
113         close( fd );
114         return NULL;
115     }
116
117     if ((serial = alloc_object( &serial_ops, fd )))
118     {
119         serial->access       = access;
120         serial->readinterval = 0;
121         serial->readmult     = 0;
122         serial->readconst    = 0;
123         serial->writemult    = 0;
124         serial->writeconst   = 0;
125         serial->eventmask    = 0;
126         serial->commerror    = 0;
127     }
128     return serial;
129 }
130
131 static void serial_dump( struct object *obj, int verbose )
132 {
133     struct serial *serial = (struct serial *)obj;
134     assert( obj->ops == &serial_ops );
135     fprintf( stderr, "Port fd=%d mask=%x\n", serial->obj.fd, serial->eventmask );
136 }
137
138 struct serial *get_serial_obj( struct process *process, handle_t handle, unsigned int access )
139 {
140     return (struct serial *)get_handle_obj( process, handle, access, &serial_ops );
141 }
142
143 static int serial_get_poll_events( struct object *obj )
144 {
145     struct serial *serial = (struct serial *)obj;
146     int events = 0;
147     assert( obj->ops == &serial_ops );
148     if (serial->access & GENERIC_READ) events |= POLLIN;
149     if (serial->access & GENERIC_WRITE) events |= POLLOUT;
150     return events;
151 }
152
153 static int serial_get_fd( struct object *obj )
154 {
155     struct serial *serial = (struct serial *)obj;
156     assert( obj->ops == &serial_ops );
157     return serial->obj.fd;
158 }
159
160 static int serial_get_info( struct object *obj, struct get_file_info_request *req )
161 {
162     assert( obj->ops == &serial_ops );
163     req->type        = FILE_TYPE_CHAR;
164     req->attr        = 0;
165     req->access_time = 0;
166     req->write_time  = 0;
167     req->size_high   = 0;
168     req->size_low    = 0;
169     req->links       = 0;
170     req->index_high  = 0;
171     req->index_low   = 0;
172     req->serial      = 0;
173     return 1;
174 }
175
176 /* these function calculates the timeout for an async operation
177    on a serial port */
178 int get_serial_async_timeout(struct object *obj, int type, int count)
179 {
180     struct serial *serial = (struct serial *)obj;
181
182     if(obj->ops != &serial_ops)
183         return 0;
184
185     switch(type)
186     {
187     case ASYNC_TYPE_READ:
188         return serial->readconst + serial->readmult*count;
189     case ASYNC_TYPE_WRITE:
190         return serial->writeconst + serial->writemult*count;
191     }
192     return 0;
193 }
194
195
196 /* create a serial */
197 DECL_HANDLER(create_serial)
198 {
199     struct serial *serial;
200
201     req->handle = 0;
202     if ((serial = create_serial( get_req_data(req), get_req_data_size(req), req->access )))
203     {
204         req->handle = alloc_handle( current->process, serial, req->access, req->inherit );
205         release_object( serial );
206     }
207 }
208
209 DECL_HANDLER(get_serial_info)
210 {
211     struct serial *serial;
212
213     if ((serial = get_serial_obj( current->process, req->handle, 0 )))
214     {
215         /* timeouts */
216         req->readinterval = serial->readinterval;
217         req->readconst    = serial->readconst;
218         req->readmult     = serial->readmult;
219         req->writeconst   = serial->writeconst;
220         req->writemult    = serial->writemult;
221
222         /* event mask */
223         req->eventmask    = serial->eventmask;
224
225         /* comm port error status */
226         req->commerror    = serial->commerror;
227
228         release_object( serial );
229     }
230 }
231
232 DECL_HANDLER(set_serial_info)
233 {
234     struct serial *serial;
235
236     if ((serial = get_serial_obj( current->process, req->handle, 0 )))
237     {
238         /* timeouts */
239         if(req->flags & SERIALINFO_SET_TIMEOUTS)
240         {
241             serial->readinterval = req->readinterval;
242             serial->readconst    = req->readconst;
243             serial->readmult     = req->readmult;
244             serial->writeconst   = req->writeconst;
245             serial->writemult    = req->writemult;
246         }
247
248         /* event mask */
249         if(req->flags & SERIALINFO_SET_MASK)
250         {
251             serial->eventmask = req->eventmask;
252         }
253
254         /* comm port error status */
255         if(req->flags & SERIALINFO_SET_ERROR)
256         {
257             serial->commerror = req->commerror;
258         }
259
260         release_object( serial );
261     }
262 }
263