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

// Use the <code>chrome.hid</code> API to interact with connected HID devices.
// This API provides access to HID operations from within the context of an app.
// Using this API, apps can function as drivers for hardware devices.
//
// Errors generated by this API are reported by setting
// $(ref:runtime.lastError) and executing the function's regular callback. The
// callback's regular parameters will be undefined in this case.
namespace hid {
  dictionary HidCollectionInfo {
    // HID usage page identifier.
    long usagePage;
    // Page-defined usage identifier.
    long usage;
    // Report IDs which belong to the collection and to its children.
    long[] reportIds;
  };

  [noinline_doc] dictionary HidDeviceInfo {
    // Opaque device ID.
    long deviceId;
    // Vendor ID.
    long vendorId;
    // Product ID.
    long productId;
    // The product name read from the device, if available.
    DOMString productName;
    // The serial number read from the device, if available.
    DOMString serialNumber;
    // Top-level collections from this device's report descriptors.
    HidCollectionInfo[] collections;
    // Top-level collection's maximum input report size.
    long maxInputReportSize;
    // Top-level collection's maximum output report size.
    long maxOutputReportSize;
    // Top-level collection's maximum feature report size.
    long maxFeatureReportSize;
    // Raw device report descriptor (not available on Windows).
    ArrayBuffer reportDescriptor;
  };

  dictionary HidConnectInfo {
    // The opaque ID used to identify this connection in all other functions.
    long connectionId;
  };

  [noinline_doc] dictionary DeviceFilter {
    // Device vendor ID.
    long? vendorId;
    // Device product ID, only checked only if the vendor ID matches.
    long? productId;
    // HID usage page identifier.
    long? usagePage;
    // HID usage identifier, checked only if the HID usage page matches.
    long? usage;
  };

  dictionary GetDevicesOptions {
    [deprecated="Equivalent to setting $(ref:DeviceFilter.vendorId)."]
    long? vendorId;
    [deprecated="Equivalent to setting $(ref:DeviceFilter.productId)."]
    long? productId;
    // A device matching any given filter will be returned. An empty filter list
    // will return all devices the app has permission for.
    DeviceFilter[]? filters;
  };

  dictionary DevicePromptOptions {
    // Allow the user to select multiple devices.
    boolean? multiple;
    // Filter the list of devices presented to the user. If multiple filters
    // are provided devices matching any filter will be displayed.
    DeviceFilter[]? filters;
  };

  callback GetDevicesCallback = void (HidDeviceInfo[] devices);
  callback ConnectCallback = void (HidConnectInfo connection);
  callback DisconnectCallback = void ();

  // |reportId|: The report ID or <code>0</code> if none.
  // |data|: The report data, the report ID prefix (if present) is removed.
  callback ReceiveCallback = void (long reportId, ArrayBuffer data);

  // |data|: The report data, including a report ID prefix if one is sent by the
  // device.
  callback ReceiveFeatureReportCallback = void (ArrayBuffer data);

  callback SendCallback = void();

  interface Functions {
    // Enumerate connected HID devices.
    // |options|: The properties to search for on target devices.
    static void getDevices(GetDevicesOptions options,
                           GetDevicesCallback callback);

    // Presents a device picker to the user and returns $(ref:HidDeviceInfo)
    // objects for the devices selected.
    // If the user cancels the picker devices will be empty. A user gesture
    // is required for the dialog to display. Without a user gesture, the
    // callback will run as though the user cancelled. If multiple filters are
    // provided devices matching any filter will be displayed.
    // |options|: Configuration of the device picker dialog box.
    // |callback|: Invoked with a list of chosen $(ref:Device)s.
    static void getUserSelectedDevices(optional DevicePromptOptions options,
                                       GetDevicesCallback callback);

    // Open a connection to an HID device for communication.
    // |deviceId|: The $(ref:HidDeviceInfo.deviceId) of the device to open.
    static void connect(long deviceId,
                        ConnectCallback callback);

    // Disconnect from a device. Invoking operations on a device after calling
    // this is safe but has no effect.
    // |connectionId|: The <code>connectionId</code> returned by $(ref:connect).
    static void disconnect(long connectionId,
                           optional DisconnectCallback callback);

    // Receive the next input report from the device.
    // |connectionId|: The <code>connectionId</code> returned by $(ref:connect).
    static void receive(long connectionId,
                        ReceiveCallback callback);

    // Send an output report to the device.
    //
    // <em>Note:</em> Do not include a report ID prefix in <code>data</code>.
    // It will be added if necessary.
    // |connectionId|: The <code>connectionId</code> returned by $(ref:connect).
    // |reportId|: The report ID to use, or <code>0</code> if none.
    // |data|: The report data.
    static void send(long connectionId,
                     long reportId,
                     ArrayBuffer data,
                     SendCallback callback);

    // Request a feature report from the device.
    // |connectionId|: The <code>connectionId</code> returned by $(ref:connect).
    // |reportId|: The report ID, or <code>0</code> if none.
    static void receiveFeatureReport(long connectionId,
                                     long reportId,
                                     ReceiveFeatureReportCallback callback);

    // Send a feature report to the device.
    //
    // <em>Note:</em> Do not include a report ID prefix in <code>data</code>.
    // It will be added if necessary.
    // |connectionId|: The <code>connectionId</code> returned by $(ref:connect).
    // |reportId|: The report ID to use, or <code>0</code> if none.
    // |data|: The report data.
    static void sendFeatureReport(long connectionId,
                                  long reportId,
                                  ArrayBuffer data,
                                  SendCallback callback);
  };

  interface Events {
    // Event generated when a device is added to the system. Events are only
    // broadcast to apps and extensions that have permission to access the
    // device. Permission may have been granted at install time or when the user
    // accepted an optional permission (see $(ref:permissions.request)).
    static void onDeviceAdded(HidDeviceInfo device);

    // Event generated when a device is removed from the system. See
    // $(ref:onDeviceAdded) for which events are delivered.
    // |deviceId|: The <code>deviceId</code> property of the device passed to
    // $(ref:onDeviceAdded).
    static void onDeviceRemoved(long deviceId);
  };
};
