4 proc debug {m} { puts "DEBUG $m" }
6 proc log {m} { puts "LOG $m" }
12 proc find-devices {} {
13 global errorCode errorInfo devices
14 set base /sys/class/tty
15 foreach candidate [glob -nocomplain -directory $base -tails ttyACM*] {
16 debug "candidate $candidate"
17 if {[catch { file link $base/$candidate/device } ltarget]} {
18 debug " readlink failed [lrange $errorCode 0 1]"
19 switch -glob $errorCode {
20 {POSIX EINVAL *} continue
21 {POSIX ENOENT *} continue
22 default { error "$ltarget \[$errorCode] $errorInfo $errorCode" }
25 if {![regexp {^(.*)\.(\d+)$} $ltarget dummy dbase interf]} {
26 debug " readlink bad target $ltarget"
29 debug " approved $dbase $interf $candidate"
30 lappend devs($dbase) [list $interf $candidate]
32 set howmany [array size devs]
34 experror "no appropriate device(s) found"
37 experror "several appropriate device(s) found [array names $devs]"
40 foreach dev [lsort -index 0 -integer $devs([lindex [array names devs] 0])] {
41 lappend devices [lindex $dev 1]
45 proc reopen-our-device {} {
48 set dchan [open /dev/[lindex $devices 1] r+]
49 fconfigure $dchan -blocking no -buffering line -translation {crlf cr}
50 read $dchan; # flush input
54 set result [read $dchan]
55 if {![regexp -line {^OK$} $result]} { experror "got [logquote $result]" }
56 fileevent $dchan readable dchan-readable
59 proc devfailure {emsg} {
60 global errorCode errorInfo dchan
61 switch -glob $errorCode {
62 {POSIX *} - EXPECTED {
63 log "device failure: $emsg"
66 log "unexpected device failure: $emsg"
67 foreach l [split $errorInfo "\n"] {
72 if {[info exists dchan]} {
73 catch { close $dchan }
78 proc try-open-our-device {} {
86 sendout-async *TTYATMUX "*TTYATMUXDEVS [join $devices ,]"
87 sendout-async *TTYATMUX "*TTYATMUXOPEN"
90 proc dchan-readable {args} {
100 if {![eof $dchan]} return
101 set errorCode EXPECTED
109 proc async-notif fixme this has wrong arguments
111 proc async-notif-or-resp-fixed {asid l} {
112 global current_command_asid
113 if {![string compare $asid $current_command_asid]} {
120 proc async-notif-creg {asid l} {
121 set ll [llength [split $l ,]]
125 async-notif {+CREG} 2 2 $l
126 async-notif {+CREG} 1 1 [lindex [split $l ,] 0]
130 async-notif {+CREG} 1 2 $l
133 bad-data $l "async-notif-creg $ll"
138 proc async-control-max0 {c l allows} {
139 async-control-core $c $l $allows {
144 if {$tw} { set wanted 1 }
147 foreach allow $allows { lappend $send [lindex $allow 0] }
148 sync-subcommand $c "$cmd=[join $send ,]" async-updated-ok $c
152 proc async-control-cmer {c l allows} {
153 async-control-core $c $l $allows {
156 set mode 0; set ind 0
157 manyset $ca($c) mode keyp disp ind bfr
158 if {$mode==3 && $ind} { set send 3,0,0,1 }
160 sync-subcommand $c "$cmd=$send" async-updated-ok $c
164 proc async-updated-ok
166 proc async-control-core {c l allows ubody_init ubody_perclient ubody_finish} {
169 if {[regexp {^(AT[^=?])\?$} dummy cmd]} {
170 sync-subcommand $c $cmd async-massage-result-subs $c $cmd
171 } elseif {[regexp {^(AT[^=?])=\?$} dummy cmd]} {
172 sync-subcommand $c $cmd async-massage-result-support $c $cmd $allows
173 } elseif {[regexp {^(AT[^=?])=([0-9,]+)$} dummy cmd values]} {
174 set values [split $values ,]
175 if {[llength $values] > [llength $allows]} {
176 bad-command "too many values"
179 while {[llength $values] < [llength $allows]} {
182 foreach val $values allow $allows {
183 if {[lsearch -exact $allow $val]<0} {
184 bad-command "$val not in allowed $allow ($allows)"
188 uplevel 1 [list upvar #0 client_async/$cmd ca]
189 upvar #0 client_async/$cmd ca
191 uplevel 1 $ubody_init
193 foreach uc [array names clients] {
194 uplevel 1 $ubody_perclient
196 uplevel 1 $ubody_finish
198 bad-command "unknown async control syntax"
202 proc set-client-echo {c yn} {
204 set client_echo($c) 0
205 client-command-complete $c OK
210 proc client-command-complete
212 proc process-client-command {c nl} {
214 {^AT\+CREG\b} { async-control-max0 $c $l {{0 1 2}} }
215 {^AT\+CGREG\b} { async-control-max0 $c $l {{0 1 2}} }
216 {^AT\*ERINFO\b} { async-control-max0 $c $l {{0 1}} }
217 {^AT\+CGEREP\b} { async-control-max0 $c $l {{0 1 2} 0} }
218 {^AT\+CMER\b} { async-control-cmer $c $l {{0 3} 0 0 {0 1} 0} }
219 {^ATE0$} { set-client-echo $c 0 }
220 {^ATE1$} { set-client-echo $c 1 }
223 proc dchan-line {l} {
226 {\+CREG:} { async-notif-creg +CREG $l }
227 {\+CGREG:} { async-notif-creg +CGREG $l }
228 {\*ERINFO:} { async-notif-or-resp-fixed *ERINFO $l }
229 {\+CGEV:} { async-notif +CGEREP $l }
230 {\+CIEV:} { async-notif +CMER $l }