Skip to content

Instantly share code, notes, and snippets.

@amitu

amitu/adb.py

Last active Aug 29, 2015
Embed
What would you like to do?
#!/usr/bin/env python
from path import path
from struct import unpack
from collections import namedtuple
import stat, os
USBDeviceDescriptor = namedtuple(
"USBDeviceDescriptor", " ".join(
[
"bLength",
"bDescriptorType",
"bcdUSB",
"bDeviceClass",
"bDeviceSubClass",
"bDeviceProtocol",
"bMaxPacketSize0",
"idVendor",
"idProduct",
"bcdDevice",
"iManufacturer",
"iProduct",
"iSerialNumber",
"bNumConfigurations",
]
)
)
USBConfigDescriptor = namedtuple(
"USBConfigDescriptor", " ".join(
[
"bLength",
"bDescriptorType",
"wTotalLength",
"bNumInterfaces",
"bConfigurationValue",
"iConfiguration",
"bmAttributes",
"bMaxPower",
]
)
)
USBInterfaceDescriptor = namedtuple(
"USBInterfaceDescriptor", " ".join(
[
"bLength",
"bDescriptorType",
"bInterfaceNumber",
"bAlternateSetting",
"bNumEndpoints",
"bInterfaceClass",
"bInterfaceSubClass",
"bInterfaceProtocol",
"iInterface",
]
)
)
USBEndpointDescriptor = namedtuple(
"USBEndpointDescriptor", " ".join(
[
"bLength",
"bDescriptorType",
"bEndpointAddress",
"bmAttributes",
"wMaxPacketSize",
"bInterval",
# "bRefresh",
# "bSynchAddress",
]
)
)
USBDevFSCtrlTransfer = namedtuple(
"USBDevFSCtrlTransfer", " ".join(
[
"bRequestType",
"bRequest",
"wValue",
"wIndex",
"wLength",
"timeout",
]
)
)
# struct usbdevfs_ctrltransfer {
# 40 __u8 bRequestType;
# 41 __u8 bRequest;
# 42 __u16 wValue;
# 43 __u16 wIndex;
# 44 __u16 wLength;
# 45 __u32 timeout; /* in milliseconds */
# 46 void __user *data;
# 47 };
USBDeviceDescriptor_Format = "<BBHBBBBHHHBBBB"
USB_DT_DEVICE_SIZE = 18
USBConfigDescriptor_Format = "<BBHBBBBB"
USB_DT_CONFIG_SIZE = 9
USBInterfaceDescriptor_Format = "<BBBBBBBBB"
USB_DT_INTERFACE_SIZE = 9
USBEndpointDescriptor_Format = "<BBBBHB"
USB_DT_ENDPOINT_SIZE = 7
USB_DT_DEVICE = 1
USB_DT_CONFIG = 2
USB_DT_INTERFACE = 4
USB_DT_ENDPOINT = 5
USB_ENDPOINT_XFER_BULK = 2
USB_ENDPOINT_DIR_MASK = 0x80
VENDOR_IDS = """
#define VENDOR_ID_ACER 0x0502
#define VENDOR_ID_ALLWINNER 0x1F3A
#define VENDOR_ID_AMLOGIC 0x1b8e
#define VENDOR_ID_ANYDATA 0x16D5
#define VENDOR_ID_ARCHOS 0x0E79
#define VENDOR_ID_ASUS 0x0b05
#define VENDOR_ID_BYD 0x1D91
#define VENDOR_ID_COMPAL 0x04B7
#define VENDOR_ID_COMPALCOMM 0x1219
#define VENDOR_ID_DELL 0x413c
#define VENDOR_ID_ECS 0x03fc
#define VENDOR_ID_EMERGING_TECH 0x297F
#define VENDOR_ID_EMERSON 0x2207
#define VENDOR_ID_FOXCONN 0x0489
#define VENDOR_ID_FUJITSU 0x04C5
#define VENDOR_ID_FUNAI 0x0F1C
#define VENDOR_ID_GARMIN_ASUS 0x091E
#define VENDOR_ID_GIGABYTE 0x0414
#define VENDOR_ID_GIGASET 0x1E85
#define VENDOR_ID_GOOGLE 0x18d1
#define VENDOR_ID_HAIER 0x201E
#define VENDOR_ID_HARRIS 0x19A5
#define VENDOR_ID_HISENSE 0x109b
#define VENDOR_ID_HP 0x03f0
#define VENDOR_ID_HTC 0x0bb4
#define VENDOR_ID_HUAWEI 0x12D1
#define VENDOR_ID_INQ_MOBILE 0x2314
#define VENDOR_ID_INTEL 0x8087
#define VENDOR_ID_INTERMEC 0x067e
#define VENDOR_ID_IRIVER 0x2420
#define VENDOR_ID_K_TOUCH 0x24E3
#define VENDOR_ID_KT_TECH 0x2116
#define VENDOR_ID_KOBO 0x2237
#define VENDOR_ID_KYOCERA 0x0482
#define VENDOR_ID_LAB126 0x1949
#define VENDOR_ID_LENOVO 0x17EF
#define VENDOR_ID_LENOVOMOBILE 0x2006
#define VENDOR_ID_LGE 0x1004
#define VENDOR_ID_LUMIGON 0x25E3
#define VENDOR_ID_MOTOROLA 0x22b8
#define VENDOR_ID_MSI 0x0DB0
#define VENDOR_ID_MTK 0x0e8d
#define VENDOR_ID_NEC 0x0409
#define VENDOR_ID_NOOK 0x2080
#define VENDOR_ID_NVIDIA 0x0955
#define VENDOR_ID_OPPO 0x22D9
#define VENDOR_ID_OTGV 0x2257
#define VENDOR_ID_OUYA 0x2836
#define VENDOR_ID_PANTECH 0x10A9
#define VENDOR_ID_PEGATRON 0x1D4D
#define VENDOR_ID_PHILIPS 0x0471
#define VENDOR_ID_PMC 0x04DA
#define VENDOR_ID_POSITIVO 0x1662
#define VENDOR_ID_PRESTIGIO 0x29e4
#define VENDOR_ID_QISDA 0x1D45
#define VENDOR_ID_QUALCOMM 0x05c6
#define VENDOR_ID_QUANTA 0x0408
#define VENDOR_ID_ROCKCHIP 0x2207
#define VENDOR_ID_SAMSUNG 0x04e8
#define VENDOR_ID_SHARP 0x04dd
#define VENDOR_ID_SK_TELESYS 0x1F53
#define VENDOR_ID_SONY 0x054C
#define VENDOR_ID_SONY_ERICSSON 0x0FCE
#define VENDOR_ID_T_AND_A 0x1BBB
#define VENDOR_ID_TECHFAITH 0x1d09
#define VENDOR_ID_TELEEPOCH 0x2340
#define VENDOR_ID_TI 0x0451
#define VENDOR_ID_TOSHIBA 0x0930
#define VENDOR_ID_UNOWHY 0x2A49
#define VENDOR_ID_VIZIO 0xE040
#define VENDOR_ID_WACOM 0x0531
#define VENDOR_ID_XIAOMI 0x2717
#define VENDOR_ID_YOTADEVICES 0x2916
#define VENDOR_ID_YULONG_COOLPAD 0x1EBF
#define VENDOR_ID_ZTE 0x19D2
""".split("\n")
VENDOR_IDS = dict(
(
eval(line.split()[2]),
line.split()[1][len("VENDOR_ID_"):]
)
for line in VENDOR_IDS if line.strip()
)
# print VENDOR_IDS
ADB_CLASS = 0xff
ADB_SUBCLASS = 0x42
ADB_PROTOCOL = 0x1
DEVICES = []
class USB(object):
def __init__(self, fname, ep_in, ep_out, zero_mask):
self.fname = fname
self.ep_in = ep_in
self.ep_out = ep_out
self.zero_mask = zero_mask
self.writeable = True
self.mark = 0
def __str__(self):
return "USB: %s" % self.__dict__
def register_device(
devname, devpath, ep_in, ep_out, interface, serial_index, zero
):
# print "register_device", devname, devpath, ep_in, ep_out, interface, zero
usb = USB(devname, ep_in, ep_out, zero)
usb.mark = 1
DEVICES.append(usb)
# print usb
try:
usb.desc = os.open(devname, os.O_RDWR)
except Exception, e:
print e, devname, "os.O_RDWR"
try:
usb.desc = os.open(devname, os.O_RDONLY)
except Exception, e:
print e, devname, "os.O_RDONLY"
return
else:
usb.writeable = False
if not serial_index:
return
def devices():
for dev_dir in path("/dev/bus/usb").dirs():
# print dev_dir
for dev_file in dev_dir.glob("*"):
# print dev_file
zero_mask = 0
try:
fd = dev_file.open("r")
except IOError, e:
print e
continue
usb_info = fd.read()
fd.close()
# print "usb_info.len =", len(usb_info)
if len(usb_info) < USB_DT_DEVICE_SIZE + USB_DT_CONFIG_SIZE:
print "desclength %s is too small" % len(usb_info)
continue
device = USBDeviceDescriptor._make(
unpack(
USBDeviceDescriptor_Format,
usb_info[:USB_DT_DEVICE_SIZE]
)
)
# devname = dev_dir.basename() + "/" + dev_file.basename()
devname = dev_file.abspath()
# print device
if (
(device.bLength != USB_DT_DEVICE_SIZE) or
(device.bDescriptorType != USB_DT_DEVICE)
):
print "bad device"
continue
vid = device.idVendor
if vid not in VENDOR_IDS:
# print "VID: %s not in VENDOR_IDS" % vid
continue
# print "VID valid", VENDOR_IDS[vid]
# pid = device.idProduct
# print "[ %s is V:%04x P:%04x ]" % (devname, vid, pid)
usb_info = usb_info[USB_DT_DEVICE_SIZE:]
config = USBConfigDescriptor._make(
unpack(
USBConfigDescriptor_Format,
usb_info[:USB_DT_CONFIG_SIZE]
)
)
# print config
if (
(config.bLength != USB_DT_CONFIG_SIZE) or
(config.bDescriptorType != USB_DT_CONFIG)
):
print "usb_config_descriptor not found"
continue
usb_info = usb_info[USB_DT_CONFIG_SIZE:]
while usb_info:
length = ord(usb_info[0])
type_ = ord(usb_info[1])
if type_ != USB_DT_INTERFACE:
usb_info = usb_info[length:]
continue
interface = USBInterfaceDescriptor._make(
unpack(
USBInterfaceDescriptor_Format,
usb_info[:USB_DT_INTERFACE_SIZE]
)
)
usb_info = usb_info[length:]
if length != USB_DT_INTERFACE_SIZE:
print "interface descriptor has wrong size"
break
# print interface
# print (
# "bInterfaceClass: %d, bInterfaceSubClass: %d, " +
# "bInterfaceProtocol: %d, bNumEndpoints: %d\n"
# ) % (
# interface.bInterfaceClass, interface.bInterfaceSubClass,
# interface.bInterfaceProtocol, interface.bNumEndpoints
# )
if (
not (
interface.bNumEndpoints == 2 and
vid in VENDOR_IDS and
interface.bInterfaceClass == ADB_CLASS and
interface.bInterfaceSubClass == ADB_SUBCLASS and
interface.bInterfaceProtocol == ADB_PROTOCOL
)
):
# print "invalid interface"
continue
print "valid adb", VENDOR_IDS[vid], len(usb_info)
ep1 = USBEndpointDescriptor._make(
unpack(
USBEndpointDescriptor_Format,
usb_info[:USB_DT_ENDPOINT_SIZE]
)
)
usb_info = usb_info[USB_DT_ENDPOINT_SIZE:]
ep2 = USBEndpointDescriptor._make(
unpack(
USBEndpointDescriptor_Format,
usb_info[:USB_DT_ENDPOINT_SIZE]
)
)
usb_info = usb_info[USB_DT_INTERFACE_SIZE:]
if (
usb_info or
ep1.bLength != USB_DT_ENDPOINT_SIZE or
ep1.bDescriptorType != USB_DT_ENDPOINT or
ep2.bLength != USB_DT_ENDPOINT_SIZE or
ep2.bDescriptorType != USB_DT_ENDPOINT
):
print "endpoints not found"
break
if (
ep1.bmAttributes != USB_ENDPOINT_XFER_BULK or
ep2.bmAttributes != USB_ENDPOINT_XFER_BULK
):
print "bulk endpoints not found"
continue
if interface.bInterfaceProtocol == 0x01:
zero_mask = ep1.wMaxPacketSize - 1
if ep1.bEndpointAddress & USB_ENDPOINT_DIR_MASK:
local_ep_in = ep1.bEndpointAddress
local_ep_out = ep2.bEndpointAddress
else:
local_ep_in = ep2.bEndpointAddress
local_ep_out = ep1.bEndpointAddress
st = dev_file.stat()
if stat.S_ISCHR(st.st_mode):
pathbuf = "/sys/dev/char/%s:%s" % (
os.major(st.st_rdev), os.minor(st.st_rdev)
)
# print pathbuf, open(pathbuf + "/product").read(),
print "serial =", open(pathbuf + "/serial").read(),
link = os.readlink(pathbuf)
if link:
devpath = "usb:%s" % link.split("/")[-1]
else:
print dev_file, "is not a char device"
continue
register_device(
devname, devpath, local_ep_in, local_ep_out, interface,
device.iSerialNumber, zero_mask
)
def shell(cmd, device):
pass
def main():
devices()
# shell("ls", DEVICES[0])
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.