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