From 44b5bf599867dd6791157e35b3b2ea32960afc36 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Thu, 7 Sep 2000 18:39:51 +0000 Subject: [PATCH] Added serial port object to the server. --- files/dos_fs.c | 20 +---- include/comm.h | 2 + include/server.h | 13 ++- misc/comm.c | 28 +++++++ server/Makefile.in | 1 + server/request.h | 2 + server/serial.c | 198 +++++++++++++++++++++++++++++++++++++++++++++ server/trace.c | 17 ++++ 8 files changed, 264 insertions(+), 17 deletions(-) create mode 100644 server/serial.c diff --git a/files/dos_fs.c b/files/dos_fs.c index f4f099a8bfc..70cc9c06558 100644 --- a/files/dos_fs.c +++ b/files/dos_fs.c @@ -28,6 +28,7 @@ #include "winerror.h" #include "drive.h" #include "file.h" +#include "comm.h" #include "heap.h" #include "msdos.h" #include "syslevel.h" @@ -648,6 +649,7 @@ HFILE DOSFS_OpenDevice( const char *name, DWORD access ) { int i; const char *p; + HFILE handle; if (!name) return (HFILE)NULL; /* if FILE_DupUnixHandle was used */ if (name[0] && (name[1] == ':')) name += 2; @@ -667,7 +669,6 @@ HFILE DOSFS_OpenDevice( const char *name, DWORD access ) OPEN_EXISTING, 0, -1, TRUE ); if (!strcmp(DOSFS_Devices[i].name,"CON")) { HFILE to_dup; - HFILE handle; switch (access & (GENERIC_READ|GENERIC_WRITE)) { case GENERIC_READ: to_dup = GetStdHandle( STD_INPUT_HANDLE ); @@ -690,22 +691,9 @@ HFILE DOSFS_OpenDevice( const char *name, DWORD access ) { return FILE_CreateDevice( i, access, NULL ); } - { - HFILE r; - char devname[40]; - PROFILE_GetWineIniString("serialports",name,"",devname,sizeof devname); - if(devname[0]) - { - TRACE_(file)("DOSFS_OpenDevice %s is %s\n", - DOSFS_Devices[i].name,devname); - r = FILE_CreateFile( devname, access, - FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, - OPEN_EXISTING, 0, -1, TRUE ); - TRACE_(file)("Create_File return %08X\n",r); - return r; - } - } + if( (handle=COMM_CreatePort(name,access)) ) + return handle; FIXME("device open %s not supported (yet)\n",DOSFS_Devices[i].name); return HFILE_ERROR; diff --git a/include/comm.h b/include/comm.h index 437731c9c56..540f2b21cc3 100644 --- a/include/comm.h +++ b/include/comm.h @@ -2,6 +2,7 @@ #define __WINE_COMM_H #include "windef.h" +#include "winbase.h" #define MAX_PORTS 9 @@ -24,5 +25,6 @@ struct DosDeviceStruct { }; extern void COMM_Init(void); +extern HANDLE COMM_CreatePort(LPCSTR name, DWORD access); #endif /* __WINE_COMM_H */ diff --git a/include/server.h b/include/server.h index 04046f80eb7..cefb21b5310 100644 --- a/include/server.h +++ b/include/server.h @@ -1312,6 +1312,15 @@ struct wait_input_idle_request OUT int event; /* handle to idle event */ }; +struct create_serial_request +{ + REQUEST_HEADER; /* request header */ + IN unsigned int access; /* wanted access rights */ + IN int inherit; /* inherit flag */ + IN unsigned int sharing; /* sharing flags */ + OUT int handle; /* handle to the port */ + IN char name[1]; /* file name */ +}; /* Everything below this line is generated automatically by tools/make_requests */ /* ### make_requests begin ### */ @@ -1425,6 +1434,7 @@ enum request REQ_GET_MSG_QUEUE, REQ_WAKE_QUEUE, REQ_WAIT_INPUT_IDLE, + REQ_CREATE_SERIAL, REQ_NB_REQUESTS }; @@ -1539,9 +1549,10 @@ union generic_request struct get_msg_queue_request get_msg_queue; struct wake_queue_request wake_queue; struct wait_input_idle_request wait_input_idle; + struct create_serial_request create_serial; }; -#define SERVER_PROTOCOL_VERSION 20 +#define SERVER_PROTOCOL_VERSION 21 /* ### make_requests end ### */ /* Everything above this line is generated automatically by tools/make_requests */ diff --git a/misc/comm.c b/misc/comm.c index 33a8f50a50b..35b4ea7bdbd 100644 --- a/misc/comm.c +++ b/misc/comm.c @@ -2841,3 +2841,31 @@ BOOL WINAPI GetDefaultCommConfigW( LPCWSTR lpszName,LPCOMMCONFIG lpCC, HeapFree( GetProcessHeap(), 0, lpszNameA ); return ret; } + +/************************************************************************** + * COMM_CreatePort INTERNAL + */ +HANDLE COMM_CreatePort(LPCSTR name, DWORD access) +{ + struct create_serial_request *req = get_req_buffer(); + DWORD r; + char devname[40]; + + TRACE("%s %lx\n", name, access); + + PROFILE_GetWineIniString("serialports",name,"",devname,sizeof devname); + if(!devname[0]) + return 0; + + TRACE("opening %s as %s\n", devname, name); + + req->handle = 0; + req->access = access; + req->sharing = FILE_SHARE_READ|FILE_SHARE_WRITE; + lstrcpynA( req->name, devname, server_remaining(req->name) ); + SetLastError(0); + r = server_call( REQ_CREATE_SERIAL ); + TRACE("create_port_request return %08lX handle = %08X\n",r,req->handle); + return req->handle; +} + diff --git a/server/Makefile.in b/server/Makefile.in index 12fd8de9c9e..6563b3272a6 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -28,6 +28,7 @@ C_SRCS = \ request.c \ select.c \ semaphore.c \ + serial.c \ snapshot.c \ sock.c \ thread.c \ diff --git a/server/request.h b/server/request.h index bf9b7977495..d66c230b4ab 100644 --- a/server/request.h +++ b/server/request.h @@ -201,6 +201,7 @@ DECL_HANDLER(init_atom_table); DECL_HANDLER(get_msg_queue); DECL_HANDLER(wake_queue); DECL_HANDLER(wait_input_idle); +DECL_HANDLER(create_serial); #ifdef WANT_REQUEST_HANDLERS @@ -314,6 +315,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_get_msg_queue, (req_handler)req_wake_queue, (req_handler)req_wait_input_idle, + (req_handler)req_create_serial, }; #endif /* WANT_REQUEST_HANDLERS */ diff --git a/server/serial.c b/server/serial.c new file mode 100644 index 00000000000..e5b60667fb5 --- /dev/null +++ b/server/serial.c @@ -0,0 +1,198 @@ +/* + * Server-side serial port communications management + * + * Copyright (C) 1998 Alexandre Julliard + * Copyright (C) 2000 Mike McCormack + * + * TODO: + * Add async read, write and WaitCommEvent handling. + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_ERRNO_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include "winerror.h" +#include "winbase.h" + +#include "handle.h" +#include "thread.h" +#include "request.h" + +static void serial_dump( struct object *obj, int verbose ); +static void serial_destroy( struct object *obj ); +static int serial_get_read_fd( struct object *obj ); +static int serial_get_write_fd( struct object *obj ); +static int serial_get_info( struct object *obj, struct get_file_info_request *req ); +static int serial_get_poll_events( struct object *obj ); + +struct serial +{ + struct object obj; + char name[16]; /* eg. /dev/ttyS1 */ + int access; + + /* timeout values */ + unsigned int readinterval; + unsigned int readconst; + unsigned int readmult; + unsigned int writeconst; + unsigned int writemult; + + unsigned int eventmask; + unsigned int commerror; + + struct termios original; + + /* FIXME: add dcb, comm status, handler module, sharing */ +}; + +static const struct object_ops serial_ops = +{ + sizeof(struct serial), /* size */ + serial_dump, /* dump */ + default_poll_add_queue, /* add_queue */ + default_poll_remove_queue, /* remove_queue */ + default_poll_signaled, /* signaled */ + no_satisfied, /* satisfied */ + serial_get_poll_events, /* get_poll_events */ + default_poll_event, /* poll_event */ + serial_get_read_fd, /* get_read_fd */ + serial_get_write_fd, /* get_write_fd */ + no_flush, /* flush */ + serial_get_info, /* get_file_info */ + serial_destroy /* destroy */ +}; + +/* SERIAL PORT functions */ + +static void serial_dump( struct object *obj, int verbose ) +{ + struct serial *serial = (struct serial *)obj; + assert( obj->ops == &serial_ops ); + + fprintf( stderr, "Port fd=%d name='%s' mask=%x\n", + serial->obj.fd, serial->name,serial->eventmask); +} + +/* same as file_destroy, but don't delete comm ports */ +static void serial_destroy( struct object *obj ) +{ + assert( obj->ops == &serial_ops ); +} + +struct serial *get_serial_obj( struct process *process, int handle, unsigned int access ) +{ + return (struct serial *)get_handle_obj( process, handle, access, &serial_ops ); +} + +static int serial_get_poll_events( struct object *obj ) +{ + 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; + return events; +} + +static int serial_get_read_fd( struct object *obj ) +{ + struct serial *serial = (struct serial *)obj; + assert( obj->ops == &serial_ops ); + return dup( serial->obj.fd ); +} + +static int serial_get_write_fd( struct object *obj ) +{ + struct serial *serial = (struct serial *)obj; + assert( obj->ops == &serial_ops ); + return dup( serial->obj.fd ); +} + +static int serial_get_info( struct object *obj, struct get_file_info_request *req ) +{ + assert( obj->ops == &serial_ops ); + req->type = FILE_TYPE_CHAR; + req->attr = 0; + req->access_time = 0; + req->write_time = 0; + req->size_high = 0; + req->size_low = 0; + req->links = 0; + req->index_high = 0; + req->index_low = 0; + req->serial = 0; + return 1; +} + +/* create a serial */ +DECL_HANDLER(create_serial) +{ + struct serial *serial; + int fd,flags; + struct termios tios; + + req->handle = -1; + + flags = 0; + switch(req->access & (GENERIC_READ | GENERIC_WRITE)) + { + case GENERIC_READ: flags |= O_RDONLY; break; + case GENERIC_WRITE: flags |= O_WRONLY; break; + case GENERIC_READ|GENERIC_WRITE: flags |= O_RDWR; break; + default: break; + } + + fd = open( req->name, flags ); + if(fd < 0) + { + file_set_error(); + return; + } + + /* check its really a serial port */ + if(0>tcgetattr(fd,&tios)) + { + file_set_error(); + close(fd); + return; + } + + serial = alloc_object( &serial_ops, fd ); + if (serial) + { + strncpy(serial->name,req->name,sizeof serial->name); + serial->name[sizeof(serial->name)-1] = 0; + + serial->access = req->access; + serial->readinterval = 0; + serial->readmult = 0; + serial->readconst = 0; + serial->writemult = 0; + serial->writeconst = 0; + serial->eventmask = 0; + serial->commerror = 0; + + req->handle = alloc_handle( current->process, serial, req->access, req->inherit ); + release_object( serial ); + } +} + diff --git a/server/trace.c b/server/trace.c index 89b09980266..07c1a6dcf49 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1417,6 +1417,20 @@ static void dump_wait_input_idle_reply( const struct wait_input_idle_request *re fprintf( stderr, " event=%d", req->event ); } +static void dump_create_serial_request( const struct create_serial_request *req ) +{ + fprintf( stderr, " access=%08x,", req->access ); + fprintf( stderr, " inherit=%d,", req->inherit ); + fprintf( stderr, " sharing=%08x,", req->sharing ); + fprintf( stderr, " name=" ); + dump_string( req, req->name ); +} + +static void dump_create_serial_reply( const struct create_serial_request *req ) +{ + fprintf( stderr, " handle=%d", req->handle ); +} + static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_new_process_request, (dump_func)dump_wait_process_request, @@ -1525,6 +1539,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_get_msg_queue_request, (dump_func)dump_wake_queue_request, (dump_func)dump_wait_input_idle_request, + (dump_func)dump_create_serial_request, }; static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { @@ -1635,6 +1650,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_get_msg_queue_reply, (dump_func)0, (dump_func)dump_wait_input_idle_reply, + (dump_func)dump_create_serial_reply, }; static const char * const req_names[REQ_NB_REQUESTS] = { @@ -1745,6 +1761,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "get_msg_queue", "wake_queue", "wait_input_idle", + "create_serial", }; /* ### make_requests end ### */