1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * @fileoverview Interface for representing a low-level gnubby device.
7 */
8'use strict';
9
10/**
11 * Low level gnubby 'driver'. One per physical USB device.
12 * @interface
13 */
14function GnubbyDevice() {}
15
16// Commands of the USB interface.
17/** Echo data through local processor only */
18GnubbyDevice.CMD_PING = 0x81;
19/** Perform reset action and read ATR string */
20GnubbyDevice.CMD_ATR = 0x82;
21/** Send raw APDU */
22GnubbyDevice.CMD_APDU = 0x83;
23/** Send lock channel command */
24GnubbyDevice.CMD_LOCK = 0x84;
25/** Obtain system information record */
26GnubbyDevice.CMD_SYSINFO = 0x85;
27/** Obtain an unused channel ID */
28GnubbyDevice.CMD_INIT = 0x86;
29/** Control prompt flashing */
30GnubbyDevice.CMD_PROMPT = 0x87;
31/** Send device identification wink */
32GnubbyDevice.CMD_WINK = 0x88;
33/** USB test */
34GnubbyDevice.CMD_USB_TEST = 0xb9;
35/** Device Firmware Upgrade */
36GnubbyDevice.CMD_DFU = 0xba;
37/** Protocol resync command */
38GnubbyDevice.CMD_SYNC = 0xbc;
39/** Error response */
40GnubbyDevice.CMD_ERROR = 0xbf;
41
42// Low-level error codes.
43/** No error */
44GnubbyDevice.OK = 0;
45/** Invalid command */
46GnubbyDevice.INVALID_CMD = 1;
47/** Invalid parameter */
48GnubbyDevice.INVALID_PAR = 2;
49/** Invalid message length */
50GnubbyDevice.INVALID_LEN = 3;
51/** Invalid message sequencing */
52GnubbyDevice.INVALID_SEQ = 4;
53/** Message has timed out */
54GnubbyDevice.TIMEOUT = 5;
55/** CHannel is busy */
56GnubbyDevice.BUSY = 6;
57/** Access denied */
58GnubbyDevice.ACCESS_DENIED = 7;
59/** Device is gone */
60GnubbyDevice.GONE = 8;
61/** Verification error */
62GnubbyDevice.VERIFY_ERROR = 9;
63/** Command requires channel lock */
64GnubbyDevice.LOCK_REQUIRED = 10;
65/** Sync error */
66GnubbyDevice.SYNC_FAIL = 11;
67/** Other unspecified error */
68GnubbyDevice.OTHER = 127;
69
70// Remote helper errors.
71/** Not a remote helper */
72GnubbyDevice.NOTREMOTE = 263;
73/** Could not reach remote endpoint */
74GnubbyDevice.COULDNOTDIAL = 264;
75
76// chrome.usb-related errors.
77/** No device */
78GnubbyDevice.NODEVICE = 512;
79/** Permission denied */
80GnubbyDevice.NOPERMISSION = 666;
81
82/** Destroys this low-level device instance. */
83GnubbyDevice.prototype.destroy = function() {};
84
85/**
86 * Register a client for this gnubby.
87 * @param {*} who The client.
88 */
89GnubbyDevice.prototype.registerClient = function(who) {};
90
91/**
92 * De-register a client.
93 * @param {*} who The client.
94 * @return {number} The number of remaining listeners for this device, or -1
95 *     if this had no clients to start with.
96 */
97GnubbyDevice.prototype.deregisterClient = function(who) {};
98
99/**
100 * @param {*} who The client.
101 * @return {boolean} Whether this device has who as a client.
102 */
103GnubbyDevice.prototype.hasClient = function(who) {};
104
105/**
106 * Queue command to be sent.
107 * If queue was empty, initiate the write.
108 * @param {number} cid The client's channel ID.
109 * @param {number} cmd The command to send.
110 * @param {ArrayBuffer|Uint8Array} data Command data
111 */
112GnubbyDevice.prototype.queueCommand = function(cid, cmd, data) {};
113
114/**
115 * @typedef {{
116 *   vendorId: number,
117 *   productId: number
118 * }}
119 */
120var UsbDeviceSpec;
121
122/**
123 * Gets the list of USB devices permitted by this app.
124 * @param {function(!Array.<!UsbDeviceSpec>)} cb Called back with a list of USB
125 *     device specifiers.
126 */
127GnubbyDevice.getPermittedUsbDevices = function(cb) {
128  chrome.permissions.getAll(function(perms) {
129    if (!perms.hasOwnProperty('permissions')) {
130      cb([]);
131      return;
132    }
133    var devs = [];
134    var permissions = perms['permissions'];
135    for (var i = 0; i < permissions.length; i++) {
136      var permission = permissions[i];
137      if (typeof permission === 'object' &&
138          permission.hasOwnProperty('usbDevices')) {
139        for (var j = 0; j < permission['usbDevices'].length; j++) {
140          var dev = permission['usbDevices'][j];
141          devs.push(
142              {'vendorId': dev['vendorId'], 'productId': dev['productId']});
143        }
144      }
145    }
146    cb(devs);
147  });
148};
149