• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4
5"""Implementation of a USB HID mouse.
6
7Two classes are provided by this module. The MouseFeature class implements
8the core functionality of a HID mouse and can be included in any HID gadget.
9The MouseGadget class implements an example mouse gadget.
10"""
11
12import struct
13
14import hid_constants
15import hid_descriptors
16import hid_gadget
17import usb_constants
18
19
20class MouseFeature(hid_gadget.HidFeature):
21  """HID feature implementation for a mouse.
22
23  REPORT_DESC provides an example HID report descriptor for a device including
24  this functionality.
25  """
26
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)
58          )
59      )
60  )
61
62  def __init__(self):
63    super(MouseFeature, self).__init__()
64    self._buttons = 0
65
66  def ButtonDown(self, button):
67    self._buttons |= button
68    if self.IsConnected():
69      self.SendReport(self.EncodeInputReport())
70
71  def ButtonUp(self, button):
72    self._buttons &= ~button
73    if self.IsConnected():
74      self.SendReport(self.EncodeInputReport())
75
76  def Move(self, x_displacement, y_displacement):
77    if self.IsConnected():
78      self.SendReport(self.EncodeInputReport(x_displacement, y_displacement))
79
80  def EncodeInputReport(self, x_displacement=0, y_displacement=0):
81    return struct.pack('Bbb', self._buttons, x_displacement, y_displacement)
82
83  def GetInputReport(self):
84    """Construct an input report.
85
86    See Device Class Definition for Human Interface Devices (HID) Version 1.11
87    Appendix B.2.
88
89    Returns:
90      A packed input report.
91    """
92    return self.EncodeInputReport()
93
94
95class MouseGadget(hid_gadget.HidGadget):
96  """USB gadget implementation of a HID mouse."""
97
98  def __init__(self):
99    self._feature = MouseFeature()
100    super(MouseGadget, self).__init__(
101        report_desc=MouseFeature.REPORT_DESC,
102        features={0: self._feature},
103        packet_size=8,
104        interval_ms=1,
105        out_endpoint=False,
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')
111
112  def ButtonDown(self, button):
113    self._feature.ButtonDown(button)
114
115  def ButtonUp(self, button):
116    self._feature.ButtonUp(button)
117
118  def Move(self, x_displacement, y_displacement):
119    self._feature.Move(x_displacement, y_displacement)
120
121
122def RegisterHandlers():
123  """Registers web request handlers with the application server."""
124
125  from tornado import web
126
127  class WebConfigureHandler(web.RequestHandler):
128
129    def post(self):
130      gadget = MouseGadget()
131      server.SwitchGadget(gadget)
132
133  class WebClickHandler(web.RequestHandler):
134
135    def post(self):
136      BUTTONS = {
137          '1': hid_constants.Mouse.BUTTON_1,
138          '2': hid_constants.Mouse.BUTTON_2,
139          '3': hid_constants.Mouse.BUTTON_3,
140      }
141
142      button = BUTTONS[self.get_argument('button')]
143      server.gadget.ButtonDown(button)
144      server.gadget.ButtonUp(button)
145
146  class WebMoveHandler(web.RequestHandler):
147
148    def post(self):
149      x = int(self.get_argument('x'))
150      y = int(self.get_argument('y'))
151      server.gadget.Move(x, y)
152
153  import server
154  server.app.add_handlers('.*$', [
155      (r'/mouse/configure', WebConfigureHandler),
156      (r'/mouse/move', WebMoveHandler),
157      (r'/mouse/click', WebClickHandler),
158  ])
159