aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGlenn Morris2008-06-13 08:08:20 +0000
committerGlenn Morris2008-06-13 08:08:20 +0000
commitd888760c951787ccc3a48d7f90bc798ee0996b9b (patch)
tree1aabac1ac803d6d2e8614eef3dcf35874e5841de /src
parent07d99e7544ffa51339ae1ba1a3785f49247e0c6e (diff)
downloademacs-d888760c951787ccc3a48d7f90bc798ee0996b9b.tar.gz
emacs-d888760c951787ccc3a48d7f90bc798ee0996b9b.zip
Daniel Engeler <engeler at gmail.com>
These changes add serial port access. * process.c: Add HAVE_SERIAL. (Fdelete_process, Fprocess_status, Fset_process_buffer) (Fset_process_filter, Fset_process_sentinel, Fprocess_contact) (list_processes_1, select_wrapper, Fstop_process) (Fcontinue_process, Fprocess_send_eof, kill_buffer_processes) (status_notify): Modify to handle serial processes. [HAVE_SERIAL] (Fserial_process_configure) [HAVE_SERIAL] (make_serial_process_unwind, Fmake_serial_process): New functions. * process.h (struct Lisp_Process): Add `type'. * sysdep.c [HAVE_TERMIOS] (serial_open, serial_configure): New functions. * w32.c (_sys_read_ahead, sys_read, sys_write): Modify to handle serial ports. (serial_open, serial_configure) New functions. * w32.h: Add FILE_SERIAL. (struct _child_process): Add ovl_read, ovl_write.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog21
-rw-r--r--src/process.c496
-rw-r--r--src/process.h10
-rw-r--r--src/sysdep.c199
-rw-r--r--src/w32.c315
-rw-r--r--src/w32.h3
6 files changed, 999 insertions, 45 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index a648ca5cbbf..e575375e560 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,24 @@
12008-06-13 Daniel Engeler <engeler@gmail.com>
2
3 These changes add serial port access.
4 * process.c: Add HAVE_SERIAL.
5 (Fdelete_process, Fprocess_status, Fset_process_buffer)
6 (Fset_process_filter, Fset_process_sentinel, Fprocess_contact)
7 (list_processes_1, select_wrapper, Fstop_process)
8 (Fcontinue_process, Fprocess_send_eof, kill_buffer_processes)
9 (status_notify): Modify to handle serial processes.
10 [HAVE_SERIAL] (Fserial_process_configure)
11 [HAVE_SERIAL] (make_serial_process_unwind, Fmake_serial_process):
12 New functions.
13 * process.h (struct Lisp_Process): Add `type'.
14 * sysdep.c [HAVE_TERMIOS] (serial_open, serial_configure):
15 New functions.
16 * w32.c (_sys_read_ahead, sys_read, sys_write): Modify to handle
17 serial ports.
18 (serial_open, serial_configure) New functions.
19 * w32.h: Add FILE_SERIAL.
20 (struct _child_process): Add ovl_read, ovl_write.
21
12008-06-13 Kenichi Handa <handa@m17n.org> 222008-06-13 Kenichi Handa <handa@m17n.org>
2 23
3 * dispextern.h (enum lface_attribute_index): New member 24 * dispextern.h (enum lface_attribute_index): New member
diff --git a/src/process.c b/src/process.c
index 413bd8522b3..1d49f8fc2b4 100644
--- a/src/process.c
+++ b/src/process.c
@@ -136,9 +136,13 @@ Lisp_Object Qprocessp;
136Lisp_Object Qrun, Qstop, Qsignal; 136Lisp_Object Qrun, Qstop, Qsignal;
137Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten; 137Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten;
138Lisp_Object Qlocal, Qipv4, Qdatagram; 138Lisp_Object Qlocal, Qipv4, Qdatagram;
139Lisp_Object Qreal, Qnetwork, Qserial;
139#ifdef AF_INET6 140#ifdef AF_INET6
140Lisp_Object Qipv6; 141Lisp_Object Qipv6;
141#endif 142#endif
143Lisp_Object QCport, QCspeed, QCprocess;
144Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
145Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;
142Lisp_Object QCname, QCbuffer, QChost, QCservice, QCtype; 146Lisp_Object QCname, QCbuffer, QChost, QCservice, QCtype;
143Lisp_Object QClocal, QCremote, QCcoding; 147Lisp_Object QClocal, QCremote, QCcoding;
144Lisp_Object QCserver, QCnowait, QCnoquery, QCstop; 148Lisp_Object QCserver, QCnowait, QCnoquery, QCstop;
@@ -155,15 +159,16 @@ extern Lisp_Object QCfamily;
155/* QCfilter is defined in keyboard.c. */ 159/* QCfilter is defined in keyboard.c. */
156extern Lisp_Object QCfilter; 160extern Lisp_Object QCfilter;
157 161
158/* a process object is a network connection when its childp field is neither
159 Qt nor Qnil but is instead a property list (KEY VAL ...). */
160
161#ifdef HAVE_SOCKETS 162#ifdef HAVE_SOCKETS
162#define NETCONN_P(p) (CONSP (XPROCESS (p)->childp)) 163#define NETCONN_P(p) (EQ (XPROCESS (p)->type, Qnetwork))
163#define NETCONN1_P(p) (CONSP ((p)->childp)) 164#define NETCONN1_P(p) (EQ ((p)->type, Qnetwork))
165#define SERIALCONN_P(p) (EQ (XPROCESS (p)->type, Qserial))
166#define SERIALCONN1_P(p) (EQ ((p)->type, Qserial))
164#else 167#else
165#define NETCONN_P(p) 0 168#define NETCONN_P(p) 0
166#define NETCONN1_P(p) 0 169#define NETCONN1_P(p) 0
170#define SERIALCONN_P(p) 0
171#define SERIALCONN1_P(p) 0
167#endif /* HAVE_SOCKETS */ 172#endif /* HAVE_SOCKETS */
168 173
169/* Define first descriptor number available for subprocesses. */ 174/* Define first descriptor number available for subprocesses. */
@@ -186,6 +191,17 @@ extern Lisp_Object QCfilter;
186 191
187extern char *get_operating_system_release (); 192extern char *get_operating_system_release ();
188 193
194/* Serial processes require termios or Windows. */
195#if defined (HAVE_TERMIOS) || defined (WINDOWSNT)
196#define HAVE_SERIAL
197#endif
198
199#ifdef HAVE_SERIAL
200/* From sysdep.c or w32.c */
201extern int serial_open (char *port);
202extern void serial_configure (struct Lisp_Process *p, Lisp_Object contact);
203#endif
204
189#ifndef USE_CRT_DLL 205#ifndef USE_CRT_DLL
190extern int errno; 206extern int errno;
191#endif 207#endif
@@ -784,7 +800,7 @@ nil, indicating the current buffer's process. */)
784 p = XPROCESS (process); 800 p = XPROCESS (process);
785 801
786 p->raw_status_new = 0; 802 p->raw_status_new = 0;
787 if (NETCONN1_P (p)) 803 if (NETCONN1_P (p) || SERIALCONN1_P (p))
788 { 804 {
789 p->status = Fcons (Qexit, Fcons (make_number (0), Qnil)); 805 p->status = Fcons (Qexit, Fcons (make_number (0), Qnil));
790 p->tick = ++process_tick; 806 p->tick = ++process_tick;
@@ -861,7 +877,7 @@ nil, indicating the current buffer's process. */)
861 status = p->status; 877 status = p->status;
862 if (CONSP (status)) 878 if (CONSP (status))
863 status = XCAR (status); 879 status = XCAR (status);
864 if (NETCONN1_P (p)) 880 if (NETCONN1_P (p) || SERIALCONN1_P (p))
865 { 881 {
866 if (EQ (status, Qexit)) 882 if (EQ (status, Qexit))
867 status = Qclosed; 883 status = Qclosed;
@@ -919,7 +935,8 @@ DEFUN ("process-command", Fprocess_command, Sprocess_command, 1, 1, 0,
919 doc: /* Return the command that was executed to start PROCESS. 935 doc: /* Return the command that was executed to start PROCESS.
920This is a list of strings, the first string being the program executed 936This is a list of strings, the first string being the program executed
921and the rest of the strings being the arguments given to it. 937and the rest of the strings being the arguments given to it.
922For a non-child channel, this is nil. */) 938For a network or serial process, this is nil (process is running) or t
939\(process is stopped). */)
923 (process) 940 (process)
924 register Lisp_Object process; 941 register Lisp_Object process;
925{ 942{
@@ -951,7 +968,7 @@ DEFUN ("set-process-buffer", Fset_process_buffer, Sset_process_buffer,
951 CHECK_BUFFER (buffer); 968 CHECK_BUFFER (buffer);
952 p = XPROCESS (process); 969 p = XPROCESS (process);
953 p->buffer = buffer; 970 p->buffer = buffer;
954 if (NETCONN1_P (p)) 971 if (NETCONN1_P (p) || SERIALCONN1_P (p))
955 p->childp = Fplist_put (p->childp, QCbuffer, buffer); 972 p->childp = Fplist_put (p->childp, QCbuffer, buffer);
956 setup_process_coding_systems (process); 973 setup_process_coding_systems (process);
957 return buffer; 974 return buffer;
@@ -1018,7 +1035,8 @@ The string argument is normally a multibyte string, except:
1018 FD_CLR (p->infd, &non_keyboard_wait_mask); 1035 FD_CLR (p->infd, &non_keyboard_wait_mask);
1019 } 1036 }
1020 else if (EQ (p->filter, Qt) 1037 else if (EQ (p->filter, Qt)
1021 && !EQ (p->command, Qt)) /* Network process not stopped. */ 1038 /* Network or serial process not stopped: */
1039 && !EQ (p->command, Qt))
1022 { 1040 {
1023 FD_SET (p->infd, &input_wait_mask); 1041 FD_SET (p->infd, &input_wait_mask);
1024 FD_SET (p->infd, &non_keyboard_wait_mask); 1042 FD_SET (p->infd, &non_keyboard_wait_mask);
@@ -1026,7 +1044,7 @@ The string argument is normally a multibyte string, except:
1026 } 1044 }
1027 1045
1028 p->filter = filter; 1046 p->filter = filter;
1029 if (NETCONN1_P (p)) 1047 if (NETCONN1_P (p) || SERIALCONN1_P (p))
1030 p->childp = Fplist_put (p->childp, QCfilter, filter); 1048 p->childp = Fplist_put (p->childp, QCfilter, filter);
1031 setup_process_coding_systems (process); 1049 setup_process_coding_systems (process);
1032 return filter; 1050 return filter;
@@ -1057,7 +1075,7 @@ It gets two arguments: the process, and a string describing the change. */)
1057 p = XPROCESS (process); 1075 p = XPROCESS (process);
1058 1076
1059 p->sentinel = sentinel; 1077 p->sentinel = sentinel;
1060 if (NETCONN1_P (p)) 1078 if (NETCONN1_P (p) || SERIALCONN1_P (p))
1061 p->childp = Fplist_put (p->childp, QCsentinel, sentinel); 1079 p->childp = Fplist_put (p->childp, QCsentinel, sentinel);
1062 return sentinel; 1080 return sentinel;
1063} 1081}
@@ -1162,11 +1180,13 @@ Lisp_Object Fprocess_datagram_address ();
1162DEFUN ("process-contact", Fprocess_contact, Sprocess_contact, 1180DEFUN ("process-contact", Fprocess_contact, Sprocess_contact,
1163 1, 2, 0, 1181 1, 2, 0,
1164 doc: /* Return the contact info of PROCESS; t for a real child. 1182 doc: /* Return the contact info of PROCESS; t for a real child.
1165For a net connection, the value depends on the optional KEY arg. 1183For a network or serial connection, the value depends on the optional
1166If KEY is nil, value is a cons cell of the form (HOST SERVICE), 1184KEY arg. If KEY is nil, value is a cons cell of the form (HOST
1167if KEY is t, the complete contact information for the connection is 1185SERVICE) for a network connection or (PORT SPEED) for a serial
1168returned, else the specific value for the keyword KEY is returned. 1186connection. If KEY is t, the complete contact information for the
1169See `make-network-process' for a list of keywords. */) 1187connection is returned, else the specific value for the keyword KEY is
1188returned. See `make-network-process' or `make-serial-process' for a
1189list of keywords. */)
1170 (process, key) 1190 (process, key)
1171 register Lisp_Object process, key; 1191 register Lisp_Object process, key;
1172{ 1192{
@@ -1182,11 +1202,14 @@ See `make-network-process' for a list of keywords. */)
1182 Fprocess_datagram_address (process)); 1202 Fprocess_datagram_address (process));
1183#endif 1203#endif
1184 1204
1185 if (!NETCONN_P (process) || EQ (key, Qt)) 1205 if ((!NETCONN_P (process) && !SERIALCONN_P (process)) || EQ (key, Qt))
1186 return contact; 1206 return contact;
1187 if (NILP (key)) 1207 if (NILP (key) && NETCONN_P (process))
1188 return Fcons (Fplist_get (contact, QChost), 1208 return Fcons (Fplist_get (contact, QChost),
1189 Fcons (Fplist_get (contact, QCservice), Qnil)); 1209 Fcons (Fplist_get (contact, QCservice), Qnil));
1210 if (NILP (key) && SERIALCONN_P (process))
1211 return Fcons (Fplist_get (contact, QCport),
1212 Fcons (Fplist_get (contact, QCspeed), Qnil));
1190 return Fplist_get (contact, key); 1213 return Fplist_get (contact, key);
1191} 1214}
1192 1215
@@ -1225,6 +1248,19 @@ a socket connection. */)
1225 return XPROCESS (process)->type; 1248 return XPROCESS (process)->type;
1226} 1249}
1227#endif 1250#endif
1251
1252DEFUN ("process-type", Fprocess_type, Sprocess_type, 1, 1, 0,
1253 doc: /* Return the connection type of PROCESS.
1254The value is either the symbol `real', `network', or `serial'.
1255PROCESS may be a process, a buffer, the name of a process or buffer, or
1256nil, indicating the current buffer's process. */)
1257 (process)
1258 Lisp_Object process;
1259{
1260 Lisp_Object proc;
1261 proc = get_process (process);
1262 return XPROCESS (proc)->type;
1263}
1228 1264
1229#ifdef HAVE_SOCKETS 1265#ifdef HAVE_SOCKETS
1230DEFUN ("format-network-address", Fformat_network_address, Sformat_network_address, 1266DEFUN ("format-network-address", Fformat_network_address, Sformat_network_address,
@@ -1325,7 +1361,7 @@ list_processes_1 (query_only)
1325 1361
1326 proc = Fcdr (XCAR (tail)); 1362 proc = Fcdr (XCAR (tail));
1327 p = XPROCESS (proc); 1363 p = XPROCESS (proc);
1328 if (NILP (p->childp)) 1364 if (NILP (p->type))
1329 continue; 1365 continue;
1330 if (!NILP (query_only) && p->kill_without_query) 1366 if (!NILP (query_only) && p->kill_without_query)
1331 continue; 1367 continue;
@@ -1393,7 +1429,7 @@ list_processes_1 (query_only)
1393 1429
1394 proc = Fcdr (XCAR (tail)); 1430 proc = Fcdr (XCAR (tail));
1395 p = XPROCESS (proc); 1431 p = XPROCESS (proc);
1396 if (NILP (p->childp)) 1432 if (NILP (p->type))
1397 continue; 1433 continue;
1398 if (!NILP (query_only) && p->kill_without_query) 1434 if (!NILP (query_only) && p->kill_without_query)
1399 continue; 1435 continue;
@@ -1418,7 +1454,7 @@ list_processes_1 (query_only)
1418#endif 1454#endif
1419 Fprinc (symbol, Qnil); 1455 Fprinc (symbol, Qnil);
1420 } 1456 }
1421 else if (NETCONN1_P (p)) 1457 else if (NETCONN1_P (p) || SERIALCONN1_P (p))
1422 { 1458 {
1423 if (EQ (symbol, Qexit)) 1459 if (EQ (symbol, Qexit))
1424 write_string ("closed", -1); 1460 write_string ("closed", -1);
@@ -1429,6 +1465,10 @@ list_processes_1 (query_only)
1429 else 1465 else
1430 Fprinc (symbol, Qnil); 1466 Fprinc (symbol, Qnil);
1431 } 1467 }
1468 else if (SERIALCONN1_P (p))
1469 {
1470 write_string ("running", -1);
1471 }
1432 else 1472 else
1433 Fprinc (symbol, Qnil); 1473 Fprinc (symbol, Qnil);
1434 1474
@@ -1493,6 +1533,22 @@ list_processes_1 (query_only)
1493 (STRINGP (host) ? (char *)SDATA (host) : "?")); 1533 (STRINGP (host) ? (char *)SDATA (host) : "?"));
1494 insert_string (tembuf); 1534 insert_string (tembuf);
1495 } 1535 }
1536 else if (SERIALCONN1_P (p))
1537 {
1538 Lisp_Object port = Fplist_get (p->childp, QCport);
1539 Lisp_Object speed = Fplist_get (p->childp, QCspeed);
1540 insert_string ("(serial port ");
1541 if (STRINGP (port))
1542 insert_string (SDATA (port));
1543 else
1544 insert_string ("?");
1545 if (INTEGERP (speed))
1546 {
1547 sprintf (tembuf, " at %d b/s", XINT (speed));
1548 insert_string (tembuf);
1549 }
1550 insert_string (")\n");
1551 }
1496 else 1552 else
1497 { 1553 {
1498 tem = p->command; 1554 tem = p->command;
@@ -1619,6 +1675,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
1619 1675
1620 XPROCESS (proc)->childp = Qt; 1676 XPROCESS (proc)->childp = Qt;
1621 XPROCESS (proc)->plist = Qnil; 1677 XPROCESS (proc)->plist = Qnil;
1678 XPROCESS (proc)->type = Qreal;
1622 XPROCESS (proc)->buffer = buffer; 1679 XPROCESS (proc)->buffer = buffer;
1623 XPROCESS (proc)->sentinel = Qnil; 1680 XPROCESS (proc)->sentinel = Qnil;
1624 XPROCESS (proc)->filter = Qnil; 1681 XPROCESS (proc)->filter = Qnil;
@@ -2656,6 +2713,312 @@ unwind_request_sigio (dummy)
2656} 2713}
2657#endif 2714#endif
2658 2715
2716#ifdef HAVE_SERIAL
2717DEFUN ("serial-process-configure",
2718 Fserial_process_configure,
2719 Sserial_process_configure,
2720 0, MANY, 0,
2721 doc: /* Configure speed, bytesize, etc. of a serial process.
2722
2723Arguments are specified as keyword/argument pairs. Attributes that
2724are not given are re-initialized from the process's current
2725configuration (available via the function `process-contact') or set to
2726reasonable default values. The following arguments are defined:
2727
2728:process PROCESS
2729:name NAME
2730:buffer BUFFER
2731:port PORT
2732-- Any of these arguments can be given to identify the process that is
2733to be configured. If none of these arguments is given, the current
2734buffer's process is used.
2735
2736:speed SPEED -- SPEED is the speed of the serial port in bits per
2737second, also called baud rate. Any value can be given for SPEED, but
2738most serial ports work only at a few defined values between 1200 and
2739115200, with 9600 being the most common value. If SPEED is nil, the
2740serial port is not configured any further, i.e., all other arguments
2741are ignored. This may be useful for special serial ports such as
2742Bluetooth-to-serial converters which can only be configured through AT
2743commands. A value of nil for SPEED can be used only when passed
2744through `make-serial-process' or `serial-term'.
2745
2746:bytesize BYTESIZE -- BYTESIZE is the number of bits per byte, which
2747can be 7 or 8. If BYTESIZE is not given or nil, a value of 8 is used.
2748
2749:parity PARITY -- PARITY can be nil (don't use parity), the symbol
2750`odd' (use odd parity), or the symbol `even' (use even parity). If
2751PARITY is not given, no parity is used.
2752
2753:stopbits STOPBITS -- STOPBITS is the number of stopbits used to
2754terminate a byte transmission. STOPBITS can be 1 or 2. If STOPBITS
2755is not given or nil, 1 stopbit is used.
2756
2757:flowcontrol FLOWCONTROL -- FLOWCONTROL determines the type of
2758flowcontrol to be used, which is either nil (don't use flowcontrol),
2759the symbol `hw' (use RTS/CTS hardware flowcontrol), or the symbol `sw'
2760\(use XON/XOFF software flowcontrol). If FLOWCONTROL is not given, no
2761flowcontrol is used.
2762
2763`serial-process-configure' is called by `make-serial-process' for the
2764initial configuration of the serial port.
2765
2766Examples:
2767
2768\(serial-process-configure :process "/dev/ttyS0" :speed 1200)
2769
2770\(serial-process-configure
2771 :buffer "COM1" :stopbits 1 :parity 'odd :flowcontrol 'hw)
2772
2773\(serial-process-configure :port "\\\\.\\COM13" :bytesize 7)
2774
2775usage: (serial-process-configure &rest ARGS) */)
2776 (nargs, args)
2777 int nargs;
2778 Lisp_Object *args;
2779{
2780 struct Lisp_Process *p;
2781 Lisp_Object contact = Qnil;
2782 Lisp_Object proc = Qnil;
2783 struct gcpro gcpro1;
2784
2785 contact = Flist (nargs, args);
2786 GCPRO1 (contact);
2787
2788 proc = Fplist_get (contact, QCprocess);
2789 if (NILP (proc))
2790 proc = Fplist_get (contact, QCname);
2791 if (NILP (proc))
2792 proc = Fplist_get (contact, QCbuffer);
2793 if (NILP (proc))
2794 proc = Fplist_get (contact, QCport);
2795 proc = get_process (proc);
2796 p = XPROCESS (proc);
2797 if (p->type != Qserial)
2798 error ("Not a serial process");
2799
2800 if (NILP (Fplist_get (p->childp, QCspeed)))
2801 {
2802 UNGCPRO;
2803 return Qnil;
2804 }
2805
2806 serial_configure (p, contact);
2807
2808 UNGCPRO;
2809 return Qnil;
2810}
2811#endif /* HAVE_SERIAL */
2812
2813#ifdef HAVE_SERIAL
2814/* Used by make-serial-process to recover from errors. */
2815Lisp_Object make_serial_process_unwind (Lisp_Object proc)
2816{
2817 if (!PROCESSP (proc))
2818 abort ();
2819 remove_process (proc);
2820 return Qnil;
2821}
2822#endif /* HAVE_SERIAL */
2823
2824#ifdef HAVE_SERIAL
2825DEFUN ("make-serial-process", Fmake_serial_process, Smake_serial_process,
2826 0, MANY, 0,
2827 doc: /* Create and return a serial port process.
2828
2829In Emacs, serial port connections are represented by process objects,
2830so input and output work as for subprocesses, and `delete-process'
2831closes a serial port connection. However, a serial process has no
2832process id, it cannot be signaled, and the status codes are different
2833from normal processes.
2834
2835`make-serial-process' creates a process and a buffer, on which you
2836probably want to use `process-send-string'. Try \\[serial-term] for
2837an interactive terminal. See below for examples.
2838
2839Arguments are specified as keyword/argument pairs. The following
2840arguments are defined:
2841
2842:port PORT -- (mandatory) PORT is the path or name of the serial port.
2843For example, this could be "/dev/ttyS0" on Unix. On Windows, this
2844could be "COM1", or "\\\\.\\COM10" for ports higher than COM9 (double
2845the backslashes in strings).
2846
2847:speed SPEED -- (mandatory) is handled by `serial-process-configure',
2848which is called by `make-serial-process'.
2849
2850:name NAME -- NAME is the name of the process. If NAME is not given,
2851the value of PORT is used.
2852
2853:buffer BUFFER -- BUFFER is the buffer (or buffer-name) to associate
2854with the process. Process output goes at the end of that buffer,
2855unless you specify an output stream or filter function to handle the
2856output. If BUFFER is not given, the value of NAME is used.
2857
2858:coding CODING -- If CODING is a symbol, it specifies the coding
2859system used for both reading and writing for this process. If CODING
2860is a cons (DECODING . ENCODING), DECODING is used for reading, and
2861ENCODING is used for writing.
2862
2863:noquery BOOL -- When exiting Emacs, query the user if BOOL is nil and
2864the process is running. If BOOL is not given, query before exiting.
2865
2866:stop BOOL -- Start process in the `stopped' state if BOOL is non-nil.
2867In the stopped state, a serial process does not accept incoming data,
2868but you can send outgoing data. The stopped state is cleared by
2869`continue-process' and set by `stop-process'.
2870
2871:filter FILTER -- Install FILTER as the process filter.
2872
2873:sentinel SENTINEL -- Install SENTINEL as the process sentinel.
2874
2875:plist PLIST -- Install PLIST as the initial plist of the process.
2876
2877:speed
2878:bytesize
2879:parity
2880:stopbits
2881:flowcontrol
2882-- These arguments are handled by `serial-process-configure', which is
2883called by `make-serial-process'.
2884
2885The original argument list, possibly modified by later configuration,
2886is available via the function `process-contact'.
2887
2888Examples:
2889
2890\(make-serial-process :port "/dev/ttyS0" :speed 9600)
2891
2892\(make-serial-process :port "COM1" :speed 115200 :stopbits 2)
2893
2894\(make-serial-process :port "\\\\.\\COM13" :speed 1200 :bytesize 7 :parity 'odd)
2895
2896\(make-serial-process :port "/dev/tty.BlueConsole-SPP-1" :speed nil)
2897
2898usage: (make-serial-process &rest ARGS) */)
2899 (nargs, args)
2900 int nargs;
2901 Lisp_Object *args;
2902{
2903 int fd = -1;
2904 Lisp_Object proc, contact, port;
2905 struct Lisp_Process *p;
2906 struct gcpro gcpro1;
2907 Lisp_Object name, buffer;
2908 Lisp_Object tem, val;
2909 int specpdl_count = -1;
2910
2911 if (nargs == 0)
2912 return Qnil;
2913
2914 contact = Flist (nargs, args);
2915 GCPRO1 (contact);
2916
2917 port = Fplist_get (contact, QCport);
2918 if (NILP (port))
2919 error ("No port specified");
2920 CHECK_STRING (port);
2921
2922 if (NILP (Fplist_member (contact, QCspeed)))
2923 error (":speed not specified");
2924 if (!NILP (Fplist_get (contact, QCspeed)))
2925 CHECK_NUMBER (Fplist_get (contact, QCspeed));
2926
2927 name = Fplist_get (contact, QCname);
2928 if (NILP (name))
2929 name = port;
2930 CHECK_STRING (name);
2931 proc = make_process (name);
2932 specpdl_count = SPECPDL_INDEX ();
2933 record_unwind_protect (make_serial_process_unwind, proc);
2934 p = XPROCESS (proc);
2935
2936 fd = serial_open ((char*) SDATA (port));
2937 p->infd = fd;
2938 p->outfd = fd;
2939 if (fd > max_process_desc)
2940 max_process_desc = fd;
2941 chan_process[fd] = proc;
2942
2943 buffer = Fplist_get (contact, QCbuffer);
2944 if (NILP (buffer))
2945 buffer = name;
2946 buffer = Fget_buffer_create (buffer);
2947 p->buffer = buffer;
2948
2949 p->childp = contact;
2950 p->plist = Fcopy_sequence (Fplist_get (contact, QCplist));
2951 p->type = Qserial;
2952 p->sentinel = Fplist_get (contact, QCsentinel);
2953 p->filter = Fplist_get (contact, QCfilter);
2954 p->log = Qnil;
2955 if (tem = Fplist_get (contact, QCnoquery), !NILP (tem))
2956 p->kill_without_query = 1;
2957 if (tem = Fplist_get (contact, QCstop), !NILP (tem))
2958 p->command = Qt;
2959 p->pty_flag = 0;
2960
2961 if (!EQ (p->command, Qt))
2962 {
2963 FD_SET (fd, &input_wait_mask);
2964 FD_SET (fd, &non_keyboard_wait_mask);
2965 }
2966
2967 if (BUFFERP (buffer))
2968 {
2969 set_marker_both (p->mark, buffer,
2970 BUF_ZV (XBUFFER (buffer)),
2971 BUF_ZV_BYTE (XBUFFER (buffer)));
2972 }
2973
2974 tem = Fplist_member (contact, QCcoding);
2975 if (!NILP (tem) && (!CONSP (tem) || !CONSP (XCDR (tem))))
2976 tem = Qnil;
2977
2978 val = Qnil;
2979 if (!NILP (tem))
2980 {
2981 val = XCAR (XCDR (tem));
2982 if (CONSP (val))
2983 val = XCAR (val);
2984 }
2985 else if (!NILP (Vcoding_system_for_read))
2986 val = Vcoding_system_for_read;
2987 else if ((!NILP (buffer) && NILP (XBUFFER (buffer)->enable_multibyte_characters))
2988 || (NILP (buffer) && NILP (buffer_defaults.enable_multibyte_characters)))
2989 val = Qnil;
2990 p->decode_coding_system = val;
2991
2992 val = Qnil;
2993 if (!NILP (tem))
2994 {
2995 val = XCAR (XCDR (tem));
2996 if (CONSP (val))
2997 val = XCDR (val);
2998 }
2999 else if (!NILP (Vcoding_system_for_write))
3000 val = Vcoding_system_for_write;
3001 else if ((!NILP (buffer) && NILP (XBUFFER (buffer)->enable_multibyte_characters))
3002 || (NILP (buffer) && NILP (buffer_defaults.enable_multibyte_characters)))
3003 val = Qnil;
3004 p->encode_coding_system = val;
3005
3006 setup_process_coding_systems (proc);
3007 p->decoding_buf = make_uninit_string (0);
3008 p->decoding_carryover = 0;
3009 p->encoding_buf = make_uninit_string (0);
3010 p->inherit_coding_system_flag
3011 = !(!NILP (tem) || NILP (buffer) || !inherit_process_coding_system);
3012
3013 Fserial_process_configure(nargs, args);
3014
3015 specpdl_ptr = specpdl + specpdl_count;
3016
3017 UNGCPRO;
3018 return proc;
3019}
3020#endif /* HAVE_SERIAL */
3021
2659/* Create a network stream/datagram client/server process. Treated 3022/* Create a network stream/datagram client/server process. Treated
2660 exactly like a normal process when reading and writing. Primary 3023 exactly like a normal process when reading and writing. Primary
2661 differences are in status display and process deletion. A network 3024 differences are in status display and process deletion. A network
@@ -3395,6 +3758,7 @@ usage: (make-network-process &rest ARGS) */)
3395 3758
3396 p->childp = contact; 3759 p->childp = contact;
3397 p->plist = Fcopy_sequence (Fplist_get (contact, QCplist)); 3760 p->plist = Fcopy_sequence (Fplist_get (contact, QCplist));
3761 p->type = Qnetwork;
3398 3762
3399 p->buffer = buffer; 3763 p->buffer = buffer;
3400 p->sentinel = sentinel; 3764 p->sentinel = sentinel;
@@ -4113,6 +4477,7 @@ server_accept_connection (server, channel)
4113 4477
4114 p->childp = contact; 4478 p->childp = contact;
4115 p->plist = Fcopy_sequence (ps->plist); 4479 p->plist = Fcopy_sequence (ps->plist);
4480 p->type = Qnetwork;
4116 4481
4117 p->buffer = buffer; 4482 p->buffer = buffer;
4118 p->sentinel = ps->sentinel; 4483 p->sentinel = ps->sentinel;
@@ -4811,7 +5176,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
4811 available now and a closed pipe. 5176 available now and a closed pipe.
4812 With luck, a closed pipe will be accompanied by 5177 With luck, a closed pipe will be accompanied by
4813 subprocess termination and SIGCHLD. */ 5178 subprocess termination and SIGCHLD. */
4814 else if (nread == 0 && !NETCONN_P (proc)) 5179 else if (nread == 0 && !NETCONN_P (proc) && !SERIALCONN_P (proc))
4815 ; 5180 ;
4816#endif /* O_NDELAY */ 5181#endif /* O_NDELAY */
4817#endif /* O_NONBLOCK */ 5182#endif /* O_NONBLOCK */
@@ -4839,7 +5204,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
4839 /* If we can detect process termination, don't consider the process 5204 /* If we can detect process termination, don't consider the process
4840 gone just because its pipe is closed. */ 5205 gone just because its pipe is closed. */
4841#ifdef SIGCHLD 5206#ifdef SIGCHLD
4842 else if (nread == 0 && !NETCONN_P (proc)) 5207 else if (nread == 0 && !NETCONN_P (proc) && !SERIALCONN_P (proc))
4843 ; 5208 ;
4844#endif 5209#endif
4845 else 5210 else
@@ -5628,7 +5993,7 @@ send_process (proc, buf, len, object)
5628 this -= rv; 5993 this -= rv;
5629 } 5994 }
5630 5995
5631 /* If we sent just part of the string, put in an EOF 5996 /* If we sent just part of the string, put in an EOF (C-d)
5632 to force it through, before we send the rest. */ 5997 to force it through, before we send the rest. */
5633 if (len > 0) 5998 if (len > 0)
5634 Fprocess_send_eof (proc); 5999 Fprocess_send_eof (proc);
@@ -5748,7 +6113,7 @@ return t unconditionally. */)
5748 proc = get_process (process); 6113 proc = get_process (process);
5749 p = XPROCESS (proc); 6114 p = XPROCESS (proc);
5750 6115
5751 if (!EQ (p->childp, Qt)) 6116 if (!EQ (p->type, Qreal))
5752 error ("Process %s is not a subprocess", 6117 error ("Process %s is not a subprocess",
5753 SDATA (p->name)); 6118 SDATA (p->name));
5754 if (p->infd < 0) 6119 if (p->infd < 0)
@@ -5791,7 +6156,7 @@ process_send_signal (process, signo, current_group, nomsg)
5791 proc = get_process (process); 6156 proc = get_process (process);
5792 p = XPROCESS (proc); 6157 p = XPROCESS (proc);
5793 6158
5794 if (!EQ (p->childp, Qt)) 6159 if (!EQ (p->type, Qreal))
5795 error ("Process %s is not a subprocess", 6160 error ("Process %s is not a subprocess",
5796 SDATA (p->name)); 6161 SDATA (p->name));
5797 if (p->infd < 0) 6162 if (p->infd < 0)
@@ -6040,12 +6405,13 @@ See function `interrupt-process' for more details on usage. */)
6040DEFUN ("stop-process", Fstop_process, Sstop_process, 0, 2, 0, 6405DEFUN ("stop-process", Fstop_process, Sstop_process, 0, 2, 0,
6041 doc: /* Stop process PROCESS. May be process or name of one. 6406 doc: /* Stop process PROCESS. May be process or name of one.
6042See function `interrupt-process' for more details on usage. 6407See function `interrupt-process' for more details on usage.
6043If PROCESS is a network process, inhibit handling of incoming traffic. */) 6408If PROCESS is a network or serial process, inhibit handling of incoming
6409traffic. */)
6044 (process, current_group) 6410 (process, current_group)
6045 Lisp_Object process, current_group; 6411 Lisp_Object process, current_group;
6046{ 6412{
6047#ifdef HAVE_SOCKETS 6413#ifdef HAVE_SOCKETS
6048 if (PROCESSP (process) && NETCONN_P (process)) 6414 if (PROCESSP (process) && (NETCONN_P (process) || SERIALCONN_P (process)))
6049 { 6415 {
6050 struct Lisp_Process *p; 6416 struct Lisp_Process *p;
6051 6417
@@ -6071,12 +6437,13 @@ If PROCESS is a network process, inhibit handling of incoming traffic. */)
6071DEFUN ("continue-process", Fcontinue_process, Scontinue_process, 0, 2, 0, 6437DEFUN ("continue-process", Fcontinue_process, Scontinue_process, 0, 2, 0,
6072 doc: /* Continue process PROCESS. May be process or name of one. 6438 doc: /* Continue process PROCESS. May be process or name of one.
6073See function `interrupt-process' for more details on usage. 6439See function `interrupt-process' for more details on usage.
6074If PROCESS is a network process, resume handling of incoming traffic. */) 6440If PROCESS is a network or serial process, resume handling of incoming
6441traffic. */)
6075 (process, current_group) 6442 (process, current_group)
6076 Lisp_Object process, current_group; 6443 Lisp_Object process, current_group;
6077{ 6444{
6078#ifdef HAVE_SOCKETS 6445#ifdef HAVE_SOCKETS
6079 if (PROCESSP (process) && NETCONN_P (process)) 6446 if (PROCESSP (process) && (NETCONN_P (process) || SERIALCONN_P (process)))
6080 { 6447 {
6081 struct Lisp_Process *p; 6448 struct Lisp_Process *p;
6082 6449
@@ -6087,6 +6454,13 @@ If PROCESS is a network process, resume handling of incoming traffic. */)
6087 { 6454 {
6088 FD_SET (p->infd, &input_wait_mask); 6455 FD_SET (p->infd, &input_wait_mask);
6089 FD_SET (p->infd, &non_keyboard_wait_mask); 6456 FD_SET (p->infd, &non_keyboard_wait_mask);
6457#ifdef WINDOWSNT
6458 if (fd_info[ p->infd ].flags & FILE_SERIAL)
6459 PurgeComm (fd_info[ p->infd ].hnd, PURGE_RXABORT | PURGE_RXCLEAR);
6460#endif
6461#ifdef HAVE_TERMIOS
6462 tcflush (p->infd, TCIFLUSH);
6463#endif
6090 } 6464 }
6091 p->command = Qnil; 6465 p->command = Qnil;
6092 return process; 6466 return process;
@@ -6272,7 +6646,9 @@ PROCESS may be a process, a buffer, the name of a process or buffer, or
6272nil, indicating the current buffer's process. 6646nil, indicating the current buffer's process.
6273If PROCESS is a network connection, or is a process communicating 6647If PROCESS is a network connection, or is a process communicating
6274through a pipe (as opposed to a pty), then you cannot send any more 6648through a pipe (as opposed to a pty), then you cannot send any more
6275text to PROCESS after you call this function. */) 6649text to PROCESS after you call this function.
6650If PROCESS is a serial process, wait until all output written to the
6651process has been transmitted to the serial port. */)
6276 (process) 6652 (process)
6277 Lisp_Object process; 6653 Lisp_Object process;
6278{ 6654{
@@ -6302,6 +6678,14 @@ text to PROCESS after you call this function. */)
6302#else 6678#else
6303 if (XPROCESS (proc)->pty_flag) 6679 if (XPROCESS (proc)->pty_flag)
6304 send_process (proc, "\004", 1, Qnil); 6680 send_process (proc, "\004", 1, Qnil);
6681 else if (XPROCESS (proc)->type == Qserial)
6682 {
6683#ifdef HAVE_TERMIOS
6684 if (tcdrain (XPROCESS (proc)->outfd) != 0)
6685 error ("tcdrain() failed: %s", emacs_strerror (errno));
6686#endif
6687 /* Do nothing on Windows because writes are blocking. */
6688 }
6305 else 6689 else
6306 { 6690 {
6307 int old_outfd, new_outfd; 6691 int old_outfd, new_outfd;
@@ -6311,7 +6695,7 @@ text to PROCESS after you call this function. */)
6311 for communication with the subprocess, call shutdown to cause EOF. 6695 for communication with the subprocess, call shutdown to cause EOF.
6312 (In some old system, shutdown to socketpair doesn't work. 6696 (In some old system, shutdown to socketpair doesn't work.
6313 Then we just can't win.) */ 6697 Then we just can't win.) */
6314 if (XPROCESS (proc)->pid == 0 6698 if (XPROCESS (proc)->type == Qnetwork
6315 || XPROCESS (proc)->outfd == XPROCESS (proc)->infd) 6699 || XPROCESS (proc)->outfd == XPROCESS (proc)->infd)
6316 shutdown (XPROCESS (proc)->outfd, 1); 6700 shutdown (XPROCESS (proc)->outfd, 1);
6317 /* In case of socketpair, outfd == infd, so don't close it. */ 6701 /* In case of socketpair, outfd == infd, so don't close it. */
@@ -6355,7 +6739,7 @@ kill_buffer_processes (buffer)
6355 if (PROCESSP (proc) 6739 if (PROCESSP (proc)
6356 && (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer))) 6740 && (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer)))
6357 { 6741 {
6358 if (NETCONN_P (proc)) 6742 if (NETCONN_P (proc) || SERIALCONN_P (proc))
6359 Fdelete_process (proc); 6743 Fdelete_process (proc);
6360 else if (XPROCESS (proc)->infd >= 0) 6744 else if (XPROCESS (proc)->infd >= 0)
6361 process_send_signal (proc, SIGHUP, Qnil, 1); 6745 process_send_signal (proc, SIGHUP, Qnil, 1);
@@ -6464,7 +6848,7 @@ sigchld_handler (signo)
6464 { 6848 {
6465 proc = XCDR (XCAR (tail)); 6849 proc = XCDR (XCAR (tail));
6466 p = XPROCESS (proc); 6850 p = XPROCESS (proc);
6467 if (EQ (p->childp, Qt) && p->pid == pid) 6851 if (EQ (p->type, Qreal) && p->pid == pid)
6468 break; 6852 break;
6469 p = 0; 6853 p = 0;
6470 } 6854 }
@@ -6686,7 +7070,8 @@ status_notify (deleting_process)
6686 while (! EQ (p->filter, Qt) 7070 while (! EQ (p->filter, Qt)
6687 && ! EQ (p->status, Qconnect) 7071 && ! EQ (p->status, Qconnect)
6688 && ! EQ (p->status, Qlisten) 7072 && ! EQ (p->status, Qlisten)
6689 && ! EQ (p->command, Qt) /* Network process not stopped. */ 7073 /* Network or serial process not stopped: */
7074 && ! EQ (p->command, Qt)
6690 && p->infd >= 0 7075 && p->infd >= 0
6691 && p != deleting_process 7076 && p != deleting_process
6692 && read_process_output (proc, p->infd) > 0); 7077 && read_process_output (proc, p->infd) > 0);
@@ -7073,6 +7458,39 @@ syms_of_process ()
7073 Qdatagram = intern ("datagram"); 7458 Qdatagram = intern ("datagram");
7074 staticpro (&Qdatagram); 7459 staticpro (&Qdatagram);
7075 7460
7461 QCport = intern (":port");
7462 staticpro (&QCport);
7463 QCspeed = intern (":speed");
7464 staticpro (&QCspeed);
7465 QCprocess = intern (":process");
7466 staticpro (&QCprocess);
7467
7468 QCbytesize = intern (":bytesize");
7469 staticpro (&QCbytesize);
7470 QCstopbits = intern (":stopbits");
7471 staticpro (&QCstopbits);
7472 QCparity = intern (":parity");
7473 staticpro (&QCparity);
7474 Qodd = intern ("odd");
7475 staticpro (&Qodd);
7476 Qeven = intern ("even");
7477 staticpro (&Qeven);
7478 QCflowcontrol = intern (":flowcontrol");
7479 staticpro (&QCflowcontrol);
7480 Qhw = intern ("hw");
7481 staticpro (&Qhw);
7482 Qsw = intern ("sw");
7483 staticpro (&Qsw);
7484 QCsummary = intern (":summary");
7485 staticpro (&QCsummary);
7486
7487 Qreal = intern ("real");
7488 staticpro (&Qreal);
7489 Qnetwork = intern ("network");
7490 staticpro (&Qnetwork);
7491 Qserial = intern ("serial");
7492 staticpro (&Qserial);
7493
7076 QCname = intern (":name"); 7494 QCname = intern (":name");
7077 staticpro (&QCname); 7495 staticpro (&QCname);
7078 QCbuffer = intern (":buffer"); 7496 QCbuffer = intern (":buffer");
@@ -7170,6 +7588,10 @@ The variable takes effect when `start-process' is called. */);
7170 defsubr (&Slist_processes); 7588 defsubr (&Slist_processes);
7171 defsubr (&Sprocess_list); 7589 defsubr (&Sprocess_list);
7172 defsubr (&Sstart_process); 7590 defsubr (&Sstart_process);
7591#ifdef HAVE_SERIAL
7592 defsubr (&Sserial_process_configure);
7593 defsubr (&Smake_serial_process);
7594#endif /* HAVE_SERIAL */
7173#ifdef HAVE_SOCKETS 7595#ifdef HAVE_SOCKETS
7174 defsubr (&Sset_network_process_option); 7596 defsubr (&Sset_network_process_option);
7175 defsubr (&Smake_network_process); 7597 defsubr (&Smake_network_process);
@@ -7199,7 +7621,7 @@ The variable takes effect when `start-process' is called. */);
7199 defsubr (&Sprocess_send_eof); 7621 defsubr (&Sprocess_send_eof);
7200 defsubr (&Ssignal_process); 7622 defsubr (&Ssignal_process);
7201 defsubr (&Swaiting_for_user_input_p); 7623 defsubr (&Swaiting_for_user_input_p);
7202/* defsubr (&Sprocess_connection); */ 7624 defsubr (&Sprocess_type);
7203 defsubr (&Sset_process_coding_system); 7625 defsubr (&Sset_process_coding_system);
7204 defsubr (&Sprocess_coding_system); 7626 defsubr (&Sprocess_coding_system);
7205 defsubr (&Sset_process_filter_multibyte); 7627 defsubr (&Sset_process_filter_multibyte);
diff --git a/src/process.h b/src/process.h
index 619eb2b5e67..29cf38a2a4f 100644
--- a/src/process.h
+++ b/src/process.h
@@ -51,11 +51,14 @@ struct Lisp_Process
51 Lisp_Object log; 51 Lisp_Object log;
52 /* Buffer that output is going to */ 52 /* Buffer that output is going to */
53 Lisp_Object buffer; 53 Lisp_Object buffer;
54 /* t if this is a real child process. 54 /* t if this is a real child process. For a network or serial
55 For a net connection, it is a plist based on the arguments to make-network-process. */ 55 connection, it is a plist based on the arguments to
56 make-network-process or make-serial-process. */
56 Lisp_Object childp; 57 Lisp_Object childp;
57 /* Plist for programs to keep per-process state information, parameters, etc. */ 58 /* Plist for programs to keep per-process state information, parameters, etc. */
58 Lisp_Object plist; 59 Lisp_Object plist;
60 /* Symbol indicating the type of process: real, network, serial */
61 Lisp_Object type;
59 /* Marker set to end of last buffer-inserted output from this process */ 62 /* Marker set to end of last buffer-inserted output from this process */
60 Lisp_Object mark; 63 Lisp_Object mark;
61 /* Symbol indicating status of process. 64 /* Symbol indicating status of process.
@@ -78,7 +81,8 @@ struct Lisp_Process
78 81
79 /* Number of this process. 82 /* Number of this process.
80 allocate_process assumes this is the first non-Lisp_Object field. 83 allocate_process assumes this is the first non-Lisp_Object field.
81 A value 0 is used for pseudo-processes such as network connections. */ 84 A value 0 is used for pseudo-processes such as network or serial
85 connections. */
82 pid_t pid; 86 pid_t pid;
83 /* Descriptor by which we read from this process */ 87 /* Descriptor by which we read from this process */
84 int infd; 88 int infd;
diff --git a/src/sysdep.c b/src/sysdep.c
index 6c3e0e4a54e..9e1813bf71b 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -166,6 +166,11 @@ extern int quit_char;
166#include "process.h" 166#include "process.h"
167#include "cm.h" /* for reset_sys_modes */ 167#include "cm.h" /* for reset_sys_modes */
168 168
169/* For serial_configure() and serial_open() */
170extern Lisp_Object QCport, QCspeed, QCprocess;
171extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
172extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;
173
169#ifdef WINDOWSNT 174#ifdef WINDOWSNT
170#include <direct.h> 175#include <direct.h>
171/* In process.h which conflicts with the local copy. */ 176/* In process.h which conflicts with the local copy. */
@@ -5379,6 +5384,200 @@ strsignal (code)
5379 return signame; 5384 return signame;
5380} 5385}
5381#endif /* HAVE_STRSIGNAL */ 5386#endif /* HAVE_STRSIGNAL */
5387
5388#ifdef HAVE_TERMIOS
5389/* For make-serial-process */
5390int serial_open (char *port)
5391{
5392 int fd = -1;
5393
5394 fd = emacs_open ((char*) port,
5395 O_RDWR
5396#ifdef O_NONBLOCK
5397 | O_NONBLOCK
5398#else
5399 | O_NDELAY
5400#endif
5401#ifdef O_NOCTTY
5402 | O_NOCTTY
5403#endif
5404 , 0);
5405 if (fd < 0)
5406 {
5407 error ("Could not open %s: %s",
5408 port, emacs_strerror (errno));
5409 }
5410#ifdef TIOCEXCL
5411 ioctl (fd, TIOCEXCL, (char *) 0);
5412#endif
5413
5414 return fd;
5415}
5416#endif /* TERMIOS */
5417
5418#ifdef HAVE_TERMIOS
5419/* For serial-process-configure */
5420void
5421serial_configure (struct Lisp_Process *p,
5422 Lisp_Object contact)
5423{
5424 Lisp_Object childp2 = Qnil;
5425 Lisp_Object tem = Qnil;
5426 struct termios attr;
5427 int err = -1;
5428 char summary[4] = "???"; /* This usually becomes "8N1". */
5429
5430 childp2 = Fcopy_sequence (p->childp);
5431
5432 /* Read port attributes and prepare default configuration. */
5433 err = tcgetattr (p->outfd, &attr);
5434 if (err != 0)
5435 error ("tcgetattr() failed: %s", emacs_strerror (errno));
5436 cfmakeraw (&attr);
5437#if defined (CLOCAL)
5438 attr.c_cflag |= CLOCAL;
5439#endif
5440#if defined (CREAD)
5441 attr.c_cflag | CREAD;
5442#endif
5443
5444 /* Configure speed. */
5445 if (!NILP (Fplist_member (contact, QCspeed)))
5446 tem = Fplist_get (contact, QCspeed);
5447 else
5448 tem = Fplist_get (p->childp, QCspeed);
5449 CHECK_NUMBER (tem);
5450 err = cfsetspeed (&attr, XINT (tem));
5451 if (err != 0)
5452 error ("cfsetspeed(%d) failed: %s", XINT (tem), emacs_strerror (errno));
5453 childp2 = Fplist_put (childp2, QCspeed, tem);
5454
5455 /* Configure bytesize. */
5456 if (!NILP (Fplist_member (contact, QCbytesize)))
5457 tem = Fplist_get (contact, QCbytesize);
5458 else
5459 tem = Fplist_get (p->childp, QCbytesize);
5460 if (NILP (tem))
5461 tem = make_number (8);
5462 CHECK_NUMBER (tem);
5463 if (XINT (tem) != 7 && XINT (tem) != 8)
5464 error (":bytesize must be nil (8), 7, or 8");
5465 summary[0] = XINT(tem) + '0';
5466#if defined (CSIZE) && defined (CS7) && defined (CS8)
5467 attr.c_cflag &= ~CSIZE;
5468 attr.c_cflag |= ((XINT (tem) == 7) ? CS7 : CS8);
5469#else
5470 /* Don't error on bytesize 8, which should be set by cfmakeraw(). */
5471 if (XINT (tem) != 8)
5472 error ("Bytesize cannot be changed");
5473#endif
5474 childp2 = Fplist_put (childp2, QCbytesize, tem);
5475
5476 /* Configure parity. */
5477 if (!NILP (Fplist_member (contact, QCparity)))
5478 tem = Fplist_get (contact, QCparity);
5479 else
5480 tem = Fplist_get (p->childp, QCparity);
5481 if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
5482 error (":parity must be nil (no parity), `even', or `odd'");
5483#if defined (PARENB) && defined (PARODD) && defined (IGNPAR) && defined (INPCK)
5484 attr.c_cflag &= ~(PARENB | PARODD);
5485 attr.c_iflag &= ~(IGNPAR | INPCK);
5486 if (NILP (tem))
5487 {
5488 summary[1] = 'N';
5489 }
5490 else if (EQ (tem, Qeven))
5491 {
5492 summary[1] = 'E';
5493 attr.c_cflag |= PARENB;
5494 attr.c_iflag |= (IGNPAR | INPCK);
5495 }
5496 else if (EQ (tem, Qodd))
5497 {
5498 summary[1] = 'O';
5499 attr.c_cflag |= (PARENB | PARODD);
5500 attr.c_iflag |= (IGNPAR | INPCK);
5501 }
5502#else
5503 /* Don't error on no parity, which should be set by cfmakeraw(). */
5504 if (!NILP (tem))
5505 error ("Parity cannot be configured");
5506#endif
5507 childp2 = Fplist_put (childp2, QCparity, tem);
5508
5509 /* Configure stopbits. */
5510 if (!NILP (Fplist_member (contact, QCstopbits)))
5511 tem = Fplist_get (contact, QCstopbits);
5512 else
5513 tem = Fplist_get (p->childp, QCstopbits);
5514 if (NILP (tem))
5515 tem = make_number (1);
5516 CHECK_NUMBER (tem);
5517 if (XINT (tem) != 1 && XINT (tem) != 2)
5518 error (":stopbits must be nil (1 stopbit), 1, or 2");
5519 summary[2] = XINT (tem) + '0';
5520#if defined (CSTOPB)
5521 attr.c_cflag &= ~CSTOPB;
5522 if (XINT (tem) == 2)
5523 attr.c_cflag |= CSTOPB;
5524#else
5525 /* Don't error on 1 stopbit, which should be set by cfmakeraw(). */
5526 if (XINT (tem) != 1)
5527 error ("Stopbits cannot be configured");
5528#endif
5529 childp2 = Fplist_put (childp2, QCstopbits, tem);
5530
5531 /* Configure flowcontrol. */
5532 if (!NILP (Fplist_member (contact, QCflowcontrol)))
5533 tem = Fplist_get (contact, QCflowcontrol);
5534 else
5535 tem = Fplist_get (p->childp, QCflowcontrol);
5536 if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
5537 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
5538#if defined (CRTSCTS)
5539 attr.c_cflag &= ~CRTSCTS;
5540#endif
5541#if defined (CNEW_RTSCTS)
5542 attr.c_cflag &= ~CNEW_RTSCTS;
5543#endif
5544#if defined (IXON) && defined (IXOFF)
5545 attr.c_iflag &= ~(IXON | IXOFF);
5546#endif
5547 if (NILP (tem))
5548 {
5549 /* Already configured. */
5550 }
5551 else if (EQ (tem, Qhw))
5552 {
5553#if defined (CRTSCTS)
5554 attr.c_cflag |= CRTSCTS;
5555#elif defined (CNEW_RTSCTS)
5556 attr.c_cflag |= CNEW_RTSCTS;
5557#else
5558 error ("Hardware flowcontrol (RTS/CTS) not supported");
5559#endif
5560 }
5561 else if (EQ (tem, Qsw))
5562 {
5563#if defined (IXON) && defined (IXOFF)
5564 attr.c_iflag |= (IXON | IXOFF);
5565#else
5566 error ("Software flowcontrol (XON/XOFF) not supported");
5567#endif
5568 }
5569 childp2 = Fplist_put (childp2, QCflowcontrol, tem);
5570
5571 /* Activate configuration. */
5572 err = tcsetattr (p->outfd, TCSANOW, &attr);
5573 if (err != 0)
5574 error ("tcsetattr() failed: %s", emacs_strerror (errno));
5575
5576 childp2 = Fplist_put (childp2, QCsummary, build_string (summary));
5577 p->childp = childp2;
5578
5579}
5580#endif /* TERMIOS */
5382 5581
5383/* arch-tag: edb43589-4e09-4544-b325-978b5b121dcf 5582/* arch-tag: edb43589-4e09-4544-b325-978b5b121dcf
5384 (do not change this comment) */ 5583 (do not change this comment) */
diff --git a/src/w32.c b/src/w32.c
index 81accb6b610..e0e19c3508a 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -102,6 +102,13 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
102#include "systime.h" 102#include "systime.h"
103#include "dispextern.h" /* for xstrcasecmp */ 103#include "dispextern.h" /* for xstrcasecmp */
104 104
105/* For serial_configure() and serial_open() */
106#include "process.h"
107/* From process.c */
108extern Lisp_Object QCport, QCspeed, QCprocess;
109extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
110extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;
111
105typedef HRESULT (WINAPI * ShGetFolderPath_fn) 112typedef HRESULT (WINAPI * ShGetFolderPath_fn)
106 (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *); 113 (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);
107 114
@@ -4063,10 +4070,10 @@ _sys_read_ahead (int fd)
4063 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY) 4070 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
4064 return STATUS_READ_ERROR; 4071 return STATUS_READ_ERROR;
4065 4072
4066 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0 4073 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SERIAL | FILE_SOCKET)) == 0
4067 || (fd_info[fd].flags & FILE_READ) == 0) 4074 || (fd_info[fd].flags & FILE_READ) == 0)
4068 { 4075 {
4069 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd)); 4076 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd));
4070 abort (); 4077 abort ();
4071 } 4078 }
4072 4079
@@ -4080,7 +4087,7 @@ _sys_read_ahead (int fd)
4080 reporting that input is available; we need this because Windows 95 4087 reporting that input is available; we need this because Windows 95
4081 connects DOS programs to pipes by making the pipe appear to be 4088 connects DOS programs to pipes by making the pipe appear to be
4082 the normal console stdout - as a result most DOS programs will 4089 the normal console stdout - as a result most DOS programs will
4083 write to stdout without buffering, ie. one character at a 4090 write to stdout without buffering, ie. one character at a
4084 time. Even some W32 programs do this - "dir" in a command 4091 time. Even some W32 programs do this - "dir" in a command
4085 shell on NT is very slow if we don't do this. */ 4092 shell on NT is very slow if we don't do this. */
4086 if (rc > 0) 4093 if (rc > 0)
@@ -4096,6 +4103,29 @@ _sys_read_ahead (int fd)
4096 Sleep (0); 4103 Sleep (0);
4097 } 4104 }
4098 } 4105 }
4106 else if (fd_info[fd].flags & FILE_SERIAL)
4107 {
4108 HANDLE hnd = fd_info[fd].hnd;
4109 OVERLAPPED *ovl = &fd_info[fd].cp->ovl_read;
4110 COMMTIMEOUTS ct;
4111
4112 /* Configure timeouts for blocking read. */
4113 if (!GetCommTimeouts (hnd, &ct))
4114 return STATUS_READ_ERROR;
4115 ct.ReadIntervalTimeout = 0;
4116 ct.ReadTotalTimeoutMultiplier = 0;
4117 ct.ReadTotalTimeoutConstant = 0;
4118 if (!SetCommTimeouts (hnd, &ct))
4119 return STATUS_READ_ERROR;
4120
4121 if (!ReadFile (hnd, &cp->chr, sizeof (char), (DWORD*) &rc, ovl))
4122 {
4123 if (GetLastError () != ERROR_IO_PENDING)
4124 return STATUS_READ_ERROR;
4125 if (!GetOverlappedResult (hnd, ovl, (DWORD*) &rc, TRUE))
4126 return STATUS_READ_ERROR;
4127 }
4128 }
4099#ifdef HAVE_SOCKETS 4129#ifdef HAVE_SOCKETS
4100 else if (fd_info[fd].flags & FILE_SOCKET) 4130 else if (fd_info[fd].flags & FILE_SOCKET)
4101 { 4131 {
@@ -4167,7 +4197,7 @@ sys_read (int fd, char * buffer, unsigned int count)
4167 return -1; 4197 return -1;
4168 } 4198 }
4169 4199
4170 if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) 4200 if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET | FILE_SERIAL))
4171 { 4201 {
4172 child_process *cp = fd_info[fd].cp; 4202 child_process *cp = fd_info[fd].cp;
4173 4203
@@ -4238,6 +4268,52 @@ sys_read (int fd, char * buffer, unsigned int count)
4238 if (to_read > 0) 4268 if (to_read > 0)
4239 nchars += _read (fd, buffer, to_read); 4269 nchars += _read (fd, buffer, to_read);
4240 } 4270 }
4271 else if (fd_info[fd].flags & FILE_SERIAL)
4272 {
4273 HANDLE hnd = fd_info[fd].hnd;
4274 OVERLAPPED *ovl = &fd_info[fd].cp->ovl_read;
4275 DWORD err = 0;
4276 int rc = 0;
4277 COMMTIMEOUTS ct;
4278
4279 if (count > 0)
4280 {
4281 /* Configure timeouts for non-blocking read. */
4282 if (!GetCommTimeouts (hnd, &ct))
4283 {
4284 errno = EIO;
4285 return -1;
4286 }
4287 ct.ReadIntervalTimeout = MAXDWORD;
4288 ct.ReadTotalTimeoutMultiplier = 0;
4289 ct.ReadTotalTimeoutConstant = 0;
4290 if (!SetCommTimeouts (hnd, &ct))
4291 {
4292 errno = EIO;
4293 return -1;
4294 }
4295
4296 if (!ResetEvent (ovl->hEvent))
4297 {
4298 errno = EIO;
4299 return -1;
4300 }
4301 if (!ReadFile (hnd, buffer, count, (DWORD*) &rc, ovl))
4302 {
4303 if (GetLastError () != ERROR_IO_PENDING)
4304 {
4305 errno = EIO;
4306 return -1;
4307 }
4308 if (!GetOverlappedResult (hnd, ovl, (DWORD*) &rc, TRUE))
4309 {
4310 errno = EIO;
4311 return -1;
4312 }
4313 }
4314 nchars += rc;
4315 }
4316 }
4241#ifdef HAVE_SOCKETS 4317#ifdef HAVE_SOCKETS
4242 else /* FILE_SOCKET */ 4318 else /* FILE_SOCKET */
4243 { 4319 {
@@ -4299,6 +4375,9 @@ sys_read (int fd, char * buffer, unsigned int count)
4299 return nchars; 4375 return nchars;
4300} 4376}
4301 4377
4378/* From w32xfns.c */
4379extern HANDLE interrupt_handle;
4380
4302/* For now, don't bother with a non-blocking mode */ 4381/* For now, don't bother with a non-blocking mode */
4303int 4382int
4304sys_write (int fd, const void * buffer, unsigned int count) 4383sys_write (int fd, const void * buffer, unsigned int count)
@@ -4311,7 +4390,7 @@ sys_write (int fd, const void * buffer, unsigned int count)
4311 return -1; 4390 return -1;
4312 } 4391 }
4313 4392
4314 if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) 4393 if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET | FILE_SERIAL))
4315 { 4394 {
4316 if ((fd_info[fd].flags & FILE_WRITE) == 0) 4395 if ((fd_info[fd].flags & FILE_WRITE) == 0)
4317 { 4396 {
@@ -4352,6 +4431,42 @@ sys_write (int fd, const void * buffer, unsigned int count)
4352 } 4431 }
4353 } 4432 }
4354 4433
4434 if (fd < MAXDESC && fd_info[fd].flags & FILE_SERIAL)
4435 {
4436 HANDLE hnd = (HANDLE) _get_osfhandle (fd);
4437 OVERLAPPED *ovl = &fd_info[fd].cp->ovl_write;
4438 HANDLE wait_hnd[2] = { interrupt_handle, ovl->hEvent };
4439 DWORD active = 0;
4440
4441 if (!WriteFile (hnd, buffer, count, (DWORD*) &nchars, ovl))
4442 {
4443 if (GetLastError () != ERROR_IO_PENDING)
4444 {
4445 errno = EIO;
4446 return -1;
4447 }
4448 if (detect_input_pending ())
4449 active = MsgWaitForMultipleObjects (2, wait_hnd, FALSE, INFINITE,
4450 QS_ALLINPUT);
4451 else
4452 active = WaitForMultipleObjects (2, wait_hnd, FALSE, INFINITE);
4453 if (active == WAIT_OBJECT_0)
4454 { /* User pressed C-g, cancel write, then leave. Don't bother
4455 cleaning up as we may only get stuck in buggy drivers. */
4456 PurgeComm (hnd, PURGE_TXABORT | PURGE_TXCLEAR);
4457 CancelIo (hnd);
4458 errno = EIO;
4459 return -1;
4460 }
4461 if (active == WAIT_OBJECT_0 + 1
4462 && !GetOverlappedResult (hnd, ovl, (DWORD*) &nchars, TRUE))
4463 {
4464 errno = EIO;
4465 return -1;
4466 }
4467 }
4468 }
4469 else
4355#ifdef HAVE_SOCKETS 4470#ifdef HAVE_SOCKETS
4356 if (fd < MAXDESC && fd_info[fd].flags & FILE_SOCKET) 4471 if (fd < MAXDESC && fd_info[fd].flags & FILE_SOCKET)
4357 { 4472 {
@@ -4612,6 +4727,196 @@ globals_of_w32 ()
4612 strcpy (dflt_group_name, "None"); 4727 strcpy (dflt_group_name, "None");
4613} 4728}
4614 4729
4730/* For make-serial-process */
4731int serial_open (char *port)
4732{
4733 HANDLE hnd;
4734 child_process *cp;
4735 int fd = -1;
4736
4737 hnd = CreateFile (port, GENERIC_READ | GENERIC_WRITE, 0, 0,
4738 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
4739 if (hnd == INVALID_HANDLE_VALUE)
4740 error ("Could not open %s", port);
4741 fd = (int) _open_osfhandle ((int) hnd, 0);
4742 if (fd == -1)
4743 error ("Could not open %s", port);
4744
4745 cp = new_child ();
4746 if (!cp)
4747 error ("Could not create child process");
4748 cp->fd = fd;
4749 cp->status = STATUS_READ_ACKNOWLEDGED;
4750 fd_info[ fd ].hnd = hnd;
4751 fd_info[ fd ].flags |=
4752 FILE_READ | FILE_WRITE | FILE_BINARY | FILE_SERIAL;
4753 if (fd_info[ fd ].cp != NULL)
4754 {
4755 error ("fd_info[fd = %d] is already in use", fd);
4756 }
4757 fd_info[ fd ].cp = cp;
4758 cp->ovl_read.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
4759 if (cp->ovl_read.hEvent == NULL)
4760 error ("Could not create read event");
4761 cp->ovl_write.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
4762 if (cp->ovl_write.hEvent == NULL)
4763 error ("Could not create write event");
4764
4765 return fd;
4766}
4767
4768/* For serial-process-configure */
4769void
4770serial_configure (struct Lisp_Process *p,
4771 Lisp_Object contact)
4772{
4773 Lisp_Object childp2 = Qnil;
4774 Lisp_Object tem = Qnil;
4775 HANDLE hnd;
4776 DCB dcb;
4777 COMMTIMEOUTS ct;
4778 char summary[4] = "???"; /* This usually becomes "8N1". */
4779
4780 if ((fd_info[ p->outfd ].flags & FILE_SERIAL) == 0)
4781 error ("Not a serial process");
4782 hnd = fd_info[ p->outfd ].hnd;
4783
4784 childp2 = Fcopy_sequence (p->childp);
4785
4786 /* Initialize timeouts for blocking read and blocking write. */
4787 if (!GetCommTimeouts (hnd, &ct))
4788 error ("GetCommTimeouts() failed");
4789 ct.ReadIntervalTimeout = 0;
4790 ct.ReadTotalTimeoutMultiplier = 0;
4791 ct.ReadTotalTimeoutConstant = 0;
4792 ct.WriteTotalTimeoutMultiplier = 0;
4793 ct.WriteTotalTimeoutConstant = 0;
4794 if (!SetCommTimeouts (hnd, &ct))
4795 error ("SetCommTimeouts() failed");
4796 /* Read port attributes and prepare default configuration. */
4797 memset (&dcb, 0, sizeof (dcb));
4798 dcb.DCBlength = sizeof (DCB);
4799 if (!GetCommState (hnd, &dcb))
4800 error ("GetCommState() failed");
4801 dcb.fBinary = TRUE;
4802 dcb.fNull = FALSE;
4803 dcb.fAbortOnError = FALSE;
4804 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
4805 dcb.ErrorChar = 0;
4806 dcb.EofChar = 0;
4807 dcb.EvtChar = 0;
4808
4809 /* Configure speed. */
4810 if (!NILP (Fplist_member (contact, QCspeed)))
4811 tem = Fplist_get (contact, QCspeed);
4812 else
4813 tem = Fplist_get (p->childp, QCspeed);
4814 CHECK_NUMBER (tem);
4815 dcb.BaudRate = XINT (tem);
4816 childp2 = Fplist_put (childp2, QCspeed, tem);
4817
4818 /* Configure bytesize. */
4819 if (!NILP (Fplist_member (contact, QCbytesize)))
4820 tem = Fplist_get (contact, QCbytesize);
4821 else
4822 tem = Fplist_get (p->childp, QCbytesize);
4823 if (NILP (tem))
4824 tem = make_number (8);
4825 CHECK_NUMBER (tem);
4826 if (XINT (tem) != 7 && XINT (tem) != 8)
4827 error (":bytesize must be nil (8), 7, or 8");
4828 dcb.ByteSize = XINT (tem);
4829 summary[0] = XINT (tem) + '0';
4830 childp2 = Fplist_put (childp2, QCbytesize, tem);
4831
4832 /* Configure parity. */
4833 if (!NILP (Fplist_member (contact, QCparity)))
4834 tem = Fplist_get (contact, QCparity);
4835 else
4836 tem = Fplist_get (p->childp, QCparity);
4837 if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
4838 error (":parity must be nil (no parity), `even', or `odd'");
4839 dcb.fParity = FALSE;
4840 dcb.Parity = NOPARITY;
4841 dcb.fErrorChar = FALSE;
4842 if (NILP (tem))
4843 {
4844 summary[1] = 'N';
4845 }
4846 else if (EQ (tem, Qeven))
4847 {
4848 summary[1] = 'E';
4849 dcb.fParity = TRUE;
4850 dcb.Parity = EVENPARITY;
4851 dcb.fErrorChar = TRUE;
4852 }
4853 else if (EQ (tem, Qodd))
4854 {
4855 summary[1] = 'O';
4856 dcb.fParity = TRUE;
4857 dcb.Parity = ODDPARITY;
4858 dcb.fErrorChar = TRUE;
4859 }
4860 childp2 = Fplist_put (childp2, QCparity, tem);
4861
4862 /* Configure stopbits. */
4863 if (!NILP (Fplist_member (contact, QCstopbits)))
4864 tem = Fplist_get (contact, QCstopbits);
4865 else
4866 tem = Fplist_get (p->childp, QCstopbits);
4867 if (NILP (tem))
4868 tem = make_number (1);
4869 CHECK_NUMBER (tem);
4870 if (XINT (tem) != 1 && XINT (tem) != 2)
4871 error (":stopbits must be nil (1 stopbit), 1, or 2");
4872 summary[2] = XINT (tem) + '0';
4873 if (XINT (tem) == 1)
4874 dcb.StopBits = ONESTOPBIT;
4875 else if (XINT (tem) == 2)
4876 dcb.StopBits = TWOSTOPBITS;
4877 childp2 = Fplist_put (childp2, QCstopbits, tem);
4878
4879 /* Configure flowcontrol. */
4880 if (!NILP (Fplist_member (contact, QCflowcontrol)))
4881 tem = Fplist_get (contact, QCflowcontrol);
4882 else
4883 tem = Fplist_get (p->childp, QCflowcontrol);
4884 if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
4885 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
4886 dcb.fOutxCtsFlow = FALSE;
4887 dcb.fOutxDsrFlow = FALSE;
4888 dcb.fDtrControl = DTR_CONTROL_DISABLE;
4889 dcb.fDsrSensitivity = FALSE;
4890 dcb.fTXContinueOnXoff = FALSE;
4891 dcb.fOutX = FALSE;
4892 dcb.fInX = FALSE;
4893 dcb.fRtsControl = RTS_CONTROL_DISABLE;
4894 dcb.XonChar = 17; /* Control-Q */
4895 dcb.XoffChar = 19; /* Control-S */
4896 if (NILP (tem))
4897 {
4898 /* Already configured. */
4899 }
4900 else if (EQ (tem, Qhw))
4901 {
4902 dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
4903 dcb.fOutxCtsFlow = TRUE;
4904 }
4905 else if (EQ (tem, Qsw))
4906 {
4907 dcb.fOutX = TRUE;
4908 dcb.fInX = TRUE;
4909 }
4910 childp2 = Fplist_put (childp2, QCflowcontrol, tem);
4911
4912 /* Activate configuration. */
4913 if (!SetCommState (hnd, &dcb))
4914 error ("SetCommState() failed");
4915
4916 childp2 = Fplist_put (childp2, QCsummary, build_string (summary));
4917 p->childp = childp2;
4918}
4919
4615/* end of w32.c */ 4920/* end of w32.c */
4616 4921
4617/* arch-tag: 90442dd3-37be-482b-b272-ac752e3049f1 4922/* arch-tag: 90442dd3-37be-482b-b272-ac752e3049f1
diff --git a/src/w32.h b/src/w32.h
index c57d8956411..65483c00ca4 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -72,6 +72,8 @@ typedef struct _child_process
72 PROCESS_INFORMATION procinfo; 72 PROCESS_INFORMATION procinfo;
73 volatile int status; 73 volatile int status;
74 char chr; 74 char chr;
75 OVERLAPPED ovl_read;
76 OVERLAPPED ovl_write;
75} child_process; 77} child_process;
76 78
77#define MAXDESC FD_SETSIZE 79#define MAXDESC FD_SETSIZE
@@ -99,6 +101,7 @@ extern filedesc fd_info [ MAXDESC ];
99#define FILE_PIPE 0x0100 101#define FILE_PIPE 0x0100
100#define FILE_SOCKET 0x0200 102#define FILE_SOCKET 0x0200
101#define FILE_NDELAY 0x0400 103#define FILE_NDELAY 0x0400
104#define FILE_SERIAL 0x0800
102 105
103extern child_process * new_child (void); 106extern child_process * new_child (void);
104extern void delete_child (child_process *cp); 107extern void delete_child (child_process *cp);