| #!/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 mock | 
 |  | 
 | import hid_constants | 
 | import hid_descriptors | 
 | import hid_gadget | 
 | import usb_constants | 
 |  | 
 |  | 
 | report_desc = hid_descriptors.ReportDescriptor( | 
 |     hid_descriptors.UsagePage(0xFF00),  # Vendor Defined | 
 |     hid_descriptors.Usage(0x00), | 
 |     hid_descriptors.Collection( | 
 |         hid_constants.CollectionType.APPLICATION, | 
 |         hid_descriptors.LogicalMinimum(0, force_length=1), | 
 |         hid_descriptors.LogicalMaximum(255, force_length=2), | 
 |         hid_descriptors.ReportSize(8), | 
 |         hid_descriptors.ReportCount(8), | 
 |         hid_descriptors.Input(hid_descriptors.Data, | 
 |                               hid_descriptors.Variable, | 
 |                               hid_descriptors.Absolute, | 
 |                               hid_descriptors.BufferedBytes), | 
 |         hid_descriptors.Output(hid_descriptors.Data, | 
 |                                hid_descriptors.Variable, | 
 |                                hid_descriptors.Absolute, | 
 |                                hid_descriptors.BufferedBytes), | 
 |         hid_descriptors.Feature(hid_descriptors.Data, | 
 |                                 hid_descriptors.Variable, | 
 |                                 hid_descriptors.Absolute, | 
 |                                 hid_descriptors.BufferedBytes) | 
 |     ) | 
 | ) | 
 |  | 
 | combo_report_desc = hid_descriptors.ReportDescriptor( | 
 |     hid_descriptors.ReportID(1), | 
 |     report_desc, | 
 |     hid_descriptors.ReportID(2), | 
 |     report_desc | 
 | ) | 
 |  | 
 |  | 
 | class HidGadgetTest(unittest.TestCase): | 
 |  | 
 |   def test_bad_intervals(self): | 
 |     with self.assertRaisesRegexp(ValueError, 'Full speed'): | 
 |       hid_gadget.HidGadget(report_desc, features={}, interval_ms=50000, | 
 |                            vendor_id=0, product_id=0) | 
 |     with self.assertRaisesRegexp(ValueError, 'High speed'): | 
 |       hid_gadget.HidGadget(report_desc, features={}, interval_ms=5000, | 
 |                            vendor_id=0, product_id=0) | 
 |  | 
 |   def test_get_string_descriptor(self): | 
 |     g = hid_gadget.HidGadget(report_desc=report_desc, features={}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     g.AddStringDescriptor(2, 'HID Gadget') | 
 |     desc = g.ControlRead(0x80, 6, 0x0302, 0x0409, 255) | 
 |     self.assertEquals(desc, '\x16\x03H\0I\0D\0 \0G\0a\0d\0g\0e\0t\0') | 
 |  | 
 |   def test_get_report_descriptor(self): | 
 |     g = hid_gadget.HidGadget(report_desc=report_desc, features={}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     desc = g.ControlRead(0x81, 6, 0x2200, 0, 63) | 
 |     self.assertEquals(desc, report_desc) | 
 |  | 
 |   def test_set_idle(self): | 
 |     g = hid_gadget.HidGadget(report_desc=report_desc, features={}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     self.assertTrue(g.ControlWrite(0x21, 0x0A, 0, 0, '')) | 
 |  | 
 |   def test_class_wrong_target(self): | 
 |     g = hid_gadget.HidGadget(report_desc=report_desc, features={}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     self.assertIsNone(g.ControlRead(0xA0, 0, 0, 0, 0))  # Device | 
 |     self.assertIsNone(g.ControlRead(0xA1, 0, 0, 1, 0))  # Interface 1 | 
 |     self.assertIsNone(g.ControlWrite(0x20, 0, 0, 0, ''))  # Device | 
 |     self.assertIsNone(g.ControlWrite(0x21, 0, 0, 1, ''))  # Interface 1 | 
 |  | 
 |   def test_send_report_zero(self): | 
 |     g = hid_gadget.HidGadget(report_desc=report_desc, features={}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     g.SendReport(0, 'Hello world!') | 
 |     chip.SendPacket.assert_called_once_with(0x81, 'Hello world!') | 
 |  | 
 |   def test_send_multiple_reports(self): | 
 |     g = hid_gadget.HidGadget(report_desc=report_desc, features={}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     g.SendReport(1, 'Hello!') | 
 |     g.SendReport(2, 'World!') | 
 |     chip.SendPacket.assert_has_calls([ | 
 |         mock.call(0x81, '\x01Hello!'), | 
 |         mock.call(0x81, '\x02World!'), | 
 |     ]) | 
 |  | 
 |  | 
 | class TestFeature(hid_gadget.HidFeature): | 
 |  | 
 |   def SetInputReport(self, data): | 
 |     self.input_report = data | 
 |     return True | 
 |  | 
 |   def SetOutputReport(self, data): | 
 |     self.output_report = data | 
 |     return True | 
 |  | 
 |   def SetFeatureReport(self, data): | 
 |     self.feature_report = data | 
 |     return True | 
 |  | 
 |   def GetInputReport(self): | 
 |     return 'Input report.' | 
 |  | 
 |   def GetOutputReport(self): | 
 |     return 'Output report.' | 
 |  | 
 |   def GetFeatureReport(self): | 
 |     return 'Feature report.' | 
 |  | 
 |  | 
 | class HidFeatureTest(unittest.TestCase): | 
 |  | 
 |   def test_disconnected(self): | 
 |     feature = TestFeature() | 
 |     with self.assertRaisesRegexp(RuntimeError, 'not connected'): | 
 |       feature.SendReport('Hello world!') | 
 |  | 
 |   def test_send_report(self): | 
 |     feature = TestFeature() | 
 |     g = hid_gadget.HidGadget(report_desc, features={1: feature}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     feature.SendReport('Hello world!') | 
 |     chip.SendPacket.assert_called_once_with(0x81, '\x01Hello world!') | 
 |     g.Disconnected() | 
 |  | 
 |   def test_get_bad_report(self): | 
 |     feature = TestFeature() | 
 |     g = hid_gadget.HidGadget(report_desc, features={1: feature}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     self.assertIsNone(g.ControlRead(0xA1, 1, 0x0102, 0, 8)) | 
 |  | 
 |   def test_set_bad_report(self): | 
 |     feature = TestFeature() | 
 |     g = hid_gadget.HidGadget(report_desc, features={1: feature}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     self.assertIsNone(g.ControlWrite(0x21, 0x09, 0x0102, 0, 'Hello!')) | 
 |  | 
 |   def test_get_input_report(self): | 
 |     feature = TestFeature() | 
 |     g = hid_gadget.HidGadget(report_desc, features={1: feature}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     report = g.ControlRead(0xA1, 1, 0x0101, 0, 8) | 
 |     self.assertEquals(report, 'Input re') | 
 |  | 
 |   def test_set_input_report(self): | 
 |     feature = TestFeature() | 
 |     g = hid_gadget.HidGadget(report_desc, features={1: feature}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     self.assertTrue(g.ControlWrite(0x21, 0x09, 0x0101, 0, 'Hello!')) | 
 |     self.assertEquals(feature.input_report, 'Hello!') | 
 |  | 
 |   def test_get_output_report(self): | 
 |     feature = TestFeature() | 
 |     g = hid_gadget.HidGadget(report_desc, features={1: feature}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     report = g.ControlRead(0xA1, 1, 0x0201, 0, 8) | 
 |     self.assertEquals(report, 'Output r') | 
 |  | 
 |   def test_set_output_report(self): | 
 |     feature = TestFeature() | 
 |     g = hid_gadget.HidGadget(report_desc, features={1: feature}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     self.assertTrue(g.ControlWrite(0x21, 0x09, 0x0201, 0, 'Hello!')) | 
 |     self.assertEquals(feature.output_report, 'Hello!') | 
 |  | 
 |   def test_receive_interrupt(self): | 
 |     feature = TestFeature() | 
 |     g = hid_gadget.HidGadget(report_desc, features={1: feature}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     g.SetConfiguration(1) | 
 |     g.ReceivePacket(0x01, '\x01Hello!') | 
 |     self.assertFalse(chip.HaltEndpoint.called) | 
 |     self.assertEquals(feature.output_report, 'Hello!') | 
 |  | 
 |   def test_receive_interrupt_report_zero(self): | 
 |     feature = TestFeature() | 
 |     g = hid_gadget.HidGadget(report_desc, features={0: feature}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     g.SetConfiguration(1) | 
 |     g.ReceivePacket(0x01, 'Hello!') | 
 |     self.assertFalse(chip.HaltEndpoint.called) | 
 |     self.assertEquals(feature.output_report, 'Hello!') | 
 |  | 
 |   def test_receive_bad_interrupt(self): | 
 |     feature = TestFeature() | 
 |     g = hid_gadget.HidGadget(report_desc, features={1: feature}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     g.SetConfiguration(1) | 
 |     g.ReceivePacket(0x01, '\x00Hello!') | 
 |     chip.HaltEndpoint.assert_called_once_with(0x01) | 
 |  | 
 |   def test_get_feature_report(self): | 
 |     feature = TestFeature() | 
 |     g = hid_gadget.HidGadget(report_desc, features={1: feature}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     report = g.ControlRead(0xA1, 1, 0x0301, 0, 8) | 
 |     self.assertEquals(report, 'Feature ') | 
 |  | 
 |   def test_set_feature_report(self): | 
 |     feature = TestFeature() | 
 |     g = hid_gadget.HidGadget(report_desc, features={1: feature}, | 
 |                              vendor_id=0, product_id=0) | 
 |     chip = mock.Mock() | 
 |     g.Connected(chip, usb_constants.Speed.HIGH) | 
 |     self.assertTrue(g.ControlWrite(0x21, 0x09, 0x0301, 0, 'Hello!')) | 
 |     self.assertEquals(feature.feature_report, 'Hello!') | 
 |  | 
 |  | 
 | if __name__ == '__main__': | 
 |   unittest.main() |