Perangkat USB

Dokumen ini menjelaskan cara menggunakan USB API untuk berkomunikasi dengan perangkat USB. Beberapa perangkat tidak dapat diakses melalui USB API (lihat bagian Peringatan di bawah untuk detailnya). Aplikasi Chrome juga dapat terhubung ke perangkat serial dan Bluetooth.

Untuk mengetahui informasi latar belakang tentang USB, lihat spesifikasi USB resmi. USB di NutShell adalah kursus kilat yang wajar dan mungkin berguna bagi Anda.

Persyaratan manifes

USB API memerlukan "usb" dalam file manifes:

"permissions": [
  "usb"
]

Selain itu, untuk mencegah sidik jari, Anda harus mendeklarasikan semua jenis perangkat yang diakses dalam file manifes. Setiap jenis perangkat USB sesuai dengan ID vendor/ID produk (VID/PID). Anda dapat menggunakan usb.getDevices untuk menghitung perangkat berdasarkan pasangan VID/PID.

Anda harus mendeklarasikan pasangan VID/PID untuk setiap jenis perangkat yang ingin Anda gunakan berdasarkan usbDevices dalam file manifes aplikasi Anda, seperti yang ditunjukkan dalam contoh di bawah ini:

"permissions": [
  {
    "usbDevices": [
      {
        "vendorId": 123,
        "productId": 456
      }
    ]
  }
]

Mulai Chrome 57, persyaratan untuk mendeklarasikan semua jenis perangkat dalam manifes aplikasi adalah tidak lagi digunakan untuk aplikasi yang berjalan sebagai aplikasi kios ChromeOS. Untuk aplikasi kios, Anda dapat menggunakan interfaceClass untuk meminta izin guna mengakses perangkat USB yang:

  • mengimplementasikan antarmuka USB kelas antarmuka tertentu
  • memiliki kelas perangkat USB tertentu

Misalnya, izin usbDevices berikut akan memberikan akses aplikasi ke semua perangkat USB yang mengimplementasikan antarmuka printer (kode kelas antarmuka 7), dan ke perangkat hub USB (kode kelas perangkat 9):

"permissions": [
  {
    "usbDevices": [
      {"interfaceClass": 7},
      {"interfaceClass": 9}
    ]
  }
]

Untuk mengetahui daftar nilai interfaceClass yang dapat diterima, lihat Kode Kelas USB.

Properti interfaceClass dapat digabungkan dengan properti vendorId untuk mendapatkan akses hanya ke USB perangkat dari vendor tertentu, seperti yang ditunjukkan oleh contoh berikut:

"permissions": [
  {
    "usbDevices": [
      {
        "vendorId": 123,
        "interfaceClass": 7
      }
    ]
  }
]

Mencari perangkat

Untuk menentukan apakah satu atau beberapa perangkat tertentu terhubung ke sistem pengguna, gunakan Metode usb.getDevices:

chrome.usb.getDevices(enumerateDevicesOptions, callback);
Parameter (jenis)Deskripsi
EnumerateDevicesOptions (objek)Objek yang menentukan vendorId (panjang) dan productId (panjang) yang digunakan untuk menemukan jenis perangkat yang benar di bus. Manifes Anda harus mendeklarasikan bagian izin usbDevices yang mencantumkan semua pasangan vendorId dan deviceId yang ingin diakses oleh aplikasi Anda.
callback (fungsi)Dipanggil saat enumerasi perangkat selesai. Callback akan dieksekusi dengan satu parameter, yaitu array objek Device dengan tiga properti: device, vendorId, productId. Properti perangkat adalah ID yang stabil untuk perangkat terhubung. Parameter tidak akan berubah hingga perangkat dicabut. Detail ID buram dan dapat berubah. Jangan mengandalkan jenisnya saat ini.
Jika tidak ada perangkat yang ditemukan, array akan kosong.

Contoh:

function onDeviceFound(devices) {
  this.devices=devices;
  if (devices) {
    if (devices.length > 0) {
      console.log("Device(s) found: "+devices.length);
    } else {
      console.log("Device could not be found");
    }
  } else {
    console.log("Permission denied.");
  }
}

chrome.usb.getDevices({"vendorId": vendorId, "productId": productId}, onDeviceFound);

Membuka perangkat

Setelah objek Device ditampilkan, Anda dapat membuka perangkat menggunakan usb.openDevice untuk mendapatkan {i>connection handle<i}. Anda hanya dapat berkomunikasi dengan perangkat USB menggunakan tuas koneksi.

PropertiDeskripsi
perangkatObjek diterima di callback usb.getDevices.
data (buffer)Berisi data yang dikirim oleh perangkat jika transfer masuk.

Contoh:

var usbConnection = null;
var onOpenCallback = function(connection) {
  if (connection) {
    usbConnection = connection;
    console.log("Device opened.");
  } else {
    console.log("Device failed to open.");
  }
};

chrome.usb.openDevice(device, onOpenCallback);

Untuk menyederhanakan proses pembukaan, Anda dapat menggunakan metode usb.findDevices, yang menghitung, meminta akses, dan membuka perangkat dalam satu panggilan:

chrome.usb.findDevices({"vendorId": vendorId, "productId": productId, "interfaceId": interfaceId}, callback);

yang setara dengan:

chrome.usb.getDevices({"vendorId": vendorId, "productId": productId}, function (devices) {
  if (!devices) {
    console.log("Error enumerating devices.");
    callback();
    return;
  }
  var connections = [], pendingAccessRequests = devices.length;
  devices.forEach(function (device) {
    chrome.usb.requestAccess(interfaceId, function () {
      // No need to check for errors at this point.
      // Nothing can be done if an error occurs anyway. You should always try
      // to open the device.
      chrome.usb.openDevices(device, function (connection) {
        if (connection) connections.push(connection);
        pendingAccessRequests--;
        if (pendingAccessRequests == 0) {
          callback(connections);
        }
      });
    });
  })
});

Transfer USB dan menerima data dari perangkat

Protokol USB menentukan empat jenis transfer: control, massal, isocronus, dan interupsi. Transfer ini dijelaskan di bawah.

Transfer dapat terjadi dua arah: perangkat-ke-host (masuk), dan host-ke-perangkat (keluar). Tenggat pada sifat protokol USB, baik pesan masuk dan keluar harus dimulai oleh {i>host<i} (komputer yang menjalankan aplikasi Chrome). Untuk pesan masuk (perangkat-ke-host), host (dimulai oleh kode JavaScript) akan mengirimkan pesan yang ditandai sebagai "masuk" ke perangkat. Detail informasi bergantung pada perangkat, namun biasanya akan memiliki beberapa identifikasi tentang apa yang Anda minta dari sumber tersebut. Perangkat kemudian merespons dengan data yang diminta. Respons perangkat ditangani oleh Chrome dan dikirimkan secara asinkron ke callback yang Anda tetapkan di metode transfer. Perjalanan keluar (host ke perangkat) serupa, tetapi responsnya tidak berisi data yang ditampilkan dari perangkat.

Untuk setiap pesan dari perangkat, callback yang ditentukan akan menerima objek peristiwa dengan properti berikut:

PropertiDeskripsi
resultCode (bilangan bulat)0 berarti berhasil; jika nilai lain mengindikasikan kegagalan. String error dapat
dibaca dari chrome.extension.lastError jika ada
indikasi kegagalan.
data (buffer)Berisi data yang dikirim oleh perangkat jika transfer masuk.

Contoh:

var onTransferCallback = function(event) {
   if (event && event.resultCode === 0 && event.data) {
     console.log("got " + event.data.byteLength + " bytes");
   }
};

chrome.usb.bulkTransfer(connectionHandle, transferInfo, onTransferCallback);

CONTROL transfer

Transfer kontrol umumnya digunakan untuk mengirim atau menerima parameter konfigurasi atau perintah ke USB. perangkat seluler. Metode controlTransfer selalu mengirim ke/membaca dari endpoint 0, dan tidak ada klaimInterface yang tidak diperlukan. Metode ini sederhana dan menerima tiga parameter:

chrome.usb.controlTransfer(connectionHandle, transferInfo, transferCallback)
Parameter (jenis)Deskripsi
connectionHandleObjek diterima di callback usb.openDevice.
transferInfoObjek parameter dengan nilai dari tabel di bawah ini. Periksa spesifikasi protokol perangkat USB untuk mengetahui detailnya.
transferCallback()Dipanggil saat transfer selesai.

Nilai untuk objek transferInfo:

NilaiDeskripsi
requestType (string)"vendor", "standard", "class" atau "dicadangkan".
penerima (string)"perangkat", "antarmuka", "endpoint" atau "lainnya".
arah ({i>string<i})"dalam" atau "keluar". "Di dalam" arah digunakan untuk memberi tahu perangkat bahwa
perangkat harus mengirimkan informasi ke host. Semua komunikasi pada bus
USB dimulai oleh host, jadi gunakan "in" transfer agar perangkat dapat
mengirim informasi kembali.
permintaan (bilangan bulat)Ditentukan oleh protokol perangkat.
nilai (bilangan bulat)Ditentukan oleh protokol perangkat.
indeks (bilangan bulat)Ditentukan oleh protokol perangkat.
panjang (bilangan bulat)Hanya digunakan saat arah berada di "in". Memberi tahu perangkat bahwa ini adalah jumlah data yang diharapkan oleh host sebagai respons.
data (buffer)Ditentukan oleh protokol perangkat, diperlukan jika arahnya "keluar".

Contoh:

var transferInfo = {
  "requestType": "vendor",
   "recipient": "device",
  "direction": "out",
  "request":  0x31,
  "value": 120,
  "index": 0,
  // Note that the ArrayBuffer, not the TypedArray itself is used.
  "data": new Uint8Array([4, 8, 15, 16, 23, 42]).buffer
};
chrome.usb.controlTransfer(connectionHandle, transferInfo, optionalCallback);

Transfer ISOCHRONOUS

Transfer isokronus adalah jenis transfer USB yang paling kompleks. Umumnya digunakan untuk feed data, seperti video dan suara. Untuk memulai transfer isocron (baik masuk maupun keluar), Anda harus menggunakan metode usb.isochronousTransfer:

chrome.usb.isochronousTransfer(connectionHandle, isochronousTransferInfo, transferCallback)
ParameterDeskripsi
connectionHandleObjek diterima di callback usb.openDevice.
isochronousTransferInfoObjek parameter dengan nilai dalam tabel di bawah ini.
transferCallback()Dipanggil saat transfer selesai.

Nilai untuk objek isochronousTransferInfo:

NilaiDeskripsi
transferInfo (objek)Objek dengan atribut berikut:
direction (string): "in" atau "out".
endpoint (bilangan bulat): yang ditentukan oleh perangkat Anda. Biasanya dapat ditemukan dengan melihat alat instrospeksi USB, seperti lsusb -v
panjang (bilangan bulat): hanya digunakan saat arah berada di "in". Memberi tahu perangkat bahwa ini adalah jumlah data yang diharapkan oleh host dalam respons.
Sekurang-kurangnya harus packets × packetLength.
data (arraybuffer): yang ditentukan oleh protokol perangkat Anda; hanya digunakan saat arah adalah "keluar".
paket (bilangan bulat)Jumlah total paket yang diharapkan dalam transfer ini.
paketPanjang (bilangan bulat)Perkiraan panjang setiap paket dalam transfer ini.

Contoh:

var transferInfo = {
  "direction": "in",
  "endpoint": 1,
  "length": 2560
};

var isoTransferInfo = {
  "transferInfo": transferInfo,
  "packets": 20,
  "packetLength": 128
};

chrome.usb.isochronousTransfer(connectionHandle, isoTransferInfo, optionalCallback);

Transfer BESAR

Transfer massal biasanya digunakan untuk mentransfer sejumlah besar data yang tidak mendesak sebelumnya. usb.bulkTransfer memiliki tiga parameter:

chrome.usb.bulkTransfer(connectionHandle, transferInfo, transferCallback);
ParameterDeskripsi
connectionHandleObjek diterima di callback usb.openDevice.
transferInfoObjek parameter dengan nilai dalam tabel di bawah ini.
transferCallbackDipanggil saat transfer selesai.

Nilai untuk objek transferInfo:

NilaiDeskripsi
arah ({i>string<i})"dalam" atau "keluar".
endpoint (bilangan bulat)Ditentukan oleh protokol perangkat.
panjang (bilangan bulat)Hanya digunakan saat arah berada di "in". Memberi tahu perangkat bahwa ini adalah jumlah data yang diharapkan oleh host sebagai respons.
data (ArrayBuffer)Ditentukan oleh protokol perangkat Anda; hanya digunakan saat arah adalah "keluar".

Contoh:

var transferInfo = {
  "direction": "out",
  "endpoint": 1,
  "data": new Uint8Array([4, 8, 15, 16, 23, 42]).buffer
};

Transfer INTERUPT

Transfer interupsi digunakan untuk data sensitif waktu dalam jumlah kecil. Karena semua komunikasi USB dimulai oleh {i>host<i}, kode {i>host<i} biasanya memeriksa perangkat secara berkala, mengirim interupsi transfer yang akan membuat perangkat mengirim data kembali jika ada apa pun di antrean interupsi (dikelola oleh perangkat). usb.interruptTransfer memiliki tiga parameter:

chrome.usb.interruptTransfer(connectionHandle, transferInfo, transferCallback);
ParameterDeskripsi
connectionHandleObjek diterima di callback usb.openDevice.
transferInfoObjek parameter dengan nilai dalam tabel di bawah ini.
transferCallbackDipanggil saat transfer selesai. Perhatikan bahwa callback ini tidak berisi respons perangkat. Tujuan callback ini hanya untuk memberi tahu kode Anda bahwa permintaan transfer asinkron telah diproses.

Nilai untuk objek transferInfo:

NilaiDeskripsi
arah ({i>string<i})"dalam" atau "keluar".
endpoint (bilangan bulat)Ditentukan oleh protokol perangkat.
panjang (bilangan bulat)Hanya digunakan saat arah berada di "in". Memberi tahu perangkat bahwa ini adalah jumlah data yang diharapkan oleh host sebagai respons.
data (ArrayBuffer)Ditentukan oleh protokol perangkat Anda; hanya digunakan saat arah adalah "keluar".

Contoh:

var transferInfo = {
  "direction": "in",
  "endpoint": 1,
  "length": 2
};
chrome.usb.interruptTransfer(connectionHandle, transferInfo, optionalCallback);

Peringatan

Tidak semua perangkat dapat diakses melalui USB API. Pada umumnya, perangkat tidak dapat diakses karena baik {i>kernel<i} Sistem Operasi atau {i>driver<i} asli menahannya dari kode ruang pengguna. Agak besar contohnya adalah perangkat dengan profil HID pada sistem OSX, dan {i>pen drive<i} USB.

Pada sebagian besar sistem Linux, perangkat USB dipetakan dengan izin hanya baca secara default. Untuk membuka perangkat seluler melalui API ini, pengguna Anda juga harus memiliki akses tulis ke API tersebut. Solusi sederhananya adalah mengatur aturan udev. Buat file /etc/udev/rules.d/50-yourdevicename.rules dengan hal berikut konten:

SUBSYSTEM=="usb", ATTR{idVendor}=="[yourdevicevendor]", MODE="0664", GROUP="plugdev"

Kemudian, cukup mulai ulang daemon udev: service udev restart. Anda dapat memeriksa apakah izin perangkat tetapkan secara benar dengan mengikuti langkah-langkah berikut:

  • Jalankan lsusb untuk menemukan nomor bus dan perangkat.
  • Jalankan ls -al /dev/bus/usb/[bus]/[device]. File ini harus dimiliki oleh grup "plugdev" dan memiliki izin akses tulis grup.

Aplikasi Anda tidak dapat melakukannya secara otomatis karena prosedur ini memerlukan akses root. Saran dari kami Anda memberikan petunjuk kepada pengguna akhir dan menautkan ke bagian Peringatan di halaman ini untuk penjelasan.

Di ChromeOS, cukup panggil usb.requestAccess. Perantara izin melakukan ini untuk Anda.