| OLD | NEW |
| (Empty) |
| 1 <h1>Accessing Hardware Devices</h1> | |
| 2 | |
| 3 <p> | |
| 4 This doc shows you how Chrome Apps can connect to USB devices and read from | |
| 5 and write to a user's serial ports. See also the reference docs for the <a | |
| 6 href="usb.html">USB API</a> and the <a href="serial.html">Serial API</a>. | |
| 7 The <a href="bluetooth.html">Bluetooth API</a> is also available; we've | |
| 8 included a link to a Bluetooth sample below. | |
| 9 </p> | |
| 10 | |
| 11 <p class="note"> | |
| 12 <b>API Samples: </b> Want to play with the code? Check out the | |
| 13 <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/serial
">serial</a>, | |
| 14 <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/servo"
>servo</a>, | |
| 15 <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/usb">u
sb</a>, | |
| 16 and | |
| 17 <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/zephyr
_hxm">zephyr_hxm | |
| 18 Bluetooth</a> samples. | |
| 19 </p> | |
| 20 | |
| 21 <h2 id="usb">Accessing USB devices</h2> | |
| 22 | |
| 23 <p> | |
| 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. | |
| 35 </p> | |
| 36 | |
| 37 <h3 id="manifest">Manifest requirement</h3> | |
| 38 | |
| 39 <p>The USB API requires the "usb" permission in the manifest file:</p> | |
| 40 | |
| 41 <pre data-filename="manifest.json"> | |
| 42 "permissions": [ | |
| 43 "usb" | |
| 44 ] | |
| 45 </pre> | |
| 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 data-filename="manifest.json"> | |
| 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 | |
| 73 <h3 id="finding_device">Finding a device</h3> | |
| 74 | |
| 75 <p> | |
| 76 To determine whether one or more specific devices are connected to a user's | |
| 77 system, use the $ref:usb.getDevices method: | |
| 78 </p> | |
| 79 | |
| 80 <pre> | |
| 81 chrome.usb.getDevices(enumerateDevicesOptions, callback); | |
| 82 </pre> | |
| 83 | |
| 84 <br/> | |
| 85 | |
| 86 <table class="simple"> | |
| 87 <tr> | |
| 88 <th scope="col">Parameter (type)</th> | |
| 89 <th scope="col">Description</th> | |
| 90 </tr> | |
| 91 <tr> | |
| 92 <td>EnumerateDevicesOptions (object)</td> | |
| 93 <td>An object specifying both a <code>vendorId</code> (long) and | |
| 94 <code>productId</code> (long) used to find the correct type of device on | |
| 95 the bus. Your manifest must declare the <code>usbDevices</code> permission | |
| 96 section listing all the <code>vendorId</code> and <code>deviceId</code> | |
| 97 pairs your app wants to access. | |
| 98 </td> | |
| 99 </tr> | |
| 100 <tr> | |
| 101 <td>callback (function)</td> | |
| 102 <td>Called when the device enumeration is finished. The callback will be | |
| 103 executed with one parameter, an array of <code>Device</code> objects with | |
| 104 three properties: <code>device</code>, <code>vendorId</code>, | |
| 105 <code>productId</code>. The device property is a stable identifier for a | |
| 106 connected device. It will not change until the device is unplugged. The | |
| 107 detail of the identifier is opaque and subject to change. Do not rely on | |
| 108 its current type. <br/> | |
| 109 If no devices are found, the array will be empty. | |
| 110 </td> | |
| 111 </tr> | |
| 112 </table> | |
| 113 | |
| 114 <p>Example:</p> | |
| 115 | |
| 116 <pre> | |
| 117 function onDeviceFound(devices) { | |
| 118 this.devices=devices; | |
| 119 if (devices) { | |
| 120 if (devices.length > 0) { | |
| 121 console.log("Device(s) found: "+devices.length); | |
| 122 } else { | |
| 123 console.log("Device could not be found"); | |
| 124 } | |
| 125 } else { | |
| 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."); | |
| 165 } | |
| 166 }; | |
| 167 | |
| 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 }); | |
| 215 </pre> | |
| 216 | |
| 217 <h3 id="usb_transfers">USB transfers and receiving data from a device</h3> | |
| 218 | |
| 219 <p> | |
| 220 The USB protocol defines four types of transfers: | |
| 221 <a href="#control_transfers">control</a>, | |
| 222 <a href="#bulk_transfers">bulk</a>, | |
| 223 <a href="#isochronous_transfers">isochronous</a> | |
| 224 and <a href="#interrupt_transfers">interrupt</a>. | |
| 225 These transfers are described below. | |
| 226 </p> | |
| 227 | |
| 228 <p> | |
| 229 Transfers can occur in both directions: device-to-host (inbound), and | |
| 230 host-to-device (outbound). Due to the nature of the USB protocol, | |
| 231 both inbound and outbound messages must be initiated by the host (the | |
| 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: | |
| 247 </p> | |
| 248 | |
| 249 <br> | |
| 250 | |
| 251 <table class="simple"> | |
| 252 <tr> | |
| 253 <th scope="col">Property</th> | |
| 254 <th scope="col">Description</th> | |
| 255 </tr> | |
| 256 <tr> | |
| 257 <td>resultCode (integer)</td> | |
| 258 <td>0 is success; other values indicate failure. An error string can be<br/> | |
| 259 read from <code>chrome.extension.lastError</code> when a failure is<br/> | |
| 260 indicated. | |
| 261 </td> | |
| 262 </tr> | |
| 263 <tr> | |
| 264 <td>data (arraybuffer)</td> | |
| 265 <td>Contains the data sent by the device if the transfer was inbound.</td> | |
| 266 </tr> | |
| 267 </table> | |
| 268 | |
| 269 <p>Example:</p> | |
| 270 | |
| 271 <pre> | |
| 272 var onTransferCallback = function(event) { | |
| 273 if (event && event.resultCode === 0 && event.data) { | |
| 274 console.log("got " + event.data.byteLength + " bytes"); | |
| 275 } | |
| 276 }; | |
| 277 | |
| 278 chrome.usb.bulkTransfer(connectionHandle, transferInfo, onTransferCallback); | |
| 279 </pre> | |
| 280 | |
| 281 <h3 id="control_transfers">CONTROL transfers</h3> | |
| 282 | |
| 283 <p>Control transfers are generally used to send or receive configuration or | |
| 284 command parameters to a USB device. The controlTransfer method always sends | |
| 285 to/reads from endpoint 0, and no claimInterface is required. | |
| 286 The method is simple and receives three parameters:</p> | |
| 287 | |
| 288 <pre> | |
| 289 chrome.usb.controlTransfer(connectionHandle, transferInfo, transferCallback) | |
| 290 </pre> | |
| 291 | |
| 292 <br> | |
| 293 | |
| 294 <table class="simple"> | |
| 295 <tr> | |
| 296 <th scope="col">Parameter (types)</th> | |
| 297 <th scope="col">Description</th> | |
| 298 </tr> | |
| 299 <tr> | |
| 300 <td>connectionHandle</td> | |
| 301 <td>Object received in $ref:usb.openDevice callback. | |
| 302 </td> | |
| 303 </tr> | |
| 304 <tr> | |
| 305 <td>transferInfo</td> | |
| 306 <td>Parameter object with values from the table below. Check your USB | |
| 307 device protocol specification for details. | |
| 308 </td> | |
| 309 </tr> | |
| 310 <tr> | |
| 311 <td>transferCallback()</td> | |
| 312 <td>Invoked when the transfer has completed.</td> | |
| 313 </tr> | |
| 314 </table> | |
| 315 | |
| 316 <p> | |
| 317 Values for | |
| 318 <code>transferInfo</code> | |
| 319 object: | |
| 320 </p> | |
| 321 | |
| 322 <table class="simple"> | |
| 323 <tr> | |
| 324 <th scope="col">Value</th> | |
| 325 <th scope="col">Description</th> | |
| 326 </tr> | |
| 327 <tr> | |
| 328 <td>requestType (string)</td> | |
| 329 <td>"vendor", "standard", "class" or "reserved".</td> | |
| 330 </tr> | |
| 331 <tr> | |
| 332 <td>recipient (string)</td> | |
| 333 <td>"device", "interface", "endpoint" or "other".</td> | |
| 334 </tr> | |
| 335 <tr> | |
| 336 <td>direction (string)</td> | |
| 337 <td>"in" or "out". The "in" direction is used to notify the device that<br/> | |
| 338 it should send information to the host. All communication on a USB<br/> | |
| 339 bus is host-initiated, so use an "in" transfer to allow a device to<br/> | |
| 340 send information back. | |
| 341 </td> | |
| 342 </tr> | |
| 343 <tr> | |
| 344 <td>request (integer)</td> | |
| 345 <td>Defined by your device's protocol.</td> | |
| 346 </tr> | |
| 347 <tr> | |
| 348 <td>value (integer)</td> | |
| 349 <td>Defined by your device's protocol.</td> | |
| 350 </tr> | |
| 351 <tr> | |
| 352 <td>index (integer)</td> | |
| 353 <td>Defined by your device's protocol.</td> | |
| 354 </tr> | |
| 355 <tr> | |
| 356 <td>length (integer)</td> | |
| 357 <td>Only used when direction is "in". Notifies the device that this is | |
| 358 the amount of data the host is expecting in response. | |
| 359 </td> | |
| 360 </tr> | |
| 361 <tr> | |
| 362 <td>data (arraybuffer)</td> | |
| 363 <td>Defined by your device's protocol, required when direction is | |
| 364 "out". | |
| 365 </td> | |
| 366 </tr> | |
| 367 </table> | |
| 368 | |
| 369 <p>Example:</p> | |
| 370 | |
| 371 <pre> | |
| 372 var transferInfo = { | |
| 373 "requestType": "vendor", | |
| 374 "recipient": "device", | |
| 375 "direction": "out", | |
| 376 "request": 0x31, | |
| 377 "value": 120, | |
| 378 "index": 0, | |
| 379 // Note that the ArrayBuffer, not the TypedArray itself is used. | |
| 380 "data": new Uint8Array([4, 8, 15, 16, 23, 42]).buffer | |
| 381 }; | |
| 382 chrome.usb.controlTransfer(connectionHandle, transferInfo, optionalCallback); | |
| 383 </pre> | |
| 384 | |
| 385 <h3 id="isochronous_transfers">ISOCHRONOUS transfers</h3> | |
| 386 | |
| 387 <p>Isochronous transfers are the most complex type of USB transfer. They are | |
| 388 commonly used for streams of data, like video and sound. To initiate an | |
| 389 isochronous transfer (either inbound or outbound), you must use | |
| 390 the $ref:usb.isochronousTransfer method:</p> | |
| 391 | |
| 392 <pre> | |
| 393 chrome.usb.isochronousTransfer(connectionHandle, isochronousTransferInfo, transf
erCallback) | |
| 394 </pre> | |
| 395 | |
| 396 <br/> | |
| 397 | |
| 398 <table class="simple"> | |
| 399 <tr> | |
| 400 <th scope="col">Parameter</th> | |
| 401 <th scope="col">Description</th> | |
| 402 </tr> | |
| 403 <tr> | |
| 404 <td>connectionHandle</td> | |
| 405 <td>Object received in $ref:usb.openDevice callback. | |
| 406 </td> | |
| 407 </tr> | |
| 408 <tr> | |
| 409 <td>isochronousTransferInfo</td> | |
| 410 <td>Parameter object with the values in the table below.</td> | |
| 411 </tr> | |
| 412 <tr> | |
| 413 <td>transferCallback()</td> | |
| 414 <td>Invoked when the transfer has completed.</td> | |
| 415 </tr> | |
| 416 </table> | |
| 417 | |
| 418 <p> | |
| 419 Values for | |
| 420 <code>isochronousTransferInfo</code> | |
| 421 object: | |
| 422 </p> | |
| 423 | |
| 424 <table class="simple"> | |
| 425 <tr> | |
| 426 <th scope="col">Value</th> | |
| 427 <th scope="col">Description</th> | |
| 428 </tr> | |
| 429 <tr> | |
| 430 <td>transferInfo (object)</td> | |
| 431 <td>An object with the following attributes:<br/> | |
| 432 <b>direction (string): </b>"in" or "out".<br/> | |
| 433 <b>endpoint (integer): </b>defined by your device. Usually can be found by | |
| 434 looking at an USB instrospection tool, like <code>lsusb -v</code><br/> | |
| 435 <b>length (integer): </b>only | |
| 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/> | |
| 441 <b>data (arraybuffer): </b>defined by your device's protocol; | |
| 442 only used when direction is "out". | |
| 443 </td> | |
| 444 </tr> | |
| 445 <tr> | |
| 446 <td>packets (integer)</td> | |
| 447 <td>Total number of packets expected in this transfer.</td> | |
| 448 </tr> | |
| 449 <tr> | |
| 450 <td>packetLength (integer)</td> | |
| 451 <td>Expected length of each packet in this transfer.</td> | |
| 452 </tr> | |
| 453 </table> | |
| 454 | |
| 455 <p>Example:</p> | |
| 456 | |
| 457 <pre> | |
| 458 var transferInfo = { | |
| 459 "direction": "in", | |
| 460 "endpoint": 1, | |
| 461 "length": 2560 | |
| 462 }; | |
| 463 | |
| 464 var isoTransferInfo = { | |
| 465 "transferInfo": transferInfo, | |
| 466 "packets": 20, | |
| 467 "packetLength": 128 | |
| 468 }; | |
| 469 | |
| 470 chrome.usb.isochronousTransfer(connectionHandle, isoTransferInfo, optionalCallba
ck); | |
| 471 </pre> | |
| 472 | |
| 473 <p class="note"> | |
| 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. | |
| 487 </p> | |
| 488 | |
| 489 <h3 id="bulk_transfers">BULK transfers</h3> | |
| 490 | |
| 491 <p>Bulk transfers are commonly used to transfer a large amount of | |
| 492 non-time-sensitive data in a reliable way. | |
| 493 $ref:usb.bulkTransfer has three parameters:</p> | |
| 494 | |
| 495 <pre> | |
| 496 chrome.usb.bulkTransfer(connectionHandle, transferInfo, transferCallback); | |
| 497 </pre> | |
| 498 | |
| 499 <br> | |
| 500 | |
| 501 <table class="simple"> | |
| 502 <tr> | |
| 503 <th scope="col">Parameter</th> | |
| 504 <th scope="col">Description</th> | |
| 505 </tr> | |
| 506 <tr> | |
| 507 <td>connectionHandle</td> | |
| 508 <td>Object received in $ref:usb.openDevice callback. | |
| 509 </td> | |
| 510 </tr> | |
| 511 <tr> | |
| 512 <td>transferInfo</td> | |
| 513 <td>Parameter object with the values in the table below.</td> | |
| 514 </tr> | |
| 515 <tr> | |
| 516 <td>transferCallback</td> | |
| 517 <td>Invoked when the transfer has completed.</td> | |
| 518 </tr> | |
| 519 </table> | |
| 520 | |
| 521 <p> | |
| 522 Values for | |
| 523 <code>transferInfo</code> | |
| 524 object: | |
| 525 </p> | |
| 526 | |
| 527 <table class="simple"> | |
| 528 <tr> | |
| 529 <th scope="col">Value</th> | |
| 530 <th scope="col">Description</th> | |
| 531 </tr> | |
| 532 <tr> | |
| 533 <td>direction (string)</td> | |
| 534 <td>"in" or "out".</td> | |
| 535 </tr> | |
| 536 <tr> | |
| 537 <td>endpoint (integer)</td> | |
| 538 <td>Defined by your device's protocol.</td> | |
| 539 </tr> | |
| 540 <tr> | |
| 541 <td>length (integer)</td> | |
| 542 <td>Only used when direction is "in". Notifies the device that this is | |
| 543 the amount of data the host is expecting in response. | |
| 544 </td> | |
| 545 </tr> | |
| 546 <tr> | |
| 547 <td>data (ArrayBuffer)</td> | |
| 548 <td>Defined by your device's protocol; only used when direction is | |
| 549 "out". | |
| 550 </td> | |
| 551 </tr> | |
| 552 </table> | |
| 553 | |
| 554 <p>Example:</p> | |
| 555 | |
| 556 <pre> | |
| 557 var transferInfo = { | |
| 558 "direction": "out", | |
| 559 "endpoint": 1, | |
| 560 "data": new Uint8Array([4, 8, 15, 16, 23, 42]).buffer | |
| 561 }; | |
| 562 </pre> | |
| 563 | |
| 564 <h3 id="interrupt_transfers">INTERRUPT transfers</h3> | |
| 565 | |
| 566 <p>Interrupt transfers are used to small amount of time sensitive data. | |
| 567 Since all USB communication is initiated by the host, host code usually polls | |
| 568 the device periodically, sending interrupt IN transfers that will make the | |
| 569 device send data back if there is anything in the interrupt queue (maintained | |
| 570 by the device). | |
| 571 $ref:usb.interruptTransfer has three parameters:</p> | |
| 572 | |
| 573 <pre> | |
| 574 chrome.usb.interruptTransfer(connectionHandle, transferInfo, transferCallback); | |
| 575 </pre> | |
| 576 | |
| 577 <br> | |
| 578 | |
| 579 <table class="simple"> | |
| 580 <tr> | |
| 581 <th scope="col">Parameter</th> | |
| 582 <th scope="col">Description</th> | |
| 583 </tr> | |
| 584 <tr> | |
| 585 <td>connectionHandle</td> | |
| 586 <td>Object received in $ref:usb.openDevice callback. | |
| 587 </td> | |
| 588 </tr> | |
| 589 <tr> | |
| 590 <td>transferInfo</td> | |
| 591 <td>Parameter object with the values in the table below.</td> | |
| 592 </tr> | |
| 593 <tr> | |
| 594 <td>transferCallback</td> | |
| 595 <td>Invoked when the transfer has completed. Notice that this callback | |
| 596 doesn't contain the device's response. The purpose of the callback is | |
| 597 simply to notify your code that the asynchronous transfer requests has | |
| 598 been processed. | |
| 599 </td> | |
| 600 </tr> | |
| 601 </table> | |
| 602 | |
| 603 <p> | |
| 604 Values for <code>transferInfo</code> object: | |
| 605 </p> | |
| 606 | |
| 607 <table class="simple"> | |
| 608 <tr> | |
| 609 <th scope="col">Value</th> | |
| 610 <th scope="col">Description</th> | |
| 611 </tr> | |
| 612 <tr> | |
| 613 <td>direction (string)</td> | |
| 614 <td>"in" or "out".</td> | |
| 615 </tr> | |
| 616 <tr> | |
| 617 <td>endpoint (integer)</td> | |
| 618 <td>Defined by your device's protocol.</td> | |
| 619 </tr> | |
| 620 <tr> | |
| 621 <td>length (integer)</td> | |
| 622 <td>Only used when direction is "in". Notifies the device that this is | |
| 623 the amount of data the host is expecting in response. | |
| 624 </td> | |
| 625 </tr> | |
| 626 <tr> | |
| 627 <td>data (ArrayBuffer)</td> | |
| 628 <td>Defined by your device's protocol; only used when direction is | |
| 629 "out". | |
| 630 </td> | |
| 631 </tr> | |
| 632 </table> | |
| 633 | |
| 634 <p>Example:</p> | |
| 635 | |
| 636 <pre> | |
| 637 var transferInfo = { | |
| 638 "direction": "in", | |
| 639 "endpoint": 1, | |
| 640 "length": 2 | |
| 641 }; | |
| 642 chrome.usb.interruptTransfer(connectionHandle, transferInfo, optionalCallback); | |
| 643 </pre> | |
| 644 | |
| 645 <h3 id="caveats">Caveats</h3> | |
| 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 | |
| 652 <p> | |
| 653 On most Linux systems, USB devices are mapped with read-only permissions by | |
| 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: | |
| 659 </p> | |
| 660 | |
| 661 <pre> | |
| 662 SUBSYSTEM=="usb", ATTR{idVendor}=="[yourdevicevendor]", MODE="0664", GROUP="plug
dev" | |
| 663 </pre> | |
| 664 | |
| 665 <p> | |
| 666 Then, just restart the udev daemon: <code>service udev restart</code>. | |
| 667 You can check if device permissions are set correctly by following these | |
| 668 steps: | |
| 669 </p> | |
| 670 | |
| 671 <ul> | |
| 672 <li>Run <code>lsusb</code> to find the bus and device numbers.</li> | |
| 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> | |
| 684 | |
| 685 <h2 id="serial">Accessing serial devices</h2> | |
| 686 | |
| 687 <p> | |
| 688 You can use the serial API to read | |
| 689 and write from a serial device. | |
| 690 </p> | |
| 691 | |
| 692 <h3 id="requirement">Manifest requirement</h3> | |
| 693 | |
| 694 <p> | |
| 695 You must add the "serial" permission to the manifest file: | |
| 696 </p> | |
| 697 <pre data-filename="manifest.json"> | |
| 698 "permissions": [ | |
| 699 "serial" | |
| 700 ] | |
| 701 </pre> | |
| 702 | |
| 703 <h3 id="listing">Listing available serial ports</h3> | |
| 704 | |
| 705 <p> | |
| 706 To get a list of available serial ports, | |
| 707 use the <code>getPorts()</code> method. <b>Note:</b> not all serial ports are av
ailable. The API uses a heuristic based on the name of the port to only expose s
erial devices that are expected to be safe. | |
| 708 </p> | |
| 709 | |
| 710 <pre> | |
| 711 var onGetPorts = function(ports) { | |
| 712 for (var i=0; i<ports.length; i++) { | |
| 713 console.log(ports[i]); | |
| 714 } | |
| 715 } | |
| 716 chrome.serial.getPorts(onGetPorts); | |
| 717 </pre> | |
| 718 | |
| 719 <h3 id="opening">Opening a serial device</h3> | |
| 720 | |
| 721 <p> | |
| 722 If you know the serial port name, you can open it for read and write using the <
code>open</code> method: | |
| 723 </p> | |
| 724 | |
| 725 <pre> | |
| 726 chrome.serial.open(portName, options, openCallback) | |
| 727 </pre> | |
| 728 | |
| 729 <table border="0"> | |
| 730 <tr> | |
| 731 <th scope="col"> Parameter </th> | |
| 732 <th scope="col"> Description </th> | |
| 733 </tr> | |
| 734 <tr> | |
| 735 <td>portName (string)</td> | |
| 736 <td>If your device's port name is unknown, you can use the <code>getPorts</c
ode> method.</td> | |
| 737 </tr> | |
| 738 <tr> | |
| 739 <td>options (object)</td> | |
| 740 <td>Parameter object with one single value: <code>bitrate</code>, an integer
specifying the desired bitrate used to communicate with the serial port.</td> | |
| 741 </tr> | |
| 742 <tr> | |
| 743 <td>openCallback</td> | |
| 744 <td>Invoked when the port has been successfully opened. The callback will be
called with one parameter, <code>openInfo</code>, that has one attribute, <code
>connectionId</code>. Save this id, because you will need it to actually communi
cate with the port. | |
| 745 </td> | |
| 746 </tr> | |
| 747 </table> | |
| 748 | |
| 749 <p>A simple example:</p> | |
| 750 | |
| 751 <pre> | |
| 752 var onOpen = function(connectionInfo) { | |
| 753 // The serial port has been opened. Save its id to use later. | |
| 754 _this.connectionId = connectionInfo.connectionId; | |
| 755 // Do whatever you need to do with the opened port. | |
| 756 } | |
| 757 // Open the serial port /dev/ttyS01 | |
| 758 chrome.serial.open("/dev/ttyS01", {bitrate: 115200}, onOpen); | |
| 759 </pre> | |
| 760 | |
| 761 <h3 id="closing">Closing a serial port</h3> | |
| 762 | |
| 763 <p> | |
| 764 Closing a serial port is simple but very important. See the example below: | |
| 765 </p> | |
| 766 | |
| 767 <pre> | |
| 768 var onClose = function(result) { | |
| 769 console.log("Serial port closed"); | |
| 770 } | |
| 771 chrome.serial.close(connectionId, onClose); | |
| 772 </pre> | |
| 773 | |
| 774 <h3 id="reading">Reading from a serial port</h3> | |
| 775 | |
| 776 <p> | |
| 777 The serial API reads from the serial port and | |
| 778 delivers the read bytes as an ArrayBuffer. | |
| 779 There is no guarantee that all the requested bytes, even if available in the por
t, will be read in one chunk. | |
| 780 The following example can accumulate read bytes, at most 128 at a time, until a
new line is read, | |
| 781 and then call a listener with the <code>ArrayBuffer</code> bytes converted to a
String: | |
| 782 </p> | |
| 783 | |
| 784 <pre> | |
| 785 var dataRead=''; | |
| 786 | |
| 787 var onCharRead=function(readInfo) { | |
| 788 if (!connectionInfo) { | |
| 789 return; | |
| 790 } | |
| 791 if (readInfo && readInfo.bytesRead>0 && readInfo.data) { | |
| 792 var str=ab2str(readInfo.data); | |
| 793 if (str[readInfo.bytesRead-1]==='\n') { | |
| 794 dataRead+=str.substring(0, readInfo.bytesRead-1); | |
| 795 onLineRead(dataRead); | |
| 796 dataRead=""; | |
| 797 } else { | |
| 798 dataRead+=str; | |
| 799 } | |
| 800 } | |
| 801 chrome.serial.read(connectionId, 128, onCharRead); | |
| 802 } | |
| 803 | |
| 804 /* Convert an ArrayBuffer to a String, using UTF-8 as the encoding scheme. | |
| 805 This is consistent with how Arduino sends characters by default */ | |
| 806 var ab2str=function(buf) { | |
| 807 return String.fromCharCode.apply(null, new Uint8Array(buf)); | |
| 808 }; | |
| 809 </pre> | |
| 810 | |
| 811 <h3 id="writing">Writing to a serial port</h3> | |
| 812 | |
| 813 <p> | |
| 814 The writing routine is simpler than reading, | |
| 815 since the writing can occur all at once. | |
| 816 The only catch is that if your data protocol is String based, | |
| 817 you have to convert your output string to an <code>ArrayBuffer</code>. | |
| 818 See the code example below: | |
| 819 </p> | |
| 820 | |
| 821 <pre> | |
| 822 var writeSerial=function(str) { | |
| 823 chrome.serial.write(connectionId, str2ab(str), onWrite); | |
| 824 } | |
| 825 // Convert string to ArrayBuffer | |
| 826 var str2ab=function(str) { | |
| 827 var buf=new ArrayBuffer(str.length); | |
| 828 var bufView=new Uint8Array(buf); | |
| 829 for (var i=0; i<str.length; i++) { | |
| 830 bufView[i]=str.charCodeAt(i); | |
| 831 } | |
| 832 return buf; | |
| 833 } | |
| 834 </pre> | |
| 835 | |
| 836 <h3 id="flushing">Flushing a serial port buffer</h3> | |
| 837 | |
| 838 <p> | |
| 839 You can flush your serial port buffer by issuing the flush command: | |
| 840 </p> | |
| 841 | |
| 842 <pre> | |
| 843 chrome.serial.flush(connectionId, onFlush); | |
| 844 </pre> | |
| 845 | |
| 846 <p class="backtotop"><a href="#top">Back to top</a></p> | |
| OLD | NEW |