Skip to content

Instantly share code, notes, and snippets.

@andhikayuana
Forked from felHR85/UsbData.java
Created June 25, 2025 08:08
Show Gist options
  • Select an option

  • Save andhikayuana/3188cd7f91f48b22c2f154ff3a5599dd to your computer and use it in GitHub Desktop.

Select an option

Save andhikayuana/3188cd7f91f48b22c2f154ff3a5599dd to your computer and use it in GitHub Desktop.

Revisions

  1. @felHR85 felHR85 revised this gist Aug 28, 2014. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions UsbDbAdapter.java
    Original file line number Diff line number Diff line change
    @@ -236,6 +236,7 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
    db.execSQL("DROP TABLE IF EXISTS " + VERSION_TABLE);
    db.execSQL("DROP TABLE IF EXISTS " + VENDOR_TABLE);
    db.execSQL("DROP TABLE IF EXISTS " + PRODUCT_TABLE);
    db.execSQL("VACUUM");
    onCreate(db);
    }else
    {
  2. @felHR85 felHR85 revised this gist Aug 6, 2014. 1 changed file with 6 additions and 0 deletions.
    6 changes: 6 additions & 0 deletions UsbDbAdapter.java
    Original file line number Diff line number Diff line change
    @@ -242,5 +242,11 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
    db.setVersion(oldVersion);
    }
    }

    @Override
    public void onDowngrade (SQLiteDatabase db, int oldVersion, int newVersion)
    {
    onUpgrade(db, oldVersion, newVersion);
    }
    }
    }
  3. @felHR85 felHR85 revised this gist Aug 6, 2014. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion UsbDataProvider.java
    Original file line number Diff line number Diff line change
    @@ -92,7 +92,8 @@ public void run()
    if(data != null)
    {
    dbAdapter.close();
    dbAdapter = new UsbDbAdapter(context, idLocalVersion++);
    idLocalVersion++;
    dbAdapter = new UsbDbAdapter(context, idLocalVersion);
    dbAdapter.open();
    UsbDataHelper.parseStringToDb(data, dbAdapter);
    if(mCallback != null)
  4. @felHR85 felHR85 revised this gist Jun 27, 2014. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions UsbIdDb.java
    Original file line number Diff line number Diff line change
    @@ -3,6 +3,8 @@
    * @author: felhr ([email protected])
    */

    // Permissions needed: <uses-permission android:name="android.permission.INTERNET" />

    // There are some callbacks related with created, opened and updated database events. It is not necessary to use them.
    private UsbDataProvider.UsbDbCallback mCallback = new UsbDataProvider.UsbDbCallback()
    {
  5. @felHR85 felHR85 created this gist Jun 27, 2014.
    64 changes: 64 additions & 0 deletions UsbData.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,64 @@
    public class UsbData
    {
    private String vendorId;
    private String vendorName;
    private String productId;
    private String productName;


    public UsbData(String vendorId, String vendorName, String productId, String productName)
    {
    this.vendorId = vendorId;
    this.vendorName = vendorName;
    this.productId = productId;
    this.productName = productName;
    }


    public String getVendorId()
    {
    return vendorId;
    }


    public void setVendorId(String vendorId)
    {
    this.vendorId = vendorId;
    }


    public String getVendorName()
    {
    return vendorName;
    }


    public void setVendorName(String vendorName)
    {
    this.vendorName = vendorName;
    }


    public String getProductId()
    {
    return productId;
    }


    public void setProductId(String productId)
    {
    this.productId = productId;
    }


    public String getProductName()
    {
    return productName;
    }


    public void setProductName(String productName)
    {
    this.productName = productName;
    }
    }
    209 changes: 209 additions & 0 deletions UsbDataHelper.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,209 @@
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.net.URLConnection;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;

    public class UsbDataHelper
    {
    private final static String USB_URL = "http://www.linux-usb.org/usb.ids";

    private UsbDataHelper()
    {

    }

    // Parse a given number of lines from url. Returns null if an error occur.
    public static List<String> parseDataFromUrl(int numberLines)
    {
    return UrlDownloaderHelper.fetchDataFromUrl(numberLines);
    }

    // Parse data from url to a local database.
    public static void parseStringToDb(List<String> data, UsbDbAdapter dbAdapter)
    {
    UsbIdRepositoryHelper.populateDb(data, dbAdapter);
    }

    // Get current repository version from url. Returns null if an error occur
    public static String getRepositoryVersion()
    {
    return UsbIdRepositoryHelper.getVersion();
    }

    private static class UrlDownloaderHelper
    {
    public static List<String> fetchDataFromUrl(int linesNumber)
    {
    int counter = 0;
    List<String> lines = new ArrayList<String>(19000);
    URL url = null;

    try
    {
    url = new URL(USB_URL);
    }catch(MalformedURLException e)
    {
    e.printStackTrace();
    url = null;
    }

    if(url != null)
    {
    try
    {
    URLConnection newConnection = url.openConnection();
    HttpURLConnection httpConexion = (HttpURLConnection) newConnection;
    int responseCode = httpConexion.getResponseCode();
    if(responseCode == HttpURLConnection.HTTP_OK)
    {
    InputStream is = httpConexion.getInputStream();
    BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"));

    String line;
    while((line = br.readLine()) != null)
    {

    lines.add(line);
    if(linesNumber != 0)
    {
    counter++;
    if(linesNumber == counter)
    return lines;
    }
    }
    }else
    {
    return null;
    }

    } catch (IOException e)
    {
    e.printStackTrace();
    return null;
    }
    }else
    {
    return null;
    }

    return lines;
    }
    }

    private static class UsbIdRepositoryHelper
    {

    // Flags
    private static boolean VID_PID_PARSING; // Parser is already parsing Vids and Pids

    // Next Section of file, there are no more vid an pids beyond this line
    private static final String NEXT_SECTION = "# List of known device classes, subclasses and protocols";

    //Tokens
    private static final char NUMBER_SIGN = '#';
    private static final String VERSION = "Version:";
    private static final String DATE = "Date:";


    private UsbIdRepositoryHelper()
    {
    VID_PID_PARSING = false;
    }

    public static void populateDb(List<String> data, UsbDbAdapter dbAdapter)
    {
    boolean keep = true;
    String tempVidKey = null;
    String tempVidName = null;
    String tempVersion = null;
    String tempDate = null;
    List<UsbData> productList = new ArrayList<UsbData>();
    Iterator<String> e = data.iterator();
    dbAdapter.beginTransaction();
    while(keep && e.hasNext())
    {
    String line = e.next();
    if(line.length() > 0)
    {
    if(!VID_PID_PARSING && line.charAt(0) == NUMBER_SIGN && line.contains(VERSION)) // Get Version
    {
    line = line.trim();
    tempVersion = line.substring(11, line.length());
    }else if(!VID_PID_PARSING && line.charAt(0) == NUMBER_SIGN && line.contains(DATE)) // Get Date
    {
    line = line.trim();
    tempDate = line.substring(11,line.length());
    dbAdapter.insertEntryVersion(tempVersion, tempDate);
    }else if(line.charAt(0) >= 0x30) // Get VID and Vendor name
    {
    if(!productList.isEmpty()) // List of Pids associated to a Vid has been completely read.
    {
    dbAdapter.insertEntryVendor(tempVidKey, tempVidName);
    Iterator<UsbData> t = productList.iterator();
    while(t.hasNext())
    {
    UsbData usbData = t.next();
    dbAdapter.insertEntryProduct(usbData);
    }
    productList.clear();
    }else if((VID_PID_PARSING && productList.isEmpty())) // There is a VID without PIDS
    {
    dbAdapter.insertEntryVendor(tempVidKey, tempVidName);
    }
    line = line.trim();
    tempVidKey = line.substring(0, 4);
    tempVidName = line.substring(5, line.length());
    if(!VID_PID_PARSING)
    VID_PID_PARSING = true;
    }else if(VID_PID_PARSING && line.charAt(0) != NUMBER_SIGN && line.length() > 1) // Get PID and product name
    {
    line = line.trim();
    String pid = line.substring(0, 4);
    String namePid = line.substring(6,line.length());
    UsbData productData = new UsbData(tempVidKey, tempVidName, pid, namePid);
    productList.add(productData);
    }else if(VID_PID_PARSING && line.equals(NEXT_SECTION)) // No more devices, add the last Vid and Pids associated
    {
    dbAdapter.insertEntryVendor(tempVidKey, tempVidName);
    Iterator<UsbData> t = productList.iterator();
    while(t.hasNext())
    {
    UsbData usbData = t.next();
    dbAdapter.insertEntryProduct(usbData);
    }
    productList.clear();
    keep = false;
    }
    }
    }
    dbAdapter.setTransactionSuccesful();
    dbAdapter.endTransaction();
    }


    public static String getVersion()
    {
    List<String> data = UrlDownloaderHelper.fetchDataFromUrl(12);
    if(data != null)
    {
    Iterator<String> e = data.iterator();
    while(e.hasNext())
    {
    String line = e.next();
    if(line.charAt(0) == NUMBER_SIGN && line.contains(VERSION)) // Get Version
    {
    return line.substring(11, line.length());
    }
    }
    }
    return null;
    }
    }
    }
    127 changes: 127 additions & 0 deletions UsbDataProvider.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,127 @@
    import java.io.File;
    import java.util.List;

    import android.content.Context;
    import android.util.Log;

    public class UsbDataProvider
    {
    private static final String CLASS_ID = UsbDataProvider.class.getSimpleName();
    private Context context;
    private HeavyTasksThread heavyTasksThread;
    private UsbDbCallback mCallback;
    private UsbDbAdapter dbAdapter;

    public UsbDataProvider(Context context)
    {
    this.context = context;
    heavyTasksThread = new HeavyTasksThread();
    heavyTasksThread.start();
    }

    public UsbDataProvider(Context context, UsbDbCallback mCallback)
    {
    this.context = context;
    heavyTasksThread = new HeavyTasksThread();
    this.mCallback = mCallback;
    heavyTasksThread.start();
    }

    public UsbData lookup(String vid, String pid)
    {
    if(dbAdapter != null)
    return dbAdapter.query(vid, pid);
    else
    return null;
    }


    private class HeavyTasksThread extends Thread
    {
    private boolean isDbCreated;

    public HeavyTasksThread()
    {
    isDbCreated = false;
    }

    @Override
    public void run()
    {
    File dbPath = context.getDatabasePath(UsbDbAdapter.DB_NAME);
    if(dbPath.exists())
    isDbCreated = true;

    if(!isDbCreated)
    {
    // First time, populate DB
    List<String> data = UsbDataHelper.parseDataFromUrl(0);
    if(data != null) //
    {
    // Open Database
    dbAdapter = new UsbDbAdapter(context, UsbDbAdapter.DB_VERSION_1);
    dbAdapter.open();

    // Data correctly parsed from url
    UsbDataHelper.parseStringToDb(data, dbAdapter);
    if(mCallback != null)
    mCallback.onDbOpenedFirstTime(true);
    }else
    {
    // Some error occurred when parsing data from url
    if(mCallback != null)
    mCallback.onDbOpenedFirstTime(false);
    }
    }else
    {
    // Database has been created before. Check version and update if necessary
    dbAdapter = new UsbDbAdapter(context, UsbDbAdapter.DB_VERSION_1);
    dbAdapter.open();
    String currentVersion = UsbDataHelper.getRepositoryVersion();
    if(currentVersion != null)
    {
    // Current remote version could be read. Check version and if not equal, update
    String localVersion = dbAdapter.queryLocalVersion();
    int idLocalVersion = dbAdapter.queryLocalVersionId();
    Log.i(CLASS_ID, "Local version: " + localVersion + " Local version Id: " +
    String.valueOf(idLocalVersion)+ " Remote version: " + currentVersion);

    if(!currentVersion.equals(localVersion)) // Remote version != local version. Try to update
    {
    List<String> data = UsbDataHelper.parseDataFromUrl(0);
    if(data != null)
    {
    dbAdapter.close();
    dbAdapter = new UsbDbAdapter(context, idLocalVersion++);
    dbAdapter.open();
    UsbDataHelper.parseStringToDb(data, dbAdapter);
    if(mCallback != null)
    mCallback.onDbUpdated(currentVersion);
    }else
    {
    dbAdapter = new UsbDbAdapter(context, idLocalVersion);
    dbAdapter.open();
    Log.i(CLASS_ID, "Db could not be updated");
    }
    }else // Remote version == Local version Open Database normally
    {
    if(mCallback != null)
    mCallback.onDbOpened();
    }
    }else
    {
    Log.i(CLASS_ID, "Remote version could not be read from url, Last db version opened");
    if(mCallback != null)
    mCallback.onDbOpened();
    }
    }
    }
    }

    public interface UsbDbCallback
    {
    public void onDbOpenedFirstTime(boolean status);
    public void onDbOpened();
    public void onDbUpdated(String newVersion);
    }
    }
    246 changes: 246 additions & 0 deletions UsbDbAdapter.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,246 @@
    import android.content.ContentValues;
    import android.content.Context;
    import android.database.Cursor;
    import android.database.SQLException;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteDatabase.CursorFactory;
    import android.database.sqlite.SQLiteOpenHelper;
    import android.database.sqlite.SQLiteStatement;

    public class UsbDbAdapter
    {
    public static final String DB_NAME = "usbIds.db";
    public static final int DB_VERSION_1 = 1;

    private static final String VERSION_TABLE = "versionTable";
    private static final String VENDOR_TABLE = "vendorTable";
    private static final String PRODUCT_TABLE = "productTable";

    //Version Table Columns
    private static final String VERSION_COLUMN = "version";
    private static final String DATE_COLUMN = "date";
    private static final String ID_VERSION = "id_version";

    // Vendor Table Columns
    private static final String KEY_ID = "_id";
    private static final String VID_COLUMN = "vid";
    private static final String VID_NAME_COLUMN = "vid_name";

    // Product Table Columns
    private static final String KEY_ID_PRODUCT = "_id";
    private static final String VID_PRODUCT_COLUMN = "vid";
    private static final String PID_PRODUCT_COLUMN = "pid";
    private static final String PID_NAME_PRODUCT_COLUMN = "pid_name";

    // SQL Statements
    private static final String CREATE_VERSION_TABLE = "create table " + VERSION_TABLE + "("
    + KEY_ID + " integer primary key autoincrement, " + VERSION_COLUMN + " text not null, "
    + DATE_COLUMN + " text not null, " + ID_VERSION + " integer);";

    private static final String CREATE_VENDOR_TABLE = "create table " + VENDOR_TABLE + "("
    +KEY_ID + " integer primary key autoincrement, " + VID_COLUMN + " text not null, " + VID_NAME_COLUMN + " text not null);";

    private static final String CREATE_PRODUCT_TABLE = "create table " + PRODUCT_TABLE + "("
    + KEY_ID_PRODUCT + " integer primary key autoincrement, " + VID_PRODUCT_COLUMN + " text not null, "
    + PID_PRODUCT_COLUMN + " text not null, " + PID_NAME_PRODUCT_COLUMN + " text not null);" ;

    private static final String SELECT_VENDOR_PRODUCT = "select vid_name, pid_name from "
    + VENDOR_TABLE + ", " + PRODUCT_TABLE + " where " + VENDOR_TABLE +".vid = ?" + " and " + PRODUCT_TABLE + ".vid = ? " + "and pid = ?";

    private static final String SELECT_VENDOR = "select vid, vid_name from " + VENDOR_TABLE + " where vid = ?";

    private static final String SELECT_VERSION = "select " + VERSION_COLUMN + " from " + VERSION_TABLE;

    private static final String SELECT_VERSION_ID = "select " + ID_VERSION + " from " + VERSION_TABLE;

    private static final String INSERT_VENDOR = "insert into " + VENDOR_TABLE + " (" + VID_COLUMN + ", " + VID_NAME_COLUMN
    + ") values(?,?)";

    private static final String INSERT_PRODUCT = "insert into " + PRODUCT_TABLE + " (" + VID_PRODUCT_COLUMN
    + ", " + PID_PRODUCT_COLUMN + ", " + PID_NAME_PRODUCT_COLUMN + ") values(?,?,?)";

    // Compiled SQL Statements
    private static SQLiteStatement insertVendor;
    private static SQLiteStatement insertProduct;


    private SQLiteDatabase db;
    private DbHelper dbHelper;
    private int currentVersion;

    public UsbDbAdapter(Context context, int version)
    {
    this.currentVersion = version;
    dbHelper = new DbHelper(context, DB_NAME, null, version);
    }

    public UsbDbAdapter open() throws SQLException
    {
    db = dbHelper.getWritableDatabase();
    return this;
    }

    public void close()
    {
    db.close();
    }

    public void beginTransaction()
    {
    db.beginTransaction();
    }

    public void endTransaction()
    {
    db.endTransaction();
    }

    public void setTransactionSuccesful()
    {
    db.setTransactionSuccessful();
    }

    public long insertEntryVersion(String version, String date)
    {
    ContentValues values = new ContentValues();
    values.put(VERSION_COLUMN, version);
    values.put(DATE_COLUMN, date);
    values.put(ID_VERSION, currentVersion);
    return db.insert(VERSION_TABLE, null, values);
    }

    public void insertEntryVendor(String vid, String vidName)
    {
    insertVendor.bindString(1, vid);
    insertVendor.bindString(2, vidName);
    insertVendor.execute();
    insertVendor.clearBindings();
    }

    public void insertEntryProduct(UsbData data)
    {
    insertProduct.bindString(1, data.getVendorId());
    insertProduct.bindString(2, data.getProductId());
    insertProduct.bindString(3, data.getProductName());
    insertProduct.execute();
    insertProduct.clearBindings();
    }

    public String queryLocalVersion()
    {
    Cursor cursor = db.rawQuery(SELECT_VERSION, null);
    cursor.moveToFirst();
    return cursor.getString(0);
    }

    public int queryLocalVersionId()
    {
    Cursor cursor = db.rawQuery(SELECT_VERSION_ID, null);
    cursor.moveToFirst();
    return cursor.getInt(0);
    }

    public UsbData query(String vid, String pid)
    {
    if(validateInput(vid, pid))
    {
    Cursor cursor = db.rawQuery(SELECT_VENDOR_PRODUCT, new String[]{vid, vid, pid});
    cursor.moveToFirst();
    if(cursor.getCount() > 0)
    {
    String vidName = cursor.getString(0);
    String pidName = cursor.getString(1);
    return new UsbData(vid, vidName, pid, pidName);
    }else
    {
    cursor = db.rawQuery(SELECT_VENDOR, new String[]{vid});
    cursor.moveToFirst();
    if(cursor.getCount() > 0)
    {
    String stringName = cursor.getString(1);
    return new UsbData(vid, stringName, pid, "None");
    }else
    {
    return new UsbData("None", "None", "None", "None");
    }
    }
    }else
    {
    return null;
    }
    }


    private boolean validateInput(String vid, String pid)
    {
    if((vid.length() > 4 || pid.length() > 4))
    return false;
    if(checkHexValue(vid) && checkHexValue(pid))
    return true;
    else
    return false;
    }

    private boolean checkHexValue(String value)
    {

    for(int i=0;i<=value.length()-1;i++)
    {
    if(value.charAt(i) < 0x30 || value.charAt(i) > 0x66)
    {
    return false;
    }else
    {
    if(value.charAt(i) > 0x39 && value.charAt(i) < 0x41)
    {
    return false;
    }else
    {
    if(value.charAt(i) > 0x46 && value.charAt(i) < 0x61)
    {
    return false;
    }
    }
    }
    }
    return true;
    }


    private static class DbHelper extends SQLiteOpenHelper
    {

    public DbHelper(Context context, String name, CursorFactory factory,
    int version)
    {
    super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db)
    {
    db.execSQL(CREATE_VERSION_TABLE);
    db.execSQL(CREATE_VENDOR_TABLE);
    db.execSQL(CREATE_PRODUCT_TABLE);

    insertVendor = db.compileStatement(INSERT_VENDOR);
    insertProduct = db.compileStatement(INSERT_PRODUCT);

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
    {
    if(newVersion > oldVersion)
    {
    db.execSQL("DROP TABLE IF EXISTS " + VERSION_TABLE);
    db.execSQL("DROP TABLE IF EXISTS " + VENDOR_TABLE);
    db.execSQL("DROP TABLE IF EXISTS " + PRODUCT_TABLE);
    onCreate(db);
    }else
    {
    db.setVersion(oldVersion);
    }
    }
    }
    }
    47 changes: 47 additions & 0 deletions UsbIdDb.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,47 @@
    /*
    * Example of use
    * @author: felhr ([email protected])
    */

    // There are some callbacks related with created, opened and updated database events. It is not necessary to use them.
    private UsbDataProvider.UsbDbCallback mCallback = new UsbDataProvider.UsbDbCallback()
    {
    @Override
    public void onDbOpenedFirstTime(boolean status)
    {
    // status == false means database could not be created due to an error fetching data from source
    // status == true means database was successfully created

    // Code here

    }

    @Override
    public void onDbOpened()
    {
    // Database opened
    // Code here
    }

    @Override
    public void onDbUpdated(String newVersion)
    {
    // Database updated with newVersion
    // Code here
    }
    };


    UsbDataProvider dataProvider;
    dataProvider = new UsbDataProvider(context, mCallback); // Create and open, open or update and open database if necessary. Notifications on callback
    //dataProvider = new UsbDataProvider(context)

    String vid = "03f0"; // Must be an hex representation of 16 bit number (0000-FFFF). Don't worry about uppercase or lowercase
    String pid= "010C"; // Must be an hex representation of 16 bit number (0000-FFFF). Don't worry about uppercase or lowercase

    UsbData data = dataProvider.lookup(vid, pid); // Returns null if vid or pid are not valid inputs or database could not be created
    if(data != null)
    {
    String vendorName = data.getVendorName(); // Vendor name
    String productName = data.getProductName(); // Product name
    }