@@ -0,0 +1,24 @@ | |||
*.apk | |||
# Generated files | |||
bin/ | |||
gen/ | |||
# Gradle files | |||
.gradle/ | |||
build/ | |||
/*/build/ | |||
gradlew* | |||
# Local configuration file (sdk path, etc) | |||
local.properties | |||
# Proguard folder generated by Eclipse | |||
proguard/ | |||
# Log Files | |||
*.log | |||
#android-studio file | |||
.idea | |||
*.iml |
@@ -0,0 +1 @@ | |||
/build |
@@ -0,0 +1,31 @@ | |||
apply plugin: 'com.android.application' | |||
android { | |||
compileSdkVersion 23 | |||
buildToolsVersion "23.0.2" | |||
defaultConfig { | |||
applicationId "fr.mobdev.lpcprog" | |||
minSdkVersion 12 | |||
targetSdkVersion 23 | |||
versionCode 1 | |||
versionName "1.0" | |||
} | |||
buildTypes { | |||
release { | |||
minifyEnabled false | |||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' | |||
} | |||
} | |||
} | |||
repositories{ | |||
maven { url "https://jitpack.io" } | |||
} | |||
dependencies { | |||
compile 'com.android.support:appcompat-v7:23.1.1' | |||
compile 'com.android.support:design:23.1.1' | |||
//compile 'com.github.felHR85:UsbSerial:4.1.1' | |||
compile files('src/main/libs/d2xx.jar') | |||
} |
@@ -0,0 +1,17 @@ | |||
# Add project specific ProGuard rules here. | |||
# By default, the flags in this file are appended to flags specified | |||
# in /home/schoumi/projet/sdk/android-sdk/tools/proguard/proguard-android.txt | |||
# You can edit the include path and order by changing the proguardFiles | |||
# directive in build.gradle. | |||
# | |||
# For more details, see | |||
# http://developer.android.com/guide/developing/tools/proguard.html | |||
# Add any project specific keep options here: | |||
# If your project uses WebView with JS, uncomment the following | |||
# and specify the fully qualified class name to the JavaScript interface | |||
# class: | |||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { | |||
# public *; | |||
#} |
@@ -0,0 +1,57 @@ | |||
package fr.mobdev.lpcprog; | |||
import android.hardware.usb.UsbDevice; | |||
import android.hardware.usb.UsbDeviceConnection; | |||
import android.os.Build; | |||
import android.support.v7.widget.RecyclerView; | |||
import android.view.LayoutInflater; | |||
import android.view.View; | |||
import android.view.ViewGroup; | |||
import android.widget.TextView; | |||
import java.util.List; | |||
public class DeviceAdapter extends RecyclerView.Adapter<DeviceHolder> { | |||
private List<UsbDevice> devices; | |||
public DeviceAdapter(List<UsbDevice> devices){ | |||
this.devices = devices; | |||
} | |||
@Override | |||
public DeviceHolder onCreateViewHolder(ViewGroup parent, int viewType) { | |||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.device_item,parent,false); | |||
return new DeviceHolder(view); | |||
} | |||
@Override | |||
public void onBindViewHolder(DeviceHolder holder, int position) { | |||
holder.setupDevice(devices.get(position)); | |||
} | |||
@Override | |||
public int getItemCount() { | |||
return devices.size(); | |||
} | |||
} | |||
class DeviceHolder extends RecyclerView.ViewHolder { | |||
public DeviceHolder(View itemView) { | |||
super(itemView); | |||
} | |||
public void setupDevice(UsbDevice device){ | |||
if(Build.VERSION.SDK_INT >= 21) { | |||
TextView name = (TextView) itemView.findViewById(R.id.device_name); | |||
name.setText("Name: " + device.getProductName()); | |||
} | |||
TextView vendor = (TextView) itemView.findViewById(R.id.device_vendor_id); | |||
vendor.setText("Vendor Id: "+device.getVendorId()); | |||
TextView product = (TextView) itemView.findViewById(R.id.device_id); | |||
product.setText("Product id: " + device.getProductId()); | |||
} | |||
} |
@@ -0,0 +1,227 @@ | |||
package fr.mobdev.lpcprog; | |||
import android.hardware.usb.UsbDevice; | |||
import android.hardware.usb.UsbDeviceConnection; | |||
import android.provider.Settings; | |||
import com.felhr.usbserial.UsbSerialDevice; | |||
import com.felhr.usbserial.UsbSerialInterface; | |||
public class IspManager { | |||
//defines | |||
private static final int REP_BUF = 100; | |||
private static final byte[] SYNC_START = "?".getBytes(); | |||
private static final byte[] SYNC = "Synchronized\r\n".getBytes(); | |||
private static final byte[] SYNC_OK = "OK\r\n".getBytes(); | |||
private static final byte[] DATA_BLOCK = "OK\r\n".getBytes(); | |||
private static final byte[] DATA_BLOCK_RESEND = "RESEND\r\n".getBytes(); | |||
private static final byte[] SYNC_ECHO_OFF = "A 0\r\n".getBytes(); | |||
private static final byte[] READ_UID = "N\r\n".getBytes(); | |||
private static final byte[] READ_PART_ID = "J\r\n".getBytes(); | |||
private static final byte[] READ_BOOT_VERSION = "K\r\n".getBytes(); | |||
//members | |||
private static IspManager instance = null; | |||
private UsbSerialDevice serialPort = null; | |||
private IspManager(){ | |||
} | |||
public static IspManager getInstance(){ | |||
if(instance == null) | |||
instance = new IspManager(); | |||
return instance; | |||
} | |||
public boolean setupDevice(UsbDevice device, UsbDeviceConnection connection, int baudRate, int data, int stops, int parity, int flow){ | |||
serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection); | |||
if(serialPort.syncOpen()) { | |||
serialPort.setBaudRate(baudRate); | |||
serialPort.setDataBits(data); | |||
serialPort.setStopBits(stops); | |||
serialPort.setParity(parity); | |||
serialPort.setFlowControl(flow); | |||
return true; | |||
} | |||
return false; | |||
} | |||
public boolean synchronize(int crystal_freq){ | |||
if(serialPort == null) | |||
return false; | |||
byte[] buf; | |||
if(serialPort.syncWrite(SYNC_START,500) != SYNC_START.length){ | |||
System.out.println("Start"); | |||
return false; | |||
} | |||
buf = new byte[SYNC.length]; | |||
serialPort.syncRead(buf,500); | |||
String result = new String(buf); | |||
String expected = new String(SYNC); | |||
if(result.compareTo(expected) != 0) { | |||
printbuffer(buf); | |||
System.out.println("Start answer "+result); | |||
return false; | |||
} | |||
if(serialPort.syncWrite(SYNC,500) != SYNC.length) { | |||
System.out.println("SYNC write"); | |||
return false; | |||
} | |||
clearBuffer(SYNC.length); | |||
buf = new byte[SYNC_OK.length]; | |||
serialPort.syncRead(buf,500); | |||
result = new String(buf); | |||
expected = new String(SYNC_OK); | |||
if(result.compareTo(expected) != 0) { | |||
printbuffer(buf); | |||
System.out.println("SYNC OK "+result); | |||
return false; | |||
} | |||
String freq = String.valueOf(crystal_freq)+"\r\n"; | |||
if(serialPort.syncWrite(freq.getBytes(),500) != freq.length()) { | |||
System.out.println("freq write"); | |||
return false; | |||
} | |||
clearBuffer(freq.length()); | |||
buf = new byte[SYNC_OK.length]; | |||
serialPort.syncRead(buf,500); | |||
result = new String(buf); | |||
expected = new String(SYNC_OK); | |||
if(result.compareTo(expected) != 0) { | |||
System.out.println("freq answer "+result); | |||
printbuffer(buf); | |||
return false; | |||
} | |||
if(serialPort.syncWrite(SYNC_ECHO_OFF,500) != SYNC_ECHO_OFF.length) { | |||
System.out.println("Sync Echo Off write"); | |||
return false; | |||
} | |||
clearBuffer(SYNC_ECHO_OFF.length); | |||
buf = new byte[3]; | |||
serialPort.syncRead(buf,500); | |||
return true; | |||
} | |||
private void printbuffer(byte[] buffer){ | |||
for(int i = 0; i < buffer.length; i++){ | |||
System.out.println(String.format("%02x",buffer[i])); | |||
} | |||
} | |||
private void clearBuffer(int size){ | |||
if(serialPort == null) | |||
return; | |||
byte[] buf = new byte[size]; | |||
int cpt=0; | |||
do{ | |||
int nb = serialPort.syncRead(buf,500); | |||
System.out.println(String.format("%02x",buf[0])); | |||
break;/* | |||
if(nb < 0){ | |||
cpt++; | |||
if(cpt >=100) { | |||
System.out.println("timeout"); | |||
break; | |||
} | |||
} else if( nb == 0){ | |||
System.out.println("nb = 0"); | |||
return; | |||
}*/ | |||
}while(buf[0] == '\r' && buf[0] != '\n'); | |||
if(buf[0] == '\r') { | |||
serialPort.syncRead(buf, 5); | |||
System.out.println(String.format("%02x", buf[0])); | |||
} | |||
System.out.println("end"); | |||
} | |||
public String[] readUid(){ | |||
if(serialPort == null) | |||
return null; | |||
byte[] buf = new byte[REP_BUF]; | |||
int ret = sendCommand(READ_UID,null); | |||
if(ret != 0){ | |||
System.out.println("Send Command "+ret); | |||
return null; | |||
} | |||
int size = serialPort.syncRead(buf,1); | |||
if(size<=0){ | |||
System.out.println("Send size "+size); | |||
return null; | |||
} | |||
String[] uids = new String[4]; | |||
for(int i = 0; i < 4; i++){ | |||
uids[0] = Long.toHexString(byteArrayToLong(buf,8*i+i*2)); | |||
} | |||
System.out.println("uids ok"); | |||
return uids; | |||
} | |||
public String readPartId(){ | |||
return null; | |||
} | |||
public String[] readBootVersion(){ | |||
return null; | |||
} | |||
public int sendCommand(byte[] cmd, String[] args){ | |||
byte[] buf = new byte[3]; | |||
if(serialPort.syncWrite(cmd,15) != cmd.length) | |||
return -5; | |||
int len = serialPort.syncRead(buf, 15); | |||
System.out.println("Len "+len); | |||
for(int i = 0; i < 3; i++){ | |||
System.out.println(String.format("%02x", buf[i])); | |||
} | |||
if(len <= 0) | |||
return -4; | |||
int ret = parseRetCode(buf); | |||
return ret; | |||
} | |||
private int parseRetCode(byte[] data){ | |||
String str = new String(data); | |||
str = str.replace("\r\n",""); | |||
int ret = Integer.parseInt(str); | |||
//int ret = byteArrayToInt(data,0); | |||
return ret; | |||
} | |||
private int byteArrayToInt(byte[] array, int offset){ | |||
int value = 0; | |||
value |= (array[offset] & 0xff) << 24; | |||
value |= (array[offset+1] & 0xff) << 16; | |||
value |= (array[offset+2] & 0xff) << 8; | |||
value |= (array[offset+3] & 0xff); | |||
return value; | |||
} | |||
private long byteArrayToLong(byte[] array, int offset){ | |||
long value = 0; | |||
value |= (array[offset] & 0xff) << 56; | |||
value |= (array[offset+1] & 0xff) << 48; | |||
value |= (array[offset+2] & 0xff) << 40; | |||
value |= (array[offset+3] & 0xff) << 32; | |||
value |= (array[offset+4] & 0xff) << 24; | |||
value |= (array[offset+5] & 0xff) << 16; | |||
value |= (array[offset+6] & 0xff) << 8; | |||
value |= (array[offset+7] & 0xff); | |||
return value; | |||
} | |||
} | |||
@@ -0,0 +1,80 @@ | |||
package fr.mobdev.lpcprog; | |||
import android.app.Activity; | |||
import android.app.PendingIntent; | |||
import android.content.Context; | |||
import android.content.Intent; | |||
import android.content.IntentFilter; | |||
import android.hardware.usb.UsbDevice; | |||
import android.hardware.usb.UsbDeviceConnection; | |||
import android.hardware.usb.UsbManager; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
public class UsbComm { | |||
private static final String ACTION_USB_PERMISSION = "fr.mobdev.usb_perm"; | |||
private UsbManager manager = null; | |||
private UsbDeviceConnection connection = null; | |||
private static int val = 0; | |||
private UsbDevice device = null; | |||
public UsbComm(Context context){ | |||
manager = (UsbManager) context.getSystemService(Context.USB_SERVICE); | |||
} | |||
public boolean searchForDevice(){ | |||
HashMap<String, UsbDevice> usbDevices = manager.getDeviceList(); | |||
if(!usbDevices.isEmpty()) { | |||
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) { | |||
UsbDevice device = entry.getValue(); | |||
int deviceVID = device.getVendorId(); | |||
int devicePID = device.getProductId(); | |||
if (deviceVID != 0x1d6b && devicePID != 0x0001 && devicePID != 0x0002 && devicePID != 0x0003) { | |||
return true; | |||
} | |||
} | |||
} | |||
return false; | |||
} | |||
public List<UsbDevice> getDevices(){ | |||
List<UsbDevice> devices = new ArrayList<>(); | |||
HashMap<String, UsbDevice> usbDevices = manager.getDeviceList(); | |||
if(!usbDevices.isEmpty()) { | |||
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) { | |||
UsbDevice device = entry.getValue(); | |||
int deviceVID = device.getVendorId(); | |||
int devicePID = device.getProductId(); | |||
if (deviceVID != 0x1d6b && devicePID != 0x0001 && devicePID != 0x0002 && devicePID != 0x0003) { | |||
devices.add(device); | |||
} | |||
} | |||
} | |||
return devices; | |||
} | |||
public boolean askForPermission(UsbDevice device, Activity activity){ | |||
if(!manager.hasPermission(device)) { | |||
PendingIntent intent = PendingIntent.getBroadcast(activity, 0, new Intent(ACTION_USB_PERMISSION), 0); | |||
manager.requestPermission(device, intent); | |||
return false; | |||
} | |||
return true; | |||
} | |||
public UsbDeviceConnection openConnection(UsbDevice device, Activity activity){ | |||
if(!manager.hasPermission(device)) { | |||
askForPermission(device, activity); | |||
return null; | |||
} | |||
if(connection == null || this.device != device) { | |||
connection = manager.openDevice(device); | |||
this.device = device; | |||
} | |||
return connection; | |||
} | |||
} | |||
@@ -0,0 +1,13 @@ | |||
package fr.mobdev.lpcprog; | |||
import android.app.Application; | |||
import android.test.ApplicationTestCase; | |||
/** | |||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a> | |||
*/ | |||
public class ApplicationTest extends ApplicationTestCase<Application> { | |||
public ApplicationTest() { | |||
super(Application.class); | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |||
package="fr.mobdev.lpcprog"> | |||
<uses-feature | |||
android:name="android.hardware.usb.host" | |||
android:required="true" /> | |||
<application | |||
android:allowBackup="true" | |||
android:icon="@mipmap/ic_launcher" | |||
android:label="@string/app_name" | |||
android:theme="@style/AppTheme"> | |||
<activity | |||
android:name=".MainActivity" | |||
android:label="@string/app_name" | |||
android:theme="@style/AppTheme.NoActionBar"> | |||
<intent-filter> | |||
<action android:name="android.intent.action.MAIN" /> | |||
<category android:name="android.intent.category.LAUNCHER" /> | |||
</intent-filter> | |||
</activity> | |||
<activity android:name=".DeviceActivity"></activity> | |||
</application> | |||
</manifest> |
@@ -0,0 +1,92 @@ | |||
package fr.mobdev.lpcprog; | |||
import android.support.v7.app.AppCompatActivity; | |||
import android.os.Bundle; | |||
import android.widget.TextView; | |||
import java.util.List; | |||
public class DeviceActivity extends AppCompatActivity { | |||
private UsbComm comm; | |||
private USBDevice dev; | |||
@Override | |||
protected void onCreate(Bundle savedInstanceState) { | |||
super.onCreate(savedInstanceState); | |||
setContentView(R.layout.device); | |||
comm = UsbComm.getInstance(this); | |||
List<USBDevice> devices = comm.getDevices(); | |||
int pid = getIntent().getIntExtra("PID",-1); | |||
int vid = getIntent().getIntExtra("VID",-1); | |||
for(USBDevice device : devices){ | |||
if(device.PID == pid && device.VID == vid){ | |||
dev = device; | |||
System.out.println("device found"); | |||
break; | |||
} | |||
} | |||
if(dev != null) { | |||
TextView name = (TextView) findViewById(R.id.name); | |||
name.setText("Name: " + dev.description); | |||
TextView vendor = (TextView) findViewById(R.id.vendor_id); | |||
vendor.setText(String.format("Vendor Id: %04x", dev.VID)); | |||
TextView product = (TextView) findViewById(R.id.id); | |||
product.setText(String.format("Product id: %04x", dev.PID)); | |||
} | |||
doUsb(); | |||
} | |||
private void doUsb(){ | |||
System.out.println("doUsb"); | |||
new Thread(new Runnable() { | |||
@Override | |||
public void run() { | |||
boolean conn = comm.openConnection(dev); | |||
IspManager manager = IspManager.getInstance(); | |||
String uidStr = "No UID Found or error"; | |||
String bootStr = "No Boot Version Found or error"; | |||
String partidStr = "No Part ID Found or error"; | |||
if(conn && manager.setupDevice(dev, 115200)) { | |||
if(!manager.synchronizeIfPossible(10000)) { | |||
System.out.println("Sync failed :("); | |||
return; | |||
} | |||
String[] version = manager.readBootVersion(); | |||
String partid = manager.readPartId(); | |||
String[] uids = manager.readUid(); | |||
if (uids != null) { | |||
uidStr = String.format("UID: %08x - %08x - %08x - %08x",Long.parseLong(uids[0]), | |||
Long.parseLong(uids[1]), | |||
Long.parseLong(uids[2]), | |||
Long.parseLong(uids[3])); | |||
} | |||
if (version != null) { | |||
bootStr = "Boot Version: " + version[0] + "." + version[1]; | |||
} | |||
if(partid != null){ | |||
partidStr = String.format("Part Id %08x",Long.parseLong(partid)); | |||
} | |||
} | |||
updateIDS(uidStr,partidStr,bootStr); | |||
} | |||
}).start(); | |||
} | |||
private void updateIDS(final String uid, final String partid, final String boot) { | |||
runOnUiThread(new Runnable() { | |||
@Override | |||
public void run() { | |||
TextView view = (TextView) findViewById(R.id.uids); | |||
view.setText(uid); | |||
view = (TextView) findViewById(R.id.part_id); | |||
view.setText(partid); | |||
view = (TextView) findViewById(R.id.boot_version); | |||
view.setText(boot); | |||
} | |||
}); | |||
} | |||
} |
@@ -0,0 +1,55 @@ | |||
package fr.mobdev.lpcprog; | |||
import android.hardware.usb.UsbDevice; | |||
import android.hardware.usb.UsbDeviceConnection; | |||
import android.os.Build; | |||
import android.support.v7.widget.RecyclerView; | |||
import android.view.LayoutInflater; | |||
import android.view.View; | |||
import android.view.ViewGroup; | |||
import android.widget.TextView; | |||
import java.util.List; | |||
public class DeviceAdapter extends RecyclerView.Adapter<DeviceHolder> { | |||
private List<USBDevice> devices; | |||
public DeviceAdapter(List<USBDevice> devices){ | |||
this.devices = devices; | |||
} | |||
@Override | |||
public DeviceHolder onCreateViewHolder(ViewGroup parent, int viewType) { | |||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.device_item,parent,false); | |||
return new DeviceHolder(view); | |||
} | |||
@Override | |||
public void onBindViewHolder(DeviceHolder holder, int position) { | |||
holder.setupDevice(devices.get(position)); | |||
} | |||
@Override | |||
public int getItemCount() { | |||
return devices.size(); | |||
} | |||
} | |||
class DeviceHolder extends RecyclerView.ViewHolder { | |||
public DeviceHolder(View itemView) { | |||
super(itemView); | |||
} | |||
public void setupDevice(USBDevice device){ | |||
TextView name = (TextView) itemView.findViewById(R.id.device_name); | |||
name.setText("Name: " + device.description); | |||
TextView vendor = (TextView) itemView.findViewById(R.id.device_vendor_id); | |||
vendor.setText(String.format("Vendor Id: %04x",device.VID)); | |||
TextView product = (TextView) itemView.findViewById(R.id.device_id); | |||
product.setText(String.format("Product id: %04x", device.PID)); | |||
} | |||
} |
@@ -0,0 +1,316 @@ | |||
package fr.mobdev.lpcprog; | |||
import com.ftdi.j2xx.D2xxManager; | |||
import com.ftdi.j2xx.FT_Device; | |||
import java.nio.ByteBuffer; | |||
import java.util.Locale; | |||
public class IspManager { | |||
//defines | |||
private static final int REP_BUF = 100; | |||
private static final byte[] SYNC_START = "?".getBytes(); | |||
private static final byte[] SYNC = "Synchronized\r\n".getBytes(); | |||
private static final byte[] SYNC_OK = "OK\r\n".getBytes(); | |||
private static final byte[] DATA_BLOCK = "OK\r\n".getBytes(); | |||
private static final byte[] DATA_BLOCK_RESEND = "RESEND\r\n".getBytes(); | |||
private static final byte[] SYNC_ECHO_OFF = "A 0\r\n".getBytes(); | |||
private static final byte[] READ_UID = "N\r\n".getBytes(); | |||
private static final byte[] READ_PART_ID = "J\r\n".getBytes(); | |||
private static final byte[] READ_BOOT_VERSION = "K\r\n".getBytes(); | |||
//members | |||
private static IspManager instance = null; | |||
private FT_Device serialPort = null; | |||
private IspManager(){ | |||
} | |||
public static IspManager getInstance(){ | |||
if(instance == null) | |||
instance = new IspManager(); | |||
return instance; | |||
} | |||
public boolean setupDevice(USBDevice device, int baudRate){ | |||
serialPort = device.device; | |||
if(serialPort != null) | |||
serialPort.resetDevice(); | |||
else | |||
System.out.println("device is null fuck"); | |||
if(serialPort!=null && serialPort.isOpen()){ | |||
serialPort.setBaudRate(baudRate); | |||
byte dc1=0x11; | |||
byte dc3=0x13; | |||
serialPort.setFlowControl(D2xxManager.FT_FLOW_XON_XOFF,dc1,dc3); | |||
serialPort.setDataCharacteristics(D2xxManager.FT_DATA_BITS_8,D2xxManager.FT_STOP_BITS_1,D2xxManager.FT_PARITY_NONE); | |||
byte l = 0x2; | |||
serialPort.setLatencyTimer(l); | |||
return true; | |||
} | |||
return false; | |||
} | |||
public boolean synchronize(int crystal_freq){ | |||
if(serialPort == null) | |||
return false; | |||
serialPort.purge(D2xxManager.FT_PURGE_RX); | |||
serialPort.purge(D2xxManager.FT_PURGE_TX); | |||
byte[] buf; | |||
if(serialPort.write(SYNC_START) != SYNC_START.length){ | |||
System.out.println("Start"); | |||
return false; | |||
} | |||
buf = new byte[SYNC.length]; | |||
serialPort.read(buf,buf.length,500); | |||
String result = new String(buf); | |||
String expected = new String(SYNC); | |||
if(result.compareTo(expected) != 0) { | |||
printbuffer(buf); | |||
serialPort.write("\r\n".getBytes()); | |||
System.out.println("Start answer "+result); | |||
return false; | |||
} | |||
if(serialPort.write(SYNC) != SYNC.length) { | |||
System.out.println("SYNC write"); | |||
return false; | |||
} | |||
clearBuffer(SYNC.length); | |||
buf = new byte[SYNC_OK.length]; | |||
serialPort.read(buf,buf.length,500); | |||
result = new String(buf); | |||
expected = new String(SYNC_OK); | |||
if(result.compareTo(expected) != 0) { | |||
printbuffer(buf); | |||
System.out.println("SYNC OK "+result); | |||
return false; | |||
} | |||
String freq = String.valueOf(crystal_freq)+"\r\n"; | |||
if(serialPort.write(freq.getBytes()) != freq.length()) { | |||
System.out.println("freq write"); | |||
return false; | |||
} | |||
clearBuffer(freq.length()); | |||
buf = new byte[SYNC_OK.length]; | |||
serialPort.read(buf,buf.length,500); | |||
result = new String(buf); | |||
expected = new String(SYNC_OK); | |||
if(result.compareTo(expected) != 0) { | |||
System.out.println("freq answer "+result); | |||
printbuffer(buf); | |||
return false; | |||
} | |||
if(serialPort.write(SYNC_ECHO_OFF) != SYNC_ECHO_OFF.length) { | |||
System.out.println("Sync Echo Off write"); | |||
return false; | |||
} | |||
clearBuffer(SYNC_ECHO_OFF.length); | |||
buf = new byte[3]; | |||
int ret = serialPort.read(buf,buf.length,500); | |||
System.out.println(String.format(Locale.getDefault(),"%d %02x %02x %02x",ret,buf[0],buf[1],buf[2])); | |||
return true; | |||
} | |||
private void printbuffer(byte[] buffer){ | |||
for(byte b : buffer){ | |||
System.out.println(String.format("%02x",b)); | |||
} | |||
} | |||
private void clearBuffer(int size){ | |||
if(serialPort == null) | |||
return; | |||
byte[] buf = new byte[size]; | |||
int readed = read(buf,size,500); | |||
System.out.println("end "+(size-readed)); | |||
} | |||
public String[] readUid(){ | |||
if(serialPort == null) | |||
return null; | |||
int ret = sendCommand(READ_UID,null); | |||
if(ret != 0){ | |||
System.out.println("Send Command "+ret); | |||
return null; | |||
} | |||
byte[] buf = new byte[REP_BUF]; | |||
int size = read(buf,50,500); | |||
for(int i = 0; i < size; i++){ | |||
System.out.println(String.format("%02x", buf[i])); | |||
} | |||
if(size<=0){ | |||
System.out.println("Send size "+size); | |||
return null; | |||
} | |||
String[] uids = new String[4]; | |||
String buffer = new String(buf); | |||
if(buffer.contains("\r") && buffer.contains("\n")) | |||
buffer = buffer.replace("\n",""); | |||
else if(!buffer.contains("\r") && buffer.contains("\n")) | |||
buffer = buffer.replace("\n","\r"); | |||
for(int i = 0; i < 4; i++){ | |||
if(buffer.contains("\r")) { | |||
uids[i] = buffer.substring(0, buffer.indexOf("\r")); | |||
buffer = buffer.substring(buffer.indexOf("\r")+1); | |||
} | |||
} | |||
System.out.println("uids ok"); | |||
return uids; | |||
} | |||
public String readPartId(){ | |||
if(serialPort == null) | |||
return null; | |||
int ret = sendCommand(READ_PART_ID,null); | |||
if(ret != 0) | |||
return null; | |||
byte[] buf = new byte[REP_BUF]; | |||
int size = read(buf,20,500); | |||
if(size <= 0) | |||
return null; | |||
String partId = new String(buf); | |||
partId = partId.substring(0,partId.indexOf("\r\n")); | |||
if(partId.contains("\r")) | |||
partId = partId.replace("\r",""); | |||
if(partId.contains("\n")) | |||
partId = partId.replace("\n",""); | |||
return partId; | |||
} | |||
public String[] readBootVersion(){ | |||
if(serialPort == null) | |||
return null; | |||
int ret = sendCommand(READ_BOOT_VERSION,null); | |||
if(ret != 0){ | |||
System.out.println("Send Command "+ret); | |||
return null; | |||
} | |||
byte[] buf = new byte[REP_BUF]; | |||
int size = read(buf,50,500); | |||
if(size <= 0){ | |||
System.out.println("Receive "+size); | |||
return null; | |||
} | |||
String[] version = new String[2]; | |||
String buffer = new String(buf); | |||
if(buffer.contains("\r") && buffer.contains("\n")) | |||
buffer = buffer.replace("\n",""); | |||
else if(!buffer.contains("\r") && buffer.contains("\n")) | |||
buffer = buffer.replace("\n","\r"); | |||
for(int i = 0; i < 2; i++){ | |||
if(buffer.contains("\r")) { | |||
version[i] = buffer.substring(0, buffer.indexOf("\r")); | |||
buffer = buffer.substring(buffer.indexOf("\r")+1); | |||
} | |||
} | |||
return version; | |||
} | |||
public int sendCommand(byte[] cmd, String[] args){ | |||
byte[] buf = new byte[3]; | |||
if(serialPort.write(cmd) != cmd.length) | |||
return -5; | |||
int len = read(buf, buf.length,500); | |||
System.out.println("Len "+len); | |||
for(int i = 0; i < 3; i++){ | |||
System.out.println(String.format("%02x", buf[i])); | |||
} | |||
if(len <= 0) | |||
return -4; | |||
return parseRetCode(buf); | |||
} | |||
public int read(byte[] buffer, int size, int timeout){ | |||
long startTime = System.nanoTime(); | |||
long timeoutNano = timeout * 1000000; | |||
int sizeRead = 0; | |||
ByteBuffer output = ByteBuffer.wrap(buffer,0,size); | |||
while(sizeRead < size){ | |||
int sizeToRead = serialPort.getQueueStatus(); | |||
if(sizeRead + sizeToRead > size) | |||
sizeToRead = size - sizeRead; | |||
byte[] buf = new byte[sizeToRead]; | |||
if(sizeToRead > 0) { | |||
int sizeReceived = serialPort.read(buf, sizeToRead, 50); | |||
if (sizeReceived < 0) | |||
return sizeReceived; | |||
sizeRead += sizeReceived; | |||
if (sizeReceived != 0) | |||
output.put(buf, 0, sizeReceived); | |||
} | |||
long time = System.nanoTime(); | |||
if(time - startTime >= timeoutNano) | |||
break; | |||
} | |||
return sizeRead; | |||
} | |||
private int parseRetCode(byte[] data){ | |||
String str = new String(data); | |||
str = str.replace("\r\n",""); | |||
return Integer.parseInt(str); | |||
} | |||
public boolean synchronizeIfPossible(int crystal_freq) { | |||
if(!synchronize(crystal_freq)) { | |||
serialPort.purge(D2xxManager.FT_PURGE_TX); | |||
serialPort.purge(D2xxManager.FT_PURGE_RX); | |||
String[] uids = readUid(); | |||
if (uids == null) { | |||
System.out.println("uids null fuck"); | |||
return false; | |||
} | |||
} | |||
return true; | |||
} | |||
/*private int byteArrayToInt(byte[] array, int offset){ | |||
int value = 0; | |||
value |= (array[offset] & 0xff) << 24; | |||
value |= (array[offset+1] & 0xff) << 16; | |||
value |= (array[offset+2] & 0xff) << 8; | |||
value |= (array[offset+3] & 0xff); | |||
return value; | |||
} | |||
private long byteArrayToLong(byte[] array, int offset){ | |||
long value = 0; | |||
value |= (array[offset] & 0xff) << 56; | |||
value |= (array[offset+1] & 0xff) << 48; | |||
value |= (array[offset+2] & 0xff) << 40; | |||
value |= (array[offset+3] & 0xff) << 32; | |||
value |= (array[offset+4] & 0xff) << 24; | |||
value |= (array[offset+5] & 0xff) << 16; | |||
value |= (array[offset+6] & 0xff) << 8; | |||
value |= (array[offset+7] & 0xff); | |||
return value; | |||
}*/ | |||
} | |||
@@ -0,0 +1,94 @@ | |||
package fr.mobdev.lpcprog; | |||
import android.content.Intent; | |||
import android.os.Bundle; | |||
import android.support.v7.app.AppCompatActivity; | |||
import android.support.v7.widget.LinearLayoutManager; | |||
import android.support.v7.widget.RecyclerView; | |||
import android.support.v7.widget.Toolbar; | |||
import android.view.GestureDetector; | |||
import android.view.Menu; | |||
import android.view.MenuItem; | |||
import android.view.MotionEvent; | |||
import android.view.View; | |||
import android.widget.Toast; | |||
import java.util.List; | |||
public class MainActivity extends AppCompatActivity { | |||
private UsbComm comm; | |||
private List<USBDevice> devices; | |||
private int value = 0; | |||
@Override | |||
protected void onCreate(Bundle savedInstanceState) { | |||
super.onCreate(savedInstanceState); | |||
setContentView(R.layout.main_activity); | |||
Toolbar toolbar = (Toolbar) findViewById(R.id.main_toolbar); | |||
setSupportActionBar(toolbar); | |||
comm = UsbComm.getInstance(this); | |||
final GestureDetector gestureDetector = new GestureDetector(MainActivity.this, new GestureDetector.SimpleOnGestureListener(){ | |||
@Override | |||
public boolean onSingleTapUp(MotionEvent e){ | |||
return true; | |||
} | |||
}); | |||
RecyclerView view = (RecyclerView) findViewById(R.id.device_list); | |||
view.setLayoutManager(new LinearLayoutManager(this)); | |||
view.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() { | |||
@Override | |||
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e){ | |||
View v = view.findChildViewUnder(e.getX(), e.getY()); | |||
if(v != null && gestureDetector.onTouchEvent(e)){ | |||
int pos = view.getChildAdapterPosition(v); | |||
System.out.println("touch "+ ++value); | |||
onItemClick(pos); | |||
return true; | |||
} | |||
return false; | |||
} | |||
}); | |||
updateList(); | |||
} | |||
@Override | |||
public boolean onCreateOptionsMenu(Menu menu) { | |||
getMenuInflater().inflate(R.menu.menu_main, menu); | |||
return true; | |||
} | |||
@Override | |||
public boolean onOptionsItemSelected(MenuItem item) { | |||
int id = item.getItemId(); | |||
if (id == R.id.action_refresh) { | |||
updateList(); | |||
return true; | |||
} | |||
return super.onOptionsItemSelected(item); | |||
} | |||
private void updateList(){ | |||
devices = comm.getDevices(); | |||
DeviceAdapter adapter = new DeviceAdapter(devices); | |||
RecyclerView view = (RecyclerView) findViewById(R.id.device_list); | |||
view.setAdapter(adapter); | |||
} | |||
private void onItemClick(final int pos){ | |||
if(devices.size()>pos){ | |||
Intent intent = new Intent(this,DeviceActivity.class); | |||
intent.putExtra("PID",devices.get(pos).PID); | |||
intent.putExtra("VID",devices.get(pos).VID); | |||
startActivity(intent); | |||
} | |||
} | |||
} |
@@ -0,0 +1,10 @@ | |||
package fr.mobdev.lpcprog; | |||
import com.ftdi.j2xx.FT_Device; | |||
public class USBDevice { | |||
public int PID; | |||
public int VID; | |||
public String description; | |||
public FT_Device device; | |||
} |
@@ -0,0 +1,89 @@ | |||
package fr.mobdev.lpcprog; | |||
import android.content.Context; | |||
import com.ftdi.j2xx.D2xxManager; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
public class UsbComm { | |||
private static UsbComm instance = null; | |||
private D2xxManager manager = null; | |||
private Context context; | |||
List<USBDevice> openedDevices; | |||
private UsbComm(Context context){ | |||
openedDevices = new ArrayList<>(); | |||
try { | |||
manager = D2xxManager.getInstance(context); | |||
this.context = context; | |||
} catch (D2xxManager.D2xxException e) { | |||
e.printStackTrace(); | |||
} | |||
} | |||
public static UsbComm getInstance(Context context){ | |||
if(instance == null) | |||
instance = new UsbComm(context); | |||
return instance; | |||
} | |||
public List<USBDevice> getDevices(){ | |||
if(manager == null) | |||
return null; | |||
List<USBDevice> devicesList = new ArrayList<>(); | |||
int deviceCount = manager.createDeviceInfoList(context); | |||
if(deviceCount > 0) { | |||
D2xxManager.FtDeviceInfoListNode[] devices = new D2xxManager.FtDeviceInfoListNode[deviceCount]; | |||
manager.getDeviceInfoList(deviceCount, devices); | |||
for (int i = 0; i < deviceCount; i++) { | |||
int deviceVID = devices[i].id >> 16; | |||
int devicePID = devices[i].id & 0xFFFF; | |||
if (deviceVID != 0x1d6b && devicePID != 0x0001 && devicePID != 0x0002 && devicePID != 0x0003) { | |||
USBDevice device = new USBDevice(); | |||
device.VID = deviceVID; | |||
device.PID = devicePID; | |||
device.description = devices[i].description; | |||
devicesList.add(device); | |||
} | |||
} | |||
} | |||
return devicesList; | |||
} | |||
public boolean openConnection(USBDevice device) { | |||
if(manager == null) | |||
return false; | |||
int deviceCount = manager.createDeviceInfoList(context); | |||
if (deviceCount > 0) { | |||
D2xxManager.FtDeviceInfoListNode[] devices = new D2xxManager.FtDeviceInfoListNode[deviceCount]; | |||
manager.getDeviceInfoList(deviceCount,devices); | |||
for (USBDevice dev : openedDevices) { | |||
if(dev.PID == device.PID && dev.VID == device.VID && dev.device.isOpen()){ | |||
device.device = dev.device; | |||
return true; | |||
} | |||
else if(dev.PID == device.PID && dev.VID == device.VID && !dev.device.isOpen()){ | |||
openedDevices.remove(dev); | |||
} | |||
} | |||
for (int i = 0; i < deviceCount; i++) { | |||
int deviceVID = devices[i].id >> 16; | |||
int devicePID = devices[i].id & 0xFFFF; | |||
if (deviceVID == device.VID && devicePID == device.PID) { | |||
device.device = manager.openByIndex(context,i); | |||
if(device.device != null) | |||
openedDevices.add(device); | |||
return true; | |||
} | |||
} | |||
} | |||
return false; | |||
} | |||
} | |||
@@ -0,0 +1,23 @@ | |||
{ | |||
"images": [ | |||
{ | |||
"filename": "ic_cached_white.png", | |||
"idiom": "universal", | |||
"scale": "1x" | |||
}, | |||
{ | |||
"filename": "ic_cached_white_2x.png", | |||
"idiom": "universal", | |||
"scale": "2x" | |||
}, | |||
{ | |||
"filename": "ic_cached_white_3x.png", | |||
"idiom": "universal", | |||
"scale": "3x" | |||
} | |||
], | |||
"info": { | |||
"author": "xcode", | |||
"version": 1 | |||
} | |||
} |
@@ -0,0 +1,55 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
android:paddingBottom="@dimen/activity_vertical_margin" | |||
android:paddingLeft="@dimen/activity_horizontal_margin" | |||
android:paddingRight="@dimen/activity_horizontal_margin" | |||
android:paddingTop="@dimen/activity_vertical_margin" | |||
tools:context="fr.mobdev.lpcprog.DeviceActivity"> | |||
<LinearLayout | |||
android:id="@+id/device_info" | |||
android:layout_alignParentTop="true" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
android:orientation="vertical"> | |||
<TextView | |||
android:id="@+id/name" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" /> | |||
<TextView | |||
android:id="@+id/vendor_id" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" /> | |||
<TextView | |||
android:id="@+id/id" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" /> | |||
</LinearLayout> | |||
<LinearLayout | |||
android:id="@+id/lpc_info" | |||
android:layout_below="@id/device_info" | |||
android:orientation="vertical" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content"> | |||
<TextView | |||
android:id="@+id/uids" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" /> | |||
<TextView | |||
android:id="@+id/part_id" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" /> | |||
<TextView | |||
android:id="@+id/boot_version" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" /> | |||
</LinearLayout> | |||
<android.support.v7.widget.RecyclerView | |||
android:id="@+id/bin_list" | |||
android:layout_below="@id/lpc_info" | |||
android:layout_alignParentBottom="true" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content"/> | |||
</RelativeLayout> |
@@ -0,0 +1,23 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<LinearLayout | |||
xmlns:android="http://schemas.android.com/apk/res/android" | |||
android:orientation="vertical" | |||
android:layout_width="match_parent" | |||
android:layout_height="100dp"> | |||
<TextView | |||
android:textStyle="bold" | |||
android:id="@+id/device_name" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
/> | |||
<TextView | |||
android:id="@+id/device_vendor_id" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
/> | |||
<TextView | |||
android:id="@+id/device_id" | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
/> | |||
</LinearLayout> |
@@ -0,0 +1,33 @@ | |||
<android.support.design.widget.CoordinatorLayout | |||
xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
android:fitsSystemWindows="true" | |||
android:layout_height="match_parent" | |||
android:layout_width="match_parent" | |||
tools:context="fr.mobdev.lpcprog.MainActivity" | |||
> | |||
<android.support.design.widget.AppBarLayout | |||
android:layout_width="match_parent" | |||
android:layout_height="wrap_content" | |||
android:theme="@style/AppTheme.PopupOverlay"> | |||
<android.support.v7.widget.Toolbar | |||
android:id="@+id/main_toolbar" | |||
android:layout_width="match_parent" | |||
android:layout_height="?attr/actionBarSize" | |||
android:background="?attr/colorPrimary" | |||
app:popupTheme="@style/AppTheme.PopupOverlay" | |||
/> | |||
</android.support.design.widget.AppBarLayout> | |||
<android.support.v7.widget.RecyclerView | |||
app:layout_behavior="@string/appbar_scrolling_view_behavior" | |||
android:id="@+id/device_list" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent"> | |||
</android.support.v7.widget.RecyclerView> | |||
</android.support.design.widget.CoordinatorLayout> |
@@ -0,0 +1,9 @@ | |||
<menu xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:app="http://schemas.android.com/apk/res-auto" | |||
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity"> | |||
<item | |||
android:id="@+id/action_refresh" | |||
android:title="@string/str_refresh" | |||
android:icon="@drawable/ic_refresh" | |||
app:showAsAction="ifRoom" /> | |||
</menu> |
@@ -0,0 +1,6 @@ | |||
<resources> | |||
<!-- Example customization of dimensions originally defined in res/values/dimens.xml | |||
(such as screen margins) for screens with more than 820dp of available width. This | |||
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). --> | |||
<dimen name="activity_horizontal_margin">64dp</dimen> | |||
</resources> |
@@ -0,0 +1,6 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<resources> | |||
<color name="colorPrimaryDark">#000000</color> | |||
<color name="colorPrimary">#000000</color> | |||
<color name="colorAccent">#FFFFFF</color> | |||
</resources> |
@@ -0,0 +1,5 @@ | |||
<resources> | |||
<!-- Default screen margins, per the Android Design guidelines. --> | |||
<dimen name="activity_horizontal_margin">16dp</dimen> | |||
<dimen name="activity_vertical_margin">16dp</dimen> | |||
</resources> |
@@ -0,0 +1,6 @@ | |||
<resources> | |||
<string name="app_name">LPCProg</string> | |||
<string name="hello_world">Hello world!</string> | |||
<string name="str_refresh">Refresh</string> | |||
</resources> |
@@ -0,0 +1,18 @@ | |||
<resources> | |||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> | |||
<!-- Customize your theme here. --> | |||
<item name="colorPrimary">@color/colorPrimary</item> | |||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item> | |||
<item name="colorAccent">@color/colorAccent</item> | |||
</style> | |||
<style name="AppTheme.NoActionBar"> | |||
<item name="windowActionBar">false</item> | |||
<item name="windowNoTitle">true</item> | |||
</style> | |||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/> | |||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Dark"/> | |||
</resources> |
@@ -0,0 +1,19 @@ | |||
// Top-level build file where you can add configuration options common to all sub-projects/modules. | |||
buildscript { | |||
repositories { | |||
jcenter() | |||
} | |||
dependencies { | |||
classpath 'com.android.tools.build:gradle:1.5.0' | |||
// NOTE: Do not place your application dependencies here; they belong | |||
// in the individual module build.gradle files | |||
} | |||
} | |||
allprojects { | |||
repositories { | |||
jcenter() | |||
} | |||
} |
@@ -0,0 +1,18 @@ | |||
# Project-wide Gradle settings. | |||
# IDE (e.g. Android Studio) users: | |||
# Gradle settings configured through the IDE *will override* | |||
# any settings specified in this file. | |||
# For more details on how to configure your build environment visit | |||
# http://www.gradle.org/docs/current/userguide/build_environment.html | |||
# Specifies the JVM arguments used for the daemon process. | |||
# The setting is particularly useful for tweaking memory settings. | |||
# Default value: -Xmx10248m -XX:MaxPermSize=256m | |||
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 | |||
# When configured, Gradle will run in incubating parallel mode. | |||
# This option should only be used with decoupled projects. More details, visit | |||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects | |||
# org.gradle.parallel=true |
@@ -0,0 +1,6 @@ | |||
#Wed Apr 10 15:27:10 PDT 2013 | |||
distributionBase=GRADLE_USER_HOME | |||
distributionPath=wrapper/dists | |||
zipStoreBase=GRADLE_USER_HOME | |||
zipStorePath=wrapper/dists | |||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip |
@@ -0,0 +1 @@ | |||
include ':app' |