1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 """Implementation of a USB HID mouse.
7 Two classes are provided by this module. The MouseFeature class implements
8 the core functionality of a HID mouse and can be included in any HID gadget.
9 The MouseGadget class implements an example mouse gadget.
15 import hid_descriptors
20 class MouseFeature(hid_gadget.HidFeature):
21 """HID feature implementation for a mouse.
23 REPORT_DESC provides an example HID report descriptor for a device including
27 REPORT_DESC = hid_descriptors.ReportDescriptor(
28 hid_descriptors.UsagePage(0x01), # Generic Desktop
29 hid_descriptors.Usage(0x02), # Mouse
30 hid_descriptors.Collection(
31 hid_constants.CollectionType.APPLICATION,
32 hid_descriptors.Usage(0x01), # Pointer
33 hid_descriptors.Collection(
34 hid_constants.CollectionType.PHYSICAL,
35 hid_descriptors.UsagePage(0x09), # Buttons
36 hid_descriptors.UsageMinimum(1),
37 hid_descriptors.UsageMaximum(3),
38 hid_descriptors.LogicalMinimum(0, force_length=1),
39 hid_descriptors.LogicalMaximum(1),
40 hid_descriptors.ReportCount(3),
41 hid_descriptors.ReportSize(1),
42 hid_descriptors.Input(hid_descriptors.Data,
43 hid_descriptors.Variable,
44 hid_descriptors.Absolute),
45 hid_descriptors.ReportCount(1),
46 hid_descriptors.ReportSize(5),
47 hid_descriptors.Input(hid_descriptors.Constant),
48 hid_descriptors.UsagePage(0x01), # Generic Desktop
49 hid_descriptors.Usage(0x30), # X
50 hid_descriptors.Usage(0x31), # Y
51 hid_descriptors.LogicalMinimum(0x81), # -127
52 hid_descriptors.LogicalMaximum(127),
53 hid_descriptors.ReportSize(8),
54 hid_descriptors.ReportCount(2),
55 hid_descriptors.Input(hid_descriptors.Data,
56 hid_descriptors.Variable,
57 hid_descriptors.Relative)
63 super(MouseFeature, self).__init__()
66 def ButtonDown(self, button):
67 self._buttons |= button
68 if self.IsConnected():
69 self.SendReport(self.EncodeInputReport())
71 def ButtonUp(self, button):
72 self._buttons &= ~button
73 if self.IsConnected():
74 self.SendReport(self.EncodeInputReport())
76 def Move(self, x_displacement, y_displacement):
77 if self.IsConnected():
78 self.SendReport(self.EncodeInputReport(x_displacement, y_displacement))
80 def EncodeInputReport(self, x_displacement=0, y_displacement=0):
81 return struct.pack('Bbb', self._buttons, x_displacement, y_displacement)
83 def GetInputReport(self):
84 """Construct an input report.
86 See Device Class Definition for Human Interface Devices (HID) Version 1.11
90 A packed input report.
92 return self.EncodeInputReport()
95 class MouseGadget(hid_gadget.HidGadget):
96 """USB gadget implementation of a HID mouse."""
99 self._feature = MouseFeature()
100 super(MouseGadget, self).__init__(
101 report_desc=MouseFeature.REPORT_DESC,
102 features={0: self._feature},
106 vendor_id=usb_constants.VendorID.GOOGLE,
107 product_id=usb_constants.ProductID.GOOGLE_MOUSE_GADGET,
108 device_version=0x0100)
109 self.AddStringDescriptor(1, 'Google Inc.')
110 self.AddStringDescriptor(2, 'Mouse Gadget')
112 def ButtonDown(self, button):
113 self._feature.ButtonDown(button)
115 def ButtonUp(self, button):
116 self._feature.ButtonUp(button)
118 def Move(self, x_displacement, y_displacement):
119 self._feature.Move(x_displacement, y_displacement)
122 def RegisterHandlers():
123 """Registers web request handlers with the application server."""
125 from tornado import web
127 class WebConfigureHandler(web.RequestHandler):
130 gadget = MouseGadget()
131 server.SwitchGadget(gadget)
133 class WebClickHandler(web.RequestHandler):
137 '1': hid_constants.Mouse.BUTTON_1,
138 '2': hid_constants.Mouse.BUTTON_2,
139 '3': hid_constants.Mouse.BUTTON_3,
142 button = BUTTONS[self.get_argument('button')]
143 server.gadget.ButtonDown(button)
144 server.gadget.ButtonUp(button)
146 class WebMoveHandler(web.RequestHandler):
149 x = int(self.get_argument('x'))
150 y = int(self.get_argument('y'))
151 server.gadget.Move(x, y)
154 server.app.add_handlers('.*$', [
155 (r'/mouse/configure', WebConfigureHandler),
156 (r'/mouse/move', WebMoveHandler),
157 (r'/mouse/click', WebClickHandler),