W3C

Web I2C API

Draft Report

This Version:
http://
Latest Published Version
http://
Previous Version:
None.
Editors:
Futomi Hatano ( 羽田野 ( はたの ) 太巳 ( ふとみ ) ), Newphoria
Masashi Honma ( 本間 ( ほんま ) 雅史 ( まさし ) ), プログラマ
Satoru Takagi ( 高木 ( たかぎ ) ( さとる ) ), KDDI

Abstract

This specification defines an API to enable web applications to access I2C (Inter-Integrated Circuit) interfaces as masters embedded in the underlying device.

Status of this document

This specification was published by the Browsers and Robotics Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.

1 Introduction

This section is non-normative.

The Web I2C API provides interfaces that web applications can access devices via I2C interfaces embedded in the underlying devices.

Using this API, web applications can communicate various devices connected via I2C interfaced, watch hardware interrupts, and so on.

This API is intended to be used under the mechanism which maintains the safety of the device by which this API operates and users using it. Note that this API is not intended to be used by web applications running on a general web browser without such considerations. As a mechanism for such consideration, there may be packaged applications having Privileged Contexts running on a browser runtime or web applications running on a browser in some kind of dedicated devices. [POWERFUL FEATURES]

2 Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in the normative parts of this document are to be interpreted as described in RFC2119. For readability, these words do not appear in all uppercase letters in this document. [RFC2119]

3 Terminology

The DOMExceptions interfaces is defined in the Web IDL specification. [WEBIDL]

The Promise is defined in ECMA-262 6th Edition. [ES6]

4 Example

This section is non-normative.

The following examples show common I2C usage in JavaScript. The variable I2C is a I2CAccess object in the examples blow.

4.1 Getting Access to the I2C

This example shows how to request access to the set of I2C interfaces on the underlying system.

var I2C = null;  // global I2CAccess object

navigator.requestI2CAccess().then(
    function(I2CAccess) {
        console.log("I2C ready!");
        I2C = I2CAccess; // store in the global
    },
    function(error) {
        console.log("Failed to get I2C access: " + error.message);
    }
);

4.2 Listing I2C ports

This example shows how to list the I2C ports available on the underlying operating system.

// get a I2CPortMap object
var ports = I2C.ports;

// show the detailed information for each port
ports.values(function(port) {
    console.log("* Port " + port.portNumber);
    console.log("  - Port name   : " + port.portName);
    console.log("  - PIN name    : " + port.pinName);
});

4.3 Getting a I2C port

This example shows how to get a I2C port.

var port = null;  // global I2CPort object

// get the I2CPort object representing the I2C port named "I2C18".
port = ports.get(2);

4.4 Listing I2C slaves

This example shows how to list the I2C slave devices connected on the specific I2C port.

[TBD]

4.5 Getting a slave device

This example shows how to get a I2C slave device.

var slaveDevice = null;
// Getting a slave device representing the slave address 0x40.
var slaveAddress = 0x40;
port.open(slaveAddress).then(
    function(I2CSlave) {
    	slaveDevice = I2CSlave; // store in global
    },
    function(error) {
        console.log("Failed to get a I2C slave device: " + error.message);
    }
);

4.6 Reading the value

This example shows how to read a value of a specified register(0x10) on a I2C slave device.

// read the eight bits value from a specified registar (0x10)
var readRegistar = 0x10;
window.setInterval(function() {
    slaveDevice.read8(readRegistar).then(readSuccess, I2CError);
}, 1000);

// the value successfully read
function readSuccess(value) {
    console.log(slaveAddress + ":" + readRegistar + ": " + value);
}

// Show an error
function I2CError(error) {
    console.log("Error: " + error.message + "(" + slaveAddress + ")");
}

4.7 Listening to changes of a spefific I2C slave device

This example shows how to listen to changes of a I2C slave values. In this example, the exported I2C port will be unexported in 60 seconds.

[TBD]

4.8 Writing a value

This example shows how to write a eight bits value of a specified register(0x11) on a I2C slave device. This example writes 0 or 1 one after the other to the I2C port 0x10 at a second interval.

// register number to write
var writeRegistar = 0x11;

// the value to be written
var v = 0;

writeValue();

function writeValue(){
	v = v ? 0 : 1;
	slaveDevice.write8(writeRegistar, v).then(writeSuccess, I2CError);
}

// the value successfully written
function writeSuccess(value) {
    console.log(slaveDevice.address + " : " + reg + " was set to " + value);
    window.setTimeout(writeValue, 1000);
}

// Show an error
function I2CError(error) {
    console.log("Error: " + error.message + "(" + slaveDevice.address + ")");
}

5 Interfaces

Although many functions return Promise, the some may be things sufficient by just returning an instance.

The policy of arbitration when two or more apps call these API is needed.

There are requests to treat also as streaming devices. Examination which enables it to use Streams is needed.

partial interface Navigator {
    Promise<I2CAccess> requestI2CAccess ();
};

The requestI2CAccess() method must be visible on the Navigator object if the script's global object is the Window object, or on the WorkerNavigator object if the script's global object is the WorkerUtils. [HTML5] [WEBWORKERS]

The requestI2CAccess() method is used to get a I2CAccess object. The requestI2CAccess() method is invoked, the user agent must run the steps as follows:

Is it proper that it belongs to Navigator instead of Generic Sensors API belongs to Window.

  1. Let promise be a new Promise object and resolver be its associated resolver.

  2. Return promise and run the following steps asynchronously.

  3. If the underlying operating system does not support I2C access, then jump to the step labeled failure below.

  4. Create a I2CPortMap object, then let map be the newly created I2CPortMap.

  5. Find all of the I2C ports available on the underlying operating system, then add it to the map.

    How can the UA find the I2C ports available on the underlying operating system?

  6. Create a I2CAccess object, then set the ports attribute to the map.

  7. Let access to be the newly created I2CAccess at the previous step.

  8. success: Call resolver's accept(value) method with access as value argument. Abort these steps.

  9. failure: Let error be a new DOMExceptions. This must be of type "NotSupportedError". Then call resolver's reject(value) method with error as value argument.

5.2 The I2CAccess interface

interface I2CAccess {
    readonly attribute I2CPortMap    ports;



};

The ports attribute must return the I2CPortMap object representing all of the I2C ports available on the underlying operating system.

5.3 The I2CPortMap interface

interface I2CPortMap {
             attribute readonly unsigned short size;
    function keys (void function (portNumber));
    function values (void function (I2CPort));
    I2CPort get(portNumber);
    I2CPort getByName(portName);

};

The size attributes is the number of I2C ports available on the underlying operating system at the current time.

The keys() method is an iterator for keys. The values() method is an iterator for values.

The get() method returnes a I2CPort object corresponding to portNumber.

The getByName() method returnes a I2CPort object corresponding to portName.

5.4 The I2CPort interface

interface I2CPort {

    Promise<I2CSlaveDevice> open(unsigned short I2CSlaveAddress);
    readonly attribute unsigned short portNumber;
    

};

The open() method is used to get I2CSlaveDevice object. When the open() method is invoked, the address number must be passed as the first argument. Otherwise, the open() method must return the I2CSlaveDevice corresponding to the specified address.

  1. Let promise be a new Promise object and resolver be its associated resolver.

  2. Return promise and run the following steps asynchronously.

  3. If the first argument is not specified, or it is not valid as a port number, or it does not represent any I2C slave device available on the underlying I2C port, then jump to the step labeled failure below.

  4. Create a I2CSlaveDevice object, then let map be the newly created I2CSlaveDevice.

  5. success: Call resolver's accept(value) method with access as value argument. Abort these steps.

  6. failure: Let error be a new DOMExceptions. This must be of type "NotSupportedError" or "OperationError". Then call resolver's reject(value) method with error as value argument.

5.5 The I2CSlaveDevice interface

I2CSlaveDevice object may be useful to applications programmers. On the other hand, probably there is no concept of slavedevice in the library on linux etc. which will serve as a base of webI2C. The realizability of an implementation should be checked.

interface I2CSlaveDevice {

    readonly attribute unsigned short slaveAddress;



    Promise  read8(unsigned short registerNumber);
    Promise  read16(unsigned short registerNumber);
    Promise  write8(unsigned short registerNumber, octet value);
    Promise  write16(unsigned short registerNumber, unsigned short value);

};

The I2CSlaveDevice interface represents a I2C slave device assigned to a I2C interface address.

The slaveAddress attribute must return the I2C address number assigned to the I2CSlaveDevice object.

The read8() method reads the value from the related I2C port. When the read8() method is invoked, the user agent must run the steps as follows:

  1. Let promise be a new Promise object and resolver be its associated resolver.

  2. Return promise and run the following steps asynchronously.

  3. Read the value of the assigned register of I2C slave device. If succeeded, let regiser value be the value. Otherwise, jump to the step labeled failure below.

  4. success: Call resolver's accept(value) method with regiser value as value argument. Abort these steps.

  5. failure: Let error be a new DOMExceptions. This must be of type "InvalidAccessError" or "OperatioError".

The write8() method writes the value passed as the first argument to the related I2C port. The value must be octet. When the write8() method is invoked, the user agent must run the steps as follows:

  1. Let promise be a new Promise object and resolver be its associated resolver.

  2. Return promise and run the following steps asynchronously.

  3. Let value be the value of the first argument passed to this method.

  4. If value is out of octet, jump to the step labeled failure below.

  5. write value to the assigned register. If succeeded, jump to the step labeled success below. Otherwise, jump to the step labeled failure below.

    In I2C, is the confirmation of having failed possible?

  6. success: Call resolver's accept(value) method with value as value argument. Abort these steps.

  7. failure: Let error be a new DOMExceptions. This must be of type "InvalidAccessError" or "OperatioError".

The read16() and the write16() are reading and writing methods for 16 bits. Each processing follows read8() and write8() except bits length.

Why is there read* write*? What is byte order?

We want Events in each slave devices. However, since I2C slave devices are various and unspecified, further investigation for designing general-purpose model is needed.

6 Security considerations

TBD

See Security and privacy considerations on [Generic Sensor API]

References

[DOM4]
DOM4, Anne van Kesteren, Aryeh Gregor, Ms2ger, Alex Russell, Robin Berjon. W3C.
[ES6]
ECMA-262 6th Edition. Ecma International.
[HTML5]
HTML5, Robin Berjon, Travis Leithead, Erika Doyle Navara, Edward O'Connor, Silvia Pfeiffer, Ian Hickson. W3C.
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels, S. Bradner. IETF.
[WEBIDL]
Web IDL, Cameron McCormack. W3C.
[WEBWORKERS]
Web Workers, Ian Hickson. W3C.
[STREAMS]
Streams API, Feras Moussa, Takeshi Yoshino. W3C.
[POWERFUL-FEATURES]
Mike West; Yan Zhu. Privileged Contexts. 24 April 2015. WD. URL: http://www.w3.org/TR/powerful-features/
[Generic Sensor API]
Generic Sensor API, Tobie Langel. Rick Waldron. W3C.

Acknowledgements

We would like to sincerely thank Rick Waldron, Much participants in a MozOpenHard project to acknowledge their contributions to this work.