runtime integer->baud-rate-constant looking via stty instead of macroexpand time via with-serial-stream

Nikolay V. Razbegaev [2009-11-27 19:27]
runtime integer->baud-rate-constant looking via stty instead of macroexpand time via with-serial-stream
Filename
README
streams.lisp
wrapers.lisp
diff --git a/README b/README
index 66af07d..6d33ae8 100644
--- a/README
+++ b/README
@@ -51,7 +51,8 @@ and specify additional stream parameters.
 type "'icanon" instead of "-icanon" to disable feature, "'(icanon t)"
 instead of "icanon" to enable feature, "'(vtime 1)" instead of "vtime 1"
 to specify some value. And switching to raw mode is just
-"'raw", not "'(raw t)".
+"'raw", not "'(raw t)". Also, baud rate can be specified in integer
+(i.e. 115200) and symbol-constant (i.e. 'b115200) form.

 SUPPORTED PLATFORMS:

@@ -65,7 +66,10 @@ TODO:

 0 Checking right `#+' and `#-' for non posix features.

-1 Testing on other OS and lisp implementation.
+1 Define termios constants via constantenum and change stty syntax
+  (keywords parameters).
+
+2 Testing on other OS and lisp implementation.

 3 Testing units.

diff --git a/streams.lisp b/streams.lisp
index 7f86f36..b5d6191 100644
--- a/streams.lisp
+++ b/streams.lisp
@@ -77,9 +77,10 @@
                                       (external-format :default)
                                       timeout read-timeout write-timeout)
                               &body body)
-  "Wrapper around `with-tty-stream' with a few number of settings:
-   - speed: baud rate. An integer, this macro will look for a corresponding
-     baud rate constant and use it, or signal an error otherwise;
+  "Wrapper around `with-open-stream' with a few settings for serial device:
+   - speed: baud rate. An integer (stty will look for a corresponding
+     baud rate constant and use it, or signal an error otherwise),
+     or constant symbol;
    - parity: one of `:n' (no parity checking), `:e' (even), `:o' (odd),
      or `:s' (space parity);
    - byte-size: character size as it described in
@@ -116,14 +117,9 @@
                                     :flag ,flag
                                     :mode ,mode
                                     :external-format ,external-format))
-     (stty (fd-of ,stream)
+     (stty ,stream
            ;; speed first
-           ,@(let* ((sym (find-symbol (format nil "B~a" speed)
-                                      :iolib.termios))
-                    (hash (gethash sym *termios-options*)))
-                   (if (and hash (eql (cdr hash) 'baud-rates))
-                       `(',sym)
-                       (error "Unknown baud rate ~a" speed)))
+           ,speed
            ;; do not block on reading
            'raw '(vtime 0) '(vmin 0)
            ;; allways reset csize before set byte size
diff --git a/wrapers.lisp b/wrapers.lisp
index 19c26ec..f0ca7f1 100644
--- a/wrapers.lisp
+++ b/wrapers.lisp
@@ -150,26 +150,36 @@
 ;; I guess that bits manipulation stuff is not a lisp way,
 ;; and using a kind of `stty (1p)' will be more lisp kind
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun stty (fd &rest options)
-  "Impliment stty (1p) in lisp way.
+(defun stty (serial &rest options)
+  "Impliment stty (1) in lisp way.
+   `serial' can be stream or fd.
    Each `options' element should be termios option name
    or list in (option-name option-value) form.
    '(flag-name t) set corresponding flag,
    '(flag-name nil) or 'flag-name reset it.
    'baud-rate-constant set corresponding speed.
    '(control-character-name control-character-value) setup corresponding
-    control character value.
+   control character value.
+   Baud rate can be specified in integer form to.

    Setup for 8n1 mode: (stty fd '(evenp nil))
-   Setup speed: (stty fd 'b115200)
+   Setup speed: (stty fd 'b115200) or (stty my-stream 115200)
    Setup raw mode: (stty fd 'raw)
    Setup cooked mode: (stty fd '(raw nil) or (stty 'cooked)
   "
   (labels ((process-option (option termios)
 	     (cond
-	       ((member option *baud-rates*)
-		(%cfsetispeed termios (symbol-value option))
-		(%cfsetospeed termios (symbol-value option)))
+	       ((or (member option *baud-rates*)
+                    (integerp option))
+                (let* ((sym (if (integerp option)
+                                (find-symbol (format nil "B~a" option)
+                                             :iolib.termios)
+                                option))
+                       (hash (gethash sym *termios-options*)))
+                  (unless (and hash (eql (cdr hash) 'baud-rates))
+                    (error "Unknown baud rate ~a" option))
+		(%cfsetispeed termios (symbol-value sym))
+		(%cfsetospeed termios (symbol-value sym))))
 	       ((member option '(evenp 'parity))
 		(make-evenp-termios termios))
 	       ((eq option 'oddp)
@@ -209,6 +219,10 @@
                                   'cc
                                   i))
                   (return nil))))))
+    (let ((fd (typecase serial
+                (integer serial)
+                (stream (fd-of serial))
+                (t (error "You should specify stream or fd")))))
     (with-foreign-objects ((set  'termios)
                            (test 'termios))
       (%tcgetattr fd set)
@@ -225,9 +239,12 @@
         (%tcsetattr fd tcsanow set)
         (%tcgetattr fd test)
         (or (compare-termios set test)
-            (if (member option *baud-rates*)
+            (if (or (member option *baud-rates*) (integerp option))
                 (error 'termios-speed-failled
-                       :request (parse-integer (symbol-name option) :start 1))
+                       :request (if (integerp option)
+                                    option
+                                    (parse-integer (symbol-name option)
+                                                   :start 1)))
                 (error 'termios-set-failled
-                       :request option)))))))
+                       :request option))))))))
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ViewGit