# 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.

"""Implementation of a USB HID keyboard.

Two classes are provided by this module. The KeyboardFeature class implements
the core functionality of a HID keyboard and can be included in any HID gadget.
The KeyboardGadget class implements an example keyboard gadget.
"""

import struct

import hid_constants
import hid_descriptors
import hid_gadget
import usb_constants


class KeyboardFeature(hid_gadget.HidFeature):
  """HID feature implementation for a keyboard.

  REPORT_DESC provides an example HID report descriptor for a device including
  this functionality.
  """

  REPORT_DESC = hid_descriptors.ReportDescriptor(
      hid_descriptors.UsagePage(0x01),  # Generic Desktop
      hid_descriptors.Usage(0x06),  # Keyboard
      hid_descriptors.Collection(
          hid_constants.CollectionType.APPLICATION,
          hid_descriptors.UsagePage(0x07),  # Key Codes
          hid_descriptors.UsageMinimum(224),
          hid_descriptors.UsageMaximum(231),
          hid_descriptors.LogicalMinimum(0, force_length=1),
          hid_descriptors.LogicalMaximum(1),
          hid_descriptors.ReportSize(1),
          hid_descriptors.ReportCount(8),
          hid_descriptors.Input(hid_descriptors.Data,
                                hid_descriptors.Variable,
                                hid_descriptors.Absolute),
          hid_descriptors.ReportCount(1),
          hid_descriptors.ReportSize(8),
          hid_descriptors.Input(hid_descriptors.Constant),
          hid_descriptors.ReportCount(5),
          hid_descriptors.ReportSize(1),
          hid_descriptors.UsagePage(0x08),  # LEDs
          hid_descriptors.UsageMinimum(1),
          hid_descriptors.UsageMaximum(5),
          hid_descriptors.Output(hid_descriptors.Data,
                                 hid_descriptors.Variable,
                                 hid_descriptors.Absolute),
          hid_descriptors.ReportCount(1),
          hid_descriptors.ReportSize(3),
          hid_descriptors.Output(hid_descriptors.Constant),
          hid_descriptors.ReportCount(6),
          hid_descriptors.ReportSize(8),
          hid_descriptors.LogicalMinimum(0, force_length=1),
          hid_descriptors.LogicalMaximum(101),
          hid_descriptors.UsagePage(0x07),  # Key Codes
          hid_descriptors.UsageMinimum(0, force_length=1),
          hid_descriptors.UsageMaximum(101),
          hid_descriptors.Input(hid_descriptors.Data, hid_descriptors.Array)
      )
  )

  def __init__(self):
    super(KeyboardFeature, self).__init__()
    self._modifiers = 0
    self._keys = [0, 0, 0, 0, 0, 0]
    self._leds = 0

  def ModifierDown(self, modifier):
    self._modifiers |= modifier
    if self.IsConnected():
      self.SendReport(self.GetInputReport())

  def ModifierUp(self, modifier):
    self._modifiers &= ~modifier
    if self.IsConnected():
      self.SendReport(self.GetInputReport())

  def KeyDown(self, keycode):
    free = self._keys.index(0)
    self._keys[free] = keycode
    if self.IsConnected():
      self.SendReport(self.GetInputReport())

  def KeyUp(self, keycode):
    free = self._keys.index(keycode)
    self._keys[free] = 0
    if self.IsConnected():
      self.SendReport(self.GetInputReport())

  def GetInputReport(self):
    """Construct an input report.

    See Device Class Definition for Human Interface Devices (HID) Version 1.11
    Appendix B.1.

    Returns:
      A packed input report.
    """
    return struct.pack('BBBBBBBB', self._modifiers, 0, *self._keys)

  def GetOutputReport(self):
    """Construct an output report.

    See Device Class Definition for Human Interface Devices (HID) Version 1.11
    Appendix B.1.

    Returns:
      A packed input report.
    """
    return struct.pack('B', self._leds)

  def SetOutputReport(self, data):
    """Handle an output report.

    See Device Class Definition for Human Interface Devices (HID) Version 1.11
    Appendix B.1.

    Args:
      data: Report data.

    Returns:
      True on success, None to stall the pipe.
    """
    if len(data) >= 1:
      self._leds, = struct.unpack('B', data)
    return True


class KeyboardGadget(hid_gadget.HidGadget):
  """USB gadget implementation of a HID keyboard."""

  def __init__(self, vendor_id=0x18D1, product_id=0xFF02):
    self._feature = KeyboardFeature()
    super(KeyboardGadget, self).__init__(
        report_desc=KeyboardFeature.REPORT_DESC,
        features={0: self._feature},
        packet_size=8,
        interval_ms=1,
        out_endpoint=True,
        vendor_id=usb_constants.VendorID.GOOGLE,
        product_id=usb_constants.ProductID.GOOGLE_KEYBOARD_GADGET,
        device_version=0x0100)
    self.AddStringDescriptor(1, 'Google Inc.')
    self.AddStringDescriptor(2, 'Keyboard Gadget')

  def ModifierDown(self, modifier):
    self._feature.ModifierDown(modifier)

  def ModifierUp(self, modifier):
    self._feature.ModifierUp(modifier)

  def KeyDown(self, keycode):
    self._feature.KeyDown(keycode)

  def KeyUp(self, keycode):
    self._feature.KeyUp(keycode)


def RegisterHandlers():
  """Registers web request handlers with the application server."""

  from tornado import web

  class WebConfigureHandler(web.RequestHandler):

    def post(self):
      server.SwitchGadget(KeyboardGadget())

  class WebTypeHandler(web.RequestHandler):

    def post(self):
      string = self.get_argument('string')
      for char in string:
        if char in hid_constants.KEY_CODES:
          code = hid_constants.KEY_CODES[char]
          server.gadget.KeyDown(code)
          server.gadget.KeyUp(code)
        elif char in hid_constants.SHIFT_KEY_CODES:
          code = hid_constants.SHIFT_KEY_CODES[char]
          server.gadget.ModifierDown(hid_constants.ModifierKey.L_SHIFT)
          server.gadget.KeyDown(code)
          server.gadget.KeyUp(code)
          server.gadget.ModifierUp(hid_constants.ModifierKey.L_SHIFT)

  class WebPressHandler(web.RequestHandler):

    def post(self):
      code = hid_constants.KEY_CODES[self.get_argument('key')]
      server.gadget.KeyDown(code)
      server.gadget.KeyUp(code)

  import server
  server.app.add_handlers('.*$', [
      (r'/keyboard/configure', WebConfigureHandler),
      (r'/keyboard/type', WebTypeHandler),
      (r'/keyboard/press', WebPressHandler),
  ])
