chromium/services/device/public/mojom/hid.mojom

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO(crbug.com/40142029): We have to mark this mojom as [Stable] before
// lacros begins the process of launching.

module device.mojom;

[Stable, Extensible]
enum HidBusType {
  kHIDBusTypeUSB = 0,
  kHIDBusTypeBluetooth = 1,
  [MinVersion=1] kHIDBusTypeUnknown = 2,
};

// Usage pages.
const uint16 kPageUndefined = 0x00;
const uint16 kPageGenericDesktop = 0x01;
const uint16 kPageSimulation = 0x02;
const uint16 kPageVirtualReality = 0x03;
const uint16 kPageSport = 0x04;
const uint16 kPageGame = 0x05;
const uint16 kPageGenericDevice = 0x06;
const uint16 kPageKeyboard = 0x07;
const uint16 kPageLed = 0x08;
const uint16 kPageButton = 0x09;
const uint16 kPageOrdinal = 0x0A;
const uint16 kPageTelephony = 0x0B;
const uint16 kPageConsumer = 0x0C;
const uint16 kPageDigitizer = 0x0D;
const uint16 kPagePidPage = 0x0F;
const uint16 kPageUnicode = 0x10;
const uint16 kPageAlphanumericDisplay = 0x14;
const uint16 kPageMedicalInstruments = 0x40;
const uint16 kPageMonitor0 = 0x80;
const uint16 kPageMonitor1 = 0x81;
const uint16 kPageMonitor2 = 0x82;
const uint16 kPageMonitor3 = 0x83;
const uint16 kPagePower0 = 0x84;
const uint16 kPagePower1 = 0x85;
const uint16 kPagePower2 = 0x86;
const uint16 kPagePower3 = 0x87;
const uint16 kPageBarCodeScanner = 0x8C;
const uint16 kPageScale = 0x8D;
const uint16 kPageMagneticStripeReader = 0x8E;
const uint16 kPageReservedPointOfSale = 0x8F;
const uint16 kPageCameraControl = 0x90;
const uint16 kPageArcade = 0x91;
const uint16 kPageFido = 0xF1D0;
const uint16 kPageVendor = 0xFF00;
const uint16 kPageMediaCenter = 0xFFBC;

// These usage enumerations are derived from the HID Usage Tables v1.12 spec.
// https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf
const uint16 kGenericDesktopUndefined = 0x00;
const uint16 kGenericDesktopPointer = 0x01;
const uint16 kGenericDesktopMouse = 0x02;
const uint16 kGenericDesktopJoystick = 0x04;
const uint16 kGenericDesktopGamePad = 0x05;
const uint16 kGenericDesktopKeyboard = 0x06;
const uint16 kGenericDesktopKeypad = 0x07;
const uint16 kGenericDesktopMultiAxisController = 0x08;
const uint16 kGenericDesktopX = 0x30;
const uint16 kGenericDesktopY = 0x31;
const uint16 kGenericDesktopZ = 0x32;
const uint16 kGenericDesktopRx = 0x33;
const uint16 kGenericDesktopRy = 0x34;
const uint16 kGenericDesktopRz = 0x35;
const uint16 kGenericDesktopSlider = 0x36;
const uint16 kGenericDesktopDial = 0x37;
const uint16 kGenericDesktopWheel = 0x38;
const uint16 kGenericDesktopHatSwitch = 0x39;
const uint16 kGenericDesktopCountedBuffer = 0x3a;
const uint16 kGenericDesktopByteCount = 0x3b;
const uint16 kGenericDesktopMotionWakeup = 0x3c;
const uint16 kGenericDesktopStart = 0x3d;
const uint16 kGenericDesktopSelect = 0x3e;
const uint16 kGenericDesktopVx = 0x40;
const uint16 kGenericDesktopVy = 0x41;
const uint16 kGenericDesktopVz = 0x42;
const uint16 kGenericDesktopVbrx = 0x43;
const uint16 kGenericDesktopVbry = 0x44;
const uint16 kGenericDesktopVbrz = 0x45;
const uint16 kGenericDesktopVno = 0x46;

const uint16 kGenericDesktopSystemControl = 0x80;
const uint16 kGenericDesktopSystemPowerDown = 0x81;
const uint16 kGenericDesktopSystemSleep = 0x82;
const uint16 kGenericDesktopSystemWakeUp = 0x83;
const uint16 kGenericDesktopSystemContextMenu = 0x84;
const uint16 kGenericDesktopSystemMainMenu = 0x85;
const uint16 kGenericDesktopSystemAppMenu = 0x86;
const uint16 kGenericDesktopSystemMenuHelp = 0x87;
const uint16 kGenericDesktopSystemMenuExit = 0x88;
const uint16 kGenericDesktopSystemMenuSelect = 0x89;
const uint16 kGenericDesktopSystemMenuRight = 0x8a;
const uint16 kGenericDesktopSystemMenuLeft = 0x8b;
const uint16 kGenericDesktopSystemMenuUp = 0x8c;
const uint16 kGenericDesktopSystemMenuDown = 0x8d;
const uint16 kGenericDesktopSystemColdRestart = 0x8e;
const uint16 kGenericDesktopSystemWarmRestart = 0x8f;

const uint16 kGenericDesktopDPadUp = 0x90;
const uint16 kGenericDesktopDPadDown = 0x91;
const uint16 kGenericDesktopDPadLeft = 0x92;
const uint16 kGenericDesktopDPadRight = 0x93;

const uint16 kGenericDesktopSystemDock = 0xa0;
const uint16 kGenericDesktopSystemUndock = 0xa1;
const uint16 kGenericDesktopSystemSetup = 0xa2;
const uint16 kGenericDesktopSystemBreak = 0xa3;
const uint16 kGenericDesktopSystemDebuggerBreak = 0xa4;
const uint16 kGenericDesktopApplicationBreak = 0xa5;
const uint16 kGenericDesktopApplicationDebuggerBreak = 0xa6;
const uint16 kGenericDesktopSystemSpeakerMute = 0xa7;
const uint16 kGenericDesktopSystemHibernate = 0xa8;
const uint16 kGenericDesktopSystemDisplayInvert = 0xb0;
const uint16 kGenericDesktopSystemDisplayInternal = 0xb1;
const uint16 kGenericDesktopSystemDisplayExternal = 0xb2;
const uint16 kGenericDesktopSystemDisplayBoth = 0xb3;
const uint16 kGenericDesktopSystemDisplayDual = 0xb4;
const uint16 kGenericDesktopSystemDisplayToggle = 0xb5;
const uint16 kGenericDesktopSystemDisplaySwap = 0xb6;

// These collection types are defined in section 6.2.2.6 of the Device Class
// Definition for HID.
// https://www.usb.org/sites/default/files/documents/hid1_11.pdf
const uint32 kHIDCollectionTypePhysical = 0x00;
const uint32 kHIDCollectionTypeApplication = 0x01;
const uint32 kHIDCollectionTypeLogical = 0x02;
const uint32 kHIDCollectionTypeReport = 0x03;
const uint32 kHIDCollectionTypeNamedArray = 0x04;
const uint32 kHIDCollectionTypeUsageSwitch = 0x05;
const uint32 kHIDCollectionTypeUsageModifier = 0x06;
const uint32 kHIDCollectionTypeVendorMin = 0x80;
const uint32 kHIDCollectionTypeVendorMax = 0xff;

[Stable]
struct HidUsageAndPage {
  uint16 usage@0;
  uint16 usage_page@1;
};

// A HID report is a packet of data sent between a HID device and its host. The
// structure of the report is described in the HID report descriptor as an
// ordered sequence of report items that define the size, count, and usages of
// fields within the report. A single HidReportItem represents one or more
// similar fields within the report, and captures the current state of local and
// global items when a main item was encountered while parsing the report
// descriptor.
// See section 6.2.2 of the Device Class Definition for HID for additional
// information about the HID report descriptor and parser behavior.
// https://www.usb.org/sites/default/files/documents/hid1_11.pdf
[Stable]
struct HidReportItem {
  // True if the usages for this item are defined by |usage_minimum| and
  // |usage_maximum|. False if the usages for this item are defined by |usages|.
  bool is_range@0;

  // Data associated with the Main item. See section 6.2.2.5 of the Device Class
  // Definition for HID.
  // https://www.usb.org/sites/default/files/documents/hid1_11.pdf
  bool is_constant@1;         // Constant (true) or Data (false).
  bool is_variable@2;         // Variable (true) or Array (false).
  bool is_relative@3;         // Relative (true) or Absolute (false).
  bool wrap@4;                // Wrap (true) or No Wrap (false).
  bool is_non_linear@5;       // Non Linear (true) or Linear (false).
  bool no_preferred_state@6;  // No Preferred (true) or Preferred State (false).
  bool has_null_position@7;   // Null state (true) or No Null position (false).
  bool is_volatile@8;         // Volatile (true) or Non Volatile (false).
  bool is_buffered_bytes@9;   // Buffered Bytes (true) or Bit Field (false).

  // Local items. See section 6.2.2.8 of the Device Class Definition for HID.
  // https://www.usb.org/sites/default/files/documents/hid1_11.pdf

  // If |is_range| is false, usages for this item are listed in |usages| in the
  // order they were encountered in the report descriptor.
  array<HidUsageAndPage> usages@10;

  // If |is_range| is true, usages for this item are assigned from a range of
  // usages starting at |usage_minimum| and incrementing until |usage_maximum|.
  // If this item is a Variable and |report_count| is larger than the number of
  // usages in this range, all remaining fields are also assigned
  // |usage_maximum|.
  HidUsageAndPage usage_minimum@11;
  HidUsageAndPage usage_maximum@12;

  // If this item has one or more entries in the Physical descriptor table,
  // |designator_minimum| and |designator_maximum| are set to the minimum and
  // maximum indices of these entries. If the item has no designators, both are
  // set to zero. A designator describes the body part intended to be used with
  // a particular control.
  uint32 designator_minimum@13;
  uint32 designator_maximum@14;

  // If this item has one or more entries in the String descriptor table,
  // |string_minimum| and |string_maximum| are set to the minimum and maximum
  // indices of these entries. If the item has no strings, both are set to zero.
  // The String descriptor contains a list of text strings for the device.
  uint32 string_minimum@15;
  uint32 string_maximum@16;

  // Global items. See section 6.2.2.7 of the Device Class Definition for HID.
  // https://www.usb.org/sites/default/files/documents/hid1_11.pdf

  // |logical_minimum| and |logical_maximum| define the extent of valid data
  // values for the item in logical units. If |has_null_position| is true,
  // values outside this range are interpreted as null input.
  int32 logical_minimum@17;
  int32 logical_maximum@18;

  // |physical_minimum| and |physical_maximum| define the extent of valid data
  // values after applying units to the logical extents.
  int32 physical_minimum@19;
  int32 physical_maximum@20;

  // The value of the unit exponent in base 10. Values between 0x0 and 0x7
  // represent positive exponents 0 to 7, values between 0x8 and 0xF represent
  // nevative exponents -8 to -1. Bits [4:31] are reserved and should be set to
  // zero.
  uint32 unit_exponent@21;

  // The units to apply to this item. The |unit| value is coded as seven 4-bit
  // fields that define the unit system and the exponents on units of length,
  // mass, time, temperature, current, and luminous intensity. Bits [28:31] are
  // reserved and should be set to zero.
  uint32 unit@22;

  // A single report item may define multiple same-sized fields within a report.
  // |report_size| and |report_count| define the size of one field (in bits) and
  // the number of fields within the item. The total size of this item in bits
  // is equal to the product of these values.
  uint32 report_size@23;
  uint32 report_count@24;
};

// Contains information collected from the HID report descriptor regarding a
// single report. The HID specification defines three categories of reports:
// Input (device to host), Output (host to device), and Feature
// (bi-directional). When a device requires multiple reports of a single
// category, each report is assigned a unique 8-bit ID. Devices that do not use
// more than one report of any type may omit report IDs.
[Stable]
struct HidReportDescription {
  // Report ID associated with this report, or zero if the device does not use
  // report IDs.
  uint8 report_id@0;

  // The sequence of report items that describe this report.
  array<HidReportItem> items@1;
};

// Contains information collected from the HID report descriptor regarding a
// single collection. Collections are hierarchical structures within the HID
// report descriptor used to group similar items. Within a report, collections
// are used to associate fields that share physical or logical characteristics.
// Collections may also be used to group entire reports or even other
// collections.
// See section 6.2.2.6 of the Device Class Definition for HID for more
// information about HID collections.
// https://www.usb.org/sites/default/files/documents/hid1_11.pdf
[Stable]
struct HidCollectionInfo {
  // Collection's usage ID.
  HidUsageAndPage usage@0;

  // HID report IDs which belong to this collection or to its embedded
  // collections, in the order they appear in the report descriptor.
  array<uint8> report_ids@1;

  // Collection type.
  uint32 collection_type@2;

  // Reports described in the report descriptor.
  array<HidReportDescription> input_reports@3;
  array<HidReportDescription> output_reports@4;
  array<HidReportDescription> feature_reports@5;

  // The children of this collection in the order they appear in the report
  // descriptor. In child collections, the reports described in the
  // |input_reports|, |output_reports|, and |feature_reports| members include
  // only the subsequence of report items from the parent collection that appear
  // within the child collection.
  array<HidCollectionInfo> children@6;
};

// Contains information related to a single logical HID device. Note that a
// single physical device may expose multiple logical devices, for instance a
// keyboard/mouse combo device would expose separate logical HID devices for
// keyboard and mouse functionality.
[Stable]
struct HidDeviceInfo {
  // A random GUID assigned to the device during enumeration. The device GUID is
  // stable as long as the application is running and the device remains
  // connected to the system.
  string guid@0;

  // A platform-specific string identifier for the physical device. When a
  // single physical device exposes multiple logical devices, the logical
  // devices will have the same value for |physical_device_id|.
  string physical_device_id@1;

  // The vendor ID value reported by the device. Vendor IDs are 16-bit values
  // assigned by the USB-IF or Bluetooth SIG to manufacturers of USB and
  // Bluetooth devices.
  // TODO(mattreynolds): Indicate whether the vendor ID was assigned by USB-IF
  // or Bluetooth SIG.
  uint16 vendor_id@2;

  // The product ID reported by the device. Product IDs are 16-bit values
  // assigned by the manufacturer to identify a particular device model.
  uint16 product_id@3;

  // The product name string reported by the device, or an empty string if no
  // product name is available.
  string product_name@4;

  // The USB serial number string, or an empty string if the device is not a USB
  // device or has no serial number.
  string serial_number@5;

  // The bus used to connect this device to the system.
  HidBusType bus_type@6;

  // An array of bytes representing the HID report descriptor reported by the
  // device, or an empty array if the report descriptor could not be read.
  array<uint8> report_descriptor@7;

  // A structured representation of the information contained in the HID report
  // descriptor.
  array<HidCollectionInfo> collections@8;

  // True if the device uses report IDs.
  bool has_report_id@9;

  // The maximum size in bytes of input, output, and feature reports supported
  // by the device.
  uint64 max_input_report_size@10;
  uint64 max_output_report_size@11;
  uint64 max_feature_report_size@12;

  // A platform-specific string identifier for the logical device.
  string device_node@13;

  // Reports that should not be accessible from Javascript.
  [MinVersion=1] array<uint8>? protected_input_report_ids@14;
  [MinVersion=1] array<uint8>? protected_output_report_ids@15;
  [MinVersion=1] array<uint8>? protected_feature_report_ids@16;

  // True if the device is excluded from access by the HID blocklist. It is
  // based solely on |vendor_id| and |product_id| information.
  [MinVersion=3] bool is_excluded_by_blocklist@17;
};

// A client interface for receiving a notification when HID devices are
// physically connected or disconnected.
[Stable, Uuid="1b9b8008-dcf3-4c2e-9d68-ca3c47778817"]
interface HidManagerClient {
  // Notifies the client that a device is added.
  DeviceAdded@0(HidDeviceInfo device_info);

  // Notifies the client that a device is being removed; called before
  // removing the device from HidService.
  DeviceRemoved@1(HidDeviceInfo device_info);

  // Notifies the client that the device info has been changed.
  // * New collections may be added.
  // * The maximum report sizes may be increased.
  // * The protected report ID lists may have additional report IDs added.
  // Other device information is not modified.
  [MinVersion=2] DeviceChanged@2(HidDeviceInfo device_info);
};

// Provides an interface for enumerating available HID devices, registering for
// device connection and disconnection notifications, and opening a connection
// for reading from and writing to a HID device.
[Stable, Uuid="9e931765-42c9-4afd-9dc5-9086621b7bb6"]
interface HidManager {
  // Enumerates available devices and set as a client of HidManager.
  // The implementation of HidManager guarantees that the returned callback
  // will always be posted earlier than DeviceAdded() and DeviceRemoved().
  GetDevicesAndSetClient@0(pending_associated_remote<HidManagerClient> client)
      => (array<HidDeviceInfo> devices);

  // Enumerates available devices only.
  GetDevices@1() => (array<HidDeviceInfo> devices);

  // Opens a connection to a device by given guid. The callback will be run
  // with null on failure.
  //
  // |connection_client|, if provided, is notified when data is received from
  // the HID device on this connection.
  //
  // |watcher|, if provided, is kept open as long as the HID connection is
  // open. When the HID connection is closed, the watcher is also closed. This
  // is useful when the connection closure should be handled somewhere other
  // than where the |connection| and |connection_client| are held.
  //
  // If |allow_protected_reports| is true, this connection is exempted from
  // the HID blocklist so that protected reports may be sent and received.
  //
  // If |allow_fido_reports| is true, this connection is allowed to send and
  // receive protected reports contained within top-level collections with the
  // kPageFido usage page even if those reports would be blocked by the HID
  // blocklist.
  Connect@2(string device_guid,
          pending_remote<HidConnectionClient>? connection_client,
          pending_remote<HidConnectionWatcher>? watcher,
          [MinVersion=1] bool allow_protected_reports,
          [MinVersion=2] bool allow_fido_reports)
      => (pending_remote<HidConnection>? connection);

  // Binds a HidManager endpoint.
  AddReceiver@3(pending_receiver<HidManager> receiver);
};

// Provides an interface for communication with a HID device. The HID spec
// allows a device to define its own packet formats (reports) for sending or
// receiving data. The methods in HidConnection send or receive data and specify
// which report is used.
[Stable, Uuid="1b9b8008-dcf3-4c2e-9d68-ca3c47778817"]
interface HidConnection {
  // A |report_id| of 0 is returned via callback if report IDs are not
  // supported by the device.
  Read@0() => (bool success, uint8 report_id, array<uint8>? buffer);

  // Pass the |report_id| as 0 if not supported by the device.
  Write@1(uint8 report_id, array<uint8> buffer) => (bool success);

  // The buffer will contain whatever report data was received from the device.
  // This may include the report ID. The report ID is not stripped because a
  // device may respond with other data in place of the report ID.
  GetFeatureReport@2(uint8 report_id) => (bool success, array<uint8>? buffer);

  // Pass the |report_id| as 0 if not supported by the device.
  SendFeatureReport@3(uint8 report_id, array<uint8> buffer) => (bool success);
};

// A client interface for receiving a notification when input reports are
// received.
[Stable, Uuid="11f949ed-fa57-4a94-a433-90b72a2d2b63"]
interface HidConnectionClient {
  // Notifies the client that an input report was received. A |report_id| of 0
  // is passed if report IDs are not used by the device.
  OnInputReport@0(uint8 report_id, array<uint8> buffer);
};

// A client interface for observing whether a HID connection is still active.
// When the connection is closed, the HidConnectionWatcher pipe is also closed.
//
// This is useful when connection closure should be handled somewhere other than
// where the connection itself is used. For instance, Chrome mediates access to
// HidManager through a HID browser service that implements permissions and UI.
// When the service creates a HID connection with HidManager::Connect, it binds
// itself as a watcher so it can be notified when the connection is closed. This
// allows the service to keep track of whether there are open connections for
// the purpose of drawing an indicator icon when a tab is using a HID device.
[Stable, Uuid="8af071b5-0994-4af7-9c3f-6025d7f9e9d0"]
interface HidConnectionWatcher {
};