OLD | NEW |
1 <h1>Accessing Hardware Devices</h1> | 1 <h1>Accessing Hardware Devices</h1> |
2 | 2 |
3 <p> | 3 <p> |
4 This doc shows you how packaged apps can connect to USB devices | 4 This doc shows you how packaged apps can connect to USB devices and read from |
5 and read from and write to a user's serial ports. | 5 and write to a user's serial ports. See also the reference docs for the <a |
6 See also the reference docs for the | 6 href="usb.html">USB API</a> and the <a href="serial.html">Serial API</a>. |
7 <a href="usb.html">USB API</a> | 7 The <a href="bluetooth.html">Bluetooth API</a> is also available; we've |
8 and the | 8 included a link to a Bluetooth sample below. |
9 <a href="serial.html">Serial API</a>. | |
10 The <a href="bluetooth.html">Bluetooth API</a> is also available; | |
11 we've include a link to a Bluetooth sample below. | |
12 </p> | 9 </p> |
13 | 10 |
14 <p class="note"> | 11 <p class="note"> |
15 <b>API Samples: </b> | 12 <b>API Samples: </b> Want to play with the code? Check out the |
16 Want to play with the code? | 13 <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/serial
">serial</a>, |
17 Check out the | 14 <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/servo"
>servo</a>, |
18 <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/serial">
serial</a>, | 15 <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/usb">u
sb</a>, |
19 <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/servo">s
ervo</a>, | 16 and |
20 <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/usb">usb
</a>, | 17 <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/zephyr
_hxm">zephyr_hxm |
21 and <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/zeph
yr_hxm">zephyr_hxm Bluetooth</a> samples. | 18 Bluetooth</a> samples. |
22 </p> | 19 </p> |
23 | 20 |
24 <h2 id="usb">Accessing USB devices</h2> | 21 <h2 id="usb">Accessing USB devices</h2> |
25 | 22 |
26 <p> | 23 <p> |
27 You can use the USB API to send messages to connected devices using only JavaScr
ipt code. Some devices are not accessible through this API - see the <a href="#c
aveats">Caveats section</a> below for more details. | 24 You can use the <a href="usb.html">USB API</a> to communicate with USB devices |
| 25 using only JavaScript code. Some devices are not accessible through this API |
| 26 – see <a href="#caveats">Caveats</a> below for details. |
| 27 </p> |
| 28 |
| 29 <p> |
| 30 For background information about USB, see the official |
| 31 <a href="http://www.usb.org/home">USB specifications</a>. <br/> |
| 32 <a href="http://www.beyondlogic.org/usbnutshell/usb1.shtml"> |
| 33 <i>USB in a NutShell</i></a> |
| 34 is a reasonable crash course that you may find helpful. |
28 </p> | 35 </p> |
29 | 36 |
30 <h3 id="manifest">Manifest requirement</h3> | 37 <h3 id="manifest">Manifest requirement</h3> |
31 | 38 |
32 <p> | 39 <p>The USB API requires the "usb" permission in the manifest file:</p> |
33 The USB API requires a special permission "usb" in the manifest file: | |
34 </p> | |
35 | 40 |
36 <pre> | 41 <pre> |
37 "permissions": [ | 42 "permissions": [ |
38 "usb" | 43 "usb" |
39 ] | 44 ] |
40 </pre> | 45 </pre> |
41 | 46 |
| 47 <p>In addition, in order to prevent |
| 48 <a href="http://en.wikipedia.org/wiki/Device_fingerprint">finger-printing</a>, |
| 49 you must declare all the device types you want to access in the manifest file. |
| 50 Each type of USB device corresponds to a vendor id/product id (VID/PID) pair. |
| 51 You can use $ref:usb.getDevices to enumerate devices by their VID/PID |
| 52 pair. |
| 53 </p> |
| 54 <p> |
| 55 You must declare the VID/PID pairs for each type of device you want to use |
| 56 under the "usbDevices" permission in your app's manifest file, as shown in the |
| 57 example below:</p> |
| 58 |
| 59 <pre> |
| 60 "permissions": [ |
| 61 "usbDevices": [ |
| 62 { |
| 63 "vendorId": 123, |
| 64 "productId": 456 |
| 65 } |
| 66 ] |
| 67 ] |
| 68 </pre> |
| 69 |
| 70 <p class="note">Note that only decimal numbers are allowed in JSON format. |
| 71 You cannot use hexadecimal numbers in these fields.</p> |
| 72 |
42 <h3 id="finding_device">Finding a device</h3> | 73 <h3 id="finding_device">Finding a device</h3> |
43 | 74 |
44 <p> | 75 <p> |
45 Every device in a USB bus is identified | 76 To determine whether one or more specific devices are connected to a user's |
46 by its vendor and product IDs. | 77 system, use the $ref:usb.getDevices method: |
47 To find a device, | 78 </p> |
48 use the <code>findDevices()</code> method | 79 |
49 which has two parameters: | 80 <pre> |
50 </p> | 81 chrome.usb.getDevices(enumerateDevicesOptions, callback); |
51 | 82 </pre> |
52 <pre> | 83 |
53 chrome.usb.findDevices(FindDeviceOptions, callback) | 84 <br/> |
54 </pre> | 85 |
55 | 86 <table class="simple"> |
56 <br> | 87 <tr> |
57 | 88 <th scope="col">Parameter (type)</th> |
58 <table class="simple"> | 89 <th scope="col">Description</th> |
59 <tr> | 90 </tr> |
60 <th scope="col"> Parameter (type) </th> | 91 <tr> |
61 <th scope="col"> Description </th> | 92 <td>EnumerateDevicesOptions (object)</td> |
62 </tr> | 93 <td>An object specifying both a <code>vendorId</code> (long) and |
63 <tr> | |
64 <td>FindDeviceOptions (object)</td> | |
65 <td>An object specifying both a <code>vendorId</code> (long) and | |
66 <code>productId</code> (long) used to find the correct type of device on | 94 <code>productId</code> (long) used to find the correct type of device on |
67 the bus. Your manifest must declare the<code>usbDevices</code> permission | 95 the bus. Your manifest must declare the <code>usbDevices</code> permission |
68 section listing all the <code>vendorId</code> and | 96 section listing all the <code>vendorId</code> and <code>deviceId</code> |
69 <code>deviceId</code> pairs your app wants to access. | 97 pairs your app wants to access. |
70 </td> | 98 </td> |
71 </tr> | 99 </tr> |
72 <tr> | 100 <tr> |
73 <td>callback (function)</td> | 101 <td>callback (function)</td> |
74 <td>Called when the device scan is finished. | 102 <td>Called when the device enumeration is finished. The callback will be |
75 The callback will be executed with one parameter, an array of device objec
ts | 103 executed with one parameter, an array of <code>Device</code> objects with |
76 with three properties: <code>handle</code>, | 104 three properties: <code>device</code>, <code>vendorId</code>, |
77 <code>vendorId</code>, | 105 <code>productId</code>. The device property is a stable identifier for a |
78 <code>productId</code>. If the optional permissions for this USB device | 106 connected device. It will not change until the device is unplugged. The |
79 were not declared in the extension manifest or the user did not consent | 107 detail of the identifier is opaque and subject to change. Do not rely on |
80 to the permissions requested, the parameter will be <code>null</code>. | 108 its current type. <br/> |
81 If no devices could be found, the array will be empty.</td> | 109 If no devices are found, the array will be empty. |
| 110 </td> |
82 </tr> | 111 </tr> |
83 </table> | 112 </table> |
84 | 113 |
85 <p> | 114 <p>Example:</p> |
86 Example: | 115 |
87 </p> | 116 <pre> |
88 | 117 function onDeviceFound(devices) { |
89 <pre> | 118 this.devices=devices; |
90 var onDeviceFound = function(devices) { | |
91 _this.devices=devices; | |
92 if (devices) { | 119 if (devices) { |
93 if (devices.length > 0) { | 120 if (devices.length > 0) { |
94 console.log("Device(s) found: "+devices.length); | 121 console.log("Device(s) found: "+devices.length); |
95 } else { | 122 } else { |
96 console.log("Device could not be found"); | 123 console.log("Device could not be found"); |
97 } | 124 } |
98 } else { | 125 } else { |
99 console.log("Did not request correct permissions"); | 126 console.log("Permission denied."); |
| 127 } |
| 128 } |
| 129 |
| 130 chrome.usb.getDevices({"vendorId": vendorId, "productId": productId}, onDeviceFo
und); |
| 131 </pre> |
| 132 |
| 133 <h3 id="usb_open">Opening a device</h3> |
| 134 <p> |
| 135 Once the <code>Device</code> objects are returned, you can open a device using |
| 136 usb.openDevice to obtain a connection handle. You can only |
| 137 communicate with USB devices using connection handles. |
| 138 </p> |
| 139 |
| 140 <table class="simple"> |
| 141 <tr> |
| 142 <th scope="col">Property</th> |
| 143 <th scope="col">Description</th> |
| 144 </tr> |
| 145 <tr> |
| 146 <td>device</td> |
| 147 <td>Object received in $ref:usb.getDevices callback.</td> |
| 148 </tr> |
| 149 <tr> |
| 150 <td>data (arraybuffer)</td> |
| 151 <td>Contains the data sent by the device if the transfer was inbound.</td> |
| 152 </tr> |
| 153 </table> |
| 154 |
| 155 <p>Example:</p> |
| 156 |
| 157 <pre> |
| 158 var usbConnection = null; |
| 159 var onOpenCallback = function(connection) { |
| 160 if (connection) { |
| 161 usbConnection = connection; |
| 162 console.log("Device opened."); |
| 163 } else { |
| 164 console.log("Device failed to open."); |
100 } | 165 } |
101 }; | 166 }; |
102 | 167 |
103 chrome.usb.findDevices({"vendorId": vendorId, "productId": productId}, onDeviceF
ound); | 168 chrome.usb.openDevice(device, onOpenCallback); |
| 169 </pre> |
| 170 |
| 171 <p class="note"> |
| 172 Not every device can be opened successfully. In general, operating systems |
| 173 lock down many types of USB interfaces (e.g. keyboards and mice, mass storage |
| 174 devices, webcams, etc.) and they cannot be claimed by user applications. |
| 175 On Linux (other than Chrome OS), once an interface of a device is locked down by |
| 176 the OS, the whole device is locked down (because all the interfaces shares the |
| 177 same device file), even if the other interfaces of the device can be used in |
| 178 theory. On Chrome OS, you can request access to unlocked interfaces using the |
| 179 $ref:usb.requestAccess method. If permitted, the permission broker will |
| 180 unlock the device file for you. |
| 181 </p> |
| 182 |
| 183 <p> |
| 184 To simplify the opening process, you can use the $ref:usb.findDevices |
| 185 method, which enumerates, requests access, and opens devices in one call: |
| 186 </p> |
| 187 |
| 188 <pre> |
| 189 chrome.usb.findDevices({"vendorId": vendorId, "productId": productId, "interface
Id": interfaceId}, callback); |
| 190 </pre> |
| 191 <p>which is equivalent to:</p> |
| 192 <pre> |
| 193 chrome.usb.getDevices({"vendorId": vendorId, "productId": productId}, function (
devices) { |
| 194 if (!devices) { |
| 195 console.log("Error enumerating devices."); |
| 196 callback(); |
| 197 return; |
| 198 } |
| 199 var connections = [], pendingAccessRequests = devices.length; |
| 200 devices.forEach(function (device) { |
| 201 chrome.usb.requestAccess(interfaceId, function () { |
| 202 // No need to check for errors at this point. |
| 203 // Nothing can be done if an error occurs anyway. You should always try |
| 204 // to open the device. |
| 205 chrome.usb.openDevices(device, function (connection) { |
| 206 if (connection) connections.push(connection); |
| 207 pendingAccessRequests--; |
| 208 if (pendingAccessRequests == 0) { |
| 209 callback(connections); |
| 210 } |
| 211 }); |
| 212 }); |
| 213 }) |
| 214 }); |
104 </pre> | 215 </pre> |
105 | 216 |
106 <h3 id="usb_transfers">USB transfers and receiving data from a device</h3> | 217 <h3 id="usb_transfers">USB transfers and receiving data from a device</h3> |
107 | 218 |
108 <p> | 219 <p> |
109 USB protocol defines four types of transfers: | 220 The USB protocol defines four types of transfers: |
110 <a href="#control_transfers">control</a>, <a href="#bulk_transfers">bulk</a>, <a
href="#isochronous_transfers">isochronous</a> and <a href="#interrupt_transfers
">interrupt</a>. | 221 <a href="#control_transfers">control</a>, |
111 Theoretically they can occur in both directions:<br> | 222 <a href="#bulk_transfers">bulk</a>, |
112 device-to-host (inbound) and host-to-device (outbound). | 223 <a href="#isochronous_transfers">isochronous</a> |
113 </p> | 224 and <a href="#interrupt_transfers">interrupt</a>. |
114 | 225 These transfers are described below. |
115 <p> | 226 </p> |
116 However, due to the nature of the USB protocol, both inbound and outbound messag
es must be initiated by the host (your computer). For inbound (device-to-host) m
essages, the host, your JavaScript code, sends a message flagged as "inbound" to
the device. The exact contents of the message depends on the device, but usuall
y will have some identification of what you are requesting from it. The device t
hen responds with the requested data. The device's response is handled by Chrome
and delivered asynchronously to the callback you specified in the transfer meth
od. | 227 |
117 An outbound (host-to-device) message is similar, but the response doesn't contai
n data returned from the device.</p> | 228 <p> |
118 | 229 Transfers can occur in both directions: device-to-host (inbound), and |
119 <p>For each message from the device, | 230 host-to-device (outbound). Due to the nature of the USB protocol, |
120 the specified callback will receive | 231 both inbound and outbound messages must be initiated by the host (the |
121 an event object with the following properties: | 232 computer that runs the Chrome app). |
| 233 For inbound (device-to-host) messages, the host (initiated by your JavaScript |
| 234 code) sends a message flagged as "inbound" to the device. |
| 235 The details of the message depend on the device, but usually will have |
| 236 some identification of what you are requesting from it. |
| 237 The device then responds with the requested data. |
| 238 The device's response is handled by Chrome and delivered asynchronously to the |
| 239 callback you specify in the transfer method. |
| 240 An outbound (host-to-device) message is similar, but the response doesn't |
| 241 contain data returned from the device. |
| 242 </p> |
| 243 |
| 244 <p> |
| 245 For each message from the device, the specified callback will receive an event |
| 246 object with the following properties: |
122 </p> | 247 </p> |
123 | 248 |
124 <br> | 249 <br> |
125 | 250 |
126 <table class="simple"> | 251 <table class="simple"> |
127 <tr> | 252 <tr> |
128 <th scope="col"> Property </th> | 253 <th scope="col">Property</th> |
129 <th scope="col"> Description </th> | 254 <th scope="col">Description</th> |
130 </tr> | 255 </tr> |
131 <tr> | 256 <tr> |
132 <td>resultCode (integer)</td> | 257 <td>resultCode (integer)</td> |
133 <td>0 is success; other values indicate failure. An error string can be read
from | 258 <td>0 is success; other values indicate failure. An error string can be<br/> |
134 <code>chrome.extension.lastError</code> when a failure is indicated.</td> | 259 read from <code>chrome.extension.lastError</code> when a failure is<br/> |
| 260 indicated. |
| 261 </td> |
135 </tr> | 262 </tr> |
136 <tr> | 263 <tr> |
137 <td>data (arraybuffer)</td> | 264 <td>data (arraybuffer)</td> |
138 <td>Contains the data sent by the device if transfer was inbound. | 265 <td>Contains the data sent by the device if the transfer was inbound.</td> |
139 </td> | |
140 </tr> | 266 </tr> |
141 </table> | 267 </table> |
142 | 268 |
143 <p> | 269 <p>Example:</p> |
144 Example: | |
145 </p> | |
146 | 270 |
147 <pre> | 271 <pre> |
148 var onTransferCallback = function(event) { | 272 var onTransferCallback = function(event) { |
149 if (event && event.resultCode === 0 && event.data) { | 273 if (event && event.resultCode === 0 && event.data) { |
150 console.log("got "+event.data.byteLength+" bytes"); | 274 console.log("got " + event.data.byteLength + " bytes"); |
151 } | 275 } |
152 }; | 276 }; |
153 | 277 |
154 chrome.usb.bulkTransfer(device, transferInfo, onTransferCallback); | 278 chrome.usb.bulkTransfer(connectionHandle, transferInfo, onTransferCallback); |
155 </pre> | 279 </pre> |
156 | 280 |
157 <h3 id="control_transfers">CONTROL transfers</h3> | 281 <h3 id="control_transfers">CONTROL transfers</h3> |
158 | 282 |
159 <p> | 283 <p>Control transfers are generally used to send or receive configuration or |
160 Control transfers are generally used to send or receive configuration | 284 command parameters to a USB device. The controlTransfer method always sends |
161 or command parameters to a USB device. | 285 to/reads from endpoint 0, and no claimInterface is required. |
162 The method is simple and receives three parameters: | 286 The method is simple and receives three parameters:</p> |
163 </p> | 287 |
164 | 288 <pre> |
165 <pre> | 289 chrome.usb.controlTransfer(connectionHandle, transferInfo, transferCallback) |
166 chrome.usb.controlTransfer(deviceObj, transferInfo, transferCallback) | |
167 </pre> | 290 </pre> |
168 | 291 |
169 <br> | 292 <br> |
170 | 293 |
171 <table class="simple"> | 294 <table class="simple"> |
172 <tr> | 295 <tr> |
173 <th scope="col"> Parameter (types)</th> | 296 <th scope="col">Parameter (types)</th> |
174 <th scope="col"> Description </th> | 297 <th scope="col">Description</th> |
175 </tr> | 298 </tr> |
176 <tr> | 299 <tr> |
177 <td>deviceObj</td> | 300 <td>connectionHandle</td> |
178 <td>Object sent in <code>findDevice()</code> callback.</td> | 301 <td>Object received in $ref:usb.openDevice callback. |
| 302 </td> |
179 </tr> | 303 </tr> |
180 <tr> | 304 <tr> |
181 <td>transferInfo</td> | 305 <td>transferInfo</td> |
182 <td>Parameter object with values from the table below. | 306 <td>Parameter object with values from the table below. Check your USB |
183 Check your USB device protocol specification for specifics.</td> | 307 device protocol specification for details. |
| 308 </td> |
184 </tr> | 309 </tr> |
185 <tr> | 310 <tr> |
186 <td>transferCallback()</td> | 311 <td>transferCallback()</td> |
187 <td>Invoked when the transfer has completed. | 312 <td>Invoked when the transfer has completed.</td> |
188 </td> | |
189 </tr> | 313 </tr> |
190 </table> | 314 </table> |
191 | 315 |
192 <p> | 316 <p> |
193 Values for <code>transferInfo</code> object: | 317 Values for |
194 </p> | 318 <code>transferInfo</code> |
195 | 319 object: |
196 <table class="simple"> | 320 </p> |
197 <tr> | 321 |
198 <th scope="col"> Value </th> | 322 <table class="simple"> |
199 <th scope="col"> Description </th> | 323 <tr> |
200 </tr> | 324 <th scope="col">Value</th> |
201 <tr> | 325 <th scope="col">Description</th> |
202 <td>requestType (string)</td> | 326 </tr> |
| 327 <tr> |
| 328 <td>requestType (string)</td> |
203 <td>"vendor", "standard", "class" or "reserved".</td> | 329 <td>"vendor", "standard", "class" or "reserved".</td> |
204 </tr> | 330 </tr> |
205 <tr> | 331 <tr> |
206 <td>recipient (string)</td> | 332 <td>recipient (string)</td> |
207 <td>"device", "interface", "endpoint" or "other".</td> | 333 <td>"device", "interface", "endpoint" or "other".</td> |
208 </tr> | 334 </tr> |
209 <tr> | 335 <tr> |
210 <td>direction (string)</td> | 336 <td>direction (string)</td> |
211 <td>"in" or "out". | 337 <td>"in" or "out". The "in" direction is used to notify the device that<br/> |
212 "in" direction is used to notify the device | 338 it should send information to the host. All communication on a USB<br/> |
213 that it should send information to the host. | 339 bus is host-initiated, so use an "in" transfer to allow a device to<br/> |
214 All communication in a USB bus is host-initiated, | 340 send information back. |
215 so use an 'in' transfer to allow a device | 341 </td> |
216 to send information back.</td> | 342 </tr> |
217 </tr> | 343 <tr> |
218 <tr> | 344 <td>request (integer)</td> |
219 <td>request (integer)</td> | |
220 <td>Defined by your device's protocol.</td> | 345 <td>Defined by your device's protocol.</td> |
221 </tr> | 346 </tr> |
222 <tr> | 347 <tr> |
223 <td>value (integer)</td> | 348 <td>value (integer)</td> |
224 <td>Defined by your device's protocol.</td> | 349 <td>Defined by your device's protocol.</td> |
225 </tr> | 350 </tr> |
226 <tr> | 351 <tr> |
227 <td>index (integer)</td> | 352 <td>index (integer)</td> |
228 <td>Defined by your device's protocol.</td> | 353 <td>Defined by your device's protocol.</td> |
229 </tr> | 354 </tr> |
230 <tr> | 355 <tr> |
231 <td>length (integer)</td> | 356 <td>length (integer)</td> |
232 <td>Only used when direction is "in". | 357 <td>Only used when direction is "in". Notifies the device that this is |
233 Notifies the device that this is the amount | 358 the amount of data the host is expecting in response. |
234 of data the host is expecting in response.</td> | 359 </td> |
235 </tr> | 360 </tr> |
236 <tr> | 361 <tr> |
237 <td>data (arraybuffer)</td> | 362 <td>data (arraybuffer)</td> |
238 <td>Defined by your device's protocol, | 363 <td>Defined by your device's protocol, required when direction is |
239 required when direction is "out".</td> | 364 "out". |
| 365 </td> |
240 </tr> | 366 </tr> |
241 </table> | 367 </table> |
242 | 368 |
243 <p> | 369 <p>Example:</p> |
244 Example: | |
245 </p> | |
246 | 370 |
247 <pre> | 371 <pre> |
248 var transferInfo = { | 372 var transferInfo = { |
249 "requestType": "vendor", | 373 "requestType": "vendor", |
250 "recipient": "device", | 374 "recipient": "device", |
251 "direction": "out", | 375 "direction": "out", |
252 "request": 0x31, | 376 "request": 0x31, |
253 "value": 120, | 377 "value": 120, |
254 "index": 0, | 378 "index": 0, |
255 "data": new Uint8Array([4, 8, 15, 16, 23, 42]).buffer | 379 // Note that the ArrayBuffer, not the TypedArray itself is used. |
256 }; | 380 "data": new Uint8Array([4, 8, 15, 16, 23, 42]).buffer |
257 chrome.usb.controlTransfer(deviceObj, transferInfo, optionalCallback); | 381 }; |
| 382 chrome.usb.controlTransfer(connectionHandle, transferInfo, optionalCallback); |
258 </pre> | 383 </pre> |
259 | 384 |
260 <h3 id="isochronous_transfers">ISOCHRONOUS transfers</h3> | 385 <h3 id="isochronous_transfers">ISOCHRONOUS transfers</h3> |
261 | 386 |
262 <p> | 387 <p>Isochronous transfers are the most complex type of USB transfer. They are |
263 Isochronous transfers is the most complex type of USB transfers. They are common
ly used for streams of data, like video and sound. To initiate an isochronous tr
ansfer (either inbound or outbound), you must use: | 388 commonly used for streams of data, like video and sound. To initiate an |
264 </p> | 389 isochronous transfer (either inbound or outbound), you must use |
265 | 390 the $ref:usb.isochronousTransfer method:</p> |
266 <pre> | 391 |
267 chrome.usb.isochronousTransfer(deviceObj, isochronousTransferInfo, transferCallb
ack) | 392 <pre> |
268 </pre> | 393 chrome.usb.isochronousTransfer(connectionHandle, isochronousTransferInfo, transf
erCallback) |
269 | 394 </pre> |
270 <br> | 395 |
271 | 396 <br/> |
272 <table class="simple"> | 397 |
273 <tr> | 398 <table class="simple"> |
274 <th scope="col"> Parameter </th> | 399 <tr> |
275 <th scope="col"> Description </th> | 400 <th scope="col">Parameter</th> |
276 </tr> | 401 <th scope="col">Description</th> |
277 <tr> | 402 </tr> |
278 <td>deviceObj</td> | 403 <tr> |
279 <td>Object sent on <code>findDevice()</code> callback.</td> | 404 <td>connectionHandle</td> |
| 405 <td>Object received in $ref:usb.openDevice callback. |
| 406 </td> |
280 </tr> | 407 </tr> |
281 <tr> | 408 <tr> |
282 <td>isochronousTransferInfo</td> | 409 <td>isochronousTransferInfo</td> |
283 <td>Parameter object with the values in the table below.</td> | 410 <td>Parameter object with the values in the table below.</td> |
284 </tr> | 411 </tr> |
285 <tr> | 412 <tr> |
286 <td>transferCallback()</td> | 413 <td>transferCallback()</td> |
287 <td>Invoked when the transfer has completed. | 414 <td>Invoked when the transfer has completed.</td> |
288 </td> | |
289 </tr> | 415 </tr> |
290 </table> | 416 </table> |
291 | 417 |
292 <p> | 418 <p> |
293 Values for <code>isochronousTransferInfo</code> object: | 419 Values for |
| 420 <code>isochronousTransferInfo</code> |
| 421 object: |
294 </p> | 422 </p> |
295 | 423 |
296 <table class="simple"> | 424 <table class="simple"> |
297 <tr> | 425 <tr> |
298 <th scope="col"> Value </th> | 426 <th scope="col">Value</th> |
299 <th scope="col"> Description </th> | 427 <th scope="col">Description</th> |
300 </tr> | 428 </tr> |
301 <tr> | 429 <tr> |
302 <td>transferInfo (object)</td> | 430 <td>transferInfo (object)</td> |
303 <td>An object with the following attributes:<br> | 431 <td>An object with the following attributes:<br/> |
304 <b>direction (string): </b>"in" or "out".<br> | 432 <b>direction (string): </b>"in" or "out".<br/> |
305 <b>endpoint (integer): </b>defined by your device. Usually can be found by
looking at an USB instrospection tool, like <code>lsusb -v</code><br> | 433 <b>endpoint (integer): </b>defined by your device. Usually can be found by |
306 <b>length (integer): </b>only used when direction is "in". | 434 looking at an USB instrospection tool, like <code>lsusb -v</code><br/> |
307 Notifies the device that this is the amount | 435 <b>length (integer): </b>only |
308 of data the host is expecting in response. Should be AT LEAST <code>packet
s * packetLength</code><br> | 436 used when direction is "in". Notifies the device that this is the amount |
| 437 of data the host is expecting in response. <br/> |
| 438 |
| 439 Should be AT LEAST <code>packets</code> × <code>packetLength</code>. |
| 440 <br/> |
309 <b>data (arraybuffer): </b>defined by your device's protocol; | 441 <b>data (arraybuffer): </b>defined by your device's protocol; |
310 only used when direction is "out". | 442 only used when direction is "out". |
311 </td> | 443 </td> |
312 </tr> | 444 </tr> |
313 <tr> | 445 <tr> |
314 <td>packets (integer)</td> | 446 <td>packets (integer)</td> |
315 <td>Total number of packets expected in this transfer.</td> | 447 <td>Total number of packets expected in this transfer.</td> |
316 </tr> | 448 </tr> |
317 <tr> | 449 <tr> |
318 <td>packetLength (integer)</td> | 450 <td>packetLength (integer)</td> |
319 <td>Expected length of each packet in this transfer.</td> | 451 <td>Expected length of each packet in this transfer.</td> |
320 </tr> | 452 </tr> |
321 </table> | 453 </table> |
322 | 454 |
323 <p> | 455 <p>Example:</p> |
324 Example: | |
325 </p> | |
326 | 456 |
327 <pre> | 457 <pre> |
328 var transferInfo = { | 458 var transferInfo = { |
329 "direction": "in", | 459 "direction": "in", |
330 "endpoint": 1, | 460 "endpoint": 1, |
331 "length": 2560 | 461 "length": 2560 |
332 }; | 462 }; |
| 463 |
333 var isoTransferInfo = { | 464 var isoTransferInfo = { |
334 "transferInfo": transferInfo, | 465 "transferInfo": transferInfo, |
335 "packets": 20, | 466 "packets": 20, |
336 "packetLength": 128 | 467 "packetLength": 128 |
337 }; | 468 }; |
338 chrome.usb.isochronousTransfer(deviceObj, isoTransferInfo, optionalCallback); | 469 |
| 470 chrome.usb.isochronousTransfer(connectionHandle, isoTransferInfo, optionalCallba
ck); |
339 </pre> | 471 </pre> |
340 | 472 |
341 <p> | 473 <p class="note"> |
342 <b>Notes:</b> One isochronous transfer will contain <code>isoTransferInfo.pack
ets</code> packets of <code>isoTransferInfo.packetLength</code> bytes. If it is
an inbound transfer (your code requested data from the device), the <code>data</
code> field in the onUsbEvent will be an ArrayBuffer of size <code>transferInfo.
length</code>. It is your duty to walk through this ArrayBuffer and extract the
different packets, each starting at a multiple of <code>isoTransferInfo.packetLe
ngth</code> bytes. If you are expecting a stream of data from the device, rememb
er that you will have to send one "inbound" transfer for each transfer you expec
t back. USB devices don't send transfers to the bus unless the host explicitly r
equests them through "inbound" transfers. | 474 <b>Notes:</b> One isochronous transfer will contain |
| 475 <code>isoTransferInfo.packets</code> packets of |
| 476 <code>isoTransferInfo.packetLength</code> bytes. |
| 477 If it is an inbound transfer (your code requested data from the device), the |
| 478 <code>data</code> field in the onUsbEvent will be an ArrayBuffer of size |
| 479 <code>transferInfo.length</code>. It is your duty to walk through this |
| 480 ArrayBuffer and extract the different packets, each starting at a multiple of |
| 481 <code>isoTransferInfo.packetLength</code> bytes. <br/> |
| 482 <br/> |
| 483 If you are expecting a stream of data from the device, remember that |
| 484 you will have to send one "inbound" transfer for each transfer you expect |
| 485 back. USB devices don't send transfers to the USB bus unless the host |
| 486 explicitly requests them through "inbound" transfers. |
343 </p> | 487 </p> |
344 | 488 |
345 <h3 id="bulk_transfers">BULK transfers</h3> | 489 <h3 id="bulk_transfers">BULK transfers</h3> |
346 | 490 |
347 <p> | 491 <p>Bulk transfers are commonly used to transfer a large amount of |
348 Bulk transfer is an USB transfer type commonly used | 492 non-time-sensitive data in a reliable way. |
349 to transfer a large amount of data in a reliable way. | 493 $ref:usb.bulkTransfer has three parameters:</p> |
350 The method has three parameters: | |
351 </p> | |
352 | 494 |
353 <pre> | 495 <pre> |
354 chrome.usb.bulkTransfer(deviceObj, transferInfo, transferCallback) | 496 chrome.usb.bulkTransfer(connectionHandle, transferInfo, transferCallback); |
355 </pre> | 497 </pre> |
356 | 498 |
357 <br> | 499 <br> |
358 | 500 |
359 <table class="simple"> | 501 <table class="simple"> |
360 <tr> | 502 <tr> |
361 <th scope="col"> Parameter </th> | 503 <th scope="col">Parameter</th> |
362 <th scope="col"> Description </th> | 504 <th scope="col">Description</th> |
363 </tr> | 505 </tr> |
364 <tr> | 506 <tr> |
365 <td>deviceObj</td> | 507 <td>connectionHandle</td> |
366 <td>Object sent on <code>findDevice()</code> callback.</td> | 508 <td>Object received in $ref:usb.openDevice callback. |
| 509 </td> |
367 </tr> | 510 </tr> |
368 <tr> | 511 <tr> |
369 <td>transferInfo</td> | 512 <td>transferInfo</td> |
370 <td>Parameter object with the values in the table below.</td> | 513 <td>Parameter object with the values in the table below.</td> |
371 </tr> | 514 </tr> |
372 <tr> | 515 <tr> |
373 <td>transferCallback</td> | 516 <td>transferCallback</td> |
374 <td>Invoked when the transfer has completed. | 517 <td>Invoked when the transfer has completed.</td> |
375 </td> | |
376 </tr> | 518 </tr> |
377 </table> | 519 </table> |
378 | 520 |
379 <p> | 521 <p> |
380 Values for <code>transferInfo</code> object: | 522 Values for |
| 523 <code>transferInfo</code> |
| 524 object: |
381 </p> | 525 </p> |
382 | 526 |
383 <table class="simple"> | 527 <table class="simple"> |
384 <tr> | 528 <tr> |
385 <th scope="col"> Value </th> | 529 <th scope="col">Value</th> |
386 <th scope="col"> Description </th> | 530 <th scope="col">Description</th> |
387 </tr> | 531 </tr> |
388 <tr> | 532 <tr> |
389 <td>direction (string)</td> | 533 <td>direction (string)</td> |
390 <td>"in" or "out".</td> | 534 <td>"in" or "out".</td> |
391 </tr> | 535 </tr> |
392 <tr> | 536 <tr> |
393 <td>endpoint (integer)</td> | 537 <td>endpoint (integer)</td> |
394 <td>Defined by your device's protocol.</td> | 538 <td>Defined by your device's protocol.</td> |
395 </tr> | 539 </tr> |
396 <tr> | 540 <tr> |
397 <td>length (integer)</td> | 541 <td>length (integer)</td> |
398 <td>Only used when direction is "in". | 542 <td>Only used when direction is "in". Notifies the device that this is |
399 Notifies the device that this is the amount | 543 the amount of data the host is expecting in response. |
400 of data the host is expecting in response.</td> | 544 </td> |
401 </tr> | 545 </tr> |
402 <tr> | 546 <tr> |
403 <td>data (ArrayBuffer)</td> | 547 <td>data (ArrayBuffer)</td> |
404 <td>Defined by your device's protocol; | 548 <td>Defined by your device's protocol; only used when direction is |
405 only used when direction is "out".</td> | 549 "out". |
| 550 </td> |
406 </tr> | 551 </tr> |
407 </table> | 552 </table> |
408 | 553 |
409 <p> | 554 <p>Example:</p> |
410 Example: | |
411 </p> | |
412 | 555 |
413 <pre> | 556 <pre> |
414 var transferInfo = { | 557 var transferInfo = { |
415 "direction": "out", | 558 "direction": "out", |
416 "endpoint": 1, | 559 "endpoint": 1, |
417 "data": new Uint8Array([4, 8, 15, 16, 23, 42]).buffer | 560 "data": new Uint8Array([4, 8, 15, 16, 23, 42]).buffer |
418 }; | 561 }; |
419 </pre> | 562 </pre> |
420 | 563 |
421 <h3 id="interrupt_transfers">INTERRUPT transfers</h3> | 564 <h3 id="interrupt_transfers">INTERRUPT transfers</h3> |
422 | 565 |
423 <p> | 566 <p>Interrupt transfers are used to small amount of time sensitive data. |
424 Interrupt transfers are used to send important notifications. | 567 Since all USB communication is initiated by the host, host code usually polls |
425 Since all USB communication is initiated by the host, | 568 the device periodically, sending interrupt IN transfers that will make the |
426 host code usually polls the device periodically, | 569 device send data back if there is anything in the interrupt queue (maintained |
427 sending interrupt IN transfers that will make the device send data back | 570 by the device). |
428 if there is anything in the interrupt queue. | 571 $ref:usb.interruptTransfer has three parameters:</p> |
429 The method has three parameters: | |
430 </p> | |
431 | 572 |
432 <pre> | 573 <pre> |
433 chrome.usb.interruptTransfer(deviceObj, transferInfo, transferCallback) | 574 chrome.usb.interruptTransfer(connectionHandle, transferInfo, transferCallback); |
434 </pre> | 575 </pre> |
435 | 576 |
436 <br> | 577 <br> |
437 | 578 |
438 <table class="simple"> | 579 <table class="simple"> |
439 <tr> | 580 <tr> |
440 <th scope="col"> Parameter </th> | 581 <th scope="col">Parameter</th> |
441 <th scope="col"> Description </th> | 582 <th scope="col">Description</th> |
442 </tr> | 583 </tr> |
443 <tr> | 584 <tr> |
444 <td>deviceObj</td> | 585 <td>connectionHandle</td> |
445 <td>Object sent on <code>findDevice()</code> callback.</td> | 586 <td>Object received in $ref:usb.openDevice callback. |
| 587 </td> |
446 </tr> | 588 </tr> |
447 <tr> | 589 <tr> |
448 <td>transferInfo</td> | 590 <td>transferInfo</td> |
449 <td>Parameter object with the values in the table below.</td> | 591 <td>Parameter object with the values in the table below.</td> |
450 </tr> | 592 </tr> |
451 <tr> | 593 <tr> |
452 <td>transferCallback</td> | 594 <td>transferCallback</td> |
453 <td>Invoked when the transfer has completed. | 595 <td>Invoked when the transfer has completed. Notice that this callback |
454 Notice that this callback doesn't contain the device's response. | 596 doesn't contain the device's response. The purpose of the callback is |
455 It's just to notify your code that the asynchronous transfer request | 597 simply to notify your code that the asynchronous transfer requests has |
456 has been processed and you can go ahead. | 598 been processed. |
457 The device's response, if any, will always be sent through | |
458 the <code>onEvent()</code> callback set on <code>findDevice()</code>. | |
459 </td> | 599 </td> |
460 </tr> | 600 </tr> |
461 </table> | 601 </table> |
462 | 602 |
463 <p> | 603 <p> |
464 Values for <code>transferInfo</code> object: | 604 Values for <code>transferInfo</code> object: |
465 </p> | 605 </p> |
466 | 606 |
467 <table class="simple"> | 607 <table class="simple"> |
468 <tr> | 608 <tr> |
469 <th scope="col"> Value </th> | 609 <th scope="col">Value</th> |
470 <th scope="col"> Description </th> | 610 <th scope="col">Description</th> |
471 </tr> | 611 </tr> |
472 <tr> | 612 <tr> |
473 <td>direction (string)</td> | 613 <td>direction (string)</td> |
474 <td>"in" or "out".</td> | 614 <td>"in" or "out".</td> |
475 </tr> | 615 </tr> |
476 <tr> | 616 <tr> |
477 <td>endpoint (integer)</td> | 617 <td>endpoint (integer)</td> |
478 <td>Defined by your device's protocol.</td> | 618 <td>Defined by your device's protocol.</td> |
479 </tr> | 619 </tr> |
480 <tr> | 620 <tr> |
481 <td>length (integer)</td> | 621 <td>length (integer)</td> |
482 <td>Only used when direction is "in". | 622 <td>Only used when direction is "in". Notifies the device that this is |
483 Notifies the device that this is the amount | 623 the amount of data the host is expecting in response. |
484 of data the host is expecting in response.</td> | 624 </td> |
485 </tr> | 625 </tr> |
486 <tr> | 626 <tr> |
487 <td>data (ArrayBuffer)</td> | 627 <td>data (ArrayBuffer)</td> |
488 <td>Defined by your device's protocol; | 628 <td>Defined by your device's protocol; only used when direction is |
489 only used when direction is "out".</td> | 629 "out". |
490 </tr> | 630 </td> |
| 631 </tr> |
| 632 </table> |
491 | 633 |
492 <p> | 634 <p>Example:</p> |
493 Example: | |
494 </p> | |
495 | 635 |
496 <pre> | 636 <pre> |
497 var transferInfo = { | 637 var transferInfo = { |
498 "direction": "in", | 638 "direction": "in", |
499 "endpoint": 1, | 639 "endpoint": 1, |
500 "length": 2 | 640 "length": 2 |
501 }; | 641 }; |
502 chrome.usb.interruptTransfer(deviceObj, transferInfo, optionalCallback); | 642 chrome.usb.interruptTransfer(connectionHandle, transferInfo, optionalCallback); |
503 </pre> | 643 </pre> |
504 | 644 |
505 <h3 id="caveats">Caveats</h3> | 645 <h3 id="caveats">Caveats</h3> |
506 | 646 |
| 647 <p>Not all devices can be accessed through the USB API. In general, devices |
| 648 are not accessible because either the Operating System's kernel or a native |
| 649 driver holds them off from user space code. Some examples are devices with |
| 650 HID profiles on OSX systems, and USB pen drives.</p> |
| 651 |
507 <p> | 652 <p> |
508 On most Linux systems, USB devices are mapped with read-only permissions by defa
ult. To access it through this API, your user will need to have write access too
. A simple solution is to set a udev rule. Create a file <code>/etc/udev/rules.d
/50-yourdevicename.rules</code> | 653 On most Linux systems, USB devices are mapped with read-only permissions by |
509 with the following content: | 654 default. To open a device through this API, your user will need to have |
| 655 write access to it too. |
| 656 A simple solution is to set a udev rule. Create a file |
| 657 <code>/etc/udev/rules.d/50-yourdevicename.rules</code> |
| 658 with the following content: |
510 </p> | 659 </p> |
511 | 660 |
512 <pre> | 661 <pre> |
513 SUBSYSTEM=="usb", ATTR{idVendor}=="[yourdevicevendor]", MODE="0664", GROUP="plug
dev" | 662 SUBSYSTEM=="usb", ATTR{idVendor}=="[yourdevicevendor]", MODE="0664", GROUP="plug
dev" |
514 </pre> | 663 </pre> |
515 | 664 |
516 <p> | 665 <p> |
517 Then, just restart the udev daemon: <code>service udev restart</code>. You can
check if the permissions are correctly set by: | 666 Then, just restart the udev daemon: <code>service udev restart</code>. |
518 <ul> | 667 You can check if device permissions are set correctly by following these |
519 <li>Find the bus and device numbers in <code>lsusb</code></li> | 668 steps: |
520 <li><code>ls -al /dev/bus/usb/[bus]/[device]</code>. This file should be own
ed by group "plugdev" and have group write permissions.</li> | |
521 </ul> | |
522 </p> | 669 </p> |
523 | 670 |
524 <p> | 671 <ul> |
525 Not all devices can be accessed through this API. In general, devices are not
accessible either because the Operating System's kernel or a native driver holds
them off from user space code. Some examples are devices with HID profiles on O
SX systems and USB pen drives. | 672 <li>Run <code>lsusb</code> to find the bus and device numbers.</li> |
526 </p> | 673 <li>Run <code>ls -al /dev/bus/usb/[bus]/[device]</code>. This file should be |
| 674 owned by group "plugdev" and have group write permissions. |
| 675 </li> |
| 676 </ul> |
| 677 |
| 678 <p>Your app cannot do this automatically since this this procedure requires root |
| 679 access. We recommend that you provide instructions to end-users and link to the |
| 680 <a href="#caveats">Caveats</a> section on this page for an explanation.</p> |
| 681 |
| 682 <p>On Chrome OS, simply call $ref:usb.requestAccess. The permission |
| 683 broker does this for you.</p> |
527 | 684 |
528 <h2 id="serial">Accessing serial devices</h2> | 685 <h2 id="serial">Accessing serial devices</h2> |
529 | 686 |
530 <p> | 687 <p> |
531 You can use the serial API to read | 688 You can use the serial API to read |
532 and write from a serial device. | 689 and write from a serial device. |
533 </p> | 690 </p> |
534 | 691 |
535 <h3 id="requirement">Manifest requirement</h3> | 692 <h3 id="requirement">Manifest requirement</h3> |
536 | 693 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 _this.connectionId = connectionInfo.connectionId; | 754 _this.connectionId = connectionInfo.connectionId; |
598 // Do whatever you need to do with the opened port. | 755 // Do whatever you need to do with the opened port. |
599 } | 756 } |
600 // Open the serial port /dev/ttyS01 | 757 // Open the serial port /dev/ttyS01 |
601 chrome.serial.open("/dev/ttyS01", {bitrate: 115200}, onOpen); | 758 chrome.serial.open("/dev/ttyS01", {bitrate: 115200}, onOpen); |
602 </pre> | 759 </pre> |
603 | 760 |
604 <h3 id="closing">Closing a serial port</h3> | 761 <h3 id="closing">Closing a serial port</h3> |
605 | 762 |
606 <p> | 763 <p> |
607 Closing a serial port is simple but very important. See the example below: | 764 Closing a serial port is simple but very important. See the example below: |
608 </p> | 765 </p> |
609 | 766 |
610 <pre> | 767 <pre> |
611 var onClose = function(result) { | 768 var onClose = function(result) { |
612 console.log("Serial port closed"); | 769 console.log("Serial port closed"); |
613 } | 770 } |
614 chrome.serial.close(connectionId, onClose); | 771 chrome.serial.close(connectionId, onClose); |
615 </pre> | 772 </pre> |
616 | 773 |
617 <h3 id="reading">Reading from a serial port</h3> | 774 <h3 id="reading">Reading from a serial port</h3> |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
680 | 837 |
681 <p> | 838 <p> |
682 You can flush your serial port buffer by issuing the flush command: | 839 You can flush your serial port buffer by issuing the flush command: |
683 </p> | 840 </p> |
684 | 841 |
685 <pre> | 842 <pre> |
686 chrome.serial.flush(connectionId, onFlush); | 843 chrome.serial.flush(connectionId, onFlush); |
687 </pre> | 844 </pre> |
688 | 845 |
689 <p class="backtotop"><a href="#top">Back to top</a></p> | 846 <p class="backtotop"><a href="#top">Back to top</a></p> |
OLD | NEW |