Home | History | Annotate | Download | only in usb_gadget
      1 #!/usr/bin/python
      2 # Copyright 2014 The Chromium Authors. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 import unittest
      7 
      8 import mock
      9 
     10 import gadget
     11 import usb_constants
     12 import usb_descriptors
     13 
     14 
     15 device_desc = usb_descriptors.DeviceDescriptor(
     16     idVendor=0x18D1,   # Google Inc.
     17     idProduct=0xFF00,
     18     bcdUSB=0x0200,
     19     iManufacturer=1,
     20     iProduct=2,
     21     iSerialNumber=3,
     22     bNumConfigurations=1,
     23     bcdDevice=0x0100)
     24 
     25 fs_config_desc = usb_descriptors.ConfigurationDescriptor(
     26     bmAttributes=0xC0,
     27     MaxPower=50)
     28 
     29 fs_interface_desc = usb_descriptors.InterfaceDescriptor(
     30     bInterfaceNumber=0
     31 )
     32 fs_config_desc.AddInterface(fs_interface_desc)
     33 
     34 fs_bulk_in_endpoint_desc = usb_descriptors.EndpointDescriptor(
     35     bEndpointAddress=0x01,
     36     bmAttributes=usb_constants.TransferType.BULK,
     37     wMaxPacketSize=64,
     38     bInterval=0
     39 )
     40 fs_interface_desc.AddEndpoint(fs_bulk_in_endpoint_desc)
     41 
     42 fs_bulk_out_endpoint_desc = usb_descriptors.EndpointDescriptor(
     43     bEndpointAddress=0x81,
     44     bmAttributes=usb_constants.TransferType.BULK,
     45     wMaxPacketSize=64,
     46     bInterval=0
     47 )
     48 fs_interface_desc.AddEndpoint(fs_bulk_out_endpoint_desc)
     49 
     50 fs_alt_interface_desc = usb_descriptors.InterfaceDescriptor(
     51     bInterfaceNumber=0,
     52     bAlternateSetting=1
     53 )
     54 fs_config_desc.AddInterface(fs_alt_interface_desc)
     55 
     56 fs_interrupt_in_endpoint_desc = usb_descriptors.EndpointDescriptor(
     57     bEndpointAddress=0x01,
     58     bmAttributes=usb_constants.TransferType.INTERRUPT,
     59     wMaxPacketSize=64,
     60     bInterval=1
     61 )
     62 fs_alt_interface_desc.AddEndpoint(fs_interrupt_in_endpoint_desc)
     63 
     64 fs_interrupt_out_endpoint_desc = usb_descriptors.EndpointDescriptor(
     65     bEndpointAddress=0x81,
     66     bmAttributes=usb_constants.TransferType.INTERRUPT,
     67     wMaxPacketSize=64,
     68     bInterval=1
     69 )
     70 fs_alt_interface_desc.AddEndpoint(fs_interrupt_out_endpoint_desc)
     71 
     72 hs_config_desc = usb_descriptors.ConfigurationDescriptor(
     73     bmAttributes=0xC0,
     74     MaxPower=50)
     75 
     76 hs_interface_desc = usb_descriptors.InterfaceDescriptor(
     77     bInterfaceNumber=0
     78 )
     79 hs_config_desc.AddInterface(hs_interface_desc)
     80 
     81 hs_bulk_in_endpoint_desc = usb_descriptors.EndpointDescriptor(
     82     bEndpointAddress=0x01,
     83     bmAttributes=usb_constants.TransferType.BULK,
     84     wMaxPacketSize=512,
     85     bInterval=0
     86 )
     87 hs_interface_desc.AddEndpoint(hs_bulk_in_endpoint_desc)
     88 
     89 hs_bulk_out_endpoint_desc = usb_descriptors.EndpointDescriptor(
     90     bEndpointAddress=0x81,
     91     bmAttributes=usb_constants.TransferType.BULK,
     92     wMaxPacketSize=512,
     93     bInterval=0
     94 )
     95 hs_interface_desc.AddEndpoint(hs_bulk_out_endpoint_desc)
     96 
     97 hs_alt_interface_desc = usb_descriptors.InterfaceDescriptor(
     98     bInterfaceNumber=0,
     99     bAlternateSetting=1
    100 )
    101 hs_config_desc.AddInterface(hs_alt_interface_desc)
    102 
    103 hs_interrupt_in_endpoint_desc = usb_descriptors.EndpointDescriptor(
    104     bEndpointAddress=0x01,
    105     bmAttributes=usb_constants.TransferType.INTERRUPT,
    106     wMaxPacketSize=256,
    107     bInterval=1
    108 )
    109 hs_alt_interface_desc.AddEndpoint(hs_interrupt_in_endpoint_desc)
    110 
    111 hs_interrupt_out_endpoint_desc = usb_descriptors.EndpointDescriptor(
    112     bEndpointAddress=0x81,
    113     bmAttributes=usb_constants.TransferType.INTERRUPT,
    114     wMaxPacketSize=256,
    115     bInterval=1
    116 )
    117 hs_alt_interface_desc.AddEndpoint(hs_interrupt_out_endpoint_desc)
    118 
    119 
    120 class GadgetTest(unittest.TestCase):
    121 
    122   def test_get_descriptors(self):
    123     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    124     self.assertEquals(g.GetDeviceDescriptor(), device_desc)
    125     self.assertEquals(g.GetFullSpeedConfigurationDescriptor(), fs_config_desc)
    126     self.assertEquals(g.GetHighSpeedConfigurationDescriptor(), hs_config_desc)
    127     with self.assertRaisesRegexp(RuntimeError, 'not connected'):
    128       g.GetConfigurationDescriptor()
    129 
    130   def test_connect_full_speed(self):
    131     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    132     g.Connected(mock.Mock(), usb_constants.Speed.FULL)
    133     self.assertTrue(g.IsConnected())
    134     self.assertEquals(g.GetSpeed(), usb_constants.Speed.FULL)
    135     self.assertEquals(g.GetConfigurationDescriptor(), fs_config_desc)
    136     g.Disconnected()
    137     self.assertFalse(g.IsConnected())
    138 
    139   def test_connect_high_speed(self):
    140     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    141     g.Connected(mock.Mock(), usb_constants.Speed.HIGH)
    142     self.assertTrue(g.IsConnected())
    143     self.assertEquals(g.GetSpeed(), usb_constants.Speed.HIGH)
    144     self.assertEquals(g.GetConfigurationDescriptor(), hs_config_desc)
    145     g.Disconnected()
    146     self.assertFalse(g.IsConnected())
    147 
    148   def test_string_index_out_of_range(self):
    149     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    150     with self.assertRaisesRegexp(ValueError, 'index out of range'):
    151       g.AddStringDescriptor(0, 'Hello world!')
    152 
    153   def test_language_id_out_of_range(self):
    154     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    155     with self.assertRaisesRegexp(ValueError, 'language code out of range'):
    156       g.AddStringDescriptor(1, 'Hello world!', lang=-1)
    157 
    158   def test_get_languages(self):
    159     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    160     g.AddStringDescriptor(1, 'Hello world!')
    161     desc = g.ControlRead(0x80, 6, 0x0300, 0, 255)
    162     self.assertEquals(desc, '\x04\x03\x09\x04')
    163 
    164   def test_get_string_descriptor(self):
    165     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    166     g.AddStringDescriptor(1, 'Hello world!')
    167     desc = g.ControlRead(0x80, 6, 0x0301, 0x0409, 255)
    168     self.assertEquals(desc, '\x1A\x03H\0e\0l\0l\0o\0 \0w\0o\0r\0l\0d\0!\0')
    169 
    170   def test_get_missing_string_descriptor(self):
    171     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    172     g.AddStringDescriptor(1, 'Hello world!')
    173     desc = g.ControlRead(0x80, 6, 0x0302, 0x0409, 255)
    174     self.assertEquals(desc, None)
    175 
    176   def test_get_missing_string_language(self):
    177     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    178     g.AddStringDescriptor(1, 'Hello world!')
    179     desc = g.ControlRead(0x80, 6, 0x0301, 0x040C, 255)
    180     self.assertEquals(desc, None)
    181 
    182   def test_class_and_vendor_transfers(self):
    183     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    184     self.assertIsNone(g.ControlRead(0xA0, 0, 0, 0, 0))
    185     self.assertIsNone(g.ControlRead(0xC0, 0, 0, 0, 0))
    186     self.assertIsNone(g.ControlWrite(0x20, 0, 0, 0, ''))
    187     self.assertIsNone(g.ControlWrite(0x40, 0, 0, 0, ''))
    188 
    189   def test_set_configuration(self):
    190     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    191     chip = mock.Mock()
    192     g.Connected(chip, usb_constants.Speed.HIGH)
    193     g.ControlWrite(0, 9, 1, 0, 0)
    194     chip.StartEndpoint.assert_has_calls([
    195         mock.call(hs_bulk_in_endpoint_desc),
    196         mock.call(hs_bulk_out_endpoint_desc)
    197     ])
    198 
    199   def test_set_configuration_zero(self):
    200     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    201     chip = mock.Mock()
    202     g.Connected(chip, usb_constants.Speed.HIGH)
    203     g.ControlWrite(0, 9, 1, 0, 0)
    204     chip.StartEndpoint.reset_mock()
    205     g.ControlWrite(0, 9, 0, 0, 0)
    206     chip.StopEndpoint.assert_has_calls([
    207         mock.call(0x01),
    208         mock.call(0x81)
    209     ])
    210 
    211   def test_set_bad_configuration(self):
    212     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    213     g.Connected(mock.Mock(), usb_constants.Speed.HIGH)
    214     self.assertIsNone(g.ControlWrite(0, 9, 2, 0, 0))
    215 
    216   def test_set_interface(self):
    217     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    218     chip = mock.Mock()
    219     g.Connected(chip, usb_constants.Speed.HIGH)
    220     self.assertTrue(g.ControlWrite(0, 9, 1, 0, 0))
    221     chip.reset_mock()
    222     self.assertTrue(g.ControlWrite(1, 11, 1, 0, 0))
    223     chip.StopEndpoint.assert_has_calls([
    224         mock.call(0x01),
    225         mock.call(0x81)
    226     ])
    227     chip.StartEndpoint.assert_has_calls([
    228         mock.call(hs_interrupt_in_endpoint_desc),
    229         mock.call(hs_interrupt_out_endpoint_desc)
    230     ])
    231     chip.reset_mock()
    232     self.assertTrue(g.ControlWrite(1, 11, 0, 0, 0))
    233     chip.StopEndpoint.assert_has_calls([
    234         mock.call(0x01),
    235         mock.call(0x81)
    236     ])
    237     chip.StartEndpoint.assert_has_calls([
    238         mock.call(hs_bulk_in_endpoint_desc),
    239         mock.call(hs_bulk_out_endpoint_desc)
    240     ])
    241 
    242   def test_set_bad_interface(self):
    243     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    244     g.Connected(mock.Mock(), usb_constants.Speed.HIGH)
    245     self.assertTrue(g.ControlWrite(0, 9, 1, 0, 0))
    246     self.assertIsNone(g.ControlWrite(1, 11, 0, 1, 0))
    247 
    248   def test_send_packet(self):
    249     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    250     chip = mock.Mock()
    251     g.Connected(chip, usb_constants.Speed.HIGH)
    252     g.SendPacket(0x81, 'Hello world!')
    253     chip.SendPacket.assert_called_once_with(0x81, 'Hello world!')
    254 
    255   def test_send_packet_disconnected(self):
    256     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    257     with self.assertRaisesRegexp(RuntimeError, 'not connected'):
    258       g.SendPacket(0x81, 'Hello world!')
    259     g.Connected(mock.Mock(), usb_constants.Speed.HIGH)
    260     g.SendPacket(0x81, 'Hello world!')
    261     g.Disconnected()
    262     with self.assertRaisesRegexp(RuntimeError, 'not connected'):
    263       g.SendPacket(0x81, 'Hello world!')
    264 
    265   def test_send_invalid_endpoint(self):
    266     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    267     chip = mock.Mock()
    268     g.Connected(chip, usb_constants.Speed.HIGH)
    269     with self.assertRaisesRegexp(ValueError, 'non-input endpoint'):
    270       g.SendPacket(0x01, 'Hello world!')
    271 
    272   def test_receive_packet(self):
    273     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    274     self.assertIsNone(g.ReceivePacket(0x01, 'Hello world!'))
    275 
    276   def test_halt_endpoint(self):
    277     g = gadget.Gadget(device_desc, fs_config_desc, hs_config_desc)
    278     chip = mock.Mock()
    279     g.Connected(chip, usb_constants.Speed.HIGH)
    280     g.HaltEndpoint(0x01)
    281     chip.HaltEndpoint.assert_called_once_with(0x01)
    282 
    283 
    284 if __name__ == '__main__':
    285   unittest.main()
    286