Browse Source

App V1

Add Parts
Feedback during flash and erros
Better handle of the plug/unplug usb device
Icon Launcher
Better User Experience
tags/release-v1.0
Schoumi 3 years ago
parent
commit
4f923003a7
62 changed files with 2091 additions and 587 deletions
  1. 8
    8
      app/build.gradle
  2. 6
    11
      app/src/main/AndroidManifest.xml
  3. 0
    218
      app/src/main/java/fr/mobdev/lpcprog/activity/DeviceActivity.java
  4. 186
    57
      app/src/main/java/fr/mobdev/lpcprog/activity/MainActivity.java
  5. 21
    15
      app/src/main/java/fr/mobdev/lpcprog/adapters/BinariesAdapter.java
  6. 7
    5
      app/src/main/java/fr/mobdev/lpcprog/adapters/DeviceAdapter.java
  7. 116
    0
      app/src/main/java/fr/mobdev/lpcprog/adapters/PartsAdapter.java
  8. 15
    6
      app/src/main/java/fr/mobdev/lpcprog/adapters/ServerAdapter.java
  9. 9
    1
      app/src/main/java/fr/mobdev/lpcprog/dialog/ServerDialog.java
  10. 273
    0
      app/src/main/java/fr/mobdev/lpcprog/fragment/AddPartFragment.java
  11. 360
    0
      app/src/main/java/fr/mobdev/lpcprog/fragment/DeviceFragment.java
  12. 81
    0
      app/src/main/java/fr/mobdev/lpcprog/fragment/PartsFragment.java
  13. 30
    43
      app/src/main/java/fr/mobdev/lpcprog/fragment/ServersFragment.java
  14. 125
    0
      app/src/main/java/fr/mobdev/lpcprog/fragment/USBListFragment.java
  15. 80
    0
      app/src/main/java/fr/mobdev/lpcprog/fragment/Watcher.java
  16. 6
    2
      app/src/main/java/fr/mobdev/lpcprog/listener/FlashListener.java
  17. 0
    1
      app/src/main/java/fr/mobdev/lpcprog/listener/NetworkListener.java
  18. 134
    19
      app/src/main/java/fr/mobdev/lpcprog/managers/DatabaseManager.java
  19. 30
    17
      app/src/main/java/fr/mobdev/lpcprog/managers/IspManager.java
  20. 8
    7
      app/src/main/java/fr/mobdev/lpcprog/managers/NetworkManager.java
  21. 1
    1
      app/src/main/java/fr/mobdev/lpcprog/managers/UsbCommManager.java
  22. 1
    1
      app/src/main/java/fr/mobdev/lpcprog/objects/Part.java
  23. BIN
      app/src/main/res/drawable-hdpi/edit.png
  24. BIN
      app/src/main/res/drawable-hdpi/ic_launcher.png
  25. BIN
      app/src/main/res/drawable-mdpi/edit.png
  26. BIN
      app/src/main/res/drawable-mdpi/ic_launcher.png
  27. BIN
      app/src/main/res/drawable-xhdpi/edit.png
  28. BIN
      app/src/main/res/drawable-xhdpi/ic_launcher.png
  29. BIN
      app/src/main/res/drawable-xxhdpi/edit.png
  30. BIN
      app/src/main/res/drawable-xxhdpi/ic_launcher.png
  31. BIN
      app/src/main/res/drawable-xxxhdpi/ic_launcher.png
  32. 6
    0
      app/src/main/res/drawable/border_red.xml
  33. 9
    0
      app/src/main/res/drawable/side_nav_bar.xml
  34. 253
    0
      app/src/main/res/layout/add_part.xml
  35. 30
    0
      app/src/main/res/layout/app_bar_main.xml
  36. 2
    1
      app/src/main/res/layout/binary_item.xml
  37. 15
    0
      app/src/main/res/layout/content_main.xml
  38. 51
    73
      app/src/main/res/layout/device.xml
  39. 25
    0
      app/src/main/res/layout/main.xml
  40. 0
    33
      app/src/main/res/layout/main_activity.xml
  41. 21
    0
      app/src/main/res/layout/nav_header_main.xml
  42. 33
    0
      app/src/main/res/layout/part_item.xml
  43. 11
    0
      app/src/main/res/layout/parts.xml
  44. 1
    1
      app/src/main/res/layout/server_item.xml
  45. 3
    2
      app/src/main/res/layout/server_section.xml
  46. 13
    37
      app/src/main/res/layout/servers.xml
  47. 22
    0
      app/src/main/res/layout/usb_list.xml
  48. 16
    0
      app/src/main/res/menu/main_drawer.xml
  49. 4
    5
      app/src/main/res/menu/menu_main.xml
  50. 0
    8
      app/src/main/res/menu/menu_servers.xml
  51. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher.png
  52. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher.png
  53. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher.png
  54. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  55. 1
    0
      app/src/main/res/values-v21/styles.xml
  56. 4
    0
      app/src/main/res/values/dimens.xml
  57. 8
    0
      app/src/main/res/values/drawables.xml
  58. 47
    1
      app/src/main/res/values/strings.xml
  59. 12
    11
      app/src/main/res/values/styles.xml
  60. 4
    0
      app/src/main/res/xml/device_filter.xml
  61. 1
    1
      build.gradle
  62. 2
    2
      gradle/wrapper/gradle-wrapper.properties

+ 8
- 8
app/build.gradle View File

@@ -1,13 +1,13 @@
apply plugin: 'com.android.application'

android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
compileSdkVersion 24
buildToolsVersion "24.0.3"

defaultConfig {
applicationId "fr.mobdev.lpcprog"
minSdkVersion 12
targetSdkVersion 23
minSdkVersion 14
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
@@ -19,13 +19,13 @@ android {
}
}

repositories{
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')
compile 'com.android.support:appcompat-v7:24.2.1'
compile 'com.android.support:design:24.2.1'
compile 'com.android.support:support-v4:24.2.1'
}

+ 6
- 11
app/src/main/AndroidManifest.xml View File

@@ -5,17 +5,20 @@
<uses-feature
android:name="android.hardware.usb.host"
android:required="true" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

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

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:screenOrientation="portrait"
android:name=".activity.MainActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -23,14 +26,6 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:label="@string/device_informations"
android:name=".activity.DeviceActivity"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:label="@string/server_management"
android:name=".activity.ServersActivity"
android:theme="@style/AppTheme.NoActionBar" />
</application>

</manifest>

+ 0
- 218
app/src/main/java/fr/mobdev/lpcprog/activity/DeviceActivity.java View File

@@ -1,218 +0,0 @@
/*
* Copyright (C) 2016 Anthony Chomienne, anthony@mob-dev.fr
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package fr.mobdev.lpcprog.activity;

import android.annotation.SuppressLint;
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;

public class DeviceActivity extends AppCompatActivity {

private UsbCommManager comm;
private USBDevice dev;
private List<Server> servers;
private long part_id;

@Override
@SuppressLint("SetTextI18n")
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<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(getApplicationContext().getString(R.string.dev_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();
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(){
System.out.println("doUsb");
new Thread(new Runnable() {
@Override
public void run() {
boolean conn = comm.openConnection(dev);
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";
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));
part_id = Long.parseLong(partid);
IspManager.getInstance(DeviceActivity.this).setPartId(part_id);
}
}
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);
}
});
}

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<List<Server>> 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();

}
}

+ 186
- 57
app/src/main/java/fr/mobdev/lpcprog/activity/MainActivity.java View File

@@ -18,103 +18,232 @@

package fr.mobdev.lpcprog.activity;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
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 java.util.List;

import fr.mobdev.lpcprog.adapters.DeviceAdapter;
import fr.mobdev.lpcprog.R;
import fr.mobdev.lpcprog.dialog.ServerDialog;
import fr.mobdev.lpcprog.fragment.AddPartFragment;
import fr.mobdev.lpcprog.fragment.DeviceFragment;
import fr.mobdev.lpcprog.fragment.PartsFragment;
import fr.mobdev.lpcprog.fragment.ServersFragment;
import fr.mobdev.lpcprog.fragment.USBListFragment;
import fr.mobdev.lpcprog.listener.ServerListener;
import fr.mobdev.lpcprog.objects.USBDevice;
import fr.mobdev.lpcprog.managers.UsbCommManager;

public class MainActivity extends AppCompatActivity {

private UsbCommManager comm;
private List<USBDevice> devices;
private int value = 0;

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener,
USBListFragment.USBInteractionListener,
AddPartFragment.OnAddInteractionListener
{

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
Toolbar toolbar = (Toolbar) findViewById(R.id.main_toolbar);
setContentView(R.layout.main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
comm = UsbCommManager.getInstance(this);

final GestureDetector gestureDetector = new GestureDetector(MainActivity.this, new GestureDetector.SimpleOnGestureListener(){
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();

final FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
Fragment frag = USBListFragment.newInstance();
transaction.replace(R.id.fragment_container, frag);
transaction.commit();

IntentFilter filter = new IntentFilter("android.hardware.usb.action.USB_DEVICE_ATTACHED");
filter.addAction("android.hardware.usb.action.USB_DEVICE_DETACHED");
filter.addAction("com.ftdi.j2xx");
registerReceiver(new BroadcastReceiver() {
@Override
public boolean onSingleTapUp(MotionEvent e){
return true;
public void onReceive(Context context, Intent intent) {
Fragment fragment = manager.findFragmentById(R.id.fragment_container);
if(fragment instanceof USBListFragment) {
((USBListFragment)fragment).updateDevice(null);
}
else if(fragment instanceof DeviceFragment){
manager.popBackStack();
}

}
});
},filter);

RecyclerView view = (RecyclerView) findViewById(R.id.device_list);
view.setLayoutManager(new LinearLayoutManager(this));
view.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}

@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 void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
updateMenu(null);
}
}

private void updateMenu(Fragment frag) {
Toolbar bar = (Toolbar) findViewById(R.id.toolbar);
Menu menu = bar.getMenu();
MenuItem add = menu.findItem(R.id.action_add_new);
MenuItem refresh = menu.findItem(R.id.action_refresh);
if(frag == null) {
FragmentManager manager = getSupportFragmentManager();
frag = manager.findFragmentById(R.id.fragment_container);
}
if(frag instanceof USBListFragment || frag instanceof DeviceFragment) {
add.setVisible(false);
refresh.setVisible(true);
} else if(frag instanceof PartsFragment || frag instanceof ServersFragment) {
add.setVisible(true);
refresh.setVisible(false);
} else {
add.setVisible(false);
refresh.setVisible(false);
}
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
updateMenu(null);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
FragmentManager manager = getSupportFragmentManager();
final Fragment frag = manager.findFragmentById(R.id.fragment_container);
if (id == R.id.action_refresh) {
updateList();
return true;
}
else if(id == R.id.action_server){
Intent newIntent = new Intent(this,ServersActivity.class);
startActivity(newIntent);
}
if(frag instanceof USBListFragment) {
((USBListFragment) frag).updateDevice(null);
} else if (frag instanceof DeviceFragment) {
((DeviceFragment) frag).updateRepositories(null);
}
} else if (id == R.id.action_add_new) {

if(frag instanceof ServersFragment) {

ServerDialog serverDialog = new ServerDialog();
serverDialog.setServerListener(new ServerListener() {
@Override
public void updateServerList() {
((ServersFragment) frag).updateServers(null);
}
});
serverDialog.show(getSupportFragmentManager(),"Server Dialog");
} else if(frag instanceof PartsFragment) {
FragmentTransaction transaction = manager.beginTransaction();
Fragment fragment = AddPartFragment.newInstance(-1);
transaction.replace(R.id.fragment_container, fragment);
transaction.addToBackStack(null);
transaction.commit();
updateMenu(fragment);
}

}
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);
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
Fragment frag = null;
final FragmentManager manager = getSupportFragmentManager();
final FragmentTransaction transaction = manager.beginTransaction();
final Fragment old = manager.findFragmentById(R.id.fragment_container);
if(id == R.id.nav_devices) {
if(!(old instanceof USBListFragment)) {
frag = USBListFragment.newInstance();
transaction.replace(R.id.fragment_container, frag);
transaction.addToBackStack(null);
transaction.commit();
}
} else if (id == R.id.nav_servers) {
if(!(old instanceof ServersFragment)) {
frag = ServersFragment.newInstance();
transaction.replace(R.id.fragment_container, frag);
transaction.addToBackStack(null);
transaction.commit();
}
} else if (id == R.id.nav_parts) {
if(!(old instanceof PartsFragment)) {
frag = PartsFragment.newInstance();
final PartsFragment fragmentParts = (PartsFragment) frag;
fragmentParts.setOnEditPressListener(new PartsFragment.OnEditPressListener() {

@Override
public void onEditPress(Long part_id) {
Fragment fragment = AddPartFragment.newInstance(part_id);
transaction.replace(R.id.fragment_container, fragment);
transaction.addToBackStack(null);
transaction.commit();
fragmentParts.updateList();
updateMenu(fragment);

}

@Override
public void onDeletePress() {
fragmentParts.updateList();
}
});
transaction.replace(R.id.fragment_container, frag);
transaction.addToBackStack(null);
transaction.commit();
}
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
updateMenu(frag);
return true;
}

@Override
public void onUSBDeviceClick(USBDevice device) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
Fragment frag = DeviceFragment.newInstance(device.PID,device.VID);
transaction.replace(R.id.fragment_container, frag);
transaction.addToBackStack(null);
transaction.commit();

}


@Override
public void onCancel() {
onBackPressed();
}

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);
@Override
public void onSubmit() {
onBackPressed();
FragmentManager manager = getSupportFragmentManager();
Fragment frag = manager.findFragmentById(R.id.fragment_container);
if(frag instanceof PartsFragment) {
((PartsFragment)frag).updateList();
updateMenu(frag);
}
}
}

+ 21
- 15
app/src/main/java/fr/mobdev/lpcprog/adapters/BinariesAdapter.java View File

@@ -18,6 +18,7 @@

package fr.mobdev.lpcprog.adapters;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.DialogInterface;
import android.support.design.widget.Snackbar;
@@ -51,10 +52,12 @@ public class BinariesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
private List<Server> servers;
private int count;
private Activity activity;
private FlashListener listener;

public BinariesAdapter(List<Server> servers, Activity activity) {
public BinariesAdapter(List<Server> servers, Activity activity, FlashListener listener) {
this.servers = servers;
this.activity = activity;
this.listener = listener;
countElements();
}

@@ -85,7 +88,7 @@ public class BinariesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
int pos = getRealPosition(position);
Server server = servers.get(section);
Binary binary = servers.get(section).binaries.get(pos);
binaryHolder.setupBinary(server,binary,activity);
binaryHolder.setupBinary(server,binary,activity,listener);
}
}

@@ -149,12 +152,13 @@ public class BinariesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
}

class BinaryHolder extends RecyclerView.ViewHolder{
DownloadListener listener;
public BinaryHolder(View itemView) {
private DownloadListener listener;
BinaryHolder(View itemView) {
super(itemView);
}

public void setupBinary(final Server server, final Binary binary, final Activity activity){
@SuppressLint("SetTextI18n")
void setupBinary(final Server server, final Binary binary, final Activity activity, final FlashListener flashListener){

TextView name = (TextView) itemView.findViewById(R.id.binary_name);
TextView version = (TextView) itemView.findViewById(R.id.binary_version);
@@ -268,8 +272,10 @@ class BinaryHolder extends RecyclerView.ViewHolder{
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())
if(file.exists()) {
//noinspection ResultOfMethodCallIgnored
file.delete();
}
binary.isDownloaded = false;
DatabaseManager.getInstance(itemView.getContext()).deleteBinary(binary.id);
//file and reset all downloaded items
@@ -284,25 +290,25 @@ class BinaryHolder extends RecyclerView.ViewHolder{
dialog.cancel();
}
});
AlertDialog alert = builder.create();
final AlertDialog alert = builder.create();
alert.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialogInterface) {
alert.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(0xFF000000);
alert.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(0xFF000000);
}
});
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) {
new Thread(new Runnable() {
@Override
public void run() {
IspManager.getInstance(itemView.getContext()).flashBinary(server,binary,flashListener);
IspManager.getInstance(itemView.getContext()).flashBinary(server,binary,flashListener,flashView);
}
}).start();
}

+ 7
- 5
app/src/main/java/fr/mobdev/lpcprog/adapters/DeviceAdapter.java View File

@@ -18,6 +18,7 @@

package fr.mobdev.lpcprog.adapters;

import android.annotation.SuppressLint;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
@@ -56,17 +57,18 @@ public class DeviceAdapter extends RecyclerView.Adapter<DeviceHolder> {
class DeviceHolder extends RecyclerView.ViewHolder {


public DeviceHolder(View itemView) {
DeviceHolder(View itemView) {
super(itemView);
}

public void setupDevice(USBDevice device){
@SuppressLint("SetTextI18n")
void setupDevice(USBDevice device){
TextView name = (TextView) itemView.findViewById(R.id.device_name);
name.setText("Name: " + device.description);
name.setText(itemView.getContext().getString(R.string.dev_name) + device.description);
TextView vendor = (TextView) itemView.findViewById(R.id.device_vendor_id);
vendor.setText(String.format("Vendor Id: %04x",device.VID));
vendor.setText(itemView.getContext().getString(R.string.vendor_id)+String.format("%04x",device.VID));
TextView product = (TextView) itemView.findViewById(R.id.device_id);
product.setText(String.format("Product id: %04x", device.PID));
product.setText(itemView.getContext().getString(R.string.product_id)+String.format("%04x", device.PID));

}


+ 116
- 0
app/src/main/java/fr/mobdev/lpcprog/adapters/PartsAdapter.java View File

@@ -0,0 +1,116 @@
/*
* Copyright (C) 2016 Anthony Chomienne, anthony@mob-dev.fr
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package fr.mobdev.lpcprog.adapters;

import android.content.DialogInterface;
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.TextView;

import java.util.List;

import fr.mobdev.lpcprog.R;
import fr.mobdev.lpcprog.fragment.PartsFragment;
import fr.mobdev.lpcprog.managers.DatabaseManager;
import fr.mobdev.lpcprog.objects.Part;

public class PartsAdapter extends RecyclerView.Adapter<PartHolder>{

private List<Part> parts;
private PartsFragment.OnEditPressListener listener;

public PartsAdapter(List<Part> devices, PartsFragment.OnEditPressListener listener){
this.parts = devices;
this.listener = listener;
}

@Override
public PartHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.part_item,parent,false);
return new PartHolder(view,listener);
}

@Override
public void onBindViewHolder(PartHolder holder, int position) {
holder.setupPart(parts.get(position));
}

@Override
public int getItemCount() {
return parts.size();
}
}

class PartHolder extends RecyclerView.ViewHolder {

private PartsFragment.OnEditPressListener listener;

PartHolder(View itemView, PartsFragment.OnEditPressListener listener) {
super(itemView);
this.listener = listener;
}

void setupPart(final Part part){
TextView name = (TextView) itemView.findViewById(R.id.part_name);
name.setText(part.part_name);
ImageView deleteView = (ImageView) itemView.findViewById(R.id.part_delete);
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_part_message)+" "+part.part_name)
.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
DatabaseManager.getInstance(itemView.getContext()).deletePart(part.id);
listener.onDeletePress();
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
final AlertDialog alert = builder.create();
alert.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialogInterface) {
alert.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(0xFF000000);
alert.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(0xFF000000);
}
});
alert.show();
}
});

ImageView editView = (ImageView) itemView.findViewById(R.id.part_edit);
editView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
listener.onEditPress(part.part_id);
}
});
}
}

+ 15
- 6
app/src/main/java/fr/mobdev/lpcprog/adapters/ServerAdapter.java View File

@@ -90,6 +90,7 @@ public class ServerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
}
}
count = size;
System.out.println("get count"+count);
}

private int getRealPosition(int fakePosition) {
@@ -123,6 +124,7 @@ public class ServerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>

@Override
public int getItemCount() {
System.out.println("get count"+count);
return count;
}

@@ -141,13 +143,13 @@ public class ServerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
}

class ServerHolder extends RecyclerView.ViewHolder{
ServerListener serverListener;
public ServerHolder(View itemView, ServerListener serverListener) {
private ServerListener serverListener;
ServerHolder(View itemView, ServerListener serverListener) {
super(itemView);
this.serverListener = serverListener;
}

public void setupServer(final Server server){
void setupServer(final Server server){
TextView view = (TextView) itemView.findViewById(R.id.server_name);
view.setText(server.url.toString());
ImageView deleteView = (ImageView) itemView.findViewById(R.id.server_delete);
@@ -170,7 +172,14 @@ class ServerHolder extends RecyclerView.ViewHolder{
dialog.cancel();
}
});
AlertDialog alert = builder.create();
final AlertDialog alert = builder.create();
alert.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialogInterface) {
alert.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(0xFF000000);
alert.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(0xFF000000);
}
});
alert.show();
}
});
@@ -179,11 +188,11 @@ class ServerHolder extends RecyclerView.ViewHolder{

class SectionHolder extends RecyclerView.ViewHolder {

public SectionHolder(View itemView) {
SectionHolder(View itemView) {
super(itemView);
}

public void setupSection(String sectionName) {
void setupSection(String sectionName) {
TextView view = (TextView)itemView.findViewById(R.id.section_name);
view.setText(sectionName);
}

+ 9
- 1
app/src/main/java/fr/mobdev/lpcprog/dialog/ServerDialog.java View File

@@ -79,7 +79,15 @@ public class ServerDialog extends DialogFragment {
dismiss();
}
});
final AlertDialog alert = builder.create();
alert.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialogInterface) {
alert.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(0xFF000000);
alert.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(0xFF000000);
}
});

return builder.create();
return alert;
}
}

+ 273
- 0
app/src/main/java/fr/mobdev/lpcprog/fragment/AddPartFragment.java View File

@@ -0,0 +1,273 @@
/*
* Copyright (C) 2016 Anthony Chomienne, anthony@mob-dev.fr
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package fr.mobdev.lpcprog.fragment;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;

import java.util.ArrayList;
import java.util.List;

import fr.mobdev.lpcprog.R;
import fr.mobdev.lpcprog.managers.DatabaseManager;
import fr.mobdev.lpcprog.objects.Part;

public class AddPartFragment extends Fragment {

private Part part;

private OnAddInteractionListener listener;
private List<TextWatcher> watchers;

public AddPartFragment() {
// Required empty public constructor
}

public static AddPartFragment newInstance(long part_id) {
AddPartFragment fragment = new AddPartFragment();
Bundle args = new Bundle();
args.putLong("part_id", part_id);
fragment.setArguments(args);
return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
long part_id = getArguments().getLong("part_id");
if(part_id != -1)
part = DatabaseManager.getInstance(getActivity()).getPart(part_id);
else
part = null;
}
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
watchers = new ArrayList<>();
final View v = inflater.inflate(R.layout.add_part, container, false);
EditText t = (EditText) v.findViewById(R.id.edit_part_id);
watchers.add(new HexaWatcher(t,this));
t.setText(part != null ? "0x"+String.format("%08x",part.part_id).toUpperCase() : "0x");
t.addTextChangedListener(watchers.get(watchers.size()-1));
t = (EditText) v.findViewById(R.id.edit_flash_base_addr);
watchers.add(new HexaWatcher(t,this));
t.setText(part != null ? "0x"+String.format("%08x",part.flash_base_addr).toUpperCase() : "0x");
t.addTextChangedListener(watchers.get(watchers.size()-1));
t = (EditText) v.findViewById(R.id.edit_flash_size);
watchers.add(new HexaWatcher(t,this));
t.setText(part != null ? "0x"+String.format("%04x",part.flash_size).toUpperCase() : "0x");
t.addTextChangedListener(watchers.get(watchers.size()-1));
t = (EditText) v.findViewById(R.id.edit_reset_vector_offset);
watchers.add(new HexaWatcher(t,this));
t.setText(part != null ? "0x"+String.format("%02x",part.reset_vector_offset).toUpperCase() : "0x");
t.addTextChangedListener(watchers.get(watchers.size()-1));
t = (EditText) v.findViewById(R.id.edit_ram_base_addr);
watchers.add(new HexaWatcher(t,this));
t.setText(part != null ? "0x"+String.format("%08x",part.ram_base_addr).toUpperCase() : "0x");
t.addTextChangedListener(watchers.get(watchers.size()-1));
t = (EditText) v.findViewById(R.id.edit_ram_size);
watchers.add(new HexaWatcher(t,this));
t.setText(part != null ? "0x"+String.format("%04x",part.ram_size).toUpperCase() : "0x");
t.addTextChangedListener(watchers.get(watchers.size()-1));
t = (EditText) v.findViewById(R.id.edit_ram_buf_offset);
watchers.add(new HexaWatcher(t,this));
t.setText(part != null ? "0x"+String.format("%03x",part.ram_buffer_offset).toUpperCase() : "0x");
t.addTextChangedListener(watchers.get(watchers.size()-1));
t = (EditText) v.findViewById(R.id.edit_ram_buf_size);
watchers.add(new HexaWatcher(t,this));
t.setText(part != null ? "0x"+String.format("%03x",part.ram_buffer_size).toUpperCase() : "0x");
t.addTextChangedListener(watchers.get(watchers.size()-1));

t = (EditText) v.findViewById(R.id.edit_part_name);
watchers.add(new EmptyWatcher(t,this));
t.setText(part != null ? part.part_name : "");
t.addTextChangedListener(watchers.get(watchers.size()-1));
t = (EditText) v.findViewById(R.id.edit_flash_nb_sector);
watchers.add(new EmptyWatcher(t,this));
t.setText(part != null ? String.valueOf(part.flash_nb_sectors) : "");
t.addTextChangedListener(watchers.get(watchers.size()-1));

Spinner s = (Spinner) v.findViewById(R.id.spinner_uuencode);
if(part != null)
s.setSelection(part.uuencode ? 0 : 1);

Button b = (Button) v.findViewById(R.id.submit);
b.setTextColor(0xFF000000);
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(part == null) {
part = new Part();
part.id = -1;
}
EditText t = (EditText) v.findViewById(R.id.edit_part_id);
part.part_id = Long.parseLong(t.getText().toString().replace("0x",""),16);
t = (EditText) v.findViewById(R.id.edit_flash_base_addr);
part.flash_base_addr = Integer.parseInt(t.getText().toString().replace("0x",""),16);
t = (EditText) v.findViewById(R.id.edit_flash_size);
part.flash_size = Integer.parseInt(t.getText().toString().replace("0x",""),16);
t = (EditText) v.findViewById(R.id.edit_reset_vector_offset);
part.reset_vector_offset = Integer.parseInt(t.getText().toString().replace("0x",""),16);
t = (EditText) v.findViewById(R.id.edit_ram_base_addr);
part.ram_base_addr = Integer.parseInt(t.getText().toString().replace("0x",""),16);
t = (EditText) v.findViewById(R.id.edit_ram_size);
part.ram_size = Integer.parseInt(t.getText().toString().replace("0x",""),16);
t = (EditText) v.findViewById(R.id.edit_ram_buf_offset);
part.ram_buffer_offset = Integer.parseInt(t.getText().toString().replace("0x",""),16);
t = (EditText) v.findViewById(R.id.edit_ram_buf_size);
part.ram_buffer_size = Integer.parseInt(t.getText().toString().replace("0x",""),16);

t = (EditText) v.findViewById(R.id.edit_part_name);
part.part_name = t.getText().toString();
t = (EditText) v.findViewById(R.id.edit_flash_nb_sector);
part.flash_nb_sectors = Integer.parseInt(t.getText().toString());
Spinner s = (Spinner) v.findViewById(R.id.spinner_uuencode);
part.uuencode = s.getSelectedItemPosition() == 0;
if(part.id == -1)
DatabaseManager.getInstance(getActivity()).addPart(part);
else
DatabaseManager.getInstance(getActivity()).updatePart(part);

//cleanup();
listener.onSubmit();
}
});
b = (Button) v.findViewById(R.id.cancel);
b.setTextColor(0xFF000000);
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
cleanup();
listener.onCancel();
}
});
modifyBt(v);
return v;
}

@Override
public void onAttach(Context context) {
super.onAttach(context);
listener = (OnAddInteractionListener) context;
}

@Override
public void onDetach() {
super.onDetach();
listener = null;
}

public interface OnAddInteractionListener {
void onCancel();
void onSubmit();
}
public void modifyBt (View v){
if (v == null)
v = getView();
boolean isValid = true;
assert v != null;
EditText t = (EditText) v.findViewById(R.id.edit_part_id);
String hexa = t.getText().toString();
if(!hexa.matches("0x[0-9A-F]*"))
isValid = false;
t = (EditText) v.findViewById(R.id.edit_flash_base_addr);
hexa = t.getText().toString();
if(!hexa.matches("0x[0-9A-F]*"))
isValid = false;
t = (EditText) v.findViewById(R.id.edit_flash_size);
hexa = t.getText().toString();
if(!hexa.matches("0x[0-9A-F]*"))
isValid = false;
t = (EditText) v.findViewById(R.id.edit_reset_vector_offset);
hexa = t.getText().toString();
if(!hexa.matches("0x[0-9A-F]*"))
isValid = false;
t = (EditText) v.findViewById(R.id.edit_ram_base_addr);
hexa = t.getText().toString();
if(!hexa.matches("0x[0-9A-F]*"))
isValid = false;
t = (EditText) v.findViewById(R.id.edit_ram_size);
hexa = t.getText().toString();
if(!hexa.matches("0x[0-9A-F]*"))
isValid = false;
t = (EditText) v.findViewById(R.id.edit_ram_buf_offset);
hexa = t.getText().toString();
if(!hexa.matches("0x[0-9A-F]*"))
isValid = false;
t = (EditText) v.findViewById(R.id.edit_ram_buf_size);
hexa = t.getText().toString();
if(!hexa.matches("0x[0-9A-F]*"))
isValid = false;

t = (EditText) v.findViewById(R.id.edit_flash_nb_sector);
if(t.getText().toString().isEmpty())
isValid = false;
t = (EditText) v.findViewById(R.id.edit_part_name);
if(t.getText().toString().isEmpty())
isValid = false;
Button b = (Button) v.findViewById(R.id.submit);
if(isValid) {
b.setTextColor(0xFF000000);
b.setEnabled(true);
}
else {
b.setTextColor(0xFFA0A0A0);
b.setEnabled(false);
}

}

public void cleanup() {
View v = getView();
assert v != null;
EditText t = (EditText) v.findViewById(R.id.edit_part_id);
t.removeTextChangedListener(watchers.get(0));
t = (EditText) v.findViewById(R.id.edit_flash_base_addr);
t.removeTextChangedListener(watchers.get(1));
t = (EditText) v.findViewById(R.id.edit_flash_size);
t.removeTextChangedListener(watchers.get(2));
t = (EditText) v.findViewById(R.id.edit_reset_vector_offset);
t.removeTextChangedListener(watchers.get(3));
t = (EditText) v.findViewById(R.id.edit_ram_base_addr);
t.removeTextChangedListener(watchers.get(4));
t = (EditText) v.findViewById(R.id.edit_ram_size);
t.removeTextChangedListener(watchers.get(5));
t = (EditText) v.findViewById(R.id.edit_ram_buf_offset);
t.removeTextChangedListener(watchers.get(6));
t = (EditText) v.findViewById(R.id.edit_ram_buf_size);
t.removeTextChangedListener(watchers.get(7));
t = (EditText) v.findViewById(R.id.edit_part_name);
t.removeTextChangedListener(watchers.get(8));
t = (EditText) v.findViewById(R.id.edit_flash_nb_sector);
t.removeTextChangedListener(watchers.get(9));

watchers.clear();
}
}

+ 360
- 0
app/src/main/java/fr/mobdev/lpcprog/fragment/DeviceFragment.java View File

@@ -0,0 +1,360 @@
/*
* Copyright (C) 2016 Anthony Chomienne, anthony@mob-dev.fr
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package fr.mobdev.lpcprog.fragment;

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.support.design.widget.Snackbar;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.LinearLayoutManager;
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.ProgressBar;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

import fr.mobdev.lpcprog.adapters.BinariesAdapter;
import fr.mobdev.lpcprog.listener.FlashListener;
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;

public class DeviceFragment extends Fragment {

private UsbCommManager comm;
private USBDevice dev;
private List<Server> servers;
private long part_id;
private FlashListener flashListener;

public DeviceFragment() {

}

public static DeviceFragment newInstance(int PID, int VID) {
DeviceFragment frag = new DeviceFragment();
Bundle args = new Bundle();
args.putInt("PID",PID);
args.putInt("VID",VID);
frag.setArguments(args);
return frag;
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@SuppressLint("SetTextI18n")
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater,container,savedInstanceState);
final View v = inflater.inflate(R.layout.device,container,false);
servers = new ArrayList<>();
comm = UsbCommManager.getInstance(getActivity());
part_id = 0;
List<USBDevice> devices = comm.getDevices();
int pid = getArguments().getInt("PID",-1);
int vid = getArguments().getInt("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) v.findViewById(R.id.name);
name.setText(getString(R.string.dev_name)+ dev.description);
TextView vendor = (TextView) v.findViewById(R.id.vendor_id);
vendor.setText(getString(R.string.vendor_id)+String.format("%04x", dev.VID));
TextView product = (TextView) v.findViewById(R.id.id);
product.setText(getString(R.string.product_id)+String.format("%04x", dev.PID));
}
doUsb();
ProgressBar bar = (ProgressBar) v.findViewById(R.id.progress_browse);
bar.setVisibility(View.GONE);

RecyclerView list = (RecyclerView) v.findViewById(R.id.bin_list);
list.setLayoutManager(new LinearLayoutManager(getContext()));
final ProgressDialog dialog = new ProgressDialog(getActivity());
dialog.setCancelable(false);
dialog.setTitle(R.string.flash_progress);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setMessage("toto");

flashListener = new FlashListener() {

@Override
public void onStartFlash() {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.show();

}
});
}

@Override
public void onSuccess() {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.dismiss();
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.flash_succeed);
builder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {

@Override
public void onClick(DialogInterface dialogInterface, int i) {

}
});
final AlertDialog alert = builder.create();
alert.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialogInterface) {
alert.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(0xFF000000);
}
});
alert.show();
}
});
}

@Override
public void onProgress(final int step, final int endStep, final int progress, final int step_res_id) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.setMax(100);
dialog.setProgress(progress);
dialog.setMessage(getString(R.string.step)+" "+String.valueOf(step)+"/"+String.valueOf(endStep)+" "+getString(step_res_id));
dialog.show();
}
});
}

@Override
public void onError(final String error, final ImageView view) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.dismiss();
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(error);
builder.setPositiveButton(R.string.retry_browse, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
view.performClick();
}
});
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {

}
});
final AlertDialog alert = builder.create();
alert.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialogInterface) {
alert.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(0xFF000000);
alert.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(0xFF000000);
}
});
alert.show();
}
});
}
};
updateRepositories(v);
return v;
}

private void doUsb(){
System.out.println("doUsb");
new Thread(new Runnable() {
@Override
public void run() {
boolean conn = comm.openConnection(dev);
IspManager manager = IspManager.getInstance(getActivity());
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)) {
updateIDS(uidStr,partidStr,bootStr);
getActivity().runOnUiThread(new Thread(new Runnable() {
@Override
public void run() {
View v = getView();
if(v == null)
return;
final Snackbar msg = Snackbar.make(v.findViewById(R.id.bin_list), getString(R.string.can_read_uid),Snackbar.LENGTH_INDEFINITE);
msg.setAction(R.string.retry_browse, new View.OnClickListener() {
@Override
public void onClick(View v) {
msg.dismiss();
doUsb();
}
});
msg.show();
}
}));
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));
part_id = Long.parseLong(partid);
IspManager.getInstance(getActivity()).setPartId(part_id);
}
}
updateIDS(uidStr,partidStr,bootStr);

}
}).start();
}
@SuppressLint("N")
private void updateIDS(final String uid, final String partid, final String boot) {
final View v = getView();
assert v != null;
if(getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
TextView view = (TextView) v.findViewById(R.id.uids);
view.setText(uid);

view = (TextView) v.findViewById(R.id.part_id);
view.setText(partid);

view = (TextView) v.findViewById(R.id.boot_version);
view.setText(boot);
}
});
}
}

public void updateRepositories(View view){
System.out.println("Update Repo");
if(view == null)
view = getView();
final View v = view;
assert v != null;
servers.clear();
final NetworkListener listener = new NetworkListener() {
@Override
public void startBinaries() {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
ProgressBar bar = (ProgressBar) v.findViewById(R.id.progress_browse);
bar.setVisibility(View.VISIBLE);
RecyclerView list = (RecyclerView) v.findViewById(R.id.bin_list);
list.setVisibility(View.GONE);

}
});
}

@Override
public void startServer(Server server) {
}

@Override
public void endServer(Server server) {
System.out.println(server.url.toString()+"empty "+server.binaries.isEmpty()+" "+server.binaries.size());
if(!server.binaries.isEmpty())
servers.add(server);
}

@Override
public void endBinaries() {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
ProgressBar bar = (ProgressBar) v.findViewById(R.id.progress_browse);
bar.setVisibility(View.GONE);
RecyclerView list = (RecyclerView) v.findViewById(R.id.bin_list);
list.setVisibility(View.VISIBLE);
BinariesAdapter adapter = new BinariesAdapter(servers, getActivity(),flashListener);
list.setAdapter(adapter);
}
});
}

@Override
public void onError(final String error) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
ProgressBar bar = (ProgressBar) v.findViewById(R.id.progress_browse);
bar.setVisibility(View.GONE);
final Snackbar msg = Snackbar.make(v.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(null);
}
});
msg.show();
List<List<Server>> localServers = DatabaseManager.getInstance(getActivity()).getServers();
servers.addAll(localServers.get(0));
servers.addAll(localServers.get(1));
servers.addAll(localServers.get(2));
RecyclerView list = (RecyclerView) v.findViewById(R.id.bin_list);
list.setVisibility(View.VISIBLE);
BinariesAdapter adapter = new BinariesAdapter(servers,getActivity(),flashListener);
list.setAdapter(adapter);

}
});
}
};
NetworkManager.getInstance(listener,getActivity()).browseBinaries();
}
}

+ 81
- 0
app/src/main/java/fr/mobdev/lpcprog/fragment/PartsFragment.java View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2016 Anthony Chomienne, anthony@mob-dev.fr
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package fr.mobdev.lpcprog.fragment;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.List;

import fr.mobdev.lpcprog.R;
import fr.mobdev.lpcprog.adapters.PartsAdapter;
import fr.mobdev.lpcprog.managers.DatabaseManager;
import fr.mobdev.lpcprog.objects.Part;

public class PartsFragment extends Fragment {

private OnEditPressListener onEditListener;

public PartsFragment() {
}

public static PartsFragment newInstance() {
return new PartsFragment();
}

public void setOnEditPressListener(OnEditPressListener listener){
onEditListener = listener;
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.parts, container, false);
RecyclerView list = (RecyclerView) v.findViewById(R.id.parts_list);
list.setLayoutManager(new LinearLayoutManager(getActivity()));
List<Part> parts = DatabaseManager.getInstance(getActivity()).getParts();
PartsAdapter adapter = new PartsAdapter(parts,onEditListener);
list.setAdapter(adapter);
return v;
}

public void updateList() {
View v = getView();
if(v == null)
return;
RecyclerView list = (RecyclerView) v.findViewById(R.id.parts_list);
List<Part> parts = DatabaseManager.getInstance(getActivity()).getParts();
PartsAdapter adapter = new PartsAdapter(parts,onEditListener);
list.setAdapter(adapter);
}

public interface OnEditPressListener{
void onEditPress(Long part_id);
void onDeletePress();
}
}

app/src/main/java/fr/mobdev/lpcprog/activity/ServersActivity.java → app/src/main/java/fr/mobdev/lpcprog/fragment/ServersFragment.java View File

@@ -16,43 +16,48 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package fr.mobdev.lpcprog.activity;
package fr.mobdev.lpcprog.fragment;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

import fr.mobdev.lpcprog.R;
import fr.mobdev.lpcprog.adapters.ServerAdapter;
import fr.mobdev.lpcprog.dialog.ServerDialog;
import fr.mobdev.lpcprog.listener.ServerListener;
import fr.mobdev.lpcprog.managers.DatabaseManager;
import fr.mobdev.lpcprog.objects.Server;

/*
* Activity that allow user to manage the server where he want to upload his images. Server must be lutim instance to work with the app
* Activity that allow user to manage the server where he want to upload his images. Server must contains a Binaries file to work with the app
*/
public class ServersActivity extends AppCompatActivity {
public class ServersFragment extends Fragment {

private List<List<Server>> dbServers;
private ServerListener serverListener;

public ServersFragment() {

}

public static Fragment newInstance() {
return new ServersFragment();
}

@Override
protected void onCreate(Bundle savedInstanceState) {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.servers);

Toolbar toolbar = (Toolbar) findViewById(R.id.servers_toolbar);
setSupportActionBar(toolbar);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View v = inflater.inflate(R.layout.servers,container,false);
/* ***** Change status of the repos: active to inactive or reverse *****

ListView serverList = (ListView) findViewById(R.id.servers_list);
@@ -68,47 +73,29 @@ public class ServersActivity extends AppCompatActivity {
serverListener = new ServerListener() {
@Override
public void updateServerList() {
updateServers();
updateServers(null);
}
};

updateServers();
updateServers(v);
return v;
}

private void updateServers()
public void updateServers(View v)
{
// build the view with server list in database
dbServers = DatabaseManager.getInstance(getApplicationContext()).getServers();
List<List<Server>> dbServers = DatabaseManager.getInstance(getActivity()).getServers();
List<String> namesList = new ArrayList<>();
namesList.add(getString(R.string.active_section));
namesList.add(getString(R.string.inactive_section));
namesList.add(getString(R.string.failed_section));
ServerAdapter adapter = new ServerAdapter(dbServers,namesList,serverListener);

RecyclerView serverList = (RecyclerView) findViewById(R.id.servers_list);
serverList.setLayoutManager(new LinearLayoutManager(this));
serverList.setAdapter(adapter);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_servers, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();

if (id == R.id.action_add_server) {

ServerDialog serverDialog = new ServerDialog();
serverDialog.setServerListener(serverListener);
serverDialog.show(getSupportFragmentManager(),"Server Dialog");
return true;
if (v == null)
v = getView();
if(v!=null) {
RecyclerView serverList = (RecyclerView) v.findViewById(R.id.servers_list);
serverList.setLayoutManager(new LinearLayoutManager(getContext()));
serverList.setAdapter(adapter);
}

return super.onOptionsItemSelected(item);
}

}

+ 125
- 0
app/src/main/java/fr/mobdev/lpcprog/fragment/USBListFragment.java View File

@@ -0,0 +1,125 @@
/*
* Copyright (C) 2016 Anthony Chomienne, anthony@mob-dev.fr
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package fr.mobdev.lpcprog.fragment;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import java.util.List;

import fr.mobdev.lpcprog.adapters.DeviceAdapter;
import fr.mobdev.lpcprog.R;
import fr.mobdev.lpcprog.objects.USBDevice;
import fr.mobdev.lpcprog.managers.UsbCommManager;

public class USBListFragment extends Fragment {

private List<USBDevice> devices;
private int value = 0;
private USBInteractionListener listener;
private UsbCommManager comm;

public USBListFragment() {

}

public static USBListFragment newInstance() {
return new USBListFragment();
}


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.usb_list,container,false);
comm = UsbCommManager.getInstance(getActivity());

final GestureDetector gestureDetector = new GestureDetector(getActivity(), new GestureDetector.SimpleOnGestureListener(){
@Override
public boolean onSingleTapUp(MotionEvent e){
return true;
}
});

RecyclerView view = (RecyclerView) v.findViewById(R.id.device_list);
view.setLayoutManager(new LinearLayoutManager(getContext()));
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;
}
});
updateDevice(v);
return v;
}

public void updateDevice(View v) {
devices = comm.getDevices();
if(v == null)
v = getView();
assert v != null;
DeviceAdapter adapter = new DeviceAdapter(devices);
RecyclerView view = (RecyclerView) v.findViewById(R.id.device_list);
view.setAdapter(adapter);
}

@Override
public void onAttach(Context context) {
super.onAttach(context);
listener = (USBInteractionListener) context;
}

@Override
public void onDetach() {
super.onDetach();
listener = null;
}


private void onItemClick(int pos){
if(devices.size()>pos){
listener.onUSBDeviceClick(devices.get(pos));
}
}

public interface USBInteractionListener {
void onUSBDeviceClick(USBDevice device);
}
}

+ 80
- 0
app/src/main/java/fr/mobdev/lpcprog/fragment/Watcher.java View File

@@ -0,0 +1,80 @@
/*
* Copyright (C) 2016 Anthony Chomienne, anthony@mob-dev.fr
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package fr.mobdev.lpcprog.fragment;

import android.graphics.PorterDuff;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;

class HexaWatcher implements TextWatcher {

private EditText v;
private AddPartFragment fragment;
HexaWatcher(EditText view,AddPartFragment fragment) {
v = view;
this.fragment = fragment;
}

@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

}

@Override
public void afterTextChanged(Editable editable) {
String hexa = editable.toString();
if(!hexa.matches("0x[0-9A-F]+"))
v.getBackground().setColorFilter(0xFFFF0000, PorterDuff.Mode.SRC);
else
v.getBackground().clearColorFilter();
fragment.modifyBt(null);
}
}

class EmptyWatcher implements TextWatcher {

private EditText v;
private AddPartFragment fragment;
EmptyWatcher(EditText view,AddPartFragment fragment) {
v = view;
this.fragment = fragment;
}

@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

}

@Override
public void afterTextChanged(Editable editable) {
String data = editable.toString();
fragment.modifyBt(null);
}
}

+ 6
- 2
app/src/main/java/fr/mobdev/lpcprog/listener/FlashListener.java View File

@@ -18,9 +18,13 @@

package fr.mobdev.lpcprog.listener;

import android.widget.ImageView;

import java.util.EventListener;

public interface FlashListener extends EventListener{

void onError(String string);
void onStartFlash();
void onSuccess();
void onProgress(int step, int endStep, int progress, int step_res_id);
void onError(String string, ImageView imageView);
}

+ 0
- 1
app/src/main/java/fr/mobdev/lpcprog/listener/NetworkListener.java View File

@@ -20,7 +20,6 @@ package fr.mobdev.lpcprog.listener;

import java.util.EventListener;

import fr.mobdev.lpcprog.objects.Binary;
import fr.mobdev.lpcprog.objects.Server;

public interface NetworkListener extends EventListener{

+ 134
- 19
app/src/main/java/fr/mobdev/lpcprog/managers/DatabaseManager.java View File

@@ -29,7 +29,7 @@ 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.Part;
import fr.mobdev.lpcprog.objects.Server;

public class DatabaseManager extends SQLiteOpenHelper {
@@ -62,6 +62,49 @@ public class DatabaseManager extends SQLiteOpenHelper {
db.insert("servers",null,values);

values.clear();
values.put("part_id",0x00008100);
values.put("part_name","LPC810M021FN8");
values.put("fl_base_addr",0x0);
values.put("fl_size",0x1000);
values.put("fl_nb_sect",4);
values.put("reset_vector_offset",0x04);
values.put("ram_base_addr",0x10000000);
values.put("ram_size",0x0400);
values.put("ram_buf_off",0x300);
values.put("ram_buf_size",0x100);
values.put("UU_encode",false);
db.insert("definitions",null,values);


values.clear();
values.put("part_id",0x00008122);
values.put("part_name","LPC812M101JHD20");
values.put("fl_base_addr",0x0);
values.put("fl_size",0x4000);
values.put("fl_nb_sect",16);
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",false);
db.insert("definitions",null,values);

values.clear();
values.put("part_id",0x2540102B);
values.put("part_name","LPC1114FHN33/302");
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",0x2000);
values.put("ram_buf_off",0x800);
values.put("ram_buf_size",0x400);
values.put("UU_encode",true);
db.insert("definitions",null,values);

values.clear();
values.put("part_id",0x3640C02B);