Commit 5b676c4e authored by reillyg@chromium.org's avatar reillyg@chromium.org

[usb_gadget p00] Classes for encoding USB descriptors.

The descriptor module defines a generic infrastructure for declaring USB
descriptor formats. Features such as fixed and computed descriptor
fields are intended to make it as easy as possible to construct a
well-formed descriptor.

BUG=396682
R=rockot@chromium.org,rpaquay@chromium.org

Review URL: https://codereview.chromium.org/409883008

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@285076 0039d316-1c4b-4281-b951-d872f2087c98
parent b8249aa9
reillyg@chromium.org
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""USB constant definitions.
"""
class DescriptorType(object):
"""Descriptor Types.
See Universal Serial Bus Specification Revision 2.0 Table 9-5.
"""
DEVICE = 1
CONFIGURATION = 2
STRING = 3
INTERFACE = 4
ENDPOINT = 5
QUALIFIER = 6
OTHER_SPEED_CONFIGURATION = 7
class DeviceClass(object):
"""Class code.
See http://www.usb.org/developers/defined_class.
"""
PER_INTERFACE = 0
AUDIO = 1
COMM = 2
HID = 3
PHYSICAL = 5
STILL_IMAGE = 6
PRINTER = 7
MASS_STORAGE = 8
HUB = 9
CDC_DATA = 10
CSCID = 11
CONTENT_SEC = 13
VIDEO = 14
VENDOR = 0xFF
class DeviceSubClass(object):
"""Subclass code.
See http://www.usb.org/developers/defined_class.
"""
PER_INTERFACE = 0
VENDOR = 0xFF
class DeviceProtocol(object):
"""Protocol code.
See http://www.usb.org/developers/defined_class.
"""
PER_INTERFACE = 0
VENDOR = 0xFF
class InterfaceClass(object):
"""Class code.
See http://www.usb.org/developers/defined_class.
"""
VENDOR = 0xFF
class InterfaceSubClass(object):
"""Subclass code.
See http://www.usb.org/developers/defined_class.
"""
VENDOR = 0xFF
class InterfaceProtocol(object):
"""Protocol code.
See http://www.usb.org/developers/defined_class.
"""
VENDOR = 0xFF
class TransferType(object):
"""Transfer Type.
See http://www.usb.org/developers/defined_class.
"""
MASK = 3
CONTROL = 0
ISOCHRONOUS = 1
BULK = 2
INTERRUPT = 3
class Dir(object):
"""Data transfer direction.
See Universal Serial Bus Specification Revision 2.0 Table 9-2.
"""
OUT = 0
IN = 0x80
class Type(object):
"""Request Type.
See Universal Serial Bus Specification Revision 2.0 Table 9-2.
"""
MASK = 0x60
STANDARD = 0x00
CLASS = 0x20
VENDOR = 0x40
RESERVED = 0x60
class Recipient(object):
"""Request Recipient.
See Universal Serial Bus Specification Revision 2.0 Table 9-2.
"""
MASK = 0x1f
DEVICE = 0
INTERFACE = 1
ENDPOINT = 2
OTHER = 3
class Request(object):
"""Standard Request Codes.
See Universal Serial Bus Specification Revision 2.0 Table 9-4.
"""
GET_STATUS = 0x00
CLEAR_FEATURE = 0x01
SET_FEATURE = 0x03
SET_ADDRESS = 0x05
GET_DESCRIPTOR = 0x06
SET_DESCRIPTOR = 0x07
GET_CONFIGURATION = 0x08
SET_CONFIGURATION = 0x09
GET_INTERFACE = 0x0A
SET_INTERFACE = 0x0B
SYNCH_FRAME = 0x0C
SET_SEL = 0x30
SET_ISOCH_DELAY = 0x31
class Speed(object):
UNKNOWN = 0
LOW = 1
FULL = 2
HIGH = 3
WIRELESS = 4
SUPER = 5
class VendorID(object):
GOOGLE = 0x18D1
This diff is collapsed.
#!/usr/bin/python
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import unittest
import usb_descriptors
class DescriptorWithField(usb_descriptors.Descriptor):
pass
DescriptorWithField.AddField('bField', 'B')
class DescriptorWithDefault(usb_descriptors.Descriptor):
pass
DescriptorWithDefault.AddField('bDefault', 'B', default=42)
class DescriptorWithFixed(usb_descriptors.Descriptor):
pass
DescriptorWithFixed.AddFixedField('bFixed', 'B', 42)
class DescriptorWithComputed(usb_descriptors.Descriptor):
@property
def foo(self):
return 42
DescriptorWithComputed.AddComputedField('bComputed', 'B', 'foo')
class DescriptorWithDescriptors(usb_descriptors.DescriptorContainer):
pass
DescriptorWithDescriptors.AddField('bType', 'B')
class DescriptorTest(unittest.TestCase):
def test_default(self):
obj = DescriptorWithDefault()
self.assertEquals(obj.bDefault, 42)
def test_change_default(self):
obj = DescriptorWithDefault()
obj.bDefault = 1
self.assertEquals(obj.bDefault, 1)
def test_override_default(self):
obj = DescriptorWithDefault(bDefault=56)
self.assertEquals(obj.bDefault, 56)
def test_fixed(self):
obj = DescriptorWithFixed()
self.assertEquals(obj.bFixed, 42)
def test_set_fixed(self):
with self.assertRaises(RuntimeError):
DescriptorWithFixed(bFixed=1)
def test_modify_fixed(self):
obj = DescriptorWithFixed()
with self.assertRaises(RuntimeError):
obj.bFixed = 1
def test_computed(self):
obj = DescriptorWithComputed()
self.assertEquals(obj.bComputed, 42)
def test_set_computed(self):
with self.assertRaises(RuntimeError):
DescriptorWithComputed(bComputed=1)
def test_modify_computed(self):
obj = DescriptorWithComputed()
with self.assertRaises(RuntimeError):
obj.bComputed = 1
def test_unexpected(self):
with self.assertRaisesRegexp(TypeError, 'Unexpected'):
DescriptorWithField(bUnexpected=1)
def test_missing(self):
with self.assertRaisesRegexp(TypeError, 'Missing'):
DescriptorWithField()
def test_size(self):
obj = DescriptorWithField(bField=42)
self.assertEquals(obj.struct_size, 1)
self.assertEquals(obj.total_size, 1)
def test_encode(self):
obj = DescriptorWithField(bField=0xff)
self.assertEquals(obj.Encode(), '\xff')
def test_string(self):
obj = DescriptorWithField(bField=42)
string = str(obj)
self.assertIn('bField', string)
self.assertIn('42', string)
def test_container(self):
parent = DescriptorWithDescriptors(bType=0)
child1 = DescriptorWithField(bField=1)
parent.Add(child1)
child2 = DescriptorWithField(bField=2)
parent.Add(child2)
self.assertEquals(parent.total_size, 3)
self.assertEquals(parent.Encode(), '\x00\x01\x02')
string = str(parent)
self.assertIn('bType', string)
self.assertIn('bField', string)
class TestUsbDescriptors(unittest.TestCase):
def test_device_descriptor(self):
device_desc = usb_descriptors.DeviceDescriptor(
idVendor=0xDEAD,
idProduct=0xBEEF,
bcdDevice=0x0100,
bNumConfigurations=1)
self.assertEquals(
device_desc.Encode(),
'\x12\x01\x00\x02\x00\x00\x00\x40\xAD\xDE\xEF\xBE\x00\x01\x00\x00\x00'
'\x01')
def test_unique_interfaces(self):
interface_desc1 = usb_descriptors.InterfaceDescriptor(bInterfaceNumber=1)
interface_desc2 = usb_descriptors.InterfaceDescriptor(bInterfaceNumber=1,
bAlternateSetting=1)
interface_desc3 = usb_descriptors.InterfaceDescriptor(bInterfaceNumber=1)
configuration_desc = usb_descriptors.ConfigurationDescriptor(
bmAttributes=0xC0,
MaxPower=100)
configuration_desc.AddInterface(interface_desc1)
configuration_desc.AddInterface(interface_desc2)
with self.assertRaisesRegexp(RuntimeError, r'Interface 1 \(alternate 0\)'):
configuration_desc.AddInterface(interface_desc3)
def test_unique_endpoints(self):
endpoint_desc1 = usb_descriptors.EndpointDescriptor(
bEndpointAddress=0x01,
bmAttributes=0x02,
wMaxPacketSize=64,
bInterval=1)
endpoint_desc2 = usb_descriptors.EndpointDescriptor(
bEndpointAddress=0x81,
bmAttributes=0x02,
wMaxPacketSize=64,
bInterval=1)
endpoint_desc3 = usb_descriptors.EndpointDescriptor(
bEndpointAddress=0x01,
bmAttributes=0x01,
wMaxPacketSize=32,
bInterval=10)
interface_desc = usb_descriptors.InterfaceDescriptor(bInterfaceNumber=1)
interface_desc.AddEndpoint(endpoint_desc1)
interface_desc.AddEndpoint(endpoint_desc2)
with self.assertRaisesRegexp(RuntimeError, 'Endpoint 0x01 already defined'):
interface_desc.AddEndpoint(endpoint_desc3)
def test_configuration_descriptor(self):
endpoint_desc = usb_descriptors.EndpointDescriptor(
bEndpointAddress=0x01,
bmAttributes=0x02,
wMaxPacketSize=64,
bInterval=1)
encoded_endpoint = '\x07\x05\x01\x02\x40\x00\x01'
self.assertEquals(endpoint_desc.Encode(), encoded_endpoint)
interface_desc = usb_descriptors.InterfaceDescriptor(bInterfaceNumber=1)
interface_desc.AddEndpoint(endpoint_desc)
self.assertEquals([endpoint_desc], interface_desc.GetEndpoints())
encoded_interface = ('\x09\x04\x01\x00\x01\xFF\xFF\xFF\x00' +
encoded_endpoint)
self.assertEquals(interface_desc.Encode(), encoded_interface)
configuration_desc = usb_descriptors.ConfigurationDescriptor(
bmAttributes=0xC0,
MaxPower=100)
configuration_desc.AddInterface(interface_desc)
self.assertEquals([interface_desc], configuration_desc.GetInterfaces())
encoded_configuration = ('\x09\x02\x19\x00\x01\x01\x00\xC0\x64' +
encoded_interface)
self.assertEquals(configuration_desc.Encode(), encoded_configuration)
def test_encode_hid_descriptor(self):
hid_desc = usb_descriptors.HidDescriptor()
hid_desc.AddDescriptor(0x22, 0x80)
hid_desc.AddDescriptor(0x23, 0x60)
encoded_desc = '\x0C\x21\x11\x01\x00\x02\x22\x80\x00\x23\x60\x00'
self.assertEquals(hid_desc.Encode(), encoded_desc)
def test_print_hid_descriptor(self):
hid_desc = usb_descriptors.HidDescriptor()
hid_desc.AddDescriptor(0x22, 0x80)
hid_desc.AddDescriptor(0x23, 0x60)
string = str(hid_desc)
self.assertIn('0x22', string)
self.assertIn('0x23', string)
if __name__ == '__main__':
unittest.main()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment