~ubuntu-branches/ubuntu/utopic/usb-modeswitch/utopic

« back to all changes in this revision

Viewing changes to usb_modeswitch.tcl

  • Committer: Package Import Robot
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2014-04-07 11:39:41 UTC
  • mfrom: (17.1.11 sid)
  • Revision ID: package-import@ubuntu.com-20140407113941-b4dwfneyd07pgijf
Tags: 2.1.1+repack0-1ubuntu1
* Merge with Debian unstable; remaining changes: (LP: #1280546)
  - patch to rewrite dispatcher to C.
  - debian/patches/redirect_dispatcher_output.patch: redirect all dispatcher
    output when called from udev to /dev/null.
  - Replace libjim depends with libpipeline-dev, libudev-dev.
* Fixed some bugs in dispatcher rewrite. (LP: #1155975)

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
# the mode switching program with the matching parameter
10
10
# file from /usr/share/usb_modeswitch
11
11
#
12
 
# Part of usb-modeswitch-1.2.3 package
13
 
# (C) Josua Dietze 2009-2012
 
12
# Part of usb-modeswitch-2.1.1 package
 
13
# (C) Josua Dietze 2009-2014
14
14
 
15
15
set arg0 [lindex $argv 0]
16
16
if [regexp {\.tcl$} $arg0] {
26
26
 
27
27
set flags(logging) 0
28
28
set flags(noswitching) 0
29
 
 
30
 
#set env(PATH) "/bin:/sbin:/usr/bin:/usr/sbin"
 
29
set flags(stordelay) 0
31
30
 
32
31
# Execution starts at file bottom
33
32
 
34
33
proc {Main} {argv argc} {
35
34
 
36
 
global scsi usb config match device flags settings
 
35
global scsi usb config match device flags setup devdir loginit
37
36
 
38
 
set loginit [ParseGlobalConfig]
 
37
set flags(logwrite) 0
 
38
Log "[ParseGlobalConfig]"
39
39
 
40
40
# The facility to add a symbolic link pointing to the
41
41
# ttyUSB port which provides interrupt transfer, i.e.
52
52
        SafeExit
53
53
}
54
54
 
55
 
set argList [split [lindex $argv 1] /]
56
 
 
57
 
if [string length [lindex $argList 1]] {
58
 
        set device [lindex $argList 1]
 
55
if {[lindex $argv 0] == "--switch-systemd"} {
 
56
        set device [string trim [lindex $argv 1] "/-"]
 
57
        set device [regsub {/} $device "-"]
 
58
        set argList [list "" $device]
 
59
        Log "\nStarted via systemd"
59
60
} else {
60
 
        set device "noname"
 
61
        if {[lindex $argv 0] == "--switch-upstart"} {
 
62
                Log "\nStarted via upstart"
 
63
        }
 
64
        set argList [split [lindex $argv 1] /]
 
65
        if [string length [lindex $argList 1]] {
 
66
                set device [lindex $argList 1]
 
67
        } else {
 
68
                set device "noname"
 
69
        }
 
70
}
 
71
if {$flags(stordelay) > 0} {
 
72
        SetStorageDelay $flags(stordelay)
61
73
}
62
74
 
63
 
Log "Raw args from udev: [lindex $argv 1]\n\n$loginit"
 
75
Log "Raw args from udev: [lindex $argv 1]\n"
64
76
 
65
77
if {$device == "noname"} {
66
 
        Log "No data from udev. Exiting"
67
 
        SafeExit
68
 
}
69
 
 
70
 
if {[lindex $argv 0] != "--switch-mode"} {
71
 
        Log "No command given. Exiting"
72
 
        SafeExit
73
 
}
74
 
 
75
 
if {![regexp /lib/udev/usb_modeswitch [lindex $argv 2]]} {
76
 
        Log "Dispatcher was not run from call script. Exiting"
77
 
        SafeExit
78
 
}
79
 
 
80
 
set settings(dbdir)     /usr/share/usb_modeswitch
81
 
set settings(dbdir_etc) /etc/usb_modeswitch.d
82
 
 
83
 
 
84
 
if {![file exists $settings(dbdir)] && ![file exists $settings(dbdir_etc)]} {
85
 
        Log "Error: no config database found in /usr/share or /etc. Exiting"
 
78
        Log "\nNo data from udev. Exit"
 
79
        SafeExit
 
80
}
 
81
 
 
82
if {![regexp -- {--switch-} [lindex $argv 0]]} {
 
83
        Log "\nNo command given. Exit"
 
84
        SafeExit
 
85
}
 
86
 
 
87
set setup(dbdir) /usr/share/usb_modeswitch
 
88
set setup(dbdir_etc) /etc/usb_modeswitch.d
 
89
 
 
90
 
 
91
if {![file exists $setup(dbdir)] && ![file exists $setup(dbdir_etc)]} {
 
92
        Log "\nError: no config database found in /usr/share or /etc. Exit"
86
93
        SafeExit
87
94
}
88
95
set bindir /usr/sbin
91
98
set devList2 {}
92
99
 
93
100
 
94
 
# arg 0: the bus id for the device (udev: %b)
 
101
# arg 0: the bus id for the device (udev: %b), often ommitted
95
102
# arg 1: the "kernel name" for the device (udev: %k)
96
103
#
97
 
# Both together give the top directory where the path
98
 
# to the SCSI attributes can be determined (further down)
99
 
# Addendum: older kernel/udev version seem to differ in
100
 
# providing these attributes - or not. So more probing
101
 
# is needed
 
104
# Used to determine the top directory for the device in sysfs
102
105
 
 
106
set ifChk 0
103
107
if {[string length [lindex $argList 0]] == 0} {
104
108
        if {[string length [lindex $argList 1]] == 0} {
105
 
                Log "No device number values given from udev! Exiting"
 
109
                Log "No device number values given from udev! Exit"
106
110
                SafeExit
107
111
        } else {
108
112
                if {![regexp {(.*?):} [lindex $argList 1] d dev_top]} {
109
 
                        Log "Could not determine top device dir from udev values! Exiting"
110
 
                        SafeExit
 
113
                        if [regexp {([0-9]+-[0-9]+\.?[0-9]*.*)} [lindex $argList 1] d dev_top] {
 
114
                                # new udev rules file, got to check class of first interface
 
115
                                set ifChk 1
 
116
                        } else {
 
117
                                Log "Could not determine device dir from udev values! Exit"
 
118
                                SafeExit
 
119
                        }
111
120
                }
112
121
        }
113
122
} else {
117
126
 
118
127
set devdir /sys/bus/usb/devices/$dev_top
119
128
if {![file isdirectory $devdir]} {
120
 
        Log "Top device directory not found ($devdir)! Exiting"
 
129
        Log "Top device directory not found ($devdir)! Exit"
121
130
        SafeExit
122
131
}
123
 
Log "Using top device dir $devdir"
124
 
set ifdir "[file tail $devdir]:1.0"
125
 
 
 
132
Log "Use top device dir $devdir"
 
133
 
 
134
set iface 0
 
135
if $ifChk {
 
136
        Log "Check class of first interface ..."
 
137
        set iclass [IfClass 0]
 
138
        if {$iface < 0} {
 
139
                Log " No access to interface 0. Exit"
 
140
                SafeExit
 
141
        }
 
142
        Log " Interface class is $iclass."
 
143
        if {$iclass == 8 || $iclass == 3} {
 
144
        } else {
 
145
                Log "No install mode found. Aborting"
 
146
                exit
 
147
        }
 
148
}
 
149
set ifdir [file tail [IfDir $iface]]
 
150
regexp {:([0-9]+\.[0-9]+)$} $ifdir d iface
 
151
 
 
152
set flags(logwrite) 1
126
153
 
127
154
# Mapping of the short string identifiers (in the config
128
155
# file names) to the long name used here
139
166
 
140
167
# Now reading the USB attributes
141
168
if {![ReadUSBAttrs $devdir]} {
142
 
        Log "USB attributes not found in sysfs tree. Exiting"
 
169
        Log "USB attributes not found in sysfs tree. Exit"
143
170
        SafeExit
144
171
}
145
172
 
146
173
if $flags(logging) {
147
 
        Log "----------------\nUSB values from sysfs:"
 
174
        Log "\n----------------\nUSB values from sysfs:"
148
175
        foreach attr {manufacturer product serial} {
149
176
                Log "  $attr\t$usb($attr)"
150
177
        }
152
179
}
153
180
 
154
181
if $flags(noswitching) {
155
 
        Log "\nSwitching globally disabled. Exiting\n"
156
182
        SysLog "usb_modeswitch: switching disabled, no action for $usb(idVendor):$usb(idProduct)"
 
183
        Log "\nSwitching globally disabled. Exit"
157
184
        SafeExit
158
185
}
159
186
 
171
198
set configList [ConfigGet conflist $usb(idVendor):$usb(idProduct)]
172
199
 
173
200
if {[llength $configList] == 0} {
174
 
        Log "Aargh! Config file missing for $usb(idVendor):$usb(idProduct)! Exiting"
 
201
        Log "Aargh! Config file missing for $usb(idVendor):$usb(idProduct)! Exit"
175
202
        SafeExit
176
203
}
177
204
 
182
209
        }
183
210
}
184
211
if $scsiNeeded {
185
 
        if [ReadSCSIAttrs $devdir:1.0] {
 
212
        if [ReadSCSIAttrs $devdir:$iface] {
186
213
                Log "----------------\nSCSI values from sysfs:"
187
214
                foreach attr {vendor model rev} {
188
215
                        Log " $attr\t$scsi($attr)"
192
219
                Log "Could not get SCSI attributes, exclude devices with SCSI match"
193
220
        }
194
221
} else {
195
 
        Log "SCSI attributes not needed, moving on"
 
222
        Log "SCSI attributes not needed, move on"
196
223
}
197
224
 
198
 
# General wait - this is important
 
225
# General wait - some devices need this
199
226
after 500
200
227
 
201
228
# Now check for a matching config file. Matching is done
207
234
        # skipping installer leftovers
208
235
        if [regexp {\.(dpkg|rpm)} $configuration] {continue}
209
236
 
210
 
        Log "checking config: $configuration"
 
237
        Log "Check config: $configuration"
211
238
        if [MatchDevice $configuration] {
212
 
                Log "! matched. Reading config data"
 
239
                Log "! matched. Read config data"
213
240
                if [string length $usb(busnum)] {
214
241
                        set busParam "-b [string trimleft $usb(busnum) 0]"
215
242
                        set devParam "-g [string trimleft $usb(devnum) 0]"
221
248
                ParseDeviceConfig $configBuffer
222
249
                if {$config(waitBefore) == ""} {
223
250
                } else {
224
 
                        Log " waiting time set to $config(waitBefore) seconds"
 
251
                        Log "Delay time of $config(waitBefore) seconds"
225
252
                        append config(waitBefore) "000"
226
253
                        after $config(waitBefore)
227
 
                        Log " waiting is over, switching starts now"
 
254
                        Log " wait is over, start mode switch"
 
255
                }
 
256
                if {$config(noMBIMCheck)==0 && $usb(bNumConfigurations) > 1} {
 
257
                        Log "Device may have an MBIM configuration, check driver ..."
 
258
                        if [CheckMBIM] {
 
259
                                Log " driver for MBIM devices is available"
 
260
                                Log "Find MBIM configuration number ..."
 
261
                                if [catch {set cfgno [exec /usr/sbin/usb_modeswitch -j -Q $busParam $devParam -v $usb(idVendor) -p $usb(idProduct)]} err] {
 
262
                                        Log "Error when trying to find MBIM configuration, switch to legacy modem mode"
 
263
                                } else {
 
264
                                        set cfgno [string trim $cfgno]
 
265
                                        if {$cfgno > 0} {
 
266
                                                set config(Configuration) $cfgno
 
267
                                                set config(driverModule) ""
 
268
                                                set configBuffer "Configuration=$cfgno"
 
269
                                        } else {
 
270
                                                Log " No MBIM configuration found, switch to legacy modem mode"
 
271
                                        }
 
272
                                }
 
273
                        } else {
 
274
                                Log " no MBIM driver found, switch to legacy modem mode"
 
275
                        }
228
276
                }
229
277
 
230
278
                # Now we are actually switching
231
279
                if $flags(logging) {
232
 
                        Log "Command to be run:\nusb_modeswitch -I -W -D -s 20 $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f \$configBuffer"
233
 
                        set report [exec /usr/sbin/usb_modeswitch -I -W -D -s 20 $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f "$configBuffer" 2>@ stdout]
 
280
                        Log "Command to be run:\nusb_modeswitch -W -D -s 20 $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f \$configBuffer"
 
281
                        set report [exec /usr/sbin/usb_modeswitch -W -D -s 20 $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f "$configBuffer" 2>@1]
234
282
                        Log "\nVerbose debug output of usb_modeswitch and libusb follows"
235
283
                        Log "(Note that some USB errors are to be expected in the process)"
236
284
                        Log "--------------------------------"
238
286
                        Log "--------------------------------"
239
287
                        Log "(end of usb_modeswitch output)\n"
240
288
                } else {
241
 
                        set report [exec /usr/sbin/usb_modeswitch -I -Q -D -s 20 $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f "$configBuffer" 2>@ stdout]
 
289
                        set report [exec /usr/sbin/usb_modeswitch -Q -D -s 20 $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f "$configBuffer" 2>@1]
242
290
                }
243
291
                break
244
292
        } else {
260
308
                foreach attr [lsort [array names usb]] {
261
309
                        Log "    [format %-26s $attr:] $usb($attr)"
262
310
                }
263
 
                Log "\nMode switching may have failed. Exiting\n"
 
311
                Log "\nMode switching may have failed. Exit"
264
312
                SafeExit
265
313
        }
266
314
} else {
267
315
        if {![file isdirectory $devdir]} {
268
 
                Log "Device directory in sysfs is gone! Something went wrong, aborting"
 
316
                Log "Device directory in sysfs is gone! Something went wrong, abort"
269
317
                SafeExit
270
318
        }
271
319
        if {![regexp {ok:} $report]} {
272
 
                Log "\nCore program reported switching failure. Exiting\n"
 
320
                Log "\nCore program reported switching failure. Exit"
273
321
                SafeExit
274
322
        }
275
323
        # Give the device another second if it's not fully back yet
281
329
 
282
330
# Now checking for bound drivers (only for class 0xff)
283
331
 
284
 
if {$usb($ifdir/bInterfaceClass) != "" && [regexp {ok:} $report]} {
 
332
if {$config(driverModule) != "" && $usb($ifdir/bInterfaceClass) != "" && [regexp {ok:} $report]} {
285
333
        if {$usb($ifdir/bInterfaceClass) != "ff"} {
286
334
                set config(driverModule) ""
287
 
                Log " No vendor-specific class found, skip driver checking"
 
335
                Log " No vendor-specific class found, skip driver check"
288
336
        }
289
337
}
290
338
 
294
342
if {$config(driverModule) != ""} {
295
343
        if {[string length "$usb(idVendor)$usb(idProduct)"] < 8} {
296
344
                if {![regexp {ok:(\w{4}):(\w{4})} $report d usb(idVendor) usb(idProduct)]} {
297
 
                        Log "No target vendor/product ID found or given, can't continue. Aborting"
 
345
                        Log "No target vendor/product ID found or given, can't continue. Abort"
298
346
                        SafeExit
299
347
                }
300
348
        }
301
349
        # wait for any drivers to bind automatically
302
350
        after 1000
303
 
        Log "Now checking for bound driver ..."
 
351
        Log "Now check for bound driver ..."
304
352
        if {![file exists $devdir/$ifdir/driver]} {
305
353
                Log " no driver has bound to interface 0 yet"
306
354
                AddToList link_list $usb(idVendor):$usb(idProduct)
339
387
 
340
388
if [regexp {ok:$} $report] {
341
389
        # "NoDriverLoading" was set
342
 
        Log "Doing no driver checking or binding for this device"
 
390
        Log "No driver check or bind for this device"
343
391
}
344
392
 
345
393
# In newer kernels there is a switch to avoid the use of a device
346
394
# reset (e.g. from usb-storage) which would possibly switch back
347
395
# a mode-switching device to initial mode
348
396
if [regexp {ok:} $report] {
349
 
        Log "Checking for AVOID_RESET_QUIRK kernel attribute"
 
397
        Log "Check for AVOID_RESET_QUIRK kernel attribute"
350
398
        if [file exists $devdir/avoid_reset_quirk] {
351
399
                if [catch {exec echo "1" >$devdir/avoid_reset_quirk 2>/dev/null} err] {
352
400
                        Log " Error setting the attribute: $err"
358
406
        }
359
407
}
360
408
 
361
 
Log "\nAll done, exiting\n"
 
409
Log "\nAll done, exit\n"
362
410
SafeExit
363
411
 
364
412
}
370
418
global scsi
371
419
set counter 0
372
420
set sysdir $topdir
373
 
Log "Checking storage tree in sysfs ..."
 
421
Log "Check storage tree in sysfs ..."
374
422
while {$counter < 20} {
375
423
        Log " loop $counter/20"
376
424
        if {![file isdirectory $sysdir]} {
402
450
        return 0
403
451
}
404
452
 
405
 
Log "Reading SCSI values ..."
 
453
Log "Read SCSI values ..."
406
454
foreach attr {vendor model rev} {
407
455
        if [file exists $sysdir/$attr] {
408
456
                set rc [open $sysdir/$attr r]
466
514
        set matchstring [lindex $tokenList 1]
467
515
        set blankstring ""
468
516
        regsub -all {_} $matchstring { } blankstring
469
 
        Log "matching $match($id)"
470
 
        Log "  match string1 (exact):  $matchstring"
471
 
        Log "  match string2 (blanks): $blankstring"
 
517
        Log "match $match($id)"
 
518
        Log "  string1 (exact):  $matchstring"
 
519
        Log "  string2 (blanks): $blankstring"
472
520
        Log " device string: [set $match($id)]"
473
521
        if {!([string match *$matchstring* [set $match($id)]] || [string match *$blankstring* [set $match($id)]])} {
474
522
                return 0
496
544
set rc [open $configFile r]
497
545
while {![eof $rc]} {
498
546
        gets $rc line
 
547
        if [regexp {^#} [string trim $line]] {continue}
499
548
        if [regexp {DisableSwitching\s*=\s*([^\s]+)} $line d val] {
500
549
                if [regexp -nocase {1|yes|true} $val] {
501
550
                        set flags(noswitching) 1
506
555
                        set flags(logging) 1
507
556
                }
508
557
        }
 
558
        if [regexp {SetStorageDelay\s*=\s*([^\s]+)} $line d val] {
 
559
                if [regexp {\d+} $val] {
 
560
                        set flags(stordelay) $val
 
561
                }
 
562
        }
509
563
 
510
564
}
511
 
return "Using global config file: $configFile"
 
565
return "Use global config file: $configFile"
512
566
 
513
567
}
514
568
# end of proc {ParseGlobalConfig}
524
578
set config(targetProduct) ""
525
579
set config(targetClass) ""
526
580
set config(Configuration) ""
 
581
set config(noMBIMCheck) 0
527
582
set config(checkSuccess) 20
528
583
set loadDriver 1
529
584
 
554
609
if [regexp -line {^[^#]*?WaitBefore.*?=.*?([0-9]+).*?$} $configContent d config(waitBefore)] {
555
610
        Log "config: WaitBefore set to $config(waitBefore)"
556
611
}
 
612
if [regexp -line {^[^#]*?NoMBIMCheck.*?=.*?([0-9]+).*?$} $configContent d config(noMBIMCheck)] {
 
613
        Log "config: noMBIMCheck set to $config(noMBIMCheck)"
 
614
}
557
615
if [regexp -line {^[^#]*?NoDriverLoading.*?=.*?(1|yes|true).*?$} $configContent] {
558
616
        set loadDriver 0
559
617
        Log "config: NoDriverLoading is set to active"
582
640
 
583
641
proc ConfigGet {command config} {
584
642
 
585
 
global settings
 
643
global setup
586
644
 
587
645
switch $command {
588
646
 
589
647
        conflist {
590
648
                # Unpackaged configs first; sorting is essential for priority
591
 
                set configList [lsort -decreasing [glob -nocomplain $settings(dbdir_etc)/$config*]]
592
 
                set configList [concat $configList [lsort -decreasing [glob -nocomplain $settings(dbdir)/$config*]]]
593
 
                if [file exists $settings(dbdir)/configPack.tar.gz] {
594
 
                        Log "Found packed config collection $settings(dbdir)/configPack.tar.gz"
595
 
                        if [catch {set packedList [exec tar -tzf $settings(dbdir)/configPack.tar.gz 2>/dev/null]} err] {
 
649
                set configList [lsort -decreasing [glob -nocomplain $setup(dbdir_etc)/$config*]]
 
650
                set configList [concat $configList [lsort -decreasing [glob -nocomplain $setup(dbdir)/$config*]]]
 
651
                if [file exists $setup(dbdir)/configPack.tar.gz] {
 
652
                        Log "Found packed config collection $setup(dbdir)/configPack.tar.gz"
 
653
                        if [catch {set packedList [exec tar -tzf $setup(dbdir)/configPack.tar.gz 2>/dev/null]} err] {
596
654
                                Log "Error: problem opening config package; tar returned\n $err"
597
655
                                return {}
598
656
                        }
609
667
        conffile {
610
668
                if [regexp {^pack/} $config] {
611
669
                        set config [regsub {pack/} $config {}]
612
 
                        Log "Extracting config $config from collection $settings(dbdir)/configPack.tar.gz"
613
 
                        set configContent [exec tar -xzOf $settings(dbdir)/configPack.tar.gz $config 2>/dev/null]
 
670
                        Log "Extract config $config from collection $setup(dbdir)/configPack.tar.gz"
 
671
                        set configContent [exec tar -xzOf $setup(dbdir)/configPack.tar.gz $config 2>/dev/null]
614
672
                } else {
615
 
                        if [regexp [list $settings(dbdir_etc)] $config] {
616
 
                                Log "Using config file from override folder $settings(dbdir_etc)"
617
 
                                SysLog "usb_modeswitch: using overriding config file $config; make sure this is intended"
 
673
                        if [regexp [list $setup(dbdir_etc)] $config] {
 
674
                                Log "Use config file from override folder $setup(dbdir_etc)"
 
675
                                SysLog "usb_modeswitch: use overriding config file $config; make sure this is intended"
618
676
                                SysLog "usb_modeswitch: please report any new or corrected settings; otherwise, check for outdated files"
619
677
                        }
620
678
                        set rc [open $config r]
630
688
 
631
689
proc {Log} {msg} {
632
690
 
633
 
global flags device
 
691
global flags device loginit
 
692
 
634
693
if {$flags(logging) == 0} {return}
635
694
 
636
 
if {![info exists flags(wc)]} {
637
 
        if [catch {set flags(wc) [open /var/log/usb_modeswitch_$device w]} err] {
638
 
                if [catch {set flags(wc) [open /dev/console w]} err] {
639
 
                        set flags(wc) "error"
640
 
                        return
641
 
                } else {
642
 
                        puts $flags(wc) "Error opening log file ($err), redirect to console"
643
 
                }
 
695
if $flags(logwrite) {
 
696
        if [string length $loginit] {
 
697
                exec echo "\nUSB_ModeSwitch log from [clock format [clock seconds]]" >/var/log/usb_modeswitch_$device
 
698
                exec echo "$loginit" >>/var/log/usb_modeswitch_$device
 
699
                set loginit ""
644
700
        }
645
 
        puts $flags(wc) "\n\nUSB_ModeSwitch log from [clock format [clock seconds]]\n"
 
701
        exec echo $msg >>/var/log/usb_modeswitch_$device
 
702
} else {
 
703
        append loginit "\n$msg"
646
704
}
647
 
if {$flags(wc) == "error"} {return}
648
 
puts $flags(wc) $msg
649
705
 
650
706
}
651
707
# end of proc {Log}
652
708
 
653
709
 
654
 
# Closing the log file if open and exit
 
710
# Writing the log file and exit
655
711
proc {SafeExit} {} {
656
712
 
657
713
global flags
658
 
if [info exists flags(wc)] {
659
 
        catch {close $flags(wc)}
660
 
}
 
714
set $flags(logwrite) 1
 
715
Log ""
661
716
exit
662
717
 
663
718
}
669
724
 
670
725
proc {hasInterrupt} {ifDir} {
671
726
        if {[llength [glob -nocomplain $ifDir/ttyUSB*]] == 0} {
672
 
                Log "  no ttyUSB interface - skip checking endpoints"
 
727
                Log "  no ttyUSB interface - skip endpoint check"
673
728
                return 0
674
729
        }
675
730
        foreach epDir [glob -nocomplain $ifDir/ep_*] {
676
731
                set e [file tail $epDir]
677
 
                Log "  checking $e ..."
 
732
                Log "  check $e ..."
678
733
                if [file exists $epDir/type] {
679
734
                        set rc [open $epDir/type r]
680
735
                        set type [read $rc]
698
753
                set rawpath [file readlink $linkpath]
699
754
                set trimpath [regsub -all {\.\./} $rawpath {}]
700
755
                if [file isdirectory /sys/$trimpath] {
701
 
                        append loginit "\n Using path $path\n"
 
756
                        append loginit "\n Use path $path\n"
702
757
                        set path /$trimpath
703
758
                }
704
759
        }
707
762
if {![regexp {ttyUSB[0-9]+} $path myPort]} {
708
763
        if $flags(logging) {
709
764
                set device [clock clicks]
710
 
                Log "$loginit\nThis is not a ttyUSB port. Aborting"
 
765
                Log "$loginit\nThis is not a ttyUSB port. Abort"
711
766
        }
712
767
        return ""
713
768
}
716
771
Log "$loginit\nMy name is $myPort\n"
717
772
 
718
773
if {![regexp {(.*?[0-9]+)\.([0-9]+)/ttyUSB} /sys$path d ifRoot ifNum]} {
719
 
        Log "Could not find interface in path\n $path. Aborting"
 
774
        Log "Could not find interface in path\n $path. Abort"
720
775
        return ""
721
776
}
722
777
 
723
778
set ifDir $ifRoot.$ifNum
724
779
 
725
 
Log "Checking my endpoints ...\n in $ifDir"
 
780
Log "Check my endpoints ...\n in $ifDir"
726
781
if [hasInterrupt $ifDir] {
727
782
        Log "\n--> I am an interrupt port"
728
783
        set rightPort 1
736
791
# possible lower interfaces
737
792
 
738
793
if { $rightPort && ($ifNum > 0) } {
739
 
        Log "\nLooking for lower ports with interrupt endpoints"
 
794
        Log "\nLook for lower ports with interrupt endpoints"
740
795
        for {set i 0} {$i < $ifNum} {incr i} {
741
796
                set ifDir $ifRoot.$i
742
797
                Log " in ifDir $ifDir ..."
793
848
                Log "Can't do anymore without module loader; get \"modtools\"!"
794
849
                return
795
850
        }
796
 
        Log "\nTrying to load module \"$config(driverModule)\""
 
851
        Log "\nTry to load module \"$config(driverModule)\""
797
852
        if [catch {set result [exec $loader -v $config(driverModule)]} err] {
798
853
                Log " Running \"$loader $config(driverModule)\" gave an error:\n  $err"
799
854
        } else {
811
866
        incr i
812
867
}
813
868
if {$i < 50} {
814
 
        Log "Trying to add ID to driver \"$config(driverModule)\""
815
 
        SysLog "usb_modeswitch: adding device ID $vid:$pid to driver \"$config(driverModule)\""
 
869
        Log "Try to add ID to driver \"$config(driverModule)\""
 
870
        SysLog "usb_modeswitch: add device ID $vid:$pid to driver \"$config(driverModule)\""
816
871
        SysLog "usb_modeswitch: please report the device ID to the Linux USB developers!"
817
872
        if [catch {exec echo "$vid $pid ff" >$idfile} err] {
818
873
                Log " Error adding ID to driver:\n  $err"
821
876
        }
822
877
} else {
823
878
        Log " \"$idfile\" not found, check if kernel version is at least 2.6.27"
824
 
        Log "Falling back to \"usbserial\""
 
879
        Log "Fall back to \"usbserial\""
825
880
        set config(driverModule) usbserial
826
 
        Log "\nTrying to unload driver \"usbserial\""
 
881
        Log "\nTry to unload driver \"usbserial\""
827
882
        if [catch {exec $loader -r usbserial} err] {
828
883
                Log " Running \"$loader -r usbserial\" gave an error:\n  $err"
829
884
                Log "No more fallbacks"
830
885
                return
831
886
        }
832
887
        after 50
833
 
        Log "\nTrying to load driver \"usbserial\" with device IDs"
 
888
        Log "\nTry to load driver \"usbserial\" with device IDs"
834
889
        if [catch {set result [exec $loader -v usbserial vendor=0x$vid product=0x$pid]} err] {
835
890
                Log " Running \"$loader usbserial\" gave an error:\n  $err"
836
891
        } else {
923
978
}
924
979
# end of proc {RemoveFromBindList}
925
980
 
 
981
 
926
982
proc {CheckSuccess} {devdir} {
927
983
 
928
984
global config usb
929
 
set ifdir "[file tail $devdir]:1.0"
 
985
set ifdir [file tail [IfDir 0]]
930
986
 
931
987
if {[string length $config(targetClass)] || [string length $config(Configuration)]} {
932
988
        set config(targetVendor) $usb(idVendor)
933
989
        set config(targetProduct) $usb(idProduct)
934
990
}
935
 
Log "Checking success of mode switch for max. $config(checkSuccess) seconds ..."
 
991
Log "Check success of mode switch for max. $config(checkSuccess) seconds ..."
936
992
 
937
993
for {set i 1} {$i <= $config(checkSuccess)} {incr i} {
938
994
        after 1000
939
995
        if {![file isdirectory $devdir]} {
940
 
                Log " Waiting for device file system ($i sec.) ..."
 
996
                Log " Wait for device file system ($i sec.) ..."
941
997
                continue
942
998
        } else {
943
 
                Log " Reading attributes ..."
 
999
                Log " Read attributes ..."
944
1000
        }
 
1001
        set ifdir [IfDir 0]
 
1002
        if {$ifdir == ""} {continue}
 
1003
        set ifdir [file tail $ifdir]
945
1004
        if {![ReadUSBAttrs $devdir $ifdir]} {
946
1005
                Log " Essential attributes are missing, continue wait ..."
947
1006
                continue
950
1009
                if {![regexp $usb($ifdir/bInterfaceClass) $config(targetClass)]} {continue}
951
1010
        }
952
1011
        if [string length $config(Configuration)] {
953
 
                if {$usb(bConfigurationValue) != $config(Configuration} {continue}
 
1012
                if {$usb(bConfigurationValue) != $config(Configuration)} {continue}
954
1013
        }
955
1014
        if {![regexp $usb(idVendor) $config(targetVendor)]} {continue}
956
1015
        if {![regexp $usb(idProduct) $config(targetProduct)]} {continue}
965
1024
}
966
1025
# end of proc {CheckSuccess}
967
1026
 
 
1027
 
 
1028
proc {IfDir} {iface} {
 
1029
 
 
1030
global devdir
 
1031
set allfiles [glob -nocomplain $devdir/*]
 
1032
set files [glob -nocomplain $devdir/*.$iface]
 
1033
if {[llength $files] == 0} {
 
1034
        return ""
 
1035
}
 
1036
set ifdir [lindex $files 0]
 
1037
if {![file isdirectory $ifdir]} {
 
1038
        return ""
 
1039
}
 
1040
return $ifdir
 
1041
 
 
1042
}
 
1043
# end of proc {IfDir}
 
1044
 
 
1045
proc {IfClass} {iface} {
 
1046
 
 
1047
set ifdir [IfDir $iface]
 
1048
 
 
1049
if {![file exists $ifdir/bInterfaceClass]} {
 
1050
        return -1
 
1051
}
 
1052
set rc [open $ifdir/bInterfaceClass r]
 
1053
set c [read $rc]
 
1054
close $rc
 
1055
return [string trimleft [string trim $c] 0]
 
1056
 
 
1057
}
 
1058
# end of proc {IfClass}
 
1059
 
 
1060
 
968
1061
proc {SysLog} {msg} {
969
1062
 
970
1063
global flags
986
1079
}
987
1080
# end of proc {SysLog}
988
1081
 
 
1082
proc {SetStorageDelay} {secs} {
 
1083
 
 
1084
Log "Adjust delay for USB storage devices ..."
 
1085
set attrib /sys/module/usb_storage/parameters/delay_use
 
1086
if {![file exists $attrib]} {
 
1087
        Log "Error: could not find delay_use attribute"
 
1088
        return
 
1089
}
 
1090
if [catch {set ch [open $attrib r+]} err] {
 
1091
        Log "Error: could not access delay_use attribute: $err"
 
1092
        return
 
1093
}
 
1094
if {[read $ch] < $secs} {
 
1095
        seek $ch 0 start
 
1096
        puts -nonewline $ch $secs
 
1097
        Log " Delay set to $secs seconds\n"
 
1098
} else {
 
1099
        Log " Current value is higher than $secs. Leave it alone\n"
 
1100
}
 
1101
close $ch
 
1102
 
 
1103
}
 
1104
# end of proc {SetStorageDelay}
 
1105
 
 
1106
proc {CheckMBIM} {} {
 
1107
 
 
1108
set kversion [exec uname -r]
 
1109
if [file exists /lib/modules/$kversion/kernel/drivers/net/usb/cdc_mbim.ko] {return 1}
 
1110
if [file exists /sys/bus/usb/drivers/cdc_mbim] {return 1}
 
1111
return 0
 
1112
 
 
1113
}
989
1114
 
990
1115
 
991
1116
# The actual entry point