Search code examples
c#node.jsnpmusb-debuggingusb-descriptor

Use NPM/Node for checking USB Debugging on Android Phone


I am trying to check if USB Debugging is turned on or off through NPM/Node. As soon as an android phone is connected to my system and USB Debugging is turned off, then i need to show a prompt to user to enable usb debugging on his phone.

According to my research, every device (Scanner/Phones/USB) connected to my system has a unique GUID which helps me to distinguish which device is connected. Further, i'm not able to fetch the usb debugging details. Please help!

Code which i have written so far is on the basis of iSerialNumber but i want to distinguish it on the basis of BUS-TYPE GUID.

var usb = require('usb');
usb.on('attach', function(device) {
var devices = usb.getDeviceList();
var check = devices[0].deviceDescriptor;
if(check.iSerialNumber == '3')
{
    console.log("Please enable USB Debugging");
}
else
{
    console.log("Connect an Android device");
}

});

I'm facing these issues.


Solution

  • if(check.iSerialNumber == '3')
    

    iSerialNumber is not actual Serial Number but it is just Index of Serial Number String Descriptor Stored in device. You can check further details about USB Device Descriptor on this link. GUID is not used by USB devices but may be used by OS itself as mentioned here. Serial Numbers are unique across every non-telephony Android devices as mentioned here so it is inadvisable to use Serial Number for flagging device as Android. The best way I found is to check against device vendor id and product id which are stored in device descriptor as idVendor and idProduct respectively. I found a list of vendor ids but did not find any list of product ids of each vendor.

    Android device exposes several interfaces for different purposes like MTP, PTP, Mass Storage and USB Debugging etc. We want to find out the status of USB Debugging interface which has Interface Class 255, Interface Sub Class 66 and Interface Protocol 1. I found these numbers here.

    Program first test if newly connected device is Android or not if it is Android then it checks for USB Debugging. I am not regular node.js user so my code is not good.

    main.js

    var usb = require('usb');
    usb.on('attach', function(device) {
        getDeviceInformation(device, function onInfromation(error, information)
        {
            if (error)
            {
                console.log("Unable to get Device information");
                return;
            }
    
            if (isAndroidDevice(information))
            {
                if (!isDebuggingEnabled(device))
                {
                    console.log("Please enable USB Debugging from Developer Options in Phone Settings");
                    return;
                }
    
                //Do your thing here
                console.log("Device connected with Debugging enabled");
                console.log("Device Information");
                console.log(information);
                console.log();
            }
        });
    });
    
    function getDeviceInformation(device, callback)
    {
        var deviceDescriptor = device.deviceDescriptor;
        var productStringIndex = deviceDescriptor.iProduct;
        var manufacturerStringIndex = deviceDescriptor.iManufacturer;
        var serialNumberIndex = deviceDescriptor.iSerialNumber;
    
        var callbacks = 3;
        var resultError = false;
        var productString = null;
        var manufacturerString = null;
        var serialNumberString = null;
    
        device.open();
        device.getStringDescriptor(productStringIndex, function callback(error, data)
        {
            if (error)resultError = true;
            else productString = data;
    
            if (--callbacks == 0)onFinish();
        });
    
        device.getStringDescriptor(manufacturerStringIndex, function callback(error, data)
        {
            if (error)resultError = true;
            else manufacturerString = data;
    
            if (--callbacks == 0)onFinish();
        });
    
        device.getStringDescriptor(serialNumberIndex, function callback(error, data)
        {
            if (error)resultError = true;
            else serialNumberString = data;
    
            if (--callbacks == 0)onFinish();
        });
    
        function onFinish()
        {
            device.close();
    
            var result = null;
            if (!resultError)
            {
                result = {
                    idVendor: deviceDescriptor.idVendor,
                    idProduct: deviceDescriptor.idProduct,
                    Product: productString,
                    Manufacturer: manufacturerString,
                    Serial: serialNumberString
                };
            }
    
            callback(resultError, result);
        }
    }
    
    /**
     *Currently this procedure only check vendor id
     *from limited set of available vendor ids
     *for complete functionality it should also
     *check for Product Id, Product Name or Serial Number
     */
    function isAndroidDevice(information)
    {
        var vendorId = information.idVendor;
        var index = require('./usb_vendor_ids').builtInVendorIds.indexOf(vendorId);
        return index == -1? false : true;
    }
    
    /**
     *Currently this procedure only check the
     *interfaces of default activated configuration 
     *for complete functionality it should check 
     *all interfaces available on each configuration 
     */
    function isDebuggingEnabled(device)
    {
        const ADB_CLASS = 255;
        const ADB_SUBCLASS = 66;
        const ADB_PROTOCOL = 1;
    
        /*opened device is necessary to set new configuration and 
         *to get available interfaces on that configuration
         */
        device.open();
    
        var result = false;
        const interfaces = device.interfaces;
        for (var i = 0, len = interfaces.length; i < len; ++i)
        {
            const bClass = interfaces[i].descriptor.bInterfaceClass;
            const bSubClass = interfaces[i].descriptor.bInterfaceSubClass;
            const bProtocol = interfaces[i].descriptor.bInterfaceProtocol;
            if (bClass == ADB_CLASS && bSubClass == ADB_SUBCLASS && bProtocol == ADB_PROTOCOL)
            {
                result = true;
                break;
            }
        }
    
        device.close();
        return result;
    }
    

    usb_vendor_ids.js

    //copied from https://github.com/karfield/adb/blob/master/src/usb_vendor_ids.c
    module.exports.builtInVendorIds = [
        0x18d1, /* Google */
        0x0bb4, /* HTC */
        0x04e8, /* Samsung */
        0x22b8, /* Motorola */
        0x1004, /* LG */
        0x12D1, /* Huawei */
        0x0502, /* Acer */
        0x0FCE, /* Sony Ericsson */
        0x0489, /* Foxconn */
        0x413c, /* Dell */
        0x0955, /* Nvidia */
        0x091E, /* Garmin-Asus */
        0x04dd, /* Sharp */
        0x19D2, /* ZTE */
        0x0482, /* Kyocera */
        0x10A9, /* Pantech */
        0x05c6, /* Qualcomm */
        0x2257, /* On-The-Go-Video */
        0x0409, /* NEC */
        0x04DA, /* Panasonic Mobile Communication */
        0x0930, /* Toshiba */
        0x1F53, /* SK Telesys */
        0x2116, /* KT Tech */
        0x0b05, /* Asus */
        0x0471, /* Philips */
        0x0451, /* Texas Instruments */
        0x0F1C, /* Funai */
        0x0414, /* Gigabyte */
        0x2420, /* IRiver */
        0x1219, /* Compal */
        0x1BBB, /* T & A Mobile Phones */
        0x2006, /* LenovoMobile */
        0x17EF, /* Lenovo */
        0xE040, /* Vizio */
        0x24E3, /* K-Touch */
        0x1D4D, /* Pegatron */
        0x0E79, /* Archos */
        0x1662, /* Positivo */
        0x15eb, /* VIA-Telecom */
        0x04c5, /* Fujitsu */
        0x091e, /* GarminAsus */
        0x109b, /* Hisense */
        0x24e3, /* KTouch */
        0x17ef, /* Lenovo */
        0x2080, /* Nook */
        0x10a9, /* Pantech */
        0x1d4d, /* Pegatron */
        0x04da, /* PMCSierra */
        0x1f53, /* SKTelesys */
        0x054c, /* Sony */
        0x0fce, /* SonyEricsson */
        0x2340, /* Teleepoch */
        0x19d2, /* ZTE */
        0x201e, /* Haier */
        /* TODO: APPEND YOUR ID HERE! */
    ];