1# Copyright (c) 2010, Tomohiro Kusumi
2# All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are met:
6#
7# 1. Redistributions of source code must retain the above copyright notice, this
8#    list of conditions and the following disclaimer.
9# 2. Redistributions in binary form must reproduce the above copyright notice,
10#    this list of conditions and the following disclaimer in the documentation
11#    and/or other materials provided with the distribution.
12#
13# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
24from .. import extension
25from .. import filebytes
26from .. import util
27
28byte_to_int = util.byte_to_int
29le_to_int = util.le_to_int
30
31USB_DT_DEVICE    = 0x01
32USB_DT_CONFIG    = 0x02
33USB_DT_STRING    = 0x03
34USB_DT_INTERFACE = 0x04
35USB_DT_ENDPOINT  = 0x05
36
37TYPE_CLASS       = (0x01 << 5)
38HID_DT_HID       = (TYPE_CLASS | 0x01)
39HID_DT_REPORT    = (TYPE_CLASS | 0x02)
40HID_DT_PHYSICAL  = (TYPE_CLASS | 0x03)
41
42def get_text(co, fo, args):
43    b = fo.read(args[-1], util.KiB)
44    if not b:
45        extension.fail("Empty buffer")
46    desc = []
47    while b:
48        if len(b) <= 2:
49            extension.fail("Invalid descriptor: " + btoh(b))
50        bLength = filebytes.ord(b[0:1])
51        bDescriptorType = filebytes.ord(b[1:2])
52        if bLength <= 0:
53            extension.fail("Invalid bLength: {0}".format(bLength))
54        d = b[:bLength]
55        if len(d) != bLength or len(d) <= 2:
56            extension.fail("Invalid bLength: {0}".format(bLength))
57        desc.append(d)
58        b = b[bLength:]
59    l = []
60    for b in desc:
61        bLength = filebytes.ord(b[0:1])
62        bDescriptorType = filebytes.ord(b[1:2])
63        if bDescriptorType == USB_DT_DEVICE:
64            l.extend(__get_device_descriptor(b))
65        elif bDescriptorType == USB_DT_CONFIG:
66            l.extend(__get_config_descriptor(b))
67        elif bDescriptorType == USB_DT_STRING:
68            l.extend(__get_string_descriptor(b))
69        elif bDescriptorType == USB_DT_INTERFACE:
70            l.extend(__get_interface_descriptor(b))
71        elif bDescriptorType == USB_DT_ENDPOINT:
72            l.extend(__get_endpoint_descriptor(b))
73        elif bDescriptorType == HID_DT_HID:
74            l.extend(__get_hid_descriptor(b))
75        else:
76            l.extend(__get_unknown_descriptor(b))
77        l.append('')
78    return l
79
80def btoh(b):
81    return ''.join(["\\x{0:02X}".format(x) for x in filebytes.iter_ords(b)])
82
83def __get_device_descriptor(b):
84    assert len(b) == 18, "Invalid device descriptor: " + btoh(b)
85    l = []
86    l.append("device descriptor " + util.get_size_repr(len(b)))
87    l.append("    bLength            = {0}".format(byte_to_int(b[0:1])))
88    l.append("    bDescriptorType    = {0}".format(byte_to_int(b[1:2])))
89    l.append("    bcdUSB             = 0x{0:04X}".format(le_to_int(b[2:4])))
90    l.append("    bDeviceClass       = {0}".format(byte_to_int(b[4:5])))
91    l.append("    bDeviceSubClass    = {0}".format(byte_to_int(b[5:6])))
92    l.append("    bDeviceProtocol    = {0}".format(byte_to_int(b[6:7])))
93    l.append("    bMaxPacketSize0    = {0}".format(byte_to_int(b[7:8])))
94    l.append("    idVendor           = 0x{0:04X}".format(le_to_int(b[8:10])))
95    l.append("    idProduct          = 0x{0:04X}".format(le_to_int(b[10:12])))
96    l.append("    bcdDevice          = 0x{0:04X}".format(le_to_int(b[12:14])))
97    l.append("    iManufacturer      = {0}".format(byte_to_int(b[14:15])))
98    l.append("    iProduct           = {0}".format(byte_to_int(b[15:16])))
99    l.append("    iSerialNumber      = {0}".format(byte_to_int(b[16:17])))
100    l.append("    bNumConfigurations = {0}".format(byte_to_int(b[17:18])))
101    return l
102
103def __get_config_descriptor(b):
104    assert len(b) == 9, "Invalid config descriptor: " + btoh(b)
105    l = []
106    l.append("config descriptor " + util.get_size_repr(len(b)))
107    l.append("    bLength             = {0}".format(byte_to_int(b[0:1])))
108    l.append("    bDescriptorType     = {0}".format(byte_to_int(b[1:2])))
109    l.append("    wTotalLength        = {0}".format(le_to_int(b[2:4])))
110    l.append("    bNumInterfaces      = {0}".format(byte_to_int(b[4:5])))
111    l.append("    bConfigurationValue = {0}".format(byte_to_int(b[5:6])))
112    l.append("    iConfiguration      = {0}".format(byte_to_int(b[6:7])))
113    l.append("    bmAttributes        = 0x{0:02X}".format(byte_to_int(b[7:8])))
114    l.append("    bMaxPower           = {0}".format(byte_to_int(b[8:9])))
115    return l
116
117def __get_string_descriptor(b):
118    assert len(b) > 2, "Invalid string descriptor: " + btoh(b)
119    l = []
120    l.append("string descriptor " + util.get_size_repr(len(b)))
121    l.append("    bLength         = {0}".format(byte_to_int(b[0:1])))
122    l.append("    bDescriptorType = {0}".format(byte_to_int(b[1:2])))
123    return l
124
125def __get_interface_descriptor(b):
126    assert len(b) == 9, "Invalid interface descriptor: " + btoh(b)
127    l = []
128    l.append("interface descriptor " + util.get_size_repr(len(b)))
129    l.append("    bLength            = {0}".format(byte_to_int(b[0:1])))
130    l.append("    bDescriptorType    = {0}".format(byte_to_int(b[1:2])))
131    l.append("    bInterfaceNumber   = {0}".format(byte_to_int(b[2:3])))
132    l.append("    bAlternateSetting  = {0}".format(byte_to_int(b[3:4])))
133    l.append("    bNumEndpoints      = {0}".format(byte_to_int(b[4:5])))
134    l.append("    bInterfaceClass    = {0}".format(byte_to_int(b[5:6])))
135    l.append("    bInterfaceSubClass = {0}".format(byte_to_int(b[6:7])))
136    l.append("    bInterfaceProtocol = {0}".format(byte_to_int(b[7:8])))
137    l.append("    iInterface         = {0}".format(byte_to_int(b[8:9])))
138    return l
139
140def __get_endpoint_descriptor(b):
141    assert len(b) == 7, "Invalid endpoint descriptor: " + btoh(b)
142    l = []
143    l.append("endpoint descriptor " + util.get_size_repr(len(b)))
144    l.append("    bLength          = {0}".format(byte_to_int(b[0:1])))
145    l.append("    bDescriptorType  = {0}".format(byte_to_int(b[1:2])))
146    l.append("    bEndpointAddress = 0x{0:02X}".format(byte_to_int(b[2:3])))
147    l.append("    bmAttributes     = 0x{0:02X}".format(byte_to_int(b[3:4])))
148    l.append("    wMaxPacketSize   = 0x{0:04X}".format(le_to_int(b[4:6])))
149    l.append("    bInterval        = {0}".format(byte_to_int(b[6:7])))
150    return l
151
152def __get_hid_descriptor(b):
153    assert len(b) > 2, "Invalid hid descriptor: " + btoh(b)
154    l = []
155    l.append("hid descriptor " + util.get_size_repr(len(b)))
156    l.append("    bLength         = {0}".format(byte_to_int(b[0:1])))
157    l.append("    bDescriptorType = {0}".format(byte_to_int(b[1:2])))
158    return l
159
160def __get_unknown_descriptor(b):
161    assert len(b) > 2, "Invalid descriptor: " + btoh(b)
162    l = []
163    l.append("unknown descriptor " + util.get_size_repr(len(b)))
164    l.append("    bLength         = {0}".format(byte_to_int(b[0:1])))
165    l.append("    bDescriptorType = {0}".format(byte_to_int(b[1:2])))
166    return l
167