3 # Wrapper (tcl) for usb_modeswitch, called from
4 # /lib/udev/rules.d/40-usb_modeswitch.rules
5 # (part of data pack "usb-modeswitch-data") via
6 # /lib/udev/usb_modeswitch
8 # Does ID check on newly discovered USB devices and calls
9 # the mode switching program with the matching parameter
10 # file from /usr/share/usb_modeswitch
12 # Part of usb-modeswitch-1.1.7 package
13 # (C) Josua Dietze 2009, 2010, 2011
16 # Setting of the these switches is done in the global config
17 # file (/etc/usb_modeswitch.conf) if available
23 set env
(PATH
) "/bin:/usr/bin"
25 # Execution starts at file bottom
27 proc {Main
} {argc argv
} {
29 global scsi usb config match wc device logging noswitching settings
31 set loginit
[ParseGlobalConfig
]
33 # The facility to add a symbolic link pointing to the
34 # ttyUSB port which provides interrupt transfer, i.e.
35 # the port to connect through; returns a symlink name
37 # This is run once for every known device interface by
40 if {[lindex $argv 0] == "--symlink-name"} {
42 set device
[clock clicks
]
44 puts -nonewline [SymLinkName
[lindex $argv 1]]
48 set settings
(dbdir
) /usr
/share
/usb_modeswitch
49 if {![file exists
$settings(dbdir
)]} {
50 # Old place available?
51 set settings
(dbdir
) /etc
/usb_modeswitch.d
52 if {![file exists
$settings(dbdir
)]} {
54 Log
"Error: no config database found in /usr/share or /etc. Exiting"
63 # argv contains the values provided from the udev rule
66 set argList
[split [lindex $argv 0] /]
68 if [string length
[lindex $argList 1]] {
69 set device
[lindex $argList 1]
74 Log
"raw args from udev: $argv\n\n$loginit"
76 if {$device == "noname"} {
77 Log
"No data from udev. Exiting"
81 # arg 0: the bus id for the device (udev: %b)
82 # arg 1: the "kernel name" for the device (udev: %k)
84 # Both together give the top directory where the path
85 # to the SCSI attributes can be determined (further down)
86 # Addendum: older kernel/udev version seem to differ in
87 # providing these attributes - or not. So more probing
90 if {[string length
[lindex $argList 0]] == 0} {
91 if {[string length
[lindex $argList 1]] == 0} {
92 Log
"No device number values given from udev! Exiting"
95 Log
"Bus ID for device not given by udev."
96 Log
" Trying to determine it from kernel name ([lindex $argList 1]) ..."
97 if {![regexp {(.
*?
):} [lindex $argList 1] d dev_top
]} {
98 Log
"Could not determine top device dir from udev values! Exiting"
103 set dev_top
[lindex $argList 0]
104 regexp {(.
*?
):} $dev_top d dev_top
108 set devdir
/sys
/bus
/usb
/devices
/$dev_top
109 if {![file isdirectory
$devdir]} {
110 Log
"Top sysfs directory not found ($devdir)! Exiting"
115 # Mapping of the short string identifiers (in the config
116 # file names) to the long name used here
118 # If we need them it's a snap to add new attributes here!
120 set match
(sVe
) scsi
(vendor
)
121 set match
(sMo
) scsi
(model
)
122 set match
(sRe
) scsi
(rev
)
123 set match
(uMa
) usb
(manufacturer
)
124 set match
(uPr
) usb
(product
)
125 set match
(uSe
) usb
(serial
)
128 # Now reading the USB attributes
132 if {[string length
"$usb(idVendor)$usb(idProduct)"] < 8} {
133 Log
"USB IDs not found in sysfs tree. Exiting"
137 Log
"----------------\nUSB values from sysfs:"
138 foreach attr
{manufacturer product serial
} {
139 Log
" $attr\t$usb($attr)"
141 Log
"----------------"
144 Log
"\nSwitching globally disabled. Exiting\n"
145 catch {exec logger
-p syslog.notice
"usb_modeswitch: switching disabled, no action for $usb(idVendor):$usb(idProduct)" 2>/dev
/null
}
149 # Check if there is more than one config file for this USB ID,
150 # which would point to a possible ambiguity. If so, check if
151 # SCSI values are needed
153 set configList
[ConfigGet
list $usb(idVendor
):$usb(idProduct
)]
155 if {[llength $configList] == 0} {
156 Log
"Aargh! Config file missing for $usb(idVendor):$usb(idProduct)! Exiting"
161 if {[llength $configList] > 1} {
162 if [regexp {:s
} $configList] {
167 Log
"SCSI attributes not needed, moving on"
171 # Getting the SCSI values via libusb results in a detached
172 # usb-storage driver. Not good for devices that want to be
173 # left alone. Fortunately, the sysfs tree provides the values
174 # too without need for direct access
176 # First we wait until the SCSI data is ready - or timeout.
177 # Timeout means: no storage driver was bound to the device.
178 # We run 20 times max, every half second (max. 10 seconds
181 # We also check if the device itself changes, probably
182 # because it was switched by the kernel (or even unplugged).
183 # Then we do simply nothing and exit quietly ...
186 while {$scsiNeeded && $counter < 20} {
189 Log
"waiting for storage tree in sysfs"
191 set sysdir
$devdir/[lindex $argList 1]
193 if {![file isdirectory
$sysdir]} {
194 # Device is gone. Unplugged? Switched by kernel?
195 Log
"sysfs device tree is gone; exiting"
198 set rc
[open $devdir/product r
]
199 set newproduct
[read -nonewline $rc]
201 if {![string match
$newproduct $usb(product
)]} {
202 # Device has just changed. Switched by someone else?
203 Log
"device has changed; exiting"
207 # Searching the storage/SCSI tree; might take a while
208 if {[set dirList
[glob -nocomplain $sysdir/host
*]] != ""} {
209 set sysdir
[lindex $dirList 0]
210 if {[set dirList
[glob -nocomplain $sysdir/target
*]] != ""} {
211 set sysdir
[lindex $dirList 0]
212 regexp {.
*target
(.
*)} $sysdir d subdir
213 if {[set dirList
[glob -nocomplain $sysdir/$subdir*]] != ""} {
214 set sysdir
[lindex $dirList 0]
215 if [file exists
$sysdir/vendor
] {
216 # Finally SCSI structure is ready, get the values
217 ReadSCSIAttrs
$sysdir
218 Log
"SCSI values read"
226 if {$counter == 20 && [string length
$scsi(vendor
)] == 0} {
227 Log
"SCSI tree not found; you may want to check if this path/file exists:"
228 Log
"$sysdir/vendor\n"
230 Log
"----------------\nSCSI values from sysfs:"
231 foreach attr
{vendor model rev
} {
232 Log
" $attr\t$scsi($attr)"
234 Log
"----------------"
236 Log
"Waiting 3 secs. after SCSI device was added"
242 # If SCSI tree in sysfs was not identified, try and get the values
243 # from a (nonswitching) call of usb_modeswitch; this detaches the
244 # storage driver, so it's just the last resort
246 if {$scsiNeeded && $scsi(vendor
)==""} {
247 set testSCSI
[exec $bindir/usb_modeswitch
-v 0x
$usb(idVendor
) -p 0x
$usb(idProduct
) 2>/dev
/null
]
248 regexp { Vendor String
: (.
*?
)\n} $testSCSI d scsi
(vendor
)
249 regexp { Model String
: (.
*?
)\n} $testSCSI d scsi
(model
)
250 regexp {Revision String
: (.
*?
)\n} $testSCSI d scsi
(rev
)
251 Log
"SCSI values from usb_modeswitch:"
252 foreach attr
{vendor model rev
} {
253 Log
" $attr\t$scsi($attr)"
257 # If we don't have the SCSI values by now, we just
258 # leave the variables empty; they won't match anything
260 # Time to check for a matching config file.
261 # Matching itself is done by MatchDevice
263 # Sorting the configuration file names reverse so that
264 # the ones with matching additions are tried first; the
265 # common configs without match attributes are used at the
266 # end and provide a fallback
269 foreach configuration
[lsort -decreasing $configList] {
271 # skipping installer leftovers
272 if [regexp {\.
(dpkg|rpm
)} $configuration] {continue}
274 Log
"checking config: $configuration"
275 if [MatchDevice
$configuration] {
276 ParseDeviceConfig
[ConfigGet config
$configuration]
277 set devList1
[ListSerialDevs
]
278 if {$config(waitBefore
) == ""} {
279 Log
"! matched, now switching"
281 Log
"! matched, waiting time set to $config(waitBefore) seconds"
282 append config
(waitBefore
) "000"
283 after $config(waitBefore
)
284 Log
" waiting is over, switching starts now"
287 # Now we are actually switching
289 Log
" (running command: $bindir/usb_modeswitch -I -W -c $settings(tmpConfig))"
290 set report
[exec $bindir/usb_modeswitch
-I -W -D -c $settings(tmpConfig
) 2>@ stdout
]
292 set report
[exec $bindir/usb_modeswitch
-I -Q -D -c $settings(tmpConfig
) 2>/dev
/null
]
294 Log
"\nVerbose debug output of usb_modeswitch and libusb follows\n(Note that some USB errors are expected in the process)"
295 Log
"--------------------------------"
297 Log
"--------------------------------"
298 Log
"(end of usb_modeswitch output)\n"
299 if [regexp {/tmp
/} $settings(tmpConfig
)] {
300 file delete
$settings(tmpConfig
)
304 Log
"* no match, not switching with this config"
308 # We're finished with switching; success checking
309 # was done by usb_modeswitch and logged via syslog.
311 # If switching was OK we now check for drivers by
312 # simply recounting serial devices under /dev
314 if {![file isdirectory
$devdir]} {
315 Log
"Device directory in sysfs is gone! Something went wrong, aborting"
318 # Give the device annother second if it's not fully back yet
319 if {![file exists
$devdir/idProduct
]} {
322 if {![file exists
$devdir/idProduct
]} {
327 # If target ID given, driver shall be loaded
328 if [regexp -nocase {ok
:[0-9a-f
]{4}:[0-9a-f
]{4}|ok
:no_data
} $report] {
330 if {[string length
"$usb(idVendor)$usb(idProduct)"] < 8} {
331 regexp {ok
:(\w
{4}):(\w
{4})} $report d usb
(idVendor
) usb
(idProduct
)
333 set t
"$usb(idVendor)$usb(idProduct)"
334 if {[string length
$t] != 8 ||
[string trim
$t 0] == ""} {
335 if {$report == "ok:no_data"} {
336 Log
"Libusb1 bug prevented device searching, and device ID not found afterwards."
338 Log
"No vendor/product ID found or given, can't continue. Aborting"
342 # For general driver loading; TODO: add respective device names.
343 # Presently only useful for HSO devices (which are recounted now)
344 if {$config(driverModule
) == ""} {
345 set config
(driverModule
) "option"
346 set config
(driverIDPath
) "/sys/bus/usb-serial/drivers/option1"
348 if {$config(driverIDPath
) == ""} {
349 set config
(driverIDPath
) "/sys/bus/usb/drivers/$config(driverModule)"
352 Log
"Driver module is \"$config(driverModule)\", ID path is $config(driverIDPath)\n"
354 # some settling time in ms
357 Log
"Now checking for newly created serial devices ..."
358 set devList2
[ListSerialDevs
]
360 if {[llength $devList1] >= [llength $devList2]} {
361 Log
" no new serial devices found"
362 AddToList link_list
$usb(idVendor
):$usb(idProduct
)
364 # If device is known, the sh wrapper will take care, else:
365 if {[InBindList
$usb(idVendor
):$usb(idProduct
)] == 0} {
366 Log
"Device not in bind_list"
369 CheckDriverBind
$usb(idVendor
) $usb(idProduct
)
372 # Old/slow systems may take a while to create the devices
373 while {[llength $devList1] >= [llength $devList2] && $counter < 14} {
375 set devList2
[ListSerialDevs
]
378 if {$counter == 14} {
379 Log
" still no new serial devices found"
381 Log
" driver successfully bound"
382 AddToList bind_list
$usb(idVendor
):$usb(idProduct
)
386 Log
" new serial devices found, driver has bound"
387 if {[llength [lsearch -glob -all $devList2 *ttyUSB
*]] > [llength [lsearch -glob -all $devList1 *ttyUSB
*]]} {
388 AddToList link_list
$usb(idVendor
):$usb(idProduct
)
392 # Just in case "NoDriverLoading" was added after the first bind
393 RemoveFromBindList
$usb(idVendor
):$usb(idProduct
)
396 if [regexp {ok
:$} $report] {
397 # "NoDriverLoading" was set
398 Log
"Doing no driver checking or binding for this device"
401 # In newer kernels there is a switch to avoid the use of a device
402 # reset (e.g. from usb-storage) which would likely switch back
403 # a mode-switching device
404 if [regexp {ok
:} $report] {
405 Log
"Checking for AVOID_RESET_QUIRK attribute"
406 if [file exists
$devdir/avoid_reset_quirk
] {
407 if [catch {exec echo
"1" >$devdir/avoid_reset_quirk
2>/dev
/null
} err
] {
408 Log
" Error setting the attribute: $err"
410 Log
" AVOID_RESET_QUIRK activated"
413 Log
" AVOID_RESET_QUIRK not present"
417 Log
"\nAll done, exiting\n"
424 proc {ReadSCSIAttrs
} {dir
} {
427 Log
"SCSI dir exists: $dir"
429 foreach attr
{vendor model rev
} {
430 if [file exists
$dir/$attr] {
431 set rc
[open $dir/$attr r
]
432 set scsi
($attr) [read -nonewline $rc]
436 Log
"Warning: SCSI attribute \"$attr\" not found."
441 # end of proc {ReadSCSIAttrs}
444 proc {ReadUSBAttrs
} {dir
} {
447 Log
"USB dir exists: $dir"
449 foreach attr
{idVendor idProduct manufacturer product serial
} {
450 if [file exists
$dir/$attr] {
451 set rc
[open $dir/$attr r
]
452 set usb
($attr) [read -nonewline $rc]
456 Log
"Warning: USB attribute \"$attr\" not found."
461 # end of proc {ReadUSBAttrs}
464 proc {MatchDevice
} {config
} {
466 global scsi usb match
468 set devinfo
[file tail
$config]
469 set infoList
[split $devinfo :]
470 set stringList
[lrange $infoList 2 end
]
471 if {[llength $stringList] == 0} {return 1}
473 foreach teststring
$stringList {
474 if {$teststring == "?"} {return 0}
475 set tokenList
[split $teststring =]
476 set id
[lindex $tokenList 0]
477 set matchstring
[lindex $tokenList 1]
479 regsub -all {_
} $matchstring { } blankstring
480 Log
"matching $match($id)"
481 Log
" match string1: $matchstring"
482 Log
" match string2: $blankstring"
483 Log
" device string: [set $match($id)]"
484 if {!([string match
*$matchstring* [set $match($id)]] ||
[string match
*$blankstring* [set $match($id)]])} {
491 # end of proc {MatchDevice}
494 proc {ParseGlobalConfig
} {} {
496 global logging noswitching
499 set places
[list /etc
/usb_modeswitch.conf
/etc
/sysconfig
/usb_modeswitch
/etc
/default/usb_modeswitch
]
500 foreach cfg
$places {
501 if [file exists
$cfg] {
507 if {$configFile == ""} {return}
509 set rc
[open $configFile r
]
512 if [regexp {DisableSwitching
\s
*=\s
*([^
\s
]+)} $line d val
] {
513 if [regexp -nocase {1|yes|true
} $val] {
517 if [regexp {EnableLogging
\s
*=\s
*([^
\s
]+)} $line d val
] {
518 if [regexp -nocase {1|yes|true
} $val] {
524 return "Using global config file: $configFile"
527 # end of proc {ParseGlobalConfig}
530 proc ParseDeviceConfig
{configFile
} {
533 set config
(driverModule
) ""
534 set config
(driverIDPath
) ""
535 set config
(waitBefore
) ""
536 set rc
[open $configFile r
]
537 set lineList
[split [read $rc] \n]
539 foreach line
$lineList {
540 if [regexp {^DriverModule
[[:blank
:]]*=[[:blank
:]]*"?(\w+)"?
} [string trim
$line] d config
(driverModule
)] {
541 Log
"config: DriverModule set to $config(driverModule)"
543 if [regexp {^DriverIDPath
[[:blank
:]]*=[[:blank
:]]*?
"?([/\-\w]+)"?
} [string trim
$line] d config
(driverIDPath
)] {
544 Log
"config: DriverIDPath set to $config(driverIDPath)"
546 if [regexp {^WaitBefore
[[:blank
:]]*=[[:blank
:]]*?
([0-9]+)} [string trim
$line] d config
(waitBefore
)] {
547 Log
"config: WaitBefore set to $config(waitBefore)"
550 set config
(waitBefore
) [string trimleft
$config(waitBefore
) 0]
553 # end of proc {ParseDeviceConfig}
556 proc ConfigGet
{command config
} {
563 if [file exists
$settings(dbdir
)/configPack.tar.gz
] {
564 Log
"Found packed config collection $settings(dbdir)/configPack.tar.gz"
565 if [catch {set configList
[exec tar
-tzf $settings(dbdir
)/configPack.tar.gz
2>/dev
/null
]} err
] {
566 Log
"Error: problem opening config package; tar returned\n $err"
569 set configList
[split $configList \n]
570 set configList
[lsearch -glob -all -inline $configList $config*]
572 set configList
[glob -nocomplain $settings(dbdir
)/$config*]
578 if [file exists
$settings(dbdir
)/configPack.tar.gz
] {
579 set settings
(tmpConfig
) /tmp
/usb_modeswitch.current_cfg
580 Log
"Extracting config $config from collection $settings(dbdir)/configPack.tar.gz"
581 set wc
[open $settings(tmpConfig
) w
]
582 puts -nonewline $wc [exec tar
-xzOf $settings(dbdir
)/configPack.tar.gz
$config 2>/dev
/null
]
585 set settings
(tmpConfig
) $config
587 return $settings(tmpConfig
)
592 # end of proc {ConfigGet}
596 global wc logging device
597 if {$logging == 0} {return}
598 if {![info exists wc
]} {
599 if [catch {set wc
[open /var
/log
/usb_modeswitch_
$device w
]} err
] {
603 puts $wc "\n\nUSB_ModeSwitch log from [clock format [clock seconds]]\n"
605 if {$wc == "error"} {return}
612 # Closing the log file if open and exit
616 if [info exists wc
] {
622 # end of proc {SafeExit}
625 # Checking for interrupt endpoint in ttyUSB port (lowest if there is
626 # more than one); if found, check for unused "gsmmodem[n]" name.
627 # Link for first modem will be "gsmmodem", then "gsmmodem2" and up
629 proc {SymLinkName
} {path
} {
632 set loginit
"* called with --symlink-name: params $path *\n"
634 # Internal proc, used only here
635 proc {hasInterrupt
} {ifDir
} {
636 if {[llength [glob -nocomplain $ifDir/ttyUSB
*]] == 0} {
637 Log
" no ttyUSB interface - skip checking endpoints"
640 foreach epDir
[glob -nocomplain $ifDir/ep_
*] {
641 Log
" in epDir $epDir ..."
642 if [file exists
$epDir/type
] {
643 set rc
[open $epDir/type r
]
646 if [regexp {Interrupt
} $type] {
647 Log
" $epDir has interrupt transfer type"
655 # In case the device path is returned as /class/tty/ttyUSB,
656 # we need to extract the USB device path from symlink "device"
657 set linkpath
/sys
$path/device
658 if [file exists
$linkpath] {
659 if {[file type
$linkpath] == "link"} {
660 set rawpath
[file readlink
$linkpath]
661 set trimpath
[regsub -all {\.
\.
/} $rawpath {}]
662 if [file isdirectory
/sys
/$trimpath] {
669 if {![regexp {ttyUSB
[0-9]+} $path myPort
]} {
670 Log
"$loginit\nCould not find port name in path\n $path. Aborting"
674 Log
"$loginit\nMy name is $myPort"
676 if {![regexp {usb
[0-9]+/([0-9]+-[0-9]+)/} $path d dev_top
]} {
677 Log
"Could not find device directory in path\n $path. Aborting"
681 if {![regexp "\[0-9\]+\\.(\[0-9\]+)/$myPort" $path d myIf
]} {
682 Log
"Could not find interface number in path\n $path. Aborting"
686 if {![regexp "$dev_top:\[0-9\]" /sys
$path ifRoot
]} {
687 Log
"Could not find interface number in path\n $path. Aborting"
691 set dirList
[split $path /]
692 set idx
[lsearch $dirList $dev_top]
694 set devDir
/sys
[join [lrange $dirList 0 $idx] /]
696 Log
"My port is $myPort, my interface is $myIf
697 devDir: $devDir\n dev_top: $dev_top\nsysPath: /sys$path"
699 regexp "$devDir/$dev_top:\[0-9\]" /sys
$path ifRoot
701 set ifDir
$ifRoot.
$myIf
703 Log
"Checking my endpoints in $ifDir"
704 if [hasInterrupt
$ifDir] {
705 Log
"\n--> I am an interrupt port\n"
708 Log
"\n--> I am not an interrupt port\n"
712 # Unfortunately, there are devices with more than one interrupt
713 # port. The assumption so far is that the lowest of these is
714 # right. Check all lower interfaces for annother one (if interface)
715 # is bigger than 0). If found, don't return any name.
717 if { $rightPort && ($myIf > 0) } {
718 Log
"Looking for lower ports with interrupt endpoints"
719 for {set i
0} {$i < $myIf} {incr i
} {
721 Log
" in ifDir $ifDir ..."
722 if [hasInterrupt
$ifDir] {
723 Log
"\n--> found an interrupt interface below me\n"
730 if {$rightPort == 0} {
731 Log
"Return empty name and exit"
735 Log
"\n--> No interrupt interface below me\n"
739 set symlinkName
"gsmmodem"
741 if {![file exists
$symlinkName]} {
744 set symlinkName gsmmodem
$idx
747 Log
"Return symlink name \"$symlinkName\" and exit"
751 # end of proc {SymLinkName}
754 # Load and bind (serial) driver
756 proc {CheckDriverBind
} {vid
pid} {
760 if [file exists
/sbin
/modprobe
] {
761 set loader
/sbin
/modprobe
763 Log
" /sbin/modprobe not found"
766 set idfile
$config(driverIDPath
)/new_id
767 if {![file exists
$idfile]} {
769 Log
"Can't do anymore without module loader; get \"modtools\"!"
772 Log
"\nTrying to load driver \"$config(driverModule)\""
773 if [catch {set result
[exec $loader -v $config(driverModule
)]} err
] {
774 Log
" Running \"$loader $config(driverModule)\" gave an error:\n $err"
776 Log
" Driver was loaded successfully:\n$result"
779 Log
"Driver was loaded already"
783 if [file exists
$idfile] {
790 Log
"Trying to add ID to driver \"$config(driverModule)\""
791 catch {exec logger
-p syslog.notice
"usb_modeswitch: adding device ID $vid:$pid to driver \"$config(driverModule)\"" 2>/dev
/null
}
792 if [catch {exec echo
"$vid $pid" >$idfile} err
] {
793 Log
"Error adding ID to driver: $err"
795 Log
" ID added to driver; check for new devices in /dev"
798 Log
" \"$idfile\" not found, can't add ID to driver;\n check if kernel version is at least 2.6.27"
799 Log
"Falling back to \"usbserial\""
800 set config
(driverModule
) usbserial
801 Log
"\nTrying to unload driver \"$config(driverModule)\""
802 if [catch {exec $loader -r $config(driverModule
)} err
] {
803 Log
" Running \"$loader $config(driverModule)\" gave an error:\n $err"
804 Log
"Can't unload usbserial. No more fallbacks"
807 Log
"\nTrying to load driver \"usbserial\" with device IDs"
808 if [catch {set result
[exec $loader -v usbserial vendor
=0x
$vid product
=0x
$pid]} err
] {
809 Log
" Running \"$loader $config(driverModule)\" gave an error:\n $err"
811 Log
" Driver was loaded successfully:\n$result"
816 # end of proc {CheckDriverBind}
819 # Check if USB ID is listed as needing driver binding
820 proc {InBindList
} {id
} {
822 set listfile
/var
/lib
/usb_modeswitch
/bind_list
823 if {![file exists
$listfile]} {return 0}
824 set rc
[open $listfile r
]
825 set buffer
[read $rc]
827 if [string match
*$id* $buffer] {
828 Log
"Found $id in bind_list"
831 Log
"No $id in bind_list"
836 # end of proc {InBindList}
838 # Add USB ID to list of devices needing later treatment
839 proc {AddToList
} {name id
} {
841 set listfile
/var
/lib
/usb_modeswitch
/$name
842 set oldlistfile
/etc
/usb_modeswitch.d
/bind_list
844 if {($name == "bind_list") && [file exists
$oldlistfile] && ![file exists
$listfile]} {
845 if [catch {file rename $oldlistfile $listfile} err
] {
846 Log
"Error renaming the old bind list file ($err)"
851 if [file exists
$listfile] {
852 set rc
[open $listfile r
]
853 set buffer
[read $rc]
855 if [string match
*$id* $buffer] {
858 set idList
[split [string trim
$buffer] \n]
861 set buffer
[join $idList "\n"]
862 if [catch {set wc
[open $listfile w
]}] {return}
867 # end of proc {AddToList}
870 # Remove USB ID from bind list (NoDriverLoading is set)
871 proc {RemoveFromBindList
} {id
} {
873 set listfile
/var
/lib
/usb_modeswitch
/bind_list
874 if [file exists
$listfile] {
875 set rc
[open $listfile r
]
876 set buffer
[read $rc]
878 set idList
[split [string trim
$buffer] \n]
882 set idx
[lsearch $idList $id]
884 set idList
[lreplace $idList $idx $idx]
888 if {[llength $idList] == 0} {
889 file delete
$listfile
892 set buffer
[join $idList "\n"]
893 if [catch {set wc
[open $listfile w
]}] {return}
898 # end of proc {RemoveFromBindList}
900 # Return a list with all relevant serial devices that are present
901 proc {ListSerialDevs
} {} {
903 set devList
[glob -nocomplain /dev
/ttyUSB
* /dev
/ttyACM
* /dev
/ttyHS
*]
904 if [file isdirectory
/dev
/tts
] {
905 eval lappend devList
[glob -nocomplain /dev
/tts
/*]
910 # end of proc {ListSerialDevs}
913 # The actual entry point