2 | //
3 | // This program is free software; you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation; either version 2 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program; if not, write to the Free Software
15 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | //
17 |
18 | package cn.rainx.ptp.usbcamera;
19 |
20 | import java.io.PrintStream;
21 |
22 |
23 | /**
24 | * PTP Command, Data, Response, and Event blocks use a "Generic Container
25 | * Structure" as a packet header.
26 | *
27 | * Note that since the string values to which various codes map
28 | * have been interned, you may safely rely on "==" and "!=" when you
29 | * make comparisons against constant values.
30 | *
31 | * @version $Id: Container.java,v 1.8 2001/04/12 23:13:00 dbrownell Exp $
32 | * @author David Brownell
33 | */
34 | abstract public class Container extends Buffer
35 | {
36 | public static final int BLOCK_TYPE_COMMAND = 1;
37 | public static final int BLOCK_TYPE_DATA = 2;
38 | public static final int BLOCK_TYPE_RESPONSE = 3;
39 | public static final int BLOCK_TYPE_EVENT = 4;
40 |
41 | protected NameFactory factory;
42 |
43 | // get/put object handles (not 0, ~0) using session context
44 | // Session session;
45 |
46 | // fixed header layout, per annex D
47 | // NOTE: session id (9.3.2) is implicit: no multisession over USB
48 | // @ 0, u32 length
49 | // @ 4, u16 buffer type
50 | // @ 6, u16 code
51 | // @ 8, u32 xid
52 | // TOTAL: 12 bytes
53 | static final int HDR_LEN = 12;
54 |
55 | public Container (byte buf [], NameFactory f)
56 | { super (buf, buf.length); factory = f; }
57 |
58 | public Container (byte buf [], int len, NameFactory f)
59 | { super (buf, len); factory = f; }
60 |
61 | // package private
62 | public void putHeader (int len, int type, int code, int xid)
63 | {
64 | if (offset != 0)
65 | throw new IllegalStateException();
66 | put32 (len);
67 | put16 (type);
68 | put16 (code);
69 | put32 (xid);
70 | }
71 |
72 |
73 | /**
74 | * Provides a printable representation of data from the block
75 | * header, including block type, code, and transaction ID.
76 | */
77 | public String toString ()
78 | {
79 | StringBuffer temp = new StringBuffer();
80 | String type = getBlockTypeName (getBlockType ());
81 | int code = getCode ();
82 |
83 | temp.append ("{ ");
84 | temp.append (type);
85 | temp.append ("; len ");
86 | temp.append (Integer.toString (getLength ()));
87 | temp.append ("; ");
88 | temp.append (getCodeName (code));
89 | temp.append ("; xid ");
90 | temp.append (Integer.toString (getXID ()));
91 |
92 | // inelegant, but ...
93 | if (this instanceof ParamVector) {
94 | ParamVector vec = (ParamVector) this;
95 | int nparams = vec.getNumParams ();
96 |
97 | if (nparams > 0) {
98 | temp.append ("; ");
99 | for (int i = 0; i < nparams; i++) {
100 | if (i != 0)
101 | temp.append (" ");
102 | temp.append ("0x");
103 | temp.append (Integer.toHexString (vec.getParam (i)));
104 | }
105 | }
106 | }
107 |
108 | temp.append (" }");
109 | return temp.toString ();
110 | }
111 |
112 | void dump (PrintStream out)
113 | {
114 | out.println (toString ());
115 | }
116 |
117 |
118 | protected void parse()
119 | {
120 | offset = HDR_LEN;
121 | }
122 |
123 | /** Returns the overall length of this data block, including header. */
124 | public int getLength ()
125 | { return /* unsigned */ getS32 (0); }
126 |
127 | /**
128 | * Returns the overall type of this data block as a coded integer.
129 | */
130 | public final int getBlockType ()
131 | { return getU16 (4); }
132 |
133 | /**
134 | * Returns an interned string, normally "command", "data", "response",
135 | * or "event", corresponding to the coded type. Unrecognized or
136 | * undefined values are returned as interned Integer.toHexString values.
137 | */
138 | public static final String getBlockTypeName (int type)
139 | {
140 | switch (type) {
141 | case 1: return "command";
142 | case 2: return "data";
143 | case 3: return "response";
144 | case 4: return "event";
145 | default: return Integer.toHexString (type).intern ();
146 | }
147 | }
148 |
149 | /**
150 | * Returns the operation, response, or event code of this block.
151 | */
152 | public final int getCode ()
153 | {
154 | return getU16 (6);
155 | }
156 |
157 | /**
158 | * Returns an interned string identifying the type of code field,
159 | * such as "OperationCode", "ResponseCode", "ObjectFormatCode",
160 | * "EventCode", or "DevicePropsCode". Unrecognized or undefined
161 | * values are returned as interned Integer.toHexString values.
162 | */
163 | public static final String getCodeType (int code)
164 | {
165 | switch (code >> 12) {
166 | case 1: return "OperationCode";
167 | case 2: return "ResponseCode";
168 | case 3: return "ObjectFormatCode";
169 | case 4: return "EventCode";
170 | case 5: return "DevicePropCode";
171 | case 8 + 1: return "Vendor-OpCode";
172 | case 8 + 2: return "Vendor-ResponseCode";
173 | case 8 + 3: return "Vendor-FormatCode";
174 | case 8 + 4: return "Vendor-EventCode";
175 | case 8 + 5: return "Vendor-PropCode";
176 | default: return Integer.toHexString (code >> 12).intern ();
177 | }
178 | }
179 |
180 | /**
181 | * Subclasses override this to map PTP codes to their names; the
182 | * results are always interned strings, so that they can be efficiently
183 | * compared ("=", "!=") against constants. Such per-instance methods
184 | * permit type-specific subclasses (and vendor extensions) to name their
185 | * code values, invoking superclass methods to name all other codes.
186 | */
187 | public String getCodeName (int code)
188 | {
189 | return getCodeString (code);
190 | }
191 |
192 | /**
193 | * Returns an interned string with name of this container's code.
194 | */
195 | public final String getCodeString ()
196 | {
197 | return getCodeName (getCode ()).intern ();
198 | }
199 |
200 | /**
201 | * Returns an interned string with the hexadecimal value of
202 | * the specified container code.
203 | */
204 | public static String getCodeString (int code)
205 | {
206 | return Integer.toHexString (code).intern ();
207 | }
208 |
209 | /**
210 | * Returns the ID of the transaction this block is associated with.
211 | */
212 | public final int getXID ()
213 | { return getS32 (8); }
214 | }
215 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/Data.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000 by David Brownell
2 | //
3 | // This program is free software; you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation; either version 2 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program; if not, write to the Free Software
15 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | //
17 |
18 | package cn.rainx.ptp.usbcamera;
19 |
20 |
21 | /**
22 | * The optional middle phase of a PTP transaction involves sending
23 | * data to or from the responder.
24 | *
25 | * @version $Id: Data.java,v 1.4 2001/04/12 23:13:00 dbrownell Exp $
26 | * @author David Brownell
27 | */
28 | public class Data extends Container
29 | {
30 | private boolean in;
31 |
32 | public Data (NameFactory f) { this (true, null, 0, f); }
33 |
34 | public Data (boolean isIn, byte buf [], NameFactory f)
35 | { super (buf, f); in = isIn; }
36 |
37 | public Data (boolean isIn, byte buf [], int len, NameFactory f)
38 | { super (buf, len, f); in = isIn; }
39 |
40 | boolean isIn ()
41 | { return in; }
42 |
43 | public String getCodeName (int code)
44 | {
45 | return factory.getOpcodeString (code);
46 | }
47 |
48 | public String toString ()
49 | {
50 | StringBuffer temp = new StringBuffer();
51 | int code = getCode ();
52 |
53 | temp.append ("{ ");
54 | temp.append (getBlockTypeName (getBlockType ()));
55 | if (in)
56 | temp.append (" IN");
57 | else
58 | temp.append (" OUT");
59 | temp.append ("; len ");
60 | temp.append (Integer.toString (getLength ()));
61 | temp.append ("; ");
62 | temp.append (factory.getOpcodeString (code));
63 | temp.append ("; xid ");
64 | temp.append (Integer.toString (getXID ()));
65 | temp.append ("}");
66 | return temp.toString ();
67 | }
68 | }
69 |
70 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/DeviceInfo.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000 by David Brownell
2 | //
3 | // This program is free software; you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation; either version 2 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program; if not, write to the Free Software
15 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | //
17 |
18 | package cn.rainx.ptp.usbcamera;
19 |
20 | import java.io.PrintStream;
21 |
22 |
23 | /**
24 | * DeviceInfo describes device functionality such supported image formats,
25 | * operations, events, and device properties.
26 | *
27 | * @version $Id: DeviceInfo.java,v 1.8 2001/04/12 23:13:00 dbrownell Exp $
28 | * @author David Brownell
29 | */
30 | public class DeviceInfo extends Data
31 | {
32 | // need some transport-neutral interface; this is USB-specific
33 |
34 | int standardVersion;
35 | int vendorExtensionId;
36 | int vendorExtensionVersion;
37 | String vendorExtensionDesc;
38 |
39 | int functionalMode; // may change;
40 | int operationsSupported []; // 10.2
41 | int eventsSupported []; // 12.5
42 | int propertiesSupported []; // 13.3.5
43 |
44 | int captureFormats []; // 6
45 | int imageFormats []; // 6
46 | String manufacturer;
47 | String model;
48 |
49 | String deviceVersion;
50 | String serialNumber;
51 |
52 | // FIXME add formal vendor hooks, which we'd consult for string
53 | // mappings ... we don't have any here.
54 |
55 | // Command, Response, ObjectInfo, Event, and DevicePropDesc can
56 | // all be subclassed; but we won't have instances here. And
57 | // there's also the vendor extension stuff here.
58 |
59 |
60 | // input -- we can't know buffer size yet
61 | DeviceInfo (NameFactory f)
62 | { super (true, null, 0, f); }
63 |
64 |
65 | private boolean supports (int supported [], int code)
66 | {
67 | for (int i = 0; i < supported.length; i++) {
68 | if (code == supported [i])
69 | return true;
70 | }
71 | return false;
72 | }
73 |
74 |
75 | /** Returns true iff the device supports this operation */
76 | public boolean supportsOperation (int opCode)
77 | {
78 | return supports (operationsSupported, opCode);
79 | }
80 |
81 | /** Returns true iff the device supports this event */
82 | public boolean supportsEvent (int eventCode)
83 | {
84 | return supports (eventsSupported, eventCode);
85 | }
86 |
87 | /** Returns true iff the device supports this property */
88 | public boolean supportsProperty (int propCode)
89 | {
90 | return supports (propertiesSupported, propCode);
91 | }
92 |
93 | /** Returns true iff the device supports this capture format */
94 | public boolean supportsCaptureFormat (int formatCode)
95 | {
96 | return supports (captureFormats, formatCode);
97 | }
98 |
99 | /** Returns true iff the device supports this image format */
100 | public boolean supportsImageFormat (int formatCode)
101 | {
102 | return supports (imageFormats, formatCode);
103 | }
104 |
105 |
106 | // fit names to standard length lines
107 | private int addString (PrintStream out, int last, String s)
108 | {
109 | last += s.length ();
110 | last++;
111 | if (last < 80) {
112 | out.print (s);
113 | out.print (" ");
114 | } else {
115 | out.println ();
116 | out.print ("\t");
117 | out.print (s);
118 | out.print (" ");
119 | last = 8 + s.length () + 1;
120 | }
121 | return last;
122 | }
123 |
124 | protected void parse()
125 | {
126 | super.parse ();
127 |
128 | standardVersion = nextU16 ();
129 | vendorExtensionId = /* unsigned */ nextS32 ();
130 | vendorExtensionVersion = nextU16 ();
131 | vendorExtensionDesc = nextString ();
132 |
133 | functionalMode = nextU16 ();
134 | operationsSupported = nextU16Array ();
135 | eventsSupported = nextU16Array ();
136 | propertiesSupported = nextU16Array ();
137 |
138 | captureFormats = nextU16Array ();
139 | imageFormats = nextU16Array ();
140 | manufacturer = nextString ();
141 | model = nextString ();
142 |
143 | deviceVersion = nextString ();
144 | serialNumber = nextString ();
145 | }
146 |
147 | void lines (PrintStream out)
148 | {
149 | if (manufacturer != null)
150 | out.println ("Manufacturer: " + manufacturer);
151 | if (model != null)
152 | out.println ("Model: " + model);
153 | if (deviceVersion != null)
154 | out.println ("Device Version: " + deviceVersion);
155 | if (serialNumber != null)
156 | out.println ("Serial Number: " + serialNumber);
157 |
158 | if (functionalMode != 0) {
159 | out.print ("Functional Mode: ");
160 | out.println (funcMode (functionalMode));
161 | }
162 |
163 | if (vendorExtensionId != 0) {
164 | out.print ("Extensions (");
165 | out.print (Integer.toString (vendorExtensionId));
166 | out.print (")");
167 | if (vendorExtensionDesc != null) {
168 | out.print (": ");
169 | out.print (vendorExtensionDesc);
170 | }
171 | out.println ();
172 |
173 | // summarize extension: ops, props, events
174 | }
175 | }
176 |
177 | public String toString ()
178 | {
179 |
180 | if (operationsSupported == null) {
181 | // System.err.println ("... device info uninitted");
182 | return "... device info uninitted";
183 | }
184 | String result = "DeviceInfo:\n";
185 | result += ("PTP Version: "
186 | + (standardVersion / 100)
187 | + "."
188 | + (standardVersion % 100));
189 |
190 | // per chapter 10
191 | result += ("\n\nOperations Supported:");
192 | for (int i = 0; i < operationsSupported.length; i++) {
193 | result += "\n\t" +factory.getOpcodeString (operationsSupported [i]);
194 | }
195 |
196 | // per chapter 11
197 | result += ("\n\nEvents Supported:");
198 | for (int i = 0; i < eventsSupported.length; i++) {
199 | result += "\n\t" +factory.getEventString (eventsSupported [i]);
200 | }
201 |
202 | // per chapter 13
203 | result += ("\n\nDevice Properties Supported:\n");
204 | for (int i = 0; i < propertiesSupported.length; i++) {
205 | result += "\t" +factory.getPropertyName (propertiesSupported [i]);
206 | }
207 |
208 | // per 6.2
209 | result += ("\n\nCapture Formats Supported:\n");
210 | for (int i = 0; i < captureFormats.length; i++) {
211 | result += "\t" +factory.getFormatString (captureFormats [i]);
212 | }
213 |
214 | // per 6.2
215 | result += ("\n\nImage Formats Supported:\n");
216 | for (int i = 0; i < imageFormats.length; i++) {
217 | result += "\t" + factory.getFormatString (imageFormats [i]);
218 | }
219 |
220 | if (vendorExtensionId != 0) {
221 | result += ("\n\nVendor Extension, id ");
222 | result += (Integer.toString (vendorExtensionId));
223 | result += (", version ");
224 | result += (standardVersion / 100);
225 | result += (".");
226 | result += (standardVersion % 100);
227 |
228 | if (vendorExtensionDesc != null) {
229 | result += "\nDescription: " +vendorExtensionDesc;
230 | }
231 | }
232 | return result;
233 | }
234 |
235 | static String funcMode (int functionalMode)
236 | {
237 | switch (functionalMode) {
238 | case 0:
239 | return "standard";
240 | case 1:
241 | return "sleeping";
242 | default:
243 | // FIXME add vendor hook
244 | StringBuffer buf = new StringBuffer();
245 |
246 | if ((functionalMode & 0x8000) == 0)
247 | buf.append ("reserved 0x");
248 | else
249 | buf.append ("vendor 0x");
250 | buf.append (Integer.toHexString (functionalMode & ~0x8000));
251 | return buf.toString ();
252 | }
253 | }
254 | }
255 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/DevicePropValue.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000 by David Brownell
2 | //
3 | // This program is free software; you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation; either version 2 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program; if not, write to the Free Software
15 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | //
17 |
18 | package cn.rainx.ptp.usbcamera;
19 |
20 | import android.widget.TextView;
21 |
22 | import java.io.PrintStream;
23 |
24 |
25 | /**
26 | * DeviceProperty values wrap various types of integers and
27 | * arrays of integers, and strings. It's sort of like a
28 | * CORBA "Any", pairing a typecode and value, except that
29 | * the typecode is known in advance so it's never marshaled.
30 | *
31 | * @see DevicePropDesc
32 | *
33 | * @version $Id: DevicePropValue.java,v 1.4 2001/04/12 23:13:00 dbrownell Exp $
34 | * @author David Brownell
35 | */
36 | public class DevicePropValue extends Data
37 | {
38 | int typecode;
39 | Object value;
40 |
41 | DevicePropValue (int tc, NameFactory f)
42 | { super (f); typecode = tc; }
43 |
44 | private DevicePropValue (int tc, Object obj, NameFactory f)
45 | {
46 | super (f);
47 | typecode = tc;
48 | value = obj;
49 |
50 | // FIXME: marshal value into the buffer.
51 | }
52 |
53 | public Object getValue ()
54 | { return value; }
55 |
56 | public int getTypeCode ()
57 | { return typecode; }
58 |
59 | protected void parse()
60 | {
61 | value = get (typecode, this);
62 | }
63 |
64 | void dump (PrintStream out)
65 | {
66 | out.print ("Type: ");
67 | out.print (getTypeName (typecode));
68 | out.print (", Value: ");
69 | out.println (value.toString ());
70 | }
71 |
72 | void showInTextView (TextView tv)
73 | {
74 | tv.setText ("Type: ");
75 | tv.append (getTypeName (typecode));
76 | tv.append (", Value: ");
77 | tv.append ("\n");
78 | tv.append (value.toString ());
79 | }
80 |
81 | public String getCodeName (int code)
82 | {
83 | return getTypeName (code);
84 | }
85 |
86 | public static Object get (int code, Buffer buf)
87 | {
88 | Object value;
89 |
90 | switch (code) {
91 | case s8:
92 | return new Integer(buf.nextS8 ());
93 | case u8:
94 | return new Integer(buf.nextU8 ());
95 | case s16:
96 | return new Integer(buf.nextS16 ());
97 | case u16:
98 | return new Integer(buf.nextU16 ());
99 | case s32:
100 | return new Integer(buf.nextS32 ());
101 | case u32:
102 | return new Long(0x0ffFFffFFL & buf.nextS32 ());
103 | case s64:
104 | return new Long(buf.nextS64 ());
105 | case u64:
106 | // FIXME: unsigned masquerading as signed ...
107 | return new Long(buf.nextS64 ());
108 |
109 | // case s128: case u128:
110 |
111 | case s8array:
112 | return buf.nextS8Array ();
113 | case u8array:
114 | return buf.nextU8Array ();
115 | case s16array:
116 | return buf.nextS16Array ();
117 | case u16array:
118 | return buf.nextU16Array ();
119 | case u32array:
120 | // FIXME: unsigned masquerading as signed ...
121 | case s32array:
122 | return buf.nextS32Array ();
123 | case u64array:
124 | // FIXME: unsigned masquerading as signed ...
125 | case s64array:
126 | return buf.nextS64Array ();
127 | // case s128array: case u128array:
128 |
129 | case string:
130 | return buf.nextString ();
131 | }
132 | throw new IllegalArgumentException();
133 | }
134 |
135 | // code values, per 5.3 table 3
136 |
137 | public static final int s8 = 0x0001;
138 | /** Unsigned eight bit integer */
139 | public static final int u8 = 0x0002;
140 | public static final int s16 = 0x0003;
141 | /** Unsigned sixteen bit integer */
142 | public static final int u16 = 0x0004;
143 | public static final int s32 = 0x0005;
144 | /** Unsigned thirty two bit integer */
145 | public static final int u32 = 0x0006;
146 | public static final int s64 = 0x0007;
147 | /** Unsigned sixty four bit integer */
148 | public static final int u64 = 0x0008;
149 | public static final int s128 = 0x0009;
150 | /** Unsigned one hundred twenty eight bit integer */
151 | public static final int u128 = 0x000a;
152 | public static final int s8array = 0x4001;
153 | /** Array of unsigned eight bit integers */
154 | public static final int u8array = 0x4002;
155 | public static final int s16array = 0x4003;
156 | /** Array of unsigned sixteen bit integers */
157 | public static final int u16array = 0x4004;
158 | public static final int s32array = 0x4005;
159 | /** Array of unsigned thirty two bit integers */
160 | public static final int u32array = 0x4006;
161 | public static final int s64array = 0x4007;
162 | /** Array of unsigned sixty four bit integers */
163 | public static final int u64array = 0x4008;
164 | public static final int s128array = 0x4009;
165 | /** Array of unsigned one hundred twenty eight bit integers */
166 | public static final int u128array = 0x400a;
167 | /** Unicode string */
168 | public static final int string = 0xffff;
169 |
170 | /**
171 | * Maps datatype codes to string names.
172 | * @param code datatype code
173 | * @return interned string identifying that datatype.
174 | */
175 | public static String getTypeName (int code)
176 | {
177 | switch (code) {
178 | case s8: return "s8";
179 | case u8: return "u8";
180 | case s16: return "s16";
181 | case u16: return "u16";
182 | case s32: return "s32";
183 | case u32: return "u32";
184 | case s64: return "s64";
185 | case u64: return "u64";
186 | case s128: return "s128";
187 | case u128: return "u128";
188 | case s8array: return "s8array";
189 | case u8array: return "u8array";
190 | case s16array: return "s16array";
191 | case u16array: return "u16array";
192 | case s32array: return "s32array";
193 | case u32array: return "u32array";
194 | case s64array: return "s64array";
195 | case u64array: return "u64array";
196 | case s128array: return "s128array";
197 | case u128array: return "u128array";
198 | case string: return "string";
199 | }
200 | return Container.getCodeString (code);
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/Event.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000 by David Brownell
2 | // Copyright 2010 by Stefano Fornari
3 | //
4 | // This program is free software; you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation; either version 2 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program; if not, write to the Free Software
16 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 | //
18 | package cn.rainx.ptp.usbcamera;
19 |
20 | /**
21 | * Events are sent spontaneously from responders to initiators.
22 | * Event codes, described in chapter 12 of the PTP specification,
23 | * identify what happened. Some events have a parameter, and
24 | * additional data (for vendor extensions) may be available
25 | * using the class control request "Get Extended Event Data".
26 | *
27 | * @author David Brownell
28 | * @author Stefano Fonari
29 | */
30 | public class Event extends ParamVector {
31 |
32 | public Event(byte buf[], NameFactory f) {
33 | super(buf, buf.length, f);
34 | }
35 | /** EventCode: */
36 | public static final int Undefined = 0x4000;
37 | /** EventCode: */
38 | public static final int CancelTransaction = 0x4001;
39 | /** EventCode: */
40 | public static final int ObjectAdded = 0x4002;
41 | /** EventCode: */
42 | public static final int ObjectRemoved = 0x4003;
43 | /** EventCode: */
44 | public static final int StoreAdded = 0x4004;
45 | /** EventCode: */
46 | public static final int StoreRemoved = 0x4005;
47 | /** EventCode: */
48 | public static final int DevicePropChanged = 0x4006;
49 | /** EventCode: */
50 | public static final int ObjectInfoChanged = 0x4007;
51 | /** EventCode: */
52 | public static final int DeviceInfoChanged = 0x4008;
53 | /** EventCode: */
54 | public static final int RequestObjectTransfer = 0x4009;
55 | /** EventCode: */
56 | public static final int StoreFull = 0x400a;
57 | /** EventCode: */
58 | public static final int DeviceReset = 0x400b;
59 | /** EventCode: */
60 | public static final int StorageInfoChanged = 0x400c;
61 | /** EventCode: */
62 | public static final int CaptureComplete = 0x400d;
63 | /** EventCode: a status event was dropped (missed an interrupt) */
64 | public static final int UnreportedStatus = 0x400e;
65 |
66 | public String getCodeName(int code) {
67 | //return factory.getEventString(code);
68 | return _getEventString(code);
69 | }
70 |
71 | static public String _getEventString(int code) {
72 | switch (code) {
73 | case Undefined:
74 | return "Undefined";
75 | case CancelTransaction:
76 | return "CancelTransaction";
77 | case ObjectAdded:
78 | return "ObjectAdded";
79 | case ObjectRemoved:
80 | return "ObjectRemoved";
81 |
82 | case StoreAdded:
83 | return "StoreAdded";
84 | case StoreRemoved:
85 | return "StoreRemoved";
86 | case DevicePropChanged:
87 | return "DevicePropChanged";
88 | case ObjectInfoChanged:
89 | return "ObjectInfoChanged";
90 |
91 | case DeviceInfoChanged:
92 | return "DeviceInfoChanged";
93 | case RequestObjectTransfer:
94 | return "RequestObjectTransfer";
95 | case StoreFull:
96 | return "StoreFull";
97 | case DeviceReset:
98 | return "DeviceReset";
99 |
100 | case StorageInfoChanged:
101 | return "StorageInfoChanged";
102 | case CaptureComplete:
103 | return "CaptureComplete";
104 | case UnreportedStatus:
105 | return "UnreportedStatus";
106 |
107 |
108 | }
109 | return getCodeString(code);
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/FileSendData.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000 by David Brownell
2 | //
3 | // This program is free software; you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation; either version 2 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program; if not, write to the Free Software
15 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | //
17 |
18 | package cn.rainx.ptp.usbcamera;
19 |
20 | import java.io.IOException;
21 | import java.io.InputStream;
22 | import java.net.URLConnection;
23 |
24 |
25 | /**
26 | * Used with {@link BaselineInitiator#sendObject sendObject}, this can read
27 | * objects from files using a relatively small amount of in-memory buffering.
28 | * That reduces system resource requirements for working with large files
29 | * such as uncompressed TIF images supported by higher end imaging devices.
30 | *
31 | * @see BaselineInitiator#sendObject
32 | *
33 | * @version $Id: FileSendData.java,v 1.3 2001/04/12 23:13:00 dbrownell Exp $
34 | * @author David Brownell
35 | */
36 | public class FileSendData extends Data
37 | {
38 | private InputStream in;
39 | private int filesize;
40 |
41 | // FIXME: shouldn't be "File" streams
42 |
43 | /**
44 | * Constructs a data object which fills the given underlying file.
45 | */
46 | public FileSendData (URLConnection data, NameFactory f)
47 | throws IOException
48 | {
49 | super (false, new byte [128 * 1024], f);
50 | in = data.getInputStream ();
51 | filesize = data.getContentLength ();
52 | }
53 |
54 | public int getLength ()
55 | {
56 | return HDR_LEN + filesize;
57 | }
58 |
59 | /**
60 | * Reads object data from the underlying file.
61 | */
62 | public int read (byte buf [], int off, int len)
63 | throws IOException
64 | {
65 | return in.read (buf, off, len);
66 | }
67 |
68 | /**
69 | * Closes the underlying file.
70 | */
71 | public void close ()
72 | throws IOException
73 | {
74 | in.close ();
75 | }
76 | }
77 |
78 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/InitiatorFactory.java:
--------------------------------------------------------------------------------
1 | package cn.rainx.ptp.usbcamera;
2 |
3 | import android.hardware.usb.UsbDevice;
4 | import android.hardware.usb.UsbManager;
5 | import android.util.Log;
6 |
7 | import cn.rainx.ptp.detect.CameraDetector;
8 | import cn.rainx.ptp.usbcamera.eos.EosInitiator;
9 | import cn.rainx.ptp.usbcamera.nikon.NikonInitiator;
10 | import cn.rainx.ptp.usbcamera.sony.SonyInitiator;
11 |
12 | /**
13 | * Created by rainx on 2017/5/27.
14 | */
15 |
16 | public class InitiatorFactory {
17 | public static final String TAG = InitiatorFactory.class.getName();
18 |
19 | static public BaselineInitiator produceInitiator(UsbDevice device, UsbManager usbManager) throws PTPException {
20 | BaselineInitiator bi;
21 | CameraDetector cd = new CameraDetector(device);
22 | if (cd.getSupportedVendorId() == CameraDetector.VENDOR_ID_CANON) {
23 | Log.d(TAG, "Device is CANON, open EOSInitiator");
24 | bi = new EosInitiator(device, usbManager.openDevice(device));
25 | } else if (cd.getSupportedVendorId() == CameraDetector.VENDOR_ID_NIKON) {
26 | Log.d(TAG, "Device is Nikon, open NikonInitiator");
27 | bi = new NikonInitiator(device, usbManager.openDevice(device));
28 | } else if (cd.getSupportedVendorId() == CameraDetector.VENDOR_ID_SONY) {
29 | Log.d(TAG, "Device is Sony, open SonyInitiator");
30 | bi = new SonyInitiator(device, usbManager.openDevice(device));
31 | } else /* if (cd.getSupportedVendorId() == CameraDetector.VENDOR_ID_OTHER) */ {
32 | Log.d(TAG, "Unkown device, open BaselineInitiator");
33 | bi = new BaselineInitiator (device, usbManager.openDevice(device));
34 | }
35 |
36 | return bi;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/KodakExtension.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000 by David Brownell
2 | //
3 | // This program is free software; you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation; either version 2 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program; if not, write to the Free Software
15 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | //
17 |
18 | package cn.rainx.ptp.usbcamera;
19 |
20 | /**
21 | * This class packages the vendor extension published by
22 | * Eastman Kodak Corporation, which has promised to openly
23 | * publish the complete specification needed to use these.
24 | *
25 | * @version $Id: KodakExtension.java,v 1.1 2001/04/12 23:13:00 dbrownell Exp $
26 | */
27 | class KodakExtension extends NameFactory
28 | {
29 | // FIXME: this should eventually host APIs for the
30 | // specialized commands, so it'll need to subclass
31 | // at least BaselineInitiator (so it can do I/O).
32 |
33 | KodakExtension () { }
34 |
35 |
36 | /*-------------------------------------------------------------*/
37 |
38 | /**
39 | * This is like SendObjectInfo. However, things like
40 | * the association ("MUSIC") need to be filled in;
41 | * there are no optional parameters.
42 | */
43 | public static final int SendFileObjectInfo = 0x9005;
44 |
45 | /**
46 | * This is SendObject, except that it was preceded
47 | * by SendFileObjectInfo
48 | */
49 | public static final int SendFileObject = 0x9006;
50 |
51 |
52 | public String getOpcodeString (int code)
53 | {
54 | switch (code) {
55 | case SendFileObjectInfo:
56 | return "Kodak_SendFileObjectInfo";
57 | case SendFileObject:
58 | return "Kodak_SendFileObject";
59 | }
60 | return Command._getOpcodeString (code);
61 | }
62 |
63 | /*-------------------------------------------------------------*/
64 |
65 | /** ResponseCode: */
66 | public static final int FilenameRequired = 0xa001;
67 |
68 | /** ResponseCode: */
69 | public static final int FilenameConflicts = 0xa002;
70 |
71 | /** ResponseCode: */
72 | public static final int FilenameInvalid = 0xa003;
73 |
74 | public String getResponseString (int code)
75 | {
76 | switch (code) {
77 | case FilenameRequired:
78 | return "Kodak_FilenameRequired";
79 | case FilenameConflicts:
80 | return "Kodak_FilenameConflicts";
81 | case FilenameInvalid:
82 | return "Kodak_FilenameInvalid";
83 | }
84 | return Response._getResponseString (code);
85 | }
86 |
87 | /*-------------------------------------------------------------*/
88 |
89 | /** ObjectFormatCode: ".fw" file for device firmware. */
90 | public static final int Firmware = 0xb001;
91 |
92 | /** ObjectFormatCode: ".m3u" style MP3 playlist. */
93 | public static final int M3U = 0xb002;
94 |
95 |
96 | public String getFormatString (int code)
97 | {
98 | switch (code) {
99 | case Firmware:
100 | return "Kodak_Firmware";
101 | case M3U:
102 | return "Kodak_M3U";
103 | }
104 | return ObjectInfo._getFormatString (code);
105 | }
106 |
107 | /*-------------------------------------------------------------*/
108 |
109 | /** Property code: */
110 | public static final int prop1 = 0xd001;
111 |
112 | /** Property code: */
113 | public static final int prop2 = 0xd002;
114 |
115 | /** Property code: */
116 | public static final int prop3 = 0xd003;
117 |
118 | /** Property code: */
119 | public static final int prop4 = 0xd004;
120 |
121 | /** Property code: */
122 | public static final int prop5 = 0xd005;
123 |
124 | /** Property code: */
125 | public static final int prop6 = 0xd006;
126 |
127 | public String getPropertyName (int code)
128 | {
129 | switch (code) {
130 | case prop1:
131 | return "Kodak_prop1";
132 | case prop2:
133 | return "Kodak_prop2";
134 | case prop3:
135 | return "Kodak_prop3";
136 | case prop4:
137 | return "Kodak_prop4";
138 | case prop5:
139 | return "Kodak_prop5";
140 | case prop6:
141 | return "Kodak_prop6";
142 | }
143 | return DevicePropDesc._getPropertyName (code);
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/NameFactory.java:
--------------------------------------------------------------------------------
1 | // Copyright 2001 by David Brownell
2 | //
3 | // This program is free software; you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation; either version 2 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program; if not, write to the Free Software
15 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | //
17 |
18 | package cn.rainx.ptp.usbcamera;
19 |
20 | /**
21 | * Supports use of objects using vendor extension codes.
22 | * The base class produces names only for standard PTP
23 | * operations, responses, properties, events, and formats.
24 | *
25 | * @version $Id: NameFactory.java,v 1.1 2001/04/12 23:13:00 dbrownell Exp $
26 | */
27 | public class NameFactory
28 | {
29 | // package private
30 | protected NameFactory () { }
31 |
32 | // package private
33 | protected NameFactory updateFactory (int vendorExtensionId)
34 | {
35 | switch (vendorExtensionId) {
36 | case 0: return this;
37 | case 1: return new KodakExtension ();
38 | }
39 | if (BaselineInitiator.DEBUG)
40 | System.err.println ("Don't know extension " + vendorExtensionId);
41 | return this;
42 | }
43 |
44 | /*
45 | static String vendorToString (int vendorExtensionId)
46 | {
47 | switch (vendorExtensionId) {
48 | // from PIMA website
49 | case 1: return "Eastman Kodak Company";
50 | case 2: return "Seiko Epson";
51 | case 3: return "Agilent Technologies, Inc.";
52 | case 4: return "Polaroid Corporation";
53 | case 5: return "Agfa-Gevaert";
54 | case 6: return "Microsoft Corporation";
55 | default:
56 | return "0x" + Integer.toHexString (vendorExtensionId);
57 | }
58 | }
59 | */
60 |
61 | /**
62 | * Maps command codes to string names.
63 | * @param code device command code
64 | * @return interned string identifying that command.
65 | */
66 | // bits 14:12 = 001
67 | public String getOpcodeString (int code)
68 | { return Command._getOpcodeString (code); }
69 |
70 | /**
71 | * Maps response codes to string names.
72 | * @param code response code
73 | * @return interned string identifying that response.
74 | */
75 | // bits 14:12 = 010
76 | public String getResponseString (int code)
77 | { return Response._getResponseString (code); }
78 |
79 | /**
80 | * Maps object format codes to string names.
81 | * @param code device format code
82 | * @return interned string identifying that format.
83 | */
84 | // bits 14:12 = 011
85 | public String getFormatString (int code)
86 | { return ObjectInfo._getFormatString (code); }
87 |
88 | /**
89 | * Maps event codes to string names.
90 | * @param code device event code
91 | * @return interned string identifying that event.
92 | */
93 | // bits 14:12 = 100
94 | public String getEventString (int code)
95 | { return Event._getEventString (code); }
96 |
97 | /**
98 | * Maps property codes to string names.
99 | * @param code device property code
100 | * @return interned string identifying that property.
101 | */
102 | // bits 14:12 = 101
103 | public String getPropertyName (int code)
104 | { return DevicePropDesc._getPropertyName (code); }
105 |
106 |
107 | // FIXME: hooks for vendor-specific filesystem types.
108 | }
109 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/OutputStreamData.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2010 by Stefano Fornari
2 | //
3 | // This program is free software; you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation; either version 2 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program; if not, write to the Free Software
15 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | */
17 | package cn.rainx.ptp.usbcamera;
18 |
19 | import java.io.IOException;
20 | import java.io.OutputStream;
21 |
22 | /**
23 | * Used with {@link BaselineInitiator#fillObject fillObject}, this writes
24 | * objects to a give output stream.
25 | *
26 | * @see BaselineInitiator#fillObject
27 | *
28 | * @author ste
29 | */
30 | public class OutputStreamData extends Data {
31 |
32 | private OutputStream out;
33 |
34 | /**
35 | * Constructs a data object which fills the given underlying file.
36 | */
37 | public OutputStreamData(OutputStream o, NameFactory f) {
38 | super(f);
39 | out = o;
40 | }
41 |
42 | /**
43 | * Writes object data to the underlying output stream
44 | */
45 | public void write(byte buf[], int off, int len) throws IOException {
46 | out.write(buf, off, len);
47 | }
48 |
49 | /**
50 | * Closes the underlying output stream.
51 | */
52 | public void close() throws IOException {
53 | out.close();
54 | }
55 |
56 | @Override
57 | protected final void parse() {
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/PTPBusyException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * cameracontrol
3 | * Copyright (C) 2010 Stefano Fornari
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under
6 | * the terms of the GNU Affero General Public License version 3 as published by
7 | * the Free Software Foundation with the addition of the following permission
8 | * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
9 | * WORK IN WHICH THE COPYRIGHT IS OWNED BY Stefano Fornari, Stefano Fornari
10 | * DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
11 | *
12 | * This program is distributed in the hope that it will be useful, but WITHOUT
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 | * details.
16 | *
17 | * You should have received a copy of the GNU Affero General Public License
18 | * along with this program; if not, see http://www.gnu.org/licenses or write to
19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 | * MA 02110-1301 USA.
21 | */
22 |
23 | package cn.rainx.ptp.usbcamera;
24 |
25 | /**
26 | *
27 | * @author ste
28 | */
29 | public class PTPBusyException extends PTPException {
30 |
31 | /**
32 | * Creates a new instance of PTPBusyException
without detail message.
33 | */
34 | public PTPBusyException() {
35 | super("Device is busy");
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/PTPException.java:
--------------------------------------------------------------------------------
1 | // Copyright 2010 by Stefano Fornari
2 | //
3 | // This program is free software; you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation; either version 2 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program; if not, write to the Free Software
15 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | //
17 | package cn.rainx.ptp.usbcamera;
18 |
19 | public class PTPException extends Exception {
20 |
21 | private int errorCode;
22 |
23 | public PTPException() {
24 | this("");
25 | }
26 |
27 | public PTPException(int errorCode) {
28 | this("", null, errorCode);
29 | }
30 |
31 | public PTPException(String string) {
32 | this(string, null);
33 | }
34 |
35 | public PTPException(String string, int errorCode) {
36 | this(string, null, errorCode);
37 | }
38 |
39 | public PTPException(String string, Throwable t) {
40 | this(string, t, Response.Undefined);
41 | }
42 |
43 | public PTPException(String string, Throwable t, int errorCode) {
44 | super(string, t);
45 | this.errorCode = errorCode;
46 | }
47 |
48 | public int getErrorCode() {
49 | return errorCode;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/PTPOpenSessionException.java:
--------------------------------------------------------------------------------
1 | package cn.rainx.ptp.usbcamera;
2 |
3 | /**
4 | * Created by rainx on 2017/6/11.
5 | */
6 |
7 | public class PTPOpenSessionException extends PTPException {
8 | public PTPOpenSessionException(String string, int code) {
9 | super(string, code);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/PTPUnsupportedException.java:
--------------------------------------------------------------------------------
1 | // Copyright 2010 by Stefano Fornari
2 | //
3 | // This program is free software; you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation; either version 2 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program; if not, write to the Free Software
15 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | //
17 | package cn.rainx.ptp.usbcamera;
18 |
19 | public class PTPUnsupportedException extends PTPException {
20 |
21 | public PTPUnsupportedException(String string) {
22 | super(string);
23 | }
24 |
25 | public PTPUnsupportedException(String string, Throwable t) {
26 | super(string, t);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/ParamVector.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000 by David Brownell
2 | //
3 | // This program is free software; you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation; either version 2 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program; if not, write to the Free Software
15 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | //
17 |
18 | package cn.rainx.ptp.usbcamera;
19 |
20 | import java.io.PrintStream;
21 |
22 |
23 | /**
24 | * This class is used for PTP messages consisting of only a set of
25 | * thirty-two bit parameters, such as commands, responses, and events.
26 | *
27 | * @version $Id: ParamVector.java,v 1.4 2001/04/12 23:13:00 dbrownell Exp $
28 | * @author David Brownell
29 | */
30 | public class ParamVector extends Container
31 | {
32 | ParamVector (byte buf [], NameFactory f)
33 | { super (buf, f); }
34 |
35 | ParamVector (byte buf [], int len, NameFactory f)
36 | { super (buf, len, f); }
37 |
38 | /** Returns the first positional parameter. */
39 | public final int getParam1 ()
40 | { return getS32 (12); }
41 |
42 | /** Returns the second positional parameter. */
43 | public final int getParam2 ()
44 | { return getS32 (16); }
45 |
46 | /** Returns the third positional parameter. */
47 | public final int getParam3 ()
48 | { return getS32 (20); }
49 |
50 | /** Returns the number of parameters in this data block */
51 | public final int getNumParams ()
52 | { return (length - MIN_LEN) / 4; }
53 |
54 |
55 | // no params
56 | static final int MIN_LEN = HDR_LEN;
57 |
58 | // allegedly some responses could have five params
59 | static final int MAX_LEN = 32;
60 |
61 |
62 | // NOTE: params in the spec are numbered from one, not zero
63 | int getParam (int i)
64 | { return getS32 (12 + (4 * i)); }
65 |
66 | void dump (PrintStream out)
67 | {
68 | out.print (this.toString ());
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/Response.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000 by David Brownell
2 | //
3 | // This program is free software; you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation; either version 2 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program; if not, write to the Free Software
15 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | //
17 |
18 | package cn.rainx.ptp.usbcamera;
19 |
20 |
21 | /**
22 | * The final phase of a PTP transaction sends a command's response from
23 | * the responder to the initiator. These include response codes, and are
24 | * described in chapter 11 of the PTP specification.
25 | *
26 | * @version $Id: Response.java,v 1.2 2001/04/12 23:13:00 dbrownell Exp $
27 | * @author David Brownell
28 | */
29 | public class Response extends ParamVector
30 | {
31 | Response (byte buf [], NameFactory f)
32 | { super (buf, f); }
33 |
34 | public Response (byte buf [], int len, NameFactory f)
35 | { super (buf, len, f); }
36 |
37 |
38 | /** ResponseCode: */
39 | public static final int Undefined = 0x2000;
40 | /** ResponseCode: */
41 | public static final int OK = 0x2001;
42 | /** ResponseCode: */
43 | public static final int GeneralError = 0x2002;
44 | /** ResponseCode: */
45 | public static final int SessionNotOpen = 0x2003;
46 |
47 | /** ResponseCode: */
48 | public static final int InvalidTransactionID = 0x2004;
49 | /** ResponseCode: */
50 | public static final int OperationNotSupported = 0x2005;
51 | /** ResponseCode: */
52 | public static final int ParameterNotSupported = 0x2006;
53 | /** ResponseCode: */
54 | public static final int IncompleteTransfer = 0x2007;
55 |
56 | /** ResponseCode: */
57 | public static final int InvalidStorageID = 0x2008;
58 | /** ResponseCode: */
59 | public static final int InvalidObjectHandle = 0x2009;
60 | /** ResponseCode: */
61 | public static final int DevicePropNotSupported = 0x200a;
62 | /** ResponseCode: */
63 | public static final int InvalidObjectFormatCode = 0x200b;
64 |
65 | /** ResponseCode: */
66 | public static final int StoreFull = 0x200c;
67 | /** ResponseCode: */
68 | public static final int ObjectWriteProtected = 0x200d;
69 | /** ResponseCode: */
70 | public static final int StoreReadOnly = 0x200e;
71 | /** ResponseCode: */
72 | public static final int AccessDenied = 0x200f;
73 |
74 |
75 | /** ResponseCode: */
76 | public static final int NoThumbnailPresent = 0x2010;
77 | /** ResponseCode: */
78 | public static final int SelfTestFailed = 0x2011;
79 | /** ResponseCode: */
80 | public static final int PartialDeletion = 0x2012;
81 | /** ResponseCode: */
82 | public static final int StoreNotAvailable = 0x2013;
83 |
84 | /** ResponseCode: */
85 | public static final int SpecificationByFormatUnsupported = 0x2014;
86 | /** ResponseCode: */
87 | public static final int NoValidObjectInfo = 0x2015;
88 | /** ResponseCode: */
89 | public static final int InvalidCodeFormat = 0x2016;
90 | /** ResponseCode: */
91 | public static final int UnknownVendorCode = 0x2017;
92 |
93 | /** ResponseCode: */
94 | public static final int CaptureAlreadyTerminated = 0x2018;
95 | /** ResponseCode: */
96 | public static final int DeviceBusy = 0x2019;
97 | /** ResponseCode: */
98 | public static final int InvalidParentObject = 0x201a;
99 | /** ResponseCode: */
100 | public static final int InvalidDevicePropFormat = 0x201b;
101 |
102 | /** ResponseCode: */
103 | public static final int InvalidDevicePropValue = 0x201c;
104 | /** ResponseCode: */
105 | public static final int InvalidParameter = 0x201d;
106 | /** ResponseCode: */
107 | public static final int SessionAlreadyOpen = 0x201e;
108 | /** ResponseCode: */
109 | public static final int TransactionCanceled = 0x201f;
110 |
111 | /** ResponseCode: */
112 | public static final int SpecificationOfDestinationUnsupported = 0x2020;
113 |
114 |
115 | public String getCodeName (int code)
116 | {
117 | return factory.getResponseString (code);
118 | }
119 |
120 | public static String _getResponseString (int code)
121 | {
122 | switch (code) {
123 | case Undefined: return "Undefined";
124 | case OK: return "OK";
125 | case GeneralError: return "GeneralError";
126 | case SessionNotOpen: return "SessionNotOpen";
127 |
128 | case InvalidTransactionID: return "InvalidTransactionID";
129 | case OperationNotSupported: return "OperationNotSupported";
130 | case ParameterNotSupported: return "ParameterNotSupported";
131 | case IncompleteTransfer: return "IncompleteTransfer";
132 |
133 | case InvalidStorageID: return "InvalidStorageID";
134 | case InvalidObjectHandle: return "InvalidObjectHandle";
135 | case DevicePropNotSupported: return "DevicePropNotSupported";
136 | case InvalidObjectFormatCode: return "InvalidObjectFormatCode";
137 |
138 | case StoreFull: return "StoreFull";
139 | case ObjectWriteProtected: return "ObjectWriteProtected";
140 | case StoreReadOnly: return "StoreReadOnly";
141 | case AccessDenied: return "AccessDenied";
142 |
143 | case NoThumbnailPresent: return "NoThumbnailPresent";
144 | case SelfTestFailed: return "SelfTestFailed";
145 | case PartialDeletion: return "PartialDeletion";
146 | case StoreNotAvailable: return "StoreNotAvailable";
147 |
148 | case SpecificationByFormatUnsupported:
149 | return "SpecificationByFormatUnsupported";
150 | case NoValidObjectInfo: return "NoValidObjectInfo";
151 | case InvalidCodeFormat: return "InvalidCodeFormat";
152 | case UnknownVendorCode: return "UnknownVendorCode";
153 |
154 | case CaptureAlreadyTerminated: return "CaptureAlreadyTerminated";
155 | case DeviceBusy: return "DeviceBusy";
156 | case InvalidParentObject: return "InvalidParentObject";
157 | case InvalidDevicePropFormat: return "InvalidDevicePropFormat";
158 |
159 | case InvalidDevicePropValue: return "InvalidDevicePropValue";
160 | case InvalidParameter: return "InvalidParameter";
161 | case SessionAlreadyOpen: return "SessionAlreadyOpen";
162 | case TransactionCanceled: return "TransactionCanceled";
163 |
164 | case SpecificationOfDestinationUnsupported:
165 | return "SpecificationOfDestinationUnsupported";
166 | }
167 | return ("0x" + Integer.toHexString (code)).intern ();
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/Session.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000 by David Brownell
2 | //
3 | // This program is free software; you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation; either version 2 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program; if not, write to the Free Software
15 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | //
17 |
18 | package cn.rainx.ptp.usbcamera;
19 |
20 |
21 | /**
22 | * Encapsulates the session between a PTP initiator and responder.
23 | *
24 | * @version $Id: Session.java,v 1.3 2001/04/12 23:13:00 dbrownell Exp $
25 | * @author David Brownell
26 | */
27 | public class Session
28 | {
29 | private int sessionId;
30 | private int xid;
31 | private boolean active;
32 | private NameFactory factory;
33 |
34 | public Session () { }
35 |
36 | void setFactory (NameFactory f) { factory = f; }
37 |
38 | NameFactory getFactory () { return factory; }
39 |
40 | int getNextXID ()
41 | { return (active ? xid++ : 0); }
42 |
43 | int getNextSessionID ()
44 | {
45 | if (!active)
46 | return ++sessionId;
47 | throw new IllegalStateException("already active");
48 | }
49 |
50 | boolean isActive ()
51 | { return active; }
52 |
53 | void open ()
54 | { xid = 1; active = true; }
55 |
56 | void close ()
57 | { active = false; }
58 |
59 | int getSessionId ()
60 | { return sessionId; }
61 |
62 | // track objects and their info by handles;
63 | // hookup to marshaling system and event framework
64 | }
65 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/StorageInfo.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000 by David Brownell
2 | //
3 | // This program is free software; you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation; either version 2 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program; if not, write to the Free Software
15 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | //
17 |
18 | package cn.rainx.ptp.usbcamera;
19 |
20 | import android.widget.TextView;
21 |
22 | import java.io.PrintStream;
23 |
24 | /**
25 | * StorageInfo provides information such as the type and capacity of
26 | * storage media, whether it's removable, and more.
27 | *
28 | * @version $Id: StorageInfo.java,v 1.5 2001/04/12 23:13:00 dbrownell Exp $
29 | * @author David Brownell
30 | */
31 | public class StorageInfo extends Data
32 | {
33 | int storageType;
34 | int filesystemType;
35 | int accessCapability;
36 | long maxCapacity;
37 |
38 | long freeSpaceInBytes;
39 | int freeSpaceInImages;
40 | String storageDescription;
41 | String volumeLabel;
42 |
43 | StorageInfo (NameFactory f) { super (f); }
44 |
45 | protected void parse()
46 | {
47 | super.parse ();
48 |
49 | storageType = nextU16 ();
50 | filesystemType = nextU16 ();
51 | accessCapability = nextU16 ();
52 | maxCapacity = /* unsigned */ nextS64 ();
53 | freeSpaceInBytes = /* unsigned */ nextS64 ();
54 | freeSpaceInImages = /* unsigned */ nextS32 ();
55 | storageDescription = nextString ();
56 | volumeLabel = nextString ();
57 | }
58 |
59 | void line (PrintStream out)
60 | {
61 | String temp;
62 |
63 | switch (storageType) {
64 | case 0: temp = "undefined"; break;
65 | case 1: temp = "Fixed ROM"; break;
66 | case 2: temp = "Removable ROM"; break;
67 | case 3: temp = "Fixed RAM"; break;
68 | case 4: temp = "Removable RAM"; break;
69 | default:
70 | temp = "Reserved-0x" + Integer.toHexString (storageType);
71 | }
72 | out.println ("Storage Type: " + temp);
73 | }
74 |
75 | void line (TextView tv)
76 | {
77 | String temp;
78 |
79 | switch (storageType) {
80 | case 0: temp = "undefined"; break;
81 | case 1: temp = "Fixed ROM"; break;
82 | case 2: temp = "Removable ROM"; break;
83 | case 3: temp = "Fixed RAM"; break;
84 | case 4: temp = "Removable RAM"; break;
85 | default:
86 | temp = "Reserved-0x" + Integer.toHexString (storageType);
87 | }
88 | tv.append ("Storage Type: " + temp +" \n");
89 | }
90 |
91 | void dump (PrintStream out)
92 | {
93 | String temp;
94 |
95 | super.dump (out);
96 | out.println ("StorageInfo:");
97 | line (out);
98 |
99 | switch (filesystemType) {
100 | case 0: temp = "undefined"; break;
101 | case 1: temp = "flat"; break;
102 | case 2: temp = "hierarchical"; break;
103 | case 3: temp = "dcf"; break;
104 | default:
105 | if ((filesystemType & 0x8000) != 0)
106 | temp = "Reserved-0x";
107 | else
108 | temp = "Vendor-0x";
109 | temp += Integer.toHexString (filesystemType);
110 | }
111 | out.println ("Filesystem Type: " + temp);
112 |
113 | // access: rw, ro, or ro "with object deletion"
114 |
115 | // CF card sizes are "marketing megabytes", not real ones
116 | if (maxCapacity != ~0)
117 | out.println ("Capacity: "
118 | + maxCapacity + " bytes ("
119 | + ((maxCapacity + 500000)/1000000) + " MB)"
120 | );
121 | if (freeSpaceInBytes != ~0)
122 | out.println ("Free space: "
123 | + freeSpaceInBytes + " bytes ("
124 | + ((freeSpaceInBytes + 500000)/1000000) + " MB)"
125 | );
126 | if (freeSpaceInImages != ~0)
127 | out.println ("Free space in Images: " + freeSpaceInImages);
128 |
129 | if (storageDescription != null)
130 | out.println ("Description: " + storageDescription);
131 | if (volumeLabel != null)
132 | out.println ("Volume Label: " + volumeLabel);
133 | }
134 |
135 |
136 | void showInTextView (TextView tv)
137 | {
138 | String temp;
139 |
140 |
141 | tv.setText ("StorageInfo:");
142 | tv.append ("\n");
143 | line (tv);
144 |
145 | switch (filesystemType) {
146 | case 0: temp = "undefined"; break;
147 | case 1: temp = "flat"; break;
148 | case 2: temp = "hierarchical"; break;
149 | case 3: temp = "dcf"; break;
150 | default:
151 | if ((filesystemType & 0x8000) != 0)
152 | temp = "Reserved-0x";
153 | else
154 | temp = "Vendor-0x";
155 | temp += Integer.toHexString (filesystemType);
156 | }
157 | tv.append ("\n");
158 | tv.append ("Filesystem Type: " + temp);
159 |
160 | // access: rw, ro, or ro "with object deletion"
161 |
162 | // CF card sizes are "marketing megabytes", not real ones
163 | if (maxCapacity != ~0)
164 | {
165 | tv.append ("\n");
166 | tv.append ("Capacity: "
167 | + maxCapacity + " bytes ("
168 | + ((maxCapacity + 500000)/1000000) + " MB)"
169 | );
170 | }
171 | if (freeSpaceInBytes != ~0)
172 | {
173 | tv.append ("\n");
174 | tv.append ("Free space: "
175 | + freeSpaceInBytes + " bytes ("
176 | + ((freeSpaceInBytes + 500000)/1000000) + " MB)"
177 | );
178 | }
179 | if (freeSpaceInImages != ~0)
180 | {
181 | tv.append ("\n");
182 | tv.append ("Free space in Images: " + freeSpaceInImages);
183 | }
184 | if (storageDescription != null)
185 | {
186 | tv.append ("\n");
187 | tv.append ("Description: " + storageDescription);
188 | }
189 | if (volumeLabel != null)
190 | {
191 | tv.append ("\n");
192 | tv.append ("Volume Label: " + volumeLabel);
193 | }
194 | }
195 |
196 |
197 | public int getStorageType() {
198 | return storageType;
199 | }
200 |
201 | public int getFilesystemType() {
202 | return filesystemType;
203 | }
204 |
205 | public int getAccessCapability() {
206 | return accessCapability;
207 | }
208 |
209 | public long getMaxCapacity() {
210 | return maxCapacity;
211 | }
212 |
213 | public long getFreeSpaceInBytes() {
214 | return freeSpaceInBytes;
215 | }
216 |
217 | public int getFreeSpaceInImages() {
218 | return freeSpaceInImages;
219 | }
220 |
221 | public String getStorageDescription() {
222 | return storageDescription;
223 | }
224 |
225 | public String getVolumeLabel() {
226 | return volumeLabel;
227 | }
228 | }
229 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/eos/EosEvent.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2010 by Stefano Fornari
2 | //
3 | // This program is free software; you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation; either version 2 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program; if not, write to the Free Software
15 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | */
17 |
18 | package cn.rainx.ptp.usbcamera.eos;
19 |
20 | import java.util.ArrayList;
21 | import java.util.List;
22 |
23 |
24 | /**
25 | *
26 | * @author ste
27 | */
28 | public class EosEvent implements EosEventConstants {
29 |
30 | /**
31 | * Event code
32 | */
33 | private int code;
34 |
35 | /**
36 | * Params
37 | */
38 | private List params;
39 |
40 | /**
41 | * Creates a new parser with the given data
42 | *
43 | * @param data the events data - NOT NULL
44 | */
45 | public EosEvent() {
46 | params = new ArrayList();
47 | }
48 |
49 | public void setCode(int code) {
50 | this.code = code;
51 | }
52 |
53 | public int getCode() {
54 | return code;
55 | }
56 |
57 | /**
58 | * @param i the parameter index
59 | * @param param the param to set
60 | */
61 | public void setParam(int i, Object value) {
62 | if (i<0) {
63 | throw new IllegalArgumentException("param index cannot be < 0");
64 | }
65 | if (params.size() <= i) {
66 | ArrayList newParams = new ArrayList(i);
67 | newParams.addAll(params);
68 | params = newParams;
69 | for (int j=params.size(); j getParamCount())) {
82 | throw new IllegalArgumentException(
83 | "index " + i + " out of range (0-" + getParamCount() + ")"
84 | );
85 | }
86 | return params.get(i-1);
87 | }
88 |
89 | public int getIntParam(int i) {
90 | return ((Integer)getParam(i)).intValue();
91 | }
92 |
93 | public String getStringParam(int i) {
94 | return (String)getParam(i);
95 | }
96 |
97 | /**
98 | *
99 | * @return the number of parameters in this event
100 | */
101 | public int getParamCount() {
102 | return params.size();
103 | }
104 |
105 | public static String getEventName (int code){
106 | switch (code) {
107 | case EosEventRequestGetEvent : return "EosEventRequestGetEvent";
108 | case EosEventObjectAddedEx : return "EosEventObjectAddedEx";
109 | case EosEventObjectRemoved : return "EosEventObjectRemoved";
110 | case EosEventRequestGetObjectInfoEx : return "EosEventRequestGetObjectInfoEx";
111 | case EosEventStorageStatusChanged : return "EosEventStorageStatusChanged";
112 | case EosEventStorageInfoChanged : return "EosEventStorageInfoChanged";
113 | case EosEventRequestObjectTransfer : return "EosEventRequestObjectTransfer";
114 | case EosEventObjectInfoChangedEx : return "EosEventObjectInfoChangedEx";
115 | case EosEventObjectContentChanged : return "EosEventObjectContentChanged";
116 | case EosEventPropValueChanged : return "EosEventPropValueChanged";
117 | case EosEventAvailListChanged : return "EosEventAvailListChanged";
118 | case EosEventCameraStatusChanged : return "EosEventCameraStatusChanged";
119 | case EosEventWillSoonShutdown : return "EosEventWillSoonShutdown";
120 | case EosEventShutdownTimerUpdated : return "EosEventShutdownTimerUpdated";
121 | case EosEventRequestCancelTransfer : return "EosEventRequestCancelTransfer";
122 | case EosEventRequestObjectTransferDT : return "EosEventRequestObjectTransferDT";
123 | case EosEventRequestCancelTransferDT : return "EosEventRequestCancelTransferDT";
124 | case EosEventStoreAdded : return "EosEventStoreAdded";
125 | case EosEventStoreRemoved : return "EosEventStoreRemoved";
126 | case EosEventBulbExposureTime : return "EosEventBulbExposureTime";
127 | case EosEventRecordingTime : return "EosEventRecordingTime";
128 | case EosEventAfResult : return "EosEventRequestObjectTransferTS";
129 | case EosEventRequestObjectTransferTS : return "EosEventAfResult";
130 | }
131 | return "0x" + Integer.toHexString(code);
132 | }
133 |
134 |
135 | public String toString() {
136 | return "event name is : " +
137 | getEventName(getCode()) +
138 | "first event param is" +
139 | getIntParam(1);
140 | }
141 |
142 | }
143 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/eos/EosEventFormat.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2010 by Stefano Fornari
2 | *
3 | * This program is free software; you can redistribute it and/or modify
4 | * it under the terms of the GNU General Public License as published by
5 | * the Free Software Foundation; either version 2 of the License, or
6 | * (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License
14 | * along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | */
17 | package cn.rainx.ptp.usbcamera.eos;
18 |
19 | import java.lang.reflect.Field;
20 |
21 | /**
22 | * This class formats an EosEvent to a string
23 | *
24 | * @author stefano fornari
25 | */
26 | public class EosEventFormat implements EosEventConstants {
27 | public static String format(EosEvent e) {
28 | StringBuilder sb = new StringBuilder();
29 |
30 | int eventCode = e.getCode();
31 |
32 | sb.append(getEventName(eventCode));
33 | sb.append(" [ ");
34 | if (eventCode == EosEventPropValueChanged) {
35 | int propCode = e.getIntParam(1);
36 | sb.append(getPropertyName(propCode))
37 | .append(": ");
38 |
39 | if ((propCode >= EosPropPictureStyleStandard) &&
40 | (propCode <= EosPropPictureStyleUserSet3)) {
41 | sb.append("(Sharpness: ")
42 | .append(e.getIntParam(4))
43 | .append(", Contrast: ")
44 | .append(e.getIntParam(3));
45 | if (((Boolean)e.getParam(2)).booleanValue()) {
46 | sb.append(", Filter effect: ")
47 | .append(getFilterEffect(e.getIntParam(5)))
48 | .append(", Toning effect: ")
49 | .append(getToningEffect(e.getIntParam(6)));
50 | } else {
51 | sb.append(", Saturation: ")
52 | .append(e.getIntParam(5))
53 | .append(", Color tone: ")
54 | .append(e.getIntParam(6));
55 | }
56 | sb.append(")");
57 | } else {
58 | if (e.getParamCount()>1) {
59 | sb.append(e.getIntParam(2));
60 | }
61 | }
62 | } else if (eventCode == EosEventObjectAddedEx) {
63 | sb.append(formatEosEventObjectAddedEx(e));
64 | }
65 | sb.append(" ]");
66 |
67 | return sb.toString();
68 | }
69 |
70 | /**
71 | * Returns the printable name of the given event
72 | *
73 | * @param code event code
74 | *
75 | * @return the printable name of the given event
76 | */
77 | public static String getEventName(int code) {
78 | Field[] fields = EosEventConstants.class.getDeclaredFields();
79 |
80 | for (Field f: fields) {
81 | String name = f.getName();
82 | if (name.startsWith("EosEvent")) {
83 | try {
84 | if (f.getInt(null) == code) {
85 | return name;
86 | }
87 | } catch (Exception e) {
88 | //
89 | // Nothing to do
90 | //
91 | }
92 | }
93 | }
94 | return "Unknown";
95 | }
96 |
97 | /**
98 | * Returns the printable name of the given property
99 | *
100 | * @param code property code
101 | *
102 | * @return the printable name of the given property
103 | */
104 | public static String getPropertyName(int code) {
105 | return getCodeName("EosProp", code);
106 | }
107 |
108 | /**
109 | * Returns the printable name of the given image format
110 | *
111 | * @param code image format code
112 | *
113 | * @return the printable name of the given image format
114 | */
115 | public static String getImageFormatName(int code) {
116 | return getCodeName("ImageFormat", code);
117 | }
118 |
119 | /**
120 | * Returns the filter effect name given the code. Names are:
121 | * 0:None, 1:Yellow, 2:Orange, 3:Red, 4:Green
122 | *
123 | * @param code the filter effect code (0-4)
124 | *
125 | * @return the filter effect name
126 | */
127 | public static String getFilterEffect(int code) {
128 | if ((code < 0) || (code > 4)) {
129 | throw new IllegalArgumentException("code must be in he range 0-4");
130 | }
131 |
132 | switch (code) {
133 | case 0: return "None";
134 | case 1: return "Yellow";
135 | case 2: return "Orange";
136 | case 3: return "Red";
137 | case 4: return "Green";
138 | }
139 |
140 | //
141 | // We should never get here
142 | //
143 | return "Unknown";
144 | }
145 |
146 | /**
147 | * Returns the toning effect name given the code. Names are:
148 | * 0:None, 1:Sepia, 2:Blue, 3:Purple, 4:Green
149 | *
150 | * @param code the toning effect code (0-4)
151 | *
152 | * @return the toning effect name
153 | */
154 | public static String getToningEffect(int code) {
155 | if ((code < 0) || (code > 4)) {
156 | throw new IllegalArgumentException("code must be in he range 0-4");
157 | }
158 |
159 | switch (code) {
160 | case 0: return "None";
161 | case 1: return "Sepia";
162 | case 2: return "Blue";
163 | case 3: return "Purple";
164 | case 4: return "Green";
165 | }
166 |
167 | //
168 | // We should never get here
169 | //
170 | return "Unknown";
171 | }
172 |
173 | // --------------------------------------------------------- Private methods
174 |
175 | private static String formatEosEventObjectAddedEx(EosEvent event) {
176 | return String.format(
177 | "Filename: %s, Size(bytes): %d, ObjectID: 0x%08X, StorageID: 0x%08X, ParentID: 0x%08X, Format: %s",
178 | event.getStringParam(6),
179 | event.getIntParam(5),
180 | event.getIntParam(1),
181 | event.getIntParam(2),
182 | event.getIntParam(3),
183 | getImageFormatName(event.getIntParam(4))
184 | );
185 | }
186 |
187 | /**
188 | * Looks up and returns the name of the code give if there is a constant
189 | * field in EosEventConstants which starts with the given prefix
190 | *
191 | * @param prefix the field name prefix
192 | * @param code image format code
193 | *
194 | * @return the printable name of the given code
195 | */
196 | private static String getCodeName(String prefix, int code) {
197 | Field[] fields = EosEventConstants.class.getDeclaredFields();
198 |
199 | for (Field f: fields) {
200 | String name = f.getName();
201 | if (name.startsWith(prefix)) {
202 | try {
203 | if (f.getInt(null) == code) {
204 | return name.substring(prefix.length());
205 | }
206 | } catch (Exception e) {
207 | //
208 | // Nothing to do
209 | //
210 | }
211 | }
212 | }
213 | return "Unknown";
214 | }
215 |
216 | }
217 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/eos/EosEventParser.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2010 by Stefano Fornari
2 | *
3 | * This program is free software; you can redistribute it and/or modify
4 | * it under the terms of the GNU General Public License as published by
5 | * the Free Software Foundation; either version 2 of the License, or
6 | * (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License
14 | * along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | */
17 |
18 | package cn.rainx.ptp.usbcamera.eos;
19 |
20 | import android.util.Log;
21 |
22 | import java.io.IOException;
23 | import java.io.InputStream;
24 |
25 | import cn.rainx.ptp.usbcamera.PTPException;
26 | import cn.rainx.ptp.usbcamera.PTPUnsupportedException;
27 |
28 | /**
29 | * This class parses a stream of bytes as a sequence of events accordingly
30 | * to how Canon EOS returns events.
31 | *
32 | * The event information is returned in a standard PTP data packet as a number
33 | * of records followed by an empty record at the end of the packet. Each record
34 | * consists of multiple four-byte fields and always starts with record length
35 | * field. Further structure of the record depends on the device property code
36 | * which always goes in the third field. The empty record consists of the size
37 | * field and four byte empty field, which is always zero.
38 | *
39 | * @author stefano fornari
40 | */
41 | public class EosEventParser implements EosEventConstants {
42 |
43 | /**
44 | * The stream data are read from
45 | */
46 | private InputStream is;
47 |
48 | /**
49 | * Creates a new parser to parse the given input stream
50 | *
51 | * @param is
52 | */
53 | public EosEventParser(InputStream is) {
54 | if (is == null) {
55 | throw new IllegalArgumentException("The input stream cannot be null");
56 | }
57 |
58 | this.is = is;
59 | }
60 |
61 | /**
62 | * Returns true is there are events in the stream (and the stream is still
63 | * open), false otherwise.
64 | *
65 | * @return true is there are events in the stream (and the stream is still
66 | * open), false otherwise.
67 | */
68 | public boolean hasEvents() {
69 | try {
70 | // Log.d("EventParser", " available: " +is.available());
71 | if (is.available() <= 0) {
72 | return false;
73 | }
74 | } catch (IOException e) {
75 | return false;
76 | }
77 |
78 | return true;
79 | }
80 |
81 | /**
82 | * Returns the next event in the stream.
83 | *
84 | * @return the next event in the stream.
85 | *
86 | * @throws PTPException in case of errors
87 | */
88 | public EosEvent getNextEvent() throws PTPException {
89 | EosEvent event = new EosEvent();
90 |
91 | try {
92 | int len = getNextS32(); // len
93 | // Log.d("EventParser", " Len: " +len);
94 | if (len < 0x8) {
95 | throw new PTPUnsupportedException("Unsupported event (size<8 ???)");
96 | }
97 | int code = getNextS32();
98 | event.setCode(code);
99 | Log.d("EventParser", " Event len: " +len +", Code: 0x" + String.format("%04x", code) +" " +EosEvent.getEventName(code));
100 | parseParameters(event, len-8);
101 | // Log.d("EventParser", " Event: params " +event.getParamCount());
102 | for (int i = 1; i<= event.getParamCount(); i++) {
103 | Object p = event.getParam(i);
104 | if (p instanceof String) {
105 | Log.d("EventParser", " params " + i + ": " + String.format("%s", p));
106 | } else if (p instanceof Boolean) {
107 | Log.d("EventParser", " params " + i + ": " + String.format("%b", p));
108 | } else{
109 | Log.d("EventParser", " params " + i + ": " + String.format("0x%04x %d", p, p));
110 | }
111 | }
112 | } catch (IOException e) {
113 | Log.d ("EventParser", " Error reading event stream");
114 | throw new PTPException("Error reading event stream", e);
115 | }
116 |
117 | return event;
118 | }
119 |
120 |
121 | // --------------------------------------------------------- Private methods
122 |
123 | private void parseParameters(EosEvent event, int len)
124 | throws PTPException, IOException {
125 | int code = event.getCode();
126 |
127 | if (code == EosEventPropValueChanged) {
128 | parsePropValueChangedParameters(event);
129 | } else if (code == EosEventShutdownTimerUpdated) {
130 | //
131 | // No parameters
132 | //
133 | } else if (code == EosEventCameraStatusChanged) {
134 | event.setParam(1, getNextS32());
135 | } else if (code == EosEventObjectAddedEx) {
136 | parseEosEventObjectAddedEx(event);
137 | } else{
138 | is.skip(len);
139 | throw new PTPUnsupportedException("Unsupported event");
140 | }
141 | }
142 |
143 | private void parsePropValueChangedParameters(EosEvent event)
144 | throws IOException {
145 | int property = getNextS32();
146 | event.setParam(1, property); // property changed
147 |
148 | if ((property >= EosPropPictureStyleStandard) &&
149 | (property <= EosPropPictureStyleUserSet3)) {
150 | boolean monochrome = (property == EosPropPictureStyleMonochrome);
151 | int size = getNextS32();
152 | if (size > 0x1C) {
153 | //
154 | // It is a EosPropPictureStyleUserXXX, let's read the type (then
155 | // we do not use it)
156 | //
157 | monochrome = (getNextS32() == EosPropPictureStyleUserTypeMonochrome);
158 | }
159 | event.setParam(2, (monochrome) ? Boolean.TRUE : Boolean.FALSE);
160 | event.setParam(3, getNextS32()); // contrast
161 | event.setParam(4, getNextS32()); // sharpness
162 | if (monochrome) {
163 | getNextS32();
164 | getNextS32();
165 | event.setParam(5, getNextS32()); // filter effect
166 | event.setParam(6, getNextS32()); // toning effect
167 | } else {
168 | event.setParam(5, getNextS32()); // saturation
169 | event.setParam(6, getNextS32()); // color tone
170 | getNextS32();
171 | getNextS32();
172 | }
173 | } else {
174 | //
175 | // default
176 | //
177 | event.setParam(2, getNextS32());
178 | }
179 |
180 | }
181 |
182 | private void parseEosEventObjectAddedEx(EosEvent event)
183 | throws IOException {
184 | event.setParam(1, getNextS32() ); // object id
185 | event.setParam(2, getNextS32() ); // storage id
186 | event.setParam(4, getNextS16() ); // format
187 | is.skip(10);
188 | event.setParam(5, getNextS32() ); // size
189 | event.setParam(3, getNextS32() ); // parent object id
190 | is.skip(4); // unknown
191 | event.setParam(6, getNextString()); // file name
192 | is.skip(4);
193 | }
194 |
195 | /**
196 | * Reads and return the next signed 32 bit integer read from the input
197 | * stream.
198 | *
199 | * @return the next signed 32 bit integer in the stream
200 | *
201 | * @throws IOException in case of IO errors
202 | */
203 | private final int getNextS32() throws IOException {
204 | int retval;
205 |
206 | retval = (0xff & is.read()) ;
207 | retval |= (0xff & is.read()) << 8;
208 | retval |= (0xff & is.read()) << 16;
209 | retval |= is.read() << 24;
210 |
211 | return retval;
212 | }
213 |
214 | /**
215 | * Reads and return the next signed 16 bit integer read from the input
216 | * stream.
217 | *
218 | * @return the next signed 16 bit integer in the stream
219 | *
220 | * @throws IOException in case of IO errors
221 | */
222 | private final int getNextS16() throws IOException {
223 | int retval;
224 |
225 | retval = (0xff & is.read()) ;
226 | retval |= (0xff & is.read()) << 8;
227 |
228 | return retval;
229 | }
230 |
231 | /**
232 | * Reads and return the next string read from the input stream. Strings are
233 | * zero (32 bit) terminated string
234 | *
235 | * @return the next string in the stream
236 | *
237 | * @throws IOException in case of IO errors
238 | */
239 | private final String getNextString() throws IOException {
240 | StringBuilder retval = new StringBuilder();
241 |
242 | char c = 0;
243 | while ((c = (char)is.read()) != 0) {
244 | retval.append(c);
245 | }
246 |
247 | //
248 | // At this point we read the string and one zero. We need to read the
249 | // remaining 3 zeros
250 | //
251 | is.skip(3);
252 |
253 | return retval.toString();
254 | }
255 |
256 | }
257 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/nikon/NikonEvent.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2010 by Stefano Fornari
2 | //
3 | // This program is free software; you can redistribute it and/or modify
4 | // it under the terms of the GNU General Public License as published by
5 | // the Free Software Foundation; either version 2 of the License, or
6 | // (at your option) any later version.
7 | //
8 | // This program is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with this program; if not, write to the Free Software
15 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | */
17 |
18 | package cn.rainx.ptp.usbcamera.nikon;
19 |
20 | import java.util.ArrayList;
21 | import java.util.List;
22 |
23 |
24 | /**
25 | *
26 | * @author ste
27 | */
28 | public class NikonEvent implements NikonEventConstants {
29 |
30 | /**
31 | * Event code
32 | */
33 | private int code;
34 |
35 | /**
36 | * Params
37 | */
38 | private List params;
39 |
40 | /**
41 | * Creates a new parser with the given data
42 | *
43 | * @param data the events data - NOT NULL
44 | */
45 | public NikonEvent() {
46 | params = new ArrayList();
47 | }
48 |
49 | public void setCode(int code) {
50 | this.code = code;
51 | }
52 |
53 | public int getCode() {
54 | return code;
55 | }
56 |
57 | /**
58 | * @param i the parameter index
59 | * @param param the param to set
60 | */
61 | public void setParam(int i, Object value) {
62 | if (i<0) {
63 | throw new IllegalArgumentException("param index cannot be < 0");
64 | }
65 | if (params.size() <= i) {
66 | ArrayList newParams = new ArrayList(i);
67 | newParams.addAll(params);
68 | params = newParams;
69 | for (int j=params.size(); j getParamCount())) {
82 | throw new IllegalArgumentException(
83 | "index " + i + " out of range (0-" + getParamCount() + ")"
84 | );
85 | }
86 | return params.get(i-1);
87 | }
88 |
89 | public int getIntParam(int i) {
90 | return ((Integer)getParam(i)).intValue();
91 | }
92 |
93 | public String getStringParam(int i) {
94 | return (String)getParam(i);
95 | }
96 |
97 | /**
98 | *
99 | * @return the number of parameters in this event
100 | */
101 | public int getParamCount() {
102 | return params.size();
103 | }
104 |
105 | public static String getEventName (int code){
106 | switch (code) {
107 | case EosEventRequestGetEvent : return "EosEventRequestGetEvent";
108 | case EosEventObjectAddedEx : return "EosEventObjectAddedEx";
109 | case EosEventObjectRemoved : return "EosEventObjectRemoved";
110 | case EosEventRequestGetObjectInfoEx : return "EosEventRequestGetObjectInfoEx";
111 | case EosEventStorageStatusChanged : return "EosEventStorageStatusChanged";
112 | case EosEventStorageInfoChanged : return "EosEventStorageInfoChanged";
113 | case EosEventRequestObjectTransfer : return "EosEventRequestObjectTransfer";
114 | case EosEventObjectInfoChangedEx : return "EosEventObjectInfoChangedEx";
115 | case EosEventObjectContentChanged : return "EosEventObjectContentChanged";
116 | case EosEventPropValueChanged : return "EosEventPropValueChanged";
117 | case EosEventAvailListChanged : return "EosEventAvailListChanged";
118 | case EosEventCameraStatusChanged : return "EosEventCameraStatusChanged";
119 | case EosEventWillSoonShutdown : return "EosEventWillSoonShutdown";
120 | case EosEventShutdownTimerUpdated : return "EosEventShutdownTimerUpdated";
121 | case EosEventRequestCancelTransfer : return "EosEventRequestCancelTransfer";
122 | case EosEventRequestObjectTransferDT : return "EosEventRequestObjectTransferDT";
123 | case EosEventRequestCancelTransferDT : return "EosEventRequestCancelTransferDT";
124 | case EosEventStoreAdded : return "EosEventStoreAdded";
125 | case EosEventStoreRemoved : return "EosEventStoreRemoved";
126 | case EosEventBulbExposureTime : return "EosEventBulbExposureTime";
127 | case EosEventRecordingTime : return "EosEventRecordingTime";
128 | case EosEventAfResult : return "EosEventRequestObjectTransferTS";
129 | case EosEventRequestObjectTransferTS : return "EosEventAfResult";
130 | }
131 | return "0x" + Integer.toHexString(code);
132 | }
133 |
134 | }
135 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/nikon/NikonEventFormat.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2010 by Stefano Fornari
2 | *
3 | * This program is free software; you can redistribute it and/or modify
4 | * it under the terms of the GNU General Public License as published by
5 | * the Free Software Foundation; either version 2 of the License, or
6 | * (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License
14 | * along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | */
17 | package cn.rainx.ptp.usbcamera.nikon;
18 |
19 | import java.lang.reflect.Field;
20 |
21 | /**
22 | * This class formats an EosEvent to a string
23 | *
24 | * @author stefano fornari
25 | */
26 | public class NikonEventFormat implements NikonEventConstants {
27 | public static String format(NikonEvent e) {
28 | StringBuilder sb = new StringBuilder();
29 |
30 | int eventCode = e.getCode();
31 |
32 | sb.append(getEventName(eventCode));
33 | sb.append(" [ ");
34 | if (eventCode == EosEventPropValueChanged) {
35 | int propCode = e.getIntParam(1);
36 | sb.append(getPropertyName(propCode))
37 | .append(": ");
38 |
39 | if ((propCode >= EosPropPictureStyleStandard) &&
40 | (propCode <= EosPropPictureStyleUserSet3)) {
41 | sb.append("(Sharpness: ")
42 | .append(e.getIntParam(4))
43 | .append(", Contrast: ")
44 | .append(e.getIntParam(3));
45 | if (((Boolean)e.getParam(2)).booleanValue()) {
46 | sb.append(", Filter effect: ")
47 | .append(getFilterEffect(e.getIntParam(5)))
48 | .append(", Toning effect: ")
49 | .append(getToningEffect(e.getIntParam(6)));
50 | } else {
51 | sb.append(", Saturation: ")
52 | .append(e.getIntParam(5))
53 | .append(", Color tone: ")
54 | .append(e.getIntParam(6));
55 | }
56 | sb.append(")");
57 | } else {
58 | if (e.getParamCount()>1) {
59 | sb.append(e.getIntParam(2));
60 | }
61 | }
62 | } else if (eventCode == EosEventObjectAddedEx) {
63 | sb.append(formatEosEventObjectAddedEx(e));
64 | }
65 | sb.append(" ]");
66 |
67 | return sb.toString();
68 | }
69 |
70 | /**
71 | * Returns the printable name of the given event
72 | *
73 | * @param code event code
74 | *
75 | * @return the printable name of the given event
76 | */
77 | public static String getEventName(int code) {
78 | Field[] fields = NikonEventConstants.class.getDeclaredFields();
79 |
80 | for (Field f: fields) {
81 | String name = f.getName();
82 | if (name.startsWith("EosEvent")) {
83 | try {
84 | if (f.getInt(null) == code) {
85 | return name;
86 | }
87 | } catch (Exception e) {
88 | //
89 | // Nothing to do
90 | //
91 | }
92 | }
93 | }
94 | return "Unknown";
95 | }
96 |
97 | /**
98 | * Returns the printable name of the given property
99 | *
100 | * @param code property code
101 | *
102 | * @return the printable name of the given property
103 | */
104 | public static String getPropertyName(int code) {
105 | return getCodeName("EosProp", code);
106 | }
107 |
108 | /**
109 | * Returns the printable name of the given image format
110 | *
111 | * @param code image format code
112 | *
113 | * @return the printable name of the given image format
114 | */
115 | public static String getImageFormatName(int code) {
116 | return getCodeName("ImageFormat", code);
117 | }
118 |
119 | /**
120 | * Returns the filter effect name given the code. Names are:
121 | * 0:None, 1:Yellow, 2:Orange, 3:Red, 4:Green
122 | *
123 | * @param code the filter effect code (0-4)
124 | *
125 | * @return the filter effect name
126 | */
127 | public static String getFilterEffect(int code) {
128 | if ((code < 0) || (code > 4)) {
129 | throw new IllegalArgumentException("code must be in he range 0-4");
130 | }
131 |
132 | switch (code) {
133 | case 0: return "None";
134 | case 1: return "Yellow";
135 | case 2: return "Orange";
136 | case 3: return "Red";
137 | case 4: return "Green";
138 | }
139 |
140 | //
141 | // We should never get here
142 | //
143 | return "Unknown";
144 | }
145 |
146 | /**
147 | * Returns the toning effect name given the code. Names are:
148 | * 0:None, 1:Sepia, 2:Blue, 3:Purple, 4:Green
149 | *
150 | * @param code the toning effect code (0-4)
151 | *
152 | * @return the toning effect name
153 | */
154 | public static String getToningEffect(int code) {
155 | if ((code < 0) || (code > 4)) {
156 | throw new IllegalArgumentException("code must be in he range 0-4");
157 | }
158 |
159 | switch (code) {
160 | case 0: return "None";
161 | case 1: return "Sepia";
162 | case 2: return "Blue";
163 | case 3: return "Purple";
164 | case 4: return "Green";
165 | }
166 |
167 | //
168 | // We should never get here
169 | //
170 | return "Unknown";
171 | }
172 |
173 | // --------------------------------------------------------- Private methods
174 |
175 | private static String formatEosEventObjectAddedEx(NikonEvent event) {
176 | return String.format(
177 | "Filename: %s, Size(bytes): %d, ObjectID: 0x%08X, StorageID: 0x%08X, ParentID: 0x%08X, Format: %s",
178 | event.getStringParam(6),
179 | event.getIntParam(5),
180 | event.getIntParam(1),
181 | event.getIntParam(2),
182 | event.getIntParam(3),
183 | getImageFormatName(event.getIntParam(4))
184 | );
185 | }
186 |
187 | /**
188 | * Looks up and returns the name of the code give if there is a constant
189 | * field in EosEventConstants which starts with the given prefix
190 | *
191 | * @param prefix the field name prefix
192 | * @param code image format code
193 | *
194 | * @return the printable name of the given code
195 | */
196 | private static String getCodeName(String prefix, int code) {
197 | Field[] fields = NikonEventConstants.class.getDeclaredFields();
198 |
199 | for (Field f: fields) {
200 | String name = f.getName();
201 | if (name.startsWith(prefix)) {
202 | try {
203 | if (f.getInt(null) == code) {
204 | return name.substring(prefix.length());
205 | }
206 | } catch (Exception e) {
207 | //
208 | // Nothing to do
209 | //
210 | }
211 | }
212 | }
213 | return "Unknown";
214 | }
215 |
216 | }
217 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/nikon/NikonEventParser.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2010 by Stefano Fornari
2 | *
3 | * This program is free software; you can redistribute it and/or modify
4 | * it under the terms of the GNU General Public License as published by
5 | * the Free Software Foundation; either version 2 of the License, or
6 | * (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License
14 | * along with this program; if not, write to the Free Software
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 | */
17 |
18 | package cn.rainx.ptp.usbcamera.nikon;
19 |
20 | import android.util.Log;
21 |
22 |
23 | import java.io.IOException;
24 | import java.io.InputStream;
25 |
26 | import cn.rainx.ptp.usbcamera.PTPException;
27 | import cn.rainx.ptp.usbcamera.PTPUnsupportedException;
28 |
29 | /**
30 | * This class parses a stream of bytes as a sequence of events accordingly
31 | * to how Canon EOS returns events.
32 | *
33 | * The event information is returned in a standard PTP data packet as a number
34 | * of records followed by an empty record at the end of the packet. Each record
35 | * consists of multiple four-byte fields and always starts with record length
36 | * field. Further structure of the record depends on the device property code
37 | * which always goes in the third field. The empty record consists of the size
38 | * field and four byte empty field, which is always zero.
39 | *
40 | * @author stefano fornari
41 | */
42 | public class NikonEventParser implements NikonEventConstants {
43 |
44 | /**
45 | * The stream data are read from
46 | */
47 | private InputStream is;
48 |
49 | /**
50 | * Creates a new parser to parse the given input stream
51 | *
52 | * @param is
53 | */
54 | public NikonEventParser(InputStream is) {
55 | if (is == null) {
56 | throw new IllegalArgumentException("The input stream cannot be null");
57 | }
58 |
59 | this.is = is;
60 | }
61 |
62 | /**
63 | * Returns true is there are events in the stream (and the stream is still
64 | * open), false otherwise.
65 | *
66 | * @return true is there are events in the stream (and the stream is still
67 | * open), false otherwise.
68 | */
69 | public boolean hasEvents() {
70 | try {
71 | // Log.d("EventParser", " available: " +is.available());
72 | if (is.available() <= 0) {
73 | return false;
74 | }
75 | } catch (IOException e) {
76 | return false;
77 | }
78 |
79 | return true;
80 | }
81 |
82 | /**
83 | * Returns the next event in the stream.
84 | *
85 | * @return the next event in the stream.
86 | *
87 | * @throws PTPException in case of errors
88 | */
89 | public NikonEvent getNextEvent() throws PTPException {
90 | NikonEvent event = new NikonEvent();
91 |
92 | try {
93 | int len = getNextS32(); // len
94 | // Log.d("EventParser", " Len: " +len);
95 | if (len < 0x8) {
96 | throw new PTPUnsupportedException("Unsupported event (size<8 ???)");
97 | }
98 | int code = getNextS32();
99 | event.setCode(code);
100 | Log.d("EventParser", " Event len: " +len +", Code: 0x" + String.format("%04x", code) +" " +NikonEvent.getEventName(code));
101 | parseParameters(event, len-8);
102 | // Log.d("EventParser", " Event: params " +event.getParamCount());
103 | for (int i = 1; i<= event.getParamCount(); i++)
104 | Log.d("EventParser", " params " +i +": " + String.format("0x%04x %d",event.getParam(i), event.getParam(i)));
105 | } catch (IOException e) {
106 | Log.d ("EventParser", " Error reading event stream");
107 | throw new PTPException("Error reading event stream", e);
108 | }
109 |
110 | return event;
111 | }
112 |
113 |
114 | // --------------------------------------------------------- Private methods
115 |
116 | private void parseParameters(NikonEvent event, int len)
117 | throws PTPException, IOException {
118 | int code = event.getCode();
119 |
120 | if (code == EosEventPropValueChanged) {
121 | parsePropValueChangedParameters(event);
122 | } else if (code == EosEventShutdownTimerUpdated) {
123 | //
124 | // No parameters
125 | //
126 | } else if (code == EosEventCameraStatusChanged) {
127 | event.setParam(1, getNextS32());
128 | } else if (code == EosEventObjectAddedEx) {
129 | parseEosEventObjectAddedEx(event);
130 | } else{
131 | is.skip(len);
132 | throw new PTPUnsupportedException("Unsupported event");
133 | }
134 | }
135 |
136 | private void parsePropValueChangedParameters(NikonEvent event)
137 | throws IOException {
138 | int property = getNextS32();
139 | event.setParam(1, property); // property changed
140 |
141 | if ((property >= EosPropPictureStyleStandard) &&
142 | (property <= EosPropPictureStyleUserSet3)) {
143 | boolean monochrome = (property == EosPropPictureStyleMonochrome);
144 | int size = getNextS32();
145 | if (size > 0x1C) {
146 | //
147 | // It is a EosPropPictureStyleUserXXX, let's read the type (then
148 | // we do not use it)
149 | //
150 | monochrome = (getNextS32() == EosPropPictureStyleUserTypeMonochrome);
151 | }
152 | event.setParam(2, (monochrome) ? Boolean.TRUE : Boolean.FALSE);
153 | event.setParam(3, getNextS32()); // contrast
154 | event.setParam(4, getNextS32()); // sharpness
155 | if (monochrome) {
156 | getNextS32();
157 | getNextS32();
158 | event.setParam(5, getNextS32()); // filter effect
159 | event.setParam(6, getNextS32()); // toning effect
160 | } else {
161 | event.setParam(5, getNextS32()); // saturation
162 | event.setParam(6, getNextS32()); // color tone
163 | getNextS32();
164 | getNextS32();
165 | }
166 | } else {
167 | //
168 | // default
169 | //
170 | event.setParam(2, getNextS32());
171 | }
172 |
173 | }
174 |
175 | private void parseEosEventObjectAddedEx(NikonEvent event)
176 | throws IOException {
177 | event.setParam(1, getNextS32() ); // object id
178 | event.setParam(2, getNextS32() ); // storage id
179 | event.setParam(4, getNextS16() ); // format
180 | is.skip(10);
181 | event.setParam(5, getNextS32() ); // size
182 | event.setParam(3, getNextS32() ); // parent object id
183 | is.skip(4); // unknown
184 | event.setParam(6, getNextString()); // file name
185 | is.skip(4);
186 | }
187 |
188 | /**
189 | * Reads and return the next signed 32 bit integer read from the input
190 | * stream.
191 | *
192 | * @return the next signed 32 bit integer in the stream
193 | *
194 | * @throws IOException in case of IO errors
195 | */
196 | private final int getNextS32() throws IOException {
197 | int retval;
198 |
199 | retval = (0xff & is.read()) ;
200 | retval |= (0xff & is.read()) << 8;
201 | retval |= (0xff & is.read()) << 16;
202 | retval |= is.read() << 24;
203 |
204 | return retval;
205 | }
206 |
207 | /**
208 | * Reads and return the next signed 16 bit integer read from the input
209 | * stream.
210 | *
211 | * @return the next signed 16 bit integer in the stream
212 | *
213 | * @throws IOException in case of IO errors
214 | */
215 | private final int getNextS16() throws IOException {
216 | int retval;
217 |
218 | retval = (0xff & is.read()) ;
219 | retval |= (0xff & is.read()) << 8;
220 |
221 | return retval;
222 | }
223 |
224 | /**
225 | * Reads and return the next string read from the input stream. Strings are
226 | * zero (32 bit) terminated string
227 | *
228 | * @return the next string in the stream
229 | *
230 | * @throws IOException in case of IO errors
231 | */
232 | private final String getNextString() throws IOException {
233 | StringBuilder retval = new StringBuilder();
234 |
235 | char c = 0;
236 | while ((c = (char)is.read()) != 0) {
237 | retval.append(c);
238 | }
239 |
240 | //
241 | // At this point we read the string and one zero. We need to read the
242 | // remaining 3 zeros
243 | //
244 | is.skip(3);
245 |
246 | return retval.toString();
247 | }
248 |
249 | }
250 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/sony/SonyDevicePropDesc.java:
--------------------------------------------------------------------------------
1 | package cn.rainx.ptp.usbcamera.sony;
2 |
3 | import cn.rainx.ptp.usbcamera.Buffer;
4 | import cn.rainx.ptp.usbcamera.DevicePropDesc;
5 | import cn.rainx.ptp.usbcamera.DevicePropValue;
6 | import cn.rainx.ptp.usbcamera.NameFactory;
7 |
8 | /**
9 | * Created by rainx on 2017/6/4.
10 | */
11 |
12 | public class SonyDevicePropDesc extends DevicePropDesc {
13 |
14 | protected int unknown;
15 |
16 |
17 | /* Device Property pack/unpack */
18 | /*
19 | #define PTP_dpd_Sony_DevicePropertyCode 0
20 | #define PTP_dpd_Sony_DataType 2
21 | #define PTP_dpd_Sony_GetSet 4
22 | #define PTP_dpd_Sony_Unknown 5
23 | #define PTP_dpd_Sony_FactoryDefaultValue 6
24 | */
25 |
26 | protected Buffer buf;
27 |
28 | public SonyDevicePropDesc(NameFactory f, Buffer buf) {
29 | super(f);
30 | this.data = buf.data;
31 | this.offset = buf.offset;
32 | this.buf = buf;
33 | }
34 |
35 | public void parse ()
36 | {
37 | // per 13.3.3, tables 23, 24, 25
38 | propertyCode = nextU16 ();
39 | dataType = nextU16 ();
40 | writable = nextU8 () != 0;
41 |
42 | unknown = nextS8();
43 |
44 | // FIXME use factories, as vendor hooks
45 | factoryDefault = DevicePropValue.get (dataType, this);
46 | currentValue = DevicePropValue.get (dataType, this);
47 |
48 | formType = nextU8 ();
49 | switch (formType) {
50 | case 0: // no more
51 | break;
52 | case 1: // range: min, max, step
53 | constraints = new Range (dataType, this);
54 | break;
55 | case 2: // enumeration: n, value1, ... valueN
56 | constraints = parseEnumeration ();
57 | break;
58 | default:
59 | System.err.println ("ILLEGAL prop desc form, " + formType);
60 | formType = 0;
61 | break;
62 | }
63 |
64 | // sync offset
65 | this.buf.offset = this.offset;
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/ptp/usbcamera/sony/SonyExtDeviceInfo.java:
--------------------------------------------------------------------------------
1 | package cn.rainx.ptp.usbcamera.sony;
2 |
3 | import android.util.Log;
4 |
5 | import java.util.Arrays;
6 |
7 | import cn.rainx.ptp.usbcamera.Data;
8 | import cn.rainx.ptp.usbcamera.NameFactory;
9 |
10 | /**
11 | * Created by rainx on 2017/6/11.
12 | */
13 |
14 | public class SonyExtDeviceInfo extends Data {
15 | private static final String TAG = "SonyExtDeviceInfo";
16 |
17 | int operationsSupported []; // 10.2
18 | int eventsSupported []; // 12.5
19 | int propertiesSupported []; // 13.3.5
20 | int allSupported[];
21 |
22 | public SonyExtDeviceInfo(NameFactory f) {
23 | super (true, null, 0, f);
24 | }
25 |
26 | /** Returns true iff the device supports this operation */
27 | public boolean supportsOperation (int opCode)
28 | {
29 | return supports (operationsSupported, opCode);
30 | }
31 |
32 | /** Returns true iff the device supports this event */
33 | public boolean supportsEvent (int eventCode)
34 | {
35 | return supports (eventsSupported, eventCode);
36 | }
37 |
38 | /** Returns true iff the device supports this property */
39 | public boolean supportsProperty (int propCode)
40 | {
41 | return supports (propertiesSupported, propCode);
42 | }
43 |
44 | private boolean supports (int supported [], int code)
45 | {
46 | for (int i = 0; i < supported.length; i++) {
47 | if (code == supported [i])
48 | return true;
49 | }
50 | return false;
51 | }
52 |
53 | protected void parse ()
54 | {
55 | super.parse ();
56 | // https://github.com/gphoto/libgphoto2/blob/979e75f15b4bed396a6cac7a505c8d65b92608f2/camlibs/ptp2/ptp.c
57 | // ptp_sony_get_vendorpropcodes
58 | // skip first
59 | nextU16();
60 | allSupported = nextU16Array ();
61 |
62 | // 一个U16Array还没有读完的情况
63 | if (allSupported.length * 2 + 2 + 4 < getLength()) {
64 | int[] p2 = nextU16Array();
65 | int oldLen = allSupported.length;
66 | allSupported = Arrays.copyOf(allSupported, oldLen + p2.length);
67 |
68 | for (int i = 0; i < p2.length; i++) {
69 | allSupported[oldLen + i] = p2[i];
70 | }
71 | }
72 | // https://github.com/gphoto/libgphoto2/blob/master/camlibs/ptp2/library.c
73 | // search PTP_OC_SONY_GetSDIOGetExtDeviceInfo
74 |
75 | int opcodes = 0, propcodes = 0, events = 0, j = 0,k = 0,l = 0;
76 |
77 | for (int op : allSupported) {
78 | switch (op & 0x7000) {
79 | case 0x1000: opcodes++; break;
80 | case 0x4000: events++; break;
81 | case 0x5000: propcodes++; break;
82 | default:
83 | Log.d (TAG, "ptp_sony_get_vendorpropcodes() unknown opcode " + op);
84 | break;
85 | }
86 | }
87 |
88 | operationsSupported = new int[opcodes];
89 | eventsSupported = new int[events];
90 | propertiesSupported = new int[propcodes];
91 |
92 | for (int op : allSupported) {
93 | switch (op & 0x7000) {
94 | case 0x1000:
95 | operationsSupported[k++] = op;
96 | break;
97 | case 0x4000:
98 | eventsSupported[l++] = op;
99 | break;
100 | case 0x5000:
101 | propertiesSupported[j++] = op;
102 | break;
103 | default:
104 | break;
105 | }
106 | }
107 |
108 | }
109 |
110 |
111 | public String toString() {
112 |
113 | String result = "DeviceInfo:\n";
114 | // per chapter 10
115 | result += ("\n\nOperations Supported:");
116 | for (int i = 0; i < operationsSupported.length; i++) {
117 | result += "\n\t" +factory.getOpcodeString (operationsSupported [i]);
118 | }
119 |
120 | // per chapter 11
121 | result += ("\n\nEvents Supported:");
122 | for (int i = 0; i < eventsSupported.length; i++) {
123 | result += "\n\t" +factory.getEventString (eventsSupported [i]);
124 | }
125 |
126 | // per chapter 13
127 | result += ("\n\nDevice Properties Supported:\n");
128 | for (int i = 0; i < propertiesSupported.length; i++) {
129 | result += "\t" +factory.getPropertyName (propertiesSupported [i]);
130 | }
131 | return result;
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/tracker/BaseInfo.java:
--------------------------------------------------------------------------------
1 | package cn.rainx.tracker;
2 |
3 | import android.content.Context;
4 | import android.content.pm.PackageManager;
5 | import android.hardware.usb.UsbDevice;
6 | import android.os.Build;
7 | import android.util.Log;
8 |
9 | import com.loopj.android.http.RequestParams;
10 |
11 | import java.util.List;
12 | import java.util.UUID;
13 |
14 | import cn.rainx.exif.ExifUtils;
15 | import cn.rainx.ptp.db.Uuid;
16 | import cn.rainx.ptp.usbcamera.BaselineInitiator;
17 |
18 | /**
19 | * Created by rainx on 2017/8/26.
20 | */
21 |
22 | public class BaseInfo {
23 |
24 | private int vendorId;
25 | private int deviceId;
26 | private String serial;
27 | private String androidDeviceUniqueId;
28 | private Integer androidUserUniqueId;
29 | private String androidDeviceInfo;
30 | private int androidOSVer;
31 | private int libVersion;
32 | private String deviceInfo = "empty";
33 | private Context context;
34 |
35 | public static final String TAG = "BaseInfo";
36 |
37 |
38 | public BaseInfo(Context context, BaselineInitiator initiator, Integer userUniqueId)
39 | {
40 | this.context = context;
41 |
42 | libVersion = initLibVersion();
43 | androidDeviceUniqueId = initAndroidDevicerUniqueId();
44 | androidOSVer = initAndroidOSVer();
45 | androidUserUniqueId = userUniqueId;
46 |
47 | androidDeviceInfo = Build.DEVICE.toString();
48 |
49 |
50 | Log.d(TAG, "get android os ver " + androidOSVer);
51 | Log.d(TAG, "android uuid is " + androidDeviceUniqueId);
52 | Log.d(TAG, "libversion is " + libVersion);
53 | if (initiator != null) {
54 | UsbDevice device = initiator.getDevice();
55 |
56 | if (device != null) {
57 | vendorId = device.getVendorId();
58 | deviceId = device.getDeviceId();
59 | serial = device.getSerialNumber();
60 | } else {
61 | vendorId = -1;
62 | deviceId = -1;
63 | serial = "empty";
64 | }
65 | try {
66 | deviceInfo = initiator.getDeviceInfo().toString();
67 | } catch (Exception e) {
68 | e.printStackTrace();
69 | // ignore it
70 | deviceInfo = "Exception when get device info";
71 | }
72 |
73 | } else {
74 | vendorId = -1;
75 | deviceId = -1;
76 | serial = "empty";
77 |
78 | }
79 |
80 | }
81 |
82 | public Context getContext() {
83 | return context;
84 | }
85 |
86 | public String getSerial() {
87 | return serial;
88 | }
89 |
90 | public void setSerial(String serial) {
91 | this.serial = serial;
92 | }
93 |
94 | public String getAndroidDeviceUniqueId() {
95 | return androidDeviceUniqueId;
96 | }
97 |
98 | public void setAndroidDeviceUniqueId(String androidDeviceUniqueId) {
99 | this.androidDeviceUniqueId = androidDeviceUniqueId;
100 | }
101 |
102 | public Integer getAndroidUserUniqueId() {
103 | return androidUserUniqueId;
104 | }
105 |
106 | public void setAndroidUserUniqueId(Integer androidUserUniqueId) {
107 | this.androidUserUniqueId = androidUserUniqueId;
108 | }
109 |
110 | public String getAndroidDeviceInfo() {
111 | return androidDeviceInfo;
112 | }
113 |
114 | public void setAndroidDeviceInfo(String androidDeviceInfo) {
115 | this.androidDeviceInfo = androidDeviceInfo;
116 | }
117 |
118 | public int getAndroidOSVer() {
119 | return androidOSVer;
120 | }
121 |
122 | public void setAndroidOSVer(int androidOSVer) {
123 | this.androidOSVer = androidOSVer;
124 | }
125 |
126 | public void setLibVersion(int libVersion) {
127 | this.libVersion = libVersion;
128 | }
129 |
130 | public int getLibVersion() {
131 | return libVersion;
132 | }
133 |
134 | public int initLibVersion()
135 | {
136 | try {
137 | return context.getPackageManager()
138 | .getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA)
139 | .metaData.getInt("iu_libversion");
140 | } catch (PackageManager.NameNotFoundException e) {
141 | e.printStackTrace();
142 | return 0;
143 | }
144 | }
145 |
146 | public String initAndroidDevicerUniqueId() {
147 | List uuids = Uuid.find(Uuid.class, "key=?", "uuid");
148 | if (uuids != null && uuids.size() > 0) {
149 | return uuids.get(0).getValue();
150 | } else {
151 | String uuid = UUID.randomUUID().toString();
152 | Uuid u = new Uuid();
153 | u.setKey("uuid");
154 | u.setValue(uuid);
155 | u.save();
156 | return uuid;
157 | }
158 | }
159 |
160 | public int initAndroidOSVer() {
161 | return Build.VERSION.SDK_INT;
162 | }
163 |
164 |
165 | public RequestParams getParams() {
166 | RequestParams params = new RequestParams();
167 | params.put("vender_id", vendorId);
168 | params.put("device_id", deviceId);
169 | params.put("serial", serial);
170 | params.put("android_device_unique_id", androidDeviceUniqueId);
171 | params.put("android_user_unique_id", androidUserUniqueId);
172 | params.put("android_device_info", androidDeviceInfo);
173 | params.put("android_os_ver", androidOSVer);
174 | params.put("lib_version", libVersion);
175 | params.put("device_info", deviceInfo);
176 |
177 | return params;
178 | }
179 |
180 | }
181 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/rainx/tracker/IuTracker.java:
--------------------------------------------------------------------------------
1 | package cn.rainx.tracker;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import android.content.SharedPreferences;
6 | import android.os.Looper;
7 | import android.preference.Preference;
8 | import android.util.Log;
9 |
10 | import com.loopj.android.http.AsyncHttpClient;
11 | import com.loopj.android.http.JsonHttpResponseHandler;
12 | import com.loopj.android.http.RequestParams;
13 | import com.loopj.android.http.SyncHttpClient;
14 |
15 | import org.json.JSONObject;
16 |
17 | import cn.rainx.ptp.usbcamera.BaselineInitiator;
18 | import cn.rainx.ptp.usbcamera.PTPException;
19 | import cz.msebera.android.httpclient.Header;
20 | import cz.msebera.android.httpclient.annotation.NotThreadSafe;
21 |
22 | import static android.util.Log.*;
23 |
24 | /**
25 | * Created by rainx on 2017/8/20.
26 | */
27 |
28 | public class IuTracker {
29 |
30 | public static final String TAG = IuTracker.class.getSimpleName();
31 |
32 | private boolean bugTrackerEnabled = true;
33 | private boolean perfTrackerEnabled = true;
34 | private boolean deviceInfoTrackerEnabled = true;
35 | private String restBaseUri;
36 | private static volatile IuTracker _instance= null;
37 |
38 | /**
39 | * 获取单例
40 | * @param restBaseUri rest服务的基础uri 如 http://127.0.0.1:8000
41 | * @return
42 | */
43 | public static synchronized IuTracker getInstance(String restBaseUri) {
44 | if (_instance == null) {
45 | _instance = new IuTracker(restBaseUri);
46 | }
47 | return _instance;
48 | }
49 |
50 | public static AsyncHttpClient syncHttpClient= new SyncHttpClient();
51 | public static AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
52 |
53 |
54 | private IuTracker(String restBaseUri) {
55 | this.restBaseUri = restBaseUri;
56 |
57 | }
58 |
59 | public void setBugTrackerEnabled(boolean bugTrackerEnabled) {
60 | this.bugTrackerEnabled = bugTrackerEnabled;
61 | }
62 |
63 | public void setPerfTrackerEnabled(boolean perfTrackerEnabled) {
64 | this.perfTrackerEnabled = perfTrackerEnabled;
65 | }
66 |
67 | public void setDeviceInfoTrackerEnabled(boolean deviceInfoTrackerEnabled) {
68 | this.deviceInfoTrackerEnabled = deviceInfoTrackerEnabled;
69 | }
70 |
71 | public void setRestBaseUri(String restBaseUri) {
72 | int len = restBaseUri.length();
73 | if (restBaseUri.substring(len - 1, len).equals("/")) {
74 | restBaseUri = restBaseUri.substring(0, len - 1);
75 | }
76 | this.restBaseUri = restBaseUri;
77 | }
78 |
79 |
80 | /**
81 | * 向服务器报告设备信息,一个客户端只会报告一次
82 | * @param baseInfo
83 | */
84 | public void reportDeviceInfo(BaseInfo baseInfo) {
85 | // need implement
86 | // 1 持久化确保改接口对于一个手机只被运行一次
87 | // 检测是否已经report 过
88 |
89 | if (!deviceInfoTrackerEnabled) {
90 | return;
91 | }
92 |
93 | final String key = "Already_Reported_DeviceInfo";
94 |
95 | final SharedPreferences sp = baseInfo.getContext().getSharedPreferences(TAG, Context.MODE_PRIVATE);
96 | if (!sp.getBoolean(key, false)) {
97 |
98 | String url = restBaseUri + "/device_info_tracker/";
99 |
100 | RequestParams params = baseInfo.getParams();
101 |
102 | getClient().post(url, params, new JsonHttpResponseHandler() {
103 | @Override
104 | public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
105 | Log.i(TAG, "done!");
106 | Log.d(TAG, response.toString());
107 | sp.edit().putBoolean(key, true);
108 | sp.edit().commit();
109 | }
110 |
111 | @Override
112 | public void onFailure(int statusCode , Header[] headers, Throwable e, JSONObject response) {
113 | e.printStackTrace();
114 | }
115 | });
116 |
117 |
118 | }
119 |
120 | }
121 |
122 | /**
123 | * 向服务器报告文件传输速度
124 | * @param baseInfo 基础信息
125 | * @param initiator USB Initiator 设备
126 | * @param filesize 文件大小
127 | * @param startTs 开始时间
128 | * @param endTs 结束时间
129 | * @param costTs 消耗时间
130 | */
131 | public void reportPerf(BaseInfo baseInfo, BaselineInitiator initiator,
132 | int filesize, float startTs, float endTs, float costTs) {
133 |
134 |
135 | if (!perfTrackerEnabled) {
136 | return;
137 | }
138 |
139 | String url = restBaseUri + "/perf_tracker/";
140 |
141 | RequestParams params = baseInfo.getParams();
142 | if (initiator != null) {
143 | params.put("sync_trigger_mode", initiator.getSyncTriggerMode());
144 | params.put("sync_mode", initiator.getSyncMode());
145 | params.put("sync_record_mode", initiator.getSyncRecordMode());
146 | } else {
147 | params.put("sync_trigger_mode", -1);
148 | params.put("sync_mode", -1);
149 | params.put("sync_record_mode", -1);
150 | }
151 | params.put("filesize", filesize);
152 | params.put("start_ts", startTs);
153 | params.put("end_ts", endTs);
154 | params.put("cost_ts", costTs);
155 |
156 | getClient().post(url, params, new JsonHttpResponseHandler() {
157 | @Override
158 | public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
159 | Log.i(TAG, "done!");
160 | Log.d(TAG, response.toString());
161 | }
162 |
163 | @Override
164 | public void onFailure(int statusCode , Header[] headers, Throwable e, JSONObject response) {
165 | e.printStackTrace();
166 | }
167 | });
168 |
169 | }
170 |
171 | /**
172 | * 向服务器报告bug
173 | * @param baseInfo 基础信息
174 | * @param initiator USB Initiator 设备
175 | * @param exception 异常信息
176 | * @param traceback 调用堆栈
177 | * @param fileinfo 正在传输的文件信息
178 | */
179 | public void reportBug(BaseInfo baseInfo, BaselineInitiator initiator, String exception,
180 | String traceback, String fileinfo) {
181 |
182 | if (!bugTrackerEnabled) {
183 | return;
184 | }
185 |
186 | String url = restBaseUri + "/bug_tracker/";
187 | RequestParams params = baseInfo.getParams();
188 | if (initiator != null) {
189 | params.put("sync_trigger_mode", initiator.getSyncTriggerMode());
190 | params.put("sync_mode", initiator.getSyncMode());
191 | params.put("sync_record_mode", initiator.getSyncRecordMode());
192 | } else {
193 | params.put("sync_trigger_mode", -1);
194 | params.put("sync_mode", -1);
195 | params.put("sync_record_mode", -1);
196 | }
197 | params.put("exception", exception);
198 | params.put("traceback", traceback);
199 | params.put("fileinfo", fileinfo);
200 |
201 | getClient().post(url, params, new JsonHttpResponseHandler() {
202 | @Override
203 | public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
204 | Log.i(TAG, "done!");
205 | Log.d(TAG, response.toString());
206 | }
207 |
208 | @Override
209 | public void onFailure(int statusCode , Header[] headers, Throwable e, JSONObject response) {
210 | e.printStackTrace();
211 | }
212 | });
213 | }
214 |
215 | /**
216 | * @return an async client when calling from the main thread, otherwise a sync client.
217 | */
218 | private static AsyncHttpClient getClient()
219 | {
220 | // Return the synchronous HTTP client when the thread is not prepared
221 | if (Looper.myLooper() == null)
222 | return syncHttpClient;
223 | return asyncHttpClient;
224 | }
225 |
226 | }
227 |
--------------------------------------------------------------------------------
/library/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/library/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/library/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/library/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/library/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/library/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/library/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/library/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/library/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/library/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/library/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/library/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/library/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/library/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/library/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/library/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/library/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/library/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/library/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/library/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/library/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/library/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | MtpController
3 | 获取设备PTP/MTP信息
4 | 全部设备信息
5 | 连接到设备
6 | 获取全部媒体对象
7 | 传输对象
8 | 获取对象信息
9 |
10 |
--------------------------------------------------------------------------------
/library/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/library/src/main/res/xml/device_filter.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/library/src/test/java/mtp/rainx/cn/mtpcontroller/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package mtp.rainx.cn.mtpcontroller;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/local.properties:
--------------------------------------------------------------------------------
1 | ## This file must *NOT* be checked into Version Control Systems,
2 | # as it contains information specific to your local configuration.
3 | #
4 | # Location of the SDK. This is only used by Gradle.
5 | # For customization when using a Version Control System, please read the
6 | # header note.
7 | #Wed Nov 20 16:52:41 CST 2019
8 | ndk.dir=/Users/p-dev/Library/Android/sdk/ndk-bundle
9 | sdk.dir=/Users/p-dev/Library/Android/sdk
10 |
--------------------------------------------------------------------------------
/mtp_controller.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/mtpcontrollerdemo/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/mtpcontrollerdemo/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.2"
6 |
7 | defaultConfig {
8 | applicationId "cn.rainx.demo"
9 | minSdkVersion 21
10 | targetSdkVersion 25
11 | versionCode 1
12 | versionName "1.0"
13 |
14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
15 |
16 | }
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | }
24 |
25 | dependencies {
26 | compile fileTree(dir: 'libs', include: ['*.jar'])
27 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
28 | exclude group: 'com.android.support', module: 'support-annotations'
29 | })
30 | compile 'com.android.support:appcompat-v7:25.3.1'
31 | compile 'com.android.support.constraint:constraint-layout:1.0.2'
32 | testCompile 'junit:junit:4.12'
33 | compile project(':library')
34 | }
35 |
--------------------------------------------------------------------------------
/mtpcontrollerdemo/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/rainx/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/mtpcontrollerdemo/src/androidTest/java/cn/rainx/demo/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package cn.rainx.demo;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 | import android.util.Log;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import cn.rainx.ptp.usbcamera.BaselineInitiator;
12 | import cn.rainx.tracker.BaseInfo;
13 | import cn.rainx.tracker.IuTracker;
14 |
15 | import static org.junit.Assert.*;
16 |
17 | /**
18 | * Instrumentation test, which will execute on an Android device.
19 | *
20 | * @see Testing documentation
21 | */
22 | @RunWith(AndroidJUnit4.class)
23 | public class ExampleInstrumentedTest {
24 |
25 | public static final String TAG = ExampleInstrumentedTest.class.getName();
26 |
27 | @Test
28 | public void useAppContext() throws Exception {
29 | // Context of the app under test.
30 | Context appContext = InstrumentationRegistry.getTargetContext();
31 |
32 | assertEquals("cn.rainx.demo", appContext.getPackageName());
33 | }
34 |
35 |
36 | private BaseInfo getBaseInfo() {
37 | Context appContext = InstrumentationRegistry.getTargetContext();
38 | BaseInfo baseInfo = new BaseInfo(appContext, null, 1000);
39 | int libver = baseInfo.getLibVersion();
40 | Log.v(TAG, libver + "");
41 | Log.v(TAG, baseInfo.getAndroidOSVer() + "");
42 | //Log.v(TAG, baseInfo.getSerial());
43 | Log.v(TAG, baseInfo.getAndroidDeviceUniqueId());
44 | Log.v(TAG, baseInfo.getAndroidUserUniqueId() + "");
45 | Log.v(TAG, baseInfo.getAndroidDeviceInfo());
46 | return baseInfo;
47 | }
48 |
49 | @Test
50 | public void testReportBaseInfo() {
51 | BaseInfo baseinfo = getBaseInfo();
52 | IuTracker tracker = IuTracker.getInstance("http://10.63.255.84:8000");
53 | tracker.reportDeviceInfo(baseinfo);
54 | }
55 |
56 | @Test
57 | public void testReportPerf() {
58 | BaseInfo baseinfo = getBaseInfo();
59 | IuTracker tracker = IuTracker.getInstance("http://10.63.255.84:8000");
60 | tracker.reportPerf(baseinfo, null, 1024 * 1024 , System.currentTimeMillis(),
61 | System.currentTimeMillis() + 10, 10);
62 | }
63 |
64 | @Test
65 | public void testReportBug() {
66 | BaseInfo baseinfo = getBaseInfo();
67 | IuTracker tracker = IuTracker.getInstance("http://10.63.255.84:8000");
68 | tracker.reportBug(baseinfo, null, "PTPException", "....traceback....", "filename : xxxx");
69 | }
70 |
71 | @Test
72 | public void testException() {
73 | Exception e = new Exception("hello");
74 | Log.v(TAG, e.toString());
75 | Log.v(TAG, e.getMessage());
76 | Log.v(TAG, e.getClass().toString());
77 |
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/mtpcontrollerdemo/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
27 |
28 |
29 |
30 |
31 |
32 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/mtpcontrollerdemo/src/main/res/layout/activity_controller.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
22 |
23 |
26 |
27 |
31 |
32 |
37 |
38 |
43 |
44 |
49 |
50 |
55 |
56 |
60 |
61 |
67 |
68 |
76 |
77 |
78 |
79 |
83 |
84 |
90 |
91 |
99 |
100 |
101 |
106 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/mtpcontrollerdemo/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/mtpcontrollerdemo/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/mtpcontrollerdemo/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/mtpcontrollerdemo/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/mtpcontrollerdemo/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/mtpcontrollerdemo/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/mtpcontrollerdemo/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/mtpcontrollerdemo/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/mtpcontrollerdemo/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/mtpcontrollerdemo/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/mtpcontrollerdemo/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/mtpcontrollerdemo/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/mtpcontrollerdemo/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/mtpcontrollerdemo/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/mtpcontrollerdemo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/mtpcontrollerdemo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/mtpcontrollerdemo/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/mtpcontrollerdemo/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/mtpcontrollerdemo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shenqinwei/mtp_controller/bb289b7ac89d73f13a29ea7cc13a307934589f0a/mtpcontrollerdemo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/mtpcontrollerdemo/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/mtpcontrollerdemo/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | MtpControllerDemo
3 | 更新exif信息
4 |
5 |
--------------------------------------------------------------------------------
/mtpcontrollerdemo/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/mtpcontrollerdemo/src/test/java/cn/rainx/demo/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package cn.rainx.demo;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':library', ':mtpcontrollerdemo'
2 |
--------------------------------------------------------------------------------