असामान्य एचआईडी डिवाइसों से कनेक्ट करना

WebHID API, वेबसाइटों को वैकल्पिक सहायक कीबोर्ड और आकर्षक गेमपैड को ऐक्सेस करने की अनुमति देता है.

François Beaufort
François Beaufort

इंसान के इंटरफ़ेस वाले डिवाइसों (एचआईडी) की एक लंबी सूची होती है. जैसे, ऐसे कीबोर्ड या अनोखे गेमपैड, जो बहुत नए हैं, बहुत पुराने हैं या किसी जिसे सिस्टम ऐक्सेस कर सकते हैं डिवाइस ड्राइवर. WebHID API इस समस्या को हल करने के लिए, खास तौर पर डिवाइस के लिए बने लॉजिक को JavaScript में लागू करने का तरीका बताया गया है.

इस्तेमाल के सुझाए गए उदाहरण

एचआईडी डिवाइस, इंसानों से इनपुट लेता है या उन्हें आउटपुट उपलब्ध कराता है. डिवाइसों के उदाहरण इनमें कीबोर्ड, पॉइंटिंग डिवाइस (माइस, टचस्क्रीन वगैरह), और गेमपैड शामिल हैं. एचआईडी प्रोटोकॉल की मदद से, इन डिवाइसों को डेस्कटॉप पर ऐक्सेस किया जा सकता है ऑपरेटिंग सिस्टम ड्राइवर का इस्तेमाल करने वाले कंप्यूटर. वेब प्लैटफ़ॉर्म, एचआईडी डिवाइसों के साथ काम करता है अच्छी तरह से काम कर रहे हैं.

असामान्य एचआईडी डिवाइसों को ऐक्सेस न कर पाना, खास तौर पर तब दर्द भरा होता है, जब यह इसमें, वैकल्पिक कीबोर्ड का इस्तेमाल किया जा सकता है (जैसे, Elgato Stream Deck, Jabra हेडसेट, X-keys) और शानदार गेमपैड है. डेस्कटॉप के लिए डिज़ाइन किए गए गेमपैड गेमपैड इनपुट (बटन, जॉयस्टिक, ट्रिगर) और आउटपुट के लिए अक्सर एचआईडी का इस्तेमाल किया जाता है (एलईडी, रंबल). माफ़ करें, गेमपैड के इनपुट और आउटपुट ठीक से काम नहीं करते कुछ खास डिवाइसों के लिए, स्टैंडर्ड और वेब ब्राउज़र के लिए अक्सर पसंद के मुताबिक लॉजिक की ज़रूरत होती है. यह लंबे समय तक नहीं चलती है और इसकी वजह से पुराने डिवाइसों और असामान्य डिवाइस. इसकी वजह से ब्राउज़र, उपयोगकर्ता की गतिविधियों की बारीकियों पर भी निर्भर हो सकता है खास डिवाइस पर करते हैं.

शब्दावली

एचआईडी में दो बुनियादी सिद्धांत होते हैं: रिपोर्ट और रिपोर्ट डिस्क्रिप्टर. रिपोर्ट वह डेटा है जो डिवाइस और सॉफ़्टवेयर क्लाइंट के बीच लेन-देन होता है. रिपोर्ट डिस्क्रिप्टर से, डिवाइस के डेटा के फ़ॉर्मैट और मतलब की जानकारी मिलती है इस्तेमाल किया जा सकता है.

एचआईडी (ह्यूमन इंटरफ़ेस डिवाइस) एक ऐसा डिवाइस है जो लोगों को आउटपुट देती है. यह एचआईडी प्रोटोकॉल भी है, जो होस्ट और डिवाइस के बीच दो-तरफ़ा कम्यूनिकेशन इंस्टॉलेशन की प्रक्रिया को आसान बनाएं. दरअसल, एचआईडी प्रोटोकॉल को मूल रूप से का इस्तेमाल किया जा सकता है. हालांकि, इसे कई दूसरे प्रोटोकॉल पर लागू किया गया है. ब्लूटूथ शामिल है.

ऐप्लिकेशन और एचआईडी डिवाइस, तीन तरह की रिपोर्ट के ज़रिए बाइनरी डेटा का लेन-देन करते हैं:

रिपोर्ट का टाइप ब्यौरा
इनपुट रिपोर्ट डिवाइस से ऐप्लिकेशन पर भेजा जाने वाला डेटा (उदाहरण के लिए, कोई बटन दबाया जाता है.)
आउटपुट रिपोर्ट ऐप्लिकेशन से डिवाइस पर भेजा जाने वाला डेटा (उदाहरण के लिए, कीबोर्ड की बैकलाइट चालू करने का अनुरोध.)
सुविधा की रिपोर्ट वह डेटा जिसे किसी भी दिशा में भेजा जा सकता है. यह फ़ॉर्मैट, डिवाइस के हिसाब से अलग-अलग होता है.

रिपोर्ट डिस्क्रिप्टर, रिपोर्ट के बाइनरी फ़ॉर्मैट की जानकारी देता है. यह फ़ॉर्मैट डिवाइस. इसकी बनावट हैरारकी है और यह रिपोर्ट को एक साथ कलेक्शन में से किसी एक को शामिल करना चाहिए. डिस्क्रिप्टर का फ़ॉर्मैट यह है एचआईडी स्पेसिफ़िकेशन से तय होता है.

एचआईडी का इस्तेमाल, अंकों वाली ऐसी वैल्यू है जो स्टैंडर्ड इनपुट या आउटपुट के बारे में बताती है. इस्तेमाल से जुड़ी जानकारी की मदद से, डिवाइस यह बता पाता है कि उसे किस तरह से इस्तेमाल करना है और का मकसद बताया है. उदाहरण के लिए, बाईं ओर एक लाइन है माउस का बटन. इस्तेमाल की जानकारी को इस्तेमाल पेजों में भी व्यवस्थित किया जाता है, जिससे डिवाइस या रिपोर्ट की हाई-लेवल कैटगरी के बारे में जानकारी.

WebHID API का इस्तेमाल करना

सुविधा की पहचान

WebHID API काम करता है या नहीं, यह देखने के लिए इसका इस्तेमाल करें:

if ("hid" in navigator) {
  // The WebHID API is supported.
}

एचआईडी कनेक्शन खोलें

WebHID API, डिज़ाइन के हिसाब से एसिंक्रोनस है, ताकि वेबसाइट के यूज़र इंटरफ़ेस (यूआई) को ब्लॉक करने की सुविधा मिलती है. ऐसा करना ज़रूरी है, क्योंकि एचआईडी डेटा मिल सकता है उसे सुनने का विकल्प चाहिए.

एचआईडी कनेक्शन खोलने के लिए, पहले HIDDevice ऑब्जेक्ट को ऐक्सेस करें. इसके लिए, आपके पास ये विकल्प हैं तो उपयोगकर्ता को कॉल करके, डिवाइस चुनने का प्रॉम्प्ट दिखाएं navigator.hid.requestDevice() या navigator.hid.getDevices() में से कोई एक चुनें इससे उन डिवाइसों की सूची दिखती है जिनका ऐक्सेस वेबसाइट को दिया गया है पहले इस्तेमाल कर रहे थे.

navigator.hid.requestDevice() फ़ंक्शन एक ज़रूरी ऑब्जेक्ट लेता है जो फ़िल्टर तय करता है. इनका इस्तेमाल यूएसबी वेंडर से कनेक्ट किए गए किसी भी डिवाइस से मिलान करने के लिए किया जाता है आइडेंटिफ़ायर (vendorId), यूएसबी प्रॉडक्ट आइडेंटिफ़ायर (productId), इस्तेमाल के बारे में जानकारी देने वाला पेज वैल्यू (usagePage) और इस्तेमाल के लिए वैल्यू (usage). आप इन्हें यहां से पा सकते हैं यूएसबी आईडी का डेटा स्टोर करने की जगह और एचआईडी के इस्तेमाल की टेबल से जुड़ा दस्तावेज़.

इस फ़ंक्शन से मिले कई HIDDevice ऑब्जेक्ट, एक से ज़्यादा आइटम दिखाते हैं एक ही डिवाइस पर एचआईडी इंटरफ़ेस.

// Filter on devices with the Nintendo Switch Joy-Con USB Vendor/Product IDs.
const filters = [
  {
    vendorId: 0x057e, // Nintendo Co., Ltd
    productId: 0x2006 // Joy-Con Left
  },
  {
    vendorId: 0x057e, // Nintendo Co., Ltd
    productId: 0x2007 // Joy-Con Right
  }
];

// Prompt user to select a Joy-Con device.
const [device] = await navigator.hid.requestDevice({ filters });
// Get all devices the user has previously granted the website access to.
const devices = await navigator.hid.getDevices();
किसी वेबसाइट पर एचआईडी डिवाइस के प्रॉम्प्ट का स्क्रीनशॉट.
Nintendo Switch जॉय-Con चुनने के लिए, उपयोगकर्ता का प्रॉम्प्ट.

exclusionFilters बटन का इस्तेमाल यहां भी किया जा सकता है. हालांकि, ऐसा करना ज़रूरी नहीं है ब्राउज़र पिकर से कुछ डिवाइसों को बाहर रखने के लिए, navigator.hid.requestDevice() जो उदाहरण के लिए, गलत तरीके से काम करती हैं.

// Request access to a device with vendor ID 0xABCD. The device must also have
// a collection with usage page Consumer (0x000C) and usage ID Consumer
// Control (0x0001). The device with product ID 0x1234 is malfunctioning.
const [device] = await navigator.hid.requestDevice({
  filters: [{ vendorId: 0xabcd, usagePage: 0x000c, usage: 0x0001 }],
  exclusionFilters: [{ vendorId: 0xabcd, productId: 0x1234 }],
});

HIDDevice ऑब्जेक्ट में, डिवाइस के लिए यूएसबी वेंडर और प्रॉडक्ट आइडेंटिफ़ायर मौजूद हैं पहचान. इसका collections एट्रिब्यूट, हैरारकी के हिसाब से शुरू किया गया है डिवाइस के रिपोर्ट फ़ॉर्मैट की जानकारी.

for (let collection of device.collections) {
  // An HID collection includes usage, usage page, reports, and subcollections.
  console.log(`Usage: ${collection.usage}`);
  console.log(`Usage page: ${collection.usagePage}`);

  for (let inputReport of collection.inputReports) {
    console.log(`Input report: ${inputReport.reportId}`);
    // Loop through inputReport.items
  }

  for (let outputReport of collection.outputReports) {
    console.log(`Output report: ${outputReport.reportId}`);
    // Loop through outputReport.items
  }

  for (let featureReport of collection.featureReports) {
    console.log(`Feature report: ${featureReport.reportId}`);
    // Loop through featureReport.items
  }

  // Loop through subcollections with collection.children
}

HIDDevice डिवाइस डिफ़ॉल्ट रूप से "बंद है" कैटगरी में दिखाए जाते हैं राज्य के हिसाब से होने चाहिए और डेटा भेजने या पाने से पहले, open() पर कॉल करके खोला गया.

// Wait for the HID connection to open before sending/receiving data.
await device.open();

इनपुट रिपोर्ट पाएं

एचआईडी कनेक्शन बन जाने के बाद, इनकमिंग इनपुट मैनेज किया जा सकता है डिवाइस से "inputreport" के इवेंट सुनकर रिपोर्ट कर सकता है. वे इवेंट एचआईडी डेटा को DataView ऑब्जेक्ट (data) के तौर पर शामिल करता है. यह एचआईडी डिवाइस का होता है से (device) तक और इनपुट रिपोर्ट से जुड़ा 8-बिट रिपोर्ट आईडी (reportId).

लाल और नीले रंग के निनटेंडो स्विच वाली फ़ोटो.
Nintendo Switch जॉय-कॉन डिवाइस.

पिछले उदाहरण की तरह, नीचे दिया गया कोड आपको यह पता लगाने का तरीका बताता है उपयोगकर्ता ने जॉय-कॉन राइट डिवाइस पर कौनसा बटन दबाया है, ताकि आप उम्मीद है कि इसे घर पर आज़मा सकते हैं.

device.addEventListener("inputreport", event => {
  const { data, device, reportId } = event;

  // Handle only the Joy-Con Right device and a specific report ID.
  if (device.productId !== 0x2007 && reportId !== 0x3f) return;

  const value = data.getUint8(0);
  if (value === 0) return;

  const someButtons = { 1: "A", 2: "X", 4: "B", 8: "Y" };
  console.log(`User pressed button ${someButtons[value]}.`);
});

आउटपुट रिपोर्ट भेजें

किसी एचआईडी डिवाइस पर आउटपुट रिपोर्ट भेजने के लिए, उस डिवाइस से जुड़ा 8-बिट रिपोर्ट आईडी पास करें इससे आउटपुट रिपोर्ट (reportId) और बाइट को BufferSource (data) के तौर पर device.sendReport(). शिकायत करने के बाद, वापस किया गया प्रॉमिस रिज़ॉल्व हो जाता है भेजा गया. अगर एचआईडी डिवाइस में रिपोर्ट आईडी इस्तेमाल नहीं किए जाते हैं, तो reportId को 0 पर सेट करें.

यहां दिया गया उदाहरण जॉय-कॉन डिवाइस पर लागू होता है और आपको इसे बनाने का तरीका बताता है और आउटपुट रिपोर्ट के बीच गड़बड़ी होना.

// First, send a command to enable vibration.
// Magical bytes come from https://github.com/mzyy94/joycon-toolweb
const enableVibrationData = [1, 0, 1, 64, 64, 0, 1, 64, 64, 0x48, 0x01];
await device.sendReport(0x01, new Uint8Array(enableVibrationData));

// Then, send a command to make the Joy-Con device rumble.
// Actual bytes are available in the sample below.
const rumbleData = [ /* ... */ ];
await device.sendReport(0x10, new Uint8Array(rumbleData));

सुविधाओं की रिपोर्ट भेजें और पाएं

सुविधा रिपोर्ट ही ऐसी एचआईडी डेटा रिपोर्ट हैं जिन्हें दोनों फ़ॉर्मैट में लागू किया जा सकता है निर्देश. वे एचआईडी डिवाइसों और ऐप्लिकेशन को नॉन स्टैंडर्ड के मुताबिक एक्सचेंज करने की अनुमति देते हैं एचआईडी डेटा. इनपुट और आउटपुट रिपोर्ट के उलट, सुविधा की रिपोर्ट नहीं मिलतीं या नियमित रूप से आवेदन के ज़रिए भेजा जाता है.

काले और सिल्वर रंग के लैपटॉप कंप्यूटर की फ़ोटो.
लैपटॉप कीबोर्ड

किसी एचआईडी डिवाइस पर सुविधा रिपोर्ट भेजने के लिए, उस डिवाइस से जुड़ा 8-बिट रिपोर्ट आईडी पास करें सुविधा रिपोर्ट (reportId) और बाइट को BufferSource (data) के तौर पर device.sendFeatureReport(). शिकायत करने के बाद, वापस किया गया प्रॉमिस रिज़ॉल्व हो जाता है भेज दिए गए हैं. अगर एचआईडी डिवाइस में रिपोर्ट आईडी इस्तेमाल नहीं किए जाते हैं, तो reportId को 0 पर सेट करें.

नीचे दिए गए उदाहरण में, फ़ीचर रिपोर्ट के इस्तेमाल के बारे में बताया गया है. साथ ही, यह भी बताया गया है कि Apple कीबोर्ड की बैकलाइट डिवाइस का अनुरोध करें, उसे खोलें, और ब्लिंक करें.

const waitFor = duration => new Promise(r => setTimeout(r, duration));

// Prompt user to select an Apple Keyboard Backlight device.
const [device] = await navigator.hid.requestDevice({
  filters: [{ vendorId: 0x05ac, usage: 0x0f, usagePage: 0xff00 }]
});

// Wait for the HID connection to open.
await device.open();

// Blink!
const reportId = 1;
for (let i = 0; i < 10; i++) {
  // Turn off
  await device.sendFeatureReport(reportId, Uint32Array.from([0, 0]));
  await waitFor(100);
  // Turn on
  await device.sendFeatureReport(reportId, Uint32Array.from([512, 0]));
  await waitFor(100);
}

किसी एचआईडी डिवाइस से सुविधा की रिपोर्ट पाने के लिए, 8-बिट रिपोर्ट आईडी पास करें फ़ीचर रिपोर्ट (reportId) से जुड़ा हुआ है device.receiveFeatureReport(). वापस किए गए प्रॉमिस का समाधान DataView ऑब्जेक्ट, जिसमें सुविधा रिपोर्ट का कॉन्टेंट मौजूद है. अगर एचआईडी डिवाइस, रिपोर्ट आईडी इस्तेमाल नहीं करता. इसलिए, reportId को 0 पर सेट करें.

// Request feature report.
const dataView = await device.receiveFeatureReport(/* reportId= */ 1);

// Read feature report contents with dataView.getInt8(), getUint8(), etc...

इंटरनेट से कनेक्ट और डिसकनेक्ट होने वाले डिवाइसों को सुनें

जब वेबसाइट को किसी एचआईडी डिवाइस को ऐक्सेस करने की अनुमति मिल जाती है, तो वह ये काम कर सकती है: "connect" को सुनकर, कनेक्शन और डिसकनेक्ट करने वाले इवेंट लगातार पाएं और "disconnect" इवेंट.

navigator.hid.addEventListener("connect", event => {
  // Automatically open event.device or warn user a device is available.
});

navigator.hid.addEventListener("disconnect", event => {
  // Remove |event.device| from the UI.
});

किसी एचआईडी डिवाइस का ऐक्सेस वापस लेना

वेबसाइट, उस एचआईडी डिवाइस को ऐक्सेस करने के लिए अनुमतियों को खाली कर सकती है जो अब काम नहीं करता HIDDevice इंस्टेंस पर forget() को कॉल करके बनाए रखने में दिलचस्पी है. इसके लिए उदाहरण के लिए, किसी ऐसे शैक्षणिक वेब ऐप्लिकेशन के लिए जिसका इस्तेमाल किसी ऐसे कंप्यूटर पर किया जाता है करते हैं, तो बड़ी संख्या में उपयोगकर्ता जनित अनुमतियों की वजह से उपयोगकर्ता अनुभव मिलता है.

forget() को HIDDevice के किसी एक इंस्टेंस पर कॉल करने से, सभी का ऐक्सेस हट जाएगा एक ही डिवाइस पर एचआईडी इंटरफ़ेस हो.

// Voluntarily revoke access to this HID device.
await device.forget();

Chrome 100 या इसके बाद के वर्शन में forget() उपलब्ध है. इसलिए, देखें कि यह सुविधा इनके साथ काम करता है:

if ("hid" in navigator && "forget" in HIDDevice.prototype) {
  // forget() is supported.
}

डेवलपर के लिए सलाह

इंटरनल पेज, about://device-log की मदद से Chrome में एचआईडी को डीबग करना आसान है एचआईडी और यूएसबी डिवाइस से जुड़े सभी इवेंट एक ही जगह पर देखे जा सकते हैं.

एचआईडी को डीबग करने के लिए, इंटरनल पेज का स्क्रीनशॉट.
एचआईडी को डीबग करने के लिए, Chrome का इंटरनल पेज.

एचआईडी डिवाइस को डंप करने के लिए, एचआईडी एक्सप्लोरर देखें में दी गई जानकारी एक ऐसे फ़ॉर्मैट में सेव की जा सकती है जिसे कोई भी व्यक्ति आसानी से पढ़ सके. इसमें, इस्तेमाल की वैल्यू से लेकर हर ऐसेट के नाम तक शामिल होते हैं एचआईडी का इस्तेमाल.

ज़्यादातर Linux सिस्टम पर, एचआईडी डिवाइसों को रीड-ओनली अनुमतियों के साथ मैप किया जाता है: डिफ़ॉल्ट. Chrome को किसी एचआईडी डिवाइस को खोलने की अनुमति देने के लिए, आपको एक नया udev जोड़ना होगा नियम में सेट अप किया गया है. /etc/udev/rules.d/50-yourdevicename.rules पर फ़ाइल बनाने के लिए निम्न सामग्री:

KERNEL=="hidraw*", ATTRS{idVendor}=="[yourdevicevendor]", MODE="0664", GROUP="plugdev"

ऊपर दी गई लाइन में, अगर आपका डिवाइस Nintendo Switch है, तो [yourdevicevendor] 057e है जैसे कि जॉय-कॉन. ATTRS{idProduct} को ज़्यादा सटीक नतीजे के लिए भी जोड़ा जा सकता है नियम. पक्का करें कि आपका user, plugdev ग्रुप का सदस्य है. इसके बाद, बस अपना डिवाइस फिर से कनेक्ट करें.

ब्राउज़र समर्थन

WebHID API हर डेस्कटॉप प्लैटफ़ॉर्म पर उपलब्ध है. जैसे- ChromeOS, Linux, macOS, और Windows) पर उपलब्ध है.

डेमो

WebHID के कुछ डेमो की सूची, web.dev/hid-examples पर दी गई है. आइए एक नज़र डालें!

सुरक्षा और निजता

स्पेसिफ़िकेशन के हिसाब से, लेखकों ने WebHID API को डिज़ाइन और लागू करने के लिए शानदार वेब प्लैटफ़ॉर्म सुविधाओं का ऐक्सेस कंट्रोल करना में बताए गए सिद्धांत, इसमें उपयोगकर्ता के कंट्रोल, पारदर्शिता, और एर्गोनॉमिक्स का इस्तेमाल करना शामिल है. इस सुविधा का इस्तेमाल करके एपीआई को मुख्य रूप से अनुमति के ऐसे मॉडल से लॉक किया जाता है जो सिर्फ़ एक एक बार में एचआईडी डिवाइस. उपयोगकर्ता के प्रॉम्प्ट के जवाब में, उपयोगकर्ता को ऐक्टिव होना चाहिए किसी एचआईडी डिवाइस को चुनने का तरीका.

सुरक्षा के बंद होने के समझौतों को समझने के लिए, सुरक्षा और निजता नीति के बारे में पढ़ें ध्यान देने लायक बातें WebHID की खास जानकारी का सेक्शन.

सबसे ऊपर, Chrome हर टॉप-लेवल कलेक्शन के इस्तेमाल की जांच करता है और अगर टॉप लेवल कलेक्शन का इस्तेमाल सुरक्षित तरीके से किया जाता है (उदाहरण के लिए, जेनरिक कीबोर्ड, माउस), फिर कोई वेबसाइट उस भाषा में परिभाषित की गई कोई भी रिपोर्ट न तो भेज सकती है और न ही प्राप्त कर सकती है संग्रह. सुरक्षित इस्तेमाल की पूरी सूची सार्वजनिक रूप से उपलब्ध है.

ध्यान दें कि सुरक्षा के लिहाज़ से संवेदनशील एचआईडी डिवाइस, जैसे कि FIDO एचआईडी डिवाइस सुरक्षित तरीके से पुष्टि करने की सुविधा) को भी Chrome में ब्लॉक कर दिया जाता है. यूएसबी की ब्लॉकलिस्ट देखें और एचआईडी की ब्लॉकलिस्ट फ़ाइलें.

सुझाव/राय दें या शिकायत करें

Chrome टीम को WebHID एपीआई.

हमें एपीआई के डिज़ाइन के बारे में बताएं

क्या एपीआई के बारे में कुछ ऐसा है जो उम्मीद के मुताबिक काम नहीं करता? या ऐसे हैं क्या आपको अपने आइडिया पर काम करने के लिए कुछ तरीके या प्रॉपर्टी नहीं मिल रही हैं?

WebHID API GitHub के रेपो से जुड़ी समस्या की शिकायत करें या अपनी राय दें करने के लिए प्रोत्साहित करते हैं.

लागू करने से जुड़ी समस्या की शिकायत करना

क्या आपको Chrome को लागू करने में कोई गड़बड़ी मिली? या, लागू करने पर क्या यह स्पेसिफ़िकेशन से अलग है?

WebHID की गड़बड़ियां ठीक करने का तरीका जानें. ज़्यादा से ज़्यादा जानकारी शामिल करना न भूलें ब्यौरा दें, बग का समाधान करने के लिए आसान निर्देश दें, और कॉम्पोनेंट को Blink>HID पर सेट किया गया है. Glitch इनके लिए बेहतरीन काम करता है: तुरंत और आसानी से दोहराने की सुविधा देता है.

सपोर्ट करें

क्या आपको WebHID API का इस्तेमाल करना है? आपके सार्वजनिक समर्थन से Chrome को टीम, सुविधाओं को प्राथमिकता देती है और अन्य ब्राउज़र वेंडर को दिखाती है कि उनके लिए मदद मिलती है.

हैशटैग का इस्तेमाल करके @ChromiumDev को ट्वीट भेजें #WebHID और हमें बताएं उसका इस्तेमाल कहां और कैसे किया जा रहा है.

मददगार लिंक

स्वीकार की गई

इस लेख पर समीक्षाएं लिखने के लिए, मैट रेनॉल्ड्स और जो मेडली का धन्यवाद. लाल और नीले रंग के Nintendo की फ़ोटो सारा कर्फ़े से स्विच करें और काले और सिल्वर रंग का लैपटॉप Unस्प्लैश पर यह कंप्यूटर फ़ोटो अतुल सिरिआक अजय ने तैयार की है.