Use one tab for indenting Java files (not a mix of tabs and spaces).
import org.apache.tools.ant.types.resources.FileProvider;
import org.apache.tools.ant.types.selectors.SelectorUtils;
-public class CopyLibsTask extends Task {
-
-
- private static BuildException buildException(Exception e)
- {
- if (e instanceof BuildException)
- return (BuildException)e;
- else
- return new BuildException(e);
- }
-
- private static int indexOf(byte[] data, byte v, int start)
- {
- if (data != null)
- for (int i=start; i<data.length; i++)
- if (data[i] == v)
- return i;
- return -1;
- }
-
- private static String fixSoname(String s)
- {
- int l = s.length();
- int i = s.lastIndexOf(".so");
- if (i >= 0 && i < l-3)
- return s.substring(0, i+3);
- else
- return s;
- }
-
- protected class Library implements Comparable<Library> {
-
- protected final File file;
- protected final ElfFile elf;
- protected final HashSet<String> needed;
- protected final Vector<String> rpath;
- protected final TreeSet<Range> fixups;
- protected final String subdir;
- protected String soname, destname;
- protected final HashSet<Library> dependencies;
- protected boolean dependedUpon;
-
- protected class Range implements Comparable<Range> {
-
- public final long start, end;
-
- public int compareTo(Range r)
- {
- if (start < r.start)
- return -1;
- else if (start > r.start)
- return 1;
- else if (end < r.end)
- return -1;
- else if (end > r.end)
- return 1;
+public class CopyLibsTask extends Task
+{
+ private static BuildException buildException(Exception e)
+ {
+ if (e instanceof BuildException)
+ return (BuildException)e;
else
- return 0;
- }
-
- public Range(long start, long end)
- {
- this.start = start;
- this.end = end;
- }
+ return new BuildException(e);
}
- public int compareTo(Library l)
+ private static int indexOf(byte[] data, byte v, int start)
{
- return destname.compareTo(l.destname);
+ if (data != null) {
+ for (int i = start; i < data.length; i++) {
+ if (data[i] == v)
+ return i;
+ }
+ }
+ return -1;
}
- protected void addNeeded(String so)
+ private static String fixSoname(String s)
{
- needed.add(so);
- }
+ int l = s.length();
+ int i = s.lastIndexOf(".so");
- protected void addRpath(String rp)
- {
- for (String p : rp.split(":"))
- if (!rpath.contains(p))
- rpath.add(p);
+ if (i >= 0 && i < (l - 3))
+ return s.substring(0, i + 3);
+ else
+ return s;
}
- private String getDynstr(ElfFile.Dynamic d, byte[] s,
- long base) throws Exception
+ protected class Library implements Comparable<Library>
{
- int offs = (int)d.d_val;
- int nul = indexOf(s, (byte)0, offs);
- if (nul < 0)
- throw new Exception("Invalid dynamic string");
- String name = new String(s, offs, nul-offs, "US-ASCII");
- offs += base;
- if (d.d_tag == ElfFile.DT_RPATH) {
- // Zap rpath
- fixups.add(new Range(offs, offs+name.length()));
- } else {
- String fix = fixSoname(name);
- if (fix.length() < name.length()) {
- fixups.add(new Range(offs+fix.length(),
- offs+name.length()));
+ protected final File file;
+ protected final ElfFile elf;
+ protected final HashSet<String> needed;
+ protected final Vector<String> rpath;
+ protected final TreeSet<Range> fixups;
+ protected final String subdir;
+ protected String soname, destname;
+ protected final HashSet<Library> dependencies;
+ protected boolean dependedUpon;
+
+ protected class Range implements Comparable<Range>
+ {
+ public final long start, end;
+
+ public int compareTo(Range r)
+ {
+ if (start < r.start)
+ return -1;
+ else if (start > r.start)
+ return 1;
+ else if (end < r.end)
+ return -1;
+ else if (end > r.end)
+ return 1;
+ else
+ return 0;
+ }
+
+ public Range(long start, long end)
+ {
+ this.start = start;
+ this.end = end;
+ }
}
- }
- return name;
- }
- private void checkDynamic(ElfFile.SectionHeader dynsh,
- ElfFile.SectionHeader strsh) throws Exception
- {
- byte strs[] = new byte[(int)strsh.sh_size];
- elf.read(strsh, strs);
- for (ElfFile.Dynamic d : elf.readDynamic(dynsh))
- if (d.d_tag == ElfFile.DT_NULL)
- break;
- else if (d.d_tag == ElfFile.DT_SONAME)
- soname = getDynstr(d, strs, strsh.sh_offset);
- else if (d.d_tag == ElfFile.DT_NEEDED)
- addNeeded(getDynstr(d, strs, strsh.sh_offset));
- else if (d.d_tag == ElfFile.DT_RPATH)
- addRpath(getDynstr(d, strs, strsh.sh_offset));
- }
+ public int compareTo(Library l)
+ {
+ return destname.compareTo(l.destname);
+ }
- private void checkElf() throws Exception
- {
- for (ElfFile.SectionHeader sh : elf.secHeaders)
- if (sh.sh_type == ElfFile.SHT_DYNAMIC)
- checkDynamic(sh, elf.secHeaders[sh.sh_link]);
- }
+ protected void addNeeded(String so)
+ {
+ needed.add(so);
+ }
- protected File getDestName(File dest)
- {
- File d = new File(dest, subdir);
- File f = new File(d, destname);
- return f;
- }
+ protected void addRpath(String rp)
+ {
+ for (String p : rp.split(":")) {
+ if (!rpath.contains(p))
+ rpath.add(p);
+ }
+ }
- protected void writeTo(File dest) throws IOException
- {
- FileInputStream is = new FileInputStream(file);
- FileOutputStream os = new FileOutputStream(dest);
- byte[] buf = new byte[65536];
- TreeSet<Range> ranges = new TreeSet<Range>(fixups);
- long offs = 0;
- outer: for(;;) {
- long next = offs + buf.length;
- if (!ranges.isEmpty()) {
- next = ranges.first().start;
+ private String getDynstr(ElfFile.Dynamic d, byte[] s,
+ long base) throws Exception
+ {
+ int offs = (int)d.d_val;
+ int nul = indexOf(s, (byte)0, offs);
+
+ if (nul < 0)
+ throw new Exception("Invalid dynamic string");
+
+ String name = new String(s, offs, nul-offs, "US-ASCII");
+ offs += base;
+
+ if (d.d_tag == ElfFile.DT_RPATH) {
+ // Zap rpath,
+ fixups.add(new Range(offs, offs + name.length()));
+ } else {
+ String fix = fixSoname(name);
+ if (fix.length() < name.length()) {
+ fixups.add(new Range(offs + fix.length(),
+ offs + name.length()));
+ }
+ }
+ return name;
}
- if (next > offs) {
- long chunk = next-offs;
- if (chunk > buf.length)
- chunk = buf.length;
- int r = is.read(buf, 0, (int)chunk);
- if (r < 0)
- break;
- os.write(buf, 0, r);
- offs += r;
- continue;
+
+ private void checkDynamic(ElfFile.SectionHeader dynsh,
+ ElfFile.SectionHeader strsh) throws Exception
+ {
+ byte strs[] = new byte[(int)strsh.sh_size];
+
+ elf.read(strsh, strs);
+
+ for (ElfFile.Dynamic d : elf.readDynamic(dynsh)) {
+ if (d.d_tag == ElfFile.DT_NULL)
+ break;
+ else if (d.d_tag == ElfFile.DT_SONAME)
+ soname = getDynstr(d, strs, strsh.sh_offset);
+ else if (d.d_tag == ElfFile.DT_NEEDED)
+ addNeeded(getDynstr(d, strs, strsh.sh_offset));
+ else if (d.d_tag == ElfFile.DT_RPATH)
+ addRpath(getDynstr(d, strs, strsh.sh_offset));
+ }
}
- while (!ranges.isEmpty() &&
- ranges.first().start <= offs) {
- Range rg = ranges.pollFirst();
- if (rg.end > offs) {
- long chunk = rg.end-offs;
- while (chunk > 0) {
- int slice = (chunk > buf.length?
- buf.length : (int)chunk);
- int r = is.read(buf, 0, slice);
- if (r < 0)
- break outer;
- if (r > 0) {
- Arrays.fill(buf, 0, r, (byte)0);
- os.write(buf, 0, r);
- chunk -= r;
- }
+
+ private void checkElf() throws Exception
+ {
+ for (ElfFile.SectionHeader sh : elf.secHeaders) {
+ if (sh.sh_type == ElfFile.SHT_DYNAMIC)
+ checkDynamic(sh, elf.secHeaders[sh.sh_link]);
}
- offs = rg.end;
- }
}
- }
- os.close();
- is.close();
- }
- protected Library(File f, String s) throws Exception
- {
- file = f;
- subdir = s;
- elf = new ElfFile(file);
- needed = new HashSet<String>();
- rpath = new Vector<String>();
- fixups = new TreeSet<Range>();
- soname = f.getName();
- dependencies = new HashSet<Library>();
- dependedUpon = false;
- checkElf();
- destname = fixSoname(soname);
- }
+ protected File getDestName(File dest)
+ {
+ File d = new File(dest, subdir);
+ File f = new File(d, destname);
+ return f;
+ }
- protected Library(Resource r) throws Exception
- {
- this(r.as(FileProvider.class).getFile(),
- new File(r.getName()).getParent());
- }
+ protected void writeTo(File dest) throws IOException
+ {
+ FileInputStream is = new FileInputStream(file);
+ FileOutputStream os = new FileOutputStream(dest);
+ byte[] buf = new byte[65536];
+ TreeSet<Range> ranges = new TreeSet<Range>(fixups);
+ long offs = 0;
+
+ outer: for(;;) {
+ long next = offs + buf.length;
+ if (!ranges.isEmpty())
+ next = ranges.first().start;
+ if (next > offs) {
+ long chunk = next - offs;
+ if (chunk > buf.length)
+ chunk = buf.length;
+ int r = is.read(buf, 0, (int)chunk);
+ if (r < 0)
+ break;
+ os.write(buf, 0, r);
+ offs += r;
+ continue;
+ }
+ while (!ranges.isEmpty() && ranges.first().start <= offs) {
+ Range rg = ranges.pollFirst();
+ if (rg.end > offs) {
+ long chunk = rg.end - offs;
+ while (chunk > 0) {
+ int slice = (chunk > buf.length ? buf.length : (int)chunk);
+ int r = is.read(buf, 0, slice);
+ if (r < 0)
+ break outer;
+ if (r > 0) {
+ Arrays.fill(buf, 0, r, (byte)0);
+ os.write(buf, 0, r);
+ chunk -= r;
+ }
+ }
+ offs = rg.end;
+ }
+ }
+ }
- public String toString() { return "Library("+file+")"; }
- };
+ os.close();
+ is.close();
+ }
- protected class Worker
- {
- protected final int machine;
- protected final Queue<Library> workQueue;
- protected final HashMap<String,Library> knownLibs;
- protected final HashSet<Library> processedLibs;
- protected final HashSet<String> allDests;
- protected final Vector<String> rpath;
+ protected Library(File f, String s) throws Exception
+ {
+ file = f;
+ subdir = s;
+ elf = new ElfFile(file);
+ needed = new HashSet<String>();
+ rpath = new Vector<String>();
+ fixups = new TreeSet<Range>();
+ soname = f.getName();
+ dependencies = new HashSet<Library>();
+ dependedUpon = false;
+ checkElf();
+ destname = fixSoname(soname);
+ }
- protected void addWork(Library l)
- {
- if (l == null)
- return;
- Library kl = knownLibs.get(l.soname);
- if (kl == l)
- return; // Already processed
- if (kl != null)
- throw new BuildException("Multiple libs with the same soname "+
- l.soname);
- knownLibs.put(l.soname, l);
- if (allDests.contains(l.destname))
- throw new BuildException("Multiple libs with simplified soname "+
- l.destname);
- allDests.add(l.destname);
- workQueue.add(l);
- }
+ protected Library(Resource r) throws Exception
+ {
+ this(r.as(FileProvider.class).getFile(),
+ new File(r.getName()).getParent());
+ }
- protected void addRpath(Vector<String> rp)
- {
- for (String p : rp)
- if (!rpath.contains(p))
- rpath.add(p);
- }
+ public String toString()
+ {
+ return "Library(" + file + ")";
+ }
- protected void setDependency(Library l1, Library l2)
- {
- if (l2 == null) // Dependancy on external lib
- return;
- l1.dependencies.add(l2);
- l2.dependedUpon = true;
- }
+ };
- protected Library findLibInRpath(String s, String subdir)
- throws Exception
+ protected class Worker
{
- for (String p : rpath) {
- File f = new File(p, s);
- if (f.exists()) {
- Library l = new Library(f, subdir);
- if (l.elf.header.e_machine == machine)
+ protected final int machine;
+ protected final Queue<Library> workQueue;
+ protected final HashMap<String,Library> knownLibs;
+ protected final HashSet<Library> processedLibs;
+ protected final HashSet<String> allDests;
+ protected final Vector<String> rpath;
+
+ protected void addWork(Library l)
+ {
+ if (l == null)
+ return;
+ Library kl = knownLibs.get(l.soname);
+ if (kl == l)
+ return; // Already processed.
+ if (kl != null)
+ throw new BuildException("Multiple libs with the same soname " + l.soname);
+ knownLibs.put(l.soname, l);
+ if (allDests.contains(l.destname))
+ throw new BuildException("Multiple libs with simplified soname " + l.destname);
+ allDests.add(l.destname);
+ workQueue.add(l);
+ }
+
+ protected void addRpath(Vector<String> rp)
+ {
+ for (String p : rp) {
+ if (!rpath.contains(p))
+ rpath.add(p);
+ }
+ }
+
+ protected void setDependency(Library l1, Library l2)
+ {
+ if (l2 == null) // Dependancy on external lib.
+ return;
+ l1.dependencies.add(l2);
+ l2.dependedUpon = true;
+ }
+
+ protected Library findLibInRpath(String s, String subdir)
+ throws Exception
+ {
+ for (String p : rpath) {
+ File f = new File(p, s);
+ if (f.exists()) {
+ Library l = new Library(f, subdir);
+ if (l.elf.header.e_machine == machine)
+ return l;
+ }
+ }
+ return null;
+ }
+
+ protected Library getLibForSoname(String s, String subdir)
+ throws Exception
+ {
+ Library l = knownLibs.get(s);
+ if (l != null)
+ return l;
+ boolean include = false;
+ for (String patt : patterns.getIncludePatterns(getProject())) {
+ if (SelectorUtils.match(patt, s)) {
+ include = true;
+ break;
+ }
+ }
+ if (!include) {
+ for (String patt : patterns.getExcludePatterns(getProject())) {
+ if (SelectorUtils.match(patt, s))
+ return null;
+ }
+ }
+ l = findLibInRpath(s, subdir);
+ if (l == null)
+ throw new Exception("Library " + s + " not found");
+ addWork(l);
return l;
}
- }
- return null;
+
+ protected void process(Library l) throws Exception
+ {
+ if (processedLibs.contains(l))
+ return; // Already processed
+ processedLibs.add(l);
+ addRpath(l.rpath);
+ for (String need : l.needed)
+ setDependency(l, getLibForSoname(need, l.subdir));
+ }
+
+ protected Vector<Library> topoSort(HashSet<Library> libs)
+ {
+ Vector<Library> order = new Vector<Library>();
+ for (Library chk : new HashSet<Library>(libs)) {
+ if (!chk.dependedUpon)
+ libs.remove(chk);
+ }
+ while (!libs.isEmpty()) {
+ HashSet<Library> leafs = new HashSet<Library>();
+ for (Library chk : new HashSet<Library>(libs)) {
+ if (chk.dependencies.isEmpty())
+ leafs.add(chk);
+ }
+ if (leafs.isEmpty())
+ throw new BuildException("Circular dependency found");
+ ArrayList<Library> llist = new ArrayList<Library>(leafs);
+ Collections.sort(llist);
+ order.addAll(llist);
+ libs.removeAll(leafs);
+ for (Library l : libs)
+ l.dependencies.removeAll(leafs);
+ }
+ return order;
+ }
+
+ protected void execute() throws BuildException
+ {
+ try {
+ while (!workQueue.isEmpty())
+ process(workQueue.remove());
+ } catch (Exception e) {
+ throw buildException(e);
+ }
+ if (property != null) {
+ Vector<Library> order =
+ topoSort(new HashSet<Library>(processedLibs));;
+ StringBuilder sb = new StringBuilder();
+ for (Library l : order) {
+ String name = l.destname;
+ if (name.startsWith("lib"))
+ name = name.substring(3);
+ if (name.endsWith(".so"))
+ name = name.substring(0, name.length() - 3);
+ sb.append(" <item>");
+ sb.append(name);
+ sb.append("</item>\n");
+ }
+ String orderedLibs = sb.toString();
+ getProject().setNewProperty(property, orderedLibs);
+ }
+ for (Library chk : new HashSet<Library>(processedLibs)) {
+ File dest = chk.getDestName(destDir);
+ if (dest.exists() &&
+ dest.lastModified() >= chk.file.lastModified())
+ processedLibs.remove(chk);
+ dest = dest.getParentFile();
+ if (!dest.exists())
+ dest.mkdirs();
+ }
+ if (processedLibs.isEmpty())
+ return;
+ log("Copying " + processedLibs.size() + " libraries into " + destDir);
+ ArrayList<Library> libs = new ArrayList<Library>(processedLibs);
+ Collections.sort(libs);
+ try {
+ for (Library l : libs)
+ l.writeTo(l.getDestName(destDir));
+ } catch (Exception e) {
+ throw buildException(e);
+ }
+ }
+
+ protected Worker(int mach)
+ {
+ machine = mach;
+ workQueue = new LinkedList<Library>();
+ knownLibs = new HashMap<String,Library>();
+ processedLibs = new HashSet<Library>();
+ allDests = new HashSet<String>();
+ rpath = new Vector<String>();
+ }
+
+ };
+
+ protected File destDir = null; // The destination directory.
+ protected Vector<ResourceCollection> rcs = new Vector<ResourceCollection>();
+ protected PatternSet patterns = new PatternSet();
+ protected String property = null;
+
+ public void setTodir(File destDir)
+ {
+ this.destDir = destDir;
}
- protected Library getLibForSoname(String s, String subdir)
- throws Exception
+ public void addFileset(FileSet set)
{
- Library l = knownLibs.get(s);
- if (l != null)
- return l;
- boolean include = false;
- for (String patt : patterns.getIncludePatterns(getProject()))
- if (SelectorUtils.match(patt, s)) {
- include = true;
- break;
- }
- if (!include) {
- for (String patt : patterns.getExcludePatterns(getProject()))
- if (SelectorUtils.match(patt, s))
- return null;
- }
- l = findLibInRpath(s, subdir);
- if (l == null)
- throw new Exception("Library "+s+" not found");
- addWork(l);
- return l;
+ add(set);
}
- protected void process(Library l) throws Exception
+ public void add(ResourceCollection res)
{
- if (processedLibs.contains(l))
- return; // Already processed
- processedLibs.add(l);
- addRpath(l.rpath);
- for (String need : l.needed)
- setDependency(l, getLibForSoname(need, l.subdir));
+ rcs.add(res);
}
- protected Vector<Library> topoSort(HashSet<Library> libs)
+ public PatternSet.NameEntry createExclude()
{
- Vector<Library> order = new Vector<Library>();
- for (Library chk : new HashSet<Library>(libs)) {
- if (!chk.dependedUpon)
- libs.remove(chk);
- }
- while (!libs.isEmpty()) {
- HashSet<Library> leafs = new HashSet<Library>();
- for (Library chk : new HashSet<Library>(libs)) {
- if (chk.dependencies.isEmpty())
- leafs.add(chk);
- }
- if (leafs.isEmpty())
- throw new BuildException("Circular dependency found");
- ArrayList<Library> llist = new ArrayList<Library>(leafs);
- Collections.sort(llist);
- order.addAll(llist);
- libs.removeAll(leafs);
- for (Library l : libs)
- l.dependencies.removeAll(leafs);
- }
- return order;
+ return patterns.createExclude();
}
- protected void execute() throws BuildException
+ public PatternSet.NameEntry createInclude()
{
- try {
- while (!workQueue.isEmpty())
- process(workQueue.remove());
- } catch (Exception e) {
- throw buildException(e);
- }
- if (property != null) {
- Vector<Library> order =
- topoSort(new HashSet<Library>(processedLibs));;
- StringBuilder sb = new StringBuilder();
- for (Library l : order) {
- String name = l.destname;
- if (name.startsWith("lib"))
- name = name.substring(3);
- if (name.endsWith(".so"))
- name = name.substring(0, name.length()-3);
- sb.append(" <item>");
- sb.append(name);
- sb.append("</item>\n");
- }
- String orderedLibs = sb.toString();
- getProject().setNewProperty(property, orderedLibs);
- }
- for (Library chk : new HashSet<Library>(processedLibs)) {
- File dest = chk.getDestName(destDir);
- if (dest.exists() &&
- dest.lastModified() >= chk.file.lastModified())
- processedLibs.remove(chk);
- dest = dest.getParentFile();
- if (!dest.exists())
- dest.mkdirs();
- }
- if (processedLibs.isEmpty())
- return;
- log("Copying "+processedLibs.size()+" libraries into "+destDir);
- ArrayList<Library> libs = new ArrayList<Library>(processedLibs);
- Collections.sort(libs);
- try {
- for (Library l : libs)
- l.writeTo(l.getDestName(destDir));
- } catch (Exception e) {
- throw buildException(e);
- }
+ return patterns.createInclude();
}
- protected Worker(int mach)
+ public void setProperty(String prop)
{
- machine = mach;
- workQueue = new LinkedList<Library>();
- knownLibs = new HashMap<String,Library>();
- processedLibs = new HashSet<Library>();
- allDests = new HashSet<String>();
- rpath = new Vector<String>();
+ property = prop;
}
- };
-
- protected File destDir = null; // the destination directory
- protected Vector<ResourceCollection> rcs = new Vector<ResourceCollection>();
- protected PatternSet patterns = new PatternSet();
- protected String property = null;
-
- public void setTodir(File destDir) {
- this.destDir = destDir;
- }
-
- public void addFileset(FileSet set) {
- add(set);
- }
-
- public void add(ResourceCollection res) {
- rcs.add(res);
- }
-
- public PatternSet.NameEntry createExclude()
- {
- return patterns.createExclude();
- }
-
- public PatternSet.NameEntry createInclude()
- {
- return patterns.createInclude();
- }
-
- public void setProperty(String prop)
- {
- property = prop;
- }
-
- public void execute() throws BuildException {
- HashMap<Integer,Worker> workers = new HashMap<Integer,Worker>();
- final int size = rcs.size();
- for (int i = 0; i < size; i++) {
- ResourceCollection rc = rcs.elementAt(i);
- for (Resource r : rc) {
- if (!r.isExists()) {
- String message = "Could not find library "
- + r.toLongString() + " to copy.";
- throw new BuildException(message);
- }
- Library l;
- try {
- l = new Library(r);
- } catch (Exception e) {
- throw buildException(e);
+
+ public void execute() throws BuildException
+ {
+ HashMap<Integer,Worker> workers = new HashMap<Integer,Worker>();
+ final int size = rcs.size();
+
+ for (int i = 0; i < size; i++) {
+ ResourceCollection rc = rcs.elementAt(i);
+ for (Resource r : rc) {
+ if (!r.isExists()) {
+ String message = "Could not find library "
+ + r.toLongString() + " to copy.";
+ throw new BuildException(message);
+ }
+ Library l;
+ try {
+ l = new Library(r);
+ } catch (Exception e) {
+ throw buildException(e);
+ }
+ Integer m = new Integer(l.elf.header.e_machine);
+ Worker w = workers.get(m);
+ if (w == null)
+ workers.put(m, (w = new Worker(m.intValue())));
+ w.addWork(l);
+ }
}
- Integer m = new Integer(l.elf.header.e_machine);
- Worker w = workers.get(m);
- if (w == null)
- workers.put(m, (w = new Worker(m.intValue())));
- w.addWork(l);
- }
+ ArrayList<Integer> machines = new ArrayList<Integer>(workers.keySet());
+ Collections.sort(machines);
+ for (Integer m : machines)
+ workers.get(m).execute();
}
- ArrayList<Integer> machines = new ArrayList<Integer>(workers.keySet());
- Collections.sort(machines);
- for (Integer m : machines)
- workers.get(m).execute();
- }
}
class ElfFile
{
- public static final int SHT_NULL = 0;
- public static final int SHT_PROGBITS = 1;
- public static final int SHT_SYMTAB = 2;
- public static final int SHT_STRTAB = 3;
- public static final int SHT_RELA = 4;
- public static final int SHT_HASH = 5;
- public static final int SHT_DYNAMIC = 6;
- public static final int SHT_NOTE = 7;
- public static final int SHT_NOBITS = 8;
- public static final int SHT_REL = 9;
- public static final int SHT_SHLIB = 10;
- public static final int SHT_DYNSYM = 11;
- public static final int SHT_INIT_ARRAY = 14;
- public static final int SHT_FINI_ARRAY = 15;
- public static final int SHT_PREINIT_ARRAY = 16;
- public static final int SHT_GROUP = 17;
- public static final int SHT_SYMTAB_SHNDX = 18;
-
- public static final int DT_NULL = 0;
- public static final int DT_NEEDED = 1;
- public static final int DT_PLTRELSZ = 2;
- public static final int DT_PLTGOT = 3;
- public static final int DT_HASH = 4;
- public static final int DT_STRTAB = 5;
- public static final int DT_SYMTAB = 6;
- public static final int DT_RELA = 7;
- public static final int DT_RELASZ = 8;
- public static final int DT_RELAENT = 9;
- public static final int DT_STRSZ = 10;
- public static final int DT_SYMENT = 11;
- public static final int DT_INIT = 12;
- public static final int DT_FINI = 13;
- public static final int DT_SONAME = 14;
- public static final int DT_RPATH = 15;
- public static final int DT_SYMBOLIC = 16;
- public static final int DT_REL = 17;
- public static final int DT_RELSZ = 18;
- public static final int DT_RELENT = 19;
- public static final int DT_PLTREL = 20;
- public static final int DT_DEBUG = 21;
- public static final int DT_TEXTREL = 22;
- public static final int DT_JMPREL = 23;
- public static final int DT_BIND_NOW = 24;
- public static final int DT_INIT_ARRAY = 25;
- public static final int DT_FINI_ARRAY = 26;
- public static final int DT_INIT_ARRAYSZ = 27;
- public static final int DT_FINI_ARRAYSZ = 28;
- public static final int DT_RUNPATH = 29;
- public static final int DT_FLAGS = 30;
- public static final int DT_ENCODING = 32;
- public static final int DT_PREINIT_ARRAY = 32;
- public static final int DT_PREINIT_ARRAYSZ = 33;
-
- protected final RandomAccessFile file;
- protected final boolean bit64, little;
- public final Header header;
- public final SectionHeader[] secHeaders;
-
- protected short swap(short s)
- {
- return (little? (short)(((s&0xff)<<8)|((s>>8)&0xff)) : s);
- }
-
- protected int swap(int i)
- {
- return (little? (((i&0xff)<<24)|((i&0xff00)<<8)|
- ((i>>8)&0xff00)|((i>>24)&0xff)) : i);
- }
-
- protected long swap(long l)
- {
- return (little? ((((long)swap((int)(l&0xffffffffL)))<<32) |
- (((long)swap((int)((l>>32)&0xffffffffL)))&0xffffffffL))
- : l);
- }
-
- protected short getHalf() throws IOException
- {
- return swap(file.readShort());
- }
-
- protected int getWord() throws IOException
- {
- return swap(file.readInt());
- }
-
- protected long getXword() throws IOException
- {
- return swap(file.readLong());
- }
-
- protected long getAddr() throws IOException
- {
- return (bit64? getXword() : getWord());
- }
-
- protected long getOff() throws IOException
- {
- return (bit64? getXword() : getWord());
- }
-
- public class Header
- {
- public final byte[] e_ident;
- public final short e_type, e_machine;
- public final int e_version;
- public final long e_entry, e_phoff, e_shoff;
- public final int e_flags;
- public final short e_ehsize, e_phentsize, e_phnum;
- public final short e_shentsize, e_shnum, e_shstrndx;
-
- private Header(byte[] ident) throws IOException
+ public static final int SHT_NULL = 0;
+ public static final int SHT_PROGBITS = 1;
+ public static final int SHT_SYMTAB = 2;
+ public static final int SHT_STRTAB = 3;
+ public static final int SHT_RELA = 4;
+ public static final int SHT_HASH = 5;
+ public static final int SHT_DYNAMIC = 6;
+ public static final int SHT_NOTE = 7;
+ public static final int SHT_NOBITS = 8;
+ public static final int SHT_REL = 9;
+ public static final int SHT_SHLIB = 10;
+ public static final int SHT_DYNSYM = 11;
+ public static final int SHT_INIT_ARRAY = 14;
+ public static final int SHT_FINI_ARRAY = 15;
+ public static final int SHT_PREINIT_ARRAY = 16;
+ public static final int SHT_GROUP = 17;
+ public static final int SHT_SYMTAB_SHNDX = 18;
+
+ public static final int DT_NULL = 0;
+ public static final int DT_NEEDED = 1;
+ public static final int DT_PLTRELSZ = 2;
+ public static final int DT_PLTGOT = 3;
+ public static final int DT_HASH = 4;
+ public static final int DT_STRTAB = 5;
+ public static final int DT_SYMTAB = 6;
+ public static final int DT_RELA = 7;
+ public static final int DT_RELASZ = 8;
+ public static final int DT_RELAENT = 9;
+ public static final int DT_STRSZ = 10;
+ public static final int DT_SYMENT = 11;
+ public static final int DT_INIT = 12;
+ public static final int DT_FINI = 13;
+ public static final int DT_SONAME = 14;
+ public static final int DT_RPATH = 15;
+ public static final int DT_SYMBOLIC = 16;
+ public static final int DT_REL = 17;
+ public static final int DT_RELSZ = 18;
+ public static final int DT_RELENT = 19;
+ public static final int DT_PLTREL = 20;
+ public static final int DT_DEBUG = 21;
+ public static final int DT_TEXTREL = 22;
+ public static final int DT_JMPREL = 23;
+ public static final int DT_BIND_NOW = 24;
+ public static final int DT_INIT_ARRAY = 25;
+ public static final int DT_FINI_ARRAY = 26;
+ public static final int DT_INIT_ARRAYSZ = 27;
+ public static final int DT_FINI_ARRAYSZ = 28;
+ public static final int DT_RUNPATH = 29;
+ public static final int DT_FLAGS = 30;
+ public static final int DT_ENCODING = 32;
+ public static final int DT_PREINIT_ARRAY = 32;
+ public static final int DT_PREINIT_ARRAYSZ = 33;
+
+ protected final RandomAccessFile file;
+ protected final boolean bit64, little;
+ public final Header header;
+ public final SectionHeader[] secHeaders;
+
+ protected short swap(short s)
{
- e_ident = ident;
- e_type = getHalf();
- e_machine = getHalf();
- e_version = getWord();
- e_entry = getAddr();
- e_phoff = getOff();
- e_shoff = getOff();
- e_flags = getWord();
- e_ehsize = getHalf();
- e_phentsize = getHalf();
- e_phnum = getHalf();
- e_shentsize = getHalf();
- e_shnum = getHalf();
- e_shstrndx = getHalf();
+ return (little ? (short)(((s & 0xff) << 8) | ((s >> 8) & 0xff)) : s);
}
- }
- public class SectionHeader
- {
- public final int sh_name, sh_type;
- public final long sh_flags, sh_addr, sh_offset, sh_size;
- public final int sh_link, sh_info;
- public final long sh_addralign, sh_entsize;
+ protected int swap(int i)
+ {
+ return (little ? (((i & 0xff) << 24) | ((i & 0xff00) << 8) |
+ ((i >> 8) & 0xff00) | ((i >> 24) & 0xff)) : i);
+ }
+
+ protected long swap(long l)
+ {
+ return (little? ((((long)swap((int)(l & 0xffffffffL))) << 32) |
+ (((long)swap((int)((l >> 32) & 0xffffffffL))) & 0xffffffffL)) : l);
+ }
+
+ protected short getHalf() throws IOException
+ {
+ return swap(file.readShort());
+ }
- private SectionHeader() throws IOException
+ protected int getWord() throws IOException
{
- sh_name = getWord();
- sh_type = getWord();
- sh_flags = (bit64? getXword() : getWord());
- sh_addr = getAddr();
- sh_offset = getOff();
- sh_size = (bit64? getXword() : getWord());
- sh_link = getWord();
- sh_info = getWord();
- if (bit64) {
- sh_addralign = getXword();
- sh_entsize = getXword();
- } else {
- sh_addralign = getWord();
- sh_entsize = getWord();
- }
+ return swap(file.readInt());
}
- }
- public class Dynamic
- {
- public final long d_tag, d_val;
+ protected long getXword() throws IOException
+ {
+ return swap(file.readLong());
+ }
+
+ protected long getAddr() throws IOException
+ {
+ return (bit64? getXword() : getWord());
+ }
+
+ protected long getOff() throws IOException
+ {
+ return (bit64 ? getXword() : getWord());
+ }
+
+ public class Header
+ {
+ public final byte[] e_ident;
+ public final short e_type, e_machine;
+ public final int e_version;
+ public final long e_entry, e_phoff, e_shoff;
+ public final int e_flags;
+ public final short e_ehsize, e_phentsize, e_phnum;
+ public final short e_shentsize, e_shnum, e_shstrndx;
+
+ private Header(byte[] ident) throws IOException
+ {
+ e_ident = ident;
+ e_type = getHalf();
+ e_machine = getHalf();
+ e_version = getWord();
+ e_entry = getAddr();
+ e_phoff = getOff();
+ e_shoff = getOff();
+ e_flags = getWord();
+ e_ehsize = getHalf();
+ e_phentsize = getHalf();
+ e_phnum = getHalf();
+ e_shentsize = getHalf();
+ e_shnum = getHalf();
+ e_shstrndx = getHalf();
+ }
+ }
+
+ public class SectionHeader
+ {
+ public final int sh_name, sh_type;
+ public final long sh_flags, sh_addr, sh_offset, sh_size;
+ public final int sh_link, sh_info;
+ public final long sh_addralign, sh_entsize;
+
+ private SectionHeader() throws IOException
+ {
+ sh_name = getWord();
+ sh_type = getWord();
+ sh_flags = (bit64 ? getXword() : getWord());
+ sh_addr = getAddr();
+ sh_offset = getOff();
+ sh_size = (bit64 ? getXword() : getWord());
+ sh_link = getWord();
+ sh_info = getWord();
+ if (bit64) {
+ sh_addralign = getXword();
+ sh_entsize = getXword();
+ } else {
+ sh_addralign = getWord();
+ sh_entsize = getWord();
+ }
+ }
+ }
+
+ public class Dynamic
+ {
+ public final long d_tag, d_val;
+
+ private Dynamic() throws IOException
+ {
+ if (bit64) {
+ d_tag = getXword();
+ d_val = getXword();
+ } else {
+ d_tag = getWord();
+ d_val = getWord();
+ }
+ }
+ }
+
+ public Dynamic[] readDynamic(SectionHeader sh) throws IOException
+ {
+ file.seek(sh.sh_offset);
+ Dynamic[] dyn = new Dynamic[(int)(sh.sh_size / sh.sh_entsize)];
+ for (int i = 0; i < dyn.length; i++)
+ dyn[i] = new Dynamic();
+ return dyn;
+ }
+
+ public void read(SectionHeader sh, byte[] buf) throws Exception
+ {
+ if (sh.sh_type == SHT_NOBITS || buf.length > sh.sh_size)
+ throw new Exception("Illegal read");
+ file.seek(sh.sh_offset);
+ file.readFully(buf);
+ }
- private Dynamic() throws IOException
+ public ElfFile(File f) throws Exception
{
- if (bit64) {
- d_tag = getXword();
- d_val = getXword();
- } else {
- d_tag = getWord();
- d_val = getWord();
- }
+ file = new RandomAccessFile(f, "r");
+ file.seek(0);
+ byte[] ident = new byte[16];
+ file.readFully(ident);
+ if (ident[0] != 0x7f || ident[1] != 'E' ||
+ ident[2] != 'L' || ident[3] != 'F')
+ throw new Exception("ELF signature not found");
+ if (ident[4] == 1)
+ bit64 = false;
+ else if (ident[4] == 2)
+ bit64 = true;
+ else
+ throw new Exception("Invalid ELF file class");
+ if (ident[5] == 1)
+ little = true;
+ else if (ident[5] == 2)
+ little = false;
+ else
+ throw new Exception("Invalid ELF data encoding");
+ header = new Header(ident);
+ file.seek(header.e_shoff);
+ secHeaders = new SectionHeader[header.e_shnum];
+ for (int i = 0; i < header.e_shnum; i++)
+ secHeaders[i] = new SectionHeader();
}
- }
-
- public Dynamic[] readDynamic(SectionHeader sh) throws IOException
- {
- file.seek(sh.sh_offset);
- Dynamic[] dyn = new Dynamic[(int)(sh.sh_size/sh.sh_entsize)];
- for (int i=0; i<dyn.length; i++)
- dyn[i] = new Dynamic();
- return dyn;
- }
-
- public void read(SectionHeader sh, byte[] buf) throws Exception
- {
- if (sh.sh_type == SHT_NOBITS || buf.length > sh.sh_size)
- throw new Exception("Illegal read");
- file.seek(sh.sh_offset);
- file.readFully(buf);
- }
-
- public ElfFile(File f) throws Exception
- {
- file = new RandomAccessFile(f, "r");
- file.seek(0);
- byte[] ident = new byte[16];
- file.readFully(ident);
- if (ident[0] != 0x7f || ident[1] != 'E' ||
- ident[2] != 'L' || ident[3] != 'F')
- throw new Exception("ELF signature not found");
- if (ident[4] == 1)
- bit64 = false;
- else if (ident[4] == 2)
- bit64 = true;
- else
- throw new Exception("Invalid ELF file class");
- if (ident[5] == 1)
- little = true;
- else if (ident[5] == 2)
- little = false;
- else
- throw new Exception("Invalid ELF data encoding");
- header = new Header(ident);
- file.seek(header.e_shoff);
- secHeaders = new SectionHeader[header.e_shnum];
- for (int i=0; i<header.e_shnum; i++)
- secHeaders[i] = new SectionHeader();
- }
}
SRAU_API void srau_init_environment(void)
{
- JNIEnv* env;
+ JNIEnv *env;
int attach_mode = srau_get_java_env(&env);
jobjectArray envs =
(jobjectArray)env->CallStaticObjectMethod(envc, getEnv);
jsize i, envn = env->GetArrayLength(envs);
- for (i=0; i<envn; i+=2) {
+ for (i = 0; i < envn; i += 2) {
jstring key = (jstring)env->GetObjectArrayElement(envs, i);
- jstring value = (jstring)env->GetObjectArrayElement(envs, i+1);
+ jstring value = (jstring)env->GetObjectArrayElement(envs, i + 1);
const char *utfkey = env->GetStringUTFChars(key, 0);
const char *utfvalue = env->GetStringUTFChars(value, 0);
setenv(utfkey, utfvalue, 1);
{
jint st;
- if (g_jvm == NULL) {
+ if (g_jvm == NULL)
return -1;
- }
st = g_jvm->GetEnv((void **)env, JNI_VERSION_1_6);
SRAU_PRIV void srau_unget_java_env(int mode)
{
- if (mode == 1) {
+ if (mode == 1)
g_jvm->DetachCurrentThread();
- }
}
SRAU_PRIV jclass srau_get_environment_class(JNIEnv *env)
{
- if (env && g_environment_class) {
+ if (env && g_environment_class)
return (jclass)env->NewLocalRef(g_environment_class);
- } else {
+ else
return 0;
- }
}
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
- JNIEnv* env;
+ JNIEnv *env;
(void)reserved;
- if (vm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK) {
- return -1;
- }
+ if (vm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK)
+ return -1;
- jclass envc = env->FindClass("org/sigrok/androidutils/Environment");
+ jclass envc = env->FindClass("org/sigrok/androidutils/Environment");
if (envc) {
g_environment_class = (jclass)env->NewGlobalRef(envc);
env->DeleteLocalRef(envc);
void JNI_OnUnload(JavaVM *vm, void *reserved)
{
- JNIEnv* env;
+ JNIEnv *env;
(void)reserved;
g_jvm = NULL;
- if (vm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK) {
- return;
- }
+ if (vm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK)
+ return;
if (g_environment_class) {
env->DeleteGlobalRef(g_environment_class);
* Use SRAU_API to mark public API symbols, and SRAU_PRIV for private symbols.
*
* Variables and functions marked 'static' are private already and don't
- * need SR_PRIV. However, functions which are not static (because they need
+ * need SRAU_PRIV. However, functions which are not static (because they need
* to be used in other libsigrokandroidutils-internal files) but are also
* not meant to be part of the public libsigrokandroidutils API, must use
* SRAU_PRIV.
/* Marks public libsigrokandroidutils API symbols. */
#define SRAU_API __attribute__((visibility("default")))
-/* Marks private, non-public libsigrokandroidutils symbols (not part of the API). */
+/* Marks private, non-public, non-API libsigrokandroidutils symbols. */
#define SRAU_PRIV __attribute__((visibility("hidden")))
-
-
SRAU_API void srau_init_environment(void);
#ifdef __cplusplus
public final class Environment
{
- static private String[] environment;
+ static private String[] environment;
- public static String[] getEnvironment()
- {
- return environment;
- }
+ public static String[] getEnvironment()
+ {
+ return environment;
+ }
- public static void initEnvironment(String apkFile)
- {
- environment = new String[]
+ public static void initEnvironment(String apkFile)
{
- "PYTHONHOME", ".",
- "PYTHONPATH", apkFile+"/assets/python3.3",
- "SIGROKDECODE_DIR", apkFile+"/assets/libsigrokdecode/decoders",
- };
- }
+ environment = new String[]
+ {
+ "PYTHONHOME", ".",
+ "PYTHONPATH", apkFile + "/assets/python3.3",
+ "SIGROKDECODE_DIR", apkFile + "/assets/libsigrokdecode/decoders",
+ };
+ }
}
public final class UsbHelper
{
- private static UsbManager manager;
+ private static UsbManager manager;
- public static void setContext(Context ctx)
- {
- if (ctx == null)
- manager = null;
- else
- manager = (UsbManager) ctx.getSystemService(Context.USB_SERVICE);
- }
-
- private static int open(UsbManager manager, String name, int mode)
- {
- if (manager == null) {
- Log.w("UsbHelper", "no manager");
- return -1;
- }
- HashMap<String,UsbDevice> devlist = manager.getDeviceList();
- UsbDevice dev = (devlist == null? null : devlist.get(name));
- if (dev == null) {
- return -1;
+ public static void setContext(Context ctx)
+ {
+ if (ctx == null)
+ manager = null;
+ else
+ manager = (UsbManager) ctx.getSystemService(Context.USB_SERVICE);
}
- if (!manager.hasPermission(dev)) {
- return -1;
+
+ private static int open(UsbManager manager, String name, int mode)
+ {
+ if (manager == null) {
+ Log.w("UsbHelper", "no manager");
+ return -1;
+ }
+ HashMap<String,UsbDevice> devlist = manager.getDeviceList();
+ UsbDevice dev = (devlist == null ? null : devlist.get(name));
+ if (dev == null)
+ return -1;
+ if (!manager.hasPermission(dev))
+ return -1;
+ UsbDeviceConnection conn = manager.openDevice(dev);
+ return (conn == null ? -1 : conn.getFileDescriptor());
}
- UsbDeviceConnection conn = manager.openDevice(dev);
- return (conn == null? -1 : conn.getFileDescriptor());
- }
- public static int open(String name, int mode)
- {
- try {
- return open(manager, name, mode);
- } catch(Exception e) {
- Log.w("UsbHelper", "caught exception "+e);
- return -1;
+ public static int open(String name, int mode)
+ {
+ try {
+ return open(manager, name, mode);
+ } catch (Exception e) {
+ Log.w("UsbHelper", "caught exception " + e);
+ return -1;
+ }
}
- }
}
public class UsbSupplicant
{
- private static final String ACTION_USB_PERMISSION =
+ private static final String ACTION_USB_PERMISSION =
"org.sigrok.androidutils.USB_PERMISSION";
- protected final Context context;
- protected final UsbManager manager;
- private final BroadcastReceiver permReceiver;
- private final BroadcastReceiver hotplugReceiver;
- private final IntentFilter permFilter;
- private final IntentFilter hotplugFilter;
- private final Vector<DeviceFilter> deviceFilters;
-
- // The code in the following inner class is taken from AOSP,
- // which is licensed under the Apache License, Version 2.0
- private static class DeviceFilter {
- // USB Vendor ID (or -1 for unspecified)
- public final int mVendorId;
- // USB Product ID (or -1 for unspecified)
- public final int mProductId;
- // USB device or interface class (or -1 for unspecified)
- public final int mClass;
- // USB device subclass (or -1 for unspecified)
- public final int mSubclass;
- // USB device protocol (or -1 for unspecified)
- public final int mProtocol;
-
- public DeviceFilter(int vid, int pid, int clasz, int subclass, int protocol) {
- mVendorId = vid;
- mProductId = pid;
- mClass = clasz;
- mSubclass = subclass;
- mProtocol = protocol;
- }
-
- public DeviceFilter(UsbDevice device) {
- mVendorId = device.getVendorId();
- mProductId = device.getProductId();
- mClass = device.getDeviceClass();
- mSubclass = device.getDeviceSubclass();
- mProtocol = device.getDeviceProtocol();
- }
-
- public static DeviceFilter read(XmlPullParser parser)
- throws XmlPullParserException, IOException {
- int vendorId = -1;
- int productId = -1;
- int deviceClass = -1;
- int deviceSubclass = -1;
- int deviceProtocol = -1;
-
- int count = parser.getAttributeCount();
- for (int i = 0; i < count; i++) {
- String name = parser.getAttributeName(i);
- // All attribute values are ints
- int value = Integer.parseInt(parser.getAttributeValue(i));
-
- if ("vendor-id".equals(name)) {
- vendorId = value;
- } else if ("product-id".equals(name)) {
- productId = value;
- } else if ("class".equals(name)) {
- deviceClass = value;
- } else if ("subclass".equals(name)) {
- deviceSubclass = value;
- } else if ("protocol".equals(name)) {
- deviceProtocol = value;
- }
- }
- return new DeviceFilter(vendorId, productId,
- deviceClass, deviceSubclass, deviceProtocol);
- }
-
- private boolean matches(int clasz, int subclass, int protocol) {
- return ((mClass == -1 || clasz == mClass) &&
- (mSubclass == -1 || subclass == mSubclass) &&
- (mProtocol == -1 || protocol == mProtocol));
- }
-
- public boolean matches(UsbDevice device) {
- if (mVendorId != -1 && device.getVendorId() != mVendorId) return false;
- if (mProductId != -1 && device.getProductId() != mProductId) return false;
-
- // check device class/subclass/protocol
- if (matches(device.getDeviceClass(), device.getDeviceSubclass(),
- device.getDeviceProtocol())) return true;
-
- // if device doesn't match, check the interfaces
- int count = device.getInterfaceCount();
- for (int i = 0; i < count; i++) {
- UsbInterface intf = device.getInterface(i);
- if (matches(intf.getInterfaceClass(), intf.getInterfaceSubclass(),
- intf.getInterfaceProtocol())) return true;
- }
-
- return false;
- }
-
- @Override
- public String toString() {
- return "DeviceFilter[mVendorId=" + mVendorId + ",mProductId=" + mProductId +
- ",mClass=" + mClass + ",mSubclass=" + mSubclass +
- ",mProtocol=" + mProtocol + "]";
- }
- }
-
- public UsbSupplicant(Context ctx, int device_filter_resource)
- {
- context = ctx;
- manager = (UsbManager) ctx.getSystemService(Context.USB_SERVICE);
- permReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (ACTION_USB_PERMISSION.equals(action)) {
- permissionCallback((UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE),
- intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false));
- }
+ protected final Context context;
+ protected final UsbManager manager;
+ private final BroadcastReceiver permReceiver;
+ private final BroadcastReceiver hotplugReceiver;
+ private final IntentFilter permFilter;
+ private final IntentFilter hotplugFilter;
+ private final Vector<DeviceFilter> deviceFilters;
+
+ // The code in the following inner class is taken from AOSP,
+ // which is licensed under the Apache License, Version 2.0.
+ private static class DeviceFilter {
+ // USB Vendor ID (or -1 for unspecified)
+ public final int mVendorId;
+ // USB Product ID (or -1 for unspecified)
+ public final int mProductId;
+ // USB device or interface class (or -1 for unspecified)
+ public final int mClass;
+ // USB device subclass (or -1 for unspecified)
+ public final int mSubclass;
+ // USB device protocol (or -1 for unspecified)
+ public final int mProtocol;
+
+ public DeviceFilter(int vid, int pid, int clasz, int subclass, int protocol) {
+ mVendorId = vid;
+ mProductId = pid;
+ mClass = clasz;
+ mSubclass = subclass;
+ mProtocol = protocol;
+ }
+
+ public DeviceFilter(UsbDevice device) {
+ mVendorId = device.getVendorId();
+ mProductId = device.getProductId();
+ mClass = device.getDeviceClass();
+ mSubclass = device.getDeviceSubclass();
+ mProtocol = device.getDeviceProtocol();
+ }
+
+ public static DeviceFilter read(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ int vendorId = -1;
+ int productId = -1;
+ int deviceClass = -1;
+ int deviceSubclass = -1;
+ int deviceProtocol = -1;
+
+ int count = parser.getAttributeCount();
+ for (int i = 0; i < count; i++) {
+ String name = parser.getAttributeName(i);
+ // All attribute values are ints
+ int value = Integer.parseInt(parser.getAttributeValue(i));
+
+ if ("vendor-id".equals(name)) {
+ vendorId = value;
+ } else if ("product-id".equals(name)) {
+ productId = value;
+ } else if ("class".equals(name)) {
+ deviceClass = value;
+ } else if ("subclass".equals(name)) {
+ deviceSubclass = value;
+ } else if ("protocol".equals(name)) {
+ deviceProtocol = value;
+ }
+ }
+ return new DeviceFilter(vendorId, productId,
+ deviceClass, deviceSubclass, deviceProtocol);
}
- };
- hotplugReceiver = new BroadcastReceiver() {
+
+ private boolean matches(int clasz, int subclass, int protocol) {
+ return ((mClass == -1 || clasz == mClass) &&
+ (mSubclass == -1 || subclass == mSubclass) &&
+ (mProtocol == -1 || protocol == mProtocol));
+ }
+
+ public boolean matches(UsbDevice device) {
+ if (mVendorId != -1 && device.getVendorId() != mVendorId)
+ return false;
+ if (mProductId != -1 && device.getProductId() != mProductId)
+ return false;
+
+ // Check device class/subclass/protocol.
+ if (matches(device.getDeviceClass(), device.getDeviceSubclass(),
+ device.getDeviceProtocol()))
+ return true;
+
+ // If device doesn't match, check the interfaces.
+ int count = device.getInterfaceCount();
+ for (int i = 0; i < count; i++) {
+ UsbInterface intf = device.getInterface(i);
+ if (matches(intf.getInterfaceClass(), intf.getInterfaceSubclass(),
+ intf.getInterfaceProtocol()))
+ return true;
+ }
+
+ return false;
+ }
+
@Override
- public void onReceive(Context context, Intent intent) {
- if (intent != null &&
- UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) {
- attachCallback((UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE));
- } else if (intent != null &&
- UsbManager.ACTION_USB_DEVICE_DETACHED.equals(intent.getAction())) {
- detachCallback((UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE));
- }
+ public String toString() {
+ return "DeviceFilter[mVendorId=" + mVendorId + ",mProductId=" + mProductId +
+ ",mClass=" + mClass + ",mSubclass=" + mSubclass +
+ ",mProtocol=" + mProtocol + "]";
}
- };
- permFilter = new IntentFilter(ACTION_USB_PERMISSION);
- hotplugFilter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED);
- hotplugFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
- deviceFilters = new Vector<DeviceFilter>();
- addDeviceFilters(ctx.getResources(), device_filter_resource);
- }
-
- private void addDeviceFilters(Resources res, int res_id)
- {
- XmlResourceParser parser = res.getXml(res_id);
- if (parser == null) {
- Log.w("UsbSupplicant", "Unable to get device filter resource");
- return;
}
- deviceFilters.clear();
- try {
- while (parser.next() != XmlPullParser.END_DOCUMENT) {
- if (parser.getEventType() == XmlPullParser.START_TAG) {
- if ("usb-device".equals(parser.getName())) {
- deviceFilters.add(DeviceFilter.read(parser));
- }
+
+ public UsbSupplicant(Context ctx, int device_filter_resource)
+ {
+ context = ctx;
+ manager = (UsbManager) ctx.getSystemService(Context.USB_SERVICE);
+ permReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (ACTION_USB_PERMISSION.equals(action)) {
+ permissionCallback((UsbDevice)intent.getParcelableExtra(
+ UsbManager.EXTRA_DEVICE), intent.getBooleanExtra(
+ UsbManager.EXTRA_PERMISSION_GRANTED, false));
+ }
+ }
+ };
+ hotplugReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent != null && UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) {
+ attachCallback((UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE));
+ } else if (intent != null && UsbManager.ACTION_USB_DEVICE_DETACHED.equals(intent.getAction())) {
+ detachCallback((UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE));
+ }
+ }
+ };
+ permFilter = new IntentFilter(ACTION_USB_PERMISSION);
+ hotplugFilter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED);
+ hotplugFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
+ deviceFilters = new Vector<DeviceFilter>();
+ addDeviceFilters(ctx.getResources(), device_filter_resource);
+ }
+
+ private void addDeviceFilters(Resources res, int res_id)
+ {
+ XmlResourceParser parser = res.getXml(res_id);
+ if (parser == null) {
+ Log.w("UsbSupplicant", "Unable to get device filter resource");
+ return;
+ }
+ deviceFilters.clear();
+ try {
+ while (parser.next() != XmlPullParser.END_DOCUMENT) {
+ if (parser.getEventType() == XmlPullParser.START_TAG) {
+ if ("usb-device".equals(parser.getName()))
+ deviceFilters.add(DeviceFilter.read(parser));
+ }
+ }
+ } catch (IOException e) {
+ Log.wtf("UsbSupplicant",
+ "Failed to parse device filter resource", e);
+ } catch (XmlPullParserException e) {
+ Log.wtf("UsbSupplicant",
+ "Failed to parse device filter resource", e);
}
- }
- } catch(IOException e) {
- Log.wtf("UsbSupplicant",
- "Failed to parse device filter resource", e);
- } catch(XmlPullParserException e) {
- Log.wtf("UsbSupplicant",
- "Failed to parse device filter resource", e);
}
- }
-
- protected boolean interresting(UsbDevice dev)
- {
- if (dev == null)
- return false;
-
- for (DeviceFilter f : deviceFilters)
- if (f.matches(dev))
- return true;
-
- return false;
- }
-
- protected void askFor(UsbDevice dev)
- {
- manager.requestPermission(dev, PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0));
- }
-
- public void start()
- {
- context.registerReceiver(permReceiver, permFilter);
- context.registerReceiver(hotplugReceiver, hotplugFilter);
- HashMap<String,UsbDevice> devlist = manager.getDeviceList();
- for (UsbDevice dev : devlist.values()) {
- if (interresting(dev) && !manager.hasPermission(dev)) {
- Log.d("UsbSupplicant", "found interresting device "+dev);
- askFor(dev);
- }
+
+ protected boolean interresting(UsbDevice dev)
+ {
+ if (dev == null)
+ return false;
+
+ for (DeviceFilter f : deviceFilters)
+ if (f.matches(dev))
+ return true;
+
+ return false;
}
- }
-
- public void stop()
- {
- context.unregisterReceiver(hotplugReceiver);
- context.unregisterReceiver(permReceiver);
- }
-
- protected void permissionCallback(UsbDevice dev, boolean granted)
- {
- Log.d("UsbSupplicant", "permission " + (granted? "granted" : "denied") + " for device " + dev);
- }
-
- protected void attachCallback(UsbDevice dev)
- {
- if (interresting(dev) && !manager.hasPermission(dev)) {
- askFor(dev);
+
+ protected void askFor(UsbDevice dev)
+ {
+ manager.requestPermission(dev, PendingIntent.getBroadcast(context, 0,
+ new Intent(ACTION_USB_PERMISSION), 0));
}
- }
- protected void detachCallback(UsbDevice dev)
- {
- }
+ public void start()
+ {
+ context.registerReceiver(permReceiver, permFilter);
+ context.registerReceiver(hotplugReceiver, hotplugFilter);
+ HashMap<String,UsbDevice> devlist = manager.getDeviceList();
+ for (UsbDevice dev : devlist.values()) {
+ if (interresting(dev) && !manager.hasPermission(dev)) {
+ Log.d("UsbSupplicant", "found interresting device " + dev);
+ askFor(dev);
+ }
+ }
+ }
+
+ public void stop()
+ {
+ context.unregisterReceiver(hotplugReceiver);
+ context.unregisterReceiver(permReceiver);
+ }
+
+ protected void permissionCallback(UsbDevice dev, boolean granted)
+ {
+ Log.d("UsbSupplicant", "permission " +
+ (granted ? "granted" : "denied") + " for device " + dev);
+ }
+
+ protected void attachCallback(UsbDevice dev)
+ {
+ if (interresting(dev) && !manager.hasPermission(dev))
+ askFor(dev);
+ }
+
+ protected void detachCallback(UsbDevice dev)
+ {
+ }
}