forked from RevengeOS/android_development
-
Notifications
You must be signed in to change notification settings - Fork 0
/
usb-reset-by-serial.py
executable file
·172 lines (137 loc) · 4.44 KB
/
usb-reset-by-serial.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#!/usr/bin/python
#
# Copyright (C) 2016 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Reset a USB device (presumbly android phone) by serial number.
Given a serial number, inspects connected USB devices and issues USB
reset to the one that matches. Python version written by Than
McIntosh, based on a perl version from Chris Ferris. Intended for use
on linux.
"""
import fcntl
import getopt
import locale
import os
import re
import shlex
import subprocess
import sys
# Serial number of device that we want to reset
flag_serial = None
# Debugging verbosity level (0 -> no output)
flag_debug = 0
USBDEVFS_RESET = ord("U") << (4*2) | 20
def verbose(level, msg):
"""Print debug trace output of verbosity level is >= value in 'level'."""
if level <= flag_debug:
sys.stderr.write(msg + "\n")
def increment_verbosity():
"""Increment debug trace level by 1."""
global flag_debug
flag_debug += 1
def issue_ioctl_to_device(device):
"""Issue USB reset ioctl to device."""
try:
fd = open(device, "wb")
except IOError as e:
error("unable to open device %s: "
"%s" % (device, e.strerror))
verbose(1, "issuing USBDEVFS_RESET ioctl() to %s" % device)
fcntl.ioctl(fd, USBDEVFS_RESET, 0)
fd.close()
# perform default locale setup if needed
def set_default_lang_locale():
if "LANG" not in os.environ:
warning("no env setting for LANG -- using default values")
os.environ["LANG"] = "en_US.UTF-8"
os.environ["LANGUAGE"] = "en_US:"
def warning(msg):
"""Issue a warning to stderr."""
sys.stderr.write("warning: " + msg + "\n")
def error(msg):
"""Issue an error to stderr, then exit."""
sys.stderr.write("error: " + msg + "\n")
exit(1)
# invoke command, returning array of lines read from it
def docmdlines(cmd, nf=None):
"""Run a command via subprocess, returning output as an array of lines."""
verbose(2, "+ docmdlines executing: %s" % cmd)
args = shlex.split(cmd)
mypipe = subprocess.Popen(args, stdout=subprocess.PIPE)
encoding = locale.getdefaultlocale()[1]
pout, perr = mypipe.communicate()
if mypipe.returncode != 0:
if perr:
decoded_err = perr.decode(encoding)
warning(decoded_err)
if nf:
return None
error("command failed (rc=%d): cmd was %s" % (mypipe.returncode, args))
decoded = pout.decode(encoding)
lines = decoded.strip().split("\n")
return lines
def perform():
"""Main driver routine."""
lines = docmdlines("usb-devices")
dmatch = re.compile(r"^\s*T:\s*Bus\s*=\s*(\d+)\s+.*\s+Dev#=\s*(\d+).*$")
smatch = re.compile(r"^\s*S:\s*SerialNumber=(.*)$")
device = None
found = False
for line in lines:
m = dmatch.match(line)
if m:
p1 = int(m.group(1))
p2 = int(m.group(2))
device = "/dev/bus/usb/%03d/%03d" % (p1, p2)
verbose(1, "setting device: %s" % device)
continue
m = smatch.match(line)
if m:
ser = m.group(1)
if ser == flag_serial:
verbose(0, "matched serial %s to device "
"%s, invoking reset" % (ser, device))
issue_ioctl_to_device(device)
found = True
break
if not found:
error("unable to locate device with serial number %s" % flag_serial)
def usage(msgarg):
"""Print usage and exit."""
if msgarg:
sys.stderr.write("error: %s\n" % msgarg)
print """\
usage: %s [options] XXYYZZ
where XXYYZZ is the serial number of a connected Android device.
options:
-d increase debug msg verbosity level
""" % os.path.basename(sys.argv[0])
sys.exit(1)
def parse_args():
"""Command line argument parsing."""
global flag_serial
try:
optlist, args = getopt.getopt(sys.argv[1:], "d")
except getopt.GetoptError as err:
# unrecognized option
usage(str(err))
if not args or len(args) != 1:
usage("supply a single device serial number as argument")
flag_serial = args[0]
for opt, _ in optlist:
if opt == "-d":
increment_verbosity()
set_default_lang_locale()
parse_args()
perform()