Alexandre Julliard | 77b9918 | 1997-09-14 17:17:23 +0000 | [diff] [blame] | 1 | /* |
Alexandre Julliard | ecc3712 | 1994-11-22 16:31:29 +0000 | [diff] [blame] | 2 | * DEC 93 Erik Bos <erik@xs4all.nl> |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 3 | * |
| 4 | * Copyright 1996 Marcus Meissner |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 5 | * |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 6 | * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no> |
| 7 | * - Implemented buffers and EnableCommNotification. |
| 8 | * |
Lawson Whitney | 96b93bb | 1999-04-04 12:38:35 +0000 | [diff] [blame] | 9 | * Apr 3, 1999. Lawson Whitney <lawson_whitney@juno.com> |
| 10 | * - Fixed the modem control part of EscapeCommFunction16. |
| 11 | * |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 12 | * Mar 3, 1999. Ove Kåven <ovek@arcticnet.no> |
| 13 | * - Use port indices instead of unixfds for win16 |
| 14 | * - Moved things around (separated win16 and win32 routines) |
| 15 | * - Added some hints on how to implement buffers and EnableCommNotification. |
Alexandre Julliard | 23946ad | 1997-06-16 17:43:53 +0000 | [diff] [blame] | 16 | * |
| 17 | * May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER] |
| 18 | * - ptr->fd wasn't getting cleared on close. |
| 19 | * - GetCommEventMask() and GetCommError() didn't do much of anything. |
| 20 | * IMHO, they are still wrong, but they at least implement the RXCHAR |
| 21 | * event and return I/O queue sizes, which makes the app I'm interested |
| 22 | * in (analog devices EZKIT DSP development system) work. |
Alexandre Julliard | 77b9918 | 1997-09-14 17:17:23 +0000 | [diff] [blame] | 23 | * |
| 24 | * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney |
| 25 | * <lawson_whitney@juno.com> |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 26 | * July 6, 1998. Fixes and comments by Valentijn Sessink |
| 27 | * <vsessink@ic.uva.nl> [V] |
Rein Klazes | cd7986b | 1998-10-11 14:02:09 +0000 | [diff] [blame] | 28 | * Oktober 98, Rein Klazes [RHK] |
| 29 | * A program that wants to monitor the modem status line (RLSD/DCD) may |
| 30 | * poll the modem status register in the commMask structure. I update the bit |
| 31 | * in GetCommError, waiting for an implementation of communication events. |
| 32 | * |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 33 | */ |
| 34 | |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 35 | #include "config.h" |
| 36 | |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 37 | #include <stdlib.h> |
Jeremy White | d3e22d9 | 2000-02-10 19:03:02 +0000 | [diff] [blame] | 38 | #include <stdio.h> |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 39 | #include <termios.h> |
| 40 | #include <fcntl.h> |
| 41 | #include <string.h> |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 42 | #ifdef HAVE_STRINGS_H |
| 43 | # include <strings.h> |
| 44 | #endif |
Alexandre Julliard | fb9a919 | 1994-03-01 19:48:04 +0000 | [diff] [blame] | 45 | #include <errno.h> |
Alexandre Julliard | 8d24ae6 | 1994-04-05 21:42:43 +0000 | [diff] [blame] | 46 | #include <ctype.h> |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 47 | #include <sys/stat.h> |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 48 | #ifdef HAVE_SYS_FILIO_H |
| 49 | # include <sys/filio.h> |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 50 | #endif |
Alexandre Julliard | 33072e1 | 1997-06-29 18:08:02 +0000 | [diff] [blame] | 51 | #include <sys/ioctl.h> |
Alexandre Julliard | 8d24ae6 | 1994-04-05 21:42:43 +0000 | [diff] [blame] | 52 | #include <unistd.h> |
| 53 | |
Jeremy White | d3e22d9 | 2000-02-10 19:03:02 +0000 | [diff] [blame] | 54 | #include "windef.h" |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 55 | #ifdef HAVE_SYS_MODEM_H |
| 56 | # include <sys/modem.h> |
| 57 | #endif |
| 58 | #ifdef HAVE_SYS_STRTIO_H |
| 59 | # include <sys/strtio.h> |
| 60 | #endif |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 61 | #include "heap.h" |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 62 | #include "options.h" |
Dimitrie O. Paun | 5bea4f8 | 2000-11-25 01:29:00 +0000 | [diff] [blame] | 63 | #include "wine/port.h" |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 64 | #include "server.h" |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 65 | #include "winerror.h" |
Alexandre Julliard | c9c2a59 | 1999-08-01 14:46:51 +0000 | [diff] [blame] | 66 | #include "services.h" |
Alexandre Julliard | 6ec108a | 2000-03-24 21:42:15 +0000 | [diff] [blame] | 67 | #include "callback.h" |
Alexandre Julliard | c9c2a59 | 1999-08-01 14:46:51 +0000 | [diff] [blame] | 68 | #include "file.h" |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 69 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 70 | #include "debugtools.h" |
Marcus Meissner | 7bea869 | 1999-03-16 10:52:17 +0000 | [diff] [blame] | 71 | |
Jeremy White | d3e22d9 | 2000-02-10 19:03:02 +0000 | [diff] [blame] | 72 | DEFAULT_DEBUG_CHANNEL(comm); |
Patrik Stridvall | b4b9fae | 1999-04-19 14:56:29 +0000 | [diff] [blame] | 73 | |
Dimitrie O. Paun | 5bea4f8 | 2000-11-25 01:29:00 +0000 | [diff] [blame] | 74 | #if !defined(TIOCINQ) && defined(FIONREAD) |
Alexandre Julliard | 33072e1 | 1997-06-29 18:08:02 +0000 | [diff] [blame] | 75 | #define TIOCINQ FIONREAD |
| 76 | #endif |
Rein Klazes | 7f383a8 | 2000-03-30 20:23:32 +0000 | [diff] [blame] | 77 | |
| 78 | /* window's semi documented modem status register */ |
| 79 | #define COMM_MSR_OFFSET 35 |
| 80 | #define MSR_CTS 0x10 |
| 81 | #define MSR_DSR 0x20 |
| 82 | #define MSR_RI 0x40 |
| 83 | #define MSR_RLSD 0x80 |
| 84 | #define MSR_MASK (MSR_CTS|MSR_DSR|MSR_RI|MSR_RLSD) |
| 85 | |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 86 | #define FLAG_LPT 0x80 |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 87 | |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 88 | #ifdef linux |
| 89 | #define CMSPAR 0x40000000 /* stick parity */ |
| 90 | #endif |
| 91 | |
Mike McCormack | 11776c1 | 2000-10-13 17:11:30 +0000 | [diff] [blame] | 92 | #define MAX_PORTS 9 |
| 93 | |
| 94 | struct DosDeviceStruct { |
Andreas Mohr | a6d83eb | 2000-12-27 04:02:46 +0000 | [diff] [blame] | 95 | char *devicename; /* /dev/ttyS0 */ |
Mike McCormack | 11776c1 | 2000-10-13 17:11:30 +0000 | [diff] [blame] | 96 | int fd; |
| 97 | int suspended; |
| 98 | int unget,xmit; |
| 99 | int baudrate; |
| 100 | int evtchar; |
| 101 | /* events */ |
| 102 | int commerror, eventmask; |
| 103 | /* buffers */ |
| 104 | char *inbuf,*outbuf; |
| 105 | unsigned ibuf_size,ibuf_head,ibuf_tail; |
| 106 | unsigned obuf_size,obuf_head,obuf_tail; |
| 107 | /* notifications */ |
| 108 | int wnd, n_read, n_write; |
| 109 | HANDLE s_read, s_write; |
| 110 | }; |
| 111 | |
| 112 | |
| 113 | static struct DosDeviceStruct COM[MAX_PORTS]; |
| 114 | static struct DosDeviceStruct LPT[MAX_PORTS]; |
Rein Klazes | cd7986b | 1998-10-11 14:02:09 +0000 | [diff] [blame] | 115 | /* pointers to unknown(==undocumented) comm structure */ |
Mike McCormack | 11776c1 | 2000-10-13 17:11:30 +0000 | [diff] [blame] | 116 | static LPCVOID *unknown[MAX_PORTS]; |
Rein Klazes | cd7986b | 1998-10-11 14:02:09 +0000 | [diff] [blame] | 117 | /* save terminal states */ |
| 118 | static struct termios m_stat[MAX_PORTS]; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 119 | |
Rein Klazes | 7f383a8 | 2000-03-30 20:23:32 +0000 | [diff] [blame] | 120 | /* update window's semi documented modem status register */ |
| 121 | /* see knowledge base Q101417 */ |
| 122 | static void COMM_MSRUpdate( UCHAR * pMsr, unsigned int mstat) |
| 123 | { |
| 124 | UCHAR tmpmsr=0; |
Dimitrie O. Paun | 5bea4f8 | 2000-11-25 01:29:00 +0000 | [diff] [blame] | 125 | #ifdef TIOCM_CTS |
Rein Klazes | 7f383a8 | 2000-03-30 20:23:32 +0000 | [diff] [blame] | 126 | if(mstat & TIOCM_CTS) tmpmsr |= MSR_CTS; |
Dimitrie O. Paun | 5bea4f8 | 2000-11-25 01:29:00 +0000 | [diff] [blame] | 127 | #endif |
| 128 | #ifdef TIOCM_DSR |
Rein Klazes | 7f383a8 | 2000-03-30 20:23:32 +0000 | [diff] [blame] | 129 | if(mstat & TIOCM_DSR) tmpmsr |= MSR_DSR; |
Dimitrie O. Paun | 5bea4f8 | 2000-11-25 01:29:00 +0000 | [diff] [blame] | 130 | #endif |
| 131 | #ifdef TIOCM_RI |
Rein Klazes | 7f383a8 | 2000-03-30 20:23:32 +0000 | [diff] [blame] | 132 | if(mstat & TIOCM_RI) tmpmsr |= MSR_RI; |
Dimitrie O. Paun | 5bea4f8 | 2000-11-25 01:29:00 +0000 | [diff] [blame] | 133 | #endif |
| 134 | #ifdef TIOCM_CAR |
Rein Klazes | 7f383a8 | 2000-03-30 20:23:32 +0000 | [diff] [blame] | 135 | if(mstat & TIOCM_CAR) tmpmsr |= MSR_RLSD; |
Dimitrie O. Paun | 5bea4f8 | 2000-11-25 01:29:00 +0000 | [diff] [blame] | 136 | #endif |
Rein Klazes | 7f383a8 | 2000-03-30 20:23:32 +0000 | [diff] [blame] | 137 | *pMsr = (*pMsr & ~MSR_MASK) | tmpmsr; |
| 138 | } |
| 139 | |
Alexandre Julliard | 594997c | 1995-04-30 10:05:20 +0000 | [diff] [blame] | 140 | void COMM_Init(void) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 141 | { |
Alexandre Julliard | 3a405ba | 1994-10-30 16:25:19 +0000 | [diff] [blame] | 142 | int x; |
| 143 | char option[10], temp[256], *btemp; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 144 | struct stat st; |
| 145 | |
| 146 | for (x=0; x!=MAX_PORTS; x++) { |
| 147 | strcpy(option,"COMx"); |
Alexandre Julliard | 3a405ba | 1994-10-30 16:25:19 +0000 | [diff] [blame] | 148 | option[3] = '1' + x; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 149 | option[4] = '\0'; |
| 150 | |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 151 | PROFILE_GetWineIniString( "serialports", option, "*", |
| 152 | temp, sizeof(temp) ); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 153 | if (!strcmp(temp, "*") || *temp == '\0') |
Alexandre Julliard | 3a405ba | 1994-10-30 16:25:19 +0000 | [diff] [blame] | 154 | COM[x].devicename = NULL; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 155 | else { |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 156 | btemp = strchr(temp,','); |
Alexandre Julliard | 3a405ba | 1994-10-30 16:25:19 +0000 | [diff] [blame] | 157 | if (btemp != NULL) { |
| 158 | *btemp++ = '\0'; |
| 159 | COM[x].baudrate = atoi(btemp); |
| 160 | } else { |
| 161 | COM[x].baudrate = -1; |
| 162 | } |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 163 | stat(temp, &st); |
| 164 | if (!S_ISCHR(st.st_mode)) |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 165 | WARN("Can't use `%s' as %s !\n", temp, option); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 166 | else |
Alexandre Julliard | 3a405ba | 1994-10-30 16:25:19 +0000 | [diff] [blame] | 167 | if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL) |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 168 | WARN("Can't malloc for device info!\n"); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 169 | else { |
Alexandre Julliard | 3a405ba | 1994-10-30 16:25:19 +0000 | [diff] [blame] | 170 | COM[x].fd = 0; |
| 171 | strcpy(COM[x].devicename, temp); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 172 | } |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 173 | TRACE("%s = %s\n", option, COM[x].devicename); |
Alexandre Julliard | 3a405ba | 1994-10-30 16:25:19 +0000 | [diff] [blame] | 174 | } |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 175 | |
| 176 | strcpy(option, "LPTx"); |
Alexandre Julliard | 3a405ba | 1994-10-30 16:25:19 +0000 | [diff] [blame] | 177 | option[3] = '1' + x; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 178 | option[4] = '\0'; |
| 179 | |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 180 | PROFILE_GetWineIniString( "parallelports", option, "*", |
| 181 | temp, sizeof(temp) ); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 182 | if (!strcmp(temp, "*") || *temp == '\0') |
Alexandre Julliard | 3a405ba | 1994-10-30 16:25:19 +0000 | [diff] [blame] | 183 | LPT[x].devicename = NULL; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 184 | else { |
| 185 | stat(temp, &st); |
| 186 | if (!S_ISCHR(st.st_mode)) |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 187 | WARN("Can't use `%s' as %s !\n", temp, option); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 188 | else |
Alexandre Julliard | 3a405ba | 1994-10-30 16:25:19 +0000 | [diff] [blame] | 189 | if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL) |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 190 | WARN("Can't malloc for device info!\n"); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 191 | else { |
Alexandre Julliard | 3a405ba | 1994-10-30 16:25:19 +0000 | [diff] [blame] | 192 | LPT[x].fd = 0; |
| 193 | strcpy(LPT[x].devicename, temp); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 194 | } |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 195 | TRACE("%s = %s\n", option, LPT[x].devicename); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 196 | } |
| 197 | |
| 198 | } |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 199 | } |
| 200 | |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 201 | |
Patrik Stridvall | 1ed4ecf | 1999-06-26 14:58:24 +0000 | [diff] [blame] | 202 | static struct DosDeviceStruct *GetDeviceStruct(int fd) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 203 | { |
| 204 | if ((fd&0x7F)<=MAX_PORTS) { |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 205 | if (!(fd&FLAG_LPT)) { |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 206 | if (COM[fd].fd) |
| 207 | return &COM[fd]; |
| 208 | } else { |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 209 | fd &= 0x7f; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 210 | if (LPT[fd].fd) |
| 211 | return &LPT[fd]; |
| 212 | } |
| 213 | } |
| 214 | |
| 215 | return NULL; |
| 216 | } |
| 217 | |
Patrik Stridvall | 1ed4ecf | 1999-06-26 14:58:24 +0000 | [diff] [blame] | 218 | static int GetCommPort_fd(int fd) |
Alexandre Julliard | 77b9918 | 1997-09-14 17:17:23 +0000 | [diff] [blame] | 219 | { |
| 220 | int x; |
| 221 | |
| 222 | for (x=0; x<MAX_PORTS; x++) { |
| 223 | if (COM[x].fd == fd) |
| 224 | return x; |
| 225 | } |
| 226 | |
| 227 | return -1; |
| 228 | } |
| 229 | |
Patrik Stridvall | 1ed4ecf | 1999-06-26 14:58:24 +0000 | [diff] [blame] | 230 | static int ValidCOMPort(int x) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 231 | { |
| 232 | return(x < MAX_PORTS ? (int) COM[x].devicename : 0); |
| 233 | } |
| 234 | |
Patrik Stridvall | 1ed4ecf | 1999-06-26 14:58:24 +0000 | [diff] [blame] | 235 | static int ValidLPTPort(int x) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 236 | { |
| 237 | return(x < MAX_PORTS ? (int) LPT[x].devicename : 0); |
| 238 | } |
| 239 | |
Patrik Stridvall | 1ed4ecf | 1999-06-26 14:58:24 +0000 | [diff] [blame] | 240 | static int WinError(void) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 241 | { |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 242 | TRACE("errno = %d\n", errno); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 243 | switch (errno) { |
| 244 | default: |
| 245 | return CE_IOE; |
| 246 | } |
| 247 | } |
| 248 | |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 249 | static unsigned comm_inbuf(struct DosDeviceStruct *ptr) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 250 | { |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 251 | return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0) |
| 252 | + ptr->ibuf_head - ptr->ibuf_tail; |
| 253 | } |
| 254 | |
| 255 | static unsigned comm_outbuf(struct DosDeviceStruct *ptr) |
| 256 | { |
| 257 | return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0) |
| 258 | + ptr->obuf_head - ptr->obuf_tail; |
| 259 | } |
| 260 | |
Lawson Whitney | 96b93bb | 1999-04-04 12:38:35 +0000 | [diff] [blame] | 261 | static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie) |
| 262 | { |
| 263 | unsigned int mstat, okay; |
| 264 | okay = ioctl(fd, TIOCMGET, &mstat); |
| 265 | if (okay) return okay; |
| 266 | if (andy) mstat &= andy; |
| 267 | mstat |= orrie; |
| 268 | return ioctl(fd, TIOCMSET, &mstat); |
| 269 | } |
| 270 | |
Alexandre Julliard | c9c2a59 | 1999-08-01 14:46:51 +0000 | [diff] [blame] | 271 | static void CALLBACK comm_notification( ULONG_PTR private ) |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 272 | { |
| 273 | struct DosDeviceStruct *ptr = (struct DosDeviceStruct *)private; |
| 274 | int prev, bleft, len; |
| 275 | WORD mask = 0; |
Alexandre Julliard | c9c2a59 | 1999-08-01 14:46:51 +0000 | [diff] [blame] | 276 | int cid = GetCommPort_fd(ptr->fd); |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 277 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 278 | TRACE("async notification\n"); |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 279 | /* read data from comm port */ |
| 280 | prev = comm_inbuf(ptr); |
| 281 | do { |
| 282 | bleft = ((ptr->ibuf_tail > ptr->ibuf_head) ? (ptr->ibuf_tail-1) : ptr->ibuf_size) |
| 283 | - ptr->ibuf_head; |
Alexandre Julliard | c9c2a59 | 1999-08-01 14:46:51 +0000 | [diff] [blame] | 284 | len = read(ptr->fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1); |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 285 | if (len > 0) { |
| 286 | if (!bleft) { |
| 287 | ptr->commerror = CE_RXOVER; |
| 288 | } else { |
Ove Kaaven | a88444e | 1999-06-12 06:43:48 +0000 | [diff] [blame] | 289 | /* check for events */ |
| 290 | if ((ptr->eventmask & EV_RXFLAG) && |
Ove Kaaven | 1c08ac6 | 1999-07-31 13:00:24 +0000 | [diff] [blame] | 291 | memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) { |
Ove Kaaven | a88444e | 1999-06-12 06:43:48 +0000 | [diff] [blame] | 292 | *(WORD*)(unknown[cid]) |= EV_RXFLAG; |
| 293 | mask |= CN_EVENT; |
| 294 | } |
Ove Kaaven | a811ea5 | 1999-05-29 11:05:38 +0000 | [diff] [blame] | 295 | if (ptr->eventmask & EV_RXCHAR) { |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 296 | *(WORD*)(unknown[cid]) |= EV_RXCHAR; |
Ove Kaaven | a811ea5 | 1999-05-29 11:05:38 +0000 | [diff] [blame] | 297 | mask |= CN_EVENT; |
| 298 | } |
Ove Kaaven | a88444e | 1999-06-12 06:43:48 +0000 | [diff] [blame] | 299 | /* advance buffer position */ |
| 300 | ptr->ibuf_head += len; |
| 301 | if (ptr->ibuf_head >= ptr->ibuf_size) |
| 302 | ptr->ibuf_head = 0; |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 303 | } |
| 304 | } |
| 305 | } while (len > 0); |
| 306 | /* check for notification */ |
| 307 | if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) && |
| 308 | (comm_inbuf(ptr)>=ptr->n_read)) { |
| 309 | /* passed the receive notification threshold */ |
| 310 | mask |= CN_RECEIVE; |
| 311 | } |
| 312 | |
| 313 | /* write any TransmitCommChar character */ |
| 314 | if (ptr->xmit>=0) { |
Alexandre Julliard | c9c2a59 | 1999-08-01 14:46:51 +0000 | [diff] [blame] | 315 | len = write(ptr->fd, &(ptr->xmit), 1); |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 316 | if (len > 0) ptr->xmit = -1; |
| 317 | } |
| 318 | /* write from output queue */ |
| 319 | prev = comm_outbuf(ptr); |
| 320 | do { |
Ove Kaaven | e85220d | 1999-05-01 10:18:21 +0000 | [diff] [blame] | 321 | bleft = ((ptr->obuf_tail <= ptr->obuf_head) ? ptr->obuf_head : ptr->obuf_size) |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 322 | - ptr->obuf_tail; |
Alexandre Julliard | c9c2a59 | 1999-08-01 14:46:51 +0000 | [diff] [blame] | 323 | len = bleft ? write(ptr->fd, ptr->outbuf + ptr->obuf_tail, bleft) : 0; |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 324 | if (len > 0) { |
| 325 | ptr->obuf_tail += len; |
| 326 | if (ptr->obuf_tail >= ptr->obuf_size) |
| 327 | ptr->obuf_tail = 0; |
| 328 | /* flag event */ |
Ove Kaaven | 542b29d | 1999-11-25 21:57:32 +0000 | [diff] [blame] | 329 | if (ptr->obuf_tail == ptr->obuf_head) { |
| 330 | if (ptr->s_write) { |
| 331 | SERVICE_Delete( ptr->s_write ); |
| 332 | ptr->s_write = INVALID_HANDLE_VALUE; |
| 333 | } |
| 334 | if (ptr->eventmask & EV_TXEMPTY) { |
| 335 | *(WORD*)(unknown[cid]) |= EV_TXEMPTY; |
| 336 | mask |= CN_EVENT; |
| 337 | } |
Ove Kaaven | a811ea5 | 1999-05-29 11:05:38 +0000 | [diff] [blame] | 338 | } |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 339 | } |
| 340 | } while (len > 0); |
| 341 | /* check for notification */ |
| 342 | if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) && |
| 343 | (comm_outbuf(ptr)<ptr->n_write)) { |
| 344 | /* passed the transmit notification threshold */ |
| 345 | mask |= CN_TRANSMIT; |
| 346 | } |
| 347 | |
| 348 | /* send notifications, if any */ |
| 349 | if (ptr->wnd && mask) { |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 350 | TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask); |
Alexandre Julliard | 4e951ea | 2000-11-08 22:47:53 +0000 | [diff] [blame] | 351 | if (Callout.PostMessageA) Callout.PostMessageA(ptr->wnd, WM_COMMNOTIFY, cid, mask); |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 352 | } |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 353 | } |
| 354 | |
Ove Kaaven | 542b29d | 1999-11-25 21:57:32 +0000 | [diff] [blame] | 355 | static void comm_waitread(struct DosDeviceStruct *ptr) |
| 356 | { |
| 357 | if (ptr->s_read != INVALID_HANDLE_VALUE) return; |
| 358 | ptr->s_read = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd, |
| 359 | GENERIC_READ | SYNCHRONIZE ), |
| 360 | comm_notification, |
| 361 | (ULONG_PTR)ptr ); |
| 362 | } |
| 363 | |
| 364 | static void comm_waitwrite(struct DosDeviceStruct *ptr) |
| 365 | { |
| 366 | if (ptr->s_write != INVALID_HANDLE_VALUE) return; |
| 367 | ptr->s_write = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd, |
| 368 | GENERIC_WRITE | SYNCHRONIZE ), |
| 369 | comm_notification, |
| 370 | (ULONG_PTR)ptr ); |
| 371 | } |
| 372 | |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 373 | /************************************************************************** |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 374 | * BuildCommDCB16 (USER.213) |
Stefan Leichter | dcb9733 | 2000-07-09 12:19:44 +0000 | [diff] [blame] | 375 | * |
| 376 | * According to the ECMA-234 (368.3) the function will return FALSE on |
| 377 | * success, otherwise it will return -1. |
| 378 | * IF THIS IS NOT CORRECT THE RETURNVALUE CHECK IN BuildCommDCBAndTimeoutsA |
| 379 | * NEEDS TO BE FIXED |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 380 | */ |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 381 | BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 382 | { |
| 383 | /* "COM1:9600,n,8,1" */ |
| 384 | /* 012345 */ |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 385 | int port; |
Alexandre Julliard | 8d24ae6 | 1994-04-05 21:42:43 +0000 | [diff] [blame] | 386 | char *ptr, temp[256]; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 387 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 388 | TRACE("(%s), ptr %p\n", device, lpdcb); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 389 | |
Alexandre Julliard | 072dfb5 | 2000-09-25 23:30:56 +0000 | [diff] [blame] | 390 | if (!strncasecmp(device,"COM",3)) { |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 391 | port = device[3] - '0'; |
| 392 | |
Alexandre Julliard | fb9a919 | 1994-03-01 19:48:04 +0000 | [diff] [blame] | 393 | |
| 394 | if (port-- == 0) { |
Andreas Mohr | a6d83eb | 2000-12-27 04:02:46 +0000 | [diff] [blame] | 395 | ERR("BUG ! COM0 can't exist!\n"); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 396 | return -1; |
Alexandre Julliard | fb9a919 | 1994-03-01 19:48:04 +0000 | [diff] [blame] | 397 | } |
| 398 | |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 399 | if (!ValidCOMPort(port)) { |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 400 | FIXME("invalid COM port %d?\n",port); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 401 | return -1; |
| 402 | } |
| 403 | |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 404 | memset(lpdcb, 0, sizeof(DCB16)); /* initialize */ |
| 405 | |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 406 | lpdcb->Id = port; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 407 | |
| 408 | if (!*(device+4)) |
| 409 | return 0; |
| 410 | |
| 411 | if (*(device+4) != ':') |
| 412 | return -1; |
| 413 | |
| 414 | strcpy(temp,device+5); |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 415 | ptr = strtok(temp, ", "); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 416 | |
Alexandre Julliard | 3a405ba | 1994-10-30 16:25:19 +0000 | [diff] [blame] | 417 | if (COM[port].baudrate > 0) |
| 418 | lpdcb->BaudRate = COM[port].baudrate; |
| 419 | else |
| 420 | lpdcb->BaudRate = atoi(ptr); |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 421 | TRACE("baudrate (%d)\n", lpdcb->BaudRate); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 422 | |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 423 | ptr = strtok(NULL, ", "); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 424 | if (islower(*ptr)) |
| 425 | *ptr = toupper(*ptr); |
| 426 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 427 | TRACE("parity (%c)\n", *ptr); |
Cliff Wright | 28d3d21 | 1998-11-22 15:05:18 +0000 | [diff] [blame] | 428 | lpdcb->fParity = TRUE; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 429 | switch (*ptr) { |
| 430 | case 'N': |
| 431 | lpdcb->Parity = NOPARITY; |
Cliff Wright | 28d3d21 | 1998-11-22 15:05:18 +0000 | [diff] [blame] | 432 | lpdcb->fParity = FALSE; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 433 | break; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 434 | case 'E': |
| 435 | lpdcb->Parity = EVENPARITY; |
| 436 | break; |
| 437 | case 'M': |
| 438 | lpdcb->Parity = MARKPARITY; |
| 439 | break; |
| 440 | case 'O': |
| 441 | lpdcb->Parity = ODDPARITY; |
| 442 | break; |
| 443 | default: |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 444 | WARN("Unknown parity `%c'!\n", *ptr); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 445 | return -1; |
| 446 | } |
| 447 | |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 448 | ptr = strtok(NULL, ", "); |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 449 | TRACE("charsize (%c)\n", *ptr); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 450 | lpdcb->ByteSize = *ptr - '0'; |
| 451 | |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 452 | ptr = strtok(NULL, ", "); |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 453 | TRACE("stopbits (%c)\n", *ptr); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 454 | switch (*ptr) { |
| 455 | case '1': |
| 456 | lpdcb->StopBits = ONESTOPBIT; |
| 457 | break; |
| 458 | case '2': |
| 459 | lpdcb->StopBits = TWOSTOPBITS; |
| 460 | break; |
| 461 | default: |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 462 | WARN("Unknown # of stopbits `%c'!\n", *ptr); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 463 | return -1; |
| 464 | } |
| 465 | } |
| 466 | |
| 467 | return 0; |
| 468 | } |
| 469 | |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 470 | /***************************************************************************** |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 471 | * OpenComm16 (USER.200) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 472 | */ |
| 473 | INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue) |
| 474 | { |
| 475 | int port,fd; |
| 476 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 477 | TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 478 | |
Eric Pouech | f216310 | 1999-07-12 13:39:58 +0000 | [diff] [blame] | 479 | if (strlen(device) < 4) |
| 480 | return IE_BADID; |
| 481 | |
| 482 | port = device[3] - '0'; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 483 | |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 484 | if (port-- == 0) |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 485 | ERR("BUG ! COM0 or LPT0 don't exist !\n"); |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 486 | |
Alexandre Julliard | 072dfb5 | 2000-09-25 23:30:56 +0000 | [diff] [blame] | 487 | if (!strncasecmp(device,"COM",3)) { |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 488 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 489 | TRACE("%s = %s\n", device, COM[port].devicename); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 490 | |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 491 | if (!ValidCOMPort(port)) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 492 | return IE_BADID; |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 493 | |
| 494 | if (COM[port].fd) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 495 | return IE_OPEN; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 496 | |
| 497 | fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK); |
| 498 | if (fd == -1) { |
Andreas Mohr | 3496556 | 2000-08-26 20:31:48 +0000 | [diff] [blame] | 499 | ERR("Couldn't open %s ! (%s)\n", COM[port].devicename, strerror(errno)); |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 500 | return IE_HARDWARE; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 501 | } else { |
| 502 | unknown[port] = SEGPTR_ALLOC(40); |
| 503 | bzero(unknown[port],40); |
| 504 | COM[port].fd = fd; |
| 505 | COM[port].commerror = 0; |
| 506 | COM[port].eventmask = 0; |
Ove Kaaven | a88444e | 1999-06-12 06:43:48 +0000 | [diff] [blame] | 507 | COM[port].evtchar = 0; /* FIXME: default? */ |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 508 | /* save terminal state */ |
| 509 | tcgetattr(fd,&m_stat[port]); |
Rein Klazes | 58a38b8 | 1999-03-23 13:44:51 +0000 | [diff] [blame] | 510 | /* set default parameters */ |
| 511 | if(COM[port].baudrate>-1){ |
| 512 | DCB16 dcb; |
| 513 | GetCommState16(port, &dcb); |
| 514 | dcb.BaudRate=COM[port].baudrate; |
| 515 | /* more defaults: |
| 516 | * databits, parity, stopbits |
| 517 | */ |
| 518 | SetCommState16( &dcb); |
| 519 | } |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 520 | /* init priority characters */ |
| 521 | COM[port].unget = -1; |
| 522 | COM[port].xmit = -1; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 523 | /* allocate buffers */ |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 524 | COM[port].ibuf_size = cbInQueue; |
| 525 | COM[port].ibuf_head = COM[port].ibuf_tail= 0; |
| 526 | COM[port].obuf_size = cbOutQueue; |
| 527 | COM[port].obuf_head = COM[port].obuf_tail = 0; |
| 528 | |
| 529 | COM[port].inbuf = malloc(cbInQueue); |
| 530 | if (COM[port].inbuf) { |
| 531 | COM[port].outbuf = malloc(cbOutQueue); |
| 532 | if (!COM[port].outbuf) |
| 533 | free(COM[port].inbuf); |
| 534 | } else COM[port].outbuf = NULL; |
| 535 | if (!COM[port].outbuf) { |
| 536 | /* not enough memory */ |
| 537 | tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]); |
| 538 | close(COM[port].fd); |
Andreas Mohr | 217a682 | 2000-08-25 21:56:19 +0000 | [diff] [blame] | 539 | ERR("out of memory\n"); |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 540 | return IE_MEMORY; |
| 541 | } |
| 542 | |
Ove Kaaven | 542b29d | 1999-11-25 21:57:32 +0000 | [diff] [blame] | 543 | COM[port].s_read = INVALID_HANDLE_VALUE; |
| 544 | COM[port].s_write = INVALID_HANDLE_VALUE; |
| 545 | comm_waitread( &COM[port] ); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 546 | return port; |
| 547 | } |
| 548 | } |
| 549 | else |
Alexandre Julliard | 072dfb5 | 2000-09-25 23:30:56 +0000 | [diff] [blame] | 550 | if (!strncasecmp(device,"LPT",3)) { |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 551 | |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 552 | if (!ValidLPTPort(port)) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 553 | return IE_BADID; |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 554 | |
| 555 | if (LPT[port].fd) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 556 | return IE_OPEN; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 557 | |
| 558 | fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0); |
| 559 | if (fd == -1) { |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 560 | return IE_HARDWARE; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 561 | } else { |
| 562 | LPT[port].fd = fd; |
| 563 | LPT[port].commerror = 0; |
| 564 | LPT[port].eventmask = 0; |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 565 | return port|FLAG_LPT; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 566 | } |
| 567 | } |
| 568 | return 0; |
| 569 | } |
| 570 | |
| 571 | /***************************************************************************** |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 572 | * CloseComm16 (USER.207) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 573 | */ |
| 574 | INT16 WINAPI CloseComm16(INT16 cid) |
| 575 | { |
| 576 | struct DosDeviceStruct *ptr; |
| 577 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 578 | TRACE("cid=%d\n", cid); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 579 | if ((ptr = GetDeviceStruct(cid)) == NULL) { |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 580 | FIXME("no cid=%d found!\n", cid); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 581 | return -1; |
| 582 | } |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 583 | if (!(cid&FLAG_LPT)) { |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 584 | /* COM port */ |
| 585 | SEGPTR_FREE(unknown[cid]); /* [LW] */ |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 586 | |
Ove Kaaven | 542b29d | 1999-11-25 21:57:32 +0000 | [diff] [blame] | 587 | SERVICE_Delete( COM[cid].s_write ); |
| 588 | SERVICE_Delete( COM[cid].s_read ); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 589 | /* free buffers */ |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 590 | free(ptr->outbuf); |
| 591 | free(ptr->inbuf); |
| 592 | |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 593 | /* reset modem lines */ |
| 594 | tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]); |
| 595 | } |
| 596 | |
| 597 | if (close(ptr->fd) == -1) { |
| 598 | ptr->commerror = WinError(); |
| 599 | /* FIXME: should we clear ptr->fd here? */ |
| 600 | return -1; |
| 601 | } else { |
| 602 | ptr->commerror = 0; |
| 603 | ptr->fd = 0; |
| 604 | return 0; |
| 605 | } |
| 606 | } |
| 607 | |
| 608 | /***************************************************************************** |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 609 | * SetCommBreak16 (USER.210) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 610 | */ |
| 611 | INT16 WINAPI SetCommBreak16(INT16 cid) |
| 612 | { |
| 613 | struct DosDeviceStruct *ptr; |
| 614 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 615 | TRACE("cid=%d\n", cid); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 616 | if ((ptr = GetDeviceStruct(cid)) == NULL) { |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 617 | FIXME("no cid=%d found!\n", cid); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 618 | return -1; |
| 619 | } |
| 620 | |
| 621 | ptr->suspended = 1; |
| 622 | ptr->commerror = 0; |
| 623 | return 0; |
| 624 | } |
| 625 | |
| 626 | /***************************************************************************** |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 627 | * ClearCommBreak16 (USER.211) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 628 | */ |
| 629 | INT16 WINAPI ClearCommBreak16(INT16 cid) |
| 630 | { |
| 631 | struct DosDeviceStruct *ptr; |
| 632 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 633 | TRACE("cid=%d\n", cid); |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 634 | if (!(ptr = GetDeviceStruct(cid))) { |
| 635 | FIXME("no cid=%d found!\n", cid); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 636 | return -1; |
| 637 | } |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 638 | ptr->suspended = 0; |
| 639 | ptr->commerror = 0; |
| 640 | return 0; |
| 641 | } |
| 642 | |
| 643 | /***************************************************************************** |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 644 | * EscapeCommFunction16 (USER.214) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 645 | */ |
| 646 | LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction) |
| 647 | { |
| 648 | int max; |
| 649 | struct DosDeviceStruct *ptr; |
| 650 | struct termios port; |
| 651 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 652 | TRACE("cid=%d, function=%d\n", cid, nFunction); |
Ove Kaaven | 1c08ac6 | 1999-07-31 13:00:24 +0000 | [diff] [blame] | 653 | if ((nFunction != GETMAXCOM) && (nFunction != GETMAXLPT)) { |
| 654 | if ((ptr = GetDeviceStruct(cid)) == NULL) { |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 655 | FIXME("no cid=%d found!\n", cid); |
Ove Kaaven | 1c08ac6 | 1999-07-31 13:00:24 +0000 | [diff] [blame] | 656 | return -1; |
| 657 | } |
| 658 | if (tcgetattr(ptr->fd,&port) == -1) { |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 659 | TRACE("tcgetattr failed\n"); |
Ove Kaaven | 1c08ac6 | 1999-07-31 13:00:24 +0000 | [diff] [blame] | 660 | ptr->commerror=WinError(); |
| 661 | return -1; |
| 662 | } |
| 663 | } else ptr = NULL; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 664 | |
| 665 | switch (nFunction) { |
| 666 | case RESETDEV: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 667 | TRACE("RESETDEV\n"); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 668 | break; |
| 669 | |
| 670 | case GETMAXCOM: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 671 | TRACE("GETMAXCOM\n"); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 672 | for (max = MAX_PORTS;!COM[max].devicename;max--) |
| 673 | ; |
| 674 | return max; |
| 675 | break; |
| 676 | |
| 677 | case GETMAXLPT: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 678 | TRACE("GETMAXLPT\n"); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 679 | for (max = MAX_PORTS;!LPT[max].devicename;max--) |
| 680 | ; |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 681 | return FLAG_LPT + max; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 682 | break; |
| 683 | |
Ove Kaaven | 1c08ac6 | 1999-07-31 13:00:24 +0000 | [diff] [blame] | 684 | case GETBASEIRQ: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 685 | TRACE("GETBASEIRQ\n"); |
Ove Kaaven | 1c08ac6 | 1999-07-31 13:00:24 +0000 | [diff] [blame] | 686 | /* FIXME: use tables */ |
| 687 | /* just fake something for now */ |
| 688 | if (cid & FLAG_LPT) { |
| 689 | /* LPT1: irq 7, LPT2: irq 5 */ |
| 690 | return (cid & 0x7f) ? 5 : 7; |
| 691 | } else { |
| 692 | /* COM1: irq 4, COM2: irq 3, |
| 693 | COM3: irq 4, COM4: irq 3 */ |
| 694 | return 4 - (cid & 1); |
| 695 | } |
| 696 | break; |
| 697 | |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 698 | case CLRDTR: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 699 | TRACE("CLRDTR\n"); |
| 700 | #ifdef TIOCM_DTR |
Lawson Whitney | 96b93bb | 1999-04-04 12:38:35 +0000 | [diff] [blame] | 701 | return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 702 | #endif |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 703 | case CLRRTS: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 704 | TRACE("CLRRTS\n"); |
| 705 | #ifdef TIOCM_RTS |
Lawson Whitney | 96b93bb | 1999-04-04 12:38:35 +0000 | [diff] [blame] | 706 | return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 707 | #endif |
| 708 | |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 709 | case SETDTR: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 710 | TRACE("SETDTR\n"); |
| 711 | #ifdef TIOCM_DTR |
Lawson Whitney | 96b93bb | 1999-04-04 12:38:35 +0000 | [diff] [blame] | 712 | return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR); |
| 713 | #endif |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 714 | |
| 715 | case SETRTS: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 716 | TRACE("SETRTS\n"); |
| 717 | #ifdef TIOCM_RTS |
Lawson Whitney | 96b93bb | 1999-04-04 12:38:35 +0000 | [diff] [blame] | 718 | return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 719 | #endif |
| 720 | |
| 721 | case SETXOFF: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 722 | TRACE("SETXOFF\n"); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 723 | port.c_iflag |= IXOFF; |
| 724 | break; |
| 725 | |
| 726 | case SETXON: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 727 | TRACE("SETXON\n"); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 728 | port.c_iflag |= IXON; |
| 729 | break; |
| 730 | |
| 731 | default: |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 732 | WARN("(cid=%d,nFunction=%d): Unknown function\n", |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 733 | cid, nFunction); |
| 734 | break; |
| 735 | } |
| 736 | |
| 737 | if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) { |
| 738 | ptr->commerror = WinError(); |
| 739 | return -1; |
| 740 | } else { |
| 741 | ptr->commerror = 0; |
| 742 | return 0; |
| 743 | } |
| 744 | } |
| 745 | |
| 746 | /***************************************************************************** |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 747 | * FlushComm16 (USER.215) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 748 | */ |
| 749 | INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue) |
| 750 | { |
| 751 | int queue; |
| 752 | struct DosDeviceStruct *ptr; |
| 753 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 754 | TRACE("cid=%d, queue=%d\n", cid, fnQueue); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 755 | if ((ptr = GetDeviceStruct(cid)) == NULL) { |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 756 | FIXME("no cid=%d found!\n", cid); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 757 | return -1; |
| 758 | } |
| 759 | switch (fnQueue) { |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 760 | case 0: |
| 761 | queue = TCOFLUSH; |
| 762 | ptr->obuf_tail = ptr->obuf_head; |
| 763 | break; |
| 764 | case 1: |
| 765 | queue = TCIFLUSH; |
| 766 | ptr->ibuf_head = ptr->ibuf_tail; |
| 767 | break; |
| 768 | default: |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 769 | WARN("(cid=%d,fnQueue=%d):Unknown queue\n", |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 770 | cid, fnQueue); |
| 771 | return -1; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 772 | } |
| 773 | if (tcflush(ptr->fd, queue)) { |
| 774 | ptr->commerror = WinError(); |
| 775 | return -1; |
| 776 | } else { |
| 777 | ptr->commerror = 0; |
| 778 | return 0; |
| 779 | } |
| 780 | } |
| 781 | |
| 782 | /******************************************************************** |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 783 | * GetCommError16 (USER.203) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 784 | */ |
| 785 | INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat) |
| 786 | { |
| 787 | int temperror; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 788 | struct DosDeviceStruct *ptr; |
| 789 | unsigned char *stol; |
| 790 | unsigned int mstat; |
| 791 | |
| 792 | if ((ptr = GetDeviceStruct(cid)) == NULL) { |
Andreas Mohr | a6d83eb | 2000-12-27 04:02:46 +0000 | [diff] [blame] | 793 | FIXME("no handle for cid = %0x!\n",cid); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 794 | return -1; |
| 795 | } |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 796 | if (cid&FLAG_LPT) { |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 797 | WARN(" cid %d not comm port\n",cid); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 798 | return CE_MODE; |
| 799 | } |
| 800 | stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET; |
| 801 | ioctl(ptr->fd,TIOCMGET,&mstat); |
Rein Klazes | 7f383a8 | 2000-03-30 20:23:32 +0000 | [diff] [blame] | 802 | COMM_MSRUpdate( stol, mstat); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 803 | |
| 804 | if (lpStat) { |
| 805 | lpStat->status = 0; |
| 806 | |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 807 | lpStat->cbOutQue = comm_outbuf(ptr); |
| 808 | lpStat->cbInQue = comm_inbuf(ptr); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 809 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 810 | TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n", |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 811 | cid, ptr->commerror, lpStat->status, lpStat->cbInQue, |
| 812 | lpStat->cbOutQue, *stol); |
| 813 | } |
| 814 | else |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 815 | TRACE("cid %d, error %d, lpStat NULL stol %x\n", |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 816 | cid, ptr->commerror, *stol); |
| 817 | |
| 818 | /* Return any errors and clear it */ |
| 819 | temperror = ptr->commerror; |
| 820 | ptr->commerror = 0; |
| 821 | return(temperror); |
| 822 | } |
| 823 | |
| 824 | /***************************************************************************** |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 825 | * SetCommEventMask16 (USER.208) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 826 | */ |
| 827 | SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask) |
| 828 | { |
| 829 | struct DosDeviceStruct *ptr; |
| 830 | unsigned char *stol; |
| 831 | int repid; |
| 832 | unsigned int mstat; |
| 833 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 834 | TRACE("cid %d,mask %d\n",cid,fuEvtMask); |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 835 | if ((ptr = GetDeviceStruct(cid)) == NULL) { |
Andreas Mohr | a6d83eb | 2000-12-27 04:02:46 +0000 | [diff] [blame] | 836 | FIXME("no handle for cid = %0x!\n",cid); |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 837 | return (SEGPTR)NULL; |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 838 | } |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 839 | |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 840 | ptr->eventmask = fuEvtMask; |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 841 | |
| 842 | if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) { |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 843 | WARN(" cid %d not comm port\n",cid); |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 844 | return (SEGPTR)NULL; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 845 | } |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 846 | /* it's a COM port ? -> modify flags */ |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 847 | stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET; |
| 848 | repid = ioctl(ptr->fd,TIOCMGET,&mstat); |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 849 | TRACE(" ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]); |
Rein Klazes | 7f383a8 | 2000-03-30 20:23:32 +0000 | [diff] [blame] | 850 | COMM_MSRUpdate( stol, mstat); |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 851 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 852 | TRACE(" modem dcd construct %x\n",*stol); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 853 | return SEGPTR_GET(unknown[cid]); |
| 854 | } |
| 855 | |
| 856 | /***************************************************************************** |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 857 | * GetCommEventMask16 (USER.209) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 858 | */ |
| 859 | UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear) |
| 860 | { |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 861 | struct DosDeviceStruct *ptr; |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 862 | WORD events; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 863 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 864 | TRACE("cid %d, mask %d\n", cid, fnEvtClear); |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 865 | if ((ptr = GetDeviceStruct(cid)) == NULL) { |
Andreas Mohr | a6d83eb | 2000-12-27 04:02:46 +0000 | [diff] [blame] | 866 | FIXME("no handle for cid = %0x!\n",cid); |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 867 | return 0; |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 868 | } |
Andreas Mohr | eed0494 | 1999-04-11 18:47:07 +0000 | [diff] [blame] | 869 | |
| 870 | if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) { |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 871 | WARN(" cid %d not comm port\n",cid); |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 872 | return 0; |
| 873 | } |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 874 | |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 875 | events = *(WORD*)(unknown[cid]) & fnEvtClear; |
| 876 | *(WORD*)(unknown[cid]) &= ~fnEvtClear; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 877 | return events; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 878 | } |
| 879 | |
| 880 | /***************************************************************************** |
| 881 | * SetCommState16 (USER.201) |
| 882 | */ |
| 883 | INT16 WINAPI SetCommState16(LPDCB16 lpdcb) |
| 884 | { |
| 885 | struct termios port; |
| 886 | struct DosDeviceStruct *ptr; |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 887 | int bytesize, stopbits; |
| 888 | int fail=0; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 889 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 890 | TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 891 | if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) { |
Andreas Mohr | a6d83eb | 2000-12-27 04:02:46 +0000 | [diff] [blame] | 892 | FIXME("no handle for cid = %0x!\n",lpdcb->Id); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 893 | return -1; |
| 894 | } |
| 895 | if (tcgetattr(ptr->fd, &port) == -1) { |
| 896 | ptr->commerror = WinError(); |
| 897 | return -1; |
| 898 | } |
| 899 | |
| 900 | port.c_cc[VMIN] = 0; |
| 901 | port.c_cc[VTIME] = 1; |
| 902 | |
| 903 | #ifdef IMAXBEL |
| 904 | port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL); |
| 905 | #else |
| 906 | port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR); |
| 907 | #endif |
| 908 | port.c_iflag |= (IGNBRK); |
| 909 | |
| 910 | port.c_oflag &= ~(OPOST); |
| 911 | |
| 912 | port.c_cflag &= ~(HUPCL); |
| 913 | port.c_cflag |= CLOCAL | CREAD; |
| 914 | |
| 915 | port.c_lflag &= ~(ICANON|ECHO|ISIG); |
| 916 | port.c_lflag |= NOFLSH; |
| 917 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 918 | TRACE("baudrate %d\n",lpdcb->BaudRate); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 919 | #ifdef CBAUD |
| 920 | port.c_cflag &= ~CBAUD; |
| 921 | switch (lpdcb->BaudRate) { |
| 922 | case 110: |
| 923 | case CBR_110: |
| 924 | port.c_cflag |= B110; |
| 925 | break; |
| 926 | case 300: |
| 927 | case CBR_300: |
| 928 | port.c_cflag |= B300; |
| 929 | break; |
| 930 | case 600: |
| 931 | case CBR_600: |
| 932 | port.c_cflag |= B600; |
| 933 | break; |
| 934 | case 1200: |
| 935 | case CBR_1200: |
| 936 | port.c_cflag |= B1200; |
| 937 | break; |
| 938 | case 2400: |
| 939 | case CBR_2400: |
| 940 | port.c_cflag |= B2400; |
| 941 | break; |
| 942 | case 4800: |
| 943 | case CBR_4800: |
| 944 | port.c_cflag |= B4800; |
| 945 | break; |
| 946 | case 9600: |
| 947 | case CBR_9600: |
| 948 | port.c_cflag |= B9600; |
| 949 | break; |
| 950 | case 19200: |
| 951 | case CBR_19200: |
| 952 | port.c_cflag |= B19200; |
| 953 | break; |
| 954 | case 38400: |
| 955 | case CBR_38400: |
| 956 | port.c_cflag |= B38400; |
| 957 | break; |
| 958 | #ifdef B57600 |
| 959 | case 57600: |
| 960 | port.c_cflag |= B57600; |
| 961 | break; |
| 962 | #endif |
| 963 | #ifdef B115200 |
| 964 | case 57601: |
| 965 | port.c_cflag |= B115200; |
| 966 | break; |
| 967 | #endif |
| 968 | default: |
| 969 | ptr->commerror = IE_BAUDRATE; |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 970 | fail=1; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 971 | } |
| 972 | #elif !defined(__EMX__) |
| 973 | switch (lpdcb->BaudRate) { |
| 974 | case 110: |
| 975 | case CBR_110: |
| 976 | port.c_ospeed = B110; |
| 977 | break; |
| 978 | case 300: |
| 979 | case CBR_300: |
| 980 | port.c_ospeed = B300; |
| 981 | break; |
| 982 | case 600: |
| 983 | case CBR_600: |
| 984 | port.c_ospeed = B600; |
| 985 | break; |
| 986 | case 1200: |
| 987 | case CBR_1200: |
| 988 | port.c_ospeed = B1200; |
| 989 | break; |
| 990 | case 2400: |
| 991 | case CBR_2400: |
| 992 | port.c_ospeed = B2400; |
| 993 | break; |
| 994 | case 4800: |
| 995 | case CBR_4800: |
| 996 | port.c_ospeed = B4800; |
| 997 | break; |
| 998 | case 9600: |
| 999 | case CBR_9600: |
| 1000 | port.c_ospeed = B9600; |
| 1001 | break; |
| 1002 | case 19200: |
| 1003 | case CBR_19200: |
| 1004 | port.c_ospeed = B19200; |
| 1005 | break; |
| 1006 | case 38400: |
| 1007 | case CBR_38400: |
| 1008 | port.c_ospeed = B38400; |
| 1009 | break; |
| 1010 | default: |
| 1011 | ptr->commerror = IE_BAUDRATE; |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 1012 | fail=1; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1013 | } |
| 1014 | port.c_ispeed = port.c_ospeed; |
| 1015 | #endif |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 1016 | bytesize=lpdcb->ByteSize; |
| 1017 | stopbits=lpdcb->StopBits; |
| 1018 | |
| 1019 | TRACE("fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity); |
| 1020 | #ifdef CMSPAR |
| 1021 | port.c_cflag &= ~(PARENB | PARODD | CMSPAR); |
| 1022 | #else |
| 1023 | port.c_cflag &= ~(PARENB | PARODD); |
| 1024 | #endif |
| 1025 | if (lpdcb->fParity) |
| 1026 | port.c_iflag |= INPCK; |
| 1027 | else |
| 1028 | port.c_iflag &= ~INPCK; |
| 1029 | switch (lpdcb->Parity) { |
| 1030 | case NOPARITY: |
| 1031 | break; |
| 1032 | case ODDPARITY: |
| 1033 | port.c_cflag |= (PARENB | PARODD); |
| 1034 | break; |
| 1035 | case EVENPARITY: |
| 1036 | port.c_cflag |= PARENB; |
| 1037 | break; |
| 1038 | #ifdef CMSPAR |
| 1039 | /* Linux defines mark/space (stick) parity */ |
| 1040 | case MARKPARITY: |
| 1041 | port.c_cflag |= (PARENB | CMSPAR); |
| 1042 | break; |
| 1043 | case SPACEPARITY: |
| 1044 | port.c_cflag |= (PARENB | PARODD | CMSPAR); |
| 1045 | break; |
| 1046 | #else |
| 1047 | /* try the POSIX way */ |
| 1048 | case MARKPARITY: |
| 1049 | if( stopbits == ONESTOPBIT) { |
| 1050 | stopbits = TWOSTOPBITS; |
| 1051 | port.c_iflag &= ~INPCK; |
| 1052 | } else { |
| 1053 | ptr->commerror = IE_BYTESIZE; |
| 1054 | fail=1; |
| 1055 | } |
| 1056 | break; |
| 1057 | case SPACEPARITY: |
| 1058 | if( bytesize < 8) { |
| 1059 | bytesize +=1; |
| 1060 | port.c_iflag &= ~INPCK; |
| 1061 | } else { |
| 1062 | ptr->commerror = IE_BYTESIZE; |
| 1063 | fail=1; |
| 1064 | } |
| 1065 | break; |
| 1066 | #endif |
| 1067 | default: |
| 1068 | ptr->commerror = IE_BYTESIZE; |
| 1069 | fail=1; |
| 1070 | } |
| 1071 | |
| 1072 | TRACE("bytesize %d\n",bytesize); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1073 | port.c_cflag &= ~CSIZE; |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 1074 | switch (bytesize) { |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1075 | case 5: |
| 1076 | port.c_cflag |= CS5; |
| 1077 | break; |
| 1078 | case 6: |
| 1079 | port.c_cflag |= CS6; |
| 1080 | break; |
| 1081 | case 7: |
| 1082 | port.c_cflag |= CS7; |
| 1083 | break; |
| 1084 | case 8: |
| 1085 | port.c_cflag |= CS8; |
| 1086 | break; |
| 1087 | default: |
| 1088 | ptr->commerror = IE_BYTESIZE; |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 1089 | fail=1; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1090 | } |
| 1091 | |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 1092 | TRACE("stopbits %d\n",stopbits); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1093 | |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 1094 | switch (stopbits) { |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1095 | case ONESTOPBIT: |
| 1096 | port.c_cflag &= ~CSTOPB; |
| 1097 | break; |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 1098 | case ONE5STOPBITS: /* wil be selected if bytesize is 5 */ |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1099 | case TWOSTOPBITS: |
| 1100 | port.c_cflag |= CSTOPB; |
| 1101 | break; |
| 1102 | default: |
| 1103 | ptr->commerror = IE_BYTESIZE; |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 1104 | fail=1; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1105 | } |
| 1106 | #ifdef CRTSCTS |
| 1107 | |
| 1108 | if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow) |
| 1109 | port.c_cflag |= CRTSCTS; |
| 1110 | |
| 1111 | if (lpdcb->fDtrDisable) |
| 1112 | port.c_cflag &= ~CRTSCTS; |
| 1113 | #endif |
| 1114 | if (lpdcb->fInX) |
| 1115 | port.c_iflag |= IXON; |
| 1116 | else |
| 1117 | port.c_iflag &= ~IXON; |
| 1118 | if (lpdcb->fOutX) |
| 1119 | port.c_iflag |= IXOFF; |
| 1120 | else |
| 1121 | port.c_iflag &= ~IXOFF; |
| 1122 | |
Ove Kaaven | a88444e | 1999-06-12 06:43:48 +0000 | [diff] [blame] | 1123 | ptr->evtchar = lpdcb->EvtChar; |
| 1124 | |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 1125 | if(fail) |
| 1126 | return -1; |
| 1127 | |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1128 | if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) { |
| 1129 | ptr->commerror = WinError(); |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 1130 | return -1; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1131 | } else { |
| 1132 | ptr->commerror = 0; |
| 1133 | return 0; |
| 1134 | } |
| 1135 | } |
| 1136 | |
| 1137 | /***************************************************************************** |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 1138 | * GetCommState16 (USER.202) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1139 | */ |
| 1140 | INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb) |
| 1141 | { |
Patrik Stridvall | fe28f25 | 1999-09-23 11:44:52 +0000 | [diff] [blame] | 1142 | int speed; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1143 | struct DosDeviceStruct *ptr; |
| 1144 | struct termios port; |
| 1145 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1146 | TRACE("cid %d, ptr %p\n", cid, lpdcb); |
Rein Klazes | 58a38b8 | 1999-03-23 13:44:51 +0000 | [diff] [blame] | 1147 | if ((ptr = GetDeviceStruct(cid)) == NULL) { |
Andreas Mohr | a6d83eb | 2000-12-27 04:02:46 +0000 | [diff] [blame] | 1148 | FIXME("no handle for cid = %0x!\n",cid); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1149 | return -1; |
| 1150 | } |
| 1151 | if (tcgetattr(ptr->fd, &port) == -1) { |
| 1152 | ptr->commerror = WinError(); |
| 1153 | return -1; |
| 1154 | } |
| 1155 | lpdcb->Id = cid; |
| 1156 | #ifndef __EMX__ |
| 1157 | #ifdef CBAUD |
Patrik Stridvall | fe28f25 | 1999-09-23 11:44:52 +0000 | [diff] [blame] | 1158 | speed = port.c_cflag & CBAUD; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1159 | #else |
Patrik Stridvall | fe28f25 | 1999-09-23 11:44:52 +0000 | [diff] [blame] | 1160 | speed = port.c_ospeed; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1161 | #endif |
Patrik Stridvall | fe28f25 | 1999-09-23 11:44:52 +0000 | [diff] [blame] | 1162 | switch(speed) { |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1163 | case B110: |
| 1164 | lpdcb->BaudRate = 110; |
| 1165 | break; |
| 1166 | case B300: |
| 1167 | lpdcb->BaudRate = 300; |
| 1168 | break; |
| 1169 | case B600: |
| 1170 | lpdcb->BaudRate = 600; |
| 1171 | break; |
| 1172 | case B1200: |
| 1173 | lpdcb->BaudRate = 1200; |
| 1174 | break; |
| 1175 | case B2400: |
| 1176 | lpdcb->BaudRate = 2400; |
| 1177 | break; |
| 1178 | case B4800: |
| 1179 | lpdcb->BaudRate = 4800; |
| 1180 | break; |
| 1181 | case B9600: |
| 1182 | lpdcb->BaudRate = 9600; |
| 1183 | break; |
| 1184 | case B19200: |
| 1185 | lpdcb->BaudRate = 19200; |
| 1186 | break; |
| 1187 | case B38400: |
| 1188 | lpdcb->BaudRate = 38400; |
| 1189 | break; |
| 1190 | #ifdef B57600 |
| 1191 | case B57600: |
| 1192 | lpdcb->BaudRate = 57600; |
| 1193 | break; |
| 1194 | #endif |
| 1195 | #ifdef B115200 |
| 1196 | case B115200: |
| 1197 | lpdcb->BaudRate = 57601; |
| 1198 | break; |
| 1199 | #endif |
| 1200 | } |
| 1201 | #endif |
| 1202 | switch (port.c_cflag & CSIZE) { |
| 1203 | case CS5: |
| 1204 | lpdcb->ByteSize = 5; |
| 1205 | break; |
| 1206 | case CS6: |
| 1207 | lpdcb->ByteSize = 6; |
| 1208 | break; |
| 1209 | case CS7: |
| 1210 | lpdcb->ByteSize = 7; |
| 1211 | break; |
| 1212 | case CS8: |
| 1213 | lpdcb->ByteSize = 8; |
| 1214 | break; |
| 1215 | } |
| 1216 | |
Rein Klazes | 58a38b8 | 1999-03-23 13:44:51 +0000 | [diff] [blame] | 1217 | if(port.c_iflag & INPCK) |
| 1218 | lpdcb->fParity = TRUE; |
| 1219 | else |
| 1220 | lpdcb->fParity = FALSE; |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 1221 | #ifdef CMSPAR |
Patrik Stridvall | c77ff5e | 2000-04-29 14:26:13 +0000 | [diff] [blame] | 1222 | switch (port.c_cflag & (PARENB | PARODD | CMSPAR)) |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 1223 | #else |
Patrik Stridvall | c77ff5e | 2000-04-29 14:26:13 +0000 | [diff] [blame] | 1224 | switch (port.c_cflag & (PARENB | PARODD)) |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 1225 | #endif |
Patrik Stridvall | c77ff5e | 2000-04-29 14:26:13 +0000 | [diff] [blame] | 1226 | { |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1227 | case 0: |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1228 | lpdcb->Parity = NOPARITY; |
| 1229 | break; |
| 1230 | case PARENB: |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1231 | lpdcb->Parity = EVENPARITY; |
| 1232 | break; |
| 1233 | case (PARENB | PARODD): |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1234 | lpdcb->Parity = ODDPARITY; |
| 1235 | break; |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 1236 | #ifdef CMSPAR |
| 1237 | case (PARENB | CMSPAR): |
| 1238 | lpdcb->Parity = MARKPARITY; |
| 1239 | break; |
| 1240 | case (PARENB | PARODD | CMSPAR): |
| 1241 | lpdcb->Parity = SPACEPARITY; |
| 1242 | break; |
| 1243 | #endif |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1244 | } |
| 1245 | |
| 1246 | if (port.c_cflag & CSTOPB) |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 1247 | if(lpdcb->ByteSize == 5) |
| 1248 | lpdcb->StopBits = ONE5STOPBITS; |
| 1249 | else |
| 1250 | lpdcb->StopBits = TWOSTOPBITS; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1251 | else |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 1252 | lpdcb->StopBits = ONESTOPBIT; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1253 | |
| 1254 | lpdcb->RlsTimeout = 50; |
| 1255 | lpdcb->CtsTimeout = 50; |
| 1256 | lpdcb->DsrTimeout = 50; |
| 1257 | lpdcb->fNull = 0; |
| 1258 | lpdcb->fChEvt = 0; |
| 1259 | lpdcb->fBinary = 1; |
| 1260 | lpdcb->fDtrDisable = 0; |
| 1261 | |
| 1262 | #ifdef CRTSCTS |
| 1263 | |
| 1264 | if (port.c_cflag & CRTSCTS) { |
| 1265 | lpdcb->fDtrflow = 1; |
| 1266 | lpdcb->fRtsflow = 1; |
| 1267 | lpdcb->fOutxCtsFlow = 1; |
| 1268 | lpdcb->fOutxDsrFlow = 1; |
| 1269 | } else |
| 1270 | #endif |
| 1271 | lpdcb->fDtrDisable = 1; |
| 1272 | |
| 1273 | if (port.c_iflag & IXON) |
| 1274 | lpdcb->fInX = 1; |
| 1275 | else |
| 1276 | lpdcb->fInX = 0; |
| 1277 | |
| 1278 | if (port.c_iflag & IXOFF) |
| 1279 | lpdcb->fOutX = 1; |
| 1280 | else |
| 1281 | lpdcb->fOutX = 0; |
| 1282 | /* |
| 1283 | lpdcb->XonChar = |
| 1284 | lpdcb->XoffChar = |
| 1285 | */ |
| 1286 | lpdcb->XonLim = 10; |
| 1287 | lpdcb->XoffLim = 10; |
| 1288 | |
Ove Kaaven | a88444e | 1999-06-12 06:43:48 +0000 | [diff] [blame] | 1289 | lpdcb->EvtChar = ptr->evtchar; |
| 1290 | |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1291 | ptr->commerror = 0; |
| 1292 | return 0; |
| 1293 | } |
| 1294 | |
| 1295 | /***************************************************************************** |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 1296 | * TransmitCommChar16 (USER.206) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1297 | */ |
| 1298 | INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit) |
| 1299 | { |
| 1300 | struct DosDeviceStruct *ptr; |
| 1301 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1302 | TRACE("cid %d, data %d \n", cid, chTransmit); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1303 | if ((ptr = GetDeviceStruct(cid)) == NULL) { |
Andreas Mohr | a6d83eb | 2000-12-27 04:02:46 +0000 | [diff] [blame] | 1304 | FIXME("no handle for cid = %0x!\n",cid); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1305 | return -1; |
| 1306 | } |
| 1307 | |
| 1308 | if (ptr->suspended) { |
| 1309 | ptr->commerror = IE_HARDWARE; |
| 1310 | return -1; |
| 1311 | } |
| 1312 | |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 1313 | if (ptr->xmit >= 0) { |
| 1314 | /* character already queued */ |
| 1315 | /* FIXME: which error would Windows return? */ |
| 1316 | ptr->commerror = CE_TXFULL; |
| 1317 | return -1; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1318 | } |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 1319 | |
| 1320 | if (ptr->obuf_head == ptr->obuf_tail) { |
| 1321 | /* transmit queue empty, try to transmit directly */ |
| 1322 | if (write(ptr->fd, &chTransmit, 1) == -1) { |
| 1323 | /* didn't work, queue it */ |
| 1324 | ptr->xmit = chTransmit; |
Ove Kaaven | 542b29d | 1999-11-25 21:57:32 +0000 | [diff] [blame] | 1325 | comm_waitwrite(ptr); |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 1326 | } |
| 1327 | } else { |
| 1328 | /* data in queue, let this char be transmitted next */ |
| 1329 | ptr->xmit = chTransmit; |
Ove Kaaven | 542b29d | 1999-11-25 21:57:32 +0000 | [diff] [blame] | 1330 | comm_waitwrite(ptr); |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 1331 | } |
| 1332 | |
| 1333 | ptr->commerror = 0; |
| 1334 | return 0; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1335 | } |
| 1336 | |
| 1337 | /***************************************************************************** |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 1338 | * UngetCommChar16 (USER.212) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1339 | */ |
| 1340 | INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget) |
| 1341 | { |
| 1342 | struct DosDeviceStruct *ptr; |
| 1343 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1344 | TRACE("cid %d (char %d)\n", cid, chUnget); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1345 | if ((ptr = GetDeviceStruct(cid)) == NULL) { |
Andreas Mohr | a6d83eb | 2000-12-27 04:02:46 +0000 | [diff] [blame] | 1346 | FIXME("no handle for cid = %0x!\n",cid); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1347 | return -1; |
| 1348 | } |
| 1349 | |
| 1350 | if (ptr->suspended) { |
| 1351 | ptr->commerror = IE_HARDWARE; |
| 1352 | return -1; |
| 1353 | } |
| 1354 | |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 1355 | if (ptr->unget>=0) { |
| 1356 | /* character already queued */ |
| 1357 | /* FIXME: which error would Windows return? */ |
| 1358 | ptr->commerror = CE_RXOVER; |
| 1359 | return -1; |
| 1360 | } |
| 1361 | |
| 1362 | ptr->unget = chUnget; |
| 1363 | |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1364 | ptr->commerror = 0; |
| 1365 | return 0; |
| 1366 | } |
| 1367 | |
| 1368 | /***************************************************************************** |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 1369 | * ReadComm16 (USER.204) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1370 | */ |
| 1371 | INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead) |
| 1372 | { |
| 1373 | int status, length; |
| 1374 | struct DosDeviceStruct *ptr; |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 1375 | LPSTR orgBuf = lpvBuf; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1376 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1377 | TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1378 | if ((ptr = GetDeviceStruct(cid)) == NULL) { |
Andreas Mohr | a6d83eb | 2000-12-27 04:02:46 +0000 | [diff] [blame] | 1379 | FIXME("no handle for cid = %0x!\n",cid); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1380 | return -1; |
| 1381 | } |
| 1382 | |
| 1383 | if (ptr->suspended) { |
| 1384 | ptr->commerror = IE_HARDWARE; |
| 1385 | return -1; |
| 1386 | } |
| 1387 | |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 1388 | /* read unget character */ |
| 1389 | if (ptr->unget>=0) { |
| 1390 | *lpvBuf++ = ptr->unget; |
| 1391 | ptr->unget = -1; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1392 | |
| 1393 | length = 1; |
| 1394 | } else |
| 1395 | length = 0; |
| 1396 | |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 1397 | /* read from receive buffer */ |
| 1398 | while (length < cbRead) { |
| 1399 | status = ((ptr->ibuf_head < ptr->ibuf_tail) ? |
| 1400 | ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail; |
| 1401 | if (!status) break; |
| 1402 | if ((cbRead - length) < status) |
| 1403 | status = cbRead - length; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1404 | |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 1405 | memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status); |
| 1406 | ptr->ibuf_tail += status; |
| 1407 | if (ptr->ibuf_tail >= ptr->ibuf_size) |
| 1408 | ptr->ibuf_tail = 0; |
| 1409 | lpvBuf += status; |
| 1410 | length += status; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1411 | } |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 1412 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1413 | TRACE("%.*s\n", length, orgBuf); |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 1414 | ptr->commerror = 0; |
| 1415 | return length; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1416 | } |
| 1417 | |
| 1418 | /***************************************************************************** |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 1419 | * WriteComm16 (USER.205) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1420 | */ |
| 1421 | INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite) |
| 1422 | { |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 1423 | int status, length; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1424 | struct DosDeviceStruct *ptr; |
| 1425 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1426 | TRACE("cid %d, ptr %p, length %d\n", |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1427 | cid, lpvBuf, cbWrite); |
| 1428 | if ((ptr = GetDeviceStruct(cid)) == NULL) { |
Andreas Mohr | a6d83eb | 2000-12-27 04:02:46 +0000 | [diff] [blame] | 1429 | FIXME("no handle for cid = %0x!\n",cid); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1430 | return -1; |
| 1431 | } |
| 1432 | |
| 1433 | if (ptr->suspended) { |
| 1434 | ptr->commerror = IE_HARDWARE; |
| 1435 | return -1; |
| 1436 | } |
| 1437 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1438 | TRACE("%.*s\n", cbWrite, lpvBuf ); |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 1439 | |
| 1440 | length = 0; |
| 1441 | while (length < cbWrite) { |
| 1442 | if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) { |
| 1443 | /* no data queued, try to write directly */ |
| 1444 | status = write(ptr->fd, lpvBuf, cbWrite - length); |
| 1445 | if (status > 0) { |
| 1446 | lpvBuf += status; |
| 1447 | length += status; |
| 1448 | continue; |
| 1449 | } |
| 1450 | } |
| 1451 | /* can't write directly, put into transmit buffer */ |
| 1452 | status = ((ptr->obuf_tail > ptr->obuf_head) ? |
| 1453 | (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head; |
| 1454 | if (!status) break; |
| 1455 | if ((cbWrite - length) < status) |
| 1456 | status = cbWrite - length; |
| 1457 | memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status); |
| 1458 | ptr->obuf_head += status; |
| 1459 | if (ptr->obuf_head >= ptr->obuf_size) |
| 1460 | ptr->obuf_head = 0; |
| 1461 | lpvBuf += status; |
| 1462 | length += status; |
Ove Kaaven | 542b29d | 1999-11-25 21:57:32 +0000 | [diff] [blame] | 1463 | comm_waitwrite(ptr); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1464 | } |
Ove Kaaven | a4dd1be | 1999-04-01 11:52:16 +0000 | [diff] [blame] | 1465 | |
| 1466 | ptr->commerror = 0; |
| 1467 | return length; |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1468 | } |
| 1469 | |
| 1470 | /*********************************************************************** |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 1471 | * EnableCommNotification16 (USER.246) |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1472 | */ |
| 1473 | BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd, |
| 1474 | INT16 cbWriteNotify, INT16 cbOutQueue ) |
| 1475 | { |
| 1476 | struct DosDeviceStruct *ptr; |
| 1477 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1478 | TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1479 | if ((ptr = GetDeviceStruct(cid)) == NULL) { |
Andreas Mohr | a6d83eb | 2000-12-27 04:02:46 +0000 | [diff] [blame] | 1480 | FIXME("no handle for cid = %0x!\n",cid); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1481 | return -1; |
| 1482 | } |
| 1483 | ptr->wnd = hwnd; |
| 1484 | ptr->n_read = cbWriteNotify; |
| 1485 | ptr->n_write = cbOutQueue; |
| 1486 | return TRUE; |
| 1487 | } |
| 1488 | |
| 1489 | |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1490 | /************************************************************************** |
| 1491 | * BuildCommDCBA (KERNEL32.14) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1492 | * |
| 1493 | * Updates a device control block data structure with values from an |
| 1494 | * ascii device control string. The device control string has two forms |
| 1495 | * normal and extended, it must be exclusively in one or the other form. |
| 1496 | * |
| 1497 | * RETURNS |
| 1498 | * |
| 1499 | * True on success, false on an malformed control string. |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1500 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1501 | BOOL WINAPI BuildCommDCBA( |
| 1502 | LPCSTR device, /* The ascii device control string used to update the DCB. */ |
| 1503 | LPDCB lpdcb /* The device control block to be updated. */) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1504 | { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1505 | return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1506 | } |
| 1507 | |
| 1508 | /************************************************************************** |
| 1509 | * BuildCommDCBAndTimeoutsA (KERNEL32.15) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1510 | * |
| 1511 | * Updates a device control block data structure with values from an |
| 1512 | * ascii device control string. Taking time out values from a time outs |
| 1513 | * struct if desired by the control string. |
| 1514 | * |
| 1515 | * RETURNS |
| 1516 | * |
| 1517 | * True on success, false bad handles etc |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1518 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1519 | BOOL WINAPI BuildCommDCBAndTimeoutsA( |
| 1520 | LPCSTR device, /* The ascii device control string. */ |
| 1521 | LPDCB lpdcb, /* The device control block to be updated. */ |
| 1522 | LPCOMMTIMEOUTS lptimeouts /* The time outs to use if asked to set them by the control string. */) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1523 | { |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1524 | int port; |
| 1525 | char *ptr,*temp; |
| 1526 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1527 | TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1528 | |
Alexandre Julliard | 072dfb5 | 2000-09-25 23:30:56 +0000 | [diff] [blame] | 1529 | if (!strncasecmp(device,"COM",3)) { |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1530 | port=device[3]-'0'; |
| 1531 | if (port--==0) { |
Andreas Mohr | a6d83eb | 2000-12-27 04:02:46 +0000 | [diff] [blame] | 1532 | ERR("BUG! COM0 can't exist!\n"); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1533 | return FALSE; |
| 1534 | } |
| 1535 | if (!ValidCOMPort(port)) |
| 1536 | return FALSE; |
| 1537 | if (*(device+4)!=':') |
| 1538 | return FALSE; |
| 1539 | temp=(LPSTR)(device+5); |
| 1540 | } else |
| 1541 | temp=(LPSTR)device; |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1542 | |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1543 | lpdcb->DCBlength = sizeof(DCB); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1544 | if (strchr(temp,',')) { /* old style */ |
| 1545 | DCB16 dcb16; |
| 1546 | BOOL16 ret; |
| 1547 | char last=temp[strlen(temp)-1]; |
| 1548 | |
| 1549 | ret=BuildCommDCB16(device,&dcb16); |
Stefan Leichter | dcb9733 | 2000-07-09 12:19:44 +0000 | [diff] [blame] | 1550 | if (ret) |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1551 | return FALSE; |
| 1552 | lpdcb->BaudRate = dcb16.BaudRate; |
| 1553 | lpdcb->ByteSize = dcb16.ByteSize; |
| 1554 | lpdcb->fBinary = dcb16.fBinary; |
| 1555 | lpdcb->Parity = dcb16.Parity; |
| 1556 | lpdcb->fParity = dcb16.fParity; |
| 1557 | lpdcb->fNull = dcb16.fNull; |
| 1558 | lpdcb->StopBits = dcb16.StopBits; |
| 1559 | if (last == 'x') { |
| 1560 | lpdcb->fInX = TRUE; |
| 1561 | lpdcb->fOutX = TRUE; |
| 1562 | lpdcb->fOutxCtsFlow = FALSE; |
| 1563 | lpdcb->fOutxDsrFlow = FALSE; |
| 1564 | lpdcb->fDtrControl = DTR_CONTROL_ENABLE; |
| 1565 | lpdcb->fRtsControl = RTS_CONTROL_ENABLE; |
| 1566 | } else if (last=='p') { |
| 1567 | lpdcb->fInX = FALSE; |
| 1568 | lpdcb->fOutX = FALSE; |
| 1569 | lpdcb->fOutxCtsFlow = TRUE; |
| 1570 | lpdcb->fOutxDsrFlow = TRUE; |
| 1571 | lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE; |
| 1572 | lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE; |
| 1573 | } else { |
| 1574 | lpdcb->fInX = FALSE; |
| 1575 | lpdcb->fOutX = FALSE; |
| 1576 | lpdcb->fOutxCtsFlow = FALSE; |
| 1577 | lpdcb->fOutxDsrFlow = FALSE; |
| 1578 | lpdcb->fDtrControl = DTR_CONTROL_ENABLE; |
| 1579 | lpdcb->fRtsControl = RTS_CONTROL_ENABLE; |
| 1580 | } |
| 1581 | lpdcb->XonChar = dcb16.XonChar; |
| 1582 | lpdcb->XoffChar = dcb16.XoffChar; |
| 1583 | lpdcb->ErrorChar= dcb16.PeChar; |
| 1584 | lpdcb->fErrorChar= dcb16.fPeChar; |
| 1585 | lpdcb->EofChar = dcb16.EofChar; |
| 1586 | lpdcb->EvtChar = dcb16.EvtChar; |
| 1587 | lpdcb->XonLim = dcb16.XonLim; |
| 1588 | lpdcb->XoffLim = dcb16.XoffLim; |
| 1589 | return TRUE; |
| 1590 | } |
| 1591 | ptr=strtok(temp," "); |
| 1592 | while (ptr) { |
| 1593 | DWORD flag,x; |
| 1594 | |
| 1595 | flag=0; |
| 1596 | if (!strncmp("baud=",ptr,5)) { |
| 1597 | if (!sscanf(ptr+5,"%ld",&x)) |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1598 | WARN("Couldn't parse %s\n",ptr); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1599 | lpdcb->BaudRate = x; |
| 1600 | flag=1; |
| 1601 | } |
| 1602 | if (!strncmp("stop=",ptr,5)) { |
| 1603 | if (!sscanf(ptr+5,"%ld",&x)) |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1604 | WARN("Couldn't parse %s\n",ptr); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1605 | lpdcb->StopBits = x; |
| 1606 | flag=1; |
| 1607 | } |
| 1608 | if (!strncmp("data=",ptr,5)) { |
| 1609 | if (!sscanf(ptr+5,"%ld",&x)) |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1610 | WARN("Couldn't parse %s\n",ptr); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1611 | lpdcb->ByteSize = x; |
| 1612 | flag=1; |
| 1613 | } |
| 1614 | if (!strncmp("parity=",ptr,7)) { |
| 1615 | lpdcb->fParity = TRUE; |
| 1616 | switch (ptr[8]) { |
| 1617 | case 'N':case 'n': |
| 1618 | lpdcb->fParity = FALSE; |
| 1619 | lpdcb->Parity = NOPARITY; |
| 1620 | break; |
| 1621 | case 'E':case 'e': |
| 1622 | lpdcb->Parity = EVENPARITY; |
| 1623 | break; |
| 1624 | case 'O':case 'o': |
| 1625 | lpdcb->Parity = ODDPARITY; |
| 1626 | break; |
| 1627 | case 'M':case 'm': |
| 1628 | lpdcb->Parity = MARKPARITY; |
| 1629 | break; |
| 1630 | } |
| 1631 | flag=1; |
| 1632 | } |
| 1633 | if (!flag) |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1634 | ERR("Unhandled specifier '%s', please report.\n",ptr); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1635 | ptr=strtok(NULL," "); |
| 1636 | } |
| 1637 | if (lpdcb->BaudRate==110) |
| 1638 | lpdcb->StopBits = 2; |
| 1639 | return TRUE; |
| 1640 | } |
| 1641 | |
| 1642 | /************************************************************************** |
| 1643 | * BuildCommDCBAndTimeoutsW (KERNEL32.16) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1644 | * |
| 1645 | * Updates a device control block data structure with values from an |
| 1646 | * unicode device control string. Taking time out values from a time outs |
| 1647 | * struct if desired by the control string. |
| 1648 | * |
| 1649 | * RETURNS |
| 1650 | * |
| 1651 | * True on success, false bad handles etc. |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1652 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1653 | BOOL WINAPI BuildCommDCBAndTimeoutsW( |
| 1654 | LPCWSTR devid, /* The unicode device control string. */ |
| 1655 | LPDCB lpdcb, /* The device control block to be updated. */ |
| 1656 | LPCOMMTIMEOUTS lptimeouts /* The time outs to use if asked to set them by the control string. */) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1657 | { |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1658 | BOOL ret = FALSE; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1659 | LPSTR devidA; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1660 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1661 | TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts); |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 1662 | devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid ); |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1663 | if (devidA) |
| 1664 | { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1665 | ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts); |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 1666 | HeapFree( GetProcessHeap(), 0, devidA ); |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1667 | } |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1668 | return ret; |
| 1669 | } |
| 1670 | |
| 1671 | /************************************************************************** |
| 1672 | * BuildCommDCBW (KERNEL32.17) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1673 | * |
| 1674 | * Updates a device control block structure with values from an |
| 1675 | * unicode device control string. The device control string has two forms |
| 1676 | * normal and extended, it must be exclusively in one or the other form. |
| 1677 | * |
| 1678 | * RETURNS |
| 1679 | * |
| 1680 | * True on success, false on an malformed control string. |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1681 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1682 | BOOL WINAPI BuildCommDCBW( |
| 1683 | LPCWSTR devid, /* The unicode device control string. */ |
| 1684 | LPDCB lpdcb /* The device control block to be updated. */) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1685 | { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1686 | return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1687 | } |
| 1688 | |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1689 | /* FIXME: having these global for win32 for now */ |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 1690 | int commerror=0; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 1691 | |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1692 | /***************************************************************************** |
| 1693 | * SetCommBreak (KERNEL32.449) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1694 | * |
| 1695 | * Halts the transmission of characters to a communications device. |
| 1696 | * |
| 1697 | * RETURNS |
| 1698 | * |
| 1699 | * True on success, and false if the communications device could not be found, |
| 1700 | * the control is not supported. |
| 1701 | * |
| 1702 | * BUGS |
| 1703 | * |
| 1704 | * Only TIOCSBRK and TIOCCBRK are supported. |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1705 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1706 | BOOL WINAPI SetCommBreak( |
| 1707 | HANDLE handle /* The communictions device to suspend. */) |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1708 | { |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1709 | #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */ |
| 1710 | int fd,result; |
| 1711 | |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 1712 | fd = FILE_GetUnixHandle( handle, GENERIC_WRITE ); |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1713 | if(fd<0) { |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 1714 | TRACE("FILE_GetUnixHandle failed\n"); |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1715 | return FALSE; |
| 1716 | } |
| 1717 | result = ioctl(fd,TIOCSBRK,0); |
| 1718 | close(fd); |
| 1719 | if (result ==-1) |
| 1720 | { |
| 1721 | TRACE("ioctl failed\n"); |
| 1722 | SetLastError(ERROR_NOT_SUPPORTED); |
| 1723 | return FALSE; |
| 1724 | } |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1725 | return TRUE; |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1726 | #else |
| 1727 | FIXME("ioctl not available\n"); |
| 1728 | SetLastError(ERROR_NOT_SUPPORTED); |
| 1729 | return FALSE; |
| 1730 | #endif |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1731 | } |
| 1732 | |
| 1733 | /***************************************************************************** |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1734 | * ClearCommBreak (KERNEL32.20) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1735 | * |
| 1736 | * Resumes character transmission from a communication device. |
| 1737 | * |
| 1738 | * RETURNS |
| 1739 | * |
| 1740 | * True on success and false if the communications device could not be found. |
| 1741 | * |
| 1742 | * BUGS |
| 1743 | * |
| 1744 | * Only TIOCSBRK and TIOCCBRK are supported. |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1745 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1746 | BOOL WINAPI ClearCommBreak( |
| 1747 | HANDLE handle /* The halted communication device whose character transmission is to be resumed. */) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 1748 | { |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1749 | #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */ |
| 1750 | int fd,result; |
| 1751 | |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 1752 | fd = FILE_GetUnixHandle( handle, GENERIC_WRITE ); |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1753 | if(fd<0) { |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 1754 | TRACE("FILE_GetUnixHandle failed\n"); |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1755 | return FALSE; |
| 1756 | } |
| 1757 | result = ioctl(fd,TIOCCBRK,0); |
| 1758 | close(fd); |
| 1759 | if (result ==-1) |
| 1760 | { |
| 1761 | TRACE("ioctl failed\n"); |
| 1762 | SetLastError(ERROR_NOT_SUPPORTED); |
| 1763 | return FALSE; |
| 1764 | } |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1765 | return TRUE; |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1766 | #else |
| 1767 | FIXME("ioctl not available\n"); |
| 1768 | SetLastError(ERROR_NOT_SUPPORTED); |
| 1769 | return FALSE; |
| 1770 | #endif |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1771 | } |
| 1772 | |
| 1773 | /***************************************************************************** |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1774 | * EscapeCommFunction (KERNEL32.214) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1775 | * |
| 1776 | * Directs a communication device to perform an extended function. |
| 1777 | * |
| 1778 | * RETURNS |
| 1779 | * |
| 1780 | * True or requested data on successful completion of the command, |
| 1781 | * false if the device is not present cannot execute the command |
| 1782 | * or the command failed. |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1783 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1784 | BOOL WINAPI EscapeCommFunction( |
| 1785 | HANDLE handle, /* The communication device to perform the extended function. */ |
| 1786 | UINT nFunction /* The extended function to be performed. */) |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1787 | { |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1788 | int fd,direct=FALSE,result=FALSE; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1789 | struct termios port; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1790 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1791 | TRACE("handle %d, function=%d\n", handle, nFunction); |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 1792 | fd = FILE_GetUnixHandle( handle, GENERIC_WRITE ); |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 1793 | if(fd<0) { |
| 1794 | FIXME("handle %d not found.\n",handle); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1795 | return FALSE; |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 1796 | } |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1797 | |
| 1798 | if (tcgetattr(fd,&port) == -1) { |
| 1799 | commerror=WinError(); |
| 1800 | close(fd); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1801 | return FALSE; |
| 1802 | } |
| 1803 | |
| 1804 | switch (nFunction) { |
| 1805 | case RESETDEV: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1806 | TRACE("\n"); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1807 | break; |
| 1808 | |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1809 | case CLRDTR: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1810 | TRACE("CLRDTR\n"); |
| 1811 | #ifdef TIOCM_DTR |
| 1812 | direct=TRUE; |
| 1813 | result= COMM_WhackModem(fd, ~TIOCM_DTR, 0); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1814 | break; |
| 1815 | #endif |
| 1816 | |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1817 | case CLRRTS: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1818 | TRACE("CLRRTS\n"); |
| 1819 | #ifdef TIOCM_RTS |
| 1820 | direct=TRUE; |
| 1821 | result= COMM_WhackModem(fd, ~TIOCM_RTS, 0); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1822 | break; |
| 1823 | #endif |
| 1824 | |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1825 | case SETDTR: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1826 | TRACE("SETDTR\n"); |
| 1827 | #ifdef TIOCM_DTR |
| 1828 | direct=TRUE; |
| 1829 | result= COMM_WhackModem(fd, 0, TIOCM_DTR); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1830 | break; |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1831 | #endif |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1832 | |
| 1833 | case SETRTS: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1834 | TRACE("SETRTS\n"); |
| 1835 | #ifdef TIOCM_DTR |
| 1836 | direct=TRUE; |
| 1837 | result= COMM_WhackModem(fd, 0, TIOCM_RTS); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1838 | break; |
| 1839 | #endif |
| 1840 | |
| 1841 | case SETXOFF: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1842 | TRACE("SETXOFF\n"); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1843 | port.c_iflag |= IXOFF; |
| 1844 | break; |
| 1845 | |
| 1846 | case SETXON: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1847 | TRACE("SETXON\n"); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1848 | port.c_iflag |= IXON; |
| 1849 | break; |
| 1850 | case SETBREAK: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1851 | TRACE("setbreak\n"); |
| 1852 | #ifdef TIOCSBRK |
| 1853 | direct=TRUE; |
| 1854 | result = ioctl(fd,TIOCSBRK,0); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1855 | break; |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1856 | #endif |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1857 | case CLRBREAK: |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1858 | TRACE("clrbreak\n"); |
| 1859 | #ifdef TIOCSBRK |
| 1860 | direct=TRUE; |
| 1861 | result = ioctl(fd,TIOCCBRK,0); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1862 | break; |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1863 | #endif |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1864 | default: |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1865 | WARN("(handle=%d,nFunction=%d): Unknown function\n", |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1866 | handle, nFunction); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1867 | break; |
| 1868 | } |
| 1869 | |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1870 | if (!direct) |
| 1871 | if (tcsetattr(fd, TCSADRAIN, &port) == -1) { |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1872 | commerror = WinError(); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1873 | close(fd); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1874 | return FALSE; |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 1875 | } else |
| 1876 | result= TRUE; |
| 1877 | else |
| 1878 | { |
| 1879 | if (result == -1) |
| 1880 | { |
| 1881 | result= FALSE; |
| 1882 | commerror=WinError(); |
| 1883 | } |
| 1884 | else |
| 1885 | result = TRUE; |
| 1886 | } |
| 1887 | close(fd); |
| 1888 | return result; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1889 | } |
| 1890 | |
Alexandre Julliard | 77b9918 | 1997-09-14 17:17:23 +0000 | [diff] [blame] | 1891 | /******************************************************************** |
| 1892 | * PurgeComm (KERNEL32.557) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1893 | * |
| 1894 | * Terminates pending operations and/or discards buffers on a |
| 1895 | * communication resource. |
| 1896 | * |
| 1897 | * RETURNS |
| 1898 | * |
| 1899 | * True on success and false if the communications handle is bad. |
Alexandre Julliard | 77b9918 | 1997-09-14 17:17:23 +0000 | [diff] [blame] | 1900 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1901 | BOOL WINAPI PurgeComm( |
| 1902 | HANDLE handle, /* The communication resource to be purged. */ |
| 1903 | DWORD flags /* Flags for clear pending/buffer on input/output. */) |
Alexandre Julliard | 77b9918 | 1997-09-14 17:17:23 +0000 | [diff] [blame] | 1904 | { |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1905 | int fd; |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1906 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1907 | TRACE("handle %d, flags %lx\n", handle, flags); |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1908 | |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 1909 | fd = FILE_GetUnixHandle( handle, GENERIC_WRITE ); |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 1910 | if(fd<0) { |
| 1911 | FIXME("no handle %d found\n",handle); |
| 1912 | return FALSE; |
| 1913 | } |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1914 | |
| 1915 | /* |
| 1916 | ** not exactly sure how these are different |
| 1917 | ** Perhaps if we had our own internal queues, one flushes them |
| 1918 | ** and the other flushes the kernel's buffers. |
| 1919 | */ |
| 1920 | if(flags&PURGE_TXABORT) |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1921 | tcflush(fd,TCOFLUSH); |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1922 | if(flags&PURGE_RXABORT) |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1923 | tcflush(fd,TCIFLUSH); |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1924 | if(flags&PURGE_TXCLEAR) |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1925 | tcflush(fd,TCOFLUSH); |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1926 | if(flags&PURGE_RXCLEAR) |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1927 | tcflush(fd,TCIFLUSH); |
Ove Kaaven | a1c45a5 | 1999-03-21 15:45:41 +0000 | [diff] [blame] | 1928 | close(fd); |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1929 | |
| 1930 | return 1; |
Alexandre Julliard | 77b9918 | 1997-09-14 17:17:23 +0000 | [diff] [blame] | 1931 | } |
| 1932 | |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1933 | /***************************************************************************** |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1934 | * ClearCommError (KERNEL32.21) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1935 | * |
| 1936 | * Enables further I/O operations on a communications resource after |
| 1937 | * supplying error and current status information. |
| 1938 | * |
| 1939 | * RETURNS |
| 1940 | * |
| 1941 | * True on success, false if the communication resource handle is bad. |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1942 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1943 | BOOL WINAPI ClearCommError( |
| 1944 | HANDLE handle, /* The communication resource with the error. */ |
| 1945 | LPDWORD errors, /* Flags indicating error the resource experienced. */ |
| 1946 | LPCOMSTAT lpStat /* The status of the communication resource. */) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 1947 | { |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1948 | int fd; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1949 | |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 1950 | fd=FILE_GetUnixHandle( handle, GENERIC_READ ); |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1951 | if(0>fd) |
| 1952 | { |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 1953 | FIXME("no handle %d found\n",handle); |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1954 | return FALSE; |
| 1955 | } |
| 1956 | |
| 1957 | if (lpStat) |
| 1958 | { |
| 1959 | lpStat->status = 0; |
| 1960 | |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 1961 | #ifdef TIOCOUTQ |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1962 | if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue)) |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1963 | WARN("ioctl returned error\n"); |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 1964 | #else |
| 1965 | lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */ |
| 1966 | #endif |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1967 | |
Dimitrie O. Paun | 5bea4f8 | 2000-11-25 01:29:00 +0000 | [diff] [blame] | 1968 | #ifdef TIOCINQ |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1969 | if(ioctl(fd, TIOCINQ, &lpStat->cbInQue)) |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1970 | WARN("ioctl returned error\n"); |
Dimitrie O. Paun | 5bea4f8 | 2000-11-25 01:29:00 +0000 | [diff] [blame] | 1971 | #endif |
Eric Pouech | f216310 | 1999-07-12 13:39:58 +0000 | [diff] [blame] | 1972 | |
| 1973 | TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n", |
| 1974 | handle, lpStat->cbInQue, lpStat->cbOutQue); |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1975 | } |
| 1976 | |
| 1977 | close(fd); |
| 1978 | |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 1979 | if(errors) |
| 1980 | *errors = 0; |
| 1981 | |
| 1982 | /* |
| 1983 | ** After an asynchronous write opperation, the |
| 1984 | ** app will call ClearCommError to see if the |
| 1985 | ** results are ready yet. It waits for ERROR_IO_PENDING |
| 1986 | */ |
| 1987 | commerror = ERROR_IO_PENDING; |
| 1988 | |
| 1989 | return TRUE; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 1990 | } |
| 1991 | |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 1992 | /***************************************************************************** |
Alexandre Julliard | 77b9918 | 1997-09-14 17:17:23 +0000 | [diff] [blame] | 1993 | * SetupComm (KERNEL32.676) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 1994 | * |
| 1995 | * Called after CreateFile to hint to the communication resource to use |
| 1996 | * specified sizes for input and output buffers rather than the default values. |
| 1997 | * |
| 1998 | * RETURNS |
| 1999 | * |
| 2000 | * True if successful, false if the communications resource handle is bad. |
| 2001 | * |
| 2002 | * BUGS |
| 2003 | * |
| 2004 | * Stub. |
Alexandre Julliard | 77b9918 | 1997-09-14 17:17:23 +0000 | [diff] [blame] | 2005 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 2006 | BOOL WINAPI SetupComm( |
| 2007 | HANDLE handle, /* The just created communication resource handle. */ |
| 2008 | DWORD insize, /* The suggested size of the communication resources input buffer in bytes. */ |
| 2009 | DWORD outsize /* The suggested size of the communication resources output buffer in bytes. */) |
Alexandre Julliard | 77b9918 | 1997-09-14 17:17:23 +0000 | [diff] [blame] | 2010 | { |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2011 | int fd; |
| 2012 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 2013 | FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize); |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 2014 | fd=FILE_GetUnixHandle( handle, GENERIC_WRITE ); |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 2015 | if(0>fd) { |
| 2016 | FIXME("handle %d not found?\n",handle); |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2017 | return FALSE; |
| 2018 | } |
| 2019 | close(fd); |
| 2020 | return TRUE; |
Alexandre Julliard | 77b9918 | 1997-09-14 17:17:23 +0000 | [diff] [blame] | 2021 | } |
| 2022 | |
| 2023 | /***************************************************************************** |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2024 | * GetCommMask (KERNEL32.156) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 2025 | * |
| 2026 | * Obtain the events associated with a communication device that will cause a call |
| 2027 | * WaitCommEvent to return. |
| 2028 | * |
| 2029 | * RETURNS |
| 2030 | * |
| 2031 | * True on success, fail on bad device handle etc. |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2032 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 2033 | BOOL WINAPI GetCommMask( |
| 2034 | HANDLE handle, /* The communications device. */ |
| 2035 | LPDWORD evtmask /* The events which cause WaitCommEvent to return. */) |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2036 | { |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 2037 | BOOL ret; |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2038 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 2039 | TRACE("handle %d, mask %p\n", handle, evtmask); |
Mike McCormack | 654fcc7 | 2000-09-16 20:55:12 +0000 | [diff] [blame] | 2040 | |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 2041 | SERVER_START_REQ |
| 2042 | { |
| 2043 | struct get_serial_info_request *req = server_alloc_req( sizeof(*req), 0 ); |
| 2044 | req->handle = handle; |
| 2045 | if ((ret = !server_call( REQ_GET_SERIAL_INFO ))) |
| 2046 | { |
| 2047 | if (evtmask) *evtmask = req->eventmask; |
| 2048 | } |
| 2049 | } |
| 2050 | SERVER_END_REQ; |
| 2051 | return ret; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2052 | } |
| 2053 | |
| 2054 | /***************************************************************************** |
| 2055 | * SetCommMask (KERNEL32.451) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 2056 | * |
| 2057 | * There be some things we need to hear about yon there communications device. |
| 2058 | * (Set which events associated with a communication device should cause |
| 2059 | * a call WaitCommEvent to return.) |
| 2060 | * |
| 2061 | * RETURNS |
| 2062 | * |
| 2063 | * True on success, false on bad handle etc. |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2064 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 2065 | BOOL WINAPI SetCommMask( |
| 2066 | HANDLE handle, /* The communications device. */ |
| 2067 | DWORD evtmask /* The events that to be monitored. */) |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2068 | { |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 2069 | BOOL ret; |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2070 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 2071 | TRACE("handle %d, mask %lx\n", handle, evtmask); |
Mike McCormack | 654fcc7 | 2000-09-16 20:55:12 +0000 | [diff] [blame] | 2072 | |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 2073 | SERVER_START_REQ |
| 2074 | { |
| 2075 | struct set_serial_info_request *req = server_alloc_req( sizeof(*req), 0 ); |
| 2076 | req->handle = handle; |
| 2077 | req->flags = SERIALINFO_SET_MASK; |
| 2078 | req->eventmask = evtmask; |
| 2079 | ret = !server_call( REQ_SET_SERIAL_INFO ); |
| 2080 | } |
| 2081 | SERVER_END_REQ; |
| 2082 | return ret; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2083 | } |
| 2084 | |
| 2085 | /***************************************************************************** |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2086 | * SetCommState (KERNEL32.452) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 2087 | * |
| 2088 | * Re-initializes all hardware and control settings of a communications device, |
| 2089 | * with values from a device control block without effecting the input and output |
| 2090 | * queues. |
| 2091 | * |
| 2092 | * RETURNS |
| 2093 | * |
| 2094 | * True on success, false on failure eg if the XonChar is equal to the XoffChar. |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2095 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 2096 | BOOL WINAPI SetCommState( |
| 2097 | HANDLE handle, /* The communications device. */ |
| 2098 | LPDCB lpdcb /* The device control block. */) |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2099 | { |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2100 | struct termios port; |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 2101 | int fd, bytesize, stopbits; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2102 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 2103 | TRACE("handle %d, ptr %p\n", handle, lpdcb); |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2104 | TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n", |
| 2105 | lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity, |
| 2106 | (lpdcb->StopBits == ONESTOPBIT)?1: |
| 2107 | (lpdcb->StopBits == TWOSTOPBITS)?2:0); |
| 2108 | TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON", |
| 2109 | (lpdcb->fOutX)?"IXOFF":"~IXOFF"); |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2110 | |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 2111 | fd = FILE_GetUnixHandle( handle, GENERIC_WRITE ); |
| 2112 | if (fd < 0) { |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 2113 | FIXME("no handle %d found\n",handle); |
| 2114 | return FALSE; |
| 2115 | } |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2116 | |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2117 | if ((tcgetattr(fd,&port)) == -1) { |
| 2118 | int save_error = errno; |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 2119 | commerror = WinError(); |
| 2120 | close( fd ); |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2121 | ERR("tcgetattr error '%s'\n", strerror(save_error)); |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2122 | return FALSE; |
| 2123 | } |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2124 | |
| 2125 | port.c_cc[VMIN] = 0; |
| 2126 | port.c_cc[VTIME] = 1; |
| 2127 | |
| 2128 | #ifdef IMAXBEL |
| 2129 | port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL); |
| 2130 | #else |
| 2131 | port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR); |
| 2132 | #endif |
| 2133 | port.c_iflag |= (IGNBRK); |
| 2134 | |
| 2135 | port.c_oflag &= ~(OPOST); |
| 2136 | |
| 2137 | port.c_cflag &= ~(HUPCL); |
| 2138 | port.c_cflag |= CLOCAL | CREAD; |
| 2139 | |
| 2140 | port.c_lflag &= ~(ICANON|ECHO|ISIG); |
| 2141 | port.c_lflag |= NOFLSH; |
| 2142 | |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2143 | /* |
| 2144 | ** MJM - removed default baudrate settings |
| 2145 | ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate); |
| 2146 | */ |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2147 | #ifdef CBAUD |
| 2148 | port.c_cflag &= ~CBAUD; |
| 2149 | switch (lpdcb->BaudRate) { |
| 2150 | case 110: |
| 2151 | case CBR_110: |
| 2152 | port.c_cflag |= B110; |
| 2153 | break; |
| 2154 | case 300: |
| 2155 | case CBR_300: |
| 2156 | port.c_cflag |= B300; |
| 2157 | break; |
| 2158 | case 600: |
| 2159 | case CBR_600: |
| 2160 | port.c_cflag |= B600; |
| 2161 | break; |
| 2162 | case 1200: |
| 2163 | case CBR_1200: |
| 2164 | port.c_cflag |= B1200; |
| 2165 | break; |
| 2166 | case 2400: |
| 2167 | case CBR_2400: |
| 2168 | port.c_cflag |= B2400; |
| 2169 | break; |
| 2170 | case 4800: |
| 2171 | case CBR_4800: |
| 2172 | port.c_cflag |= B4800; |
| 2173 | break; |
| 2174 | case 9600: |
| 2175 | case CBR_9600: |
| 2176 | port.c_cflag |= B9600; |
| 2177 | break; |
| 2178 | case 19200: |
| 2179 | case CBR_19200: |
| 2180 | port.c_cflag |= B19200; |
| 2181 | break; |
| 2182 | case 38400: |
| 2183 | case CBR_38400: |
| 2184 | port.c_cflag |= B38400; |
| 2185 | break; |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2186 | #ifdef B57600 |
| 2187 | case 57600: |
| 2188 | port.c_cflag |= B57600; |
| 2189 | break; |
| 2190 | #endif |
| 2191 | #ifdef B115200 |
| 2192 | case 115200: |
| 2193 | port.c_cflag |= B115200; |
| 2194 | break; |
| 2195 | #endif |
| 2196 | #ifdef B230400 |
| 2197 | case 230400: |
| 2198 | port.c_cflag |= B230400; |
| 2199 | break; |
| 2200 | #endif |
| 2201 | #ifdef B460800 |
| 2202 | case 460600: |
| 2203 | port.c_cflag |= B460800; |
| 2204 | break; |
| 2205 | #endif |
| 2206 | default: |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2207 | commerror = IE_BAUDRATE; |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2208 | close( fd ); |
| 2209 | ERR("baudrate %ld\n",lpdcb->BaudRate); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2210 | return FALSE; |
| 2211 | } |
Alexandre Julliard | 349a953 | 1997-02-02 19:01:52 +0000 | [diff] [blame] | 2212 | #elif !defined(__EMX__) |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2213 | switch (lpdcb->BaudRate) { |
| 2214 | case 110: |
| 2215 | case CBR_110: |
| 2216 | port.c_ospeed = B110; |
| 2217 | break; |
| 2218 | case 300: |
| 2219 | case CBR_300: |
| 2220 | port.c_ospeed = B300; |
| 2221 | break; |
| 2222 | case 600: |
| 2223 | case CBR_600: |
| 2224 | port.c_ospeed = B600; |
| 2225 | break; |
| 2226 | case 1200: |
| 2227 | case CBR_1200: |
| 2228 | port.c_ospeed = B1200; |
| 2229 | break; |
| 2230 | case 2400: |
| 2231 | case CBR_2400: |
| 2232 | port.c_ospeed = B2400; |
| 2233 | break; |
| 2234 | case 4800: |
| 2235 | case CBR_4800: |
| 2236 | port.c_ospeed = B4800; |
| 2237 | break; |
| 2238 | case 9600: |
| 2239 | case CBR_9600: |
| 2240 | port.c_ospeed = B9600; |
| 2241 | break; |
| 2242 | case 19200: |
| 2243 | case CBR_19200: |
| 2244 | port.c_ospeed = B19200; |
| 2245 | break; |
| 2246 | case 38400: |
| 2247 | case CBR_38400: |
| 2248 | port.c_ospeed = B38400; |
| 2249 | break; |
| 2250 | default: |
| 2251 | commerror = IE_BAUDRATE; |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 2252 | close( fd ); |
Gerald Pfeifer | 093af59 | 2000-05-30 15:28:37 +0000 | [diff] [blame] | 2253 | ERR("baudrate %ld\n",lpdcb->BaudRate); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2254 | return FALSE; |
| 2255 | } |
| 2256 | port.c_ispeed = port.c_ospeed; |
| 2257 | #endif |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 2258 | bytesize=lpdcb->ByteSize; |
| 2259 | stopbits=lpdcb->StopBits; |
| 2260 | |
| 2261 | #ifdef CMSPAR |
| 2262 | port.c_cflag &= ~(PARENB | PARODD | CMSPAR); |
| 2263 | #else |
| 2264 | port.c_cflag &= ~(PARENB | PARODD); |
| 2265 | #endif |
| 2266 | if (lpdcb->fParity) |
| 2267 | port.c_iflag |= INPCK; |
| 2268 | else |
| 2269 | port.c_iflag &= ~INPCK; |
| 2270 | switch (lpdcb->Parity) { |
| 2271 | case NOPARITY: |
| 2272 | break; |
| 2273 | case ODDPARITY: |
| 2274 | port.c_cflag |= (PARENB | PARODD); |
| 2275 | break; |
| 2276 | case EVENPARITY: |
| 2277 | port.c_cflag |= PARENB; |
| 2278 | break; |
| 2279 | #ifdef CMSPAR |
| 2280 | /* Linux defines mark/space (stick) parity */ |
| 2281 | case MARKPARITY: |
| 2282 | port.c_cflag |= (PARENB | CMSPAR); |
| 2283 | break; |
| 2284 | case SPACEPARITY: |
| 2285 | port.c_cflag |= (PARENB | PARODD | CMSPAR); |
| 2286 | break; |
| 2287 | #else |
| 2288 | /* try the POSIX way */ |
| 2289 | case MARKPARITY: |
| 2290 | if( stopbits == ONESTOPBIT) { |
| 2291 | stopbits = TWOSTOPBITS; |
| 2292 | port.c_iflag &= ~INPCK; |
| 2293 | } else { |
| 2294 | commerror = IE_BYTESIZE; |
| 2295 | close( fd ); |
| 2296 | ERR("Cannot set MARK Parity\n"); |
| 2297 | return FALSE; |
| 2298 | } |
| 2299 | break; |
| 2300 | case SPACEPARITY: |
| 2301 | if( bytesize < 8) { |
| 2302 | bytesize +=1; |
| 2303 | port.c_iflag &= ~INPCK; |
| 2304 | } else { |
| 2305 | commerror = IE_BYTESIZE; |
| 2306 | close( fd ); |
| 2307 | ERR("Cannot set SPACE Parity\n"); |
| 2308 | return FALSE; |
| 2309 | } |
| 2310 | break; |
| 2311 | #endif |
| 2312 | default: |
| 2313 | commerror = IE_BYTESIZE; |
| 2314 | close( fd ); |
| 2315 | ERR("Parity\n"); |
| 2316 | return FALSE; |
| 2317 | } |
| 2318 | |
| 2319 | |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2320 | port.c_cflag &= ~CSIZE; |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 2321 | switch (bytesize) { |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2322 | case 5: |
| 2323 | port.c_cflag |= CS5; |
| 2324 | break; |
| 2325 | case 6: |
| 2326 | port.c_cflag |= CS6; |
| 2327 | break; |
| 2328 | case 7: |
| 2329 | port.c_cflag |= CS7; |
| 2330 | break; |
| 2331 | case 8: |
| 2332 | port.c_cflag |= CS8; |
| 2333 | break; |
| 2334 | default: |
| 2335 | commerror = IE_BYTESIZE; |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 2336 | close( fd ); |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2337 | ERR("ByteSize\n"); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2338 | return FALSE; |
| 2339 | } |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 2340 | |
| 2341 | switch (stopbits) { |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2342 | case ONESTOPBIT: |
| 2343 | port.c_cflag &= ~CSTOPB; |
| 2344 | break; |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 2345 | case ONE5STOPBITS: /* wil be selected if bytesize is 5 */ |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2346 | case TWOSTOPBITS: |
| 2347 | port.c_cflag |= CSTOPB; |
| 2348 | break; |
| 2349 | default: |
| 2350 | commerror = IE_BYTESIZE; |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 2351 | close( fd ); |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2352 | ERR("StopBits\n"); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2353 | return FALSE; |
| 2354 | } |
| 2355 | #ifdef CRTSCTS |
| 2356 | if ( lpdcb->fOutxCtsFlow || |
| 2357 | lpdcb->fDtrControl == DTR_CONTROL_ENABLE|| |
| 2358 | lpdcb->fRtsControl == RTS_CONTROL_ENABLE |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2359 | ) |
| 2360 | { |
| 2361 | port.c_cflag |= CRTSCTS; |
| 2362 | TRACE("CRTSCTS\n"); |
| 2363 | } |
| 2364 | |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2365 | if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE) |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2366 | { |
| 2367 | port.c_cflag &= ~CRTSCTS; |
| 2368 | TRACE("~CRTSCTS\n"); |
| 2369 | } |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2370 | |
| 2371 | #endif |
| 2372 | if (lpdcb->fInX) |
| 2373 | port.c_iflag |= IXON; |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 2374 | else |
| 2375 | port.c_iflag &= ~IXON; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2376 | if (lpdcb->fOutX) |
| 2377 | port.c_iflag |= IXOFF; |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 2378 | else |
| 2379 | port.c_iflag &= ~IXOFF; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2380 | |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2381 | if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/ |
| 2382 | int save_error=errno; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2383 | commerror = WinError(); |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 2384 | close( fd ); |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2385 | ERR("tcgetattr error '%s'\n", strerror(save_error)); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2386 | return FALSE; |
| 2387 | } else { |
| 2388 | commerror = 0; |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 2389 | close( fd ); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2390 | return TRUE; |
| 2391 | } |
| 2392 | } |
| 2393 | |
| 2394 | |
| 2395 | /***************************************************************************** |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2396 | * GetCommState (KERNEL32.159) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 2397 | * |
| 2398 | * Fills in a device control block with information from a communications device. |
| 2399 | * |
| 2400 | * RETURNS |
| 2401 | * |
| 2402 | * True on success, false if the communication device handle is bad etc |
| 2403 | * |
| 2404 | * BUGS |
| 2405 | * |
| 2406 | * XonChar and XoffChar are not set. |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2407 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 2408 | BOOL WINAPI GetCommState( |
| 2409 | HANDLE handle, /* The communications device. */ |
| 2410 | LPDCB lpdcb /* The device control block. */) |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2411 | { |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2412 | struct termios port; |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2413 | int fd,speed; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2414 | |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 2415 | TRACE("handle %d, ptr %p\n", handle, lpdcb); |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2416 | |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 2417 | fd = FILE_GetUnixHandle( handle, GENERIC_READ ); |
| 2418 | if (fd < 0) |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2419 | { |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 2420 | ERR("FILE_GetUnixHandle failed\n"); |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2421 | return FALSE; |
| 2422 | } |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2423 | if (tcgetattr(fd, &port) == -1) { |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2424 | int save_error=errno; |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2425 | ERR("tcgetattr error '%s'\n", strerror(save_error)); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2426 | commerror = WinError(); |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 2427 | close( fd ); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2428 | return FALSE; |
| 2429 | } |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 2430 | close( fd ); |
Alexandre Julliard | 349a953 | 1997-02-02 19:01:52 +0000 | [diff] [blame] | 2431 | #ifndef __EMX__ |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2432 | #ifdef CBAUD |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2433 | speed= (port.c_cflag & CBAUD); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2434 | #else |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2435 | speed= (cfgetospeed(&port)); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2436 | #endif |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2437 | switch (speed) { |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2438 | case B110: |
| 2439 | lpdcb->BaudRate = 110; |
| 2440 | break; |
| 2441 | case B300: |
| 2442 | lpdcb->BaudRate = 300; |
| 2443 | break; |
| 2444 | case B600: |
| 2445 | lpdcb->BaudRate = 600; |
| 2446 | break; |
| 2447 | case B1200: |
| 2448 | lpdcb->BaudRate = 1200; |
| 2449 | break; |
| 2450 | case B2400: |
| 2451 | lpdcb->BaudRate = 2400; |
| 2452 | break; |
| 2453 | case B4800: |
| 2454 | lpdcb->BaudRate = 4800; |
| 2455 | break; |
| 2456 | case B9600: |
| 2457 | lpdcb->BaudRate = 9600; |
| 2458 | break; |
| 2459 | case B19200: |
| 2460 | lpdcb->BaudRate = 19200; |
| 2461 | break; |
| 2462 | case B38400: |
| 2463 | lpdcb->BaudRate = 38400; |
| 2464 | break; |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2465 | #ifdef B57600 |
| 2466 | case B57600: |
| 2467 | lpdcb->BaudRate = 57600; |
| 2468 | break; |
| 2469 | #endif |
| 2470 | #ifdef B115200 |
| 2471 | case B115200: |
| 2472 | lpdcb->BaudRate = 115200; |
| 2473 | break; |
| 2474 | #endif |
| 2475 | #ifdef B230400 |
| 2476 | case B230400: |
| 2477 | lpdcb->BaudRate = 230400; |
| 2478 | break; |
| 2479 | #endif |
| 2480 | #ifdef B460800 |
| 2481 | case B460800: |
| 2482 | lpdcb->BaudRate = 460800; |
| 2483 | break; |
| 2484 | #endif |
| 2485 | default: |
| 2486 | ERR("unknown speed %x \n",speed); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2487 | } |
Alexandre Julliard | 349a953 | 1997-02-02 19:01:52 +0000 | [diff] [blame] | 2488 | #endif |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2489 | switch (port.c_cflag & CSIZE) { |
| 2490 | case CS5: |
| 2491 | lpdcb->ByteSize = 5; |
| 2492 | break; |
| 2493 | case CS6: |
| 2494 | lpdcb->ByteSize = 6; |
| 2495 | break; |
| 2496 | case CS7: |
| 2497 | lpdcb->ByteSize = 7; |
| 2498 | break; |
| 2499 | case CS8: |
| 2500 | lpdcb->ByteSize = 8; |
| 2501 | break; |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2502 | default: |
| 2503 | ERR("unknown size %x \n",port.c_cflag & CSIZE); |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2504 | } |
| 2505 | |
Rein Klazes | 58a38b8 | 1999-03-23 13:44:51 +0000 | [diff] [blame] | 2506 | if(port.c_iflag & INPCK) |
| 2507 | lpdcb->fParity = TRUE; |
| 2508 | else |
| 2509 | lpdcb->fParity = FALSE; |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 2510 | #ifdef CMSPAR |
Patrik Stridvall | c77ff5e | 2000-04-29 14:26:13 +0000 | [diff] [blame] | 2511 | switch (port.c_cflag & (PARENB | PARODD | CMSPAR)) |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 2512 | #else |
Patrik Stridvall | c77ff5e | 2000-04-29 14:26:13 +0000 | [diff] [blame] | 2513 | switch (port.c_cflag & (PARENB | PARODD)) |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 2514 | #endif |
Patrik Stridvall | c77ff5e | 2000-04-29 14:26:13 +0000 | [diff] [blame] | 2515 | { |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2516 | case 0: |
Cliff Wright | 28d3d21 | 1998-11-22 15:05:18 +0000 | [diff] [blame] | 2517 | lpdcb->Parity = NOPARITY; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2518 | break; |
| 2519 | case PARENB: |
Cliff Wright | 28d3d21 | 1998-11-22 15:05:18 +0000 | [diff] [blame] | 2520 | lpdcb->Parity = EVENPARITY; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2521 | break; |
| 2522 | case (PARENB | PARODD): |
Cliff Wright | 28d3d21 | 1998-11-22 15:05:18 +0000 | [diff] [blame] | 2523 | lpdcb->Parity = ODDPARITY; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2524 | break; |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 2525 | #ifdef CMSPAR |
| 2526 | case (PARENB | CMSPAR): |
| 2527 | lpdcb->Parity = MARKPARITY; |
| 2528 | break; |
| 2529 | case (PARENB | PARODD | CMSPAR): |
| 2530 | lpdcb->Parity = SPACEPARITY; |
| 2531 | break; |
| 2532 | #endif |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2533 | } |
| 2534 | |
| 2535 | if (port.c_cflag & CSTOPB) |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 2536 | if(lpdcb->ByteSize == 5) |
| 2537 | lpdcb->StopBits = ONE5STOPBITS; |
| 2538 | else |
| 2539 | lpdcb->StopBits = TWOSTOPBITS; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2540 | else |
Rein Klazes | 0a54d5a | 2000-04-28 14:44:33 +0000 | [diff] [blame] | 2541 | lpdcb->StopBits = ONESTOPBIT; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2542 | |
| 2543 | lpdcb->fNull = 0; |
| 2544 | lpdcb->fBinary = 1; |
| 2545 | |
| 2546 | #ifdef CRTSCTS |
| 2547 | |
| 2548 | if (port.c_cflag & CRTSCTS) { |
| 2549 | lpdcb->fDtrControl = DTR_CONTROL_ENABLE; |
| 2550 | lpdcb->fRtsControl = RTS_CONTROL_ENABLE; |
| 2551 | lpdcb->fOutxCtsFlow = 1; |
| 2552 | lpdcb->fOutxDsrFlow = 1; |
| 2553 | } else |
| 2554 | #endif |
| 2555 | { |
| 2556 | lpdcb->fDtrControl = DTR_CONTROL_DISABLE; |
| 2557 | lpdcb->fRtsControl = RTS_CONTROL_DISABLE; |
| 2558 | } |
| 2559 | if (port.c_iflag & IXON) |
| 2560 | lpdcb->fInX = 1; |
| 2561 | else |
| 2562 | lpdcb->fInX = 0; |
| 2563 | |
| 2564 | if (port.c_iflag & IXOFF) |
| 2565 | lpdcb->fOutX = 1; |
| 2566 | else |
| 2567 | lpdcb->fOutX = 0; |
| 2568 | /* |
| 2569 | lpdcb->XonChar = |
| 2570 | lpdcb->XoffChar = |
| 2571 | */ |
| 2572 | lpdcb->XonLim = 10; |
| 2573 | lpdcb->XoffLim = 10; |
| 2574 | |
| 2575 | commerror = 0; |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2576 | |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2577 | TRACE("OK\n"); |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2578 | |
Uwe Bonnes | f57ef1d | 1999-08-07 12:28:09 +0000 | [diff] [blame] | 2579 | TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n", |
| 2580 | lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity, |
| 2581 | (lpdcb->StopBits == ONESTOPBIT)?1: |
| 2582 | (lpdcb->StopBits == TWOSTOPBITS)?2:0); |
| 2583 | TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON", |
| 2584 | (lpdcb->fOutX)?"IXOFF":"~IXOFF"); |
| 2585 | #ifdef CRTSCTS |
| 2586 | if ( lpdcb->fOutxCtsFlow || |
| 2587 | lpdcb->fDtrControl == DTR_CONTROL_ENABLE|| |
| 2588 | lpdcb->fRtsControl == RTS_CONTROL_ENABLE |
| 2589 | ) |
| 2590 | TRACE("CRTSCTS\n"); |
| 2591 | |
| 2592 | if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE) |
| 2593 | TRACE("~CRTSCTS\n"); |
| 2594 | |
| 2595 | #endif |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2596 | return TRUE; |
| 2597 | } |
| 2598 | |
| 2599 | /***************************************************************************** |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2600 | * TransmitCommChar (KERNEL32.535) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 2601 | * |
| 2602 | * Transmits a single character in front of any pending characters in the |
| 2603 | * output buffer. Usually used to send an interrupt character to a host. |
| 2604 | * |
| 2605 | * RETURNS |
| 2606 | * |
| 2607 | * True if the call succeeded, false if the previous command character to the |
| 2608 | * same device has not been sent yet the handle is bad etc. |
| 2609 | * |
| 2610 | * BUGS |
| 2611 | * |
| 2612 | * Stub. |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2613 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 2614 | BOOL WINAPI TransmitCommChar( |
| 2615 | HANDLE hComm, /* The communication device in need of a command character. */ |
| 2616 | CHAR chTransmit /* The character to transmit. */) |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2617 | { |
Mike McCormack | 6a31f96 | 2000-06-15 00:15:11 +0000 | [diff] [blame] | 2618 | FIXME("(%x,'%c'), use win32 handle!\n",hComm,chTransmit); |
| 2619 | return TRUE; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2620 | } |
| 2621 | |
| 2622 | /***************************************************************************** |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2623 | * GetCommTimeouts (KERNEL32.160) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 2624 | * |
| 2625 | * Obtains the request time out values for the communications device. |
| 2626 | * |
| 2627 | * RETURNS |
| 2628 | * |
| 2629 | * True on success, false if communications device handle is bad |
| 2630 | * or the target structure is null. |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2631 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 2632 | BOOL WINAPI GetCommTimeouts( |
| 2633 | HANDLE hComm, /* The communications device. */ |
| 2634 | LPCOMMTIMEOUTS lptimeouts /* The struct of request time outs. */) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 2635 | { |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 2636 | BOOL ret; |
Mike McCormack | 654fcc7 | 2000-09-16 20:55:12 +0000 | [diff] [blame] | 2637 | |
| 2638 | TRACE("(%x,%p)\n",hComm,lptimeouts); |
| 2639 | |
| 2640 | if(!lptimeouts) |
| 2641 | { |
| 2642 | SetLastError(ERROR_INVALID_PARAMETER); |
| 2643 | return FALSE; |
| 2644 | } |
| 2645 | |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 2646 | SERVER_START_REQ |
| 2647 | { |
| 2648 | struct get_serial_info_request *req = server_alloc_req( sizeof(*req), 0 ); |
| 2649 | req->handle = hComm; |
| 2650 | if ((ret = !server_call( REQ_GET_SERIAL_INFO ))) |
| 2651 | { |
| 2652 | lptimeouts->ReadIntervalTimeout = req->readinterval; |
| 2653 | lptimeouts->ReadTotalTimeoutMultiplier = req->readmult; |
| 2654 | lptimeouts->ReadTotalTimeoutConstant = req->readconst; |
| 2655 | lptimeouts->WriteTotalTimeoutMultiplier = req->writemult; |
| 2656 | lptimeouts->WriteTotalTimeoutConstant = req->writeconst; |
| 2657 | } |
| 2658 | } |
| 2659 | SERVER_END_REQ; |
| 2660 | return ret; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2661 | } |
| 2662 | |
| 2663 | /***************************************************************************** |
| 2664 | * SetCommTimeouts (KERNEL32.453) |
Mike McCormack | 654fcc7 | 2000-09-16 20:55:12 +0000 | [diff] [blame] | 2665 | * |
| 2666 | * Sets the timeouts used when reading and writing data to/from COMM ports. |
| 2667 | * |
| 2668 | * ReadIntervalTimeout |
| 2669 | * - converted and passes to linux kernel as c_cc[VTIME] |
| 2670 | * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant |
| 2671 | * - used in ReadFile to calculate GetOverlappedResult's timeout |
| 2672 | * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant |
| 2673 | * - used in WriteFile to calculate GetOverlappedResult's timeout |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 2674 | * |
| 2675 | * RETURNS |
| 2676 | * |
| 2677 | * True if the time outs were set, false otherwise. |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 2678 | */ |
Mike McCormack | 654fcc7 | 2000-09-16 20:55:12 +0000 | [diff] [blame] | 2679 | BOOL WINAPI SetCommTimeouts( |
Patrik Stridvall | 2b3aa61 | 2000-12-01 23:58:28 +0000 | [diff] [blame] | 2680 | HANDLE hComm, /* [in] handle of COMM device */ |
| 2681 | LPCOMMTIMEOUTS lptimeouts /* [in] pointer to COMMTIMEOUTS structure */ |
Mike McCormack | 654fcc7 | 2000-09-16 20:55:12 +0000 | [diff] [blame] | 2682 | ) { |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 2683 | BOOL ret; |
| 2684 | int fd; |
Mike McCormack | 654fcc7 | 2000-09-16 20:55:12 +0000 | [diff] [blame] | 2685 | struct termios tios; |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 2686 | |
Mike McCormack | 654fcc7 | 2000-09-16 20:55:12 +0000 | [diff] [blame] | 2687 | TRACE("(%x,%p)\n",hComm,lptimeouts); |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 2688 | |
Mike McCormack | 654fcc7 | 2000-09-16 20:55:12 +0000 | [diff] [blame] | 2689 | if(!lptimeouts) |
| 2690 | { |
| 2691 | SetLastError(ERROR_INVALID_PARAMETER); |
Mike McCormack | 654fcc7 | 2000-09-16 20:55:12 +0000 | [diff] [blame] | 2692 | return FALSE; |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 2693 | } |
| 2694 | |
| 2695 | SERVER_START_REQ |
| 2696 | { |
| 2697 | struct set_serial_info_request *req = server_alloc_req( sizeof(*req), 0 ); |
| 2698 | req->handle = hComm; |
| 2699 | req->flags = SERIALINFO_SET_TIMEOUTS; |
| 2700 | req->readinterval = lptimeouts->ReadIntervalTimeout ; |
| 2701 | req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ; |
| 2702 | req->readconst = lptimeouts->ReadTotalTimeoutConstant ; |
| 2703 | req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ; |
| 2704 | req->writeconst = lptimeouts->WriteTotalTimeoutConstant ; |
| 2705 | ret = !server_call( REQ_SET_SERIAL_INFO ); |
| 2706 | } |
| 2707 | SERVER_END_REQ; |
| 2708 | if (!ret) return FALSE; |
Mike McCormack | 654fcc7 | 2000-09-16 20:55:12 +0000 | [diff] [blame] | 2709 | |
| 2710 | /* FIXME: move this stuff to the server */ |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 2711 | fd = FILE_GetUnixHandle( hComm, GENERIC_WRITE ); |
Mike McCormack | 654fcc7 | 2000-09-16 20:55:12 +0000 | [diff] [blame] | 2712 | if (fd < 0) { |
| 2713 | FIXME("no fd for handle = %0x!.\n",hComm); |
| 2714 | return FALSE; |
| 2715 | } |
Marcus Meissner | 7547d4d | 2000-01-05 01:46:53 +0000 | [diff] [blame] | 2716 | |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 2717 | if (-1==tcgetattr(fd,&tios)) { |
| 2718 | FIXME("tcgetattr on fd %d failed!\n",fd); |
| 2719 | return FALSE; |
| 2720 | } |
| 2721 | /* VTIME is in 1/10 seconds */ |
| 2722 | tios.c_cc[VTIME]= (lptimeouts->ReadIntervalTimeout+99)/100; |
| 2723 | if (-1==tcsetattr(fd,0,&tios)) { |
| 2724 | FIXME("tcsetattr on fd %d failed!\n",fd); |
| 2725 | return FALSE; |
| 2726 | } |
Mike McCormack | 654fcc7 | 2000-09-16 20:55:12 +0000 | [diff] [blame] | 2727 | close(fd); |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 2728 | return TRUE; |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 2729 | } |
| 2730 | |
Uwe Bonnes | 94113fa | 1998-11-30 10:40:02 +0000 | [diff] [blame] | 2731 | /*********************************************************************** |
| 2732 | * GetCommModemStatus (KERNEL32.285) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 2733 | * |
| 2734 | * Obtains the four control register bits if supported by the hardware. |
| 2735 | * |
| 2736 | * RETURNS |
| 2737 | * |
| 2738 | * True if the communications handle was good and for hardware that |
| 2739 | * control register access, false otherwise. |
Uwe Bonnes | 94113fa | 1998-11-30 10:40:02 +0000 | [diff] [blame] | 2740 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 2741 | BOOL WINAPI GetCommModemStatus( |
| 2742 | HANDLE hFile, /* The communications device. */ |
| 2743 | LPDWORD lpModemStat /* The control register bits. */) |
Uwe Bonnes | 94113fa | 1998-11-30 10:40:02 +0000 | [diff] [blame] | 2744 | { |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 2745 | int fd,mstat, result=FALSE; |
| 2746 | |
| 2747 | *lpModemStat=0; |
| 2748 | #ifdef TIOCMGET |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 2749 | fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE ); |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 2750 | if(fd<0) |
| 2751 | return FALSE; |
| 2752 | result = ioctl(fd, TIOCMGET, &mstat); |
| 2753 | close(fd); |
| 2754 | if (result == -1) |
| 2755 | { |
| 2756 | TRACE("ioctl failed\n"); |
| 2757 | return FALSE; |
| 2758 | } |
Dimitrie O. Paun | 5bea4f8 | 2000-11-25 01:29:00 +0000 | [diff] [blame] | 2759 | #ifdef TIOCM_CTS |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 2760 | if (mstat & TIOCM_CTS) |
| 2761 | *lpModemStat |= MS_CTS_ON; |
Dimitrie O. Paun | 5bea4f8 | 2000-11-25 01:29:00 +0000 | [diff] [blame] | 2762 | #endif |
| 2763 | #ifdef TIOCM_DSR |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 2764 | if (mstat & TIOCM_DSR) |
| 2765 | *lpModemStat |= MS_DSR_ON; |
Dimitrie O. Paun | 5bea4f8 | 2000-11-25 01:29:00 +0000 | [diff] [blame] | 2766 | #endif |
| 2767 | #ifdef TIOCM_RNG |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 2768 | if (mstat & TIOCM_RNG) |
| 2769 | *lpModemStat |= MS_RING_ON; |
Dimitrie O. Paun | 5bea4f8 | 2000-11-25 01:29:00 +0000 | [diff] [blame] | 2770 | #endif |
| 2771 | #ifdef TIOCM_CAR |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 2772 | /*FIXME: Not really sure about RLSD UB 990810*/ |
| 2773 | if (mstat & TIOCM_CAR) |
| 2774 | *lpModemStat |= MS_RLSD_ON; |
Dimitrie O. Paun | 5bea4f8 | 2000-11-25 01:29:00 +0000 | [diff] [blame] | 2775 | #endif |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 2776 | TRACE("%s%s%s%s\n", |
| 2777 | (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"", |
| 2778 | (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"", |
| 2779 | (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"", |
| 2780 | (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":""); |
Uwe Bonnes | 94113fa | 1998-11-30 10:40:02 +0000 | [diff] [blame] | 2781 | return TRUE; |
Uwe Bonnes | 684ee2c | 1999-08-14 15:53:50 +0000 | [diff] [blame] | 2782 | #else |
| 2783 | return FALSE; |
| 2784 | #endif |
Uwe Bonnes | 94113fa | 1998-11-30 10:40:02 +0000 | [diff] [blame] | 2785 | } |
Mike McCormack | 1eac191 | 2000-11-13 19:27:21 +0000 | [diff] [blame] | 2786 | |
| 2787 | VOID COMM_WaitCommEventService(void **args) |
| 2788 | { |
| 2789 | LPOVERLAPPED lpOverlapped = (LPOVERLAPPED)args[0]; |
| 2790 | LPDWORD buffer = (LPDWORD)args[1]; |
| 2791 | DWORD events = (DWORD)args[2]; |
| 2792 | |
| 2793 | TRACE("overlapped %p wait complete %p <- %lx\n",lpOverlapped,buffer,events); |
| 2794 | if(buffer) |
| 2795 | *buffer = events; |
| 2796 | |
Mike McCormack | 1c80bc9 | 2000-12-29 19:35:25 +0000 | [diff] [blame] | 2797 | lpOverlapped->Internal = STATUS_SUCCESS; |
Mike McCormack | 1eac191 | 2000-11-13 19:27:21 +0000 | [diff] [blame] | 2798 | SetEvent( lpOverlapped->hEvent); |
Mike McCormack | 1c80bc9 | 2000-12-29 19:35:25 +0000 | [diff] [blame] | 2799 | CloseHandle(lpOverlapped->InternalHigh); |
Mike McCormack | 1eac191 | 2000-11-13 19:27:21 +0000 | [diff] [blame] | 2800 | } |
| 2801 | |
Uwe Bonnes | 94113fa | 1998-11-30 10:40:02 +0000 | [diff] [blame] | 2802 | /*********************************************************************** |
| 2803 | * WaitCommEvent (KERNEL32.719) |
Mike McCormack | 1eac191 | 2000-11-13 19:27:21 +0000 | [diff] [blame] | 2804 | * |
| 2805 | * Wait until something interesting happens on a COMM port. |
| 2806 | * Interesting things (events) are set by calling SetCommMask before |
| 2807 | * this function is called. |
| 2808 | * |
| 2809 | * RETURNS: |
| 2810 | * TRUE if successful |
| 2811 | * FALSE if failure |
| 2812 | * |
| 2813 | * The set of detected events will be written to *lpdwEventMask |
| 2814 | * ERROR_IO_PENDING will be returned the overlapped structure was passed |
| 2815 | * |
| 2816 | * BUGS: |
| 2817 | * Only supports EV_RXCHAR and EV_TXEMPTY |
Uwe Bonnes | 94113fa | 1998-11-30 10:40:02 +0000 | [diff] [blame] | 2818 | */ |
Mike McCormack | 1eac191 | 2000-11-13 19:27:21 +0000 | [diff] [blame] | 2819 | BOOL WINAPI WaitCommEvent( |
Patrik Stridvall | 2b3aa61 | 2000-12-01 23:58:28 +0000 | [diff] [blame] | 2820 | HANDLE hFile, /* [in] handle of comm port to wait for */ |
| 2821 | LPDWORD lpdwEvents, /* [out] event(s) that were detected */ |
| 2822 | LPOVERLAPPED lpOverlapped /* [in/out] for Asynchronous waiting */ |
Mike McCormack | 1eac191 | 2000-11-13 19:27:21 +0000 | [diff] [blame] | 2823 | ) { |
| 2824 | OVERLAPPED ov; |
| 2825 | LPOVERLAPPED lpov; |
| 2826 | int ret; |
| 2827 | |
| 2828 | TRACE("(%x %p %p )\n",hFile, lpdwEvents,lpOverlapped); |
| 2829 | |
| 2830 | /* if there is no overlapped structure, create our own */ |
| 2831 | if(!lpOverlapped) |
| 2832 | { |
| 2833 | ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL); |
| 2834 | lpov = &ov; |
| 2835 | } |
| 2836 | else |
| 2837 | lpov = lpOverlapped; |
| 2838 | |
| 2839 | /* check that the overlapped structure has a valid event flag */ |
| 2840 | if ( (lpov->hEvent==0) || (lpov->hEvent == INVALID_HANDLE_VALUE) ) |
Mike McCormack | 1c80bc9 | 2000-12-29 19:35:25 +0000 | [diff] [blame] | 2841 | { |
Mike McCormack | 1eac191 | 2000-11-13 19:27:21 +0000 | [diff] [blame] | 2842 | ERR("Couldn't create Event flag for Overlapped structure\n"); |
| 2843 | SetLastError(ERROR_INVALID_PARAMETER); |
| 2844 | return FALSE; |
| 2845 | } |
| 2846 | |
Mike McCormack | 1c80bc9 | 2000-12-29 19:35:25 +0000 | [diff] [blame] | 2847 | ResetEvent(lpov->hEvent); |
| 2848 | |
| 2849 | lpov->Internal = STATUS_PENDING; |
| 2850 | lpov->InternalHigh = 0; |
Mike McCormack | 1eac191 | 2000-11-13 19:27:21 +0000 | [diff] [blame] | 2851 | lpov->Offset = 0; |
| 2852 | lpov->OffsetHigh = 0; |
| 2853 | |
| 2854 | /* start an ASYNCHRONOUS WaitCommEvent */ |
| 2855 | SERVER_START_REQ |
| 2856 | { |
| 2857 | struct create_async_request *req = server_alloc_req( sizeof(*req), 0 ); |
| 2858 | |
| 2859 | req->file_handle = hFile; |
| 2860 | req->overlapped = lpov; |
| 2861 | req->buffer = lpdwEvents; |
| 2862 | req->count = 0; |
| 2863 | req->func = COMM_WaitCommEventService; |
| 2864 | req->type = ASYNC_TYPE_WAIT; |
| 2865 | |
| 2866 | ret=server_call( REQ_CREATE_ASYNC ); |
| 2867 | |
Mike McCormack | 1c80bc9 | 2000-12-29 19:35:25 +0000 | [diff] [blame] | 2868 | lpov->InternalHigh = req->ov_handle; |
Mike McCormack | 1eac191 | 2000-11-13 19:27:21 +0000 | [diff] [blame] | 2869 | } |
| 2870 | SERVER_END_REQ; |
| 2871 | |
| 2872 | if(ret) |
| 2873 | { |
| 2874 | if(!lpOverlapped) |
| 2875 | CloseHandle(lpov->hEvent); |
| 2876 | TRACE("server call failed.\n"); |
| 2877 | return FALSE; |
| 2878 | } |
| 2879 | |
Mike McCormack | 1c80bc9 | 2000-12-29 19:35:25 +0000 | [diff] [blame] | 2880 | /* activate the overlapped operation */ |
| 2881 | lpov->Internal = STATUS_PENDING; |
| 2882 | |
Mike McCormack | 1eac191 | 2000-11-13 19:27:21 +0000 | [diff] [blame] | 2883 | /* wait ourselves if the caller didn't give us an overlapped struct */ |
| 2884 | if(!lpOverlapped) |
| 2885 | { |
| 2886 | GetOverlappedResult(hFile, lpov, NULL, TRUE); |
| 2887 | CloseHandle(lpov->hEvent); |
| 2888 | lpov->hEvent=0; |
| 2889 | } |
| 2890 | else |
| 2891 | { |
| 2892 | /* caller wants overlapped I/O using GetOverlapped result */ |
| 2893 | SetLastError(ERROR_IO_PENDING); |
| 2894 | return FALSE; |
| 2895 | } |
| 2896 | |
| 2897 | return TRUE; |
Uwe Bonnes | 94113fa | 1998-11-30 10:40:02 +0000 | [diff] [blame] | 2898 | } |
| 2899 | |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2900 | /*********************************************************************** |
Mike McCormack | a341a96 | 2000-07-15 21:36:31 +0000 | [diff] [blame] | 2901 | * GetCommProperties (KERNEL32.286) |
| 2902 | * |
| 2903 | * This function fills in a structure with the capabilities of the |
| 2904 | * communications port driver. |
| 2905 | * |
| 2906 | * RETURNS |
| 2907 | * |
| 2908 | * TRUE on success, FALSE on failure |
| 2909 | * If successful, the lpCommProp structure be filled in with |
| 2910 | * properties of the comm port. |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2911 | */ |
Mike McCormack | a341a96 | 2000-07-15 21:36:31 +0000 | [diff] [blame] | 2912 | BOOL WINAPI GetCommProperties( |
Patrik Stridvall | 2b3aa61 | 2000-12-01 23:58:28 +0000 | [diff] [blame] | 2913 | HANDLE hFile, /* [in] handle of the comm port */ |
| 2914 | LPCOMMPROP lpCommProp /* [out] pointer to struct to be filled */ |
Mike McCormack | a341a96 | 2000-07-15 21:36:31 +0000 | [diff] [blame] | 2915 | ) { |
Mike McCormack | 6a31f96 | 2000-06-15 00:15:11 +0000 | [diff] [blame] | 2916 | FIXME("(%d %p )\n",hFile,lpCommProp); |
Mike McCormack | a341a96 | 2000-07-15 21:36:31 +0000 | [diff] [blame] | 2917 | if(!lpCommProp) |
| 2918 | return FALSE; |
| 2919 | |
| 2920 | /* |
| 2921 | * These values should be valid for LINUX's serial driver |
| 2922 | * FIXME: Perhaps they deserve an #ifdef LINUX |
| 2923 | */ |
| 2924 | memset(lpCommProp,0,sizeof(COMMPROP)); |
| 2925 | lpCommProp->wPacketLength = 1; |
| 2926 | lpCommProp->wPacketVersion = 1; |
| 2927 | lpCommProp->dwServiceMask = SP_SERIALCOMM; |
| 2928 | lpCommProp->dwReserved1 = 0; |
| 2929 | lpCommProp->dwMaxTxQueue = 4096; |
| 2930 | lpCommProp->dwMaxRxQueue = 4096; |
| 2931 | lpCommProp->dwMaxBaud = BAUD_115200; |
| 2932 | lpCommProp->dwProvSubType = PST_RS232; |
| 2933 | lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS ; |
| 2934 | lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING | |
| 2935 | SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ; |
| 2936 | lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 | |
| 2937 | BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 | |
| 2938 | BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ; |
| 2939 | lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ; |
| 2940 | lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 | |
| 2941 | PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE; |
| 2942 | lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue; |
| 2943 | lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue; |
| 2944 | |
Michael McCormack | a848607 | 1999-03-14 12:25:36 +0000 | [diff] [blame] | 2945 | return TRUE; |
| 2946 | } |
| 2947 | |
Stefan Leichter | 00e7c33 | 2000-07-08 18:29:54 +0000 | [diff] [blame] | 2948 | /*********************************************************************** |
Mike McCormack | a341a96 | 2000-07-15 21:36:31 +0000 | [diff] [blame] | 2949 | * FIXME: |
| 2950 | * The functionality of CommConfigDialogA, GetDefaultCommConfig and |
| 2951 | * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL). |
| 2952 | * This is dependent on the type of COMM port, but since it is doubtful |
| 2953 | * anybody will get around to implementing support for fancy serial |
| 2954 | * ports in WINE, this is hardcoded for the time being. The name of |
| 2955 | * this DLL should be stored in and read from the system registry in |
| 2956 | * the hive HKEY_LOCAL_MACHINE, key |
| 2957 | * System\\CurrentControlSet\\Services\\Class\\Ports\\???? |
| 2958 | * where ???? is the port number... that is determined by PNP |
| 2959 | * The DLL should be loaded when the COMM port is opened, and closed |
| 2960 | * when the COMM port is closed. - MJM 20 June 2000 |
| 2961 | ***********************************************************************/ |
| 2962 | static CHAR lpszSerialUI[] = "serialui.dll"; |
| 2963 | |
| 2964 | |
| 2965 | /*********************************************************************** |
| 2966 | * CommConfigDialogA (KERNEL32.140) |
| 2967 | * |
| 2968 | * Raises a dialog that allows the user to configure a comm port. |
| 2969 | * Fills the COMMCONFIG struct with information specified by the user. |
| 2970 | * This function should call a similar routine in the COMM driver... |
| 2971 | * |
| 2972 | * RETURNS |
| 2973 | * |
| 2974 | * TRUE on success, FALSE on failure |
| 2975 | * If successful, the lpCommConfig structure will contain a new |
| 2976 | * configuration for the comm port, as specified by the user. |
| 2977 | * |
| 2978 | * BUGS |
| 2979 | * The library with the CommConfigDialog code is never unloaded. |
| 2980 | * Perhaps this should be done when the comm port is closed? |
| 2981 | */ |
| 2982 | BOOL WINAPI CommConfigDialogA( |
Patrik Stridvall | 2b3aa61 | 2000-12-01 23:58:28 +0000 | [diff] [blame] | 2983 | LPCSTR lpszDevice, /* [in] name of communications device */ |
| 2984 | HANDLE hWnd, /* [in] parent window for the dialog */ |
| 2985 | LPCOMMCONFIG lpCommConfig /* [out] pointer to struct to fill */ |
Mike McCormack | a341a96 | 2000-07-15 21:36:31 +0000 | [diff] [blame] | 2986 | ) { |
| 2987 | FARPROC lpfnCommDialog; |
| 2988 | HMODULE hConfigModule; |
| 2989 | BOOL r; |
| 2990 | |
| 2991 | TRACE("(%p %x %p)\n",lpszDevice, hWnd, lpCommConfig); |
| 2992 | |
| 2993 | hConfigModule = LoadLibraryA(lpszSerialUI); |
| 2994 | if(!hConfigModule) |
| 2995 | return FALSE; |
| 2996 | |
| 2997 | lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L); |
| 2998 | |
| 2999 | if(!lpfnCommDialog) |
| 3000 | return FALSE; |
| 3001 | |
| 3002 | r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig); |
| 3003 | |
| 3004 | /* UnloadLibrary(hConfigModule); */ |
| 3005 | |
| 3006 | return r; |
| 3007 | } |
| 3008 | |
| 3009 | /*********************************************************************** |
| 3010 | * CommConfigDialogW (KERNEL32.141) |
| 3011 | * |
| 3012 | * see CommConfigDialogA for more info |
| 3013 | */ |
| 3014 | BOOL WINAPI CommConfigDialogW( |
Patrik Stridvall | 2b3aa61 | 2000-12-01 23:58:28 +0000 | [diff] [blame] | 3015 | LPCWSTR lpszDevice, /* [in] name of communications device */ |
| 3016 | HANDLE hWnd, /* [in] parent window for the dialog */ |
| 3017 | LPCOMMCONFIG lpCommConfig /* [out] pointer to struct to fill */ |
Mike McCormack | a341a96 | 2000-07-15 21:36:31 +0000 | [diff] [blame] | 3018 | ) { |
| 3019 | BOOL r; |
| 3020 | LPSTR lpDeviceA; |
| 3021 | |
| 3022 | lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice ); |
| 3023 | if(lpDeviceA) |
| 3024 | return FALSE; |
| 3025 | r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig); |
| 3026 | HeapFree( GetProcessHeap(), 0, lpDeviceA ); |
| 3027 | return r; |
| 3028 | } |
| 3029 | |
| 3030 | /*********************************************************************** |
| 3031 | * GetCommConfig (KERNEL32.283) |
| 3032 | * |
| 3033 | * Fill in the COMMCONFIG structure for the comm port hFile |
| 3034 | * |
| 3035 | * RETURNS |
| 3036 | * |
| 3037 | * TRUE on success, FALSE on failure |
| 3038 | * If successful, lpCommConfig contains the comm port configuration. |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 3039 | * |
| 3040 | * BUGS |
| 3041 | * |
| 3042 | * The signature is missing a the parameter for the size of the COMMCONFIG |
| 3043 | * structure/buffer it should be |
| 3044 | * BOOL WINAPI GetCommConfig(HANDLE hFile,LPCOMMCONFIG lpCommConfig,LPDWORD lpdwSize) |
Mike McCormack | a341a96 | 2000-07-15 21:36:31 +0000 | [diff] [blame] | 3045 | */ |
| 3046 | BOOL WINAPI GetCommConfig( |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 3047 | HANDLE hFile, /* The communications device. */ |
| 3048 | LPCOMMCONFIG lpCommConfig /* The communications configuration of the device (if it fits). */ |
| 3049 | /* LPDWORD lpdwSize Initially the size of the configuration buffer/structure, |
| 3050 | afterwards the number of bytes copied to the buffer or the needed size of the buffer. */ |
Mike McCormack | a341a96 | 2000-07-15 21:36:31 +0000 | [diff] [blame] | 3051 | ) { |
| 3052 | BOOL r; |
| 3053 | |
| 3054 | TRACE("(%x %p)\n",hFile,lpCommConfig); |
| 3055 | |
| 3056 | if(lpCommConfig == NULL) |
| 3057 | return FALSE; |
| 3058 | |
| 3059 | lpCommConfig->dwSize = sizeof(COMMCONFIG); |
| 3060 | lpCommConfig->wVersion = 1; |
| 3061 | lpCommConfig->wReserved = 0; |
| 3062 | r = GetCommState(hFile,&lpCommConfig->dcb); |
| 3063 | lpCommConfig->dwProviderSubType = PST_RS232; |
| 3064 | lpCommConfig->dwProviderOffset = 0; |
| 3065 | lpCommConfig->dwProviderSize = 0; |
| 3066 | |
| 3067 | return r; |
| 3068 | } |
| 3069 | |
| 3070 | /*********************************************************************** |
| 3071 | * SetCommConfig (KERNEL32.617) |
| 3072 | * |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 3073 | * Sets the configuration of the commications device. |
| 3074 | * |
| 3075 | * RETURNS |
| 3076 | * |
| 3077 | * True on success, false if the handle was bad is not a communications device. |
Mike McCormack | a341a96 | 2000-07-15 21:36:31 +0000 | [diff] [blame] | 3078 | */ |
| 3079 | BOOL WINAPI SetCommConfig( |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 3080 | HANDLE hFile, /* The communications device. */ |
| 3081 | LPCOMMCONFIG lpCommConfig /* The desired configuration. */ |
Mike McCormack | a341a96 | 2000-07-15 21:36:31 +0000 | [diff] [blame] | 3082 | ) { |
Mike McCormack | a341a96 | 2000-07-15 21:36:31 +0000 | [diff] [blame] | 3083 | TRACE("(%x %p)\n",hFile,lpCommConfig); |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 3084 | return SetCommState(hFile,&lpCommConfig->dcb); |
Mike McCormack | a341a96 | 2000-07-15 21:36:31 +0000 | [diff] [blame] | 3085 | } |
| 3086 | |
| 3087 | /*********************************************************************** |
Mike McCormack | 556d11d | 2000-09-18 01:41:07 +0000 | [diff] [blame] | 3088 | * SetDefaultCommConfigA (KERNEL32.638) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 3089 | * |
| 3090 | * Initializes the default configuration for the specified communication |
| 3091 | * device. (ascii) |
| 3092 | * |
| 3093 | * RETURNS |
| 3094 | * |
| 3095 | * True if the device was found and the defaults set, false otherwise |
Mike McCormack | a341a96 | 2000-07-15 21:36:31 +0000 | [diff] [blame] | 3096 | */ |
| 3097 | BOOL WINAPI SetDefaultCommConfigA( |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 3098 | LPCSTR lpszDevice, /* The ascii name of the device targeted for configuration. */ |
| 3099 | LPCOMMCONFIG lpCommConfig, /* The default configuration for the device. */ |
| 3100 | DWORD dwSize /* The number of bytes in the configuration structure. */ |
Mike McCormack | a341a96 | 2000-07-15 21:36:31 +0000 | [diff] [blame] | 3101 | ) { |
| 3102 | FARPROC lpfnSetDefaultCommConfig; |
| 3103 | HMODULE hConfigModule; |
| 3104 | BOOL r; |
| 3105 | |
| 3106 | TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize); |
| 3107 | |
| 3108 | hConfigModule = LoadLibraryA(lpszSerialUI); |
| 3109 | if(!hConfigModule) |
| 3110 | return FALSE; |
| 3111 | |
| 3112 | lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L); |
| 3113 | |
| 3114 | if(! lpfnSetDefaultCommConfig) |
| 3115 | return TRUE; |
| 3116 | |
| 3117 | r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize); |
| 3118 | |
| 3119 | /* UnloadLibrary(hConfigModule); */ |
| 3120 | |
| 3121 | return r; |
| 3122 | } |
| 3123 | |
| 3124 | |
| 3125 | /*********************************************************************** |
| 3126 | * SetDefaultCommConfigW (KERNEL32.639) |
| 3127 | * |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 3128 | * Initializes the default configuration for the specified |
| 3129 | * communication device. (unicode) |
| 3130 | * |
| 3131 | * RETURNS |
| 3132 | * |
Mike McCormack | a341a96 | 2000-07-15 21:36:31 +0000 | [diff] [blame] | 3133 | */ |
| 3134 | BOOL WINAPI SetDefaultCommConfigW( |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 3135 | LPCWSTR lpszDevice, /* The unicode name of the device targeted for configuration. */ |
| 3136 | LPCOMMCONFIG lpCommConfig, /* The default configuration for the device. */ |
| 3137 | DWORD dwSize /* The number of bytes in the configuration structure. */ |
Mike McCormack | a341a96 | 2000-07-15 21:36:31 +0000 | [diff] [blame] | 3138 | ) { |
| 3139 | BOOL r; |
| 3140 | LPSTR lpDeviceA; |
| 3141 | |
| 3142 | TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize); |
| 3143 | |
| 3144 | lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice ); |
| 3145 | if(lpDeviceA) |
| 3146 | return FALSE; |
| 3147 | r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize); |
| 3148 | HeapFree( GetProcessHeap(), 0, lpDeviceA ); |
| 3149 | return r; |
| 3150 | } |
| 3151 | |
| 3152 | |
| 3153 | /*********************************************************************** |
Stefan Leichter | 00e7c33 | 2000-07-08 18:29:54 +0000 | [diff] [blame] | 3154 | * GetDefaultCommConfigA (KERNEL32.313) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 3155 | * |
| 3156 | * Acquires the default configuration of the specified communication device. (unicode) |
| 3157 | * |
| 3158 | * RETURNS |
| 3159 | * |
| 3160 | * True on successful reading of the default configuration, |
| 3161 | * if the device is not found or the buffer is too small. |
Stefan Leichter | 00e7c33 | 2000-07-08 18:29:54 +0000 | [diff] [blame] | 3162 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 3163 | BOOL WINAPI GetDefaultCommConfigA( |
| 3164 | LPCSTR lpszName, /* The ascii name of the device targeted for configuration. */ |
| 3165 | LPCOMMCONFIG lpCC, /* The default configuration for the device. */ |
| 3166 | LPDWORD lpdwSize ) /* Initially the size of the default configuration buffer, |
| 3167 | afterwards the number of bytes copied to the buffer or the needed size of the buffer. */ |
| 3168 | { |
Stefan Leichter | 00e7c33 | 2000-07-08 18:29:54 +0000 | [diff] [blame] | 3169 | LPDCB lpdcb = &(lpCC->dcb); |
| 3170 | char temp[40]; |
| 3171 | |
| 3172 | if (strncasecmp(lpszName,"COM",3)) { |
| 3173 | ERR("not implemented for <%s>\n", lpszName); |
| 3174 | return FALSE; |
| 3175 | } |
| 3176 | |
| 3177 | if (!ValidCOMPort(lpszName[3]-'1')) |
| 3178 | return FALSE; |
| 3179 | |
| 3180 | TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize ); |
| 3181 | if (*lpdwSize < sizeof(COMMCONFIG)) { |
| 3182 | *lpdwSize = sizeof(COMMCONFIG); |
| 3183 | return FALSE; |
| 3184 | } |
| 3185 | |
| 3186 | *lpdwSize = sizeof(COMMCONFIG); |
| 3187 | |
| 3188 | lpCC->dwSize = sizeof(COMMCONFIG); |
| 3189 | lpCC->wVersion = 1; |
| 3190 | lpCC->dwProviderSubType = PST_RS232; |
| 3191 | lpCC->dwProviderOffset = 0L; |
| 3192 | lpCC->dwProviderSize = 0L; |
| 3193 | |
| 3194 | (void) sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]); |
| 3195 | FIXME("setting %s as default\n", temp); |
| 3196 | |
| 3197 | return BuildCommDCBA( temp, lpdcb); |
| 3198 | } |
| 3199 | |
| 3200 | /************************************************************************** |
| 3201 | * GetDefaultCommConfigW (KERNEL32.314) |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 3202 | * |
| 3203 | * Acquires the default configuration of the specified communication device. (unicode) |
| 3204 | * |
| 3205 | * RETURNS |
| 3206 | * |
| 3207 | * True on successful reading of the default configuration, |
| 3208 | * if the device is not found or the buffer is too small. |
Stefan Leichter | 00e7c33 | 2000-07-08 18:29:54 +0000 | [diff] [blame] | 3209 | */ |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 3210 | BOOL WINAPI GetDefaultCommConfigW( |
| 3211 | LPCWSTR lpszName, /* The unicode name of the device targeted for configuration. */ |
| 3212 | LPCOMMCONFIG lpCC, /* The default configuration for the device. */ |
| 3213 | LPDWORD lpdwSize /* Initially the size of the default configuration buffer, |
| 3214 | afterwards the number of bytes copied to the buffer or the needed size of the buffer. */ |
| 3215 | ) { |
| 3216 | BOOL ret = FALSE; |
Stefan Leichter | 00e7c33 | 2000-07-08 18:29:54 +0000 | [diff] [blame] | 3217 | LPSTR lpszNameA; |
Stefan Leichter | 00e7c33 | 2000-07-08 18:29:54 +0000 | [diff] [blame] | 3218 | |
Gerald Pfeifer | 5dae382 | 2000-07-15 14:58:32 +0000 | [diff] [blame] | 3219 | TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize); |
Stefan Leichter | 00e7c33 | 2000-07-08 18:29:54 +0000 | [diff] [blame] | 3220 | lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName ); |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 3221 | if (lpszNameA) |
| 3222 | { |
Stefan Leichter | 00e7c33 | 2000-07-08 18:29:54 +0000 | [diff] [blame] | 3223 | ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize); |
| 3224 | HeapFree( GetProcessHeap(), 0, lpszNameA ); |
Andrew Johnston | 03131aa | 2000-12-19 23:33:03 +0000 | [diff] [blame] | 3225 | } |
Stefan Leichter | 00e7c33 | 2000-07-08 18:29:54 +0000 | [diff] [blame] | 3226 | return ret; |
| 3227 | } |
Mike McCormack | 44b5bf5 | 2000-09-07 18:39:51 +0000 | [diff] [blame] | 3228 | |