Added handle_t type to server interface so that we can make handles
[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 functions are for interaction with asynchronous i/o objects */
177 int serial_async_setup(struct object *obj, struct async *ov)
178 {
179     struct serial *serial = (struct serial *)obj;
180     int timeout;
181
182     if(obj->ops != &serial_ops)
183         return 0;
184
185     switch(async_type(ov))
186     {
187     case ASYNC_TYPE_READ:
188         timeout = serial->readconst + serial->readmult*async_count(ov);
189         async_add_timeout(ov, timeout);
190         async_set_eventmask(ov,EV_RXCHAR);
191         break;
192     case ASYNC_TYPE_WRITE:
193         timeout = serial->writeconst + serial->writemult*async_count(ov);
194         async_add_timeout(ov, timeout);
195         async_set_eventmask(ov,EV_TXEMPTY);
196         break;
197     case ASYNC_TYPE_WAIT:
198         async_set_eventmask(ov,serial->eventmask);
199         break;
200     }
201
202     return 1;
203 }
204
205 int serial_async_get_poll_events( struct async *ov )
206 {
207     int events=0,mask;
208
209     switch(async_type(ov))
210     {
211     case ASYNC_TYPE_READ:
212         events |= POLLIN;
213         break;
214     case ASYNC_TYPE_WRITE:
215         events |= POLLOUT;
216         break;
217     case ASYNC_TYPE_WAIT:
218     /* 
219      * FIXME: here is the spot to implement other WaitCommEvent flags
220      */
221         mask = async_get_eventmask(ov);
222         if(mask&EV_RXCHAR)
223             events |= POLLIN;
224         if(mask&EV_TXEMPTY)
225             events |= POLLOUT;
226         break;
227     }
228     return events;
229 }
230
231 /* receive a select event, and output a windows event */
232 int serial_async_poll_event(struct object *obj, int event)
233 {
234     int r=0;
235
236     /* 
237      * FIXME: here is the spot to implement other WaitCommEvent flags
238      */
239     if(event & POLLIN)
240         r |= EV_RXCHAR;
241     if(event & POLLOUT)
242         r |= EV_TXEMPTY;
243
244     return r;
245 }
246
247 /* create a serial */
248 DECL_HANDLER(create_serial)
249 {
250     struct serial *serial;
251
252     req->handle = 0;
253     if ((serial = create_serial( get_req_data(req), get_req_data_size(req), req->access )))
254     {
255         req->handle = alloc_handle( current->process, serial, req->access, req->inherit );
256         release_object( serial );
257     }
258 }
259
260 DECL_HANDLER(get_serial_info)
261 {
262     struct serial *serial;
263
264     if ((serial = get_serial_obj( current->process, req->handle, 0 )))
265     {
266         /* timeouts */
267         req->readinterval = serial->readinterval;
268         req->readconst    = serial->readconst;
269         req->readmult     = serial->readmult;
270         req->writeconst   = serial->writeconst;
271         req->writemult    = serial->writemult;
272
273         /* event mask */
274         req->eventmask    = serial->eventmask;
275
276         /* comm port error status */
277         req->commerror    = serial->commerror;
278
279         release_object( serial );
280     }
281 }
282
283 DECL_HANDLER(set_serial_info)
284 {
285     struct serial *serial;
286
287     if ((serial = get_serial_obj( current->process, req->handle, 0 )))
288     {
289         /* timeouts */
290         if(req->flags & SERIALINFO_SET_TIMEOUTS)
291         {
292             serial->readinterval = req->readinterval;
293             serial->readconst    = req->readconst;
294             serial->readmult     = req->readmult;
295             serial->writeconst   = req->writeconst;
296             serial->writemult    = req->writemult;
297         }
298
299         /* event mask */
300         if(req->flags & SERIALINFO_SET_MASK)
301         {
302             serial->eventmask = req->eventmask;
303         }
304
305         /* comm port error status */
306         if(req->flags & SERIALINFO_SET_ERROR)
307         {
308             serial->commerror = req->commerror;
309         }
310
311         release_object( serial );
312     }
313 }
314