+DEFUN ("make-serial-process", Fmake_serial_process, Smake_serial_process,
+ 0, MANY, 0,
+ doc: /* Create and return a serial port process.
+
+In Emacs, serial port connections are represented by process objects,
+so input and output work as for subprocesses, and `delete-process'
+closes a serial port connection. However, a serial process has no
+process id, it cannot be signaled, and the status codes are different
+from normal processes.
+
+`make-serial-process' creates a process and a buffer, on which you
+probably want to use `process-send-string'. Try \\[serial-term] for
+an interactive terminal. See below for examples.
+
+Arguments are specified as keyword/argument pairs. The following
+arguments are defined:
+
+:port PORT -- (mandatory) PORT is the path or name of the serial port.
+For example, this could be "/dev/ttyS0" on Unix. On Windows, this
+could be "COM1", or "\\\\.\\COM10" for ports higher than COM9 (double
+the backslashes in strings).
+
+:speed SPEED -- (mandatory) is handled by `serial-process-configure',
+which is called by `make-serial-process'.
+
+:name NAME -- NAME is the name of the process. If NAME is not given,
+the value of PORT is used.
+
+:buffer BUFFER -- BUFFER is the buffer (or buffer-name) to associate
+with the process. Process output goes at the end of that buffer,
+unless you specify an output stream or filter function to handle the
+output. If BUFFER is not given, the value of NAME is used.
+
+:coding CODING -- If CODING is a symbol, it specifies the coding
+system used for both reading and writing for this process. If CODING
+is a cons (DECODING . ENCODING), DECODING is used for reading, and
+ENCODING is used for writing.
+
+:noquery BOOL -- When exiting Emacs, query the user if BOOL is nil and
+the process is running. If BOOL is not given, query before exiting.
+
+:stop BOOL -- Start process in the `stopped' state if BOOL is non-nil.
+In the stopped state, a serial process does not accept incoming data,
+but you can send outgoing data. The stopped state is cleared by
+`continue-process' and set by `stop-process'.
+
+:filter FILTER -- Install FILTER as the process filter.
+
+:sentinel SENTINEL -- Install SENTINEL as the process sentinel.
+
+:plist PLIST -- Install PLIST as the initial plist of the process.
+
+:speed
+:bytesize
+:parity
+:stopbits
+:flowcontrol
+-- These arguments are handled by `serial-process-configure', which is
+called by `make-serial-process'.
+
+The original argument list, possibly modified by later configuration,
+is available via the function `process-contact'.
+
+Examples:
+
+\(make-serial-process :port "/dev/ttyS0" :speed 9600)
+
+\(make-serial-process :port "COM1" :speed 115200 :stopbits 2)
+
+\(make-serial-process :port "\\\\.\\COM13" :speed 1200 :bytesize 7 :parity 'odd)
+
+\(make-serial-process :port "/dev/tty.BlueConsole-SPP-1" :speed nil)
+
+usage: (make-serial-process &rest ARGS) */)
+ (nargs, args)
+ int nargs;
+ Lisp_Object *args;
+{
+ int fd = -1;
+ Lisp_Object proc, contact, port;
+ struct Lisp_Process *p;
+ struct gcpro gcpro1;
+ Lisp_Object name, buffer;
+ Lisp_Object tem, val;
+ int specpdl_count = -1;
+
+ if (nargs == 0)
+ return Qnil;
+
+ contact = Flist (nargs, args);
+ GCPRO1 (contact);
+
+ port = Fplist_get (contact, QCport);
+ if (NILP (port))
+ error ("No port specified");
+ CHECK_STRING (port);
+
+ if (NILP (Fplist_member (contact, QCspeed)))
+ error (":speed not specified");
+ if (!NILP (Fplist_get (contact, QCspeed)))
+ CHECK_NUMBER (Fplist_get (contact, QCspeed));
+
+ name = Fplist_get (contact, QCname);
+ if (NILP (name))
+ name = port;
+ CHECK_STRING (name);
+ proc = make_process (name);
+ specpdl_count = SPECPDL_INDEX ();
+ record_unwind_protect (make_serial_process_unwind, proc);
+ p = XPROCESS (proc);
+
+ fd = serial_open ((char*) SDATA (port));
+ p->infd = fd;
+ p->outfd = fd;
+ if (fd > max_process_desc)
+ max_process_desc = fd;
+ chan_process[fd] = proc;
+
+ buffer = Fplist_get (contact, QCbuffer);
+ if (NILP (buffer))
+ buffer = name;
+ buffer = Fget_buffer_create (buffer);
+ p->buffer = buffer;
+
+ p->childp = contact;
+ p->plist = Fcopy_sequence (Fplist_get (contact, QCplist));
+ p->type = Qserial;
+ p->sentinel = Fplist_get (contact, QCsentinel);
+ p->filter = Fplist_get (contact, QCfilter);
+ p->log = Qnil;
+ if (tem = Fplist_get (contact, QCnoquery), !NILP (tem))
+ p->kill_without_query = 1;
+ if (tem = Fplist_get (contact, QCstop), !NILP (tem))
+ p->command = Qt;
+ p->pty_flag = 0;
+
+ if (!EQ (p->command, Qt))
+ {
+ FD_SET (fd, &input_wait_mask);
+ FD_SET (fd, &non_keyboard_wait_mask);
+ }
+
+ if (BUFFERP (buffer))
+ {
+ set_marker_both (p->mark, buffer,
+ BUF_ZV (XBUFFER (buffer)),
+ BUF_ZV_BYTE (XBUFFER (buffer)));
+ }
+
+ tem = Fplist_member (contact, QCcoding);
+ if (!NILP (tem) && (!CONSP (tem) || !CONSP (XCDR (tem))))
+ tem = Qnil;
+
+ val = Qnil;
+ if (!NILP (tem))
+ {
+ val = XCAR (XCDR (tem));
+ if (CONSP (val))
+ val = XCAR (val);
+ }
+ else if (!NILP (Vcoding_system_for_read))
+ val = Vcoding_system_for_read;
+ else if ((!NILP (buffer) && NILP (XBUFFER (buffer)->enable_multibyte_characters))
+ || (NILP (buffer) && NILP (buffer_defaults.enable_multibyte_characters)))
+ val = Qnil;
+ p->decode_coding_system = val;
+
+ val = Qnil;
+ if (!NILP (tem))
+ {
+ val = XCAR (XCDR (tem));
+ if (CONSP (val))
+ val = XCDR (val);
+ }
+ else if (!NILP (Vcoding_system_for_write))
+ val = Vcoding_system_for_write;
+ else if ((!NILP (buffer) && NILP (XBUFFER (buffer)->enable_multibyte_characters))
+ || (NILP (buffer) && NILP (buffer_defaults.enable_multibyte_characters)))
+ val = Qnil;
+ p->encode_coding_system = val;
+
+ setup_process_coding_systems (proc);
+ p->decoding_buf = make_uninit_string (0);
+ p->decoding_carryover = 0;
+ p->encoding_buf = make_uninit_string (0);
+ p->inherit_coding_system_flag
+ = !(!NILP (tem) || NILP (buffer) || !inherit_process_coding_system);
+
+ Fserial_process_configure(nargs, args);
+
+ specpdl_ptr = specpdl + specpdl_count;
+
+ UNGCPRO;
+ return proc;
+}
+#endif /* HAVE_SERIAL */
+