diff --git a/app/src/main/java/fr/mobdev/lpcprog/activity/DeviceActivity.java b/app/src/main/java/fr/mobdev/lpcprog/activity/DeviceActivity.java index fe143a6..3c8446d 100644 --- a/app/src/main/java/fr/mobdev/lpcprog/activity/DeviceActivity.java +++ b/app/src/main/java/fr/mobdev/lpcprog/activity/DeviceActivity.java @@ -1,13 +1,25 @@ package fr.mobdev.lpcprog.activity; +import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.Toolbar; +import android.view.View; +import android.widget.ProgressBar; import android.widget.TextView; +import java.util.ArrayList; import java.util.List; +import fr.mobdev.lpcprog.adapters.BinariesAdapter; +import fr.mobdev.lpcprog.listener.NetworkListener; +import fr.mobdev.lpcprog.managers.DatabaseManager; import fr.mobdev.lpcprog.managers.IspManager; import fr.mobdev.lpcprog.R; +import fr.mobdev.lpcprog.managers.NetworkManager; +import fr.mobdev.lpcprog.objects.Server; import fr.mobdev.lpcprog.objects.USBDevice; import fr.mobdev.lpcprog.managers.UsbCommManager; @@ -15,12 +27,18 @@ public class DeviceActivity extends AppCompatActivity { private UsbCommManager comm; private USBDevice dev; + private List servers; + private long part_id; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.device); + Toolbar toolbar = (Toolbar) findViewById(R.id.device_toolbar); + setSupportActionBar(toolbar); + servers = new ArrayList<>(); comm = UsbCommManager.getInstance(this); + part_id = 0; List devices = comm.getDevices(); int pid = getIntent().getIntExtra("PID",-1); int vid = getIntent().getIntExtra("VID",-1); @@ -40,6 +58,12 @@ public class DeviceActivity extends AppCompatActivity { product.setText(String.format("Product id: %04x", dev.PID)); } doUsb(); + ProgressBar bar = (ProgressBar) findViewById(R.id.progress_browse); + bar.setVisibility(View.GONE); + + RecyclerView list = (RecyclerView) findViewById(R.id.bin_list); + list.setLayoutManager(new LinearLayoutManager(this)); + updateRepositories(); } private void doUsb(){ @@ -48,7 +72,7 @@ public class DeviceActivity extends AppCompatActivity { @Override public void run() { boolean conn = comm.openConnection(dev); - IspManager manager = IspManager.getInstance(); + IspManager manager = IspManager.getInstance(DeviceActivity.this); String uidStr = "No UID Found or error"; String bootStr = "No Boot Version Found or error"; String partidStr = "No Part ID Found or error"; @@ -71,6 +95,8 @@ public class DeviceActivity extends AppCompatActivity { } if(partid != null){ partidStr = String.format("Part Id %08x",Long.parseLong(partid)); + part_id = Long.parseLong(partid); + IspManager.getInstance(DeviceActivity.this).setPartId(part_id); } } updateIDS(uidStr,partidStr,bootStr); @@ -94,4 +120,79 @@ public class DeviceActivity extends AppCompatActivity { } }); } + + private void updateRepositories(){ + System.out.println("Update Repo"); + NetworkListener listener = new NetworkListener() { + @Override + public void startBinaries() { + runOnUiThread(new Runnable() { + @Override + public void run() { + ProgressBar bar = (ProgressBar) findViewById(R.id.progress_browse); + bar.setVisibility(View.VISIBLE); + RecyclerView list = (RecyclerView) findViewById(R.id.bin_list); + list.setVisibility(View.GONE); + + } + }); + } + + @Override + public void startServer(Server server) { + } + + @Override + public void endServer(Server server) { + if(!server.binaries.isEmpty()) + servers.add(server); + } + + @Override + public void endBinaries() { + runOnUiThread(new Runnable() { + @Override + public void run() { + ProgressBar bar = (ProgressBar) findViewById(R.id.progress_browse); + bar.setVisibility(View.GONE); + RecyclerView list = (RecyclerView) findViewById(R.id.bin_list); + list.setVisibility(View.VISIBLE); + BinariesAdapter adapter = new BinariesAdapter(servers, DeviceActivity.this); + list.setAdapter(adapter); + } + }); + } + + @Override + public void onError(final String error) { + runOnUiThread(new Runnable() { + @Override + public void run() { + ProgressBar bar = (ProgressBar) findViewById(R.id.progress_browse); + bar.setVisibility(View.GONE); + final Snackbar msg = Snackbar.make(findViewById(R.id.bin_list), error,Snackbar.LENGTH_INDEFINITE); + msg.setAction(R.string.retry_browse, new View.OnClickListener() { + @Override + public void onClick(View v) { + msg.dismiss(); + updateRepositories(); + } + }); + msg.show(); + List> localServers = DatabaseManager.getInstance(DeviceActivity.this).getServers(); + servers.addAll(localServers.get(0)); + servers.addAll(localServers.get(1)); + servers.addAll(localServers.get(2)); + RecyclerView list = (RecyclerView) findViewById(R.id.bin_list); + list.setVisibility(View.VISIBLE); + BinariesAdapter adapter = new BinariesAdapter(servers,DeviceActivity.this); + list.setAdapter(adapter); + + } + }); + } + }; + NetworkManager.getInstance(listener,this).browseBinaries(); + + } } diff --git a/app/src/main/java/fr/mobdev/lpcprog/adapters/BinariesAdapter.java b/app/src/main/java/fr/mobdev/lpcprog/adapters/BinariesAdapter.java new file mode 100644 index 0000000..c205e55 --- /dev/null +++ b/app/src/main/java/fr/mobdev/lpcprog/adapters/BinariesAdapter.java @@ -0,0 +1,289 @@ +package fr.mobdev.lpcprog.adapters; + +import android.app.Activity; +import android.content.DialogInterface; +import android.support.design.widget.Snackbar; +import android.support.v7.app.AlertDialog; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; + +import java.io.File; +import java.util.List; + +import fr.mobdev.lpcprog.R; +import fr.mobdev.lpcprog.listener.DownloadListener; +import fr.mobdev.lpcprog.listener.FlashListener; +import fr.mobdev.lpcprog.managers.DatabaseManager; +import fr.mobdev.lpcprog.managers.IspManager; +import fr.mobdev.lpcprog.managers.NetworkManager; +import fr.mobdev.lpcprog.objects.Binary; +import fr.mobdev.lpcprog.objects.Server; + +public class BinariesAdapter extends RecyclerView.Adapter { + + private static final int SECTION = 0; + private static final int FIELD = 1; + + private List servers; + private int count; + private Activity activity; + + public BinariesAdapter(List servers, Activity activity) { + this.servers = servers; + this.activity = activity; + countElements(); + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view; + if (viewType == SECTION) { + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.server_section, parent, false); + return new SectionHolder(view); + } else { + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.binary_item, parent, false); + return new BinaryHolder(view); + } + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + if (holder instanceof SectionHolder) { + SectionHolder sectionHolder = (SectionHolder) holder; + int section = getSection(position); + System.out.println("pos " + position + " section " + section); + String sectionName = servers.get(section).url.toString(); + sectionHolder.setupSection(sectionName); + } else if (holder instanceof BinaryHolder) { + BinaryHolder binaryHolder = (BinaryHolder) holder; + + int section = getSection(position); + int pos = getRealPosition(position); + Server server = servers.get(section); + Binary binary = servers.get(section).binaries.get(pos); + binaryHolder.setupBinary(server,binary,activity); + } + } + + private void countElements() { + int size = 0; + for (int i = 0; i < servers.size(); i++) { + if (servers.get(i).binaries.size() > 0) { + size++; + size += servers.get(i).binaries.size(); + } + } + count = size; + } + + private int getRealPosition(int fakePosition) { + System.out.println("get real " + fakePosition); + fakePosition -= 1; + for (int i = 0; i < servers.size(); i++) { + int serverSize = servers.get(i).binaries.size(); + if (fakePosition - serverSize < 0) + return fakePosition; + if (serverSize > 0) { + fakePosition -= 1; + fakePosition -= serverSize; + } + } + return -1; + } + + private int getSection(int fakePosition) { + int prev_size = 1; + for (int i = 0; i < servers.size(); i++) { + int serverSize = servers.get(i).binaries.size(); + if (fakePosition < prev_size + serverSize) + return i; + if (servers.get(i).binaries.size() > 0) { + prev_size += 1; + prev_size += serverSize; + } + } + return -1;//error + } + + @Override + public int getItemCount() { + return count; + } + + @Override + public int getItemViewType(int position) { + int nbValues = 0; + for (int i = 0; i < servers.size(); i++) { + if (position == i + nbValues) + return SECTION; + else if (position < i + nbValues) + break; + nbValues += servers.get(i).binaries.size(); + } + return FIELD; + } +} + +class BinaryHolder extends RecyclerView.ViewHolder{ + DownloadListener listener; + public BinaryHolder(View itemView) { + super(itemView); + } + + public void setupBinary(final Server server, final Binary binary, final Activity activity){ + + TextView name = (TextView) itemView.findViewById(R.id.binary_name); + TextView version = (TextView) itemView.findViewById(R.id.binary_version); + + final LinearLayout downloadedLayout = (LinearLayout) itemView.findViewById(R.id.layout_downloaded); + final ImageView deleteView = (ImageView) itemView.findViewById(R.id.delete_download); + final ImageView flashView = (ImageView) itemView.findViewById(R.id.flash_download); + final ImageView downloadView = (ImageView) itemView.findViewById(R.id.download); + final ImageView stopView = (ImageView) itemView.findViewById(R.id.cancel_download); + final ProgressBar progressBar = (ProgressBar) itemView.findViewById(R.id.progress_download); + + name.setText(binary.name); + version.setText("V "+binary.version); + if(binary.isDownloaded) { + downloadView.setVisibility(View.GONE); + downloadedLayout.setVisibility(View.VISIBLE); + stopView.setVisibility(View.GONE); + progressBar.setVisibility(View.GONE); + } else if(binary.isDownloading){ + downloadView.setVisibility(View.GONE); + downloadedLayout.setVisibility(View.GONE); + stopView.setVisibility(View.VISIBLE); + progressBar.setVisibility(View.VISIBLE); + } else { + downloadView.setVisibility(View.VISIBLE); + downloadedLayout.setVisibility(View.GONE); + stopView.setVisibility(View.GONE); + progressBar.setVisibility(View.GONE); + } + + listener = new DownloadListener() { + + @Override + public void downloadCanceled(Server server, Binary binary) { + binary.isDownloading = false; + binary.progress = 0; + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + downloadView.setVisibility(View.VISIBLE); + downloadedLayout.setVisibility(View.GONE); + stopView.setVisibility(View.GONE); + progressBar.setVisibility(View.GONE); + } + }); + } + + @Override + public void downloadSuccessful(Server server, Binary binary) { + binary.isDownloading = false; + binary.progress = 0; + binary.isDownloaded = true; + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + downloadView.setVisibility(View.GONE); + downloadedLayout.setVisibility(View.VISIBLE); + stopView.setVisibility(View.GONE); + progressBar.setVisibility(View.GONE); + } + }); + } + + @Override + public void downloadError(Server server, Binary binary, final String error) { + binary.isDownloading = false; + binary.progress = 0; + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + downloadView.setVisibility(View.VISIBLE); + downloadedLayout.setVisibility(View.GONE); + stopView.setVisibility(View.GONE); + progressBar.setVisibility(View.GONE); + Snackbar.make(activity.findViewById(R.id.bin_list), error,Snackbar.LENGTH_LONG); + } + }); + } + + @Override + public void progress(Server server, Binary binary, final int progress) { + binary.progress = progress; + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + progressBar.setProgress(progress); + } + }); + } + }; + + downloadView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + binary.isDownloading = true; + binary.progress = 0; + NetworkManager.getInstance(null,itemView.getContext()).retrieveBinary(server,binary,listener); + } + }); + + + deleteView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + AlertDialog.Builder builder = new AlertDialog.Builder(itemView.getContext()); + builder.setMessage(itemView.getContext().getString(R.string.delete_binary_message)+" "+binary.name+" "+ + itemView.getContext().getString(R.string.version)+" "+binary.version+" ?") + .setCancelable(false) + .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + //delete server from database and update the view + File file = new File(itemView.getContext().getApplicationInfo().dataDir+"/"+server.id+"/"+binary.path+binary.filename); + if(file.exists()) + file.delete(); + binary.isDownloaded = false; + DatabaseManager.getInstance(itemView.getContext()).deleteBinary(binary.id); + //file and reset all downloaded items + downloadView.setVisibility(View.VISIBLE); + downloadedLayout.setVisibility(View.GONE); + progressBar.setVisibility(View.GONE); + stopView.setVisibility(View.GONE); + } + }) + .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }); + AlertDialog alert = builder.create(); + alert.show(); + } + }); + + final FlashListener flashListener = new FlashListener() { + @Override + public void onError(String string) { + System.out.println("flash_error "+string); + } + }; + + flashView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + IspManager.getInstance(itemView.getContext()).flash(server,binary,flashListener); + } + }); + } +} + diff --git a/app/src/main/java/fr/mobdev/lpcprog/listener/DownloadListener.java b/app/src/main/java/fr/mobdev/lpcprog/listener/DownloadListener.java new file mode 100644 index 0000000..ef068da --- /dev/null +++ b/app/src/main/java/fr/mobdev/lpcprog/listener/DownloadListener.java @@ -0,0 +1,13 @@ +package fr.mobdev.lpcprog.listener; + +import java.util.EventListener; + +import fr.mobdev.lpcprog.objects.Binary; +import fr.mobdev.lpcprog.objects.Server; + +public interface DownloadListener extends EventListener { + void downloadCanceled(Server server, Binary binary); + void downloadSuccessful(Server server, Binary binary); + void downloadError(Server server, Binary binary, String string); + void progress(Server server, Binary binary, int progress); +} diff --git a/app/src/main/java/fr/mobdev/lpcprog/listener/FlashListener.java b/app/src/main/java/fr/mobdev/lpcprog/listener/FlashListener.java new file mode 100644 index 0000000..7f6f95e --- /dev/null +++ b/app/src/main/java/fr/mobdev/lpcprog/listener/FlashListener.java @@ -0,0 +1,8 @@ +package fr.mobdev.lpcprog.listener; + +import java.util.EventListener; + +public interface FlashListener extends EventListener{ + + void onError(String string); +} diff --git a/app/src/main/java/fr/mobdev/lpcprog/listener/NetworkListener.java b/app/src/main/java/fr/mobdev/lpcprog/listener/NetworkListener.java index f850117..db899b9 100644 --- a/app/src/main/java/fr/mobdev/lpcprog/listener/NetworkListener.java +++ b/app/src/main/java/fr/mobdev/lpcprog/listener/NetworkListener.java @@ -29,9 +29,4 @@ public interface NetworkListener extends EventListener{ void endServer(Server server); void endBinaries(); void onError(String string); - void downloadCanceled(Server server, Binary binary); - void downloadSuccessful(Server server, Binary binary); - void downloadFailed(Server server, Binary binary); - void downloadError(Server server, Binary binary, String string); - void progress(Server server, Binary binary, int progress); } diff --git a/app/src/main/java/fr/mobdev/lpcprog/managers/DatabaseManager.java b/app/src/main/java/fr/mobdev/lpcprog/managers/DatabaseManager.java index 35f6644..76c818c 100644 --- a/app/src/main/java/fr/mobdev/lpcprog/managers/DatabaseManager.java +++ b/app/src/main/java/fr/mobdev/lpcprog/managers/DatabaseManager.java @@ -28,6 +28,8 @@ import java.net.URL; import java.util.ArrayList; import java.util.List; +import fr.mobdev.lpcprog.objects.Binary; +import fr.mobdev.lpcprog.objects.Parts; import fr.mobdev.lpcprog.objects.Server; public class DatabaseManager extends SQLiteOpenHelper { @@ -47,14 +49,31 @@ public class DatabaseManager extends SQLiteOpenHelper { @Override public void onCreate(SQLiteDatabase db) { db.execSQL("Create table if not exists binaries (" + - "id integer primary key autoincrement, name varchar(1024), short_hash varchar(1024), real_short_hash varchar(1024), date INTEGER, storage_duration INTEGER ,thumb TEXT, token varchar(1024));"); + "id integer primary key autoincrement, server_id INTEGER, name varchar(1024), filename varchar(1024), version INTEGER, path varchar(1024), sha1 varchar(1024));"); db.execSQL("Create table if not exists servers (" + "id integer primary key autoincrement, url varchar(1024), isActive INTEGER, attempted INTEGER);"); + db.execSQL("Create table if not exists definitions (" + + "id integer primary key autoincrement, part_id INTEGER, part_name varchar(1024), fl_base_addr INTEGER, fl_size INTEGER, fl_nb_sect INTEGER," + + "reset_vector_offset INTEGER, ram_base_addr INTEGER, ram_size INTEGER, ram_buf_off INTEGER, ram_buf_size INTEGER, UU_encode INTEGER);"); ContentValues values = new ContentValues(); values.put("url","https://wiki.mob-dev.fr/files/"); values.put("isActive",1); values.put("attempted",0); db.insert("servers",null,values); + + values.clear(); + values.put("part_id",0x3640C02B); + values.put("part_name","LPC1224FBD48/101"); + values.put("fl_base_addr",0x0); + values.put("fl_size",0x8000); + values.put("fl_nb_sect",8); + values.put("reset_vector_offset",0x04); + values.put("ram_base_addr",0x10000000); + values.put("ram_size",0x1000); + values.put("ram_buf_off",0x800); + values.put("ram_buf_size",0x400); + values.put("UU_encode",true); + db.insert("definitions",null,values); } @Override @@ -106,6 +125,7 @@ public class DatabaseManager extends SQLiteOpenHelper { int isActive = cursor.getInt(col++); server.isActive = isActive != 0; server.attempted = cursor.getInt(col); + server.binaries = getBinaries(server.id); if (server.isActive && server.attempted == 0) active.add(server); else if (server.isActive && server.attempted != 0) @@ -120,6 +140,91 @@ public class DatabaseManager extends SQLiteOpenHelper { return list; } + private List getBinaries(long id) { + List binaries = new ArrayList<>(); + String whereClause = "server_id = ?"; + String[] whereArgs = new String[1]; + whereArgs[0] = String.valueOf(id); + Cursor cursor = getReadableDatabase().query("binaries", null, whereClause, whereArgs, null, null, null); + while (cursor.moveToNext()){ + System.out.println("Found a binary in db"); + int col = 0; + Binary b = new Binary(); + b.id = cursor.getLong(col++); + col++;//ignore server id + b.name = cursor.getString(col++); + b.filename = cursor.getString(col++); + b.version = cursor.getInt(col++); + b.path = cursor.getString(col++); + b.sha1 = cursor.getString(col); + b.isDownloaded = true; + b.progress = 0; + b.isDownloading = false; + binaries.add(b); + } + cursor.close(); + return binaries; + } + public void serverFail(Server server) { + server.attempted++; + if(server.attempted == 5){ + server.attempted = 0; + server.isActive = false; + } + ContentValues values = new ContentValues(); + values.put("attempted",server.attempted); + values.put("isActive",server.isActive); + String whereClause = "id = ?"; + String[] whereArgs = new String[1]; + whereArgs[0] = String.valueOf(server.id); + getWritableDatabase().update("servers",values,whereClause,whereArgs); + } + + public void addBinary(Server server, Binary binary) { + System.out.println("add binary"); + ContentValues values = new ContentValues(); + values.put("server_id",server.id); + values.put("name",binary.name); + values.put("filename",binary.filename); + values.put("version",binary.version); + values.put("path",binary.path); + values.put("sha1",binary.sha1); + values.put("name",binary.name); + getWritableDatabase().insert("binaries",null,values); + } + + public void deleteBinary(long id) { + String whereClause = "id = ?"; + String[] whereArgs = new String[1]; + whereArgs[0] = String.valueOf(id); + getWritableDatabase().delete("binaries",whereClause,whereArgs); + } + + public Parts getParts(long part_id) { + Parts parts = null; + String whereClause = "part_id = ?"; + String[] whereArgs = new String[1]; + whereArgs[0] = String.valueOf(part_id); + System.out.println("part_id "+part_id); + Cursor cursor = getReadableDatabase().query("definitions", null, whereClause, whereArgs, null, null, null); + if (cursor.moveToNext()) { + parts = new Parts(); + int col = 0; + parts.id = cursor.getLong(col++); + parts.part_id = cursor.getInt(col++); + parts.part_name = cursor.getString(col++); + parts.flash_base_addr = cursor.getInt(col++); + parts.flash_size = cursor.getInt(col++); + parts.flash_nb_sectors = cursor.getInt(col++); + parts.reset_vector_offset = cursor.getInt(col++); + parts.ram_base_addr = cursor.getInt(col++); + parts.ram_size = cursor.getInt(col++); + parts.ram_buffer_offset = cursor.getInt(col++); + parts.ram_buffer_size = cursor.getInt(col++); + parts.uuencode = cursor.getInt(col) == 1; + } + + return parts; } } diff --git a/app/src/main/java/fr/mobdev/lpcprog/managers/IspManager.java b/app/src/main/java/fr/mobdev/lpcprog/managers/IspManager.java index 60aa576..041fd08 100644 --- a/app/src/main/java/fr/mobdev/lpcprog/managers/IspManager.java +++ b/app/src/main/java/fr/mobdev/lpcprog/managers/IspManager.java @@ -1,54 +1,77 @@ package fr.mobdev.lpcprog.managers; +import android.content.Context; + import com.ftdi.j2xx.D2xxManager; import com.ftdi.j2xx.FT_Device; +import java.io.File; +import java.io.FileInputStream; import java.nio.ByteBuffer; import java.util.Locale; +import fr.mobdev.lpcprog.R; +import fr.mobdev.lpcprog.listener.FlashListener; +import fr.mobdev.lpcprog.objects.Binary; +import fr.mobdev.lpcprog.objects.Parts; +import fr.mobdev.lpcprog.objects.Server; import fr.mobdev.lpcprog.objects.USBDevice; 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 int SERIAL_BUF_SIZE = 1300; + private static final int LINE_DATA_LENGTH = 45; + private static final int LINES_PER_BLOCK = 20; + private static final int MAX_DATA_BLOCK_SIZE = LINES_PER_BLOCK * LINE_DATA_LENGTH; + private static final int UUENCODE_ADDED_VAL = 32; + private static final int LINE_DATA_LENGTH_MAX = 45; + 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 = "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(); + private static final byte[] UNLOCK = "U 23130\r\n".getBytes(); //members private static IspManager instance = null; private FT_Device serialPort = null; + private Context context; + private long part_id = 0; - private IspManager(){ + private IspManager(Context context) { + this.context = context; } - public static IspManager getInstance(){ - if(instance == null) - instance = new IspManager(); + public static IspManager getInstance(Context context) { + if (instance == null) + instance = new IspManager(context); return instance; } - public boolean setupDevice(USBDevice device, int baudRate){ + public void setPartId(long part){ + part_id = part; + } + + public boolean setupDevice(USBDevice device, int baudRate) { serialPort = device.device; - if(serialPort != null) + if (serialPort != null) serialPort.resetDevice(); else System.out.println("device is null fuck"); - if(serialPort!=null && serialPort.isOpen()){ + 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 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; @@ -56,174 +79,164 @@ public class IspManager { return false; } - public boolean synchronize(int crystal_freq){ - if(serialPort == null) + 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){ + 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); + serialPort.read(buf, buf.length, 500); String result = new String(buf); String expected = new String(SYNC); - if(result.compareTo(expected) != 0) { - printbuffer(buf); + if (result.compareTo(expected) != 0) { serialPort.write("\r\n".getBytes()); - System.out.println("Start answer "+result); + System.out.println("Start answer " + result); return false; } - if(serialPort.write(SYNC) != SYNC.length) { + 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); + 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); + if (result.compareTo(expected) != 0) { + System.out.println("SYNC OK " + result); return false; } - String freq = String.valueOf(crystal_freq)+"\r\n"; - if(serialPort.write(freq.getBytes()) != freq.length()) { + 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); + 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); + if (result.compareTo(expected) != 0) { + System.out.println("freq answer " + result); return false; } - if(serialPort.write(SYNC_ECHO_OFF) != SYNC_ECHO_OFF.length) { + 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])); + 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) + 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)); + int readed = read(buf, size, 500); + System.out.println("end " + (size - readed)); } - public String[] readUid(){ - if(serialPort == null) + public String[] readUid() { + if (serialPort == null) return null; - int ret = sendCommand(READ_UID,null); + int ret = sendCommand(READ_UID, null); - if(ret != 0){ - System.out.println("Send Command "+ret); + 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++){ + 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); + 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"); + 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")) { + 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); + buffer = buffer.substring(buffer.indexOf("\r") + 1); } } System.out.println("uids ok"); return uids; } - public String readPartId(){ - if(serialPort == null) + public String readPartId() { + if (serialPort == null) return null; - int ret = sendCommand(READ_PART_ID,null); - if(ret != 0) + 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) + 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",""); + 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) + public String[] readBootVersion() { + if (serialPort == null) return null; - int ret = sendCommand(READ_BOOT_VERSION,null); - if(ret != 0){ - System.out.println("Send Command "+ret); + 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); + int size = read(buf, 50, 500); - if(size <= 0){ - System.out.println("Receive "+size); + 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"); + 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")) { + 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); + buffer = buffer.substring(buffer.indexOf("\r") + 1); } } @@ -231,33 +244,58 @@ public class IspManager { return version; } - public int sendCommand(byte[] cmd, String[] args){ + private int sendCommand(byte[] cmd, String[] args) { + if(args != null)//FIXME + return -1; byte[] buf = new byte[3]; - if(serialPort.write(cmd) != cmd.length) + 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++){ + 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) + if (len <= 0) return -4; return parseRetCode(buf); } - public int read(byte[] buffer, int size, int timeout){ + private int sendCommand(byte[] cmd, char c, int addr, int count) { + int ret = 0; + int len = 0; + + byte[] buf = String.format(Locale.getDefault(),"%c %d %d\r\n",c,addr,count).getBytes(); + len = buf.length; + if(len > REP_BUF) { + len = REP_BUF; + } + int sent = serialPort.write(buf,len); + if(len != sent) { + return -5; + } + buf = new byte[3]; + len = read(buf,3,500); + if(len <= 0) { + return -4; + } + ret = parseRetCode(buf); + + return ret; + } + + private 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); + ByteBuffer output = ByteBuffer.wrap(buffer, 0, size); - while(sizeRead < size){ + while (sizeRead < size) { int sizeToRead = serialPort.getQueueStatus(); - if(sizeRead + sizeToRead > size) + if (sizeRead + sizeToRead > size) sizeToRead = size - sizeRead; byte[] buf = new byte[sizeToRead]; - if(sizeToRead > 0) { + if (sizeToRead > 0) { int sizeReceived = serialPort.read(buf, sizeToRead, 50); if (sizeReceived < 0) return sizeReceived; @@ -266,21 +304,22 @@ public class IspManager { output.put(buf, 0, sizeReceived); } long time = System.nanoTime(); - if(time - startTime >= timeoutNano) + if (time - startTime >= timeoutNano) break; } return sizeRead; } - private int parseRetCode(byte[] data){ + private int parseRetCode(byte[] data) { String str = new String(data); - str = str.replace("\r\n",""); - + str = str.replace("\r\n", ""); + if (!str.matches("[0-9 -+]*")) + return -1; return Integer.parseInt(str); } public boolean synchronizeIfPossible(int crystal_freq) { - if(!synchronize(crystal_freq)) { + if (!synchronize(crystal_freq)) { serialPort.purge(D2xxManager.FT_PURGE_TX); serialPort.purge(D2xxManager.FT_PURGE_RX); String[] uids = readUid(); @@ -293,26 +332,413 @@ public class IspManager { return true; } - /*private int byteArrayToInt(byte[] array, int offset){ + private int eraseFlash(Parts parts) { + int ret = unlock(); + if (ret != 0) { + System.out.println("unlock fail"); + return -1; + } + for (int i = 0; i < parts.flash_nb_sectors; i++) { + //blank-check + ret = send_cmd_sectors('I', i, i); + if (ret == 0) { + continue; + } + + if (ret < 0) { + System.out.println("blank "+i+" fail"); + return ret; + } else { + byte buf[] = new byte[REP_BUF]; + read(buf, 40, 500); + } + //prepare-for-write + ret = send_cmd_sectors('P', i, i); + if (ret != 0) { + System.out.println("prepare-for-write "+i+" fail"); + return ret; + } + //erase + ret = send_cmd_sectors('E', i, i); + if (ret != 0) { + System.out.println("erase "+i+" fail"); + return ret; + } + } + return 0; + } + + private int send_cmd_sectors(char cmd, int first_sector, int last_sector) { + byte[] buf = new byte[3]; + int ret; + int len; + + if(last_sector < first_sector){ + return -6; + } + + String request = String.format(Locale.getDefault(),"%c %d %d\r\n",cmd, first_sector, last_sector); + len = serialPort.write(request.getBytes()); + if(len != request.getBytes().length){ + return -5; + } + len = read(buf,3,500); + if(len <= 0){ + return -4; + } + + ret = parseRetCode(buf); + + return ret; + } + + private int unlock() { + int ret = sendCommand(UNLOCK,null); + if(ret != 0) + return -1; + return 0; + } + + public void flash(final Server server, final Binary binary, final FlashListener listener) { + new Thread(new Runnable() { + @Override + public void run() { + flashBinary(server,binary,listener); + } + }).start(); + } + + private int flashBinary(Server server, Binary binary, FlashListener listener) { + Parts parts = DatabaseManager.getInstance(context).getParts(part_id); + if(parts == null) { + listener.onError(context.getString(R.string.parts_missing)); + return -1; + } + int sector_size = parts.flash_size / parts.flash_nb_sectors; + long ram_addr = parts.ram_base_addr + parts.ram_buffer_offset; + boolean uuencode = parts.uuencode; + byte data[]; + + //Sanity Checks + if (ram_addr > parts.ram_base_addr + parts.ram_size) { + listener.onError(context.getString(R.string.buffer_out_ram)); + return -2; + } + + long write_size = calcWriteSize(sector_size, parts.ram_buffer_size); + if (write_size == 0) { + listener.onError(context.getString(R.string.block_size_null)); + return -3; + } + + int ret = eraseFlash(parts); + if (ret != 0) { + listener.onError(context.getString(R.string.cant_erase_flash)); + return -4; + } + + + data = new byte[parts.flash_size]; + //copy file buffer to data array + File file = new File(context.getApplicationInfo().dataDir + "/" + server.id + "/" + binary.path + binary.filename); + int size = copy_buffer(file, data, parts.flash_size); + if (size <= 0) { + System.out.println("Size " + size); + listener.onError(context.getString(R.string.copy_file)); + return -5; + } + + fill_data_with_0(data, size, parts.flash_size); + int cksum = calc_binary_checksum(data); + setChecksum(data, 28, cksum); + if(!verifyChecksum(data,cksum)) { + listener.onError(context.getString(R.string.checksum_failed)); + return -6; + } + long blocks = (size / write_size) + ((size % write_size == 0) ? 0 : 1); + if (blocks * write_size > parts.flash_size) { + listener.onError(context.getString(R.string.flash_outside_end)); + } + + for(int i = 0; i < blocks; i++){ + int current_sector = (int)(i*write_size)/sector_size; + int flash_addr = (int)(parts.flash_base_addr + (i*write_size)); + //prepare-for-write + ret = send_cmd_sectors('P',current_sector,current_sector); + if(ret != 0){ + listener.onError(context.getString(R.string.prepare_write_error)+" "+i); + return ret; + } + + ret = send_buf_to_ram(data,(int)(i*write_size),(int)ram_addr,(int)write_size, uuencode); + if(ret != 0) { + listener.onError(context.getString(R.string.write_ram_error)+" "+i); + return ret; + } + + //write-to-ram + ret = send_cmd_address('C', flash_addr, (int)ram_addr, (int) write_size); + if(ret != 0){ + listener.onError(context.getString(R.string.copy_to_flash_error)+" "+i); + return ret; + } + + } + + return ret; + } + + private int send_cmd_address(char c, int flash_addr, int ram_addr, int write_size) { + int ret; + int len; + byte[] buf = new byte[3]; + String request = String.format(Locale.getDefault(),"%c %d %d %d\r\n",c,flash_addr,ram_addr,write_size); + len = serialPort.write(request.getBytes()); + if(len != request.getBytes().length){ + System.out.println("cmd addr write"); + return -5; + } + len = read(buf,3,500); + if (len <= 0) { + System.out.println("cmd addr read"); + return -4; + } + ret = parseRetCode(buf); + + System.out.println("cmd addr ret "+ret); + return ret; + } + + private int send_buf_to_ram(byte[] data, int offset, int ram_addr, int write_size, boolean uuencode) { + int ret; + int len; + int blocks; + int total_sent =0; + + byte[] dataToSend = new byte[write_size]; + System.arraycopy(data,offset,dataToSend,0,write_size); + + ret = sendCommand("write-to-ram".getBytes(),'W',ram_addr,write_size); + if(ret != 0){ + System.out.println("ask for write to ram"); + return -8; + } + if(!uuencode) { + len = serialPort.write(dataToSend); + if(len != write_size){ + return -7; + } + return 0; + } + + blocks = get_nb_blocks(write_size); + + int resend_requested_for_block = 0; + for(int i = 0; i < blocks; i++){ + byte[] buf = new byte[SERIAL_BUF_SIZE]; + byte[] repbuf = new byte[REP_BUF]; + int data_size; + int encoded_size; + int computed_checksum; + data_size = (write_size - total_sent); + if( data_size >= MAX_DATA_BLOCK_SIZE) + data_size = MAX_DATA_BLOCK_SIZE; + encoded_size = uu_encode(buf,dataToSend,total_sent,data_size); + computed_checksum = calc_checksum(dataToSend,total_sent,data_size); + + byte[] checksum = String.format(Locale.getDefault(),"%d\r\n", computed_checksum).getBytes(); + System.out.println(String.format(Locale.getDefault(),"%d %08x",i,computed_checksum)); + System.arraycopy(checksum,0,buf,encoded_size,checksum.length); + encoded_size+=checksum.length; + //buf[encoded_size]='\0'; + //encoded_size++; + for(int j = 0; j < encoded_size; j++) { + System.out.print(String.format(Locale.getDefault(),"%02x",buf[j])); + if(j%10==0) + System.out.println(""); + } + len = serialPort.write(buf,encoded_size); + if(len != encoded_size) { + System.out.println("write fail "+i); + return -8; + } + len = read(repbuf,REP_BUF,500); + if(len <= 0) { + System.out.println("read answer fail "+i); + return -9; + } + repbuf[len]='\0'; + System.out.println("Length "+len); + for(int j = 0; j < len; j++) { + System.out.println(String.format(Locale.getDefault(),"%02x",repbuf[j])); + } + String result = new String(repbuf,0,len); + String expected = new String(DATA_BLOCK_OK); + System.out.println("result "+result+"."); + if(result.compareTo(expected)==0){ + total_sent += data_size; + resend_requested_for_block = 0; + } else { + resend_requested_for_block++; + if(resend_requested_for_block >= 3) { + System.out.println("resend fail "+i); + return -10; + } + i--; + } + } + + return ret; + } + + + private int uu_encode(byte[] data_out, byte[] data, int offset, int orig_size) { + //TODO + System.out.println("uu "+offset+" "+orig_size); + int new_size = 0; + int pos = offset; + while(pos < offset+orig_size) { + int line_length = offset + orig_size - pos; + int i = 0; + if(line_length > LINE_DATA_LENGTH_MAX) { + line_length = LINE_DATA_LENGTH_MAX; + } + data_out[new_size] = (byte) (line_length + UUENCODE_ADDED_VAL); + new_size++; + while (i < line_length) { + int triplet = 0; + for(int j = 0; j < 3; j++) { + System.out.println(String.format(Locale.getDefault(),"pos %d i %d j %d line_length %d",pos,i,j,line_length)); + triplet |= ((data[pos+i+j] & 0xFF) << (8 * (2-j))); + if(i+j >= line_length-1) + break; + } + for(int j = 0; j < 4; j++) { + data_out[new_size+j] = (byte)((triplet >> (6 * (3 - j))) & 0x3F); + data_out[new_size+j] += UUENCODE_ADDED_VAL; + } + i+=3; + new_size += 4; + } + pos += line_length; + data_out[new_size++] = '\r'; + data_out[new_size++] = '\n'; + } + return new_size; + } + + private int get_nb_blocks(int count) { + int lines; + int blocks; + lines = count / LINE_DATA_LENGTH; + if(count % LINE_DATA_LENGTH != 0) { + lines += 1; + } + blocks = lines / LINES_PER_BLOCK; + if(lines % LINES_PER_BLOCK != 0) { + blocks += 1; + } + return blocks; + } + + private boolean verifyChecksum(byte[] data, int cksum) { + int verif = byteArrayToInt(data,28); + return verif == cksum; + } + + private void setChecksum(byte[] data, int offset, int cksum) { + byte[] check = intToByteArray(cksum); + System.arraycopy(check,0,data,offset,4); + } + + private int calc_checksum(byte[] data, int offset, int datasize) { + int sum = 0; + for(int i = offset; i < offset+datasize; i++) { + int b = 0; + b |= (data[i] & 0xFF); + sum = sum + b; + } + return sum; + } + + private int calc_binary_checksum(byte[] data){ + int[] val = new int[7]; + val[0] = byteArrayToInt(data, 0); + val[1] = byteArrayToInt(data, 4); + val[2] = byteArrayToInt(data, 8); + val[3] = byteArrayToInt(data, 12); + val[4] = byteArrayToInt(data, 16); + val[5] = byteArrayToInt(data, 20); + val[6] = byteArrayToInt(data, 24); + + int sum = 0 - val[0] - val[1] - val[2] - val[3] - val[4] - val[5] - val[6]; + System.out.println("sum " + String.format("%08x", sum)); + return sum; + } + + private void fill_data_with_0(byte[] data, int offset, int flash_size) { + for (int i = offset; i < flash_size; i++) + data[i] = 0; + } + + private int copy_buffer(File file, byte[] data, int max_size) { + int sizeReaded; + int moreSize = 0; + try { + FileInputStream stream = new FileInputStream(file); + int count = stream.read(data, 0, max_size); + sizeReaded = count; + if (count == max_size) { + byte[] b = new byte[1]; + while (count > 0) { + count = stream.read(b, 0, 1); + if (count > 0) + moreSize += count; + } + } + } catch (Exception e) { + e.printStackTrace(); + return -1; + } + if (sizeReaded == max_size && moreSize != 0) + return -moreSize; + return sizeReaded; + } + + private long calcWriteSize(int sector_size, int ram_buffer_size) { + long write_size = (sector_size < ram_buffer_size) ? sector_size : ram_buffer_size; + if (write_size >= 4096) { + write_size = 4096; + } else if (write_size >= 1024) { + write_size = 1024; + } else if (write_size >= 512) { + write_size = 512; + } else if (write_size >= 256) { + write_size = 256; + } else if (write_size >= 64) { + write_size = 64; + } else { + write_size = 0; + } + return write_size; + } + + 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); + value |= (array[offset] & 0xff); + value |= (array[offset + 1] & 0xff) << 8; + value |= (array[offset + 2] & 0xff) << 16; + value |= (array[offset + 3] & 0xff) << 24; 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; - }*/ + private byte[] intToByteArray(int value){ + byte[] output = new byte[4]; + output[0] = (byte)(value & 0xFF); + output[1] = (byte)((value >> 8) & 0xFF); + output[2] = (byte)((value >> 16) & 0xFF); + output[3] = (byte)((value >> 24) & 0xFF); + return output; + } } diff --git a/app/src/main/java/fr/mobdev/lpcprog/managers/NetworkManager.java b/app/src/main/java/fr/mobdev/lpcprog/managers/NetworkManager.java index 7477284..44dcd80 100644 --- a/app/src/main/java/fr/mobdev/lpcprog/managers/NetworkManager.java +++ b/app/src/main/java/fr/mobdev/lpcprog/managers/NetworkManager.java @@ -7,7 +7,6 @@ import android.net.NetworkInfo; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -15,11 +14,11 @@ import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import fr.mobdev.lpcprog.R; +import fr.mobdev.lpcprog.listener.DownloadListener; import fr.mobdev.lpcprog.listener.NetworkListener; import fr.mobdev.lpcprog.objects.Binary; import fr.mobdev.lpcprog.objects.Server; @@ -29,14 +28,14 @@ public class NetworkManager { private NetworkListener listener; private static NetworkManager instance; private Context context; - private boolean isCanceled; private boolean downloadInProgress; + private List cancelList; private NetworkManager(NetworkListener listener, Context context) { this.listener = listener; this.context = context; - this.isCanceled = false; + cancelList = new ArrayList<>(); } public static NetworkManager getInstance(NetworkListener listener, Context context){ @@ -70,17 +69,17 @@ public class NetworkManager { listener.onError(context.getString(R.string.network_error)); } - public void retrieveBinary(final Server server, final Binary binary){ + public void retrieveBinary(final Server server, final Binary binary, final DownloadListener downloadListener){ if(isConnectedToInternet(context)){ new Thread(new Runnable() { @Override public void run() { - getBinary(server, binary); + getBinary(server, binary,downloadListener); } }).start(); } else - listener.onError(context.getString(R.string.network_error)); + this.listener.onError(context.getString(R.string.network_error)); } private void getBinariesList(){ @@ -94,7 +93,7 @@ public class NetworkManager { } listener.startBinaries(); - + List serverInError = new ArrayList<>(); for(Server server : serversAvailable) { listener.startServer(server); try { @@ -106,20 +105,27 @@ public class NetworkManager { InputStreamReader isr = new InputStreamReader(stream); BufferedReader reader = new BufferedReader(isr); String line = reader.readLine(); + System.out.println("Browse binaries"); while(line != null){ Binary b = parseLine(line); - if(b != null) + System.out.println("Found a binary "+b.name); + if(b != null && !server.contains(b)) { server.addBinary(b); + DatabaseManager.getInstance(context).addBinary(server,b); + } line = reader.readLine(); } } } catch (IOException e) { e.printStackTrace(); DatabaseManager.getInstance(context).serverFail(server); + serverInError.add(server); } finally { listener.endServer(server); } } + if(serverInError.containsAll(servers)) + listener.onError(context.getString(R.string.all_server_error)); listener.endBinaries(); } @@ -138,10 +144,13 @@ public class NetworkManager { b.path = line.substring(0,line.indexOf(";")); line = line.substring(line.indexOf(";")+1); b.sha1 = line.substring(0,line.indexOf(";")); + b.isDownloaded = false; + b.isDownloading = false; + b.progress = 0; return b; } - private void getBinary(Server server, Binary binary){ + private void getBinary(Server server, Binary binary, DownloadListener downloadListener){ try { URL url = new URL(server.url.toString() + binary.path + binary.filename); downloadInProgress = true; @@ -149,9 +158,8 @@ public class NetworkManager { connection.setDoInput(true); InputStream stream = connection.getInputStream(); File file = new File(context.getApplicationInfo().dataDir+"/"+server.id+"/"+binary.path+binary.filename); - file.getParentFile().mkdirs(); - if (!file.createNewFile() && !file.canWrite()){ - listener.downloadError(server,binary,context.getString(R.string.cant_create_file)); + if ((!file.getParentFile().exists() && !file.getParentFile().mkdirs()) || !file.createNewFile() && !file.canWrite()){ + downloadListener.downloadError(server,binary,context.getString(R.string.cant_create_file)); return; } FileOutputStream output = new FileOutputStream(file); @@ -161,34 +169,35 @@ public class NetworkManager { long totalSizeReaded = 0; int sizeReaded ; while((sizeReaded = stream.read(data)) != -1){ - if(isCanceled) { - isCanceled = false; + if(cancelList.contains(binary)) { downloadInProgress = false; - listener.downloadCanceled(server,binary); + downloadListener.downloadCanceled(server,binary); stream.close(); output.close(); cleanupFile(server,binary); + cancelList.remove(binary); return; } totalSizeReaded += sizeReaded; if(fileLength > 0){ - listener.progress(server,binary, (int) totalSizeReaded * 100 / fileLength); + downloadListener.progress(server,binary, (int) totalSizeReaded * 100 / fileLength); } output.write(data,0,sizeReaded); } output.close(); if(checkFileSha1(server,binary)) - listener.downloadSuccessful(server,binary); + downloadListener.downloadSuccessful(server,binary); else - listener.downloadError(server,binary,context.getString(R.string.sha1_error)); + downloadListener.downloadError(server,binary,context.getString(R.string.sha1_error)); } }catch (IOException e) { e.printStackTrace(); cleanupFile(server,binary); - listener.downloadFailed(server,binary); + DatabaseManager.getInstance(context).serverFail(server); + downloadListener.downloadError(server,binary, context.getString(R.string.unknown_error)); } downloadInProgress = false; - isCanceled = false; + cancelList.remove(binary); } public boolean checkFileSha1(Server server, Binary binary){ @@ -218,9 +227,9 @@ public class NetworkManager { return f.delete(); } - public void cancelDownload(){ + public void cancelDownload(Binary binary){ if(downloadInProgress) - isCanceled = true; + cancelList.add(binary); } private boolean isConnectedToInternet(Context context) diff --git a/app/src/main/java/fr/mobdev/lpcprog/objects/Binary.java b/app/src/main/java/fr/mobdev/lpcprog/objects/Binary.java index dfa20c7..5a5bb8e 100644 --- a/app/src/main/java/fr/mobdev/lpcprog/objects/Binary.java +++ b/app/src/main/java/fr/mobdev/lpcprog/objects/Binary.java @@ -7,4 +7,35 @@ public class Binary { public int version; public String path; public String sha1; + public boolean isDownloaded; + public boolean isDownloading; + public int progress = 0; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Binary binary = (Binary) o; + + if (version != binary.version) { + System.out.println("version"); + return false; + } + if (!name.equals(binary.name)){ + System.out.println("name"); + return false; + } + if (!filename.equals(binary.filename)) { + System.out.println("filename"); + return false; + } + if (!path.equals(binary.path)) { + System.out.println("path"); + return false; + } + System.out.println("sha1 "+sha1.equals(binary.sha1)); + return sha1.equals(binary.sha1); + + } } diff --git a/app/src/main/java/fr/mobdev/lpcprog/objects/Parts.java b/app/src/main/java/fr/mobdev/lpcprog/objects/Parts.java new file mode 100644 index 0000000..b857a3f --- /dev/null +++ b/app/src/main/java/fr/mobdev/lpcprog/objects/Parts.java @@ -0,0 +1,16 @@ +package fr.mobdev.lpcprog.objects; + +public class Parts { + public long id; + public long part_id; + public String part_name; + public int flash_base_addr; + public int flash_size; + public int flash_nb_sectors; + public int reset_vector_offset; + public int ram_base_addr; + public int ram_size; + public int ram_buffer_offset; + public int ram_buffer_size; + public boolean uuencode; +} diff --git a/app/src/main/java/fr/mobdev/lpcprog/objects/Server.java b/app/src/main/java/fr/mobdev/lpcprog/objects/Server.java index 6e54ecf..1993d73 100644 --- a/app/src/main/java/fr/mobdev/lpcprog/objects/Server.java +++ b/app/src/main/java/fr/mobdev/lpcprog/objects/Server.java @@ -9,9 +9,16 @@ public class Server { public URL url; public boolean isActive; public int attempted; - public List binaries = new ArrayList<>(); + public List binaries; public void addBinary(Binary b) { binaries.add(b); } + + public boolean contains(Binary b) { + for(Binary binary : binaries){ + System.out.println("Binary equals?"+b.name+" "+b.equals(binary)); + } + return binaries.contains(b); + } } diff --git a/app/src/main/res/drawable-hdpi/cancel.png b/app/src/main/res/drawable-hdpi/cancel.png new file mode 100644 index 0000000..60f86de Binary files /dev/null and b/app/src/main/res/drawable-hdpi/cancel.png differ diff --git a/app/src/main/res/drawable-hdpi/chip.png b/app/src/main/res/drawable-hdpi/chip.png new file mode 100644 index 0000000..4f3f586 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/chip.png differ diff --git a/app/src/main/res/drawable-hdpi/delete.png b/app/src/main/res/drawable-hdpi/delete.png new file mode 100644 index 0000000..989fc24 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/delete.png differ diff --git a/app/src/main/res/drawable-hdpi/download.png b/app/src/main/res/drawable-hdpi/download.png new file mode 100644 index 0000000..c556134 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/download.png differ diff --git a/app/src/main/res/drawable-hdpi/stop.png b/app/src/main/res/drawable-hdpi/stop.png new file mode 100644 index 0000000..07952e0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/stop.png differ diff --git a/app/src/main/res/drawable-mdpi/cancel.png b/app/src/main/res/drawable-mdpi/cancel.png new file mode 100644 index 0000000..b53bf0e Binary files /dev/null and b/app/src/main/res/drawable-mdpi/cancel.png differ diff --git a/app/src/main/res/drawable-mdpi/chip.png b/app/src/main/res/drawable-mdpi/chip.png new file mode 100644 index 0000000..5365405 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/chip.png differ diff --git a/app/src/main/res/drawable-mdpi/delete.png b/app/src/main/res/drawable-mdpi/delete.png new file mode 100644 index 0000000..30f9c71 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/delete.png differ diff --git a/app/src/main/res/drawable-mdpi/download.png b/app/src/main/res/drawable-mdpi/download.png new file mode 100644 index 0000000..4aab51d Binary files /dev/null and b/app/src/main/res/drawable-mdpi/download.png differ diff --git a/app/src/main/res/drawable-mdpi/stop.png b/app/src/main/res/drawable-mdpi/stop.png new file mode 100644 index 0000000..f0d8284 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/stop.png differ diff --git a/app/src/main/res/drawable-xhdpi/cancel.png b/app/src/main/res/drawable-xhdpi/cancel.png new file mode 100644 index 0000000..fa8742e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/cancel.png differ diff --git a/app/src/main/res/drawable-xhdpi/chip.png b/app/src/main/res/drawable-xhdpi/chip.png new file mode 100644 index 0000000..433b810 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/chip.png differ diff --git a/app/src/main/res/drawable-xhdpi/delete.png b/app/src/main/res/drawable-xhdpi/delete.png new file mode 100644 index 0000000..e154951 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/delete.png differ diff --git a/app/src/main/res/drawable-xhdpi/download.png b/app/src/main/res/drawable-xhdpi/download.png new file mode 100644 index 0000000..b091b92 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/download.png differ diff --git a/app/src/main/res/drawable-xhdpi/stop.png b/app/src/main/res/drawable-xhdpi/stop.png new file mode 100644 index 0000000..7a01500 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/stop.png differ diff --git a/app/src/main/res/drawable-xxhdpi/cancel.png b/app/src/main/res/drawable-xxhdpi/cancel.png new file mode 100644 index 0000000..86d9589 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/cancel.png differ diff --git a/app/src/main/res/drawable-xxhdpi/chip.png b/app/src/main/res/drawable-xxhdpi/chip.png new file mode 100644 index 0000000..983a92a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/chip.png differ diff --git a/app/src/main/res/drawable-xxhdpi/delete.png b/app/src/main/res/drawable-xxhdpi/delete.png new file mode 100644 index 0000000..4c55c64 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/delete.png differ diff --git a/app/src/main/res/drawable-xxhdpi/download.png b/app/src/main/res/drawable-xxhdpi/download.png new file mode 100644 index 0000000..ebc6ff4 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/download.png differ diff --git a/app/src/main/res/drawable-xxhdpi/stop.png b/app/src/main/res/drawable-xxhdpi/stop.png new file mode 100644 index 0000000..cf271e0 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/stop.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/cancel.png b/app/src/main/res/drawable-xxxhdpi/cancel.png new file mode 100644 index 0000000..49b244c Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/cancel.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/download.png b/app/src/main/res/drawable-xxxhdpi/download.png new file mode 100644 index 0000000..0f1afc3 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/download.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/stop.png b/app/src/main/res/drawable-xxxhdpi/stop.png new file mode 100644 index 0000000..f65174a Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/stop.png differ diff --git a/app/src/main/res/drawable/progbar.xml b/app/src/main/res/drawable/progbar.xml new file mode 100644 index 0000000..cab1341 --- /dev/null +++ b/app/src/main/res/drawable/progbar.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/binary_item.xml b/app/src/main/res/layout/binary_item.xml index 3509b84..fd8364d 100644 --- a/app/src/main/res/layout/binary_item.xml +++ b/app/src/main/res/layout/binary_item.xml @@ -1,6 +1,84 @@ - + android:layout_height="60dp"> - \ No newline at end of file + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/device.xml b/app/src/main/res/layout/device.xml index 069d7d0..4576ed8 100644 --- a/app/src/main/res/layout/device.xml +++ b/app/src/main/res/layout/device.xml @@ -6,10 +6,6 @@ android:fitsSystemWindows="true" android:layout_height="match_parent" android:layout_width="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=".activity.DeviceActivity" > @@ -19,7 +15,7 @@ android:theme="@style/AppTheme.PopupOverlay"> + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4019401..5c8b53e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -14,7 +14,22 @@ Manage Servers Network Unavailable Verification on file Failed - Can\\\'t create file + Can\'t create file + Would you delete + version + Unknown Error + Retry + Can\'t read any server + Invalid Configuration, buffer out of RAM + Can\'t flash using block size null + Unable to load file + Can\'t erase flash + Checksum on binary file fail + Can\'t flash outside of flash + Can\'t flash this LPC, parts unknown + Prepare for write fail + write data in ram fail + Copy to flash fail http:// https:// diff --git a/build.gradle b/build.gradle index cb98401..e220f0b 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.0.0' + classpath 'com.android.tools.build:gradle:2.1.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files