Skip to content

Instantly share code, notes, and snippets.

@felHR85
Last active August 13, 2018 06:31
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save felHR85/afe18397dc2441862337 to your computer and use it in GitHub Desktop.
An easy to use android solution to get a readable representation of Usb vid (vendor name) and pid (product name). Data is collected and stored in a local SQLite database from http://www.linux-usb.org/usb-ids.html
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;
}
}
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;
}
}
}
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();
idLocalVersion++;
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);
}
}
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);
db.execSQL("VACUUM");
onCreate(db);
}else
{
db.setVersion(oldVersion);
}
}
@Override
public void onDowngrade (SQLiteDatabase db, int oldVersion, int newVersion)
{
onUpgrade(db, oldVersion, newVersion);
}
}
}
/*
* Example of use
* @author: felhr (felhr85@gmail.com)
*/
// 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()
{
@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
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment