This document describes an API for providing access to devices that
support the Human Interface Device (HID) protocol.
Introduction
A HID (Human Interface Device) is a type of device that takes input
from or provides output to humans. It also refers to the HID protocol,
a standard for bi-directional communication between a host and a device
that is designed to simplify the installation procedure. The HID
protocol was originally developed for USB devices but has since been
implemented over many other protocols, including Bluetooth.
The web platform already supports input from many HID devices.
Keyboards, pointing devices, and gamepads are all typically implemented
using the HID protocol. However, this support relies on the operating
system's HID drivers that transform the HID input into high-level input
APIs. Devices that are not well supported by the host's HID driver are
often inaccessible to web pages. Similarly, the outputs on most devices
that are not supported by the host's HID driver are inaccessible.
The most common classes of HID input devices are already
well-supported on the web platform through existing high-level input
APIs. For instance, mouse input is accessible through
{{PointerEvent}} and keyboard input is accessible through
{{KeyboardEvent}}. Input from these devices is handled using the
host's native HID driver and typically does not require
device-specific drivers or configuration to work correctly. WebHID is
not intended for devices like these that are already well-supported
through high-level input APIs.
For some classes of HID devices, the web platform supports some
features of the device but limits access to other features. For
instance, [[GAMEPAD]] supports the input capabilities of most game
controllers but does not support less common capabilities like LED
indicators or audio. These features are often not well-supported by
host APIs and adding support within the user agent can lead to
significant complexity. WebHID would give applications an alternative
when the functionality provided by the high-level API is incomplete.
Many HID devices are not supported through any web platform API. The
HID specification describes a wide array of devices that could be
supported through HID, including virtual reality controls, flight
simulators, medical equipment, and more. WebHID would allow these
devices to be used without requiring additional drivers or
modification to the user agent.
Prototyping, hobbyists, and educational devices
HID is attractive for prototyping and hobbyist applications because
it allows devices to use the host's generic HID driver instead of
requiring a driver for each host where the device will be used. The
simplified installation procedure also makes it easier for educators
to deploy a device to a classroom of students without modifying the
system configuration on each host. Providing access to HID devices
through the web platform would further reduce installation
requirements, particularly for devices that are currently only
supported through host-specific applications.
Security and Privacy Considerations
Abusing Access to a Device
HID peripherals may expose powerful functionality that should not be
made accessible to the page without explicit consent from the user.
For instance, a HID peripheral may have sensors that allow it to
collect information about its surroundings. A device may store
private information that should not be revealed or overwritten. Many
devices expose functionality that allow the device firmware to be
upgraded. Operating systems typically do not restrict access to HID
devices from applications, and this access can occasionally be abused
to damage the device or corrupt the data stored on it.
In some cases, a device may expose functionality that should not be
accessible at all from a web page. Specific devices may be blocked by
recognizing the device by its [=vendor ID=] and [=product ID=] and
hiding such devices during enumeration. The [=report descriptor=]
allows a device to describe its own capabilities, and this
information can be used to block classes of devices even when the
[=vendor ID=] and [=product ID=] cannot be known in advance. This can
be accomplished by inspecting the [=HID usage=] values assigned to
collections within the [=report descriptor=]; for instance, access to
keyboard-like devices can be denied by denying access to devices that
include a [=top-level collection=] with the [=HID usage=] for a
keyboard.
To mitigate abuse, a device will not be made available to the page
until the user has granted explicit access. Access must first be
requested by the page and will be granted once the user has selected
the device from a chooser displaying all available devices. Once a
page has been granted access, an indicator will be displayed to
indicate the device is in use.
Attacking a Device
The HID protocol is extremely versatile, and a wide variety of
devices have been designed that take advantage of this versatility.
As a result, there are many possibilities for how access to a device
could allow a malicious page to damage the device itself. It is
relatively common for HID peripherals to allow firmware updates to be
sent using custom HID reports. Device manufacturers must take care to
design the firmware upgrade mechanism to verify that the firmware
binary is authentic, and should also protect against downgrades that
could reduce the security of a device. Untrusted upgrades could be
used to add new capabilities to a device or cause it to masquerade as
an entirely different type of device.
Some devices may be damaged when inputs are provided outside of the
expected range. For instance, the rumble feature on a gamepad could
become damaged if a page sends an invalid rumble command.
In general, these types of attacks are device-specific and cannot be
mitigated at the API level.
Attacking the Host
If a malicious page gains access to a device, in some cases this
access can be used to attack the host. A major concern is whether the
device can be used to generate trusted input events. These events
serve as a proxy for user intent and can be used to access more
powerful web platform features.
Mice and keyboards are typically implemented as HID peripherals, and
are also capable of generating trusted input. A HID keyboard or mouse
may contain advanced features like programmable macros, which store a
sequence of inputs and allow the sequence to be played back at a
later time. Device manufacturers must take care to design such
features in a way that would prevent a malicious app from
reprogramming the device with an unexpected input sequence, and must
also protect against triggering macro playback without the user's
explicit consent.
Mitigation
To mitigate security and privacy risks, it is recommended that user
agents implement a chooser-based flow for requesting device access.
When a page requests access to a HID device, the user agent should
display a dialog that informs the user that the page wants to access
a device. The dialog should display a list of connected HID devices
and ask the user to select a device that will be exposed to the page.
To reduce the possibility of accidental clicks, the dialog should
require two separate interactions: one interaction to select the
device from the list and a second interaction to confirm the
selection and dismiss the dialog.
Instances of {{HID}} are created with the internal slots described in
the following table:
Internal slot
Initial value
Description (non-normative)
[[\devices]]
An empty [=ordered set=]
An [=ordered set=] of {{HIDDevice}} instances representing the
[=HID interfaces=] currently available on the system
onconnect attribute
{{HID/onconnect}} is an [=event handler IDL attribute=] for the
connect event type.
ondisconnect attribute
{{HID/ondisconnect}} is an [=event handler IDL attribute=] for the
disconnect event type.
When a [=HID interface=] becomes available on the system, run the
following steps:
A HID interface is a logical interface that can be used to
communicate with a device over the HID protocol. Each [=HID
interface=] has exactly one [=report descriptor=] that describes the
set of reports supported by that interface. A single physical device
may expose more than one [=HID interface=]. Devices with multiple
[=HID interfaces=] run these steps once for each interface.
For example, USB devices are implemented as a collection of
interfaces, each of which may specify an interface class. When a
device has multiple USB interfaces that use the HID class, each
interface is enumerated as a separate [=HID interface=].
Let |device:HIDDevice| be a {{HIDDevice}}.
Set |device|.{{HIDDevice/[[vendorId]]}} to the [=vendor ID=] of the
device that exposes the interface.
Set |device|.{{HIDDevice/[[productId]]}} to the [=product ID=] of
the device that exposes the interface.
Set |device|.{{HIDDevice/[[productName]]}} to the [=product name=]
of the device that exposes the interface.
Set |device|.{{HIDDevice/[[collections]]}} to the result of
[=parsing the Report descriptor=].
Let |hid:HID| be the result of calling |device|'s [=relevant global
object=]'s {{Navigator}} object's {{Navigator/hid}} getter.
[=list/Append=] |device| to |hid|.{{HID/[[devices]]}}.
If the user has allowed the site to access |device| as the result
of a previous call to {{HID/requestDevice()}}, then [=queue a global
task=] on the [=relevant global object=] of |hid| using the [=HID
device task source=] to [=fire an event=] named {{connect}} at |hid|
using {{HIDConnectionEvent}} with its {{HIDConnectionEvent/device}}
attribute initialized to |device|.
To parse the report
descriptor, run the following steps:
The system will typically read the [=report descriptor=] [=byte
sequence=] for each [=HID interface=] when a device is first
connected and cache the values in the system registry. If the
[=report descriptor=] is not available but the system provides
information that can be used to reconstruct the layout of each
report, the user agent may use an alternate algorithm instead of
parsing the [=report descriptor=].
The [=report descriptor=] format is described in
[[USBIF-HID-CLASS]] section 6.2.2. The algorithm below is intended
to implement the same parsing algorithm described in that section.
The [=report descriptor=] contains three classes of items.
Main items are used to define and group data fields.
Global items and Local items describe the
data fields. [=Local items=] define characteristics that only apply
to the next [=Main item=], while [=Global items=] define
characteristics that affect all subsequently defined [=Main
items=].
Each item has a item data field containing 0, 1, 2, or 4
bytes of data associated with the item and a bSize field
that describes how many bytes are used to store the [=item data
field=]. Each item also has a tag that identifies its type.
Let |items| be the result of converting the [=report descriptor=]
[=byte sequence=] into a [=list=] of [=Main items=], [=Global items=],
and [=Local items=].
Initialize |collections:sequence<HIDCollectionInfo>| to be an
empty [=sequence=] of {{HIDCollectionInfo}}.
Initialize |ancestors| to be an empty [=list=].
Initialize |localState| to be an empty [=ordered map=].
Initialize |usages| to be an empty [=sequence=] of `unsigned long`.
Initialize |stringIndices| to be an empty [=list=].
Initialize |globalStack| to be an empty [=stack=].
Initialize |initialGlobalState| to be an empty [=ordered map=].
Initialize |reportId| to 0.
Set |initialGlobalState|["{{HIDReportItem/unitSystem}}"] to
{{HIDUnitSystem/"none"}}.
Set |initialGlobalState|["{{HIDReportItem/unitExponent}}"] to 0.
Set
|initialGlobalState|["{{HIDReportItem/unitFactorLengthExponent}}"] to
0.
Set
|initialGlobalState|["{{HIDReportItem/unitFactorMassExponent}}"] to 0.
Set
|initialGlobalState|["{{HIDReportItem/unitFactorTimeExponent}}"] to 0.
Set
|initialGlobalState|["{{HIDReportItem/unitFactorTemperatureExponent}}"]
to 0.
Set
|initialGlobalState|["{{HIDReportItem/unitFactorCurrentExponent}}"] to
0.
Set
|initialGlobalState|["{{HIDReportItem/unitFactorLuminousIntensityExponent}}"]
to 0.
Set |initialGlobalState|["{{HIDReportItem/logicalMinimum}}"] to 0.
Set |initialGlobalState|["{{HIDReportItem/logicalMaximum}}"] to 0.
Set |initialGlobalState|["{{HIDReportItem/physicalMinimum}}"] to 0.
Set |initialGlobalState|["{{HIDReportItem/physicalMaximum}}"] to 0.
[=Main items=] are described in [[USBIF-HID-CLASS]] sections
<IP_ADDRESS> through <IP_ADDRESS>. An item with the Input tag,
Output tag, or Feature tag defines a field
within an input, output, or feature report. The [=item data
field=] of a [=Main item=] with an [=Input tag=], [=Output tag=],
or [=Feature tag=] is a bit field containing several boolean
parameters describing the data field. An item with the
Collection tag defines a new collection nested within
the current collection, or a new [=top-level collection=] if
there is no current collection. The [=item data field=] of a
[=Main item=] with a [=Collection tag=] contains the
collection type. An item with the End Collection
tag closes the current collection.
If |item| is a [=Main item=]:
If |item| has the [=Input tag=], [=Output tag=], or
[=Feature tag=]:
Let |globalState| be the last [=list/item=] of
|globalStack|.
Let |reportId:octet| be
|globalState|["{{HIDReportInfo/reportId}}"].
Let |reportItem:HIDReportItem| be the result of
[=creating a HID report item=] with |item|, |localState|,
|globalState|, |usages|, and |strings|.
[=list/For each=] |collection:HIDCollectionInfo| of
|ancestors|:
Let |reports:sequence<HIDCollectionInfo>| be:
|collection|["{{HIDCollectionInfo/inputReports}}"]
if |item| has the [=Input tag=],
|collection|["{{HIDCollectionInfo/outputReports}}"]
if |item| has the [=Output tag=], or
|collection|["{{HIDCollectionInfo/featureReports}}"]
if |item| has the [=Feature tag=].
If |reports| contains an item with its
{{HIDReportInfo/reportId}} attribute equal to
|reportId|, then let |report| be that item.
Otherwise:
Let |report:HIDReportInfo| be a [=new=]
{{HIDReportInfo}} dictionary.
Set |report|["{{HIDReportInfo/reportId}}"] to
|reportId|.
Set |report|["{{HIDReportInfo/items}}"] to an
empty [=sequence=] of {{HIDReportItem}}.
[=list/Append=] |report| to |reports|.
[=list/Append=] |item| to
|report|["{{HIDReportInfo/items}}"].
If |item| has the [=Collection tag=]:
Let |collection:HIDCollectionInfo| be a [=new=]
{{HIDCollectionInfo}} dictionary.
Let |usage| be the first [=list/item=] of |usages|.
If the [=list/size=] of |usages| is greater than 1,
remove the first [=list/item=] of |usages|.
Set |collection|["{{HIDCollectionInfo/usagePage}}"] to
|globalState|["{{HIDCollectionInfo/usagePage}}"].
Set |collection|["{{HIDCollectionInfo/usage}}"] to
|usage|.
Set |collection|["{{HIDCollectionInfo/type}}"] to the
value representing the collection's type.
Set |collection|["{{HIDCollectionInfo/children}}"] to
an empty [=sequence=] of {{HIDCollectionInfo}}.
Set |collection|["{{HIDCollectionInfo/inputReports}}"]
to an empty [=sequence=] of {{HIDReportInfo}}.
Set |collection|["{{HIDCollectionInfo/outputReports}}"]
to an empty [=sequence=] of {{HIDReportInfo}}.
Set
|collection|["{{HIDCollectionInfo/featureReports}}"] to an
empty [=sequence=] of {{HIDReportInfo}}.
If |ancestors| [=list/is empty=], [=list/append=]
|collection| to |collections|.
Otherwise:
Let |parent:HIDCollectionInfo| be the last
[=list/item=] of |ancestors|.
[=list/Append=] |collection| to
|parent|["{{HIDCollectionInfo/children}}"].
[=list/Append=] |collection| to |ancestors|.
If |item| has the [=End Collection tag=], then
[=list/remove=] the last [=list/item=] of |ancestors|.
Set |localState| to be an empty [=ordered map=].
Set |usages| to be an empty [=sequence=] of `unsigned
long`.
[=Global items=] are described in section <IP_ADDRESS>. An
item with the Usage Page tag, Logical
Minimum tag, Logical Maximum tag,
Physical Minimum tag, Physical Maximum
tag, Unit Exponent tag, Unit
tag, Report Size tag, Report ID
tag, or Report Count tag modifies the
respective field of the global item state table. An item
with the Push tag pushes a copy of the current
global item state table onto the item state stack. An
item with the Pop tag replaces the global item
state table with the top of the item state stack. The
global Report ID value is not affected when manipulating
the item state stack.
If |item| is a [=Global item=]:
Let |globalState| be the last [=list/item=] of
|globalStack|.
Let |value:unsigned long| be the [=item data field=]
interpreted as an `unsigned long`.
If |item| has the [=Usage Page tag=], then set
|globalState|["{{HIDCollectionInfo/usagePage}}"] to
|value|.
If |item| has the [=Logical Minimum tag=], then set
|globalState|["{{HIDReportItem/logicalMinimum}}"] to
|value|.
If |item| has the [=Logical Maximum tag=], then set
|globalState|["{{HIDReportItem/logicalMaximum}}"] to
|value|.
If |item| has the [=Physical Minimum tag=], then set
|globalState|["{{HIDReportItem/physicalMinimum}}"] to
|value|.
If |item| has the [=Physical Maximum tag=], then set
|globalState|["{{HIDReportItem/physicalMaximum}}"] to
|value|.
If |item| has the [=Report Size tag=], then set
|globalState|["{{HIDReportItem/reportSize}}"] to |value|.
If |item| has the [=Report ID tag=], then set
|globalState|["{{HIDReportInfo/reportId}}"] to |value|.
If |item| has the [=Report Count tag=], then set
|globalState|["{{HIDReportItem/reportCount}}"] to |value|.
If |item| has the [=Unit tag=]:
Let |nibbles| be the result of interpreting |value|
as a [=sequence=] of eight 4-bit signed two's
complement integers starting from the low-order bits.
If |nibbles|[0] is:
0, then set
|globalState|["{{HIDReportItem/unitSystem}}"] to
{{HIDUnitSystem/"none"}}
1, then set
|globalState|["{{HIDReportItem/unitSystem}}"] to
{{HIDUnitSystem/"si-linear"}}
2, then set
|globalState|["{{HIDReportItem/unitSystem}}"] to
{{HIDUnitSystem/"si-rotation"}}
3, then set
|globalState|["{{HIDReportItem/unitSystem}}"] to
{{HIDUnitSystem/"english-linear"}}
4, then set
|globalState|["{{HIDReportItem/unitSystem}}"] to
{{HIDUnitSystem/"english-rotation"}}
-1, then set
|globalState|["{{HIDReportItem/unitSystem}}"] to
{{HIDUnitSystem/"vendor-defined"}}
Otherwise, set
|globalState|["{{HIDReportItem/unitSystem}}"] to
{{HIDUnitSystem/"reserved"}}
Set
|globalState|["{{HIDReportItem/unitFactorLengthExponent}}"]
to |nibbles|[1].
Set
|globalState|["{{HIDReportItem/unitFactorMassExponent}}"]
to |nibbles|[2].
Set
|globalState|["{{HIDReportItem/unitFactorTimeExponent}}"]
to |nibbles|[3].
Set
|globalState|["{{HIDReportItem/unitFactorTemperatureExponent}}"]
to |nibbles|[4].
Set
|globalState|["{{HIDReportItem/unitFactorCurrentExponent}}"]
to |nibbles|[5].
Set
|globalState|["{{HIDReportItem/unitFactorLuminousIntensityExponent}}"]
to |nibbles|[6].
If |item| has the [=Unit Exponent tag=], then set
|globalState|["{{HIDReportItem/unitExponent}}"] to the
result of interpreting the lowest 4 bits of the [=item data
field=] as a signed two's complement integer.
If |item| has the [=Push tag=], then [=stack/push=] a
copy of |globalState| onto |globalStack|.
If |item| has the [=Pop tag=], then [=stack/pop=] from
|globalStack|.
[=Local items=] are described in section <IP_ADDRESS>. An item
with the Usage tag, Usage Minimum tag,
Usage Maximum tag, String Index tag,
String Minimum tag, or String Maximum
tag modifies the respective field of the local item
state table. The local item state is cleared after each
[=Main item=].
If |item| is a [=Local item=]:
Let |value:unsigned long| be the [=item data field=]
interpreted as an `unsigned long`.
If |item| has the [=Usage tag=]:
If |item|'s [=bSize field=] is 1 or 2:
Let |usageId:unsigned short| be an `unsigned short`
containing the lower 16 bits of |value|.
Let |globalState| be the last [=list/item=] of
|globalStack|.
Set |value| to a [=HID usage=] composed of
|globalState|["{{HIDCollectionInfo/usagePage}}"] in the
high order bits and |usageId| in the low order bits.
[=list/Append=] |value| to |usages|.
If |item| has the [=Usage Minimum tag=], then set
|localState|["{{HIDReportItem/usageMinimum}}"] to |value|.
If |item| has the [=Usage Maximum tag=], then set
|localState|["{{HIDReportItem/usageMaximum}}"] to |value|.
If |item| has the [=String Index tag=], then
[=list/append=] |value| to |stringIndices|.
If |item| has the [=String Minimum tag=], then set
|localState|[`"stringMinimum"`] to |value|.
If |item| has the [=String Maximum tag=], then set
|localState|[`"stringMaximum"`] to |value|.
To create a HID report
item with |item|, |localState|, |globalState|, |usages|, and
|stringIndices|, run the following steps:
Let |reportItem:HIDReportItem| be a [=new=] {{HIDReportItem}}
dictionary.
Let |value:unsigned long| be the [=item data field=] interpreted as
an `unsigned long`.
Let |bitfield| be a [=list=] of `boolean` values representing each
of the bits of |value|, starting from the low-order bits.
Set |reportItem|["{{HIDReportItem/isConstant}}"] to |bitfield|[0].
Set |reportItem|["{{HIDReportItem/isArray}}"] to !|bitfield|[1].
Set |reportItem|["{{HIDReportItem/isAbsolute}}"] to !|bitfield|[2].
Set |reportItem|["{{HIDReportItem/wrap}}"] to |bitfield|[3].
Set |reportItem|["{{HIDReportItem/isLinear}}"] to !|bitfield|[4].
Set |reportItem|["{{HIDReportItem/hasPreferredState}}"] to
|bitfield|[5].
Set |reportItem|["{{HIDReportItem/hasNull}}"] to |bitfield|[6].
Set |reportItem|["{{HIDReportItem/isVolatile}}"] to |bitfield|[7].
Set |reportItem|["{{HIDReportItem/isBufferedBytes}}"] to
|bitfield|[8].
Set |reportItem|["{{HIDReportItem/usages}}"] to |usages|.
Set |reportItem|["{{HIDReportItem/reportSize}}"] to
|globalState|["{{HIDReportItem/reportSize}}"].
Set |reportItem|["{{HIDReportItem/reportCount}}"] to
|globalState|["{{HIDReportItem/reportCount}}"].
Set |reportItem|["{{HIDReportItem/unitExponent}}"] to
|globalState|["{{HIDReportItem/unitExponent}}"].
Set |reportItem|["{{HIDReportItem/unitSystem}}"] to
|globalState|["{{HIDReportItem/unitSystem}}"].
Set |reportItem|["{{HIDReportItem/unitFactorLengthExponent}}"] to
|globalState|["{{HIDReportItem/unitFactorLengthExponent}}"].
Set |reportItem|["{{HIDReportItem/unitFactorMassExponent}}"] to
|globalState|["{{HIDReportItem/unitFactorMassExponent}}"].
Set |reportItem|["{{HIDReportItem/unitFactorTimeExponent}}"] to
|globalState|["{{HIDReportItem/unitFactorTimeExponent}}"].
Set |reportItem|["{{HIDReportItem/unitFactorTemperatureExponent}}"]
to |globalState|["{{HIDReportItem/unitFactorTemperatureExponent}}"].
Set |reportItem|["{{HIDReportItem/unitFactorCurrentExponent}}"] to
|globalState|["{{HIDReportItem/unitFactorCurrentExponent}}"].
Set
|reportItem|["{{HIDReportItem/unitFactorLuminousIntensityExponent}}"]
to
|globalState|["{{HIDReportItem/unitFactorLuminousIntensityExponent}}"].
Set |reportItem|["{{HIDReportItem/logicalMinimum}}"] to
|globalState|["{{HIDReportItem/logicalMinimum}}"].
Set |reportItem|["{{HIDReportItem/logicalMaximum}}"] to
|globalState|["{{HIDReportItem/logicalMaximum}}"].
Set |reportItem|["{{HIDReportItem/physicalMinimum}}"] to
|globalState|["{{HIDReportItem/physicalMinimum}}"].
Set |reportItem|["{{HIDReportItem/physicalMaximum}}"] to
|globalState|["{{HIDReportItem/physicalMaximum}}"].
If "{{HIDReportItem/usageMinimum}}" is in |localState|, then set
|reportItem|["{{HIDReportItem/usageMinimum}}"] to
|localState|["{{HIDReportItem/usageMinimum}}"].
If "{{HIDReportItem/usageMaximum}}" is in |localState|, then set
|reportItem|["{{HIDReportItem/usageMaximum}}"] to
|localState|["{{HIDReportItem/usageMaximum}}"].
Set |reportItem|["{{HIDReportItem/isRange}}"] to `true` if
|reportItem|["{{HIDReportItem/usageMinimum}}"] is less than
|reportItem|["{{HIDReportItem/usageMaximum}}"], or `false` otherwise.
If `"stringMinimum"` is in |localState| and `"stringMaximum"` is in
|localState|:
[=list/Append=] the [=list/item=]s of [=the range=] from
|localState|[`"stringMinimum"`] to |localState|[`"stringMaximum"`]
to |stringIndices|.
[=list/For each=] |stringIndex| of |stringIndices|:
Let |string| be the result of reading the string descriptor at
index |stringIndex|.
[=list/Append=] |string| to
|reportItem|["{{HIDReportItem/strings}}"].
Return |reportItem|.
When a [=HID interface=] becomes unavailable on the system, run the
following steps:
Let |device:HIDDevice| be the {{HIDDevice}} in
|hid|.{{HID/[[devices]]}} representing the interface.
Let |hid:HID| be the result of calling |device|'s [=relevant global
object=]'s {{Navigator}} object's {{Navigator/hid}} getter.
[=list/Remove=] |device| from |hid|.{{HID/[[devices]]}}.
If the user has allowed the site to access |device| as the result
of a previous call to {{HID/requestDevice()}}, then [=queue a global
task=] on the [=relevant global object=] of |hid| using the [=HID
device task source=] to [=fire an event=] named {{disconnect}} at |hid|
using {{HIDConnectionEvent}} with its {{HIDConnectionEvent/device}}
attribute initialized to |device|.
getDevices() method
The {{HID/getDevices()}} method steps are:
Let |promise:Promise| be [=a new promise=].
If [=this=]'s [=relevant global object=]'s [=associated
Document=] is not [=allowed to use=] the [=policy-controlled
feature=] named `"hid"`, [=reject=] |promise| with a
"{{SecurityError}}" {{DOMException}} and return |promise|.
Run the following steps [=in parallel=]:
Let |devices:sequence<HIDDevice>| be an empty
[=sequence=] of {{HIDDevice}}.
[=list/For each=] |device:HIDDevice| of
[=this=].{{HID/[[devices]]}}:
If the user has allowed the site to access |device| as
the result of a previous call to {{HID/requestDevice()}},
then [=list/append=] |device| to |devices|.
[=Queue a global task=] on the [=relevant global object=] of
[=this=] using the [=HID device task source=] to [=resolve=]
|promise| with |devices|.
Return |promise|.
requestDevice() method
The {{HID/requestDevice()}} permission dialog presents a list of
connected devices and asks the user to select one.
If a device has multiple [=HID interfaces=], the dialog MAY present
only a single item that represents all the interfaces. When the
user selects an item that represents multiple [=HID interfaces=],
the user agent MUST grant access to all the [=HID interfaces=]
exposed by the device.
The {{HID/requestDevice()}} method steps are:
Let |promise:Promise| be [=a new promise=].
If [=this=]'s [=relevant global object=]'s [=associated
Document=] is not [=allowed to use=] the [=policy-controlled
feature=] named `"hid"`, [=reject=] |promise| with a
"{{SecurityError}}" {{DOMException}} and return |promise|.
If the [=relevant global object=] of [=this=] does not have
[=transient activation=], [=reject=] |promise| with a
"{{SecurityError}}" {{DOMException}} and return |promise|.
If |options|["{{HIDDeviceRequestOptions/filters}}"] is present,
then run the following steps [=list/for each=]
|filter:HIDDeviceFilter| of
|options|["{{HIDDeviceRequestOptions/filters}}"]:
If |filter| is empty, then [=reject=] |promise| with a
{{TypeError}} and return |promise|.
If |filter|["{{HIDDeviceFilter/productId}}"] is present and
|filter|["{{HIDDeviceFilter/vendorId}}"] is not present,
[=reject=] |promise| with a {{TypeError}} and return |promise|.
If |filter|["{{HIDDeviceFilter/usage}}"] is present and
|filter|["{{HIDDeviceFilter/usagePage}}"] is not present,
[=reject=] |promise| with a {{TypeError}} and return |promise|.
Run the following steps [=in parallel=]:
Initialize |availableDevices| to be an empty [=list=].
[=list/For each=] |device:HIDDevice| of
[=this=].{{HID/[[devices]]}}:
If |device| [=matches any filter=] in
|options|["{{HIDDeviceRequestOptions/filters}}"], then
[=list/append=] |device| to |availableDevices|.
Prompt the user to grant the site access to a HID device by
presenting them with the list of devices in |availableDevices|.
The user agent may modify the device list before presenting
it to the user. For example, devices with multiple [=HID
interfaces=] SHOULD be represented by a single item such that
selecting the item grants access to all interfaces exposed by
the device. Whether a device is implemented as a single
interface or a collection of interfaces is an implementation
detail that may not be known by the user and should not be
considered relevant for device access permissions.
Let |devices:sequence<HIDDevice>| be an empty
[=sequence=] of {{HIDDevice}}.
If the user does not choose a device, [=queue a global task=]
on the [=relevant global object=] of [=this=] using the [=HID
device task source=] to [=resolve=] |promise| with |devices| and
abort these steps.
[=list/For each=] |device:HIDDevice| of
[=this=].{{HID/[[devices]]}}:
If |device| represents a [=HID interface=] exposed by the
chosen device, then [=list/append=] |device| to |devices|.
[=Queue a global task=] on the [=relevant global object=] of
|device| using the [=HID device task source=] to [=resolve=]
|promise| with |devices|.
dictionary HIDDeviceFilter {
unsigned long vendorId;
unsigned short productId;
unsigned short usagePage;
unsigned short usage;
};
vendorId member
The [=vendor ID=] to match.
productId member
The [=product ID=] to match. If the {{HIDDeviceFilter/vendorId}}
member is not present, {{HIDDeviceFilter/productId}} is ignored.
usagePage member
The [=top-level collection=] [=usage page=] to match.
usage member
The [=top-level collection=] [=usage ID=] to match. If the
{{HIDDeviceFilter/usagePage}} member is not present,
{{HIDDeviceFilter/usage}} is ignored.
Device filters are used to narrow the list of devices presented
to the user in the chooser dialog created by
{{HID/requestDevice()}}. When no filters are provided, all
connected devices are included. When one or more filters are
provided, a device is included if any filter matches.
All {{HIDDeviceFilter}} members are optional. Each member
specifies a rule. To match a {{HIDDeviceFilter}}, every rule must
be satisfied. An empty {{HIDDeviceFilter}} matches any device.
Device ID rules are used to select devices by their [=vendor ID=]
and [=product ID=]. This is useful when an application is only
designed to work with a specific device, or otherwise relies on
vendor-specific functionality. Including a
{{HIDDeviceFilter/vendorId}} rule causes the filter to only match
devices with the specified [=vendor ID=]. If a
{{HIDDeviceFilter/productId}} rule is also included, the filter
will only match devices with the specified [=vendor ID=] and
[=product ID=]. {{HIDDeviceFilter/productId}} is ignored if it is
specified without a {{HIDDeviceFilter/vendorId}} rule.
Usage rules are used to select devices by the [=HID usages=]
assigned to the [=top-level collections=] of the device. This is
useful when an application is designed to work with a standard
class of device. To match a device, at least one of the device's
collections must match every usage rule. Including a
{{HIDDeviceFilter/usagePage}} rule causes the filter to only
match if the device contains a collection with the specified
[=usage page=]. If a {{HIDDeviceFilter/usage}} rule is also
included, the filter will only match devices with the specified
[=usage page=] and [=usage ID=]. {{HIDDeviceFilter/usage}} is
ignored if it is specified without a
{{HIDDeviceFilter/usagePage}} rule.
Device ID rules and usage rules may be combined. For instance, an
application may want to match devices from a particular vendor,
but only devices that implement a specific device class.
A {{HIDDevice}} |device:HIDDevice| matches any filter in
a [=sequence=] |filters:sequence<HIDDeviceFilter>| of
{{HIDDeviceFilter}} if these steps return `true`:
If |filters| is empty, then return `true`.
[=list/For each=] |filter:HIDDeviceFilter| of |filters|:
If |filter| [=matches the device IDs=] of |device| and
|filter| [=matches any collection=] of |device|, then return
`true`.
Return `false`.
A {{HIDDeviceFilter}} |filter:HIDDeviceFilter| matches the
device IDs of |device:HIDDevice| if these steps return
`true`:
If "{{HIDDeviceFilter/vendorId}}" is in |filter|:
If |filter|["{{HIDDeviceFilter/vendorId}}"] is not equal to
|device|.{{HIDDevice/vendorId}}, then return `false`.
If "{{HIDDeviceFilter/productId}}" is in |filter| and
|filter|["{{HIDDeviceFilter/productId}}"] is not equal to
|device|.{{HIDDevice/productId}}, then return `false`.
Return `true`.
A {{HIDDeviceFilter}} |filter:HIDDeviceFilter| matches any
collection of |device:HIDDevice| if these steps return
`true`:
[=list/For each=] |collection:HIDCollectionInfo| of
|device|.{{HIDDevice/collections}}:
If |filter| [=matches the collection=] |collection| then
return `true`.
Return `false`.
A {{HIDDeviceFilter}} |filter:HIDDeviceFilter| matches the
collection |collection:HIDCollectionInfo| if these steps
return `true`:
If "{{HIDDeviceFilter/usagePage}}" is in |filter|:
If |filter|["{{HIDDeviceFilter/usagePage}}"] is not equal
to |collection|.{{HIDCollectionInfo/usagePage}}, then return
`false`.
If "{{HIDCollectionInfo/usage}}" is in |filter| and
|filter|["{{HIDDeviceFilter/usage}}"] is not equal to
|collection|.{{HIDCollectionInfo/usage}}, then return `false`.
{{HIDDevice/oninputreport}} is an [=event handler IDL attribute=] for
the inputreport event type.
opened attribute
A flag indicating that the {{HIDDevice}} is ready to transfer data.
The {{HIDDevice/opened}} getter steps are:
If [=this=].{{HIDDevice/[[state]]}} is `opened`, then return
`true`.
Return `false`.
vendorId attribute
A vendor ID is an `unsigned short` value assigned by a
vendor ID source that identifies the manufacturer of a device.
The {{HIDDevice/vendorId}} attribute is the [=vendor ID=] of the
device. If the device has no [=vendor ID=] or the [=vendor ID=]
cannot be accessed, the attribute MUST be 0.
The {{HIDDevice/vendorId}} getter steps are:
Return [=this=].{{HIDDevice/[[vendorId]]}}.
productId attribute
A product ID is an `unsigned short` value assigned by
the manufacturer of the device that identifies the product.
The {{HIDDevice/productId}} attribute is the [=product ID=] of the
device. If the device has no [=product ID=] or the [=product ID=]
cannot be accessed, the attribute MUST be 0.
The {{HIDDevice/productId}} getter steps are:
Return [=this=].{{HIDDevice/[[productId]]}}.
productName attribute
A string identifying the product.
For USB HID devices, the product name SHOULD contain the
value of the string descriptor at the index `iProduct` specified in
the Device Descriptor. For Bluetooth HID devices, the [=product
name=] SHOULD contain the value of the Device Name characteristic.
If the device has no [=product name=] or the [=product name=] is
empty or cannot be accessed, the attribute MUST return an empty
string.
The {{HIDDevice/productName}} string SHOULD NOT contain any
identifiers like a serial number or Bluetooth device address that
could be used to uniquely identify the device.
The {{HIDDevice/productName}} getter steps are:
Return [=this=].{{HIDDevice/[[productName]]}}.
collections attribute
A [=sequence=] of {{HIDCollectionInfo}} representing the
[=top-level collections=] in the [=report descriptor=].
The {{HIDDevice/collections}} getter steps are:
Return [=this=].{{HIDDevice/[[collections]]}}.
Top-level collections group items that serve similar
purposes within the device. Applications look at the [=HID usage=]
applied to [=top-level collections=] to identify devices. An
application may not recognize a device if it does not follow the
conventions for a particular type of device. Refer to
[[USBIF-HID-USAGE]] for more information about the conventional
behavior for standard HID devices.
When an input report is received from a |device:HIDDevice|, run the
following steps:
If the input report is a [=blocked report=], abort these steps.
Let |reportId:octet| be the report ID for this report, or 0 if the
[=HID interface=] does not [=use report IDs=].
Let |data:DataView| be a {{DataView}} created over the [=byte
sequence=] representing the input report. If the [=HID interface=]
[=uses report IDs=], the [=byte sequence=] MUST NOT include the report
ID byte.
[=Queue a global task=] on the [=relevant global object=] of
[=this=] using the [=HID device task source=] to [=fire an event=]
named {{inputreport}} at |device| using {{HIDInputReportEvent}} with
its {{HIDInputReportEvent/device}} attribute initialized to |device|,
its {{HIDInputReportEvent/reportId}} attribute initialized to
|reportId|, and its {{HIDInputReportEvent/data}} attribute initialized
to |data|.
open() method
The {{HIDDevice/open()}} method steps are:
Let |promise:Promise| be [=a new promise=].
If [=this=].{{HIDDevice/[[state]]}} is not `"closed"`, then
[=reject=] |promise| with a "{{InvalidStateError}}" {{DOMException}}
and return |promise|.
Set [=this=].{{HIDDevice/[[state]]}} to `"opening"`.
Perform the following steps [=in parallel=]:
Invoke the operating system to open the HID device.
If this fails for any reason, [=queue a global task=] on the
[=relevant global object=] of [=this=] using the [=HID device
task source=] to [=reject=] |promise| with a "{{NetworkError}}"
{{DOMException}} and abort these steps.
Set [=this=].{{HIDDevice/[[state]]}} to `"opened"`.
[=Queue a global task=] on the [=relevant global object=] of
[=this=] using the [=HID device task source=] to [=resolve=]
|promise| with `undefined`.
Return |promise|.
close() method
The {{HIDDevice/close()}} method steps are:
Let |promise:Promise| be [=a new promise=].
Set [=this=].{{HIDDevice/[[state]]}} to `"closing"`.
[=list/For each=] |pendingPromise:Promise| of
[=this=].{{HIDDevice/[[pendingSendReportPromises]]}}:
[=Reject=] |pendingPromise| with an "{{AbortError}}"
{{DOMException}}.
Invoke the operating system to close the HID device and
release any associated resources.
Set [=this=].{{HIDDevice/[[state]]}} to `"closed"`.
[=Queue a global task=] on the [=relevant global object=] of
[=this=] using the [=HID device task source=] to [=resolve=]
|promise| with `undefined`.
Return |promise|.
sendReport() method
The {{HIDDevice/sendReport()}} method is used to send an output
report with the specified |reportId:octet| and |data:BufferSource|.
If the [=HID interface=] does not [=use report IDs=], pass 0
instead of the report ID.
For [=HID interfaces=] that [=use report IDs=], the report ID value
0 is reserved and should not be used.
The {{HIDDevice/sendReport()}} method steps are:
Let |promise:Promise| be [=a new promise=].
If [=this=].{{HIDDevice/[[state]]}} is not `"opened"`, then
[=reject=] |promise| with a "{{InvalidStateError}}" {{DOMException}}
and return |promise|.
If |reportId:octet| is 0 and the [=HID interface=] represented by
[=this=] [=uses report IDs=], or if |reportId| is not 0 and the
interface does not [=use report IDs=], then [=reject=] |promise| with
a "{{TypeError}}" {{DOMException}} and return |promise|.
[=list/Append=] |promise| to
[=this=].{{HIDDevice/[[pendingSendReportPromises]]}}.
Perform the following steps [=in parallel=]:
If this report is a [=blocked report=], [=queue a global
task=] on the [=relevant global object=] of [=this=] using the
[=HID device task source=] to [=reject=] |promise| with a
"{{NotAllowedError}}" {{DOMException}} and abort these steps.
Invoke the operating system to send an output report with the
specified |reportId:octet| and |data:BufferSource|.
If this fails for any reason, [=queue a global task=] on the
[=relevant global object=] of [=this=] using the [=HID device
task source=] to [=reject=] |promise| with a "{{NetworkError}}"
{{DOMException}} and abort these steps.
[=Queue a global task=] on the [=relevant global object=] of
[=this=] using the [=HID device task source=] to [=resolve=]
|promise| with `undefined`.
Return |promise|.
sendFeatureReport() method
The {{HIDDevice/sendFeatureReport()}} method is used to send a
feature report with the specified |reportId:octet| and
|data:BufferSource|. If the [=HID interface=] does not [=use report
IDs=], pass 0 instead of the report ID.
For [=HID interfaces=] that [=use report IDs=], the report ID value
0 is reserved and should not be used.
The {{HIDDevice/sendFeatureReport()}} method steps are:
Let |promise:Promise| be [=a new promise=].
If [=this=].{{HIDDevice/[[state]]}} is not `"opened"`, then
[=reject=] |promise| with a "{{InvalidStateError}}" {{DOMException}}
and return |promise|.
If |reportId:octet| is 0 and the [=HID interface=] represented by
[=this=] [=uses report IDs=], or if |reportId| is not 0 and the
interface does not [=use report IDs=], then [=reject=] |promise| with
a "{{TypeError}}" {{DOMException}} and return |promise|.
[=list/Append=] |promise| to
[=this=].{{HIDDevice/[[pendingSendFeatureReportPromises]]}}.
Perform the following steps [=in parallel=]:
If this report is a [=blocked report=], [=queue a global
task=] on the [=relevant global object=] of [=this=] using the
[=HID device task source=] to [=reject=] |promise| with a
"{{NotAllowedError}}" {{DOMException}} and abort these steps.
Invoke the operating system to send a feature report with the
specified |reportId:octet| and |data:BufferSource|.
If this fails for any reason, [=queue a global task=] on the
[=relevant global object=] of [=this=] using the [=HID device
task source=] to [=reject=] |promise| with a "{{NetworkError}}"
{{DOMException}} and abort these steps.
[=Queue a global task=] on the [=relevant global object=] of
[=this=] using the [=HID device task source=] to [=resolve=]
|promise| with `undefined`.
Return |promise|.
receiveFeatureReport() method
The {{HIDDevice/receiveFeatureReport()}} method is used to request
a feature report with the specified |reportId:octet|. If the [=HID
interface=] does not [=use report IDs=], pass 0 instead of the
report ID.
For [=HID interfaces=] that [=use report IDs=], the report ID value
0 is reserved and should not be used.
The {{HIDDevice/receiveFeatureReport()}} method steps are:
Let |promise:Promise| be [=a new promise=].
If [=this=].{{HIDDevice/[[state]]}} is not `"opened"`, then
[=reject=] |promise| with a "{{InvalidStateError}}" {{DOMException}}
and return |promise|.
If |reportId:octet| is 0 and the [=HID interface=] represented by
[=this=] [=uses report IDs=], or if |reportId| is not 0 and the
interface does not [=use report IDs=], then [=reject=] |promise| with
a "{{TypeError}}" {{DOMException}} and return |promise|.
[=list/Append=] |promise| to
[=this=].{{HIDDevice/[[pendingReceiveFeatureReportPromises]]}}.
Perform the following steps [=in parallel=]:
If this report is a [=blocked report=], [=queue a global
task=] on the [=relevant global object=] of [=this=] using the
[=HID device task source=] to [=reject=] |promise| with a
"{{NotAllowedError}}" {{DOMException}} and abort these steps.
Let |data:DataView| be a {{DataView}} created over the [=byte
sequence=] representing the result of invoking the operating
system to read a feature report with the specified
|reportId:octet|.
|data| will contain whatever report data was received from
the operating system. If the device [=uses report IDs=] the
first byte may be the report ID. This byte is included
because the device may respond with other data in place of
the report ID.
If reading the feature report fails for any reason, [=queue a
global task=] on the [=relevant global object=] of [=this=] using
the [=HID device task source=] to [=reject=] |promise| with a
"{{NetworkError}}" {{DOMException}} and abort these steps.
[=Queue a global task=] on the [=relevant global object=] of
[=this=] using the [=HID device task source=] to [=resolve=]
|promise| with |data|.
The {{HIDDevice}} instance that represents the [=HID interface=] that
sent the input report.
reportId attribute
The one-byte identification prefix for this report, or 0 if the [=HID
interface=] does not [=use report IDs=].
data attribute
A {{DataView}} containing the data from the input report, excluding
the {{HIDInputReportEvent/reportId}} byte if the [=HID interface=]
[=uses report IDs=].
dictionary HIDCollectionInfo {
unsigned short usagePage;
unsigned short usage;
octet type;
sequence<HIDCollectionInfo> children;
sequence<HIDReportInfo> inputReports;
sequence<HIDReportInfo> outputReports;
sequence<HIDReportInfo> featureReports;
};
When a device is first connected to the system, the system MUST
retrieve the [=report descriptor=] for each [=HID interface=] exposed
by the device. The Report descriptor is a [=byte sequence=]
that can be expanded into a hierarchical data structure describing the
layout of each report supported by the device. The elements of this
data structure are called items. Groups of items that share a
relationship are called collections.
A {{HIDCollectionInfo}} object represents a single collection within
the [=report descriptor=]. When a collection contains nested
collections, the nested collections are included as elements of
{{HIDCollectionInfo/children}}.
The {{HIDCollectionInfo/inputReports}},
{{HIDCollectionInfo/outputReports}}, and
{{HIDCollectionInfo/featureReports}} attributes contain [=sequences=]
of {{HIDReportInfo}} that give information about each report described
within this collection. For a [=top-level collection=], the
{{HIDReportInfo}} represents a flattened view of all items that compose
the report. The flattened view interleaves items contained in nested
collections with items contained within the [=top-level collection=].
For a nested collection, the {{HIDReportInfo}} includes only the items
contained within the collection and its nested collections.
usagePage member
The [=usage page=] component of the [=HID usage=] associated with
this collection.
HID usages are constants that can be interpreted by an
application to identify the purpose and meaning of an item or
collection. A [=HID usage=] is an `unsigned long` value composed of
an `unsigned short` usage page in the high order bits
and an `unsigned short` usage ID in the low order bits.
Standard [=HID usage=] values are described in [[USBIF-HID-CLASS]]
and other documents published by the USB Implementers Forum.
The [=HID usages=] of the [=top-level collections=] exposed by the
device is used to identify the general device type.
usage member
The [=usage ID=] component of the [=HID usage=] associated with
this collection.
A [=usage ID=] is used to select an individual [=HID usage=] on a
[=usage page=]. By convention, [=usage IDs=] 0x01 through 0x1F are
reserved for [=top-level collections=].
type member
A value representing the [=collection type=].
[=Collection type=]
Value
Physical
0x00
Application
0x01
Logical
0x02
Report
0x03
Named Array
0x04
Usage Switch
0x05
Usage Modified
0x06
Reserved for future use
0x07 to 0x7F
Vendor-defined
0x80 to 0xFF
Each [=collection type=] describes a different type of relationship
among the grouped items. Refer to [[USBIF-HID-CLASS]] section
<IP_ADDRESS> for more information about [=collection types=].
children member
A [=sequence=] of {{HIDCollectionInfo}} representing the collections
nested within this collection.
inputReports member
A [=sequence=] of {{HIDReportInfo}} representing the input reports
described within this collection.
outputReports member
A [=sequence=] of {{HIDReportInfo}} representing the output reports
described within this collection.
featureReports member
A [=sequence=] of {{HIDReportInfo}} representing the feature reports
described within this collection.
A {{HIDReportInfo}} represents one input, output, or feature report
within the [=report descriptor=].
reportId member
A [=HID interface=] uses report
IDs if it prepends a one-byte identification prefix to each
report transfer. The {{HIDReportInfo/reportId}} member is the prefix
for this report if the interface [=uses report IDs=], or 0 otherwise.
items member
A [=sequence=] of {{HIDReportItem}} representing the fields of this
report.
`HIDReportItem` dictionary
dictionary HIDReportItem {
boolean isAbsolute;
boolean isArray;
boolean isBufferedBytes;
boolean isConstant;
boolean isLinear;
boolean isRange;
boolean isVolatile;
boolean hasNull;
boolean hasPreferredState;
boolean wrap;
sequence<unsigned long> usages;
unsigned long usageMinimum;
unsigned long usageMaximum;
unsigned short reportSize;
unsigned short reportCount;
byte unitExponent;
HIDUnitSystem unitSystem;
byte unitFactorLengthExponent;
byte unitFactorMassExponent;
byte unitFactorTimeExponent;
byte unitFactorTemperatureExponent;
byte unitFactorCurrentExponent;
byte unitFactorLuminousIntensityExponent;
long logicalMinimum;
long logicalMaximum;
long physicalMinimum;
long physicalMaximum;
sequence<DOMString> strings;
};
isAbsolute member
`true` if the data is absolute (based on a fixed origin), or `false`
if the data is relative (indicating the change in value from the last
report).
isArray member
`true` if the item creates array data fields in reports where each
data field contains an index corresponding to a pressed button or
key, or `false` if the item creates variable data fields in reports
where each data field contains a value.
isBufferedBytes member
`true` if the item emits a fixed-sized stream of bytes, or `false` if
the item is a numeric quantity.
isConstant member
`true` if the item is a static read-only field and cannot be
modified, or `false` if the item defines report fields that contain
modifiable device data.
isLinear member
`true` if the item represents a linear relationship between what is
measured and what is reported, or `false` if the data has been
processed in some way.
isRange member
`true` if the item assigns usages from a [=HID usage=] range defined
by {{HIDReportItem/usageMinimum}} and {{HIDReportItem/usageMaximum}},
or `false` if the item has a [=sequence=] of [=HID usage=] values in
{{HIDReportItem/usages}}.
isVolatile member
`true` if the item value can change without host interaction, or
`false` if the item value should only be changed by the host.
Only used for Feature and Output items.
hasNull member
`true` if the item has a null state in which it is not sending
meaningful data, or `false` if it does not have a null state. When in
a null state, the item will report a value outside of the specified
{{HIDReportItem/logicalMinimum}} and
{{HIDReportItem/logicalMaximum}}.
hasPreferredState member
`true` if the item has a preferred state to which it will return when
the user is not physically interacting with the control, or `false`
if the item does not have a preferred state.
wrap member
`true` if the item value rolls over when reaching either the extreme
high or low value, or `false` if the item value does not roll over.
usages member
If {{HIDReportItem/isRange}} is `true` or this item has no
associated [=HID usage=] values, then {{HIDReportItem/usages}} MUST
be undefined.
If {{HIDReportItem/isRange}} is `false` then
{{HIDReportItem/usages}} is a [=sequence=] of [=HID usage=] values
associated with this item.
usageMinimum member
If {{HIDReportItem/isRange}} is `true` then
{{HIDReportItem/usageMinimum}} contains the minimum [=HID usage=]
value in the usage range associated with this item.
If {{HIDReportItem/isRange}} is `false` then
{{HIDReportItem/usageMinimum}} MUST be undefined.
usageMaximum member
If {{HIDReportItem/isRange}} is `true` then
{{HIDReportItem/usageMaximum}} contains the maximum [=HID usage=]
value in the usage range associated with this item.
If {{HIDReportItem/isRange}} is `false` then
{{HIDReportItem/usageMaximum}} MUST be undefined.
reportSize member
The size of each report data field in bits. The
{{HIDReportItem/reportSize}} MUST be greater than 0.
reportCount member
The number of fields included in the report for this item. The
{{HIDReportItem/reportCount}} MUST be greater than 0.
unitExponent member
The value of the unit exponent, or 0 if the item has no unit
definition.
unitSystem member
A {{HIDUnitSystem}} enum value specifying the unit system for the
unit definition, or {{HIDUnitSystem/"none"}} if the item has no unit
definition.
unitFactorLengthExponent member
The value of the exponent for the length unit (centimeters, radians,
inch, or degrees) in the unit definition, or 0 if the item has no
unit definition.
unitFactorMassExponent member
The value of the exponent for the mass unit (gram or slug) in the
unit definition, or 0 if the item has no unit definition.
unitFactorTimeExponent member
The value of the exponent for the time unit (seconds) in the unit
definition, or 0 if the item has no unit definition.
unitFactorTemperatureExponent member
The value of the exponent for the temperature unit (Kelvin or degrees
Fahrenheit) in the unit definition, or 0 if the item has no unit
definition.
unitFactorCurrentExponent member
The value of the exponent for the electrical current unit (Ampere) in
the unit definition, or 0 if the item has no unit definition.
unitFactorLuminousIntensityExponent member
The value of the exponent for the luminous intensity unit (Candela)
in the unit definition, or 0 if the item has no unit definition.
logicalMinimum member
The minimum extent of this item in logical units. This is the minimum
value that a variable or array item will report.
logicalMaximum member
The maximum extent of this item in logical units. This is the maximum
value that a variable or array item wll report.
physicalMinimum member
The minimum value for the physical extent of this item. This
represents the {{HIDReportItem/logicalMinimum}} with units applied to
it.
physicalMaximum member
The maximum value for the physical extent of this item. This
represents the {{HIDReportItem/logicalMaximum}} with units applied to
it.
strings member
The strings associated with this item, or an empty [=sequence=] if no
strings are associated with this item.
HIDUnitSystem enum
[[USBIF-HID-CLASS]] section <IP_ADDRESS> defines four standard unit systems:
SI Linear, SI Rotation, English Linear, and English Rotation. Each item
uses one of these four unit systems, a vendor-defined unit system, or
no unit system.
No unit system. Indicates that the item does not have a unit
definition.
`"si-linear"`
The SI Linear unit system uses centimeter, gram, second, Kelvin,
Ampere, Candela.
`"si-rotation"`
The SI Rotation unit system uses radian, gram, second, Kelvin,
Ampere, Candela.
`"english-linear"`
The English Linear unit system uses inch, slug, second, degree
Fahrenheit, Ampere, Candela.
`"english-rotation"`
The English Rotation unit system uses degree, slug, second, degree
Fahrenheit, Ampere, Candela.
`"vendor-defined"`
A vendor-defined unit system.
`"reserved"`
Indicates that the device used a reserved value for its unit system.
Usage Examples
The HID Blocklist
This specification relies on a blocklist file in the https://github.com/WICG/webhid
repository to restrict the set of HID devices a website can access.
The result of parsing the blocklist at a URL |url| is a
[=sequence=] of dictionary objects produced by fetching |url| and
parsing its contents as JSON.
A report is a blocked report if the following steps return
`true`:
[=list/For each=] |rule| of the [=HID blocklist=]:
If the report is [=blocked by a blocklist rule=] |rule| then
return `true`.
Return `false`.
A report is blocked by a blocklist rule |rule| if the
following steps return `true`:
Let |reportId:octet| be the report ID of the report, or 0 if the
[=HID interface=] does not [=use report IDs=].
Let |reportType| be `"input"` if the report is an input report,
`"output"` if the report is an output report, or `"feature"` if the
report is a feature report.
Let |collection:HIDCollectionInfo| be the [=top-level collection=]
that contains the report.
If |rule| contains `"vendor"` and |rule|[`"vendor"`] is not
|device|.{{HIDDevice/vendorId}}, return `false`.
If |rule| contains `"product"` and |rule|[`"product"`] is not
|device|.{{HIDDevice/productId}}, return `false`.
If |rule| contains `"reportId"` and |rule|[`"reportId"`] is not
|reportId|, return `false`.
If |rule| contains `"reportType"` and |rule|[`"reportType"`] is not
|reportType|, return `false`.
If |rule| contains `"usagePage"` and |rule|[`"usagePage"`] is not
|collection|["{{HIDCollectionInfo/usagePage}}"], return `false`.
If |rule| contains `"usage"` and |rule|.[`"usage"`] is not
|collection|["{{HIDCollectionInfo/usage}}"], return `false`.
Return `true`.
Integrations
Permissions Policy
This specification defines a feature that controls whether the
{{Navigator/hid}} attribute is exposed on the {{Navigator}} object.
The feature name for this feature is `"hid"`.
The [=default allowlist=] for this feature is `'self'`.
Acknowledgements
The following people contributed to the development of this
document.


My hobbies and interests!
In order of how much I love doing them
Eating Ramen
Reading Tech/Hardware News
Playing Video Games
Watching College Hockey
Back to home


Face Detection
Detecting faces in images is the first step to a number of exciting facial recognition and emotion-prediction tasks. For
example, enabling a 1-1 in-store experience for loyal customers, powering apps that utilize a mobile camera,
or improving log-in security for known customers.
The Face Detection API enables you to detect one or more faces in an image, along with selected attributes such
as predicted age, gender, and the presence of other facial features. 27 landmark positions are also recorded
for each face identified.
{{errorMessage}}
Number of faces: {{ faces ? faces.length : 0 }}
{{ faces | json }}
Want to build this?


remoter-builder
/
remoter.builder
/
ServiceConnector
/
disconnectAll
disconnectAll
fun
disconnectAll
(
)
:
Unit
Disconnects from all the services that are returned from this


--- title: I am a Hero ---
you see, in this world there's two kinds of people, my friend: those with loaded guns and those who dig. you dig. this is the ak-47 assault rifle, the preferred weapon of your enemy.


AGW Website Mockup
ABOUT
OUR STORY
OUR COMMITMENT TO YOU
LOCATIONS
PRODUCTS
NEW ARRIVALS
FEATURED
TOP RATED
HIS
HERS
KIDS
ACCESSORIES
SPRING CATALOG
THE ESSENTIALS
SALE
BLOG
CONTACT


green color indicates A customer wins on more than 60% of their bets
| Customer | Event | Participant | Stake | Win |
|---|---|---|---|---|
| {{settle.Customer}} | {{settle.Event}} | {{settle.Participant}} | {{settle.Stake}} | {{settle.Win}} |
green color indicates All upcoming (i.e. unsettled) bets from customers that win at an unusual rate should be highlighted as risky
yellow color indicate Bets where the stake is more than 10 times higher than that customer’s average bet in their betting history should be highlighted as unusual
Bets where the stake is more than 30 times higher than that customer’s average bet in their betting history should be highlighted as highly unusual
| Customer | Event | Participant | Stake | To Win |
|---|---|---|---|---|
| {{settle.Customer}} | {{settle.Event}} | {{settle.Participant}} | {{settle.Stake}} | {{settle.ToWin}} |


With the newest Angular CLI (version 6, released 2018–04–03) and the new addition to Angular family — the Angular Elements package it’s extremely easy to create native custom elements.
If you don’t know what custom elements are or what is the connection to Angular, there are several great talks that introduce to these concepts, I highly encourage you to watch one of these.
So now, without further ado, let’s see some code!
1. Install Angular CLI 6 and initialize the project
npm i -g @angular/cli ng
new elements-demo --prefix custom
We’re not doing anything special yet, so all the normal ng new parameters apply, you could add sass or anything to the mix, but here we’ll stop at setting a custom prefix to, well, “custom”.
2. Add elements & polyfill
In order to have elements functionality available we need the Angular library and a polyfill — with the new CLI it’s just a matter of one(!) simple command:
ng add @angular/elements
3. Create a component
Let’s create one with Input and Output to see how they translate to custom elements that are understood by browsers:
ng g component button --inline-style --inline-template -v Native
We use ViewEncapsulation.Native so that the styles are bundled with the template and the component’s class into one file.
After adding some style & template our button.component.ts looks like this:
4. Registering component in NgModule
This is the vital part: we use the Angular’s createCustomElement function to create a class that can be used with browsers’ native customElements.define functionality.


Class: Seahorse::Client::Http::Headers
| Relationships & Source Files | |
| Super Chains via Extension / Inclusion / Inheritance | |
|
Instance Chain:
self,
Enumerable
|
|
| Inherits: | Object |
| Defined in: | gems/aws-sdk-core/lib/seahorse/client/http/headers.rb |
Overview
Provides a Hash-like interface for HTTP headers. Header names are treated indifferently as lower-cased strings. Header values are cast to strings.
headers = Http::Headers.new
headers['Content-Length'] = 100
headers[:Authorization] = 'Abc'
headers.keys
#=> ['content-length', 'authorization']
headers.values
#=> ['100', 'Abc']
You can get the header values as a vanilla hash by calling #to_h:
headers.to_h
#=> { 'content-length' => '100', 'authorization' => 'Abc' }
Instance Method Summary
- #[](key) ⇒ String
- #[]=(key, value)
- #clear
- #delete(key)
- #each {|key, value| ... } ⇒ nil (also: #each_pair)
-
#each_pair(&block)
Alias for #each.
-
#has_key?(key)
Alias for #key?.
-
#include?(key)
Alias for #key?.
- #key?(key) ⇒ Boolean (also: #has_key?, #include?)
- #keys ⇒ Array<String>
-
#to_h
Alias for #to_hash.
- #to_hash ⇒ Hash (also: #to_h)
- #update(headers) ⇒ Headers
- #values ⇒ Array<String>
- #values_at(*keys) ⇒ Array<String>
Instance Method Details
#[](key) ⇒ String
# File 'gems/aws-sdk-core/lib/seahorse/client/http/headers.rb', line 40
def [](key) @data[key.to_s.downcase] end
#[]=(key, value)
# File 'gems/aws-sdk-core/lib/seahorse/client/http/headers.rb', line 46
def []=(key, value) @data[key.to_s.downcase] = value.to_s end
#clear
[ GitHub ]# File 'gems/aws-sdk-core/lib/seahorse/client/http/headers.rb', line 64
def clear @data = {} end
#delete(key)
# File 'gems/aws-sdk-core/lib/seahorse/client/http/headers.rb', line 60
def delete(key) @data.delete(key.to_s.downcase) end
#each {|key, value| ... } ⇒ nil
Also known as: #each_pair
# File 'gems/aws-sdk-core/lib/seahorse/client/http/headers.rb', line 87
def each(&block) if block_given? @data.each_pair do |key, value| yield(key, value) end nil else @data.enum_for(:each) end end
#each_pair(&block)
Alias for #each.
# File 'gems/aws-sdk-core/lib/seahorse/client/http/headers.rb', line 97
alias each_pair each
#has_key?(key)
Alias for #key?.
# File 'gems/aws-sdk-core/lib/seahorse/client/http/headers.rb', line 103
alias has_key? key?
#include?(key)
Alias for #key?.
# File 'gems/aws-sdk-core/lib/seahorse/client/http/headers.rb', line 104
alias include? key?
#key?(key) ⇒ Boolean
Also known as: #has_key?, #include?
# File 'gems/aws-sdk-core/lib/seahorse/client/http/headers.rb', line 100
def key?(key) @data.key?(key.to_s.downcase) end
#keys ⇒ Array
<String
>
# File 'gems/aws-sdk-core/lib/seahorse/client/http/headers.rb', line 69
def keys @data.keys end
#to_h
Alias for #to_hash.
# File 'gems/aws-sdk-core/lib/seahorse/client/http/headers.rb', line 110
alias to_h to_hash
#to_hash ⇒ Hash
Also known as: #to_h
# File 'gems/aws-sdk-core/lib/seahorse/client/http/headers.rb', line 107
def to_hash @data.dup end
#update(headers) ⇒ Headers
# File 'gems/aws-sdk-core/lib/seahorse/client/http/headers.rb', line 52
def update(headers) headers.each_pair do |k, v| self[k] = v end self end
#values ⇒ Array
<String
>
# File 'gems/aws-sdk-core/lib/seahorse/client/http/headers.rb', line 74
def values @data.values end


The rugby evening headlines as English champions Saracens fined again and rising Welsh star cited
Another busy day in the rugby universe
by Matthew SouthcombeHere are you evening headlines for Tuesday, November 19.
Millard facing ban
Rising Cardiff Blues star Harri Millard has been cited following the region's win over Calvisano at the weekend.
The promising 23-year-old will be hauled in front of a judicial panel for allegedly striking Calvisano's Kayle Van Zyl with his foot during the Challenge Cup clash.
The hearing will take place tomorrow and determine whether or not the Welshman is guilty.
The offence carries a low end entry point of two weeks, mid-range of six weeks and a top end of 10 to 52 weeks.
Saracens hit with ANOTHER fine
It's been a tough few weeks for Saracens who have been slapped with another fine.
Recently, the defending English and European champions accepted a 35-point deduction and a £5.36 million fine for breaching salary cap regulations in the Gallagher Premiership.
After that furore was whipped up a few weeks back, Sarries didn't turn up to the European Champions Cup launch in Cardiff, as they are obliged to do.
As such, tournament organisers have slapped them with another undisclosed fine.
A statement from EPCR read: "Having previously indicated that they would be represented at the event, Saracens' failure to attend constituted a breach of the 2019-20 Heineken Champions Cup media rules, and compromised EPCR's ability to deliver the rights contracted to its broadcast, commercial and media partners."
"In light of this breach of its rules, EPCR has decided to impose a fine on Saracens which has been paid by the club, and the sum of which will remain undisclosed."
How to sign up to the Welsh Rugby Podcast
It's time for a new Wales regime, and the Welsh Rugby podcast is the place for all the inside information and debate.
We're recording twice every week and you can subscribe below to never miss out on the latest episode.
Subscribe today!
Apple: https://apple.co/2UA707b
All other devices: https://bit.ly/2yDFD3l
Ospreys sign Super Rugby talent
The Ospreys have signed former New Zealand Maori fly-half Marty McKenzie after losing star signing Gareth Anscombe for much of the season.
Anscombe is battling back from a serious knee injury that he suffered against England this summer, dashing his World Cup dreams, but is expected to miss most, if not all, of the season.
The Wales pivot was due to show up at the Liberty Stadium after this year's global gathering, but Ospreys fans will have to wait to see their star signing.
As such, the region have called in reinforcements and McKenzie, brother of All Blacks star Damian, will link up with the region immediately.
McKenzie joins the Ospreys until the end of the season.
Wayne Pivac names first Wales squad
New Wales boss Wayne Pivac has named the first squad of his tenure.
In it, he picks 22 players who featured for Wales at the Rugby World Cup and five uncapped players, including New Zealand-born Willis Halaholo and Johnny McNicholl.
Full details on the squad can be found here.


Functions to compute pair-wise dissimilarities (distance matrices) and multiple-site dissimilarities, separating the turnover and nestedness-resultant components of taxonomic (incidence and abundance based), functional and phylogenetic beta diversity.
| Version: | 1.5.1 |
| Imports: | ape, fastmatch, geometry, picante, rcdd |
| Suggests: | doParallel, foreach, vegan |
| Published: | 2018-10-18 |
| Author: | Andres Baselga [aut, cre], David Orme [aut], Sebastien Villeger [aut], Julien De Bortoli [aut], Fabien Leprieur [aut], Maxime Logez [ctb], Renato Henriques-Silva [ctb] |
| Maintainer: | Andres Baselga <andres.baselga at usc.es> |
| License: | GPL-2 | GPL-3 [expanded from: GPL (≥ 2)] |
| NeedsCompilation: | no |
| Materials: | NEWS |
| In views: | Phylogenetics |
| CRAN checks: | betapart results |
| Reference manual: | betapart.pdf |
| Package source: | betapart_1.5.1.tar.gz |
| Windows binaries: | r-devel: betapart_1.5.1.zip, r-release: betapart_1.5.1.zip, r-oldrel: betapart_1.5.1.zip |
| OS X binaries: | r-release: betapart_1.5.1.tgz, r-oldrel: betapart_1.5.1.tgz |
| Old sources: | betapart archive |
Please use the canonical form https://CRAN.R-project.org/package=betapart to link to this page.


{{competition_data['competition_detail_faq_overview']}}
{{competition_data['competition_detail_data_readme']}}
Evaluation
(of your latest code submission)Score
{{competition_data.user_submissions_detail.submission_score_display}}
Leader Board (Top 10)
{{competition_data['competition_detail_leaderboard_readme']}}
{% for submission_data in competition_data.top_submissions_detail %}
person
{{submission_data["team_name"]}} ({{submission_data["user_name"]}})
Score: {{submission_data["submission_score_display"]}}
{% endfor %}
{{competition_data['competition_detail_rules_readme']}}


Last updated: February 17, 2018
The information contained on http://www.edeqa.com website (the "Service") is for general information purposes only.
Waytous assumes no responsibility for errors or omissions in the contents on the Service.
In no event shall Edeqa be liable for any special, direct, indirect, consequential, or incidental damages or any damages whatsoever, whether in an action of contract, negligence or other tort, arising out of or in connection with the use of the Service or the contents of the Service. Edeqa reserves the right to make additions, deletions, or modification to the contents on the Service at any time without prior notice.
http://www.edeqa.com website may contain links to external websites that are not provided or maintained by or in any way affiliated with Edeqa.
Please note that Edeqa does not guarantee the accuracy, relevance, timeliness, or completeness of any information on these external websites.


No Bullshit Lab is a one-of-a-kind accelerator for makers and crafters, focused on developing innovative product ideas and helping them become promising companies.
Together with Nova SBE Venture Lab, one of the leading business schools in Europe, we developed a program crafted for hardware startups and your specific needs.
The accelerator is going to take place in NOW_, the biggest open co-working space in Europe, home to Lisbon Impact Hub and a 400sqm Tool shop. Here you will have access to tools like 3D Printers, CNCs, Laser Cutters, Electronics Benchs and a lot more!
We are not crazy about having a TON of partnerships, but we do care about the ones that matter and add value. Groupe Auchan is a retail conglomerate with 60B€+ revenue/year that are offering you the chance to streamline the process of testing and iterating your product in a real retail environment.
Kano
Latch
DRYE & PCH
2Mar Robotics


ll Congratulations, You have finished the game! You have a score of , hit targets and missed bullets . Would you like to add your score to the highscores? Add Shoot.kerm.is Level bullets remaining seconds remaining Score : Press space to continue → ← Press R to play again


[:page name="shutdownPlainView" args="reason"] [:include "/webapp/view/templates/head.html" /]
[= reason, encode: 'none']


info Shows submitted {{ ReportType.getPluralName(reportType) }} and their release statuses. Search by accession or unique name, or simply click search to show most recent submissions. The results will show the most recently submitted {{ReportType.getPluralName(reportType)}} in your submission account. Shows submitted {{ ReportType.getPluralName(reportType) }} and their archival statuses. Search by accession or other conditions, or simply click search to show most recent submissions. The results will show the most recently submitted {{ReportType.getPluralName(reportType)}} in your submission account. Shows the {{ ReportType.getPluralName(reportType) }}. Search by accession or other conditions, or simply click search to show most recent submissions. The results will show the {{ReportType.getPluralName(reportType)}} in your submission account. The primary use of this report is to retrieve sequence accessions assigned as part of genome assembly, transcriptome assembly or sequence flat file submissions. Shows uploaded files scheduled to be removed unless submitted by the expiration date. Uploaded files will only be included into the archive once they have been submitted either as runs or analyses. Note that unlike all other reports, the contents of this report may not be fully up to date. This report is refreshed at most once per day.
Please click search to see the results.
| {{ col }} | {{getElementValue(element, col)}} |
|
|
Action:
|
|---|


What is Blue and Gold Certification?
Blue and Gold Certification is a process through which engineering student organizations at Berkeley demonstrate their commitment to diversity, equity, and inclusion within their organizations. All certified organizations have attended several mandatory trainings, stripped exclusive requirements from their applications, and reflected on ways in which club culture at Berkeley can be improved for all students. In return, these organizations are given access to a wide range of benefits, including funding, publicity, and other resources.


import numpy as np
import gym
[docs]def state_dict_to_state_array(state_dict, state_array, state_names):
"""
Mapping of a passed state dictionary to a fitting state array.
This function is mainly used in the initialization phase to map a dictionary of passed state_name, state_value pairs
to a numpy state array with the entries of the state_dict at the corresponding places of the state_names.
Args:
state_dict(dict): Dictionary containing pairs of state_name, state_values for the state_array
state_array(iterable): Array into which the state_dict entries shall be passed
state_names(list/ndarray(str)): List of the state names.
"""
for ind, key in enumerate(state_names):
try:
state_array[ind] = state_dict[key]
except KeyError:
pass
[docs]def set_state_array(input_values, state_names):
"""
Setting of the input values to a valid state array with the shape of the physical systems state.
The input values can be passed as dict with state_name: value pairs or as list / ndarray. In the latter case the
shape of the list has to fit the state_names shape and the list will just be returned as array. If a float is
passed as input value, then this value will be set onto all positions of the state array equally.
Args:
input_values(dict(float) / list(float) / ndarray(float) / float): Values to be set onto the state array.
state_names(list(str)): List containing the state names of the physical system.
Returns:
An initialized state array with all values passed in input values set onto the corresponding position in
the state_names and zero otherwise.
"""
if type(input_values) is dict:
state_array = np.zeros_like(state_names, dtype=float)
state_dict_to_state_array(input_values, state_array, state_names)
elif type(input_values) is np.ndarray:
assert len(input_values) == len(state_names)
state_array = input_values
elif type(input_values) is list:
assert len(input_values) == len(state_names)
state_array = np.array(input_values)
elif type(input_values) is float or type(input_values) is int:
state_array = input_values * np.ones_like(state_names, dtype=float)
else:
raise Exception('Incorrect type for the input values.')
return state_array
[docs]def instantiate(superclass, instance, **kwargs):
"""
Instantiation of an instance that inherits from the passed superclass.
The instance can be passed as a key-string, a class pointer or an already instantiated object. In the latter case
the same object will be simply returned. If a string is passed the corresponding class will be taken from the
registry and instantiated with the given kwargs. If a class pointer is passed, then the class is instantiated with
with given kwargs, directly.
Args:
superclass(class): Superclass pointer for registry access
instance(str, class, object): Instance to instantiate
kwargs: Arguments for the instantiation of the object
Returns:
An instantiated object.
"""
if type(instance) is type and issubclass(instance, superclass):
return instance(**kwargs)
elif isinstance(instance, superclass):
return instance
elif type(instance) is str:
return make_module(superclass, instance, **kwargs)
else:
raise Exception('Instantiation Error.')
# Registry dictionary that stores the keys to instantiate the components with the keystrings
_registry = {}
[docs]def make_module(superclass, keystring, **kwargs):
"""
Instantiation by an object that is specified by the key-string an its superclass from the registry.
Args:
superclass(class): Superclass pointer for registry access
keystring(str): String to access the class pointer in the registry.
kwargs: Arguments for the instantiation of the object.
Returns:
An instantiated object.
"""
try:
return _registry[superclass][keystring](**kwargs)
except KeyError:
raise Exception(f'Key {keystring} or baseclass {superclass.__name__} not found in the registry.')
[docs]def register_superclass(superclass):
"""
Method to register a new superclass that can contain several key-strings for instantiation in the registry.
Basically, all superclasses in GEM are already registered like the Physical Systems, Reference Generators, ...
"""
_registry[superclass] = {}
[docs]def register_class(subclass, superclass, keystring):
"""
Method to register a new class with a key-string into the registry of the superclass
to be instantiable with the key-string.
"""
_registry[superclass][keystring] = subclass
#: Short notation for the gym.make call to avoid the necessary import of gym when making environments.
make = gym.make


Password Recovery for
A password is required.
Please enter a stronger password.
Please enter a more secure password.
The passwords don't match.


I feel like a toddler. My brain hurts and nothing makes sense. The internet insists on explaining things to me like I already know things. Dear Internet, I most certainly do not. I have included here the stuff that did make sense. May these humble building blocks aid you in your own pursuit of understanding.
Modules vs. Classes
From my blog post on the map method, a module is a way of grouping together methods, classes, and constants - a collection of reuseable code. A class, on the other hand, is a Ruby ‘thing’ (object) with a state and a behavior.
Quick define: superclass and subclass describe the relationship between classes. The subclass acquires the behaviors (methods) of the superclass. It’s a hierarchy. Super → top, sub → bottom.
| — | Modules | Classes |
|---|---|---|
| Definition | A collection of reuseable code. | A Ruby object with a state and a behavior. |
| Instantiation | No. | Yes. Class.new() |
| Inclusion | Include in classes or modules with the include command. A module can be included by multiple classes. |
No. |
| Inheritance | Does not do inheritance. | Can inherit methods from it’s superclass, can serve as a base for a subclass to inherit. |
| Purpose | A code container, good for organization. Provides methods that you can use across multiple classes. Use when you want to group things together that don’t naturally form a class. | To create instances of itself. |
| Contains | methods, constants, variables | methods, constants, variables |
| Syntax | module ModuleName .. end |
class ClassName .. end |
Namespace & Mixins
Stay with me, these terms require some exposition. This wonderfully fabulous article provides a great explanation. In fact, it’s so great that I’m going to include it here:
A good example of when the term ‘namespace’ becomes relevant is when you want to collaborate with other developers and share code.
(Nothing below here is mine)
Say you write a set of trigonometry functions sin, cos, and so on. You stuff them all into a file, trig.rb, for future generations to enjoy. Meanwhile, Sally is working on a simulation of good and evil, and codes up a set of her own useful routines, including beGood and sin, and sticks them into action.rb. Joe, who wants to write a program to find out how many angels can dance on the head of a pin, needs to load both trig.rb and action.rb into his program. But both define a method called sin. Bad news.
The answer is the module mechanism. Modules define a namespace, a sandbox in which your methods and constants can play without having to worry about being stepped on by other methods and constants. The trig functions can go into one module:
module Trig
PI = 3.141592654
def Trig.sin(x)
# ..
end
def Trig.cos(x)
# ..
end
end
and the good and bad action methods can go into another:
module Action
VERY_BAD = 0
BAD = 1
def Action.sin(badness)
# ...
end
end
Pretty awesome right?!
More awesomeness that isn’t mine: “A module can’t have instances, because a module isn’t a class. However, you can include a module within a class definition. When this happens, all the module’s instance methods are suddenly available as methods in the class as well. They get mixed in. In fact, mixed-in modules effectively behave as superclasses.”
There you go. Now you understand namespaces and mixins. If you don’t, email me and tell me I did a poor job of explaining it / stringing together internet examples. I will not be offended and will likely thank you for the feedback.


--- layout: post title: A Terrain Quilt date: 2012-02-19 11:18:24.000000000 -05:00 categories: - Celebrations - Craft - Quilts - Sewing tags: - Bella Solid Terrain Iris - Birthday quilt - Kate Spain - quilt - Terrain by Kate Spain status: publish type: post published: true meta: aktt_notify_twitter: 'no' _edit_last: '1' dsq_thread_id: '1188577643' author: login: cint email<EMAIL_ADDRESS>display_name: Jacinta first_name: Jacinta last_name: '' ---
I have been busy the last couple of days trying to get a quilt finished for a dear friend who turned 40 this week. Her party was last night, but I didn't quite get the quilt finished in time. But alas today, it is done. She loves purple and it seemed the Kate Spain Terrain charm packs I had stashed away had been waiting for just the right person, with it's lovely mix of purples and complimentary colours. Teamed with the solid purple (Bella solid Terrain Iris, by Moda), I am happy with how it has come together.
The design is my own, using two packs of charm squares and about 3 metres of the Bella Iris solid fabric. Unfortunately the lighting wasn't the best tonight and the purple is really hard to capture correctly. Of course the pictures I took showing the whole of the front and back turned out terribly, so will have to add some more pictures tomorrow.
[caption id="attachment_1482" align="aligncenter" width="600" caption="Front of quilt"][/caption]
[caption id="attachment_1483" align="aligncenter" width="600" caption="Back of quilt"][/caption]
Her party was so much fun and I managed to catch up with lots of lovely people who I don't get to see often. We were entertain with beautiful singing and music being played by her talented friends. Although, I must admit my late night has caught up with me tonight. I can hardly keep my eyes open. I hope you have had a beautiful weekend? Jacinta x


class Mercenary::Command
Attributes
Public Class Methods
Public: Creates a new Command
name - the name of the command parent - (optional) the instancce of Mercenary::Command
which you wish to
be the parent of this command
Returns nothing
# File lib/mercenary/command.rb, line 23 def initialize(name, parent = nil) @name = name @options = [] @commands = {} @actions = [] @map = {} @parent = parent @trace = false @aliases = [] end
Public Instance Methods
Public: Add an action Proc to be executed at runtime
block - the Proc to be executed at runtime
Returns nothing
# File lib/mercenary/command.rb, line 127 def action(&block) @actions << block end
Public: Add version and help options to the command
opts - instance of OptionParser
Returns nothing
# File lib/mercenary/command.rb, line 192 def add_default_options(opts) option "show_help", "-h", "--help", "Show this message" option "show_version", "-v", "--version", "Print the name and version" option "show_backtrace", "-t", "--trace", "Show the full backtrace when an error occurs" opts.on("-v", "--version", "Print the version") do puts "#{name} #{version}" exit(0) end opts.on("-t", "--trace", "Show full backtrace if an error occurs") do @trace = true end opts.on_tail("-h", "--help", "Show this message") do puts self exit end end
Public: Add an alias for this command's name to be attached to the parent
cmd_name - the name of the alias
Returns nothing
# File lib/mercenary/command.rb, line 116 def alias(cmd_name) logger.debug "adding alias to parent for self: '#{cmd_name}'" aliases << cmd_name @parent.commands[cmd_name] = self end
Public: Adds a subcommand
cmd_name - the name of the command block - a block accepting the new instance of Mercenary::Command
to be
modified (optional)
Returns nothing
# File lib/mercenary/command.rb, line 105 def command(cmd_name) cmd = Command.new(cmd_name, self) yield cmd @commands[cmd_name] = cmd end
Public: Sets the default command
command_name - the command name to be executed in the event no args are
present
Returns the default command if there is one, `nil` otherwise
# File lib/mercenary/command.rb, line 73 def default_command(command_name = nil) if command_name if commands.key?(command_name) @default_command = commands[command_name] if command_name @default_command else raise ArgumentError, "'#{command_name}' couldn't be found in this command's list of commands." end else @default_command end end
Public: Execute all actions given the inputted args and options
argv - (optional) command-line args (sans opts) config - (optional) the Hash configuration of string key to value
Returns nothing
# File lib/mercenary/command.rb, line 217 def execute(argv = [], config = {}) if actions.empty? && !default_command.nil? default_command.execute else actions.each { |a| a.call(argv, config) } end end
Public: Get the name of the current command plus that of
its parent commands
Returns the full name of the command
# File lib/mercenary/command.rb, line 253 def full_name the_name = [] the_name << parent.full_name if parent&.full_name the_name << name the_name.join(" ") end
Public: Run the command
argv - an array of string args opts - the instance of OptionParser config - the output config hash
Returns the command to be executed
# File lib/mercenary/command.rb, line 157 def go(argv, opts, config) opts.banner = "Usage: #{syntax}" process_options(opts, config) add_default_options(opts) if argv[0] && cmd = commands[argv[0].to_sym] logger.debug "Found subcommand '#{cmd.name}'" argv.shift cmd.go(argv, opts, config) else logger.debug "No additional command found, time to exec" self end end
Public: Check if this command has a subcommand
sub_command - the name of the subcommand
Returns true if this command is the parent of a command of name 'sub_command' and false otherwise
# File lib/mercenary/command.rb, line 231 def has_command?(sub_command) commands.key?(sub_command) end
Public: Identify this command
Returns a string which identifies this command
# File lib/mercenary/command.rb, line 238 def ident "<Command name=#{identity}>" end
Public: Get the full identity (name & version) of this command
Returns a string containing the name and version if it exists
# File lib/mercenary/command.rb, line 245 def identity "#{full_name} #{version}".strip end
Public: Fetch a Logger (stdlib)
level - the logger level (a Logger constant, see docs for more info)
Returns the instance of Logger
# File lib/mercenary/command.rb, line 137 def logger(level = nil) unless @logger @logger = Logger.new(STDOUT) @logger.level = level || Logger::INFO @logger.formatter = proc do |severity, _datetime, _progname, msg| "#{identity} | " << "#{severity.downcase.capitalize}:".ljust(7) << " #{msg}\n" end end @logger.level = level unless level.nil? @logger end
Public: Return all the names and aliases for this command.
Returns a comma-separated String list of the name followed by its aliases
# File lib/mercenary/command.rb, line 263 def names_and_aliases ([name.to_s] + aliases).compact.join(", ") end
Public: Adds an option switch
sym - the variable key which is used to identify the value of the switch
at runtime in the options hash
Returns nothing
# File lib/mercenary/command.rb, line 92 def option(sym, *options) new_option = Option.new(sym, options) @options << new_option @map[new_option] = sym end
Public: Add this command's options to OptionParser and set a default
action of setting the value of the option to the inputted hash
opts - instance of OptionParser config - the Hash in which the option values should be placed
Returns nothing
# File lib/mercenary/command.rb, line 179 def process_options(opts, config) options.each do |option| opts.on(*option.for_option_parser) do |x| config[map[option]] = x end end end
Public: Build a string containing a summary of the command
Returns a one-line summary of the command.
# File lib/mercenary/command.rb, line 270 def summarize " #{names_and_aliases.ljust(20)} #{description}" end
Public: Build a string containing the command name, options and any subcommands
Returns the string identifying this command, its options and its subcommands
# File lib/mercenary/command.rb, line 277 def to_s Presenter.new(self).print_command end
Public: Sets or gets the command version
version - the command version (optional)
Returns the version and sets it if an argument is non-nil
# File lib/mercenary/command.rb, line 39 def version(version = nil) @version = version if version @version end


BREAKING: INEC presents Certificates of Return to Lyon, APC lawmaker-elect
by https://www.facebook.com/CheerfulpraiseMike Odiegwu, Yenagoa
The Independent National Electoral Commission (INEC) has presented a Certificates of Return to the Bayelsa State Governor-Elect, Chief David Lyon.
Lyon of the All Progressives Congress (APC) defeated 44 candidates including the 7 Candidate of the Peoples Democratic Party (PDP), Senator Douye Diri, to win a keenly contested election.
The commission also presented a Certificate of Return to a member of the Bayelsa State House of Assembly representing Brass Constituency 1, Charles Daniel, whose supplementary election was concluded on November 16.
The State Resident Electoral Commissioner (REC), Pastor Monday Udoh, in his welcome address, said the election conducted by INEC was adjudged right in the eyes of the world.
He said the process, which started in May 2019, came with a lot of apprehension following fears of violence hinged on the outcome of previous elections in the state that were marred by violence and killings.
But he noted that through various engagements with stakeholders, civil society groups, alternative dispute mechanism and security agencies, the election was free, fair and credible.
He said despite pockets of skirmishes in some areas, no life was lost in the election.
Details shortly…


collapse allexpand all
Category V: Arts and Letters (ARLT)
- http://www.usc.edu/gecg
- For further registration information, please contact the department offering the course. Course descriptions are available at www.usc.edu/gecg
Introduction to the pleasures and power of poetry, exploring elements
drawn from high-points of English poetry, and the lives and works of major poets.
(Duplicates credit in ARLT 101g)
- General Education: This course satisfies the university's general education requirement.
- Note: Register for lecture and one discussion
| Section | Session | Type | Time | Days | Registered | Instructor | Location | Syllabus | Info |
|---|---|---|---|---|---|---|---|---|---|
| 32872R | 001 | Lecture | 2:00-3:20pm | Mon, Wed |
65 of 65 |
Dana Gioia | THH201 | ||
| 32860R | 001 | Discussion | 4:00-4:50pm | Monday | 22 of 25 | VKC154 | |||
| 32861R | 001 | Discussion | 5:00-5:50pm | Monday | 10 of 25 | VKC154 | |||
| 32853R | 001 | Discussion | 12:00-12:50pm | Wednesday | 7 of 25 | VKC154 | |||
| 32854R | 001 | Discussion | 1:00-1:50pm | Wednesday | 20 of 25 | SOSB48 | |||
| 32856R | 001 | Discussion | 11:00-11:50am | Thursday | 4 of 25 | VKC157 | |||
| 32857R | 001 | Discussion | 12:00-12:50pm | Thursday | 2 of 25 | THH121 |
An exploration of the culture, vibrance, heritage, mythology, variety,
and pathology of a city that was born in hopes and captured the worlds imagination.
Duplicates credit in ARLT 101g.
- General Education: This course satisfies the university's general education requirement.
- Note: Register for lecture and one discussion
| Section | Session | Type | Time | Days | Registered | Instructor | Location | Syllabus | Info |
|---|---|---|---|---|---|---|---|---|---|
| 32876R | 001 | Lecture | 10:00-11:50am | Mon, Wed | 59 of 65 | Thomas Gustafson | THH201 | ||
| 32891R | 001 | Discussion | 1:00-1:50pm | Tuesday | 10 of 25 | THHB9 | |||
| 32897R | 001 | Discussion | 12:00-12:50pm | Tuesday | 10 of 25 | THHB9 | |||
| 32890R | 001 | Discussion | 12:00-12:50pm | Thursday | 5 of 25 | THHB9 | |||
| 32892R | 001 | Discussion | 1:00-1:50pm | Thursday | 8 of 25 | THHB9 | |||
| 32895R | 001 | Discussion | 9:00-9:50am | Friday | 10 of 25 | MHP102 | |||
| 32896R | 001 | Discussion | 10:00-10:50am | Friday | 16 of 25 | MHP102 |
Critical study of controversial social issues such as abortion,
euthanasia, the death penalty, war and terrorism, sexual morality, affirmative action, and
economic justice.
- General Education: This course satisfies the university's general education requirement.
- Note: Register for lecture and one discussion
| Section | Session | Type | Time | Days | Registered | Instructor | Location | Syllabus | Info |
|---|---|---|---|---|---|---|---|---|---|
| 49374R | 001 | Lecture | 2:00-3:15pm | Tue, Thu | 86 of 100 | Mark Schroeder | SGM124 | ||
| 49375R | 001 | Discussion | 8:00-8:50am | Monday | 10 of 25 | MHP102 | |||
| 49376R | 001 | Discussion | 9:00-9:50am | Monday |
25 of 25 |
MHP102 | |||
| 49377R | 001 | Discussion | 8:00-8:50am | Wednesday | 12 of 25 | MHP102 | |||
| 49378R | 001 | Discussion | 9:00-9:50am | Wednesday |
25 of 25 |
MHP102 | |||
| 49379R | 001 | Discussion | 8:00-8:50am | Friday | 2 of 25 | VKC252 | |||
| 49380R | 001 | Discussion | 9:00-9:50am | Friday | 12 of 25 | WPH101 |
Explores the nature of justice, and how apparently conflicting ideals,
such as freedom and equality, are to be balanced within a just society.
- General Education: This course satisfies the university's general education requirement.
- Note: Register for lecture and one discussion
| Section | Session | Type | Time | Days | Registered | Instructor | Location | Syllabus | Info |
|---|---|---|---|---|---|---|---|---|---|
| 49401R | 001 | Lecture | 9:30-10:45am | Tue, Thu | 51 of 65 | Jonathan Quong | THH301 | ||
| 49402R | 001 | Discussion | 8:00-8:50am | Wednesday | 7 of 25 | THH112 | |||
| 49403R | 001 | Discussion | 9:00-9:50am | Wednesday | 11 of 25 | VKC157 | |||
| 49404R | 001 | Discussion | 10:00-10:50am | Wednesday | 18 of 25 | VKC157 | |||
| 49405R | 001 | Discussion | 8:00-8:50am | Friday | 3 of 25 | VKC157 | |||
| 49406R | 001 | Discussion | 9:00-9:50am | Friday | 2 of 25 | VKC201 | |||
| 49407R | 001 | Discussion | 10:00-10:50am | Friday | 10 of 25 | VKC201 |
Explores various conceptions of morality and what makes actions right or
wrong, together with the implications of these views for concrete ethical issues.
- General Education: This course satisfies the university's general education requirement.
- Note: Register for lecture and one discussion
| Section | Session | Type | Time | Days | Registered | Instructor | Location | Syllabus | Info |
|---|---|---|---|---|---|---|---|---|---|
| 49473R | 001 | Lecture | 2:00-3:15pm | Mon, Wed |
100 of 100 |
Jacob Ross | SAL101 | ||
| 49474R | 001 | Discussion | 8:00-8:50am | Tuesday | 13 of 25 | VKC157 | |||
| 49475R | 001 | Discussion | 9:00-9:50am | Tuesday | 22 of 25 | VKC157 | |||
| 49476R | 001 | Discussion | 10:00-10:50am | Tuesday |
25 of 25 |
MHP102 | |||
| 49477R | 001 | Discussion | 8:00-8:50am | Thursday | 7 of 25 | MHP102 | |||
| 49478R | 001 | Discussion | 9:00-9:50am | Thursday | 8 of 25 | MHP102 | |||
| 49479R | 001 | Discussion | 10:00-10:50am | Thursday |
25 of 25 |
MHP102 |
Dostoevsky's novels as psychological and philosophical analyses of modern
alienated man. Readings in Dostoevsky and selections from Gide, Kafka, Camus, and Sartre.
Conducted in English.
- General Education: This course satisfies the university's general education requirement.
| Section | Session | Type | Time | Days | Registered | Instructor | Location | Syllabus | Info |
|---|---|---|---|---|---|---|---|---|---|
| 60232D | 001 | Lecture | 12:30-1:50pm | Tue, Thu |
19 of 19 |
Greta Matzner-Gore | THH213 |
Theories of feminism; historical, social and cultural perspectives of the
women's movement in America, Europe, and in developing countries; men's roles in the
feminist movement.
- General Education: This course satisfies the university's general education requirement.
- Diversity: This course satisfies the university's diversity requirement.
- Note: This course carries GE credit but it is intended for a specific group of students rather than a general student audience. Gender Studies majors and minors can obtain D-clearance through the department.
| Section | Session | Type | Time | Days | Registered | Instructor | Location | Syllabus | Info |
|---|---|---|---|---|---|---|---|---|---|
| 34919D | 001 | Lecture-Discussion | 12:30-1:50pm | Tue, Thu | 8 of 19 | VKC106 | |||
| 34924R | 001 | Lecture | 4:00-5:50pm | Mon, Wed | 39 of 45 | MHP101 | |||
| 34925R | 001 | Discussion | 9:00-9:50am | Friday | 5 of 25 | THH215 | |||
| 34926R | 001 | Discussion | 10:00-10:50am | Friday | 20 of 25 | THH213 | |||
| 34928R | 001 | Discussion | 11:00-11:50am | Friday | 8 of 25 | VKC206 | |||
| 34929R | 001 | Discussion | 12:00-12:50pm | Friday | 5 of 25 | VKC205 | |||
| 34930R | 001 | Discussion | 2:00-2:50pm | Friday | 1 of 20 | THHB10 |


Four Volkswagen executives charged with embezzlement in Germany
The four accused were not named, but two were described as former board members
by AFP | PTIGerman prosecutors said Tuesday they have filed embezzlement charges against four Volkswagen executives for having accorded excessive salaries and bonuses to several members of an employees' council.
The action benefitting five members of the works council cost the car giant around 5.1 million euros ($5.6 million) in overpayments, prosecutors said.
Of the sum, the chairman of the council alone received 3.1 million euros in excessive pay or bonuses.
The four accused were not named, but two were described as former board members. The third is an ex-executive and the fourth a "current leading manager".
The case is the latest in a series of legal entanglements that Volkswagen is grappling with.
After it admitted four years ago to illegally fitting 11 million vehicles worldwide with software to make the cars seem less polluting, the German car giant has found itself battling a series of lawsuits.
Its top executives -- past and present -- have been charged with "market manipulation", while shareholders have launched a massive joint lawsuit seeking nine billion euros of damages.
Some 400,000 drivers' cases have also been bundled into a mammoth trial that began on September 30.


{% extends '_layouts/layout_ids.html' %} {% block page_title %}Manage and view your health information{{serviceName}}{% endblock %} {% block pageTitle %}Manage and view your health information{% endblock %} {% block content %}
To contine proving your ID, please enter your login details