Implemented 64bit file size handling.
[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     fd = open( name, flags );
101     free( name );
102     if (fd < 0)
103     {
104         file_set_error();
105         return NULL;
106     }
107
108     /* check its really a serial port */
109     if (tcgetattr(fd,&tios))
110     {
111         file_set_error();
112         close( fd );
113         return NULL;
114     }
115
116     if ((serial = alloc_object( &serial_ops, fd )))
117     {
118         serial->access       = access;
119         serial->readinterval = 0;
120         serial->readmult     = 0;
121         serial->readconst    = 0;
122         serial->writemult    = 0;
123         serial->writeconst   = 0;
124         serial->eventmask    = 0;
125         serial->commerror    = 0;
126     }
127     return serial;
128 }
129
130 static void serial_dump( struct object *obj, int verbose )
131 {
132     struct serial *serial = (struct serial *)obj;
133     assert( obj->ops == &serial_ops );
134     fprintf( stderr, "Port fd=%d mask=%x\n", serial->obj.fd, serial->eventmask );
135 }
136
137 struct serial *get_serial_obj( struct process *process, handle_t handle, unsigned int access )
138 {
139     return (struct serial *)get_handle_obj( process, handle, access, &serial_ops );
140 }
141
142 static int serial_get_poll_events( struct object *obj )
143 {
144     struct serial *serial = (struct serial *)obj;
145     int events = 0;
146     assert( obj->ops == &serial_ops );
147     if (serial->access & GENERIC_READ) events |= POLLIN;
148     if (serial->access & GENERIC_WRITE) events |= POLLOUT;
149     return events;
150 }
151
152 static int serial_get_fd( struct object *obj )
153 {
154     struct serial *serial = (struct serial *)obj;
155     assert( obj->ops == &serial_ops );
156     return serial->obj.fd;
157 }
158
159 static int serial_get_info( struct object *obj, struct get_file_info_request *req )
160 {
161     assert( obj->ops == &serial_ops );
162     req->type        = FILE_TYPE_CHAR;
163     req->attr        = 0;
164     req->access_time = 0;
165     req->write_time  = 0;
166     req->size_high   = 0;
167     req->size_low    = 0;
168     req->links       = 0;
169     req->index_high  = 0;
170     req->index_low   = 0;
171     req->serial      = 0;
172     return 1;
173 }
174
175 /* these function calculates the timeout for an async operation
176    on a serial port */
177 int get_serial_async_timeout(struct object *obj, int type, int count)
178 {
179     struct serial *serial = (struct serial *)obj;
180
181     if(obj->ops != &serial_ops)
182         return 0;
183
184     switch(type)
185     {
186     case ASYNC_TYPE_READ:
187         return serial->readconst + serial->readmult*count;
188     case ASYNC_TYPE_WRITE:
189         return serial->writeconst + serial->writemult*count;
190     }
191     return 0;
192 }
193
194
195 /* create a serial */
196 DECL_HANDLER(create_serial)
197 {
198     struct serial *serial;
199
200     req->handle = 0;
201     if ((serial = create_serial( get_req_data(req), get_req_data_size(req), req->access )))
202     {
203         req->handle = alloc_handle( current->process, serial, req->access, req->inherit );
204         release_object( serial );
205     }
206 }
207
208 DECL_HANDLER(get_serial_info)
209 {
210     struct serial *serial;
211
212     if ((serial = get_serial_obj( current->process, req->handle, 0 )))
213     {
214         /* timeouts */
215         req->readinterval = serial->readinterval;
216         req->readconst    = serial->readconst;
217         req->readmult     = serial->readmult;
218         req->writeconst   = serial->writeconst;
219         req->writemult    = serial->writemult;
220
221         /* event mask */
222         req->eventmask    = serial->eventmask;
223
224         /* comm port error status */
225         req->commerror    = serial->commerror;
226
227         release_object( serial );
228     }
229 }
230
231 DECL_HANDLER(set_serial_info)
232 {
233     struct serial *serial;
234
235     if ((serial = get_serial_obj( current->process, req->handle, 0 )))
236     {
237         /* timeouts */
238         if(req->flags & SERIALINFO_SET_TIMEOUTS)
239         {
240             serial->readinterval = req->readinterval;
241             serial->readconst    = req->readconst;
242             serial->readmult     = req->readmult;
243             serial->writeconst   = req->writeconst;
244             serial->writemult    = req->writemult;
245         }
246
247         /* event mask */
248         if(req->flags & SERIALINFO_SET_MASK)
249         {
250             serial->eventmask = req->eventmask;
251         }
252
253         /* comm port error status */
254         if(req->flags & SERIALINFO_SET_ERROR)
255         {
256             serial->commerror = req->commerror;
257         }
258
259         release_object( serial );
260     }
261 }
262