引入ryc库

chengzhenyu 6 anni fa
parent
commit
0b9430cee5
72 ha cambiato i file con 7006 aggiunte e 6 eliminazioni
  1. 1 0
      .idea/gradle.xml
  2. 1 0
      .idea/modules.xml
  3. 8 0
      build.gradle
  4. 4 4
      gradle.properties
  5. 1 1
      gradle/wrapper/gradle-wrapper.properties
  6. 1 0
      ryc/.gitignore
  7. 27 0
      ryc/build.gradle
  8. 21 0
      ryc/proguard-rules.pro
  9. 6 0
      ryc/src/main/AndroidManifest.xml
  10. 24 0
      ryc/src/main/java/com/remoteyourcam/usb/AppConfig.java
  11. 193 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/Camera.java
  12. 179 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/EosCamera.java
  13. 30 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/EosConstants.java
  14. 30 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/FocusPoint.java
  15. 381 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/NikonCamera.java
  16. 162 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/PacketUtil.java
  17. 35 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/PtpAction.java
  18. 887 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/PtpCamera.java
  19. 501 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/PtpConstants.java
  20. 803 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/PtpPropertyHelper.java
  21. 47 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/PtpService.java
  22. 76 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/PtpUsbConnection.java
  23. 234 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/PtpUsbService.java
  24. 34 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/WorkerNotifier.java
  25. 61 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/CloseSessionCommand.java
  26. 188 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/Command.java
  27. 62 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetDeviceInfoCommand.java
  28. 57 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetDevicePropDescCommand.java
  29. 68 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetDevicePropValueCommand.java
  30. 90 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetObjectCommand.java
  31. 79 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetObjectHandlesCommand.java
  32. 73 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetObjectInfoCommand.java
  33. 54 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetStorageIdsCommand.java
  34. 53 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetStorageInfoCommand.java
  35. 72 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetStorageInfosAction.java
  36. 71 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetThumb.java
  37. 44 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/InitiateCaptureCommand.java
  38. 44 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/InitiateOpenCaptureCommand.java
  39. 48 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/OpenSessionCommand.java
  40. 51 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/RetrieveAddedObjectInfoAction.java
  41. 54 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/RetrieveImageAction.java
  42. 70 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/RetrieveImageInfoAction.java
  43. 86 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/RetrievePictureAction.java
  44. 76 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/SetDevicePropValueCommand.java
  45. 70 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/SimpleCommand.java
  46. 29 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosCommand.java
  47. 184 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosEventCheckCommand.java
  48. 153 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosGetLiveViewPictureCommand.java
  49. 65 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosOpenSessionAction.java
  50. 46 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosSetExtendedEventInfoCommand.java
  51. 84 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosSetLiveViewAction.java
  52. 45 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosSetPcModeCommand.java
  53. 64 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosSetPropertyCommand.java
  54. 43 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosTakePictureCommand.java
  55. 47 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonAfDriveCommand.java
  56. 46 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonAfDriveDeviceReadyCommand.java
  57. 54 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonCloseSessionAction.java
  58. 29 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonCommand.java
  59. 81 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonEventCheckCommand.java
  60. 70 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonGetLiveViewImageAction.java
  61. 158 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonGetLiveViewImageCommand.java
  62. 51 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonGetVendorPropCodesCommand.java
  63. 69 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonOpenSessionAction.java
  64. 66 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonStartLiveViewAction.java
  65. 54 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonStopLiveViewAction.java
  66. 113 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/model/DeviceInfo.java
  67. 102 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/model/DevicePropDesc.java
  68. 44 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/model/LiveViewData.java
  69. 101 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/model/ObjectInfo.java
  70. 47 0
      ryc/src/main/java/com/remoteyourcam/usb/ptp/model/StorageInfo.java
  71. 3 0
      ryc/src/main/res/values/strings.xml
  72. 1 1
      settings.gradle

+ 1 - 0
.idea/gradle.xml

@@ -11,6 +11,7 @@
11 11
             <option value="$PROJECT_DIR$" />
12 12
             <option value="$PROJECT_DIR$/app" />
13 13
             <option value="$PROJECT_DIR$/common" />
14
+            <option value="$PROJECT_DIR$/ryc" />
14 15
             <option value="$PROJECT_DIR$/views" />
15 16
           </set>
16 17
         </option>

+ 1 - 0
.idea/modules.xml

@@ -6,6 +6,7 @@
6 6
       <module fileurl="file://$PROJECT_DIR$/common/common.iml" filepath="$PROJECT_DIR$/common/common.iml" />
7 7
       <module fileurl="file://$PROJECT_DIR$/lensman.iml" filepath="$PROJECT_DIR$/lensman.iml" />
8 8
       <module fileurl="file://$PROJECT_DIR$/lensman_ssh.iml" filepath="$PROJECT_DIR$/lensman_ssh.iml" />
9
+      <module fileurl="file://$PROJECT_DIR$/ryc/ryc.iml" filepath="$PROJECT_DIR$/ryc/ryc.iml" />
9 10
       <module fileurl="file://$PROJECT_DIR$/views/views.iml" filepath="$PROJECT_DIR$/views/views.iml" />
10 11
     </modules>
11 12
   </component>

+ 8 - 0
build.gradle

@@ -3,6 +3,10 @@
3 3
 buildscript {
4 4
     repositories {
5 5
         jcenter()
6
+        mavenCentral()
7
+        maven {
8
+            url 'https://maven.google.com'
9
+        }
6 10
     }
7 11
     dependencies {
8 12
         classpath 'com.android.tools.build:gradle:2.3.3'
@@ -15,6 +19,10 @@ buildscript {
15 19
 allprojects {
16 20
     repositories {
17 21
         jcenter()
22
+        mavenCentral()
23
+        maven {
24
+            url 'https://maven.google.com'
25
+        }
18 26
     }
19 27
 }
20 28
 

+ 4 - 4
gradle.properties

@@ -16,7 +16,7 @@ org.gradle.parallel=true
16 16
 android.useDeprecatedNdk=true
17 17
 org.gradle.configureondemand=true
18 18
 
19
-COMPILE_SDK_VERSION=23
20
-BUILD_TOOLS_VERSION=25.0.2
21
-MIN_SDK_VERSION=15
22
-TARGET_SDK_VERSION=21
19
+COMPILE_SDK_VERSION=25
20
+BUILD_TOOLS_VERSION=28.0.3
21
+MIN_SDK_VERSION=19
22
+TARGET_SDK_VERSION=26

+ 1 - 1
gradle/wrapper/gradle-wrapper.properties

@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
3 3
 distributionPath=wrapper/dists
4 4
 zipStoreBase=GRADLE_USER_HOME
5 5
 zipStorePath=wrapper/dists
6
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
6
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

+ 1 - 0
ryc/.gitignore

@@ -0,0 +1 @@
1
+/build

+ 27 - 0
ryc/build.gradle

@@ -0,0 +1,27 @@
1
+apply plugin: 'com.android.library'
2
+
3
+android {
4
+    compileSdkVersion COMPILE_SDK_VERSION as int
5
+    buildToolsVersion BUILD_TOOLS_VERSION as String
6
+
7
+
8
+    defaultConfig {
9
+        minSdkVersion MIN_SDK_VERSION as int
10
+        targetSdkVersion TARGET_SDK_VERSION as int
11
+        versionCode 1
12
+        versionName "1.0"
13
+
14
+    }
15
+
16
+    buildTypes {
17
+        release {
18
+            minifyEnabled false
19
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20
+        }
21
+    }
22
+
23
+}
24
+
25
+dependencies {
26
+    compile fileTree(dir: 'libs', include: ['*.jar'])
27
+}

+ 21 - 0
ryc/proguard-rules.pro

@@ -0,0 +1,21 @@
1
+# Add project specific ProGuard rules here.
2
+# You can control the set of applied configuration files using the
3
+# proguardFiles setting in build.gradle.
4
+#
5
+# For more details, see
6
+#   http://developer.android.com/guide/developing/tools/proguard.html
7
+
8
+# If your project uses WebView with JS, uncomment the following
9
+# and specify the fully qualified class name to the JavaScript interface
10
+# class:
11
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12
+#   public *;
13
+#}
14
+
15
+# Uncomment this to preserve the line number information for
16
+# debugging stack traces.
17
+#-keepattributes SourceFile,LineNumberTable
18
+
19
+# If you keep the line number information, uncomment this to
20
+# hide the original source file name.
21
+#-renamesourcefileattribute SourceFile

+ 6 - 0
ryc/src/main/AndroidManifest.xml

@@ -0,0 +1,6 @@
1
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+    package="com.remoteyourcam.usb">
3
+    <uses-feature android:name="android.hardware.usb.host" />
4
+    <uses-sdk android:minSdkVersion="19" />
5
+
6
+</manifest>

+ 24 - 0
ryc/src/main/java/com/remoteyourcam/usb/AppConfig.java

@@ -0,0 +1,24 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb;
17
+
18
+public class AppConfig {
19
+    public static final boolean LOG = true;
20
+    public static final boolean LOG_PACKETS = false;
21
+
22
+    public static final int EVENTCHECK_PERIOD = 700;
23
+    public static final int USB_TRANSFER_TIMEOUT = 30000;
24
+}

+ 193 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/Camera.java

@@ -0,0 +1,193 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp;
17
+
18
+import java.io.File;
19
+import java.util.List;
20
+
21
+import android.graphics.Bitmap;
22
+
23
+import com.remoteyourcam.usb.ptp.model.LiveViewData;
24
+import com.remoteyourcam.usb.ptp.model.ObjectInfo;
25
+
26
+public interface Camera {
27
+
28
+    public static class Property {
29
+        public static final int ShutterSpeed = 1;
30
+        public static final int ApertureValue = 2;
31
+        public static final int IsoSpeed = 3;
32
+        public static final int Whitebalance = 4;
33
+        public static final int ShootingMode = 5;
34
+        public static final int BatteryLevel = 6;
35
+        public static final int AvailableShots = 7;
36
+        public static final int ColorTemperature = 8;
37
+        public static final int FocusMode = 9;
38
+        public static final int PictureStyle = 10;
39
+        public static final int ExposureMeteringMode = 11;
40
+        public static final int FocusMeteringMode = 12;
41
+        public static final int CurrentFocusPoint = 13;
42
+        public static final int CurrentExposureIndicator = 14;
43
+        public static final int FocusPoints = 15;
44
+        public static final int ExposureCompensation = 16;
45
+    }
46
+
47
+    public static class DriveLens {
48
+        public static final int Near = 1;
49
+        public static final int Far = 2;
50
+        public static final int Soft = 1;
51
+        public static final int Medium = 2;
52
+        public static final int Hard = 3;
53
+    }
54
+
55
+    public interface CameraListener {
56
+
57
+        void onCameraStarted(Camera camera);
58
+
59
+        void onCameraStopped(Camera camera);
60
+
61
+        void onNoCameraFound();
62
+
63
+        void onError(String message);
64
+
65
+        void onPropertyChanged(int property, int value);
66
+
67
+        void onPropertyStateChanged(int property, boolean enabled);
68
+
69
+        void onPropertyDescChanged(int property, int[] values);
70
+
71
+        void onLiveViewStarted();
72
+
73
+        void onLiveViewData(LiveViewData data);
74
+
75
+        void onLiveViewStopped();
76
+
77
+        void onCapturedPictureReceived(int objectHandle, String filename, Bitmap thumbnail, Bitmap bitmap);
78
+
79
+        void onBulbStarted();
80
+
81
+        void onBulbExposureTime(int seconds);
82
+
83
+        void onBulbStopped();
84
+
85
+        void onFocusStarted();
86
+
87
+        void onFocusEnded(boolean hasFocused);
88
+
89
+        void onFocusPointsChanged();
90
+
91
+        void onObjectAdded(int handle);
92
+
93
+        void onLogMessage(String msg);
94
+    }
95
+
96
+    // callbacks aren't on UI thread
97
+    public interface WorkerListener {
98
+        void onWorkerStarted();
99
+
100
+        void onWorkerEnded();
101
+    }
102
+
103
+    // callbacks aren't on UI thread
104
+    public interface StorageInfoListener {
105
+        void onStorageFound(int handle, String label);
106
+
107
+        void onAllStoragesFound();
108
+
109
+        void onImageHandlesRetrieved(int[] handles);
110
+    }
111
+
112
+    public interface RetrieveImageInfoListener {
113
+        void onImageInfoRetrieved(int objectHandle, ObjectInfo objectInfo, Bitmap thumbnail);
114
+    }
115
+
116
+    public interface RetrieveImageListener {
117
+        void onImageRetrieved(int objectHandle, Bitmap image);
118
+    }
119
+
120
+    void setWorkerListener(WorkerListener listener);
121
+
122
+    void setCapturedPictureSampleSize(int sampleSize);
123
+
124
+    String getDeviceName();
125
+
126
+    boolean isSessionOpen();
127
+
128
+    int getProperty(int property);
129
+
130
+    boolean getPropertyEnabledState(int property);
131
+
132
+    int[] getPropertyDesc(int property);
133
+
134
+    void setProperty(int property, int value);
135
+
136
+    String propertyToString(int property, int value);
137
+
138
+    Integer propertyToIcon(int property, int value);
139
+
140
+    String getBiggestPropertyValue(int property);
141
+
142
+    void focus();
143
+
144
+    boolean isAutoFocusSupported();
145
+
146
+    void capture();
147
+
148
+    void openCapture();
149
+
150
+    boolean isLiveViewSupported();
151
+
152
+    boolean isLiveViewAfAreaSupported();
153
+
154
+    boolean isHistogramSupported();
155
+
156
+    boolean isLiveViewOpen();
157
+
158
+    void setLiveView(boolean enabled);
159
+
160
+    void getLiveViewPicture(LiveViewData reuse);
161
+
162
+    /**
163
+     * Sets the center point of the auto focus frame in Live view.
164
+     *
165
+     * @param posx
166
+     *            range 0.0 (left) - 1.0 (right)
167
+     * @param posy
168
+     *            range 0.0 (top) - 1.0 (bottom)
169
+     */
170
+    void setLiveViewAfArea(float posx, float posy);
171
+
172
+    boolean isDriveLensSupported();
173
+
174
+    void driveLens(int driveDirection, int pulses);
175
+
176
+    boolean isSettingPropertyPossible(int property);
177
+
178
+    void writeDebugInfo(File out);
179
+
180
+    String getDeviceInfo();
181
+
182
+    List<FocusPoint> getFocusPoints();
183
+
184
+    void retrievePicture(int objectHandle);
185
+
186
+    void retrieveStorages(StorageInfoListener listener);
187
+
188
+    void retrieveImageHandles(StorageInfoListener listener, int storageId, int objectFormat);
189
+
190
+    void retrieveImageInfo(RetrieveImageInfoListener listener, int objectHandle);
191
+
192
+    void retrieveImage(RetrieveImageListener listener, int objectHandle);
193
+}

+ 179 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/EosCamera.java

@@ -0,0 +1,179 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp;
17
+
18
+import java.util.ArrayList;
19
+import java.util.List;
20
+import java.util.Set;
21
+
22
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
23
+import com.remoteyourcam.usb.ptp.commands.SimpleCommand;
24
+import com.remoteyourcam.usb.ptp.commands.eos.EosEventCheckCommand;
25
+import com.remoteyourcam.usb.ptp.commands.eos.EosGetLiveViewPictureCommand;
26
+import com.remoteyourcam.usb.ptp.commands.eos.EosOpenSessionAction;
27
+import com.remoteyourcam.usb.ptp.commands.eos.EosSetLiveViewAction;
28
+import com.remoteyourcam.usb.ptp.commands.eos.EosSetPropertyCommand;
29
+import com.remoteyourcam.usb.ptp.commands.eos.EosTakePictureCommand;
30
+import com.remoteyourcam.usb.ptp.model.LiveViewData;
31
+
32
+public class EosCamera extends PtpCamera {
33
+
34
+    public EosCamera(PtpUsbConnection connection, CameraListener listener, WorkerListener workerListener) {
35
+        super(connection, listener, workerListener);
36
+
37
+        addPropertyMapping(Camera.Property.ShutterSpeed, PtpConstants.Property.EosShutterSpeed);
38
+        addPropertyMapping(Camera.Property.ApertureValue, PtpConstants.Property.EosApertureValue);
39
+        addPropertyMapping(Camera.Property.IsoSpeed, PtpConstants.Property.EosIsoSpeed);
40
+        addPropertyMapping(Camera.Property.Whitebalance, PtpConstants.Property.EosWhitebalance);
41
+        addPropertyMapping(Camera.Property.ShootingMode, PtpConstants.Property.EosShootingMode);
42
+        addPropertyMapping(Camera.Property.AvailableShots, PtpConstants.Property.EosAvailableShots);
43
+        addPropertyMapping(Camera.Property.ColorTemperature, PtpConstants.Property.EosColorTemperature);
44
+        addPropertyMapping(Camera.Property.FocusMode, PtpConstants.Property.EosAfMode);
45
+        addPropertyMapping(Camera.Property.PictureStyle, PtpConstants.Property.EosPictureStyle);
46
+        addPropertyMapping(Camera.Property.ExposureMeteringMode, PtpConstants.Property.EosMeteringMode);
47
+        addPropertyMapping(Camera.Property.ExposureCompensation, PtpConstants.Property.EosExposureCompensation);
48
+
49
+        histogramSupported = true;
50
+    }
51
+
52
+    @Override
53
+    protected void onOperationCodesReceived(Set<Integer> operations) {
54
+        if (operations.contains(Operation.EosGetLiveViewPicture)) {
55
+            liveViewSupported = true;
56
+        }
57
+        if (operations.contains(Operation.EosBulbStart) && operations.contains(Operation.EosBulbEnd)) {
58
+            bulbSupported = true;
59
+        }
60
+        if (operations.contains(Operation.EosDriveLens)) {
61
+            driveLensSupported = true;
62
+        }
63
+        if (operations.contains(Operation.EosRemoteReleaseOn) && operations.contains(Operation.EosRemoteReleaseOff)) {
64
+            //autoFocusSupported = true;
65
+        }
66
+    }
67
+
68
+    public void onEventDirItemCreated(int objectHandle, int storageId, int objectFormat, String filename) {
69
+        onEventObjectAdded(objectHandle);
70
+    }
71
+
72
+    @Override
73
+    protected void openSession() {
74
+        queue.add(new EosOpenSessionAction(this));
75
+    }
76
+
77
+    @Override
78
+    protected void queueEventCheck() {
79
+        queue.add(new EosEventCheckCommand(this));
80
+    }
81
+
82
+    @Override
83
+    public void focus() {
84
+        //queue.add(new SimpleCommand(this, Operation.EosRemoteReleaseOn, 1, 0));
85
+    }
86
+
87
+    @Override
88
+    public void capture() {
89
+        if (isBulbCurrentShutterSpeed()) {
90
+            queue.add(new SimpleCommand(this, cameraIsCapturing ? Operation.EosBulbEnd : Operation.EosBulbStart));
91
+        } else {
92
+            queue.add(new EosTakePictureCommand(this));
93
+        }
94
+    }
95
+
96
+    @Override
97
+    public void setProperty(int property, int value) {
98
+        if (properties.containsKey(property)) {
99
+            queue.add(new EosSetPropertyCommand(this, virtualToPtpProperty.get(property), value));
100
+        }
101
+    }
102
+
103
+    @Override
104
+    public void setLiveView(boolean enabled) {
105
+        if (liveViewSupported) {
106
+            queue.add(new EosSetLiveViewAction(this, enabled));
107
+        }
108
+    }
109
+
110
+    @Override
111
+    public void getLiveViewPicture(LiveViewData data) {
112
+        if (liveViewOpen) {
113
+            queue.add(new EosGetLiveViewPictureCommand(this, data));
114
+        }
115
+    }
116
+
117
+    @Override
118
+    protected boolean isBulbCurrentShutterSpeed() {
119
+        Integer value = ptpProperties.get(PtpConstants.Property.EosShutterSpeed);
120
+        return bulbSupported && value != null && value == PtpPropertyHelper.EOS_SHUTTER_SPEED_BULB;
121
+    }
122
+
123
+    @Override
124
+    public void driveLens(int driveDirection, int pulses) {
125
+        if (driveLensSupported && liveViewOpen) {
126
+            int value = driveDirection == Camera.DriveLens.Near ? 0 : 0x8000;
127
+            switch (pulses) {
128
+            case DriveLens.Hard:
129
+                value |= 0x0003;
130
+                break;
131
+            case DriveLens.Medium:
132
+                value |= 0x0002;
133
+                break;
134
+            case DriveLens.Soft:
135
+            default:
136
+                value |= 0x0001;
137
+                break;
138
+            }
139
+            queue.add(new SimpleCommand(this, PtpConstants.Operation.EosDriveLens, value));
140
+        }
141
+    }
142
+
143
+    @Override
144
+    public boolean isSettingPropertyPossible(int property) {
145
+        Integer mode = ptpProperties.get(PtpConstants.Property.EosShootingMode);
146
+        Integer wb = ptpProperties.get(PtpConstants.Property.WhiteBalance);
147
+        if (mode == null) {
148
+            return false;
149
+        }
150
+        switch (property) {
151
+        case Property.ShutterSpeed:
152
+            return mode == 3 || mode == 1;
153
+        case Property.ApertureValue:
154
+            return mode == 3 || mode == 2;
155
+        case Property.IsoSpeed:
156
+        case Property.Whitebalance:
157
+        case Property.ExposureMeteringMode:
158
+            return mode >= 0 && mode <= 6;
159
+        case Property.FocusPoints:
160
+            return false;
161
+        case Property.ExposureCompensation:
162
+            return mode == 0 || mode == 1 || mode == 2 || mode == 5 || mode == 6;
163
+        case Property.ColorTemperature:
164
+            return wb != null && wb == 9;
165
+        default:
166
+            return true;
167
+        }
168
+    }
169
+
170
+    @Override
171
+    public void setLiveViewAfArea(float posx, float posy) {
172
+        // TODO Auto-generated method stub
173
+    }
174
+
175
+    @Override
176
+    public List<FocusPoint> getFocusPoints() {
177
+        return new ArrayList<FocusPoint>();
178
+    }
179
+}

+ 30 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/EosConstants.java

@@ -0,0 +1,30 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp;
17
+
18
+public class EosConstants {
19
+
20
+    public static class EvfOutputDevice {
21
+        public static final int DISABLE = 0x0;
22
+        public static final int TFT = 0x01;
23
+        public static final int PC = 0x02;
24
+    }
25
+
26
+    public static class EvfMode {
27
+        public static final int DISABLE = 0;
28
+        public static final int ENABLE = 1;
29
+    }
30
+}

+ 30 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/FocusPoint.java

@@ -0,0 +1,30 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp;
17
+
18
+public class FocusPoint {
19
+    public int id;
20
+    public float posx;
21
+    public float posy;
22
+    public float radius;
23
+
24
+    public FocusPoint(int id, float posx, float posy, float radius) {
25
+        this.id = id;
26
+        this.posx = posx;
27
+        this.posy = posy;
28
+        this.radius = radius;
29
+    }
30
+}

+ 381 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/NikonCamera.java

@@ -0,0 +1,381 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp;
17
+
18
+import java.util.ArrayList;
19
+import java.util.HashSet;
20
+import java.util.List;
21
+import java.util.Set;
22
+
23
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
24
+import com.remoteyourcam.usb.ptp.commands.GetDevicePropDescCommand;
25
+import com.remoteyourcam.usb.ptp.commands.InitiateCaptureCommand;
26
+import com.remoteyourcam.usb.ptp.commands.RetrieveAddedObjectInfoAction;
27
+import com.remoteyourcam.usb.ptp.commands.RetrievePictureAction;
28
+import com.remoteyourcam.usb.ptp.commands.SimpleCommand;
29
+import com.remoteyourcam.usb.ptp.commands.nikon.NikonAfDriveCommand;
30
+import com.remoteyourcam.usb.ptp.commands.nikon.NikonCloseSessionAction;
31
+import com.remoteyourcam.usb.ptp.commands.nikon.NikonEventCheckCommand;
32
+import com.remoteyourcam.usb.ptp.commands.nikon.NikonGetLiveViewImageAction;
33
+import com.remoteyourcam.usb.ptp.commands.nikon.NikonGetLiveViewImageCommand;
34
+import com.remoteyourcam.usb.ptp.commands.nikon.NikonOpenSessionAction;
35
+import com.remoteyourcam.usb.ptp.commands.nikon.NikonStartLiveViewAction;
36
+import com.remoteyourcam.usb.ptp.commands.nikon.NikonStopLiveViewAction;
37
+import com.remoteyourcam.usb.ptp.model.DevicePropDesc;
38
+import com.remoteyourcam.usb.ptp.model.LiveViewData;
39
+
40
+public class NikonCamera extends PtpCamera {
41
+
42
+    private Set<Integer> supportedOperations;
43
+    private int[] vendorPropCodes = new int[0];
44
+    private int enableAfAreaPoint;
45
+    private boolean gotNikonShutterSpeed;
46
+    private boolean liveViewStoppedInternal;
47
+
48
+    public NikonCamera(PtpUsbConnection connection, CameraListener listener, WorkerListener workerListener) {
49
+        super(connection, listener, workerListener);
50
+
51
+        histogramSupported = false;
52
+    }
53
+
54
+    @Override
55
+    protected void onOperationCodesReceived(Set<Integer> operations) {
56
+        supportedOperations = operations;
57
+        if (operations.contains(Operation.NikonGetLiveViewImage) && operations.contains(Operation.NikonStartLiveView)
58
+                && operations.contains(Operation.NikonEndLiveView)) {
59
+            liveViewSupported = true;
60
+        }
61
+        if (operations.contains(Operation.NikonMfDrive)) {
62
+            driveLensSupported = true;
63
+        }
64
+        if (operations.contains(Operation.NikonChangeAfArea)) {
65
+            liveViewAfAreaSupported = true;
66
+        }
67
+        if (operations.contains(Operation.NikonAfDrive)) {
68
+            autoFocusSupported = true;
69
+        }
70
+    }
71
+
72
+    @Override
73
+    public void onPropertyChanged(int property, int value) {
74
+        super.onPropertyChanged(property, value);
75
+        if (property == PtpConstants.Property.NikonEnableAfAreaPoint) {
76
+            enableAfAreaPoint = value;
77
+            handler.post(new Runnable() {
78
+                @Override
79
+                public void run() {
80
+                    if (listener != null) {
81
+                        listener.onFocusPointsChanged();
82
+                    }
83
+                }
84
+            });
85
+        }
86
+    }
87
+
88
+    @Override
89
+    public void onPropertyDescChanged(int property, DevicePropDesc desc) {
90
+        if (!gotNikonShutterSpeed) {
91
+            if (property == PtpConstants.Property.NikonShutterSpeed) {
92
+                // some cameras have this properties with only 2/3 values
93
+                if (desc.description.length <= 4) {
94
+                    return;
95
+                }
96
+                addPropertyMapping(Camera.Property.ShutterSpeed, PtpConstants.Property.NikonShutterSpeed);
97
+                gotNikonShutterSpeed = true;
98
+            } else if (property == PtpConstants.Property.ExposureTime) {
99
+                addPropertyMapping(Camera.Property.ShutterSpeed, PtpConstants.Property.ExposureTime);
100
+                gotNikonShutterSpeed = true;
101
+            }
102
+        }
103
+        super.onPropertyDescChanged(property, desc);
104
+    }
105
+
106
+    private void onPropertyCodesReceived(Set<Integer> properties) {
107
+        if (properties.contains(PtpConstants.Property.NikonShutterSpeed)) {
108
+            queue.add(new GetDevicePropDescCommand(this, PtpConstants.Property.NikonShutterSpeed));
109
+        }
110
+        if (properties.contains(PtpConstants.Property.ExposureTime)) {
111
+            queue.add(new GetDevicePropDescCommand(this, PtpConstants.Property.ExposureTime));
112
+        }
113
+
114
+        addPropertyMapping(Camera.Property.ApertureValue, PtpConstants.Property.FNumber);
115
+        addPropertyMapping(Camera.Property.IsoSpeed, PtpConstants.Property.ExposureIndex);
116
+        addPropertyMapping(Camera.Property.Whitebalance, PtpConstants.Property.WhiteBalance);
117
+        addPropertyMapping(Camera.Property.ColorTemperature, PtpConstants.Property.NikonWbColorTemp);
118
+        addPropertyMapping(Camera.Property.ShootingMode, PtpConstants.Property.ExposureProgramMode);
119
+        addPropertyMapping(Camera.Property.BatteryLevel, PtpConstants.Property.BatteryLevel);
120
+        //addPropertyMapping(Camera.Property.AvailableShots, PtpConstants.Property);
121
+        addPropertyMapping(Camera.Property.FocusMode, PtpConstants.Property.FocusMode);
122
+        addPropertyMapping(Camera.Property.PictureStyle, PtpConstants.Property.NikonActivePicCtrlItem);
123
+        addPropertyMapping(Camera.Property.ExposureMeteringMode, PtpConstants.Property.ExposureMeteringMode);
124
+        addPropertyMapping(Camera.Property.FocusMeteringMode, PtpConstants.Property.FocusMeteringMode);
125
+        addPropertyMapping(Camera.Property.CurrentFocusPoint, PtpConstants.Property.NikonFocusArea);
126
+        addPropertyMapping(Camera.Property.CurrentExposureIndicator, PtpConstants.Property.NikonExposureIndicateStatus);
127
+        addPropertyMapping(Camera.Property.ExposureCompensation, PtpConstants.Property.ExposureBiasCompensation);
128
+
129
+        if (properties.contains(PtpConstants.Property.NikonEnableAfAreaPoint)) {
130
+            addInternalProperty(PtpConstants.Property.NikonEnableAfAreaPoint);
131
+        }
132
+
133
+        for (Integer property : properties) {
134
+            if (ptpToVirtualProperty.containsKey(property) || ptpInternalProperties.contains(property)) {
135
+                queue.add(new GetDevicePropDescCommand(this, property));
136
+            }
137
+        }
138
+    }
139
+
140
+    @Override
141
+    protected void openSession() {
142
+        queue.add(new NikonOpenSessionAction(this));
143
+    }
144
+
145
+    @Override
146
+    protected void closeSession() {
147
+        queue.add(new NikonCloseSessionAction(this));
148
+    }
149
+
150
+    @Override
151
+    protected void queueEventCheck() {
152
+        queue.add(new NikonEventCheckCommand(this));
153
+    }
154
+
155
+    @Override
156
+    public void onSessionOpened() {
157
+        super.onSessionOpened();
158
+        Set<Integer> properties = new HashSet<Integer>();
159
+        for (int i = 0; i < deviceInfo.devicePropertiesSupported.length; ++i) {
160
+            properties.add(deviceInfo.devicePropertiesSupported[i]);
161
+        }
162
+        for (int i = 0; i < vendorPropCodes.length; ++i) {
163
+            properties.add(vendorPropCodes[i]);
164
+        }
165
+        onPropertyCodesReceived(properties);
166
+    }
167
+
168
+    public void setVendorPropCodes(int[] vendorPropCodes) {
169
+        this.vendorPropCodes = vendorPropCodes;
170
+    }
171
+
172
+    @Override
173
+    public void retrievePicture(int objectHandle) {
174
+        queue.add(new RetrievePictureAction(this, objectHandle, pictureSampleSize));
175
+        queue.add(new SimpleCommand(this, PtpConstants.Operation.NikonDeleteImagesInSdram, objectHandle));
176
+    }
177
+
178
+    public void onEventObjectAdded(int objectHandle) {
179
+        queue.add(new RetrieveAddedObjectInfoAction(this, objectHandle));
180
+    }
181
+
182
+    public void onEventCaptureComplete() {
183
+        //TODO
184
+    }
185
+
186
+    public boolean hasSupportForOperation(int operation) {
187
+        return supportedOperations.contains(operation);
188
+    }
189
+
190
+    @Override
191
+    public void driveLens(int driveDirection, int pulses) {
192
+        queue.add(new SimpleCommand(this, Operation.NikonMfDrive, driveDirection == DriveLens.Far ? 0x02 : 0x01,
193
+                pulses * 300));
194
+    }
195
+
196
+    @Override
197
+    protected boolean isBulbCurrentShutterSpeed() {
198
+        //TODO
199
+        return false;
200
+    }
201
+
202
+    public void onLiveViewStoppedInternal() {
203
+        liveViewStoppedInternal = true;
204
+    }
205
+
206
+    @Override
207
+    public void setLiveView(boolean enabled) {
208
+        liveViewStoppedInternal = false;
209
+        if (enabled) {
210
+            queue.add(new NikonStartLiveViewAction(this));
211
+        } else {
212
+            queue.add(new NikonStopLiveViewAction(this, true));
213
+        }
214
+    }
215
+
216
+    @Override
217
+    public void getLiveViewPicture(LiveViewData reuse) {
218
+        if (liveViewSupported && liveViewStoppedInternal) {
219
+            liveViewStoppedInternal = false;
220
+            queue.add(new NikonGetLiveViewImageAction(this, reuse));
221
+        } else {
222
+            queue.add(new NikonGetLiveViewImageCommand(this, reuse));
223
+        }
224
+    }
225
+
226
+    @Override
227
+    public boolean isSettingPropertyPossible(int property) {
228
+        Integer mode = ptpProperties.get(PtpConstants.Property.ExposureProgramMode);
229
+        Integer wb = ptpProperties.get(PtpConstants.Property.WhiteBalance);
230
+        if (mode == null) {
231
+            return false;
232
+        }
233
+        switch (property) {
234
+        case Property.ShutterSpeed:
235
+            return mode == 4 || mode == 1;
236
+        case Property.ApertureValue:
237
+            return mode == 3 || mode == 1;
238
+        case Property.IsoSpeed: //TODO this should only be disabled for DIP when isoautosetting is on
239
+        case Property.Whitebalance:
240
+        case Property.ExposureMeteringMode:
241
+        case Property.ExposureCompensation:
242
+            return mode < 0x8010;
243
+        case Property.FocusPoints:
244
+            return true;
245
+        case Property.ColorTemperature:
246
+            return wb != null && wb == 0x8012;
247
+        default:
248
+            return true;
249
+        }
250
+    }
251
+
252
+    @Override
253
+    public void focus() {
254
+        queue.add(new NikonAfDriveCommand(this));
255
+    }
256
+
257
+    @Override
258
+    public void capture() {
259
+        if (liveViewOpen) {
260
+            queue.add(new NikonStopLiveViewAction(this, false));
261
+        }
262
+        queue.add(new InitiateCaptureCommand(this));
263
+    }
264
+
265
+    private int wholeWidth;
266
+    private int wholeHeight;
267
+    private int afAreaWidth;
268
+    private int afAreaHeight;
269
+
270
+    @Override
271
+    public void onLiveViewReceived(LiveViewData data) {
272
+        super.onLiveViewReceived(data);
273
+        if (data != null) {
274
+            wholeWidth = data.nikonWholeWidth;
275
+            wholeHeight = data.nikonWholeHeight;
276
+            afAreaWidth = data.nikonAfFrameWidth;
277
+            afAreaHeight = data.nikonAfFrameHeight;
278
+        }
279
+    }
280
+
281
+    @Override
282
+    public void setLiveViewAfArea(float posx, float posy) {
283
+        if (supportedOperations.contains(Operation.NikonChangeAfArea)) {
284
+            float centerx = Math.min(wholeWidth - (afAreaWidth >> 1), Math.max(afAreaWidth >> 1, posx * wholeWidth));
285
+            float centery = Math
286
+                    .min(wholeHeight - (afAreaHeight >> 1), Math.max(afAreaHeight >> 1, posy * wholeHeight));
287
+            queue.add(new SimpleCommand(this, PtpConstants.Operation.NikonChangeAfArea, (int) centerx, (int) centery));
288
+        }
289
+    }
290
+
291
+    @Override
292
+    public List<FocusPoint> getFocusPoints() {
293
+        List<FocusPoint> points = new ArrayList<FocusPoint>();
294
+        switch (productId) {
295
+        case PtpConstants.Product.NikonD40:
296
+        /* TODO no productId for D60 case PtpConstants.Product.NikonD60: */{
297
+            points.add(new FocusPoint(0, 0.5f, 0.5f, 0.04f));
298
+            points.add(new FocusPoint(0, 0.30f, 0.5f, 0.04f));
299
+            points.add(new FocusPoint(0, 0.70f, 0.5f, 0.04f));
300
+            return points;
301
+        }
302
+        case PtpConstants.Product.NikonD200:
303
+        case PtpConstants.Product.NikonD80: {
304
+            points.add(new FocusPoint(0, 0.5f, 0.5f, 0.04f));
305
+            points.add(new FocusPoint(1, 0.5f, 0.29f, 0.04f));
306
+            points.add(new FocusPoint(2, 0.5f, 0.71f, 0.04f));
307
+            points.add(new FocusPoint(3, 0.33f, 0.5f, 0.04f));
308
+            points.add(new FocusPoint(4, 0.67f, 0.5f, 0.04f));
309
+            points.add(new FocusPoint(5, 0.22f, 0.5f, 0.04f));
310
+            points.add(new FocusPoint(6, 0.78f, 0.5f, 0.04f));
311
+            points.add(new FocusPoint(7, 0.33f, 0.39f, 0.04f));
312
+            points.add(new FocusPoint(8, 0.67f, 0.39f, 0.04f));
313
+            points.add(new FocusPoint(9, 0.33f, 0.61f, 0.04f));
314
+            points.add(new FocusPoint(10, 0.67f, 0.61f, 0.04f));
315
+            return points;
316
+        }
317
+        case PtpConstants.Product.NikonD5000:
318
+        case PtpConstants.Product.NikonD90: {
319
+            points.add(new FocusPoint(1, 0.5f, 0.5f, 0.04f));
320
+            points.add(new FocusPoint(2, 0.5f, 0.3f, 0.04f));
321
+            points.add(new FocusPoint(3, 0.5f, 0.7f, 0.04f));
322
+            points.add(new FocusPoint(4, 0.33f, 0.5f, 0.04f));
323
+            points.add(new FocusPoint(5, 0.33f, 0.35f, 0.04f));
324
+            points.add(new FocusPoint(6, 0.33f, 0.65f, 0.04f));
325
+            points.add(new FocusPoint(7, 0.22f, 0.5f, 0.04f));
326
+            points.add(new FocusPoint(8, 0.67f, 0.5f, 0.04f));
327
+            points.add(new FocusPoint(9, 0.67f, 0.35f, 0.04f));
328
+            points.add(new FocusPoint(10, 0.67f, 0.65f, 0.04f));
329
+            points.add(new FocusPoint(11, 0.78f, 0.5f, 0.04f));
330
+            return points;
331
+        }
332
+        case PtpConstants.Product.NikonD300:
333
+            //case PtpConstants.Product.NikonD700: same id as d300
334
+        case PtpConstants.Product.NikonD300S:
335
+        case PtpConstants.Product.NikonD3:
336
+        case PtpConstants.Product.NikonD3S:
337
+        case PtpConstants.Product.NikonD3X: {
338
+            points.add(new FocusPoint(1, 0.5f, 0.5f, 0.035f));
339
+            points.add(new FocusPoint(3, 0.5f, 0.36f, 0.035f));
340
+            points.add(new FocusPoint(5, 0.5f, 0.64f, 0.035f));
341
+
342
+            points.add(new FocusPoint(21, 0.65f, 0.5f, 0.035f));
343
+            points.add(new FocusPoint(23, 0.65f, 0.4f, 0.035f));
344
+            points.add(new FocusPoint(25, 0.65f, 0.6f, 0.035f));
345
+            points.add(new FocusPoint(31, 0.75f, 0.5f, 0.035f));
346
+
347
+            points.add(new FocusPoint(39, 0.35f, 0.5f, 0.035f));
348
+            points.add(new FocusPoint(41, 0.35f, 0.4f, 0.035f));
349
+            points.add(new FocusPoint(43, 0.35f, 0.6f, 0.035f));
350
+            points.add(new FocusPoint(49, 0.25f, 0.5f, 0.035f));
351
+
352
+            if (enableAfAreaPoint == 0) {
353
+                //TODO has more points when EnableAFAreaPoint is 0
354
+            }
355
+            return points;
356
+        }
357
+        case PtpConstants.Product.NikonD7000: {
358
+            points.add(new FocusPoint(1, 0.5f, 0.5f, 0.035f));
359
+            points.add(new FocusPoint(3, 0.5f, 0.32f, 0.035f));
360
+            points.add(new FocusPoint(5, 0.5f, 0.68f, 0.035f));
361
+
362
+            points.add(new FocusPoint(19, 0.68f, 0.5f, 0.035f));
363
+            points.add(new FocusPoint(20, 0.68f, 0.4f, 0.035f));
364
+            points.add(new FocusPoint(21, 0.68f, 0.6f, 0.035f));
365
+            points.add(new FocusPoint(25, 0.80f, 0.5f, 0.035f));
366
+
367
+            points.add(new FocusPoint(31, 0.32f, 0.5f, 0.035f));
368
+            points.add(new FocusPoint(32, 0.32f, 0.4f, 0.035f));
369
+            points.add(new FocusPoint(33, 0.32f, 0.6f, 0.035f));
370
+            points.add(new FocusPoint(37, 0.20f, 0.5f, 0.035f));
371
+
372
+            if (enableAfAreaPoint == 0) {
373
+                //TODO has more points when EnableAFAreaPoint is 0
374
+            }
375
+            return points;
376
+        }
377
+        default:
378
+            return points;
379
+        }
380
+    }
381
+}

+ 162 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/PacketUtil.java

@@ -0,0 +1,162 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import android.util.Log;
21
+
22
+public class PacketUtil {
23
+
24
+    public static int[] readU32Array(ByteBuffer b) {
25
+        int len = b.getInt();
26
+        int[] a = new int[len];
27
+        for (int i = 0; i < len; ++i) {
28
+            a[i] = b.getInt();
29
+        }
30
+        return a;
31
+    }
32
+
33
+    public static int[] readU16Array(ByteBuffer b) {
34
+        int len = b.getInt();
35
+        int[] a = new int[len];
36
+        for (int i = 0; i < len; ++i) {
37
+            a[i] = b.getShort() & 0xFFFF;
38
+        }
39
+        return a;
40
+    }
41
+
42
+    public static void writeU16Array(ByteBuffer b, int[] a) {
43
+        b.putInt(a.length);
44
+        for (int v : a) {
45
+            b.putShort((short) v);
46
+        }
47
+    }
48
+
49
+    public static int[] readU8Array(ByteBuffer b) {
50
+        int len = b.getInt();
51
+        int[] a = new int[len];
52
+        for (int i = 0; i < len; ++i) {
53
+            a[i] = b.get() & 0xFF;
54
+        }
55
+        return a;
56
+    }
57
+
58
+    public static int[] readU32Enumeration(ByteBuffer b) {
59
+        int len = b.getShort() & 0xFFFF;
60
+        int[] a = new int[len];
61
+        for (int i = 0; i < len; ++i) {
62
+            a[i] = b.getInt();
63
+        }
64
+        return a;
65
+    }
66
+
67
+    public static int[] readS16Enumeration(ByteBuffer b) {
68
+        int len = b.getShort() & 0xFFFF;
69
+        int[] a = new int[len];
70
+        for (int i = 0; i < len; ++i) {
71
+            a[i] = b.getShort();
72
+        }
73
+        return a;
74
+    }
75
+
76
+    public static int[] readU16Enumeration(ByteBuffer b) {
77
+        int len = b.getShort() & 0xFFFF;
78
+        int[] a = new int[len];
79
+        for (int i = 0; i < len; ++i) {
80
+            a[i] = b.getShort() & 0xFFFF;
81
+        }
82
+        return a;
83
+    }
84
+
85
+    public static int[] readU8Enumeration(ByteBuffer b) {
86
+        int len = b.getShort() & 0xFFFF;
87
+        int[] a = new int[len];
88
+        for (int i = 0; i < len; ++i) {
89
+            a[i] = b.get() & 0xFF;
90
+        }
91
+        return a;
92
+    }
93
+
94
+    public static String readString(ByteBuffer b) {
95
+        int len = b.get() & 0xFF;
96
+        if (len > 0) {
97
+            char[] ch = new char[len - 1];
98
+            for (int i = 0; i < len - 1; ++i) {
99
+                ch[i] = b.getChar();
100
+            }
101
+            // read '\0'
102
+            b.getChar();
103
+            return String.copyValueOf(ch);
104
+        }
105
+        return "";
106
+    }
107
+
108
+    public static void writeString(ByteBuffer b, String s) {
109
+        b.put((byte) s.length());
110
+        if (s.length() > 0) {
111
+            for (int i = 0; i < s.length(); ++i) {
112
+                b.putShort((short) s.charAt(i));
113
+            }
114
+            b.putShort((short) 0);
115
+        }
116
+    }
117
+
118
+    public static String hexDumpToString(byte[] a, int offset, int len) {
119
+        int lines = len / 16;
120
+        int rest = len % 16;
121
+
122
+        StringBuilder b = new StringBuilder((lines + 1) * 97);
123
+
124
+        for (int i = 0; i < lines; ++i) {
125
+            b.append(String.format("%04x ", i * 16));
126
+            for (int k = 0; k < 16; ++k) {
127
+                b.append(String.format("%02x ", a[offset + i * 16 + k]));
128
+            }
129
+            for (int k = 0; k < 16; ++k) {
130
+                char ch = (char) a[offset + i * 16 + k];
131
+                b.append(ch >= 0x20 && ch <= 0x7E ? ch : '.');
132
+            }
133
+            b.append('\n');
134
+        }
135
+
136
+        if (rest != 0) {
137
+            b.append(String.format("%04x ", lines * 16));
138
+            for (int k = 0; k < rest; ++k) {
139
+                b.append(String.format("%02x ", a[offset + lines * 16 + k]));
140
+            }
141
+            for (int k = 0; k < (16 - rest) * 3; ++k) {
142
+                b.append(' ');
143
+            }
144
+            for (int k = 0; k < rest; ++k) {
145
+                char ch = (char) a[offset + lines * 16 + k];
146
+                b.append(ch >= 0x20 && ch <= 0x7E ? ch : '.');
147
+            }
148
+            b.append('\n');
149
+        }
150
+
151
+        return b.toString();
152
+    }
153
+
154
+    public static void logHexdump(String tag, byte[] a, int offset, int len) {
155
+        Log.i(tag, hexDumpToString(a, offset, len));
156
+    }
157
+
158
+    public static void logHexdump(String tag, byte[] a, int len) {
159
+        logHexdump(tag, a, 0, len);
160
+    }
161
+
162
+}

+ 35 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/PtpAction.java

@@ -0,0 +1,35 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp;
17
+
18
+/**
19
+ * {@code PtpActions} execute one or more {@code Command}s against the actual
20
+ * hardware.
21
+ *
22
+ * A {@code PtpCamera} queues {@Code PtpAction}s into the worker thread
23
+ * for further communications. The action should do the communication via the
24
+ * given {@code IO} interface and based on the received data and response repor
25
+ * back to the actual {@code PtpCamera}.
26
+ */
27
+public interface PtpAction {
28
+
29
+    void exec(PtpCamera.IO io);
30
+
31
+    /**
32
+     * Reset an already used action so it can be re-used.
33
+     */
34
+    void reset();
35
+}

+ 887 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/PtpCamera.java

@@ -0,0 +1,887 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp;
17
+
18
+import android.graphics.Bitmap;
19
+import android.hardware.usb.UsbRequest;
20
+import android.os.Handler;
21
+import android.util.Log;
22
+
23
+import com.remoteyourcam.usb.AppConfig;
24
+import com.remoteyourcam.usb.ptp.commands.CloseSessionCommand;
25
+import com.remoteyourcam.usb.ptp.commands.Command;
26
+import com.remoteyourcam.usb.ptp.commands.GetDeviceInfoCommand;
27
+import com.remoteyourcam.usb.ptp.commands.GetDevicePropValueCommand;
28
+import com.remoteyourcam.usb.ptp.commands.GetObjectHandlesCommand;
29
+import com.remoteyourcam.usb.ptp.commands.GetStorageInfosAction;
30
+import com.remoteyourcam.usb.ptp.commands.InitiateCaptureCommand;
31
+import com.remoteyourcam.usb.ptp.commands.InitiateOpenCaptureCommand;
32
+import com.remoteyourcam.usb.ptp.commands.OpenSessionCommand;
33
+import com.remoteyourcam.usb.ptp.commands.RetrieveImageAction;
34
+import com.remoteyourcam.usb.ptp.commands.RetrieveImageInfoAction;
35
+import com.remoteyourcam.usb.ptp.commands.RetrievePictureAction;
36
+import com.remoteyourcam.usb.ptp.commands.SetDevicePropValueCommand;
37
+import com.remoteyourcam.usb.ptp.commands.SimpleCommand;
38
+import com.remoteyourcam.usb.ptp.model.DeviceInfo;
39
+import com.remoteyourcam.usb.ptp.model.DevicePropDesc;
40
+import com.remoteyourcam.usb.ptp.model.LiveViewData;
41
+
42
+import java.io.File;
43
+import java.io.FileWriter;
44
+import java.io.IOException;
45
+import java.nio.ByteBuffer;
46
+import java.nio.ByteOrder;
47
+import java.util.Arrays;
48
+import java.util.HashMap;
49
+import java.util.HashSet;
50
+import java.util.Map;
51
+import java.util.Set;
52
+import java.util.concurrent.LinkedBlockingQueue;
53
+import java.util.concurrent.TimeUnit;
54
+
55
+public abstract class PtpCamera implements Camera {
56
+
57
+    public interface IO {
58
+        void handleCommand(Command command);
59
+    }
60
+
61
+    enum State {
62
+        // initial state
63
+        Starting,
64
+        // open session
65
+        Active,
66
+        // someone has asked to close session
67
+        Stoping,
68
+        // thread has stopped
69
+        Stopped,
70
+        // error happened
71
+        Error
72
+    }
73
+
74
+    private static final String TAG = PtpCamera.class.getSimpleName();
75
+
76
+    private final WorkerThread workerThread = new WorkerThread();
77
+    private final PtpUsbConnection connection;
78
+
79
+    protected final Handler handler = new Handler();
80
+    protected final LinkedBlockingQueue<PtpAction> queue = new LinkedBlockingQueue<PtpAction>();
81
+    protected CameraListener listener;
82
+    protected State state;
83
+
84
+    private int transactionId;
85
+    protected DeviceInfo deviceInfo;
86
+
87
+    protected boolean histogramSupported;
88
+    protected boolean liveViewSupported;
89
+    protected boolean liveViewAfAreaSupported;
90
+    protected boolean liveViewOpen;
91
+
92
+    protected boolean bulbSupported;
93
+
94
+    protected boolean driveLensSupported;
95
+
96
+    protected boolean autoFocusSupported;
97
+
98
+    protected boolean cameraIsCapturing;
99
+
100
+    protected final Map<Integer, Integer> virtualToPtpProperty = new HashMap<Integer, Integer>();
101
+    protected final Map<Integer, Integer> ptpToVirtualProperty = new HashMap<Integer, Integer>();
102
+
103
+    // current property values and descriptions
104
+    protected final Map<Integer, DevicePropDesc> ptpPropertyDesc = new HashMap<Integer, DevicePropDesc>();
105
+    protected final Map<Integer, Integer> ptpProperties = new HashMap<Integer, Integer>();
106
+    protected final Map<Integer, Integer> properties = new HashMap<Integer, Integer>();
107
+    private final Map<Integer, int[]> propertyDescriptions = new HashMap<Integer, int[]>();
108
+    protected final Set<Integer> ptpInternalProperties = new HashSet<Integer>();
109
+
110
+    private final int vendorId;
111
+    protected final int productId;
112
+
113
+    private WorkerListener workerListener;
114
+    protected int pictureSampleSize;
115
+
116
+    public PtpCamera(PtpUsbConnection connection, CameraListener listener, WorkerListener workerListener) {
117
+        this.connection = connection;
118
+        this.listener = listener;
119
+        this.workerListener = workerListener;
120
+        this.pictureSampleSize = 2;
121
+        state = State.Starting;
122
+        vendorId = connection.getVendorId();
123
+        productId = connection.getProductId();
124
+        queue.add(new GetDeviceInfoCommand(this));
125
+        openSession();
126
+        workerThread.start();
127
+        if (AppConfig.LOG) {
128
+            Log.i(TAG, String.format("Starting session for %04x %04x", vendorId, productId));
129
+        }
130
+    }
131
+
132
+    protected void addPropertyMapping(int virtual, int ptp) {
133
+        ptpToVirtualProperty.put(ptp, virtual);
134
+        virtualToPtpProperty.put(virtual, ptp);
135
+    }
136
+
137
+    protected void addInternalProperty(int ptp) {
138
+        ptpInternalProperties.add(ptp);
139
+    }
140
+
141
+    public void setListener(CameraListener listener) {
142
+        this.listener = listener;
143
+    }
144
+
145
+    public void shutdown() {
146
+        state = State.Stoping;
147
+        workerThread.lastEventCheck = System.currentTimeMillis() + 1000000L;
148
+        queue.clear();
149
+        if (liveViewOpen) {
150
+            //TODO
151
+            setLiveView(false);
152
+        }
153
+        closeSession();
154
+    }
155
+
156
+    public void shutdownHard() {
157
+        state = State.Stopped;
158
+        synchronized (workerThread) {
159
+            workerThread.stop = true;
160
+        }
161
+        if (connection != null) {
162
+            connection.close();
163
+            //TODO possible NPE, need to join workerThread
164
+            //connection = null;
165
+        }
166
+    }
167
+
168
+    public State getState() {
169
+        return state;
170
+    }
171
+
172
+    public int nextTransactionId() {
173
+        return transactionId++;
174
+    }
175
+
176
+    public int currentTransactionId() {
177
+        return transactionId;
178
+    }
179
+
180
+    public void resetTransactionId() {
181
+        transactionId = 0;
182
+    }
183
+
184
+    public int getProductId() {
185
+        return productId;
186
+    }
187
+
188
+    public void setDeviceInfo(DeviceInfo deviceInfo) {
189
+        if (AppConfig.LOG) {
190
+            Log.i(TAG, deviceInfo.toString());
191
+        }
192
+        this.deviceInfo = deviceInfo;
193
+
194
+        Set<Integer> operations = new HashSet<Integer>();
195
+        for (int i = 0; i < deviceInfo.operationsSupported.length; ++i) {
196
+            operations.add(deviceInfo.operationsSupported[i]);
197
+        }
198
+
199
+        onOperationCodesReceived(operations);
200
+    }
201
+
202
+    public void enqueue(final Command cmd, int delay) {
203
+        handler.postDelayed(new Runnable() {
204
+            @Override
205
+            public void run() {
206
+                if (state == State.Active) {
207
+                    queue.add(cmd);
208
+                }
209
+            }
210
+        }, delay);
211
+    }
212
+
213
+    /**
214
+     * Deriving classes should override this method to get the set of supported
215
+     * operations of the camera. Based on this information functionality has to
216
+     * be enabled/disabled.
217
+     */
218
+    protected abstract void onOperationCodesReceived(Set<Integer> operations);
219
+
220
+    public int getPtpProperty(int property) {
221
+        Integer value = ptpProperties.get(property);
222
+        return value != null ? value : 0;
223
+    }
224
+
225
+    public void onSessionOpened() {
226
+        state = State.Active;
227
+        handler.post(new Runnable() {
228
+            @Override
229
+            public void run() {
230
+                if (listener != null) {
231
+                    listener.onCameraStarted(PtpCamera.this);
232
+                }
233
+            }
234
+        });
235
+    }
236
+
237
+    public void onSessionClosed() {
238
+        shutdownHard();
239
+        handler.post(new Runnable() {
240
+            @Override
241
+            public void run() {
242
+                if (listener != null) {
243
+                    listener.onCameraStopped(PtpCamera.this);
244
+                }
245
+            }
246
+        });
247
+    }
248
+
249
+    public void onPropertyChanged(int property, final int value) {
250
+        Log.i(TAG, "p " + property + " " + value);
251
+        ptpProperties.put(property, value);
252
+        final Integer virtual = ptpToVirtualProperty.get(property);
253
+        if (AppConfig.LOG) {
254
+            Log.d(TAG, String.format("onPropertyChanged %s %s(%d)", PtpConstants.propertyToString(property),
255
+                    virtual != null ? propertyToString(virtual, value) : "", value));
256
+        }
257
+        if (virtual != null) {
258
+            handler.post(new Runnable() {
259
+                @Override
260
+                public void run() {
261
+                    properties.put(virtual, value);
262
+                    if (listener != null) {
263
+                        listener.onPropertyChanged(virtual, value);
264
+                    }
265
+                }
266
+            });
267
+        }
268
+    }
269
+
270
+    public void onPropertyDescChanged(int property, final int[] values) {
271
+        //if (BuildConfig.LOG) {
272
+            Log.d(TAG,
273
+                    String.format("onPropertyDescChanged %s:\n%s", PtpConstants.propertyToString(property),
274
+                            Arrays.toString(values)));
275
+        //}
276
+        final Integer virtual = ptpToVirtualProperty.get(property);
277
+        if (virtual != null) {
278
+            handler.post(new Runnable() {
279
+                @Override
280
+                public void run() {
281
+                    propertyDescriptions.put(virtual, values);
282
+                    if (listener != null) {
283
+                        listener.onPropertyDescChanged(virtual, values);
284
+                    }
285
+                }
286
+            });
287
+        }
288
+    }
289
+
290
+    public void onPropertyDescChanged(int property, DevicePropDesc desc) {
291
+        ptpPropertyDesc.put(property, desc);
292
+        onPropertyDescChanged(property, desc.description);
293
+    }
294
+
295
+    public void onLiveViewStarted() {
296
+        liveViewOpen = true;
297
+        handler.post(new Runnable() {
298
+            @Override
299
+            public void run() {
300
+                if (listener != null) {
301
+                    listener.onLiveViewStarted();
302
+                }
303
+            }
304
+        });
305
+    }
306
+
307
+    public void onLiveViewRestarted() {
308
+        liveViewOpen = true;
309
+        handler.post(new Runnable() {
310
+            @Override
311
+            public void run() {
312
+                if (listener != null) {
313
+                    listener.onLiveViewStarted();
314
+                }
315
+            }
316
+        });
317
+    }
318
+
319
+    public void onLiveViewStopped() {
320
+        liveViewOpen = false;
321
+        handler.post(new Runnable() {
322
+            @Override
323
+            public void run() {
324
+                if (listener != null) {
325
+                    listener.onLiveViewStopped();
326
+                }
327
+            }
328
+        });
329
+    }
330
+
331
+    public void onLiveViewReceived(final LiveViewData data) {
332
+        handler.post(new Runnable() {
333
+            @Override
334
+            public void run() {
335
+                if (listener != null) {
336
+                    listener.onLiveViewData(data);
337
+                }
338
+            }
339
+        });
340
+    }
341
+
342
+    public void onPictureReceived(final int objectHandle, final String filename, final Bitmap thumbnail,
343
+            final Bitmap bitmap) {
344
+        handler.post(new Runnable() {
345
+            @Override
346
+            public void run() {
347
+                if (listener != null) {
348
+                    listener.onCapturedPictureReceived(objectHandle, filename, thumbnail, bitmap);
349
+                }
350
+            }
351
+        });
352
+    }
353
+
354
+    public void onEventCameraCapture(boolean started) {
355
+        cameraIsCapturing = started;
356
+        if (isBulbCurrentShutterSpeed()) {
357
+            handler.post(new Runnable() {
358
+                @Override
359
+                public void run() {
360
+                    if (listener != null) {
361
+                        if (cameraIsCapturing) {
362
+                            listener.onBulbStarted();
363
+                        } else {
364
+                            listener.onBulbStopped();
365
+                        }
366
+                    }
367
+                }
368
+            });
369
+        }
370
+    }
371
+
372
+    public void onEventDevicePropChanged(int property) {
373
+        if ((ptpToVirtualProperty.containsKey(property) || ptpInternalProperties.contains(property))
374
+                && ptpPropertyDesc.containsKey(property)) {
375
+            DevicePropDesc desc = ptpPropertyDesc.get(property);
376
+            queue.add(new GetDevicePropValueCommand(this, property, desc.datatype));
377
+        }
378
+    }
379
+
380
+    public void onEventObjectAdded(final int handle) {
381
+        handler.post(new Runnable() {
382
+            @Override
383
+            public void run() {
384
+                if (listener != null) {
385
+                    listener.onObjectAdded(handle);
386
+                }
387
+            }
388
+        });
389
+    }
390
+
391
+    public void onBulbExposureTime(final int seconds) {
392
+        if (seconds >= 0 && seconds <= 360000) {
393
+            handler.post(new Runnable() {
394
+                @Override
395
+                public void run() {
396
+                    if (listener != null) {
397
+                        listener.onBulbExposureTime(seconds);
398
+                    }
399
+                }
400
+            });
401
+        }
402
+    }
403
+
404
+    public void onFocusStarted() {
405
+        handler.post(new Runnable() {
406
+            @Override
407
+            public void run() {
408
+                if (listener != null) {
409
+                    listener.onFocusStarted();
410
+                }
411
+            }
412
+        });
413
+    }
414
+
415
+    public void onFocusEnded(final boolean hasFocused) {
416
+        handler.post(new Runnable() {
417
+            @Override
418
+            public void run() {
419
+                if (listener != null) {
420
+                    listener.onFocusEnded(hasFocused);
421
+                }
422
+            }
423
+        });
424
+    }
425
+
426
+    public void onDeviceBusy(PtpAction action, boolean requeue) {
427
+        if (AppConfig.LOG) {
428
+            Log.i(TAG, "onDeviceBusy, sleeping a bit");
429
+        }
430
+        if (requeue) {
431
+            action.reset();
432
+            queue.add(action);
433
+        }
434
+        try {
435
+            Thread.sleep(200);
436
+        } catch (InterruptedException e) {
437
+            // nop
438
+        }
439
+    }
440
+
441
+    public void onPtpWarning(final String message) {
442
+        if (AppConfig.LOG) {
443
+            Log.i(TAG, "onPtpWarning: " + message);
444
+        }
445
+    }
446
+
447
+    public void onPtpError(final String message) {
448
+        if (AppConfig.LOG) {
449
+            Log.e(TAG, "onPtpError: " + message);
450
+        }
451
+        state = State.Error;
452
+        if (state == State.Active) {
453
+            shutdown();
454
+        } else {
455
+            shutdownHard();
456
+        }
457
+        handler.post(new Runnable() {
458
+            @Override
459
+            public void run() {
460
+                if (listener != null) {
461
+                    listener.onError(message);
462
+                }
463
+            }
464
+        });
465
+    }
466
+
467
+    private void onUsbError(final String message) {
468
+        if (AppConfig.LOG) {
469
+            Log.e(TAG, "onUsbError: " + message);
470
+        }
471
+        queue.clear();
472
+        shutdownHard();
473
+        state = State.Error;
474
+        handler.post(new Runnable() {
475
+            @Override
476
+            public void run() {
477
+                if (listener != null) {
478
+                    listener.onError(String.format("Error in USB communication: %s", message));
479
+                }
480
+            }
481
+        });
482
+    }
483
+
484
+    protected abstract void queueEventCheck();
485
+
486
+    protected abstract boolean isBulbCurrentShutterSpeed();
487
+
488
+    private class WorkerThread extends Thread implements IO {
489
+        public boolean stop;
490
+
491
+        private int maxPacketOutSize;
492
+        private int maxPacketInSize;
493
+        private long lastEventCheck;
494
+        private UsbRequest r1;
495
+        private UsbRequest r2;
496
+        private UsbRequest r3;
497
+        private final int bigInSize = 0x4000;
498
+        // buffers for async data io, size bigInSize
499
+        private ByteBuffer bigIn1;
500
+        private ByteBuffer bigIn2;
501
+        private ByteBuffer bigIn3;
502
+        // buffer for small packets like command and response
503
+        private ByteBuffer smallIn;
504
+        // buffer containing full data out packet for processing
505
+        private int fullInSize = 0x4000;
506
+        private ByteBuffer fullIn;
507
+
508
+        @Override
509
+        public void run() {
510
+
511
+            notifyWorkStarted();
512
+
513
+            maxPacketOutSize = connection.getMaxPacketOutSize();
514
+            maxPacketInSize = connection.getMaxPacketInSize();
515
+
516
+            if (maxPacketOutSize <= 0 || maxPacketOutSize > 0xffff) {
517
+                onUsbError(String.format("Usb initialization error: out size invalid %d", maxPacketOutSize));
518
+                return;
519
+            }
520
+
521
+            if (maxPacketInSize <= 0 || maxPacketInSize > 0xffff) {
522
+                onUsbError(String.format("usb initialization error: in size invalid %d", maxPacketInSize));
523
+                return;
524
+            }
525
+
526
+            smallIn = ByteBuffer.allocate(Math.max(maxPacketInSize, maxPacketOutSize));
527
+            smallIn.order(ByteOrder.LITTLE_ENDIAN);
528
+
529
+            bigIn1 = ByteBuffer.allocate(bigInSize);
530
+            bigIn1.order(ByteOrder.LITTLE_ENDIAN);
531
+            bigIn2 = ByteBuffer.allocate(bigInSize);
532
+            bigIn2.order(ByteOrder.LITTLE_ENDIAN);
533
+            bigIn3 = ByteBuffer.allocate(bigInSize);
534
+            bigIn3.order(ByteOrder.LITTLE_ENDIAN);
535
+
536
+            fullIn = ByteBuffer.allocate(fullInSize);
537
+            fullIn.order(ByteOrder.LITTLE_ENDIAN);
538
+
539
+            r1 = connection.createInRequest();
540
+            r2 = connection.createInRequest();
541
+            r3 = connection.createInRequest();
542
+
543
+            while (true) {
544
+                synchronized (this) {
545
+                    if (stop) {
546
+                        break;
547
+                    }
548
+                }
549
+
550
+                if (lastEventCheck + AppConfig.EVENTCHECK_PERIOD < System.currentTimeMillis()) {
551
+                    lastEventCheck = System.currentTimeMillis();
552
+                    PtpCamera.this.queueEventCheck();
553
+                }
554
+
555
+                PtpAction action = null;
556
+                try {
557
+                    action = queue.poll(1000, TimeUnit.MILLISECONDS);
558
+                } catch (InterruptedException e) {
559
+                    // nop
560
+                }
561
+
562
+                if (action != null) {
563
+                    action.exec(this);
564
+                }
565
+            }
566
+            r3.close();
567
+            r2.close();
568
+            r1.close();
569
+
570
+            notifyWorkEnded();
571
+        }
572
+
573
+        @Override
574
+        public void handleCommand(Command command) {
575
+            if (AppConfig.LOG) {
576
+                Log.i(TAG, "handling command " + command.getClass().getSimpleName());
577
+            }
578
+
579
+            ByteBuffer b = smallIn;
580
+            b.position(0);
581
+            command.encodeCommand(b);
582
+
583
+            int outLen = b.position();
584
+
585
+            int res = connection.bulkTransferOut(b.array(), outLen, AppConfig.USB_TRANSFER_TIMEOUT);
586
+            if (res < outLen) {
587
+                onUsbError(String.format("Code CP %d %d", res, outLen));
588
+                return;
589
+            }
590
+
591
+            if (command.hasDataToSend()) {
592
+                b = ByteBuffer.allocate(connection.getMaxPacketOutSize());
593
+                b.order(ByteOrder.LITTLE_ENDIAN);
594
+                command.encodeData(b);
595
+                outLen = b.position();
596
+                res = connection.bulkTransferOut(b.array(), outLen, AppConfig.USB_TRANSFER_TIMEOUT);
597
+                if (res < outLen) {
598
+                    onUsbError(String.format("Code DP %d %d", res, outLen));
599
+                    return;
600
+                }
601
+            }
602
+
603
+            while (!command.hasResponseReceived()) {
604
+                int maxPacketSize = maxPacketInSize;
605
+                ByteBuffer in = smallIn;
606
+                in.position(0);
607
+
608
+                res = 0;
609
+                while (res == 0) {
610
+                    res = connection.bulkTransferIn(in.array(), maxPacketSize, AppConfig.USB_TRANSFER_TIMEOUT);
611
+                }
612
+                if (res < 12) {
613
+                    onUsbError(String.format("Couldn't read header, only %d bytes available!", res));
614
+                    return;
615
+                }
616
+
617
+                int read = res;
618
+                int length = in.getInt();
619
+                ByteBuffer infull = null;
620
+
621
+                if (read < length) {
622
+                    if (length > fullInSize) {
623
+                        fullInSize = (int) (length * 1.5);
624
+                        fullIn = ByteBuffer.allocate(fullInSize);
625
+                        fullIn.order(ByteOrder.LITTLE_ENDIAN);
626
+                    }
627
+                    infull = fullIn;
628
+                    infull.position(0);
629
+                    infull.put(in.array(), 0, read);
630
+                    maxPacketSize = bigInSize;
631
+
632
+                    int nextSize = Math.min(maxPacketSize, length - read);
633
+                    int nextSize2 = Math.max(0, Math.min(maxPacketSize, length - read - nextSize));
634
+                    int nextSize3 = 0;
635
+
636
+                    r1.queue(bigIn1, nextSize);
637
+
638
+                    if (nextSize2 > 0) {
639
+                        r2.queue(bigIn2, nextSize2);
640
+                    }
641
+
642
+                    while (read < length) {
643
+
644
+                        nextSize3 = Math.max(0, Math.min(maxPacketSize, length - read - nextSize - nextSize2));
645
+
646
+                        if (nextSize3 > 0) {
647
+                            bigIn3.position(0);
648
+                            r3.queue(bigIn3, nextSize3);
649
+                        }
650
+
651
+                        if (nextSize > 0) {
652
+                            connection.requestWait();
653
+                            System.arraycopy(bigIn1.array(), 0, infull.array(), read, nextSize);
654
+                            read += nextSize;
655
+                        }
656
+
657
+                        nextSize = Math.max(0, Math.min(maxPacketSize, length - read - nextSize2 - nextSize3));
658
+
659
+                        if (nextSize > 0) {
660
+                            bigIn1.position(0);
661
+                            r1.queue(bigIn1, nextSize);
662
+                        }
663
+
664
+                        if (nextSize2 > 0) {
665
+                            connection.requestWait();
666
+                            System.arraycopy(bigIn2.array(), 0, infull.array(), read, nextSize2);
667
+                            read += nextSize2;
668
+                        }
669
+
670
+                        nextSize2 = Math.max(0, Math.min(maxPacketSize, length - read - nextSize - nextSize3));
671
+
672
+                        if (nextSize2 > 0) {
673
+                            bigIn2.position(0);
674
+                            r2.queue(bigIn2, nextSize2);
675
+                        }
676
+
677
+                        if (nextSize3 > 0) {
678
+                            connection.requestWait();
679
+                            System.arraycopy(bigIn3.array(), 0, infull.array(), read, nextSize3);
680
+                            read += nextSize3;
681
+                        }
682
+                    }
683
+                } else {
684
+                    infull = in;
685
+                }
686
+
687
+                infull.position(0);
688
+                try {
689
+                    command.receivedRead(infull);
690
+                    infull = null;
691
+                } catch (RuntimeException e) {
692
+                    // TODO user could send us some data here
693
+                    if (AppConfig.LOG) {
694
+                        Log.e(TAG, "Exception " + e.getLocalizedMessage());
695
+                        e.printStackTrace();
696
+                    }
697
+                    onPtpError(String.format("Error parsing %s with length %d", command.getClass().getSimpleName(),
698
+                            length));
699
+                }
700
+            }
701
+        }
702
+
703
+        private void notifyWorkStarted() {
704
+            WorkerListener l = workerListener;
705
+            if (l != null) {
706
+                l.onWorkerStarted();
707
+            }
708
+        }
709
+
710
+        private void notifyWorkEnded() {
711
+            WorkerListener l = workerListener;
712
+            if (l != null) {
713
+                l.onWorkerEnded();
714
+            }
715
+        }
716
+    }
717
+
718
+    protected void openSession() {
719
+        queue.add(new OpenSessionCommand(this));
720
+    }
721
+
722
+    protected void closeSession() {
723
+        queue.add(new CloseSessionCommand(this));
724
+    }
725
+
726
+    @Override
727
+    public void setWorkerListener(WorkerListener listener) {
728
+        workerListener = listener;
729
+    }
730
+
731
+    @Override
732
+    public String getDeviceName() {
733
+        return deviceInfo != null ? deviceInfo.model : "";
734
+    }
735
+
736
+    @Override
737
+    public boolean isSessionOpen() {
738
+        return state == State.Active;
739
+    }
740
+
741
+    @Override
742
+    public int getProperty(final int property) {
743
+        if (properties.containsKey(property)) {
744
+            return properties.get(property);
745
+        }
746
+        return 0x7fffffff;
747
+    }
748
+
749
+    @Override
750
+    public boolean getPropertyEnabledState(int property) {
751
+        // TODO Auto-generated method stub
752
+        return false;
753
+    }
754
+
755
+    @Override
756
+    public int[] getPropertyDesc(int property) {
757
+        if (propertyDescriptions.containsKey(property)) {
758
+            return propertyDescriptions.get(property);
759
+        }
760
+        return new int[0];
761
+    }
762
+
763
+    @Override
764
+    public void setProperty(int property, int value) {
765
+        final Integer ptpProperty = virtualToPtpProperty.get(property);
766
+        if (ptpProperty != null && ptpPropertyDesc.containsKey(ptpProperty)) {
767
+            queue.add(new SetDevicePropValueCommand(this, ptpProperty, value, ptpPropertyDesc.get(ptpProperty).datatype));
768
+        }
769
+    }
770
+
771
+    @Override
772
+    public String propertyToString(int property, int value) {
773
+        Integer ptpProperty = virtualToPtpProperty.get(property);
774
+        if (ptpProperty != null) {
775
+            String text = PtpPropertyHelper.mapToString(productId, ptpProperty, value);
776
+            return text != null ? text : "?";
777
+        } else {
778
+            return "";
779
+        }
780
+    }
781
+
782
+    @Override
783
+    public Integer propertyToIcon(int property, int value) {
784
+        Integer ptpProperty = virtualToPtpProperty.get(property);
785
+        if (ptpProperty != null) {
786
+            Integer iconId = PtpPropertyHelper.mapToDrawable(ptpProperty, value);
787
+            return iconId != null ? iconId : null;
788
+        } else {
789
+            return null;
790
+        }
791
+    }
792
+
793
+    @Override
794
+    public String getBiggestPropertyValue(int property) {
795
+        Integer ptpProperty = virtualToPtpProperty.get(property);
796
+        if (ptpProperty != null) {
797
+            return PtpPropertyHelper.getBiggestValue(ptpProperty);
798
+        } else {
799
+            return "";
800
+        }
801
+    }
802
+
803
+    @Override
804
+    public void capture() {
805
+        queue.add(new InitiateCaptureCommand(this));
806
+    }
807
+
808
+    @Override
809
+    public void openCapture() {
810
+        queue.add(new InitiateOpenCaptureCommand(this));
811
+    }
812
+
813
+    @Override
814
+    public boolean isAutoFocusSupported() {
815
+        return autoFocusSupported;
816
+    }
817
+
818
+    @Override
819
+    public boolean isLiveViewSupported() {
820
+        return liveViewSupported;
821
+    }
822
+
823
+    @Override
824
+    public boolean isLiveViewAfAreaSupported() {
825
+        return liveViewAfAreaSupported;
826
+    }
827
+
828
+    @Override
829
+    public boolean isHistogramSupported() {
830
+        return histogramSupported;
831
+    }
832
+
833
+    @Override
834
+    public boolean isLiveViewOpen() {
835
+        return liveViewOpen;
836
+    }
837
+
838
+    @Override
839
+    public boolean isDriveLensSupported() {
840
+        return driveLensSupported;
841
+    }
842
+
843
+    @Override
844
+    public String getDeviceInfo() {
845
+        return deviceInfo != null ? deviceInfo.toString() : "unknown";
846
+    }
847
+
848
+    @Override
849
+    public void writeDebugInfo(File out) {
850
+        try {
851
+            FileWriter writer = new FileWriter(out);
852
+            writer.append(deviceInfo.toString());
853
+            writer.close();
854
+        } catch (IOException e) {
855
+        }
856
+    }
857
+
858
+    @Override
859
+    public void retrievePicture(int objectHandle) {
860
+        queue.add(new RetrievePictureAction(this, objectHandle, pictureSampleSize));
861
+    }
862
+
863
+    @Override
864
+    public void retrieveStorages(StorageInfoListener listener) {
865
+        queue.add(new GetStorageInfosAction(this, listener));
866
+    }
867
+
868
+    @Override
869
+    public void retrieveImageHandles(StorageInfoListener listener, int storageId, int objectFormat) {
870
+        queue.add(new GetObjectHandlesCommand(this, listener, storageId, objectFormat));
871
+    }
872
+
873
+    @Override
874
+    public void retrieveImageInfo(RetrieveImageInfoListener listener, int objectHandle) {
875
+        queue.add(new RetrieveImageInfoAction(this, listener, objectHandle));
876
+    }
877
+
878
+    @Override
879
+    public void retrieveImage(RetrieveImageListener listener, int objectHandle) {
880
+        queue.add(new RetrieveImageAction(this, listener, objectHandle, pictureSampleSize));
881
+    }
882
+
883
+    @Override
884
+    public void setCapturedPictureSampleSize(int sampleSize) {
885
+        this.pictureSampleSize = sampleSize;
886
+    }
887
+}

+ 501 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/PtpConstants.java

@@ -0,0 +1,501 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp;
17
+
18
+import java.io.BufferedReader;
19
+import java.io.BufferedWriter;
20
+import java.io.IOException;
21
+import java.io.InputStreamReader;
22
+import java.io.OutputStreamWriter;
23
+import java.lang.reflect.Field;
24
+import java.lang.reflect.Modifier;
25
+
26
+public class PtpConstants {
27
+
28
+    public static final int CanonVendorId = 0x04a9;
29
+    public static final int NikonVendorId = 0x04b0;
30
+
31
+    public static boolean isCompatibleVendor(int vendorId) {
32
+        return vendorId == CanonVendorId || vendorId == NikonVendorId;
33
+    }
34
+
35
+    public static class Product {
36
+        // TODO D60 seems not to have a unique id
37
+        //public static final int NikonD700 = 0x041A; // Same as D300?
38
+        public static final int NikonD300 = 0x041A;
39
+        public static final int NikonD300S = 0x0425;
40
+        public static final int NikonD5000 = 0x0423;
41
+        public static final int NikonD5100 = 0x0429;
42
+        public static final int NikonD7000 = 0x0428;
43
+        public static final int NikonD80 = 0x0412;
44
+        public static final int NikonD200 = 0x0410;
45
+        public static final int NikonD3 = 0x041C;
46
+        public static final int NikonD3S = 0x0426;
47
+        public static final int NikonD3X = 0x0420;
48
+        public static final int NikonD40 = 0x0414;
49
+        public static final int NikonD90 = 0x0421;
50
+        public static final int NikonD700 = 0x0422;
51
+    }
52
+
53
+    public static class Type {
54
+        public static final int Undefined = 0;
55
+        public static final int Command = 1;
56
+        public static final int Data = 2;
57
+        public static final int Response = 3;
58
+        public static final int Event = 4;
59
+    }
60
+
61
+    public static String typeToString(int type) {
62
+        return constantToString(Type.class, type);
63
+    }
64
+
65
+    public static class Operation {
66
+        public static final int UndefinedOperationCode = 0x1000;
67
+        public static final int GetDeviceInfo = 0x1001;
68
+        public static final int OpenSession = 0x1002;
69
+        public static final int CloseSession = 0x1003;
70
+        public static final int GetStorageIDs = 0x1004;
71
+        public static final int GetStorageInfo = 0x1005;
72
+        public static final int GetNumObjects = 0x1006;
73
+        public static final int GetObjectHandles = 0x1007;
74
+        public static final int GetObjectInfo = 0x1008;
75
+        public static final int GetObject = 0x1009;
76
+        public static final int GetThumb = 0x100A;
77
+        public static final int DeleteObject = 0x100B;
78
+        public static final int SendObjectInfo = 0x100C;
79
+        public static final int SendObject = 0x100D;
80
+        public static final int InitiateCapture = 0x100E;
81
+        public static final int FormatStore = 0x100F;
82
+        public static final int ResetDevice = 0x1010;
83
+        public static final int SelfTest = 0x1011;
84
+        public static final int SetObjectProtection = 0x1012;
85
+        public static final int PowerDown = 0x1013;
86
+        public static final int GetDevicePropDesc = 0x1014;
87
+        public static final int GetDevicePropValue = 0x1015;
88
+        public static final int SetDevicePropValue = 0x1016;
89
+        public static final int ResetDevicePropValue = 0x1017;
90
+        public static final int TerminateOpenCapture = 0x1018;
91
+        public static final int MoveObject = 0x1019;
92
+        public static final int CopyObject = 0x101A;
93
+        public static final int GetPartialObject = 0x101B;
94
+        public static final int InitiateOpenCapture = 0x101C;
95
+
96
+        public static final int NikonInitiateCaptureRecInSdram = 0x90C0;
97
+        public static final int NikonAfDrive = 0x90C1;
98
+        public static final int NikonChangeCameraMode = 0x90C2;
99
+        public static final int NikonDeleteImagesInSdram = 0x90C3;
100
+        public static final int NikonGetLargeThumb = 0x90C4;
101
+        public static final int NikonGetEvent = 0x90C7;
102
+        public static final int NikonDeviceReady = 0x90C8;
103
+        public static final int NikonSetPreWbData = 0x90C9;
104
+        public static final int NikonGetVendorPropCodes = 0x90CA;
105
+        public static final int NikonAfAndCaptureInSdram = 0x90CB;
106
+        public static final int NikonGetPicCtrlData = 0x90CC;
107
+        public static final int NikonSetPicCtrlData = 0x90CD;
108
+        public static final int NikonDeleteCustomPicCtrl = 0x90CE;
109
+        public static final int NikonGetPicCtrlCapability = 0x90CF;
110
+        public static final int NikonGetPreviewImage = 0x9200;
111
+        public static final int NikonStartLiveView = 0x9201;
112
+        public static final int NikonEndLiveView = 0x9202;
113
+        public static final int NikonGetLiveViewImage = 0x9203;
114
+        public static final int NikonMfDrive = 0x9204;
115
+        public static final int NikonChangeAfArea = 0x9205;
116
+        public static final int NikonAfDriveCancel = 0x9206;
117
+        public static final int NikonInitiateCaptureRecInMedia = 0x9207;
118
+        public static final int NikonGetObjectPropsSupported = 0x9801;
119
+        public static final int NikonGetObjectPropDesc = 0x9802;
120
+        public static final int NikonGetObjectPropValue = 0x9803;
121
+        public static final int NikonGetObjectPropList = 0x9805;
122
+        public static final int NikonGetVendorStorageIDs = 0x9209;
123
+        public static final int NIKONStartMovieRecInCard = 0x920a;
124
+        public static final int NIKONEndMovieRec = 0x920b;
125
+        public static final int NIKONTerminateCapture = 0x920c;
126
+        public static final int NIKONGetPartialObjectHiSpeed = 0x920b;
127
+
128
+        // Canon EOS
129
+        public static final int EosTakePicture = 0x910F;
130
+        public static final int EosSetDevicePropValue = 0x9110;
131
+        public static final int EosSetPCConnectMode = 0x9114;
132
+        public static final int EosSetEventMode = 0x9115;
133
+        public static final int EosEventCheck = 0x9116;
134
+        public static final int EosTransferComplete = 0x9117;
135
+        public static final int EosResetTransfer = 0x9119;
136
+        public static final int EosBulbStart = 0x9125;
137
+        public static final int EosBulbEnd = 0x9126;
138
+        public static final int EosGetDevicePropValue = 0x9127;
139
+        public static final int EosRemoteReleaseOn = 0x9128;
140
+        public static final int EosRemoteReleaseOff = 0x9129;
141
+        public static final int EosGetLiveViewPicture = 0x9153;
142
+        public static final int EosDriveLens = 0x9155;
143
+    }
144
+
145
+    public static String operationToString(int operation) {
146
+        return constantToString(Operation.class, operation);
147
+    }
148
+
149
+    public static class Event {
150
+        public static final int CancelTransaction = 0x4001;
151
+        public static final int ObjectAdded = 0x4002;
152
+        public static final int ObjectRemoved = 0x4003;
153
+        public static final int StoreAdded = 0x4004;
154
+        public static final int StoreRemoved = 0x4005;
155
+        public static final int DevicePropChanged = 0x4006;
156
+        public static final int ObjectInfoChanged = 0x4007;
157
+        public static final int DeviceInfoChanged = 0x4008;
158
+        public static final int RequestObjectTransfer = 0x4009;
159
+        public static final int StoreFull = 0x400A;
160
+        public static final int StorageInfoChanged = 0x400C;
161
+        public static final int CaptureComplete = 0x400D;
162
+
163
+        // Nikon
164
+        public static final int NikonObjectAddedInSdram = 0xffffC101;
165
+        public static final int NikonCaptureCompleteRecInSdram = 0xC102;
166
+        public static final int NikonPreviewImageAdded = 0xffffC104;
167
+
168
+        // Canon EOS
169
+        public static final int EosObjectAdded = 0xC181; // ? dir item request transfer or dir item created
170
+        public static final int EosDevicePropChanged = 0xC189;
171
+        public static final int EosDevicePropDescChanged = 0xC18A;
172
+        public static final int EosCameraStatus = 0xC18B;
173
+        public static final int EosWillSoonShutdown = 0xC18D;
174
+        public static final int EosBulbExposureTime = 0xc194;
175
+
176
+    }
177
+
178
+    public static String eventToString(int event) {
179
+        return constantToString(Event.class, event);
180
+    }
181
+
182
+    public static class Response {
183
+        public static final int Ok = 0x2001;
184
+        public static final int GeneralError = 0x2002;
185
+        public static final int SessionNotOpen = 0x2003;
186
+        public static final int InvalidTransactionID = 0x2004;
187
+        public static final int OperationNotSupported = 0x2005;
188
+        public static final int ParameterNotSupported = 0x2006;
189
+        public static final int IncompleteTransfer = 0x2007;
190
+        public static final int InvalidStorageID = 0x2008;
191
+        public static final int InvalidObjectHandle = 0x2009;
192
+        public static final int DevicePropNotSupported = 0x200A;
193
+        public static final int InvalidObjectFormatCode = 0x200B;
194
+        public static final int StoreIsFull = 0x200C;
195
+        public static final int ObjectWriteProtect = 0x200D;
196
+        public static final int StoreReadOnly = 0x200E;
197
+        public static final int AccessDenied = 0x200F;
198
+        public static final int NoThumbnailPresent = 0x2010;
199
+        public static final int PartialDeletion = 0x2012;
200
+        public static final int StoreNotAvailable = 0x2013;
201
+        public static final int SpecificationByFormatUnsupported = 0x2014;
202
+        public static final int NoValidObjectInfo = 0x2015;
203
+        public static final int DeviceBusy = 0x2019;
204
+        public static final int InvalidParentObject = 0x201A;
205
+        public static final int InvalidDevicePropFormat = 0x201B;
206
+        public static final int InvalidDevicePropValue = 0x201C;
207
+        public static final int InvalidParameter = 0x201D;
208
+        public static final int SessionAlreadyOpen = 0x201E;
209
+        public static final int TransferCancelled = 0x201F;
210
+        public static final int SpecificationOfDestinationUnsupported = 0x2020;
211
+
212
+        // Nikon ?
213
+        public static final int HardwareError = 0xA001;
214
+        public static final int OutOfFocus = 0xA002;
215
+        public static final int ChangeCameraModeFailed = 0xA003;
216
+        public static final int InvalidStatus = 0xA004;
217
+        public static final int SetPropertyNotSupport = 0xA005;
218
+        public static final int WbPresetError = 0xA006;
219
+        public static final int DustReferenceError = 0xA007;
220
+        public static final int ShutterSpeedBulb = 0xA008;
221
+        public static final int MirrorUpSequence = 0xA009;
222
+        public static final int CameraModeNotAdjustFnumber = 0xA00A;
223
+        public static final int NotLiveView = 0xA00B;
224
+        public static final int MfDriveStepEnd = 0xA00C;
225
+        public static final int MfDriveStepInsufficiency = 0xA00E;
226
+        public static final int InvalidObjectPropCode = 0xA801;
227
+        public static final int InvalidObjectPropFormat = 0xA802;
228
+        public static final int ObjectPropNotSupported = 0xA80A;
229
+
230
+        // Canon EOS
231
+        public static final int EosUnknown_MirrorUp = 0xA102; // ?
232
+    }
233
+
234
+    public static String responseToString(int response) {
235
+        return constantToString(Response.class, response);
236
+    }
237
+
238
+    public static class ObjectFormat {
239
+        public static final int UnknownNonImageObject = 0x3000;
240
+        public static final int Association = 0x3001;
241
+        public static final int Script = 0x3002;
242
+        public static final int Executable = 0x3003;
243
+        public static final int Text = 0x3004;
244
+        public static final int HTML = 0x3005;
245
+        public static final int DPOF = 0x3006;
246
+        public static final int AIFF = 0x3007;
247
+        public static final int WAV = 0x3008;
248
+        public static final int MP3 = 0x3009;
249
+        public static final int AVI = 0x300A;
250
+        public static final int MPEG = 0x300B;
251
+        public static final int ASF = 0x300C;
252
+        public static final int UnknownImageObject = 0x3800;
253
+        public static final int EXIF_JPEG = 0x3801;
254
+        public static final int TIFF_EP = 0x3802;
255
+        public static final int FlashPix = 0x3803;
256
+        public static final int BMP = 0x3804;
257
+        public static final int CIFF = 0x3805;
258
+        public static final int Undefined_Reserved1 = 0x3806;
259
+        public static final int GIF = 0x3807;
260
+        public static final int JFIF = 0x3808;
261
+        public static final int PCD = 0x3809;
262
+        public static final int PICT = 0x380A;
263
+        public static final int PNG = 0x380B;
264
+        public static final int Undefined_Reserved2 = 0x380C;
265
+        public static final int TIFF = 0x380D;
266
+        public static final int TIFF_IT = 0x380E;
267
+        public static final int JP2 = 0x380F;
268
+        public static final int JPX = 0x3810;
269
+
270
+        // Canon
271
+        public static final int EosCRW = 0xb101;
272
+        public static final int EosCRW3 = 0xb103;
273
+        public static final int EosMOV = 0xb104;
274
+    }
275
+
276
+    public static String objectFormatToString(int objectFormat) {
277
+        return constantToString(ObjectFormat.class, objectFormat);
278
+    }
279
+
280
+    public static class Property {
281
+        // PTP
282
+        public static final int UndefinedProperty = 0x5000;
283
+        public static final int BatteryLevel = 0x5001;
284
+        public static final int FunctionalMode = 0x5002;
285
+        public static final int ImageSize = 0x5003;
286
+        public static final int CompressionSetting = 0x5004;
287
+        public static final int WhiteBalance = 0x5005;
288
+        public static final int RGBGain = 0x5006;
289
+        public static final int FNumber = 0x5007; // Aperture Value
290
+        public static final int FocalLength = 0x5008;
291
+        public static final int FocusDistance = 0x5009;
292
+        public static final int FocusMode = 0x500A;
293
+        public static final int ExposureMeteringMode = 0x500B;
294
+        public static final int FlashMode = 0x500C;
295
+        public static final int ExposureTime = 0x500D; // Shutter Speed
296
+        public static final int ExposureProgramMode = 0x500E;
297
+        public static final int ExposureIndex = 0x500F; // ISO Speed
298
+        public static final int ExposureBiasCompensation = 0x5010;
299
+        public static final int DateTime = 0x5011;
300
+        public static final int CaptureDelay = 0x5012;
301
+        public static final int StillCaptureMode = 0x5013;
302
+        public static final int Contrast = 0x5014;
303
+        public static final int Sharpness = 0x5015;
304
+        public static final int DigitalZoom = 0x5016;
305
+        public static final int EffectMode = 0x5017;
306
+        public static final int BurstNumber = 0x5018;
307
+        public static final int BurstInterval = 0x5019;
308
+        public static final int TimelapseNumber = 0x501A;
309
+        public static final int TimelapseInterval = 0x501B;
310
+        public static final int FocusMeteringMode = 0x501C;
311
+        public static final int UploadURL = 0x501D;
312
+        public static final int Artist = 0x501E;
313
+        public static final int CopyrightInfo = 0x501F;
314
+
315
+        // MTP/Microsoft
316
+        public static final int MtpDeviceFriendlyName = 0xD402;
317
+        public static final int MtpSessionInitiatorInfo = 0xD406;
318
+        public static final int MtpPerceivedDeviceType = 0xD407;
319
+
320
+        // Canon EOS
321
+        public static final int EosApertureValue = 0xD101;
322
+        public static final int EosShutterSpeed = 0xD102;
323
+        public static final int EosIsoSpeed = 0xD103;
324
+        public static final int EosExposureCompensation = 0xD104;
325
+        public static final int EosShootingMode = 0xD105;
326
+        public static final int EosDriveMode = 0xD106;
327
+        public static final int EosMeteringMode = 0xD107;
328
+        public static final int EosAfMode = 0xD108;
329
+        public static final int EosWhitebalance = 0xD109;
330
+        public static final int EosColorTemperature = 0xD10A;
331
+        public static final int EosPictureStyle = 0xD110;
332
+        public static final int EosAvailableShots = 0xD11B;
333
+        public static final int EosEvfOutputDevice = 0xD1B0;
334
+        public static final int EosEvfMode = 0xD1B3;
335
+        public static final int EosEvfWhitebalance = 0xD1B4;
336
+        public static final int EosEvfColorTemperature = 0xD1B6;
337
+
338
+        // Nikon
339
+        public static final int NikonShutterSpeed = 0xD100;
340
+        public static final int NikonFocusArea = 0xD108;
341
+        public static final int NikonWbColorTemp = 0xD01E;
342
+        public static final int NikonRecordingMedia = 0xD10B;
343
+        public static final int NikonExposureIndicateStatus = 0xD1B1;
344
+        public static final int NikonActivePicCtrlItem = 0xD200;
345
+        public static final int NikonEnableAfAreaPoint = 0xD08D;
346
+    }
347
+
348
+    public static String propertyToString(int property) {
349
+        return constantToString(Property.class, property);
350
+    }
351
+
352
+    public static class Datatype {
353
+        public static final int int8 = 0x0001;
354
+        public static final int uint8 = 0x002;
355
+        public static final int int16 = 0x003;
356
+        public static final int uint16 = 0x004;
357
+        public static final int int32 = 0x005;
358
+        public static final int uint32 = 0x006;
359
+        public static final int int64 = 0x007;
360
+        public static final int uint64 = 0x008;
361
+        public static final int int128 = 0x009;
362
+        public static final int uint128 = 0x00A;
363
+        public static final int aint8 = 0x4001;
364
+        public static final int auint8 = 0x4002;
365
+        public static final int aint16 = 0x4003;
366
+        public static final int auInt16 = 0x4004;
367
+        public static final int aint32 = 0x4005;
368
+        public static final int auint32 = 0x4006;
369
+        public static final int aint64 = 0x4007;
370
+        public static final int auint64 = 0x4008;
371
+        public static final int aint128 = 0x4009;
372
+        public static final int auint128 = 0x400A;
373
+        public static final int string = 0x00;
374
+    }
375
+
376
+    public static String datatypetoString(int datatype) {
377
+        return constantToString(Datatype.class, datatype);
378
+    }
379
+
380
+    public static int getDatatypeSize(int datatype) {
381
+        switch (datatype) {
382
+        case Datatype.int8:
383
+        case Datatype.uint8:
384
+            return 1;
385
+        case Datatype.int16:
386
+        case Datatype.uint16:
387
+            return 2;
388
+        case Datatype.int32:
389
+        case Datatype.uint32:
390
+            return 4;
391
+        case Datatype.int64:
392
+        case Datatype.uint64:
393
+            return 8;
394
+        default:
395
+            throw new UnsupportedOperationException();
396
+        }
397
+    }
398
+
399
+    /**
400
+     * Returns a string representation of the code field an PTP packet.
401
+     */
402
+    public static String codeToString(int type, int code) {
403
+        switch (type) {
404
+        case Type.Command:
405
+        case Type.Data:
406
+            return operationToString(code);
407
+        case Type.Response:
408
+            return responseToString(code);
409
+        case Type.Event:
410
+            return eventToString(code);
411
+        default:
412
+            return String.format("0x%04x", code);
413
+        }
414
+    }
415
+
416
+    /**
417
+     * Returns the name of the constant that has the specified {@code constant}
418
+     * in the specified {@code clazz}.
419
+     */
420
+    public static String constantToString(Class<?> clazz, int constant) {
421
+        String hexString = String.format("0x%04x", constant);
422
+        for (Field f : clazz.getDeclaredFields()) {
423
+            if (f.getType() != int.class || !Modifier.isStatic(f.getModifiers()) || !Modifier.isFinal(f.getModifiers())) {
424
+                continue;
425
+            }
426
+            try {
427
+                if (f.getInt(null) == constant) {
428
+                    return f.getName() + "(" + hexString + ")";
429
+                }
430
+            } catch (Throwable e) {
431
+                // nop
432
+                e.printStackTrace();
433
+            }
434
+        }
435
+        return hexString;
436
+    }
437
+
438
+    /**
439
+     * Reads {@code DeviceInfo.toString} from input and rewrites codes to
440
+     * names(codes).
441
+     *
442
+     * @throws IOException
443
+     */
444
+    public static void main(String[] args) throws IOException {
445
+        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
446
+        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
447
+        String line = null;
448
+        int state = 0;
449
+
450
+        while ((line = reader.readLine()) != null) {
451
+            if ("OperationsSupported:".equals(line)) {
452
+                state = 1;
453
+                writer.write(line);
454
+            } else if ("EventsSupported:".equals(line)) {
455
+                state = 2;
456
+                writer.write(line);
457
+            } else if ("DevicePropertiesSupported:".equals(line)) {
458
+                state = 3;
459
+                writer.write(line);
460
+            } else if ("CaptureFormats:".equals(line)) {
461
+                state = 4;
462
+                writer.write(line);
463
+            } else if ("ImageFormats:".equals(line)) {
464
+                state = 5;
465
+                writer.write(line);
466
+            } else {
467
+                if (line.startsWith("    0x") || line.matches("    .+\\)$")) {
468
+                    if (line.startsWith("    0x")) {
469
+                        line = line.trim().substring(2);
470
+                    } else {
471
+                        int bracket = line.indexOf('(');
472
+                        line = line.substring(bracket + 3, line.length() - 1);
473
+                    }
474
+                    int number = Integer.parseInt(line, 16);
475
+                    String value = null;
476
+                    switch (state) {
477
+                    case 1:
478
+                        value = operationToString(number);
479
+                        break;
480
+                    case 2:
481
+                        value = eventToString(number);
482
+                        break;
483
+                    case 3:
484
+                        value = propertyToString(number);
485
+                        break;
486
+                    case 4:
487
+                    case 5:
488
+                        value = objectFormatToString(number);
489
+                        break;
490
+                    }
491
+                    writer.write(String.format("    %s", value));
492
+                } else {
493
+                    writer.write(line);
494
+                }
495
+            }
496
+             writer.newLine();
497
+        }
498
+
499
+        writer.flush();
500
+    }
501
+}

+ 803 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/PtpPropertyHelper.java

@@ -0,0 +1,803 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp;
17
+
18
+import com.remoteyourcam.usb.ptp.PtpConstants.Product;
19
+import com.remoteyourcam.usb.ptp.PtpConstants.Property;
20
+
21
+import java.util.HashMap;
22
+import java.util.Map;
23
+
24
+/**
25
+ * Helper to convert property values to their string representations.
26
+ */
27
+public class PtpPropertyHelper {
28
+
29
+    public static final int EOS_SHUTTER_SPEED_BULB = 0x0c;
30
+
31
+    private static final Map<Integer, String> eosShutterSpeedMap = new HashMap<Integer, String>();
32
+    private static final Map<Integer, String> eosApertureValueMap = new HashMap<Integer, String>();
33
+    private static final Map<Integer, String> eosIsoSpeedMap = new HashMap<Integer, String>();
34
+    private static final Map<Integer, String> eosWhitebalanceMap = new HashMap<Integer, String>();
35
+    private static final Map<Integer, Integer> eosWhitebalanceIconsMap = new HashMap<Integer, Integer>();
36
+    private static final Map<Integer, String> eosShootingModeMap = new HashMap<Integer, String>();
37
+    private static final Map<Integer, Integer> eosShootingModeIconsMap = new HashMap<Integer, Integer>();
38
+    private static final Map<Integer, Integer> eosMeteringModeIconsMap = new HashMap<Integer, Integer>();
39
+    private static final Map<Integer, String> eosDriveModeMap = new HashMap<Integer, String>();
40
+    private static final Map<Integer, Integer> eosDriveModeIconsMap = new HashMap<Integer, Integer>();
41
+    private static final Map<Integer, String> eosFocusModeMap = new HashMap<Integer, String>();
42
+    private static final Map<Integer, String> eosPictureStyleMap = new HashMap<Integer, String>();
43
+
44
+    private static final Map<Integer, String> nikonWhitebalanceMap = new HashMap<Integer, String>();
45
+    private static final Map<Integer, Integer> nikonWhitebalanceIconsMap = new HashMap<Integer, Integer>();
46
+    private static final Map<Integer, String> nikonExposureIndexMap = new HashMap<Integer, String>();
47
+    private static final Map<Integer, Integer> nikonExposureProgramMap = new HashMap<Integer, Integer>();
48
+    private static final Map<Integer, String> nikonWbColorTempD300SMap = new HashMap<Integer, String>();
49
+    private static final Map<Integer, String> nikonWbColorTempD200Map = new HashMap<Integer, String>();
50
+    private static final Map<Integer, String> nikonFocusModeMap = new HashMap<Integer, String>();
51
+    private static final Map<Integer, String> nikonActivePicCtrlItemMap = new HashMap<Integer, String>();
52
+    private static final Map<Integer, Integer> nikonMeteringModeMap = new HashMap<Integer, Integer>();
53
+    private static final Map<Integer, String> nikonFocusMeteringModeMap = new HashMap<Integer, String>();
54
+    private static final Map<Integer, Integer> nikonFocusMeteringModeIconsMap = new HashMap<Integer, Integer>();
55
+
56
+    public static String mapToString(int productId, int property, int value) {
57
+        switch (property) {
58
+        case Property.EosShutterSpeed: {
59
+            String s = eosShutterSpeedMap.get(value);
60
+            return s != null ? s : "?";
61
+        }
62
+        case Property.EosApertureValue: {
63
+            String s = eosApertureValueMap.get(value);
64
+            return "f " + (s != null ? s : '?');
65
+        }
66
+        case Property.EosIsoSpeed:
67
+            return eosIsoSpeedMap.get(value);
68
+        case Property.EosWhitebalance:
69
+            return eosWhitebalanceMap.get(value);
70
+        case Property.EosShootingMode:
71
+            return eosShootingModeMap.get(value);
72
+        case Property.EosDriveMode:
73
+            return eosDriveModeMap.get(value);
74
+        case Property.WhiteBalance:
75
+            return nikonWhitebalanceMap.get(value);
76
+        case Property.FNumber: {
77
+            int major = value / 100;
78
+            int minor = value % 100;
79
+            if (minor == 0) {
80
+                return "f " + major;
81
+            } else if (minor % 10 == 0) {
82
+                return "f " + major + '.' + minor / 10;
83
+            } else {
84
+                return "f " + major + '.' + minor;
85
+            }
86
+        }
87
+        case Property.ExposureTime: {
88
+            if (value == 0xFFFFFFFF) {
89
+                return "Bulb";
90
+            }
91
+            int seconds = value / 10000;
92
+            int rest = value % 10000;
93
+            StringBuilder b = new StringBuilder();
94
+            if (seconds > 0) {
95
+                b.append(seconds).append("\"");
96
+            }
97
+            if (rest > 0) {
98
+                b.append("1/").append(Math.round(1.0 / (rest * 0.0001)));
99
+            }
100
+            return b.toString();
101
+        }
102
+        case Property.ExposureIndex:
103
+            return getNikonExposureIndex(productId, value);
104
+        case Property.EosColorTemperature:
105
+            return Integer.toString(value) + "K";
106
+        case Property.NikonWbColorTemp:
107
+            return getNikonWbColorTemp(productId, value);
108
+        case Property.EosAfMode:
109
+            return eosFocusModeMap.get(value);
110
+        case Property.FocusMode:
111
+            return nikonFocusModeMap.get(value);
112
+        case Property.NikonShutterSpeed: {
113
+            int numerator = value >> 16 & 0xffff;
114
+            int denominator = value & 0xffff;
115
+            if (denominator == 1) {
116
+                return "" + numerator + "\"";
117
+            } else if (numerator == 1) {
118
+                return "1/" + denominator;
119
+            } else if (value == 0xFFFFFFFF) {
120
+                return "Bulb";
121
+            } else if (value == 0xFFFFFFFE) {
122
+                return "Flash";
123
+            } else if (numerator > denominator) {
124
+                return String.format("%.1f\"", numerator / (double) denominator);
125
+            }
126
+            return "" + numerator + "/" + denominator;
127
+        }
128
+        case Property.NikonActivePicCtrlItem:
129
+            return nikonActivePicCtrlItemMap.get(value);
130
+        case Property.FocusMeteringMode:
131
+            return nikonFocusMeteringModeMap.get(value);
132
+        case Property.NikonExposureIndicateStatus:
133
+            return "" + value / 6 + "." + Math.abs(value) % 6 + " EV";
134
+        case Property.EosPictureStyle:
135
+            return eosPictureStyleMap.get(value);
136
+        case Property.EosExposureCompensation: {
137
+            int v;
138
+            char ch;
139
+            if (value > 0x80) {
140
+                v = 0x100 - value;
141
+                ch = '-';
142
+            } else {
143
+                v = value;
144
+                ch = '+';
145
+            }
146
+            if (v == 0) {
147
+                return " 0";
148
+            }
149
+            int first = v / 8;
150
+            int second = v % 8;
151
+            String dec = second == 3 ? "1/3" : second == 4 ? "1/2" : second == 5 ? "2/3" : "";
152
+            if (first > 0) {
153
+                return String.format("%c%d %s", ch, first, dec);
154
+            } else {
155
+                return String.format("%c%s", ch, dec);
156
+            }
157
+        }
158
+        case Property.ExposureBiasCompensation: {
159
+            int dec = Math.round(Math.abs(value) / 100.0f);
160
+            int upper = dec / 10;
161
+            int lower = dec % 10;
162
+            char sign = value >= 0 ? '+' : '-';
163
+            return String.format("%c%d.%d", sign, upper, lower);
164
+        }
165
+        default:
166
+            return "?";
167
+        }
168
+    }
169
+
170
+    private static String getNikonExposureIndex(int productId, int value) {
171
+        switch (productId) {
172
+        case Product.NikonD300:
173
+        case Product.NikonD300S:
174
+        case Product.NikonD5000:
175
+            if (value == 0x0064) {
176
+                return "LO-1";
177
+            } else if (value == 0x007D) {
178
+                return "LO-0.7";
179
+            } else if (value == 0x00A0) {
180
+                return "LO-0.3";
181
+            } else if (value == 0x0FA0) {
182
+                return "Hi-0.3";
183
+            } else if (value == 0x1194) {
184
+                return "Hi-0.5";
185
+            } else if (value == 0x1388) {
186
+                return "Hi-0.7";
187
+            } else if (value == 0x1900) {
188
+                return "Hi-1";
189
+            }
190
+            break;
191
+        case Product.NikonD7000:
192
+            if (value == 0x1F40) {
193
+                return "Hi-0.3";
194
+            } else if (value == 0x2328) {
195
+                return "Hi-0.5";
196
+            } else if (value == 0x2710) {
197
+                return "Hi-0.7";
198
+            } else if (value == 0x3200) {
199
+                return "Hi-1";
200
+            } else if (value == 0x6400) {
201
+                return "Hi-2";
202
+            }
203
+            break;
204
+        case Product.NikonD80:
205
+        case Product.NikonD200:
206
+        case Product.NikonD40:
207
+            if (value == 0x07D0) {
208
+                return "Hi-0.3";
209
+            } else if (value == 0x09C4) {
210
+                return "Hi-0.7";
211
+            } else if (value == 0x0C80) {
212
+                return "Hi-1";
213
+            } else if (value == 0x0898) { // D200 only
214
+                return "Hi-0.5";
215
+            }
216
+            break;
217
+        case Product.NikonD3:
218
+            if (value == 0x0064) {
219
+                return "LO-1";
220
+            } else if (value == 0x007D) {
221
+                return "LO-0.7";
222
+            } else if (value == 0x008C) {
223
+                return "LO-0.5";
224
+            } else if (value == 0x00A0) {
225
+                return "LO-0.3";
226
+            } else if (value == 0x2080) {
227
+                return "Hi-0.3";
228
+            } else if (value == 0x2300) {
229
+                return "Hi-0.5";
230
+            } else if (value == 0x2800) {
231
+                return "Hi-0.7";
232
+            } else if (value == 0x3200) {
233
+                return "Hi-1";
234
+            } else if (value == 0x6400) {
235
+                return "Hi-2";
236
+            }
237
+            break;
238
+        case Product.NikonD3X:
239
+            if (value == 0x0032) {
240
+                return "LO-1";
241
+            } else if (value == 0x003E) {
242
+                return "LO-0.7";
243
+            } else if (value == 0x0046) {
244
+                return "LO-0.5";
245
+            } else if (value == 0x0050) {
246
+                return "LO-0.3";
247
+            } else if (value == 0x07D0) {
248
+                return "Hi-0.3";
249
+            } else if (value == 0x08C0) {
250
+                return "Hi-0.5";
251
+            } else if (value == 0x0A00) {
252
+                return "Hi-0.7";
253
+            } else if (value == 0x0C80) {
254
+                return "Hi-1";
255
+            } else if (value == 0x1900) {
256
+                return "Hi-2";
257
+            }
258
+            break;
259
+        case Product.NikonD3S:
260
+            if (value == 0x0064) {
261
+                return "LO-1";
262
+            } else if (value == 0x007D) {
263
+                return "LO-0.7";
264
+            } else if (value == 0x008C) {
265
+                return "LO-0.5";
266
+            } else if (value == 0x00A0) {
267
+                return "LO-0.3";
268
+            } else if (value == 0x3840) {
269
+                return "Hi-0.3";
270
+            } else if (value == 0x4650) {
271
+                return "Hi-0.5";
272
+            } else if (value == 0x4E20) {
273
+                return "Hi-0.7";
274
+            } else if (value == 0x6400) {
275
+                return "Hi-1";
276
+            } else if (value == 0xC800) {
277
+                return "Hi-2";
278
+            }
279
+            break;
280
+        }
281
+        return nikonExposureIndexMap.get(value);
282
+    }
283
+
284
+    private static String getNikonWbColorTemp(int productId, int value) {
285
+        switch (productId) {
286
+        case Product.NikonD300S:
287
+        case Product.NikonD3:
288
+        case Product.NikonD3S:
289
+        case Product.NikonD3X:
290
+        case Product.NikonD300:
291
+        case Product.NikonD700:
292
+        case Product.NikonD7000:
293
+        case Product.NikonD90:
294
+            return nikonWbColorTempD300SMap.get(value);
295
+        case Product.NikonD200:
296
+        case Product.NikonD80:
297
+            return nikonWbColorTempD200Map.get(value);
298
+            //case Product.NikonD60:
299
+            //case Product.NikonD40:
300
+            //case Product.NikonD5000:
301
+            //    return null;
302
+        }
303
+        return null;
304
+    }
305
+
306
+    public static Integer mapToDrawable(int property, int value) {
307
+//        switch (property) {
308
+//        case Property.EosWhitebalance: {
309
+//            Integer resId = eosWhitebalanceIconsMap.get(value);
310
+//            return resId != null ? resId : R.drawable.whitebalance_unknown;
311
+//        }
312
+//        case Property.EosShootingMode: {
313
+//            Integer resId = eosShootingModeIconsMap.get(value);
314
+//            return resId != null ? resId : R.drawable.shootingmode_unknown;
315
+//        }
316
+//        case Property.EosMeteringMode: {
317
+//            Integer resId = eosMeteringModeIconsMap.get(value);
318
+//            return resId != null ? resId : R.drawable.whitebalance_unknown; //TODO own unknown image
319
+//        }
320
+//        case Property.EosDriveMode: {
321
+//            Integer resId = eosDriveModeIconsMap.get(value);
322
+//            return resId != null ? resId : R.drawable.whitebalance_unknown; //TODO own unknown image
323
+//        }
324
+//        case Property.WhiteBalance: {
325
+//            Integer resId = nikonWhitebalanceIconsMap.get(value);
326
+//            return resId != null ? resId : R.drawable.whitebalance_unknown;
327
+//        }
328
+//        case Property.ExposureProgramMode: {
329
+//            Integer resId = nikonExposureProgramMap.get(value);
330
+//            return resId != null ? resId : R.drawable.whitebalance_unknown;
331
+//        }
332
+//        case Property.ExposureMeteringMode: {
333
+//            Integer resId = nikonMeteringModeMap.get(value);
334
+//            return resId != null ? resId : R.drawable.whitebalance_unknown;
335
+//        }
336
+//        case Property.FocusMeteringMode: {
337
+//            Integer resId = nikonFocusMeteringModeIconsMap.get(value);
338
+//            return resId != null ? resId : R.drawable.whitebalance_unknown;
339
+//        }
340
+//        default:
341
+//            return null;
342
+//        }
343
+        return null;
344
+    }
345
+
346
+    public static String getBiggestValue(int property) {
347
+        switch (property) {
348
+        case Property.EosShutterSpeed:
349
+            return "1/8000";
350
+        case Property.EosApertureValue:
351
+            return "f 9.5";
352
+        case Property.EosIsoSpeed:
353
+            return "102400";
354
+        case Property.FNumber:
355
+            return "33.3"; // ?
356
+        case Property.ExposureTime:
357
+            return "1/10000";
358
+        case Property.ExposureIndex:
359
+            return "LO-0.3";
360
+        default:
361
+            return "";
362
+        }
363
+    }
364
+
365
+    static {
366
+        eosShutterSpeedMap.put(0x0c, "Bulb");
367
+        eosShutterSpeedMap.put(0x10, "30\"");
368
+        eosShutterSpeedMap.put(0x13, "25\"");
369
+        eosShutterSpeedMap.put(0x14, "20\"");
370
+        eosShutterSpeedMap.put(0x15, "20\""); // (1/3)");
371
+        eosShutterSpeedMap.put(0x18, "15\"");
372
+        eosShutterSpeedMap.put(0x1B, "13\"");
373
+        eosShutterSpeedMap.put(0x1C, "10\"");
374
+        eosShutterSpeedMap.put(0x1D, "10\""); // (1/3)");
375
+        eosShutterSpeedMap.put(0x20, "8\"");
376
+        eosShutterSpeedMap.put(0x23, "6\""); // (1/3)");
377
+        eosShutterSpeedMap.put(0x24, "6\"");
378
+        eosShutterSpeedMap.put(0x25, "5\"");
379
+        eosShutterSpeedMap.put(0x28, "4\"");
380
+        eosShutterSpeedMap.put(0x2B, "3\"2");
381
+        eosShutterSpeedMap.put(0x2C, "3\"");
382
+        eosShutterSpeedMap.put(0x2D, "2\"5");
383
+        eosShutterSpeedMap.put(0x25, "5\"");
384
+        eosShutterSpeedMap.put(0x28, "4\"");
385
+        eosShutterSpeedMap.put(0x2B, "3\"2");
386
+        eosShutterSpeedMap.put(0x2C, "3\"");
387
+        eosShutterSpeedMap.put(0x2D, "2\"5");
388
+        eosShutterSpeedMap.put(0x30, "2\"");
389
+        eosShutterSpeedMap.put(0x33, "1\"6");
390
+        eosShutterSpeedMap.put(0x34, "1\"5");
391
+        eosShutterSpeedMap.put(0x35, "1\"3");
392
+        eosShutterSpeedMap.put(0x38, "1");
393
+        eosShutterSpeedMap.put(0x3B, "0\"8");
394
+        eosShutterSpeedMap.put(0x3C, "0\"7");
395
+        eosShutterSpeedMap.put(0x3D, "0\"6");
396
+        eosShutterSpeedMap.put(0x40, "0\"5");
397
+        eosShutterSpeedMap.put(0x43, "0\"4");
398
+        eosShutterSpeedMap.put(0x44, "0\"3");
399
+        eosShutterSpeedMap.put(0x45, "0\"3"); // (1/3)");
400
+        eosShutterSpeedMap.put(0x48, "1/4");
401
+        eosShutterSpeedMap.put(0x4B, "1/5");
402
+        eosShutterSpeedMap.put(0x4C, "1/6");
403
+        eosShutterSpeedMap.put(0x4D, "1/6"); // (1/3)");
404
+        eosShutterSpeedMap.put(0x50, "1/8");
405
+        eosShutterSpeedMap.put(0x53, "1/10"); // (1/3)");
406
+        eosShutterSpeedMap.put(0x54, "1/10");
407
+        eosShutterSpeedMap.put(0x55, "1/13");
408
+        eosShutterSpeedMap.put(0x58, "1/15");
409
+        eosShutterSpeedMap.put(0x5B, "1/20"); // (1/3)");
410
+        eosShutterSpeedMap.put(0x5C, "1/20");
411
+        eosShutterSpeedMap.put(0x5D, "1/25");
412
+        eosShutterSpeedMap.put(0x60, "1/30");
413
+        eosShutterSpeedMap.put(0x63, "1/40");
414
+        eosShutterSpeedMap.put(0x64, "1/45");
415
+        eosShutterSpeedMap.put(0x65, "1/50");
416
+        eosShutterSpeedMap.put(0x68, "1/60");
417
+        eosShutterSpeedMap.put(0x6B, "1/80");
418
+        eosShutterSpeedMap.put(0x6C, "1/90");
419
+        eosShutterSpeedMap.put(0x6D, "1/100");
420
+        eosShutterSpeedMap.put(0x70, "1/125");
421
+        eosShutterSpeedMap.put(0x73, "1/160");
422
+        eosShutterSpeedMap.put(0x74, "1/180");
423
+        eosShutterSpeedMap.put(0x75, "1/200");
424
+        eosShutterSpeedMap.put(0x78, "1/250");
425
+        eosShutterSpeedMap.put(0x7B, "1/320");
426
+        eosShutterSpeedMap.put(0x7C, "1/350");
427
+        eosShutterSpeedMap.put(0x7D, "1/400");
428
+        eosShutterSpeedMap.put(0x80, "1/500");
429
+        eosShutterSpeedMap.put(0x83, "1/640");
430
+        eosShutterSpeedMap.put(0x84, "1/750");
431
+        eosShutterSpeedMap.put(0x85, "1/800");
432
+        eosShutterSpeedMap.put(0x88, "1/1000");
433
+        eosShutterSpeedMap.put(0x8B, "1/1250");
434
+        eosShutterSpeedMap.put(0x8C, "1/1500");
435
+        eosShutterSpeedMap.put(0x8D, "1/1600");
436
+        eosShutterSpeedMap.put(0x90, "1/2000");
437
+        eosShutterSpeedMap.put(0x93, "1/2500");
438
+        eosShutterSpeedMap.put(0x94, "1/3000");
439
+        eosShutterSpeedMap.put(0x95, "1/3200");
440
+        eosShutterSpeedMap.put(0x98, "1/4000");
441
+        eosShutterSpeedMap.put(0x9B, "1/5000");
442
+        eosShutterSpeedMap.put(0x9C, "1/6000");
443
+        eosShutterSpeedMap.put(0x9D, "1/6400");
444
+        eosShutterSpeedMap.put(0xA0, "1/8000");
445
+
446
+        eosApertureValueMap.put(0x08, "1");
447
+        eosApertureValueMap.put(0x0B, "1.1");
448
+        eosApertureValueMap.put(0x0C, "1.2");
449
+        eosApertureValueMap.put(0x0D, "1.2"); // (1/3)");
450
+        eosApertureValueMap.put(0x10, "1.4");
451
+        eosApertureValueMap.put(0x13, "1.6");
452
+        eosApertureValueMap.put(0x14, "1.8");
453
+        eosApertureValueMap.put(0x15, "1.8"); // (1/3)");
454
+        eosApertureValueMap.put(0x18, "2");
455
+        eosApertureValueMap.put(0x1B, "2.2");
456
+        eosApertureValueMap.put(0x1C, "2.5");
457
+        eosApertureValueMap.put(0x1D, "2.5"); // (1/3)");
458
+        eosApertureValueMap.put(0x20, "2.8");
459
+        eosApertureValueMap.put(0x23, "3.2");
460
+        eosApertureValueMap.put(0x24, "3.5");
461
+        eosApertureValueMap.put(0x25, "3.5"); // (1/3)");
462
+        eosApertureValueMap.put(0x28, "4");
463
+        eosApertureValueMap.put(0x2B, "4.5");
464
+        eosApertureValueMap.put(0x2C, "4.5");
465
+        eosApertureValueMap.put(0x2D, "5.0");
466
+        eosApertureValueMap.put(0x30, "5.6");
467
+        eosApertureValueMap.put(0x33, "6.3");
468
+        eosApertureValueMap.put(0x34, "6.7");
469
+        eosApertureValueMap.put(0x35, "7.1");
470
+        eosApertureValueMap.put(0x38, "8");
471
+        eosApertureValueMap.put(0x3B, "9");
472
+        eosApertureValueMap.put(0x3C, "9.5");
473
+        eosApertureValueMap.put(0x3D, "10");
474
+        eosApertureValueMap.put(0x40, "11");
475
+        eosApertureValueMap.put(0x43, "13"); // (1/3)");
476
+        eosApertureValueMap.put(0x44, "13");
477
+        eosApertureValueMap.put(0x45, "14");
478
+        eosApertureValueMap.put(0x48, "16");
479
+        eosApertureValueMap.put(0x4B, "18");
480
+        eosApertureValueMap.put(0x4C, "19");
481
+        eosApertureValueMap.put(0x4D, "20");
482
+        eosApertureValueMap.put(0x50, "22");
483
+        eosApertureValueMap.put(0x53, "25");
484
+        eosApertureValueMap.put(0x54, "27");
485
+        eosApertureValueMap.put(0x55, "29");
486
+        eosApertureValueMap.put(0x58, "32");
487
+        eosApertureValueMap.put(0x5B, "36");
488
+        eosApertureValueMap.put(0x5C, "38");
489
+        eosApertureValueMap.put(0x5D, "40");
490
+        eosApertureValueMap.put(0x60, "45");
491
+        eosApertureValueMap.put(0x63, "51");
492
+        eosApertureValueMap.put(0x64, "54");
493
+        eosApertureValueMap.put(0x65, "57");
494
+        eosApertureValueMap.put(0x68, "64");
495
+        eosApertureValueMap.put(0x6B, "72");
496
+        eosApertureValueMap.put(0x6C, "76");
497
+        eosApertureValueMap.put(0x6D, "80");
498
+        eosApertureValueMap.put(0x70, "91");
499
+
500
+        eosIsoSpeedMap.put(0x00, "Auto");
501
+        eosIsoSpeedMap.put(0x28, "6");
502
+        eosIsoSpeedMap.put(0x30, "12");
503
+        eosIsoSpeedMap.put(0x38, "25");
504
+        eosIsoSpeedMap.put(0x40, "50");
505
+        eosIsoSpeedMap.put(0x48, "100");
506
+        eosIsoSpeedMap.put(0x4b, "125");
507
+        eosIsoSpeedMap.put(0x4d, "160");
508
+        eosIsoSpeedMap.put(0x50, "200");
509
+        eosIsoSpeedMap.put(0x53, "250");
510
+        eosIsoSpeedMap.put(0x55, "320");
511
+        eosIsoSpeedMap.put(0x58, "400");
512
+        eosIsoSpeedMap.put(0x5b, "500");
513
+        eosIsoSpeedMap.put(0x5d, "640");
514
+        eosIsoSpeedMap.put(0x60, "800");
515
+        eosIsoSpeedMap.put(0x63, "1000");
516
+        eosIsoSpeedMap.put(0x65, "1250");
517
+        eosIsoSpeedMap.put(0x68, "1600");
518
+        eosIsoSpeedMap.put(0x6b, "2000");
519
+        eosIsoSpeedMap.put(0x6d, "2500");
520
+        eosIsoSpeedMap.put(0x70, "3200");
521
+        eosIsoSpeedMap.put(0x73, "4000");
522
+        eosIsoSpeedMap.put(0x75, "5000");
523
+        eosIsoSpeedMap.put(0x78, "6400");
524
+        eosIsoSpeedMap.put(0x80, "12800");
525
+        eosIsoSpeedMap.put(0x88, "25600");
526
+        eosIsoSpeedMap.put(0x90, "51200");
527
+        eosIsoSpeedMap.put(0x98, "102400");
528
+
529
+        eosWhitebalanceMap.put(0, "Auto");
530
+        eosWhitebalanceMap.put(1, "Daylight");
531
+        eosWhitebalanceMap.put(2, "Cloudy");
532
+        eosWhitebalanceMap.put(3, "Tungsten");
533
+        eosWhitebalanceMap.put(4, "Fluorescent");
534
+        eosWhitebalanceMap.put(5, "Flash");
535
+        eosWhitebalanceMap.put(6, "Manual 1");
536
+        eosWhitebalanceMap.put(8, "Shade");
537
+        eosWhitebalanceMap.put(9, "Color temperature");
538
+        eosWhitebalanceMap.put(10, "PC-1");
539
+        eosWhitebalanceMap.put(11, "PC-2");
540
+        eosWhitebalanceMap.put(12, "PC-3");
541
+        eosWhitebalanceMap.put(15, "Manual 2");
542
+        eosWhitebalanceMap.put(16, "Manual 3");
543
+        eosWhitebalanceMap.put(18, "Manual 4");
544
+        eosWhitebalanceMap.put(19, "Manual");
545
+        eosWhitebalanceMap.put(20, "PC-4");
546
+        eosWhitebalanceMap.put(21, "PC-5");
547
+
548
+//        eosWhitebalanceIconsMap.put(0, R.drawable.whitebalance_auto);
549
+//        eosWhitebalanceIconsMap.put(1, R.drawable.whitebalance_daylight);
550
+//        eosWhitebalanceIconsMap.put(2, R.drawable.whitebalance_cloudy);
551
+//        eosWhitebalanceIconsMap.put(3, R.drawable.whitebalance_tungsten);
552
+//        eosWhitebalanceIconsMap.put(4, R.drawable.whitebalance_fluorescent);
553
+//        eosWhitebalanceIconsMap.put(5, R.drawable.whitebalance_flash);
554
+//        eosWhitebalanceIconsMap.put(6, R.drawable.whitebalance_manual1);
555
+//        eosWhitebalanceIconsMap.put(8, R.drawable.whitebalance_shade);
556
+//        eosWhitebalanceIconsMap.put(9, R.drawable.whitebalance_color_temperature);
557
+//        eosWhitebalanceIconsMap.put(10, R.drawable.whitebalance_custom1);
558
+//        eosWhitebalanceIconsMap.put(11, R.drawable.whitebalance_custom2);
559
+//        eosWhitebalanceIconsMap.put(12, R.drawable.whitebalance_custom3);
560
+//        eosWhitebalanceIconsMap.put(15, R.drawable.whitebalance_manual2);
561
+//        eosWhitebalanceIconsMap.put(16, R.drawable.whitebalance_manual3);
562
+//        eosWhitebalanceIconsMap.put(18, R.drawable.whitebalance_manual4);
563
+//        eosWhitebalanceIconsMap.put(19, R.drawable.whitebalance_manual5);
564
+//        eosWhitebalanceIconsMap.put(20, R.drawable.whitebalance_custom4);
565
+//        eosWhitebalanceIconsMap.put(21, R.drawable.whitebalance_custom5);
566
+
567
+        eosShootingModeMap.put(0, "Program AE");
568
+        eosShootingModeMap.put(1, "Shutter-Speed Priority AE");
569
+        eosShootingModeMap.put(2, "Aperture Priority AE");
570
+        eosShootingModeMap.put(3, "Manual Exposure");
571
+        eosShootingModeMap.put(4, "Bulb");
572
+        eosShootingModeMap.put(5, "Auto Depth-of-Field AE");
573
+        eosShootingModeMap.put(6, "Depth-of-Field AE");
574
+        eosShootingModeMap.put(8, "Lock");
575
+        eosShootingModeMap.put(9, "Auto");
576
+        eosShootingModeMap.put(10, "Night Scene Portrait");
577
+        eosShootingModeMap.put(11, "Sports");
578
+        eosShootingModeMap.put(12, "Portrait");
579
+        eosShootingModeMap.put(13, "Landscape");
580
+        eosShootingModeMap.put(14, "Close-Up");
581
+        eosShootingModeMap.put(15, "Flash Off");
582
+        eosShootingModeMap.put(19, "Creative Auto");
583
+
584
+//        eosShootingModeIconsMap.put(0, R.drawable.shootingmode_program);
585
+//        eosShootingModeIconsMap.put(1, R.drawable.shootingmode_tv);
586
+//        eosShootingModeIconsMap.put(2, R.drawable.shootingmode_av);
587
+//        eosShootingModeIconsMap.put(3, R.drawable.shootingmode_m);
588
+//        eosShootingModeIconsMap.put(4, R.drawable.shootingmode_bulb);
589
+//        eosShootingModeIconsMap.put(5, R.drawable.shootingmode_adep);
590
+//        eosShootingModeIconsMap.put(6, R.drawable.shootingmode_dep);
591
+//        eosShootingModeIconsMap.put(8, R.drawable.shootingmode_lock);
592
+//        eosShootingModeIconsMap.put(9, R.drawable.shootingmode_auto);
593
+//        eosShootingModeIconsMap.put(10, R.drawable.shootingmode_night_scene_portrait);
594
+//        eosShootingModeIconsMap.put(11, R.drawable.shootingmode_sports);
595
+//        eosShootingModeIconsMap.put(12, R.drawable.shootingmode_portrait);
596
+//        eosShootingModeIconsMap.put(13, R.drawable.shootingmode_landscape);
597
+//        eosShootingModeIconsMap.put(14, R.drawable.shootingmode_close_up);
598
+//        eosShootingModeIconsMap.put(15, R.drawable.shootingmode_flash_off);
599
+//        eosShootingModeIconsMap.put(19, R.drawable.shootingmode_creativeauto);
600
+
601
+        eosDriveModeMap.put(0, "Single Shooting");
602
+        eosDriveModeMap.put(1, "Continuous Shooting");
603
+        eosDriveModeMap.put(2, "Video");
604
+        eosDriveModeMap.put(3, "?");
605
+        eosDriveModeMap.put(4, "High-Speed Continuous Shooting");
606
+        eosDriveModeMap.put(5, "Low-Speed Continuous Shooting");
607
+        eosDriveModeMap.put(6, "Silent Single Shooting");
608
+        eosDriveModeMap.put(7, "10-Sec Self-Timer plus Continuous Shooting");
609
+        eosDriveModeMap.put(0x10, "10-Sec Self-Timer");
610
+        eosDriveModeMap.put(0x11, "2-Sec Self-Timer");
611
+
612
+        // TODO easDriveModeIconsmap
613
+
614
+        eosFocusModeMap.put(0, "One-Shot AF");
615
+        eosFocusModeMap.put(1, "AI Servo AF");
616
+        eosFocusModeMap.put(2, "AI Focus AF");
617
+        eosFocusModeMap.put(3, "Manual Focus");
618
+
619
+        nikonWhitebalanceMap.put(2, "Auto");
620
+        nikonWhitebalanceMap.put(4, "Sunny");
621
+        nikonWhitebalanceMap.put(5, "Fluorescent");
622
+        nikonWhitebalanceMap.put(6, "Incandescent");
623
+        nikonWhitebalanceMap.put(7, "Flash");
624
+        nikonWhitebalanceMap.put(0x8010, "Cloudy");
625
+        nikonWhitebalanceMap.put(0x8011, "Sunny shade");
626
+        nikonWhitebalanceMap.put(0x8012, "Color temperature");
627
+        nikonWhitebalanceMap.put(0x8013, "Preset");
628
+
629
+//        nikonWhitebalanceIconsMap.put(2, R.drawable.whitebalance_auto);
630
+//        nikonWhitebalanceIconsMap.put(4, R.drawable.whitebalance_daylight);
631
+//        nikonWhitebalanceIconsMap.put(5, R.drawable.whitebalance_fluorescent);
632
+//        nikonWhitebalanceIconsMap.put(6, R.drawable.whitebalance_tungsten);
633
+//        nikonWhitebalanceIconsMap.put(7, R.drawable.whitebalance_flash);
634
+//        nikonWhitebalanceIconsMap.put(0x8010, R.drawable.whitebalance_cloudy);
635
+//        nikonWhitebalanceIconsMap.put(0x8011, R.drawable.whitebalance_shade);
636
+//        nikonWhitebalanceIconsMap.put(0x8012, R.drawable.whitebalance_color_temperature);
637
+//        nikonWhitebalanceIconsMap.put(0x8013, R.drawable.whitebalance_custom1); // TODO create Nikon specific icon
638
+
639
+        nikonExposureIndexMap.put(0x0064, "100");
640
+        nikonExposureIndexMap.put(0x007D, "125");
641
+        nikonExposureIndexMap.put(0x00A0, "160");
642
+        nikonExposureIndexMap.put(0x00C8, "200");
643
+        nikonExposureIndexMap.put(0x00FA, "250");
644
+        nikonExposureIndexMap.put(0x0118, "280");
645
+        nikonExposureIndexMap.put(0x0140, "320");
646
+        nikonExposureIndexMap.put(0x0190, "400");
647
+        nikonExposureIndexMap.put(0x01F4, "500");
648
+        nikonExposureIndexMap.put(0x0230, "560");
649
+        nikonExposureIndexMap.put(0x0280, "640");
650
+        nikonExposureIndexMap.put(0x0320, "800");
651
+        nikonExposureIndexMap.put(0x03E8, "1000");
652
+        nikonExposureIndexMap.put(0x044C, "1100");
653
+        nikonExposureIndexMap.put(0x04E2, "1250");
654
+        nikonExposureIndexMap.put(0x0640, "1600");
655
+        nikonExposureIndexMap.put(0x07D0, "2000");
656
+        nikonExposureIndexMap.put(0x0898, "2200");
657
+        nikonExposureIndexMap.put(0x09C4, "2500");
658
+        nikonExposureIndexMap.put(0x0C80, "3200");
659
+        nikonExposureIndexMap.put(0x0FA0, "4000");
660
+        nikonExposureIndexMap.put(0x1194, "4500");
661
+        nikonExposureIndexMap.put(0x1388, "5000");
662
+        nikonExposureIndexMap.put(0x1900, "6400");
663
+        nikonExposureIndexMap.put(0x1F40, "8000");
664
+        nikonExposureIndexMap.put(0x2328, "9000");
665
+        nikonExposureIndexMap.put(0x2710, "10000");
666
+        nikonExposureIndexMap.put(0x3200, "12800");
667
+
668
+//        nikonExposureProgramMap.put(0x0001, R.drawable.shootingmode_m);
669
+//        nikonExposureProgramMap.put(0x0002, R.drawable.shootingmode_program);
670
+//        nikonExposureProgramMap.put(0x0003, R.drawable.shootingmode_av);
671
+//        nikonExposureProgramMap.put(0x0004, R.drawable.shootingmode_tv);
672
+//        nikonExposureProgramMap.put(0x8010, R.drawable.shootingmode_auto);
673
+//        nikonExposureProgramMap.put(0x8011, R.drawable.shootingmode_portrait);
674
+//        nikonExposureProgramMap.put(0x8012, R.drawable.shootingmode_landscape);
675
+//        nikonExposureProgramMap.put(0x8013, R.drawable.shootingmode_close_up);
676
+//        nikonExposureProgramMap.put(0x8014, R.drawable.shootingmode_sports);
677
+//        nikonExposureProgramMap.put(0x8015, R.drawable.shootingmode_night_scene_portrait);
678
+//        nikonExposureProgramMap.put(0x8016, R.drawable.shootingmode_flash_off);
679
+//        nikonExposureProgramMap.put(0x8017, R.drawable.shootingmode_unknown); // TODO Child
680
+//        nikonExposureProgramMap.put(0x8018, R.drawable.shootingmode_unknown); // TODO SCENE
681
+//        nikonExposureProgramMap.put(0x8050, R.drawable.shootingmode_unknown); // TODO User mode U1
682
+//        nikonExposureProgramMap.put(0x8051, R.drawable.shootingmode_unknown); // TODO User mode U2
683
+
684
+        nikonWbColorTempD300SMap.put(0, "2500K");
685
+        nikonWbColorTempD300SMap.put(1, "2560K");
686
+        nikonWbColorTempD300SMap.put(2, "2630K");
687
+        nikonWbColorTempD300SMap.put(3, "2700K");
688
+        nikonWbColorTempD300SMap.put(4, "2780K");
689
+        nikonWbColorTempD300SMap.put(5, "2860K");
690
+        nikonWbColorTempD300SMap.put(6, "2940K");
691
+        nikonWbColorTempD300SMap.put(7, "3030K");
692
+        nikonWbColorTempD300SMap.put(8, "3130K");
693
+        nikonWbColorTempD300SMap.put(9, "3230K");
694
+        nikonWbColorTempD300SMap.put(10, "3330K");
695
+        nikonWbColorTempD300SMap.put(11, "3450K");
696
+        nikonWbColorTempD300SMap.put(12, "3570K");
697
+        nikonWbColorTempD300SMap.put(13, "3700K");
698
+        nikonWbColorTempD300SMap.put(14, "3850K");
699
+        nikonWbColorTempD300SMap.put(15, "4000K");
700
+        nikonWbColorTempD300SMap.put(16, "4170K");
701
+        nikonWbColorTempD300SMap.put(17, "4350K");
702
+        nikonWbColorTempD300SMap.put(18, "4550K");
703
+        nikonWbColorTempD300SMap.put(19, "4760K");
704
+        nikonWbColorTempD300SMap.put(20, "5000K");
705
+        nikonWbColorTempD300SMap.put(21, "5260K");
706
+        nikonWbColorTempD300SMap.put(22, "5560K");
707
+        nikonWbColorTempD300SMap.put(23, "5880K");
708
+        nikonWbColorTempD300SMap.put(24, "6250K");
709
+        nikonWbColorTempD300SMap.put(25, "6670K");
710
+        nikonWbColorTempD300SMap.put(26, "7140K");
711
+        nikonWbColorTempD300SMap.put(27, "7690K");
712
+        nikonWbColorTempD300SMap.put(28, "8330K");
713
+        nikonWbColorTempD300SMap.put(29, "9090K");
714
+        nikonWbColorTempD300SMap.put(30, "10000K");
715
+
716
+        nikonWbColorTempD200Map.put(0, "2500K");
717
+        nikonWbColorTempD200Map.put(1, "2550K");
718
+        nikonWbColorTempD200Map.put(2, "2650K");
719
+        nikonWbColorTempD200Map.put(3, "2700K");
720
+        nikonWbColorTempD200Map.put(4, "2800K");
721
+        nikonWbColorTempD200Map.put(5, "2850K");
722
+        nikonWbColorTempD200Map.put(6, "2950K");
723
+        nikonWbColorTempD200Map.put(7, "3000K");
724
+        nikonWbColorTempD200Map.put(8, "3100K");
725
+        nikonWbColorTempD200Map.put(9, "3200K");
726
+        nikonWbColorTempD200Map.put(10, "3300K");
727
+        nikonWbColorTempD200Map.put(11, "3400K");
728
+        nikonWbColorTempD200Map.put(12, "3600K");
729
+        nikonWbColorTempD200Map.put(13, "3700K");
730
+        nikonWbColorTempD200Map.put(14, "3800K");
731
+        nikonWbColorTempD200Map.put(15, "4000K");
732
+        nikonWbColorTempD200Map.put(16, "4200K");
733
+        nikonWbColorTempD200Map.put(17, "4300K");
734
+        nikonWbColorTempD200Map.put(18, "4500K");
735
+        nikonWbColorTempD200Map.put(19, "4800K");
736
+        nikonWbColorTempD200Map.put(20, "5000K");
737
+        nikonWbColorTempD200Map.put(21, "5300K");
738
+        nikonWbColorTempD200Map.put(22, "5600K");
739
+        nikonWbColorTempD200Map.put(23, "5900K");
740
+        nikonWbColorTempD200Map.put(24, "6300K");
741
+        nikonWbColorTempD200Map.put(25, "6700K");
742
+        nikonWbColorTempD200Map.put(26, "7100K");
743
+        nikonWbColorTempD200Map.put(27, "7700K");
744
+        nikonWbColorTempD200Map.put(28, "8300K");
745
+        nikonWbColorTempD200Map.put(29, "9100K");
746
+        nikonWbColorTempD200Map.put(30, "10000K");
747
+
748
+        nikonFocusModeMap.put(0x0001, "Manual Focus");
749
+        nikonFocusModeMap.put(0x8010, "Single AF servo");
750
+        nikonFocusModeMap.put(0x8011, "Continous AF servo");
751
+        nikonFocusModeMap.put(0x8012, "AF servo auto switch");
752
+        nikonFocusModeMap.put(0x8013, "Constant AF servo");
753
+
754
+        nikonActivePicCtrlItemMap.put(1, "SD");
755
+        nikonActivePicCtrlItemMap.put(2, "NL");
756
+        nikonActivePicCtrlItemMap.put(3, "VI");
757
+        nikonActivePicCtrlItemMap.put(4, "MC");
758
+        nikonActivePicCtrlItemMap.put(5, "PT");
759
+        nikonActivePicCtrlItemMap.put(6, "LS");
760
+        nikonActivePicCtrlItemMap.put(101, "O-1");
761
+        nikonActivePicCtrlItemMap.put(102, "O-2");
762
+        nikonActivePicCtrlItemMap.put(103, "O-3");
763
+        nikonActivePicCtrlItemMap.put(104, "O-4");
764
+        nikonActivePicCtrlItemMap.put(201, "C-1");
765
+        nikonActivePicCtrlItemMap.put(202, "C-2");
766
+        nikonActivePicCtrlItemMap.put(203, "C-3");
767
+        nikonActivePicCtrlItemMap.put(204, "C-4");
768
+        nikonActivePicCtrlItemMap.put(205, "C-5");
769
+        nikonActivePicCtrlItemMap.put(206, "C-6");
770
+        nikonActivePicCtrlItemMap.put(207, "C-7");
771
+        nikonActivePicCtrlItemMap.put(208, "C-8");
772
+        nikonActivePicCtrlItemMap.put(209, "C-9");
773
+
774
+//        nikonMeteringModeMap.put(2, R.drawable.metering_exposure_center_weighted_nikon);
775
+//        nikonMeteringModeMap.put(3, R.drawable.metering_exposure_matrix_nikon);
776
+//        nikonMeteringModeMap.put(4, R.drawable.metering_exposure_spot);
777
+//
778
+//        eosMeteringModeIconsMap.put(1, R.drawable.metering_exposure_spot);
779
+//        eosMeteringModeIconsMap.put(3, R.drawable.metering_exposure_evaluative_canon);
780
+//        eosMeteringModeIconsMap.put(4, R.drawable.metering_exposure_partial);
781
+//        eosMeteringModeIconsMap.put(5, R.drawable.metering_exposure_center_weighted_average_canon);
782
+
783
+        nikonFocusMeteringModeMap.put(0x0002, "Dynamic");
784
+        nikonFocusMeteringModeMap.put(0x8010, "Single point");
785
+        nikonFocusMeteringModeMap.put(0x8011, "Auto area");
786
+        nikonFocusMeteringModeMap.put(0x8012, "3D");
787
+
788
+//        nikonFocusMeteringModeIconsMap.put(0x0002, R.drawable.metering_af_dynamic_area);
789
+//        nikonFocusMeteringModeIconsMap.put(0x8010, R.drawable.metering_af_single_point);
790
+//        nikonFocusMeteringModeIconsMap.put(0x8011, R.drawable.metering_af_auto_area);
791
+//        nikonFocusMeteringModeIconsMap.put(0x8012, R.drawable.metering_af_3d_tracking);
792
+
793
+        eosPictureStyleMap.put(0x81, "ST");
794
+        eosPictureStyleMap.put(0x82, "PT");
795
+        eosPictureStyleMap.put(0x83, "LS");
796
+        eosPictureStyleMap.put(0x84, "NL");
797
+        eosPictureStyleMap.put(0x85, "FL");
798
+        eosPictureStyleMap.put(0x86, "MO");
799
+        eosPictureStyleMap.put(0x21, "UD1");
800
+        eosPictureStyleMap.put(0x22, "UD2");
801
+        eosPictureStyleMap.put(0x23, "UD3");
802
+    }
803
+}

+ 47 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/PtpService.java

@@ -0,0 +1,47 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp;
17
+
18
+import com.remoteyourcam.usb.ptp.Camera.CameraListener;
19
+
20
+import android.content.Context;
21
+import android.content.Intent;
22
+
23
+public interface PtpService {
24
+
25
+    void setCameraListener(CameraListener listener);
26
+
27
+    void initialize(Context context, Intent intent);
28
+
29
+    void shutdown();
30
+
31
+    void lazyShutdown();
32
+
33
+    public static class Singleton {
34
+        private static PtpService singleton;
35
+
36
+        public static PtpService getInstance(Context context) {
37
+            if (singleton == null) {
38
+                singleton = new PtpUsbService(context);
39
+            }
40
+            return singleton;
41
+        }
42
+
43
+        public static void setInstance(PtpService service) {
44
+            singleton = service;
45
+        }
46
+    }
47
+}

+ 76 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/PtpUsbConnection.java

@@ -0,0 +1,76 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp;
17
+
18
+import android.hardware.usb.UsbDeviceConnection;
19
+import android.hardware.usb.UsbEndpoint;
20
+import android.hardware.usb.UsbRequest;
21
+
22
+public class PtpUsbConnection {
23
+
24
+    private final UsbDeviceConnection connection;
25
+    private final UsbEndpoint bulkOut;
26
+    private final UsbEndpoint bulkIn;
27
+    private final int vendorId;
28
+    private final int productId;
29
+
30
+    public PtpUsbConnection(UsbDeviceConnection connection, UsbEndpoint bulkIn, UsbEndpoint bulkOut, int vendorId,
31
+            int productId) {
32
+        this.connection = connection;
33
+        this.bulkIn = bulkIn;
34
+        this.bulkOut = bulkOut;
35
+        this.vendorId = vendorId;
36
+        this.productId = productId;
37
+    }
38
+
39
+    public int getVendorId() {
40
+        return vendorId;
41
+    }
42
+
43
+    public int getProductId() {
44
+        return productId;
45
+    }
46
+
47
+    public void close() {
48
+        connection.close();
49
+    }
50
+
51
+    public int getMaxPacketInSize() {
52
+        return bulkIn.getMaxPacketSize();
53
+    }
54
+
55
+    public int getMaxPacketOutSize() {
56
+        return bulkOut.getMaxPacketSize();
57
+    }
58
+
59
+    public UsbRequest createInRequest() {
60
+        UsbRequest r = new UsbRequest();
61
+        r.initialize(connection, bulkIn);
62
+        return r;
63
+    }
64
+
65
+    public int bulkTransferOut(byte[] buffer, int length, int timeout) {
66
+        return connection.bulkTransfer(bulkOut, buffer, length, timeout);
67
+    }
68
+
69
+    public int bulkTransferIn(byte[] buffer, int maxLength, int timeout) {
70
+        return connection.bulkTransfer(bulkIn, buffer, maxLength, timeout);
71
+    }
72
+
73
+    public void requestWait() {
74
+        connection.requestWait();
75
+    }
76
+}

+ 234 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/PtpUsbService.java

@@ -0,0 +1,234 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp;
17
+
18
+import java.util.Map;
19
+
20
+import android.app.PendingIntent;
21
+import android.content.BroadcastReceiver;
22
+import android.content.Context;
23
+import android.content.Intent;
24
+import android.content.IntentFilter;
25
+import android.hardware.usb.UsbConstants;
26
+import android.hardware.usb.UsbDevice;
27
+import android.hardware.usb.UsbEndpoint;
28
+import android.hardware.usb.UsbInterface;
29
+import android.hardware.usb.UsbManager;
30
+import android.os.Handler;
31
+import android.util.Log;
32
+
33
+import com.remoteyourcam.usb.AppConfig;
34
+import com.remoteyourcam.usb.ptp.Camera.CameraListener;
35
+import com.remoteyourcam.usb.ptp.PtpCamera.State;
36
+
37
+public class PtpUsbService implements PtpService {
38
+
39
+    private final String TAG = PtpUsbService.class.getSimpleName();
40
+
41
+    private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
42
+    private final BroadcastReceiver permissonReceiver = new BroadcastReceiver() {
43
+        @Override
44
+        public void onReceive(Context context, Intent intent) {
45
+            String action = intent.getAction();
46
+            if (ACTION_USB_PERMISSION.equals(action)) {
47
+                unregisterPermissionReceiver(context);
48
+                synchronized (this) {
49
+                    UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
50
+
51
+                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
52
+                        connect(context, device);
53
+                    } else {
54
+                        //TODO report
55
+                    }
56
+                }
57
+            }
58
+        }
59
+    };
60
+
61
+    private final Handler handler = new Handler();
62
+    private final UsbManager usbManager;
63
+    private PtpCamera camera;
64
+    private CameraListener listener;
65
+
66
+    Runnable shutdownRunnable = new Runnable() {
67
+        @Override
68
+        public void run() {
69
+            shutdown();
70
+        }
71
+    };
72
+
73
+    public PtpUsbService(Context context) {
74
+        this.usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
75
+    }
76
+
77
+    @Override
78
+    public void setCameraListener(CameraListener listener) {
79
+        this.listener = listener;
80
+        if (camera != null) {
81
+            camera.setListener(listener);
82
+        }
83
+    }
84
+
85
+    @Override
86
+    public void initialize(Context context, Intent intent) {
87
+        handler.removeCallbacks(shutdownRunnable);
88
+        if (camera != null) {
89
+            if (AppConfig.LOG) {
90
+                Log.i(TAG, "initialize: camera available");
91
+                listener.onLogMessage("有可用相机,初始化中");
92
+            }
93
+            if (camera.getState() == State.Active) {
94
+                if (listener != null) {
95
+                    listener.onCameraStarted(camera);
96
+                }
97
+                return;
98
+            }
99
+            if (AppConfig.LOG) {
100
+                Log.i(TAG, "initialize: camera not active, satet " + camera.getState());
101
+            }
102
+            camera.shutdownHard();
103
+        }
104
+        UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
105
+        if (device != null) {
106
+            if (AppConfig.LOG) {
107
+                Log.i(TAG, "initialize: got device through intent");
108
+                listener.onLogMessage("发现可用相机设备"+device.getDeviceName());
109
+            }
110
+            connect(context, device);
111
+        } else {
112
+            if (AppConfig.LOG) {
113
+                Log.i(TAG, "initialize: looking for compatible camera");
114
+                listener.onLogMessage("查找相机设备...");
115
+            }
116
+            device = lookupCompatibleDevice(usbManager);
117
+            if (device != null) {
118
+                listener.onLogMessage("查找到相机设备"+device.getDeviceName());
119
+                registerPermissionReceiver(context);
120
+                PendingIntent mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(
121
+                        ACTION_USB_PERMISSION), 0);
122
+                usbManager.requestPermission(device, mPermissionIntent);
123
+            } else {
124
+                listener.onNoCameraFound();
125
+            }
126
+        }
127
+    }
128
+
129
+    @Override
130
+    public void shutdown() {
131
+        if (AppConfig.LOG) {
132
+            Log.i(TAG, "shutdown");
133
+            listener.onLogMessage("关闭设备");
134
+        }
135
+        if (camera != null) {
136
+            camera.shutdown();
137
+            camera = null;
138
+        }
139
+    }
140
+
141
+    @Override
142
+    public void lazyShutdown() {
143
+        if (AppConfig.LOG) {
144
+            Log.i(TAG, "lazy shutdown");
145
+        }
146
+        handler.postDelayed(shutdownRunnable, 4000);
147
+    }
148
+
149
+    private void registerPermissionReceiver(Context context) {
150
+        if (AppConfig.LOG) {
151
+            Log.i(TAG, "register permission receiver");
152
+        }
153
+        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
154
+        context.registerReceiver(permissonReceiver, filter);
155
+    }
156
+
157
+    private void unregisterPermissionReceiver(Context context) {
158
+        if (AppConfig.LOG) {
159
+            Log.i(TAG, "unregister permission receiver");
160
+        }
161
+        context.unregisterReceiver(permissonReceiver);
162
+    }
163
+
164
+    private UsbDevice lookupCompatibleDevice(UsbManager manager) {
165
+        Map<String, UsbDevice> deviceList = manager.getDeviceList();
166
+        for (Map.Entry<String, UsbDevice> e : deviceList.entrySet()) {
167
+            UsbDevice d = e.getValue();
168
+            if (d.getVendorId() == PtpConstants.CanonVendorId || d.getVendorId() == PtpConstants.NikonVendorId) {
169
+                return d;
170
+            }
171
+        }
172
+        return null;
173
+    }
174
+
175
+    private boolean connect(Context context, UsbDevice device) {
176
+        if (camera != null) {
177
+            camera.shutdown();
178
+            camera = null;
179
+        }
180
+        for (int i = 0, n = device.getInterfaceCount(); i < n; ++i) {
181
+            UsbInterface intf = device.getInterface(i);
182
+
183
+            if (intf.getEndpointCount() != 3) {
184
+                continue;
185
+            }
186
+
187
+            UsbEndpoint in = null;
188
+            UsbEndpoint out = null;
189
+
190
+            for (int e = 0, en = intf.getEndpointCount(); e < en; ++e) {
191
+                UsbEndpoint endpoint = intf.getEndpoint(e);
192
+                if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
193
+                    if (endpoint.getDirection() == UsbConstants.USB_DIR_IN) {
194
+                        in = endpoint;
195
+                    } else if (endpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
196
+                        out = endpoint;
197
+                    }
198
+                }
199
+            }
200
+
201
+            if (in == null || out == null) {
202
+                continue;
203
+            }
204
+
205
+            if (AppConfig.LOG) {
206
+                Log.i(TAG, "Found compatible USB interface");
207
+                Log.i(TAG, "Interface class " + intf.getInterfaceClass());
208
+                Log.i(TAG, "Interface subclass " + intf.getInterfaceSubclass());
209
+                Log.i(TAG, "Interface protocol " + intf.getInterfaceProtocol());
210
+                Log.i(TAG, "Bulk out max size " + out.getMaxPacketSize());
211
+                Log.i(TAG, "Bulk in max size " + in.getMaxPacketSize());
212
+                listener.onLogMessage("发现兼容的USB接口设备 "+ device.getDeviceName() +" "+  device.getVendorId());
213
+            }
214
+
215
+            if (device.getVendorId() == PtpConstants.CanonVendorId) {
216
+                PtpUsbConnection connection = new PtpUsbConnection(usbManager.openDevice(device), in, out,
217
+                        device.getVendorId(), device.getProductId());
218
+                camera = new EosCamera(connection, listener, new WorkerNotifier(context));
219
+            } else if (device.getVendorId() == PtpConstants.NikonVendorId) {
220
+                PtpUsbConnection connection = new PtpUsbConnection(usbManager.openDevice(device), in, out,
221
+                        device.getVendorId(), device.getProductId());
222
+                camera = new NikonCamera(connection, listener, new WorkerNotifier(context));
223
+            }
224
+
225
+            return true;
226
+        }
227
+
228
+        if (listener != null) {
229
+            listener.onError("No compatible camera found");
230
+        }
231
+
232
+        return false;
233
+    }
234
+}

+ 34 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/WorkerNotifier.java

@@ -0,0 +1,34 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp;
17
+
18
+import android.content.Context;
19
+
20
+public class WorkerNotifier implements Camera.WorkerListener {
21
+
22
+
23
+    public WorkerNotifier(Context context) {
24
+    }
25
+
26
+    @Override
27
+    public void onWorkerStarted() {
28
+    }
29
+
30
+    @Override
31
+    public void onWorkerEnded() {
32
+    }
33
+
34
+}

+ 61 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/CloseSessionCommand.java

@@ -0,0 +1,61 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.AppConfig;
21
+import com.remoteyourcam.usb.ptp.PtpCamera;
22
+import com.remoteyourcam.usb.ptp.PtpConstants;
23
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
24
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
25
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
26
+
27
+import android.util.Log;
28
+
29
+public class CloseSessionCommand extends Command {
30
+
31
+    private final String TAG = CloseSessionCommand.class.getSimpleName();
32
+
33
+    public CloseSessionCommand(PtpCamera camera) {
34
+        super(camera);
35
+    }
36
+
37
+    @Override
38
+    public void exec(IO io) {
39
+        io.handleCommand(this);
40
+        // Can this even happen?
41
+        if (responseCode == Response.DeviceBusy) {
42
+            camera.onDeviceBusy(this, true);
43
+            return;
44
+        }
45
+        // close even when error happened
46
+        camera.onSessionClosed();
47
+        if (responseCode != Response.Ok) {
48
+            // TODO error report
49
+            if (AppConfig.LOG) {
50
+                Log.w(TAG,
51
+                        String.format("Error response when closing session, response %s",
52
+                                PtpConstants.responseToString(responseCode)));
53
+            }
54
+        }
55
+    }
56
+
57
+    @Override
58
+    public void encodeCommand(ByteBuffer b) {
59
+        encodeCommand(b, Operation.CloseSession);
60
+    }
61
+}

+ 188 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/Command.java

@@ -0,0 +1,188 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import android.util.Log;
19
+
20
+import com.remoteyourcam.usb.AppConfig;
21
+import com.remoteyourcam.usb.ptp.PacketUtil;
22
+import com.remoteyourcam.usb.ptp.PtpAction;
23
+import com.remoteyourcam.usb.ptp.PtpCamera;
24
+import com.remoteyourcam.usb.ptp.PtpConstants;
25
+import com.remoteyourcam.usb.ptp.PtpConstants.Type;
26
+
27
+import java.nio.ByteBuffer;
28
+
29
+/**
30
+ * Base class for all PTP commands.
31
+ */
32
+public abstract class Command implements PtpAction {
33
+
34
+    private static final String TAG = "Command";
35
+
36
+    protected final PtpCamera camera;
37
+
38
+    /**
39
+     * Deriving classes have to set this field to true if they want to send data
40
+     * from host to camera.
41
+     */
42
+    protected boolean hasDataToSend;
43
+
44
+    /**
45
+     * Received response code, should be handled in
46
+     * {@link #exec(com.remoteyourcam.usb.ptp.PtpCamera.IO)}.
47
+     */
48
+    protected int responseCode;
49
+
50
+    private boolean hasResponseReceived;
51
+
52
+    public Command(PtpCamera camera) {
53
+        this.camera = camera;
54
+    }
55
+
56
+    @Override
57
+    public abstract void exec(PtpCamera.IO io);
58
+
59
+    public abstract void encodeCommand(ByteBuffer b);
60
+
61
+    /**
62
+     * Derived classes should implement this method if they want to send data
63
+     * from host to camera. The field {@code hasDataToSend} has to be set to
64
+     * true for the sending to be done. The data to send must not be greater
65
+     * than the USB max packet size, any size below 256 should be save.
66
+     */
67
+    public void encodeData(ByteBuffer b) {
68
+    }
69
+
70
+    /**
71
+     * Derived classes should implement this method if they want to decode data
72
+     * received in an data packet that has been sent by the camera. The
73
+     * {@code ByteBuffer} already points to the first byte behind the
74
+     * transaction id, i.e. the payload.
75
+     */
76
+    protected void decodeData(ByteBuffer b, int length) {
77
+        if (AppConfig.LOG) {
78
+            Log.w(TAG, "Received data packet but handler not implemented");
79
+        }
80
+    }
81
+
82
+    /**
83
+     * Override if any special response data has to be decoded. The
84
+     * {@code ByteBuffer} already points to the first byte behind the
85
+     * transaction id, i.e. the payload.
86
+     */
87
+    protected void decodeResponse(ByteBuffer b, int length) {
88
+    }
89
+
90
+    public boolean hasDataToSend() {
91
+        return hasDataToSend;
92
+    }
93
+
94
+    public boolean hasResponseReceived() {
95
+        return hasResponseReceived;
96
+    }
97
+
98
+    public int getResponseCode() {
99
+        return responseCode;
100
+    }
101
+
102
+    public void receivedRead(ByteBuffer b) {
103
+        int length = b.getInt();
104
+        int type = b.getShort() & 0xFFFF;
105
+        int code = b.getShort() & 0xFFFF;
106
+        int tx = b.getInt();
107
+
108
+        if (AppConfig.LOG) {
109
+            Log.i(TAG,
110
+                    String.format("Received %s packet for %s, length %d, code %s, tx %d",
111
+                            PtpConstants.typeToString(type), getClass().getSimpleName(), length,
112
+                            PtpConstants.codeToString(type, code), tx));
113
+        }
114
+        if (AppConfig.LOG_PACKETS) {
115
+            PacketUtil.logHexdump(TAG, b.array(), length < 512 ? length : 512);
116
+        }
117
+
118
+        if (type == Type.Data) {
119
+            decodeData(b, length);
120
+        } else if (type == Type.Response) {
121
+            hasResponseReceived = true;
122
+            responseCode = code;
123
+            decodeResponse(b, length);
124
+        } else {
125
+            // error
126
+            hasResponseReceived = true;
127
+        }
128
+    }
129
+
130
+    /**
131
+     * Reset fields so this command may be requeued.
132
+     */
133
+    @Override
134
+    public void reset() {
135
+        responseCode = 0;
136
+        hasResponseReceived = false;
137
+    }
138
+
139
+    protected void encodeCommand(ByteBuffer b, int code) {
140
+        b.putInt(12);
141
+        b.putShort((short) Type.Command);
142
+        b.putShort((short) code);
143
+        b.putInt(camera.nextTransactionId());
144
+        if (AppConfig.LOG_PACKETS) {
145
+            Log.i(TAG, "command packet for " + getClass().getSimpleName());
146
+            PacketUtil.logHexdump(TAG, b.array(), 12);
147
+        }
148
+    }
149
+
150
+    protected void encodeCommand(ByteBuffer b, int code, int p0) {
151
+        b.putInt(16);
152
+        b.putShort((short) Type.Command);
153
+        b.putShort((short) code);
154
+        b.putInt(camera.nextTransactionId());
155
+        b.putInt(p0);
156
+        if (AppConfig.LOG_PACKETS) {
157
+            Log.i(TAG, "command packet for " + getClass().getSimpleName());
158
+            PacketUtil.logHexdump(TAG, b.array(), 16);
159
+        }
160
+    }
161
+
162
+    protected void encodeCommand(ByteBuffer b, int code, int p0, int p1) {
163
+        b.putInt(20);
164
+        b.putShort((short) Type.Command);
165
+        b.putShort((short) code);
166
+        b.putInt(camera.nextTransactionId());
167
+        b.putInt(p0);
168
+        b.putInt(p1);
169
+        if (AppConfig.LOG_PACKETS) {
170
+            Log.i(TAG, "command packet for " + getClass().getSimpleName());
171
+            PacketUtil.logHexdump(TAG, b.array(), 20);
172
+        }
173
+    }
174
+
175
+    protected void encodeCommand(ByteBuffer b, int code, int p0, int p1, int p2) {
176
+        b.putInt(24);
177
+        b.putShort((short) Type.Command);
178
+        b.putShort((short) code);
179
+        b.putInt(camera.nextTransactionId());
180
+        b.putInt(p0);
181
+        b.putInt(p1);
182
+        b.putInt(p2);
183
+        if (AppConfig.LOG_PACKETS) {
184
+            Log.i(TAG, "command packet for " + getClass().getSimpleName());
185
+            PacketUtil.logHexdump(TAG, b.array(), 24);
186
+        }
187
+    }
188
+}

+ 62 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetDeviceInfoCommand.java

@@ -0,0 +1,62 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.PtpCamera;
21
+import com.remoteyourcam.usb.ptp.PtpConstants;
22
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
23
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
24
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
25
+import com.remoteyourcam.usb.ptp.model.DeviceInfo;
26
+
27
+public class GetDeviceInfoCommand extends Command {
28
+
29
+    private DeviceInfo info;
30
+
31
+    public GetDeviceInfoCommand(PtpCamera camera) {
32
+        super(camera);
33
+    }
34
+
35
+    @Override
36
+    public void exec(IO io) {
37
+        io.handleCommand(this);
38
+        if (responseCode != Response.Ok) {
39
+            camera.onPtpError(String.format("Couldn't read device information, error code \"%s\"",
40
+                    PtpConstants.responseToString(responseCode)));
41
+        } else if (info == null) {
42
+            camera.onPtpError("Couldn't retrieve device information");
43
+        }
44
+    }
45
+
46
+    @Override
47
+    public void reset() {
48
+        super.reset();
49
+        info = null;
50
+    }
51
+
52
+    @Override
53
+    public void encodeCommand(ByteBuffer b) {
54
+        encodeCommand(b, Operation.GetDeviceInfo);
55
+    }
56
+
57
+    @Override
58
+    protected void decodeData(ByteBuffer b, int length) {
59
+        info = new DeviceInfo(b, length);
60
+        camera.setDeviceInfo(info);
61
+    }
62
+}

+ 57 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetDevicePropDescCommand.java

@@ -0,0 +1,57 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.PtpCamera;
21
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
22
+import com.remoteyourcam.usb.ptp.PtpConstants;
23
+import com.remoteyourcam.usb.ptp.model.DevicePropDesc;
24
+
25
+public class GetDevicePropDescCommand extends Command {
26
+
27
+    private final int property;
28
+    private DevicePropDesc devicePropDesc;
29
+
30
+    public GetDevicePropDescCommand(PtpCamera camera, int property) {
31
+        super(camera);
32
+        this.property = property;
33
+    }
34
+
35
+    @Override
36
+    public void exec(IO io) {
37
+        io.handleCommand(this);
38
+        if (responseCode == PtpConstants.Response.DeviceBusy) {
39
+            camera.onDeviceBusy(this, true);
40
+        }
41
+        if (devicePropDesc != null) {
42
+            // this order is important
43
+            camera.onPropertyDescChanged(property, devicePropDesc);
44
+            camera.onPropertyChanged(property, devicePropDesc.currentValue);
45
+        }
46
+    }
47
+
48
+    @Override
49
+    public void encodeCommand(ByteBuffer b) {
50
+        encodeCommand(b, PtpConstants.Operation.GetDevicePropDesc, property);
51
+    }
52
+
53
+    @Override
54
+    protected void decodeData(ByteBuffer b, int length) {
55
+        devicePropDesc = new DevicePropDesc(b, length);
56
+    }
57
+}

+ 68 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetDevicePropValueCommand.java

@@ -0,0 +1,68 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.PtpCamera;
21
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
22
+import com.remoteyourcam.usb.ptp.PtpConstants;
23
+import com.remoteyourcam.usb.ptp.PtpConstants.Datatype;
24
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
25
+
26
+public class GetDevicePropValueCommand extends Command {
27
+
28
+    private final int property;
29
+    private final int datatype;
30
+    private int value;
31
+
32
+    public GetDevicePropValueCommand(PtpCamera camera, int property, int datatype) {
33
+        super(camera);
34
+        this.property = property;
35
+        this.datatype = datatype;
36
+    }
37
+
38
+    @Override
39
+    public void exec(IO io) {
40
+        io.handleCommand(this);
41
+        if (responseCode == Response.DeviceBusy) {
42
+            camera.onDeviceBusy(this, true);
43
+        }
44
+        if (responseCode == Response.Ok) {
45
+            camera.onPropertyChanged(property, value);
46
+        }
47
+    }
48
+
49
+    @Override
50
+    public void encodeCommand(ByteBuffer b) {
51
+        encodeCommand(b, PtpConstants.Operation.GetDevicePropValue, property);
52
+    }
53
+
54
+    @Override
55
+    protected void decodeData(ByteBuffer b, int length) {
56
+        if (datatype == Datatype.int8) {
57
+            value = b.get();
58
+        } else if (datatype == Datatype.uint8) {
59
+            value = b.get() & 0xFF;
60
+        } else if (datatype == Datatype.uint16) {
61
+            value = b.getShort() & 0xFFFF;
62
+        } else if (datatype == Datatype.int16) {
63
+            value = b.getShort();
64
+        } else if (datatype == Datatype.int32 || datatype == Datatype.uint32) {
65
+            value = b.getInt();
66
+        }
67
+    }
68
+}

+ 90 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetObjectCommand.java

@@ -0,0 +1,90 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import android.graphics.Bitmap;
21
+import android.graphics.BitmapFactory;
22
+import android.util.Log;
23
+
24
+import com.remoteyourcam.usb.ptp.PtpCamera;
25
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
26
+import com.remoteyourcam.usb.ptp.PtpConstants;
27
+
28
+/**
29
+ * Read file data from camera with specified {@code objectHandle}.
30
+ */
31
+public class GetObjectCommand extends Command {
32
+
33
+    private static final String TAG = GetObjectCommand.class.getSimpleName();
34
+
35
+    private final int objectHandle;
36
+
37
+    private final BitmapFactory.Options options;
38
+    private Bitmap inBitmap;
39
+
40
+    private boolean outOfMemoryError;
41
+
42
+    public GetObjectCommand(PtpCamera camera, int objectHandle, int sampleSize) {
43
+        super(camera);
44
+        this.objectHandle = objectHandle;
45
+        options = new BitmapFactory.Options();
46
+        if (sampleSize >= 1 && sampleSize <= 4) {
47
+            options.inSampleSize = sampleSize;
48
+        } else {
49
+            options.inSampleSize = 2;
50
+        }
51
+    }
52
+
53
+    public Bitmap getBitmap() {
54
+        return inBitmap;
55
+    }
56
+
57
+    public boolean isOutOfMemoryError() {
58
+        return outOfMemoryError;
59
+    }
60
+
61
+    @Override
62
+    public void exec(IO io) {
63
+        throw new UnsupportedOperationException();
64
+    }
65
+
66
+    @Override
67
+    public void reset() {
68
+        super.reset();
69
+        inBitmap = null;
70
+        outOfMemoryError = false;
71
+    }
72
+
73
+    @Override
74
+    public void encodeCommand(ByteBuffer b) {
75
+        encodeCommand(b, PtpConstants.Operation.GetObject, objectHandle);
76
+    }
77
+
78
+    @Override
79
+    protected void decodeData(ByteBuffer b, int length) {
80
+        try {
81
+            // 12 == offset of data header
82
+            inBitmap = BitmapFactory.decodeByteArray(b.array(), 12, length - 12, options);
83
+        } catch (RuntimeException e) {
84
+            Log.i(TAG, "exception on decoding picture : " + e.toString());
85
+        } catch (OutOfMemoryError e) {
86
+            System.gc();
87
+            outOfMemoryError = true;
88
+        }
89
+    }
90
+}

+ 79 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetObjectHandlesCommand.java

@@ -0,0 +1,79 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.Camera.StorageInfoListener;
21
+import com.remoteyourcam.usb.ptp.PacketUtil;
22
+import com.remoteyourcam.usb.ptp.PtpCamera;
23
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
24
+import com.remoteyourcam.usb.ptp.PtpConstants;
25
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
26
+
27
+public class GetObjectHandlesCommand extends Command {
28
+
29
+    private final int storageId;
30
+    private final int objectFormat;
31
+    private final int associationHandle;
32
+    private int[] objectHandles;
33
+    private final StorageInfoListener listener;
34
+
35
+    public int[] getObjectHandles() {
36
+        if (objectHandles == null) {
37
+            return new int[0];
38
+        }
39
+        return objectHandles;
40
+    }
41
+
42
+    public GetObjectHandlesCommand(PtpCamera camera, StorageInfoListener listener, int storageId) {
43
+        this(camera, listener, storageId, 0, 0);
44
+    }
45
+
46
+    public GetObjectHandlesCommand(PtpCamera camera, StorageInfoListener listener, int storageId, int objectFormat) {
47
+        this(camera, listener, storageId, objectFormat, 0);
48
+    }
49
+
50
+    public GetObjectHandlesCommand(PtpCamera camera, StorageInfoListener listener, int storageId, int objectFormat,
51
+            int associationHandle) {
52
+        super(camera);
53
+        this.listener = listener;
54
+        this.storageId = storageId;
55
+        this.objectFormat = objectFormat;
56
+        this.associationHandle = associationHandle;
57
+    }
58
+
59
+    @Override
60
+    public void exec(IO io) {
61
+        io.handleCommand(this);
62
+        if (getResponseCode() != Response.Ok) {
63
+            // error
64
+            listener.onImageHandlesRetrieved(new int[0]);
65
+            return;
66
+        }
67
+        listener.onImageHandlesRetrieved(objectHandles);
68
+    }
69
+
70
+    @Override
71
+    public void encodeCommand(ByteBuffer b) {
72
+        super.encodeCommand(b, PtpConstants.Operation.GetObjectHandles, storageId, objectFormat, associationHandle);
73
+    }
74
+
75
+    @Override
76
+    protected void decodeData(ByteBuffer b, int length) {
77
+        objectHandles = PacketUtil.readU32Array(b);
78
+    }
79
+}

+ 73 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetObjectInfoCommand.java

@@ -0,0 +1,73 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.AppConfig;
21
+import com.remoteyourcam.usb.ptp.PtpCamera;
22
+import com.remoteyourcam.usb.ptp.PtpConstants;
23
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
24
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
25
+import com.remoteyourcam.usb.ptp.model.ObjectInfo;
26
+
27
+import android.util.Log;
28
+
29
+public class GetObjectInfoCommand extends Command {
30
+
31
+    private final String TAG = GetObjectInfoCommand.class.getSimpleName();
32
+
33
+    private final int outObjectHandle;
34
+    private ObjectInfo inObjectInfo;
35
+
36
+    public GetObjectInfoCommand(PtpCamera camera, int objectHandle) {
37
+        super(camera);
38
+        this.outObjectHandle = objectHandle;
39
+    }
40
+
41
+    public ObjectInfo getObjectInfo() {
42
+        return inObjectInfo;
43
+    }
44
+
45
+    @Override
46
+    public void exec(IO io) {
47
+        io.handleCommand(this);
48
+        if (responseCode == Response.DeviceBusy) {
49
+            camera.onDeviceBusy(this, true);
50
+        }
51
+        if (inObjectInfo != null) {
52
+            if (AppConfig.LOG) {
53
+                Log.i(TAG, inObjectInfo.toString());
54
+            }
55
+        }
56
+    }
57
+
58
+    @Override
59
+    public void reset() {
60
+        super.reset();
61
+        inObjectInfo = null;
62
+    }
63
+
64
+    @Override
65
+    public void encodeCommand(ByteBuffer b) {
66
+        encodeCommand(b, PtpConstants.Operation.GetObjectInfo, outObjectHandle);
67
+    }
68
+
69
+    @Override
70
+    protected void decodeData(ByteBuffer b, int length) {
71
+        inObjectInfo = new ObjectInfo(b, length);
72
+    }
73
+}

+ 54 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetStorageIdsCommand.java

@@ -0,0 +1,54 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.PacketUtil;
21
+import com.remoteyourcam.usb.ptp.PtpCamera;
22
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
23
+import com.remoteyourcam.usb.ptp.PtpConstants;
24
+
25
+public class GetStorageIdsCommand extends Command {
26
+
27
+    private int[] storageIds;
28
+
29
+    public int[] getStorageIds() {
30
+        if (storageIds == null) {
31
+            return new int[0];
32
+        }
33
+        return storageIds;
34
+    }
35
+
36
+    public GetStorageIdsCommand(PtpCamera camera) {
37
+        super(camera);
38
+    }
39
+
40
+    @Override
41
+    public void exec(IO io) {
42
+        io.handleCommand(this);
43
+    }
44
+
45
+    @Override
46
+    public void encodeCommand(ByteBuffer b) {
47
+        super.encodeCommand(b, PtpConstants.Operation.GetStorageIDs);
48
+    }
49
+
50
+    @Override
51
+    protected void decodeData(ByteBuffer b, int length) {
52
+        storageIds = PacketUtil.readU32Array(b);
53
+    }
54
+}

+ 53 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetStorageInfoCommand.java

@@ -0,0 +1,53 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.PtpCamera;
21
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
22
+import com.remoteyourcam.usb.ptp.PtpConstants;
23
+import com.remoteyourcam.usb.ptp.model.StorageInfo;
24
+
25
+public class GetStorageInfoCommand extends Command {
26
+
27
+    private StorageInfo storageInfo;
28
+    private final int storageId;
29
+
30
+    public StorageInfo getStorageInfo() {
31
+        return storageInfo;
32
+    }
33
+
34
+    public GetStorageInfoCommand(PtpCamera camera, int storageId) {
35
+        super(camera);
36
+        this.storageId = storageId;
37
+    }
38
+
39
+    @Override
40
+    public void exec(IO io) {
41
+        io.handleCommand(this);
42
+    }
43
+
44
+    @Override
45
+    public void encodeCommand(ByteBuffer b) {
46
+        super.encodeCommand(b, PtpConstants.Operation.GetStorageInfo, storageId);
47
+    }
48
+
49
+    @Override
50
+    protected void decodeData(ByteBuffer b, int length) {
51
+        storageInfo = new StorageInfo(b, length);
52
+    }
53
+}

+ 72 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetStorageInfosAction.java

@@ -0,0 +1,72 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import com.remoteyourcam.usb.ptp.Camera;
19
+import com.remoteyourcam.usb.ptp.Camera.StorageInfoListener;
20
+import com.remoteyourcam.usb.ptp.PtpAction;
21
+import com.remoteyourcam.usb.ptp.PtpCamera;
22
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
23
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
24
+
25
+public class GetStorageInfosAction implements PtpAction {
26
+
27
+    private final PtpCamera camera;
28
+    private final StorageInfoListener listener;
29
+
30
+    public GetStorageInfosAction(PtpCamera camera, Camera.StorageInfoListener listener) {
31
+        this.camera = camera;
32
+        this.listener = listener;
33
+    }
34
+
35
+    @Override
36
+    public void exec(IO io) {
37
+        GetStorageIdsCommand getStorageIds = new GetStorageIdsCommand(camera);
38
+        io.handleCommand(getStorageIds);
39
+
40
+        if (getStorageIds.getResponseCode() != Response.Ok) {
41
+            listener.onAllStoragesFound();
42
+            return;
43
+        }
44
+
45
+        int ids[] = getStorageIds.getStorageIds();
46
+        for (int i = 0; i < ids.length; ++i) {
47
+            int storageId = ids[i];
48
+            if(storageId == 131073){
49
+                GetStorageInfoCommand c = new GetStorageInfoCommand(camera, storageId);
50
+                io.handleCommand(c);
51
+
52
+                if (c.getResponseCode() != Response.Ok) {
53
+                    listener.onAllStoragesFound();
54
+                    return;
55
+                }
56
+
57
+                String label = c.getStorageInfo().volumeLabel.isEmpty() ? c.getStorageInfo().storageDescription : c
58
+                        .getStorageInfo().volumeLabel;
59
+                if (label == null || label.isEmpty()) {
60
+                    label = "Storage " + i;
61
+                }
62
+                listener.onStorageFound(storageId, label);
63
+            }
64
+        }
65
+
66
+        listener.onAllStoragesFound();
67
+    }
68
+
69
+    @Override
70
+    public void reset() {
71
+    }
72
+}

+ 71 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/GetThumb.java

@@ -0,0 +1,71 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import android.graphics.Bitmap;
21
+import android.graphics.BitmapFactory;
22
+import android.util.Log;
23
+
24
+import com.remoteyourcam.usb.ptp.PtpCamera;
25
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
26
+import com.remoteyourcam.usb.ptp.PtpConstants;
27
+
28
+public class GetThumb extends Command {
29
+
30
+    private static final String TAG = GetThumb.class.getSimpleName();
31
+
32
+    private final int objectHandle;
33
+    private Bitmap inBitmap;
34
+
35
+    public GetThumb(PtpCamera camera, int objectHandle) {
36
+        super(camera);
37
+        this.objectHandle = objectHandle;
38
+    }
39
+
40
+    public Bitmap getBitmap() {
41
+        return inBitmap;
42
+    }
43
+
44
+    @Override
45
+    public void exec(IO io) {
46
+        throw new UnsupportedOperationException();
47
+    }
48
+
49
+    @Override
50
+    public void reset() {
51
+        super.reset();
52
+        inBitmap = null;
53
+    }
54
+
55
+    @Override
56
+    public void encodeCommand(ByteBuffer b) {
57
+        encodeCommand(b, PtpConstants.Operation.GetThumb, objectHandle);
58
+    }
59
+
60
+    @Override
61
+    protected void decodeData(ByteBuffer b, int length) {
62
+        try {
63
+            // 12 == offset of data header
64
+            inBitmap = BitmapFactory.decodeByteArray(b.array(), 12, length - 12);
65
+        } catch (RuntimeException e) {
66
+            Log.i(TAG, "exception on decoding picture : " + e.toString());
67
+        } catch (OutOfMemoryError e) {
68
+            System.gc();
69
+        }
70
+    }
71
+}

+ 44 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/InitiateCaptureCommand.java

@@ -0,0 +1,44 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.PtpCamera;
21
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
22
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
23
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
24
+
25
+public class InitiateCaptureCommand extends Command {
26
+
27
+    public InitiateCaptureCommand(PtpCamera camera) {
28
+        super(camera);
29
+    }
30
+
31
+    @Override
32
+    public void exec(IO io) {
33
+        io.handleCommand(this);
34
+        if (responseCode == Response.DeviceBusy) {
35
+            camera.onDeviceBusy(this, true); // TODO when nikon live view is enabled this stalls
36
+            return;
37
+        }
38
+    }
39
+
40
+    @Override
41
+    public void encodeCommand(ByteBuffer b) {
42
+        encodeCommand(b, Operation.InitiateCapture, 0, 0);
43
+    }
44
+}

+ 44 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/InitiateOpenCaptureCommand.java

@@ -0,0 +1,44 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import com.remoteyourcam.usb.ptp.PtpCamera;
19
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
20
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
21
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
22
+
23
+import java.nio.ByteBuffer;
24
+
25
+public class InitiateOpenCaptureCommand extends Command {
26
+
27
+    public InitiateOpenCaptureCommand(PtpCamera camera) {
28
+        super(camera);
29
+    }
30
+
31
+    @Override
32
+    public void exec(IO io) {
33
+        io.handleCommand(this);
34
+        if (responseCode == Response.DeviceBusy) {
35
+            camera.onDeviceBusy(this, true); // TODO when nikon live view is enabled this stalls
36
+            return;
37
+        }
38
+    }
39
+
40
+    @Override
41
+    public void encodeCommand(ByteBuffer b) {
42
+        encodeCommand(b, Operation.InitiateOpenCapture, 0, 0);
43
+    }
44
+}

+ 48 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/OpenSessionCommand.java

@@ -0,0 +1,48 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.PtpCamera;
21
+import com.remoteyourcam.usb.ptp.PtpConstants;
22
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
23
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
24
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
25
+
26
+public class OpenSessionCommand extends Command {
27
+
28
+    public OpenSessionCommand(PtpCamera camera) {
29
+        super(camera);
30
+    }
31
+
32
+    @Override
33
+    public void exec(IO io) {
34
+        io.handleCommand(this);
35
+        if (responseCode == Response.Ok) {
36
+            camera.onSessionOpened();
37
+        } else {
38
+            camera.onPtpError(String.format("Couldn't open session, error code \"%s\"",
39
+                    PtpConstants.responseToString(responseCode)));
40
+        }
41
+    }
42
+
43
+    @Override
44
+    public void encodeCommand(ByteBuffer b) {
45
+        camera.resetTransactionId();
46
+        encodeCommand(b, Operation.OpenSession, 1);
47
+    }
48
+}

+ 51 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/RetrieveAddedObjectInfoAction.java

@@ -0,0 +1,51 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import com.remoteyourcam.usb.ptp.PtpAction;
19
+import com.remoteyourcam.usb.ptp.PtpCamera;
20
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
21
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
22
+
23
+public class RetrieveAddedObjectInfoAction implements PtpAction {
24
+
25
+    private final PtpCamera camera;
26
+    private final int objectHandle;
27
+
28
+    public RetrieveAddedObjectInfoAction(PtpCamera camera, int objectHandle) {
29
+        this.camera = camera;
30
+        this.objectHandle = objectHandle;
31
+    }
32
+
33
+    @Override
34
+    public void exec(IO io) {
35
+        GetObjectInfoCommand getInfo = new GetObjectInfoCommand(camera, objectHandle);
36
+        io.handleCommand(getInfo);
37
+
38
+        if (getInfo.getResponseCode() != Response.Ok) {
39
+            return;
40
+        }
41
+        if (getInfo.getObjectInfo() == null) {
42
+            return;
43
+        }
44
+
45
+        camera.onEventObjectAdded(objectHandle);
46
+    }
47
+
48
+    @Override
49
+    public void reset() {
50
+    }
51
+}

+ 54 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/RetrieveImageAction.java

@@ -0,0 +1,54 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import com.remoteyourcam.usb.ptp.Camera.RetrieveImageListener;
19
+import com.remoteyourcam.usb.ptp.PtpAction;
20
+import com.remoteyourcam.usb.ptp.PtpCamera;
21
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
22
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
23
+
24
+public class RetrieveImageAction implements PtpAction {
25
+
26
+    private final PtpCamera camera;
27
+    private final int objectHandle;
28
+    private final RetrieveImageListener listener;
29
+    private final int sampleSize;
30
+
31
+    public RetrieveImageAction(PtpCamera camera, RetrieveImageListener listener, int objectHandle, int sampleSize) {
32
+        this.camera = camera;
33
+        this.listener = listener;
34
+        this.objectHandle = objectHandle;
35
+        this.sampleSize = sampleSize;
36
+    }
37
+
38
+    @Override
39
+    public void exec(IO io) {
40
+        GetObjectCommand getObject = new GetObjectCommand(camera, objectHandle, sampleSize);
41
+        io.handleCommand(getObject);
42
+
43
+        if (getObject.getResponseCode() != Response.Ok || getObject.getBitmap() == null) {
44
+            listener.onImageRetrieved(0, null);
45
+            return;
46
+        }
47
+
48
+        listener.onImageRetrieved(objectHandle, getObject.getBitmap());
49
+    }
50
+
51
+    @Override
52
+    public void reset() {
53
+    }
54
+}

+ 70 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/RetrieveImageInfoAction.java

@@ -0,0 +1,70 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import android.graphics.Bitmap;
19
+
20
+import com.remoteyourcam.usb.ptp.Camera.RetrieveImageInfoListener;
21
+import com.remoteyourcam.usb.ptp.PtpAction;
22
+import com.remoteyourcam.usb.ptp.PtpCamera;
23
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
24
+import com.remoteyourcam.usb.ptp.PtpConstants;
25
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
26
+import com.remoteyourcam.usb.ptp.model.ObjectInfo;
27
+
28
+public class RetrieveImageInfoAction implements PtpAction {
29
+
30
+    private final PtpCamera camera;
31
+    private final int objectHandle;
32
+    private final RetrieveImageInfoListener listener;
33
+
34
+    public RetrieveImageInfoAction(PtpCamera camera, RetrieveImageInfoListener listener, int objectHandle) {
35
+        this.camera = camera;
36
+        this.listener = listener;
37
+        this.objectHandle = objectHandle;
38
+    }
39
+
40
+    @Override
41
+    public void exec(IO io) {
42
+        GetObjectInfoCommand getInfo = new GetObjectInfoCommand(camera, objectHandle);
43
+        io.handleCommand(getInfo);
44
+
45
+        if (getInfo.getResponseCode() != Response.Ok) {
46
+            return;
47
+        }
48
+
49
+        ObjectInfo objectInfo = getInfo.getObjectInfo();
50
+        if (objectInfo == null) {
51
+            return;
52
+        }
53
+
54
+        Bitmap thumbnail = null;
55
+        if (objectInfo.thumbFormat == PtpConstants.ObjectFormat.JFIF
56
+                || objectInfo.thumbFormat == PtpConstants.ObjectFormat.EXIF_JPEG) {
57
+            GetThumb getThumb = new GetThumb(camera, objectHandle);
58
+            io.handleCommand(getThumb);
59
+            if (getThumb.getResponseCode() == Response.Ok) {
60
+                thumbnail = getThumb.getBitmap();
61
+            }
62
+        }
63
+
64
+        listener.onImageInfoRetrieved(objectHandle, getInfo.getObjectInfo(), thumbnail);
65
+    }
66
+
67
+    @Override
68
+    public void reset() {
69
+    }
70
+}

+ 86 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/RetrievePictureAction.java

@@ -0,0 +1,86 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import android.graphics.Bitmap;
19
+
20
+import com.remoteyourcam.usb.ptp.PtpAction;
21
+import com.remoteyourcam.usb.ptp.PtpCamera;
22
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
23
+import com.remoteyourcam.usb.ptp.PtpConstants;
24
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
25
+import com.remoteyourcam.usb.ptp.model.ObjectInfo;
26
+
27
+public class RetrievePictureAction implements PtpAction {
28
+
29
+    private final PtpCamera camera;
30
+    private final int objectHandle;
31
+    private final int sampleSize;
32
+
33
+    public RetrievePictureAction(PtpCamera camera, int objectHandle, int sampleSize) {
34
+        this.camera = camera;
35
+        this.objectHandle = objectHandle;
36
+        this.sampleSize = sampleSize;
37
+    }
38
+
39
+    @Override
40
+    public void exec(IO io) {
41
+        GetObjectInfoCommand getInfo = new GetObjectInfoCommand(camera, objectHandle);
42
+        io.handleCommand(getInfo);
43
+
44
+        if (getInfo.getResponseCode() != Response.Ok) {
45
+            return;
46
+        }
47
+
48
+        ObjectInfo objectInfo = getInfo.getObjectInfo();
49
+        if (objectInfo == null) {
50
+            return;
51
+        }
52
+
53
+        Bitmap thumbnail = null;
54
+        if (objectInfo.thumbFormat == PtpConstants.ObjectFormat.JFIF
55
+                || objectInfo.thumbFormat == PtpConstants.ObjectFormat.EXIF_JPEG) {
56
+            GetThumb getThumb = new GetThumb(camera, objectHandle);
57
+            io.handleCommand(getThumb);
58
+            if (getThumb.getResponseCode() == Response.Ok) {
59
+                thumbnail = getThumb.getBitmap();
60
+            }
61
+        }
62
+
63
+        GetObjectCommand getObject = new GetObjectCommand(camera, objectHandle, sampleSize);
64
+        io.handleCommand(getObject);
65
+
66
+        if (getObject.getResponseCode() != Response.Ok) {
67
+            return;
68
+        }
69
+        if (getObject.getBitmap() == null) {
70
+            if (getObject.isOutOfMemoryError()) {
71
+                camera.onPictureReceived(objectHandle, getInfo.getObjectInfo().filename, thumbnail, null);
72
+            }
73
+            return;
74
+        }
75
+
76
+        if (thumbnail == null) {
77
+            // TODO resize real picture?
78
+        }
79
+
80
+        camera.onPictureReceived(objectHandle, getInfo.getObjectInfo().filename, thumbnail, getObject.getBitmap());
81
+    }
82
+
83
+    @Override
84
+    public void reset() {
85
+    }
86
+}

+ 76 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/SetDevicePropValueCommand.java

@@ -0,0 +1,76 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.PtpCamera;
21
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
22
+import com.remoteyourcam.usb.ptp.PtpConstants;
23
+import com.remoteyourcam.usb.ptp.PtpConstants.Datatype;
24
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
25
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
26
+import com.remoteyourcam.usb.ptp.PtpConstants.Type;
27
+
28
+public class SetDevicePropValueCommand extends Command {
29
+
30
+    private final int property;
31
+    private final int value;
32
+    private final int datatype;
33
+
34
+    public SetDevicePropValueCommand(PtpCamera camera, int property, int value, int datatype) {
35
+        super(camera);
36
+        this.property = property;
37
+        this.value = value;
38
+        this.datatype = datatype;
39
+        hasDataToSend = true;
40
+    }
41
+
42
+    @Override
43
+    public void exec(IO io) {
44
+        io.handleCommand(this);
45
+        if (responseCode == Response.DeviceBusy) {
46
+            camera.onDeviceBusy(this, true);
47
+            return;
48
+        } else if (responseCode == Response.Ok) {
49
+            camera.onPropertyChanged(property, value);
50
+        }
51
+    }
52
+
53
+    @Override
54
+    public void encodeCommand(ByteBuffer b) {
55
+        encodeCommand(b, Operation.SetDevicePropValue, property);
56
+    }
57
+
58
+    @Override
59
+    public void encodeData(ByteBuffer b) {
60
+        // header
61
+        b.putInt(12 + PtpConstants.getDatatypeSize(datatype));
62
+        b.putShort((short) Type.Data);
63
+        b.putShort((short) Operation.SetDevicePropValue);
64
+        b.putInt(camera.currentTransactionId());
65
+        // specific block
66
+        if (datatype == Datatype.int8 || datatype == Datatype.uint8) {
67
+            b.put((byte) value);
68
+        } else if (datatype == Datatype.int16 || datatype == Datatype.uint16) {
69
+            b.putShort((short) value);
70
+        } else if (datatype == Datatype.int32 || datatype == Datatype.uint32) {
71
+            b.putInt(value);
72
+        } else {
73
+            throw new UnsupportedOperationException();
74
+        }
75
+    }
76
+}

+ 70 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/SimpleCommand.java

@@ -0,0 +1,70 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.PtpCamera;
21
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
22
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
23
+
24
+public class SimpleCommand extends Command {
25
+
26
+    private final int operation;
27
+    private int numParams;
28
+    private int p0;
29
+    private int p1;
30
+
31
+    public SimpleCommand(PtpCamera camera, int operation) {
32
+        super(camera);
33
+        this.operation = operation;
34
+    }
35
+
36
+    public SimpleCommand(PtpCamera camera, int operation, int p0) {
37
+        super(camera);
38
+        this.operation = operation;
39
+        this.p0 = p0;
40
+        this.numParams = 1;
41
+    }
42
+
43
+    public SimpleCommand(PtpCamera camera, int operation, int p0, int p1) {
44
+        super(camera);
45
+        this.operation = operation;
46
+        this.p0 = p0;
47
+        this.p1 = p1;
48
+        this.numParams = 2;
49
+    }
50
+
51
+    @Override
52
+    public void exec(IO io) {
53
+        io.handleCommand(this);
54
+        if (responseCode == Response.DeviceBusy) {
55
+            camera.onDeviceBusy(this, true);
56
+            return;
57
+        }
58
+    }
59
+
60
+    @Override
61
+    public void encodeCommand(ByteBuffer b) {
62
+        if (numParams == 2) {
63
+            encodeCommand(b, operation, p0, p1);
64
+        } else if (numParams == 1) {
65
+            encodeCommand(b, operation, p0);
66
+        } else {
67
+            encodeCommand(b, operation);
68
+        }
69
+    }
70
+}

+ 29 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosCommand.java

@@ -0,0 +1,29 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.eos;
17
+
18
+import com.remoteyourcam.usb.ptp.EosCamera;
19
+import com.remoteyourcam.usb.ptp.commands.Command;
20
+
21
+public abstract class EosCommand extends Command {
22
+
23
+    protected EosCamera camera;
24
+
25
+    public EosCommand(EosCamera camera) {
26
+        super(camera);
27
+        this.camera = camera;
28
+    }
29
+}

+ 184 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosEventCheckCommand.java

@@ -0,0 +1,184 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.eos;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import android.util.Log;
21
+
22
+import com.remoteyourcam.usb.AppConfig;
23
+import com.remoteyourcam.usb.ptp.EosCamera;
24
+import com.remoteyourcam.usb.ptp.PacketUtil;
25
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
26
+import com.remoteyourcam.usb.ptp.PtpConstants;
27
+import com.remoteyourcam.usb.ptp.PtpConstants.Event;
28
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
29
+import com.remoteyourcam.usb.ptp.PtpConstants.Property;
30
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
31
+
32
+public class EosEventCheckCommand extends EosCommand {
33
+
34
+    private static final String TAG = EosEventCheckCommand.class.getSimpleName();
35
+
36
+    public EosEventCheckCommand(EosCamera camera) {
37
+        super(camera);
38
+    }
39
+
40
+    @Override
41
+    public void exec(IO io) {
42
+        io.handleCommand(this);
43
+        if (responseCode == Response.DeviceBusy) {
44
+            camera.onDeviceBusy(this, false);
45
+        }
46
+    }
47
+
48
+    @Override
49
+    public void encodeCommand(ByteBuffer b) {
50
+        encodeCommand(b, Operation.EosEventCheck);
51
+    }
52
+
53
+    @Override
54
+    protected void decodeData(ByteBuffer b, int length) {
55
+        while (b.position() < length) {
56
+            int eventLength = b.getInt();
57
+            int event = b.getInt();
58
+            if (AppConfig.LOG) {
59
+                Log.i(TAG, "event length " + eventLength);
60
+                Log.i(TAG, "event type " + PtpConstants.eventToString(event));
61
+            }
62
+            switch (event) {
63
+            case Event.EosObjectAdded: {
64
+                int objectHandle = b.getInt();
65
+                int storageId = b.getInt();
66
+                int objectFormat = b.getShort();
67
+                skip(b, eventLength - 18);
68
+                camera.onEventDirItemCreated(objectHandle, storageId, objectFormat, "TODO");
69
+                break;
70
+            }
71
+            case Event.EosDevicePropChanged: {
72
+                int property = b.getInt();
73
+                if (AppConfig.LOG) {
74
+                    Log.i(TAG, "property " + PtpConstants.propertyToString(property));
75
+                }
76
+                switch (property) {
77
+                case Property.EosApertureValue:
78
+                case Property.EosShutterSpeed:
79
+                case Property.EosIsoSpeed:
80
+                case Property.EosWhitebalance:
81
+                case Property.EosEvfOutputDevice:
82
+                case Property.EosShootingMode:
83
+                case Property.EosAvailableShots:
84
+                case Property.EosColorTemperature:
85
+                case Property.EosAfMode:
86
+                case Property.EosMeteringMode:
87
+                case Property.EosExposureCompensation:
88
+                case Property.EosPictureStyle:
89
+                case Property.EosEvfMode: {
90
+                    int value = b.getInt();
91
+                    if (AppConfig.LOG) {
92
+                        Log.i(TAG, "value " + value);
93
+                    }
94
+                    camera.onPropertyChanged(property, value);
95
+                    break;
96
+                }
97
+                default:
98
+                    if (AppConfig.LOG && eventLength <= 200) {
99
+                        PacketUtil.logHexdump(TAG, b.array(), b.position(), eventLength - 12);
100
+                    }
101
+                    skip(b, eventLength - 12);
102
+                    break;
103
+                }
104
+                break;
105
+            }
106
+            case Event.EosDevicePropDescChanged: {
107
+                int property = b.getInt();
108
+                if (AppConfig.LOG) {
109
+                    Log.i(TAG, "property " + PtpConstants.propertyToString(property));
110
+                }
111
+                switch (property) {
112
+                case Property.EosApertureValue:
113
+                case Property.EosShutterSpeed:
114
+                case Property.EosIsoSpeed:
115
+                case Property.EosMeteringMode:
116
+                case Property.EosPictureStyle:
117
+                case Property.EosExposureCompensation:
118
+                case Property.EosColorTemperature:
119
+                case Property.EosWhitebalance: {
120
+                    /* int dataType = */b.getInt();
121
+                    int num = b.getInt();
122
+                    if (AppConfig.LOG) {
123
+                        Log.i(TAG, "property desc with num " + num);
124
+                    }
125
+                    if (eventLength != 20 + 4 * num) {
126
+                        if (AppConfig.LOG) {
127
+                            Log.i(TAG, String.format("Event Desc length invalid should be %d but is %d", 20 + 4 * num,
128
+                                    eventLength));
129
+                            PacketUtil.logHexdump(TAG, b.array(), b.position() - 20, eventLength);
130
+                        }
131
+                    }
132
+                    int[] values = new int[num];
133
+                    for (int i = 0; i < num; ++i) {
134
+                        values[i] = b.getInt();
135
+                    }
136
+                    if (eventLength != 20 + 4 * num) {
137
+                        for (int i = 20 + 4 * num; i < eventLength; ++i) {
138
+                            b.get();
139
+                        }
140
+                    }
141
+                    camera.onPropertyDescChanged(property, values);
142
+                    break;
143
+                }
144
+                default:
145
+                    if (AppConfig.LOG && eventLength <= 50) {
146
+                        PacketUtil.logHexdump(TAG, b.array(), b.position(), eventLength - 12);
147
+                    }
148
+                    skip(b, eventLength - 12);
149
+                }
150
+                break;
151
+            }
152
+            case Event.EosBulbExposureTime: {
153
+                int seconds = b.getInt();
154
+                camera.onBulbExposureTime(seconds);
155
+                break;
156
+            }
157
+            case Event.EosCameraStatus: {
158
+                // 0 - capture stopped
159
+                // 1 - capture started
160
+                int status = b.getInt();
161
+                camera.onEventCameraCapture(status != 0);
162
+                break;
163
+            }
164
+            case Event.EosWillSoonShutdown: {
165
+                /* int seconds = */b.getInt();
166
+                //TODO
167
+                break;
168
+            }
169
+            default:
170
+                //                if (BuildConfig.LOG) {
171
+                //                    PacketUtil.logHexdump(b.array(), b.position(), eventLength - 8);
172
+                //                }
173
+                skip(b, eventLength - 8);
174
+                break;
175
+            }
176
+        }
177
+    }
178
+
179
+    private void skip(ByteBuffer b, int length) {
180
+        for (int i = 0; i < length; ++i) {
181
+            b.get();
182
+        }
183
+    }
184
+}

+ 153 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosGetLiveViewPictureCommand.java

@@ -0,0 +1,153 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.eos;
17
+
18
+import java.nio.ByteBuffer;
19
+import java.nio.ByteOrder;
20
+
21
+import android.graphics.BitmapFactory;
22
+import android.graphics.BitmapFactory.Options;
23
+import android.util.Log;
24
+
25
+import com.remoteyourcam.usb.AppConfig;
26
+import com.remoteyourcam.usb.ptp.EosCamera;
27
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
28
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
29
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
30
+import com.remoteyourcam.usb.ptp.model.LiveViewData;
31
+
32
+public class EosGetLiveViewPictureCommand extends EosCommand {
33
+
34
+    private static final String TAG = EosGetLiveViewPictureCommand.class.getSimpleName();
35
+    private static byte[] tmpStorage = new byte[0x4000];
36
+    private final Options options;
37
+    private LiveViewData data;
38
+
39
+    public EosGetLiveViewPictureCommand(EosCamera camera, LiveViewData data) {
40
+        super(camera);
41
+        if (data == null) {
42
+            this.data = new LiveViewData();
43
+            this.data.histogram = ByteBuffer.allocate(1024 * 4);
44
+            this.data.histogram.order(ByteOrder.LITTLE_ENDIAN);
45
+        } else {
46
+            this.data = data;
47
+        }
48
+        options = new BitmapFactory.Options();
49
+        options.inBitmap = this.data.bitmap;
50
+        options.inSampleSize = 1;
51
+        options.inTempStorage = tmpStorage;
52
+        this.data.bitmap = null;
53
+    }
54
+
55
+    @Override
56
+    public void exec(IO io) {
57
+        io.handleCommand(this);
58
+        if (responseCode == Response.DeviceBusy) {
59
+            camera.onDeviceBusy(this, true);
60
+            return;
61
+        }
62
+        if (this.data.bitmap != null && responseCode == Response.Ok) {
63
+            camera.onLiveViewReceived(data);
64
+        } else {
65
+            camera.onLiveViewReceived(null);
66
+        }
67
+    }
68
+
69
+    @Override
70
+    public void encodeCommand(ByteBuffer b) {
71
+        encodeCommand(b, Operation.EosGetLiveViewPicture, 0x100000);
72
+    }
73
+
74
+    @Override
75
+    protected void decodeData(ByteBuffer b, int length) {
76
+
77
+        data.hasHistogram = false;
78
+        data.hasAfFrame = false;
79
+
80
+        if (length < 1000) {
81
+            if (AppConfig.LOG) {
82
+                Log.w(TAG, String.format("liveview data size too small %d", length));
83
+            }
84
+            return;
85
+        }
86
+
87
+        try {
88
+
89
+            while (b.hasRemaining()) {
90
+                int subLength = b.getInt();
91
+                int type = b.getInt();
92
+
93
+                if (subLength < 8) {
94
+                    throw new RuntimeException("Invalid sub size " + subLength);
95
+                }
96
+
97
+                int unknownInt = 0;
98
+
99
+                switch (type) {
100
+                case 0x01:
101
+                    data.bitmap = BitmapFactory.decodeByteArray(b.array(), b.position(), subLength - 8, options);
102
+                    b.position(b.position() + subLength - 8);
103
+                    break;
104
+                case 0x04:
105
+                    data.zoomFactor = b.getInt();
106
+                    break;
107
+                case 0x05:
108
+                    // zoomfocusx, zoomfocusy
109
+                    data.zoomRectRight = b.getInt();
110
+                    data.zoomRectBottom = b.getInt();
111
+                    if (AppConfig.LOG) {
112
+                        Log.i(TAG, "header 5 " + data.zoomRectRight + " " + data.zoomRectBottom);
113
+                    }
114
+                    break;
115
+                case 0x06:
116
+                    // imagex, imagey (if zoomed should be non zero)
117
+                    data.zoomRectLeft = b.getInt();
118
+                    data.zoomRectTop = b.getInt();
119
+                    if (AppConfig.LOG) {
120
+                        Log.i(TAG, "header 6 " + data.zoomRectLeft + " " + data.zoomRectTop);
121
+                    }
122
+                    break;
123
+                case 0x07:
124
+                    unknownInt = b.getInt();
125
+                    if (AppConfig.LOG) {
126
+                        Log.i(TAG, "header 7 " + unknownInt + " " + subLength);
127
+                    }
128
+                    break;
129
+                case 0x03:
130
+                    data.hasHistogram = true;
131
+                    b.get(data.histogram.array(), 0, 1024 * 4);
132
+                    break;
133
+                case 0x08: // faces if faces focus
134
+                case 0x0e: // TODO original width, original height
135
+                default:
136
+                    b.position(b.position() + subLength - 8);
137
+                    if (AppConfig.LOG) {
138
+                        Log.i(TAG, "unknown header " + type + " size " + subLength);
139
+                    }
140
+                    break;
141
+                }
142
+
143
+                if (length - b.position() < 8) {
144
+                    break;
145
+                }
146
+            }
147
+
148
+        } catch (RuntimeException e) {
149
+            Log.e(TAG, "" + e.toString());
150
+            Log.e(TAG, "" + e.getLocalizedMessage());
151
+        }
152
+    }
153
+}

+ 65 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosOpenSessionAction.java

@@ -0,0 +1,65 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.eos;
17
+
18
+import com.remoteyourcam.usb.ptp.EosCamera;
19
+import com.remoteyourcam.usb.ptp.PtpAction;
20
+import com.remoteyourcam.usb.ptp.PtpConstants;
21
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
22
+import com.remoteyourcam.usb.ptp.commands.OpenSessionCommand;
23
+
24
+public class EosOpenSessionAction implements PtpAction {
25
+
26
+    private final EosCamera camera;
27
+
28
+    public EosOpenSessionAction(EosCamera camera) {
29
+        this.camera = camera;
30
+    }
31
+
32
+    @Override
33
+    public void exec(IO io) {
34
+        OpenSessionCommand openSession = new OpenSessionCommand(camera);
35
+        io.handleCommand(openSession);
36
+        if (openSession.getResponseCode() == PtpConstants.Response.Ok) {
37
+            EosSetPcModeCommand setPcMode = new EosSetPcModeCommand(camera);
38
+            io.handleCommand(setPcMode);
39
+            if (setPcMode.getResponseCode() == PtpConstants.Response.Ok) {
40
+                EosSetExtendedEventInfoCommand c = new EosSetExtendedEventInfoCommand(camera);
41
+                io.handleCommand(c);
42
+                if (c.getResponseCode() == PtpConstants.Response.Ok) {
43
+                    camera.onSessionOpened();
44
+                    return;
45
+                } else {
46
+                    camera.onPtpError(String.format(
47
+                            "Couldn't open session! Setting extended event info failed with error code \"%s\"",
48
+                            PtpConstants.responseToString(c.getResponseCode())));
49
+                }
50
+            } else {
51
+                camera.onPtpError(String.format(
52
+                        "Couldn't open session! Setting PcMode property failed with error code \"%s\"",
53
+                        PtpConstants.responseToString(setPcMode.getResponseCode())));
54
+            }
55
+        } else {
56
+            camera.onPtpError(String.format(
57
+                    "Couldn't open session! Open session command failed with error code \"%s\"",
58
+                    PtpConstants.responseToString(openSession.getResponseCode())));
59
+        }
60
+    }
61
+
62
+    @Override
63
+    public void reset() {
64
+    }
65
+}

+ 46 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosSetExtendedEventInfoCommand.java

@@ -0,0 +1,46 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.eos;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.EosCamera;
21
+import com.remoteyourcam.usb.ptp.PtpConstants;
22
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
23
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
24
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
25
+
26
+public class EosSetExtendedEventInfoCommand extends EosCommand {
27
+
28
+    public EosSetExtendedEventInfoCommand(EosCamera camera) {
29
+        super(camera);
30
+    }
31
+
32
+    @Override
33
+    public void exec(IO io) {
34
+        io.handleCommand(this);
35
+        if (responseCode != Response.Ok) {
36
+            camera.onPtpError(String.format(
37
+                    "Couldn't initialize session! Setting extended event info failed, error code %s",
38
+                    PtpConstants.responseToString(responseCode)));
39
+        }
40
+    }
41
+
42
+    @Override
43
+    public void encodeCommand(ByteBuffer b) {
44
+        encodeCommand(b, Operation.EosSetEventMode, 1);
45
+    }
46
+}

+ 84 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosSetLiveViewAction.java

@@ -0,0 +1,84 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.eos;
17
+
18
+import com.remoteyourcam.usb.ptp.EosCamera;
19
+import com.remoteyourcam.usb.ptp.EosConstants;
20
+import com.remoteyourcam.usb.ptp.PtpAction;
21
+import com.remoteyourcam.usb.ptp.EosConstants.EvfMode;
22
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
23
+import com.remoteyourcam.usb.ptp.PtpConstants.Property;
24
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
25
+
26
+public class EosSetLiveViewAction implements PtpAction {
27
+
28
+    private final EosCamera camera;
29
+    private final boolean enabled;
30
+
31
+    public EosSetLiveViewAction(EosCamera camera, boolean enabled) {
32
+        this.camera = camera;
33
+        this.enabled = enabled;
34
+    }
35
+
36
+    @Override
37
+    public void exec(IO io) {
38
+        int evfMode = camera.getPtpProperty(Property.EosEvfMode);
39
+
40
+        if (enabled && evfMode != EvfMode.ENABLE || !enabled && evfMode != EvfMode.DISABLE) {
41
+            EosSetPropertyCommand setEvfMode = new EosSetPropertyCommand(camera, Property.EosEvfMode,
42
+                    enabled ? EvfMode.ENABLE : EvfMode.DISABLE);
43
+            io.handleCommand(setEvfMode);
44
+
45
+            if (setEvfMode.getResponseCode() == Response.DeviceBusy) {
46
+                camera.onDeviceBusy(this, true);
47
+                return;
48
+            } else if (setEvfMode.getResponseCode() != Response.Ok) {
49
+                camera.onPtpWarning("Couldn't open live view");
50
+                return;
51
+            }
52
+        }
53
+
54
+        int outputDevice = camera.getPtpProperty(Property.EosEvfOutputDevice);
55
+
56
+        if (enabled) {
57
+            outputDevice |= EosConstants.EvfOutputDevice.PC;
58
+        } else {
59
+            outputDevice &= ~EosConstants.EvfOutputDevice.PC;
60
+        }
61
+
62
+        EosSetPropertyCommand setOutputDevice = new EosSetPropertyCommand(camera, Property.EosEvfOutputDevice,
63
+                outputDevice);
64
+        io.handleCommand(setOutputDevice);
65
+
66
+        if (setOutputDevice.getResponseCode() == Response.DeviceBusy) {
67
+            camera.onDeviceBusy(this, true);
68
+        } else if (setOutputDevice.getResponseCode() == Response.Ok) {
69
+            if (!enabled) {
70
+                camera.onLiveViewStopped();
71
+            } else {
72
+                camera.onLiveViewStarted();
73
+            }
74
+            return;
75
+        } else {
76
+            camera.onPtpWarning("Couldn't open live view");
77
+        }
78
+
79
+    }
80
+
81
+    @Override
82
+    public void reset() {
83
+    }
84
+}

+ 45 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosSetPcModeCommand.java

@@ -0,0 +1,45 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.eos;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.EosCamera;
21
+import com.remoteyourcam.usb.ptp.PtpConstants;
22
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
23
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
24
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
25
+
26
+public class EosSetPcModeCommand extends EosCommand {
27
+
28
+    public EosSetPcModeCommand(EosCamera camera) {
29
+        super(camera);
30
+    }
31
+
32
+    @Override
33
+    public void exec(IO io) {
34
+        io.handleCommand(this);
35
+        if (responseCode != Response.Ok) {
36
+            camera.onPtpError(String.format("Couldn't initialize session! setting PC Mode failed, error code %s",
37
+                    PtpConstants.responseToString(responseCode)));
38
+        }
39
+    }
40
+
41
+    @Override
42
+    public void encodeCommand(ByteBuffer b) {
43
+        encodeCommand(b, Operation.EosSetPCConnectMode, 1);
44
+    }
45
+}

+ 64 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosSetPropertyCommand.java

@@ -0,0 +1,64 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.eos;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.EosCamera;
21
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
22
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
23
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
24
+import com.remoteyourcam.usb.ptp.PtpConstants.Type;
25
+
26
+public class EosSetPropertyCommand extends EosCommand {
27
+
28
+    private final int property;
29
+    private final int value;
30
+
31
+    public EosSetPropertyCommand(EosCamera camera, int property, int value) {
32
+        super(camera);
33
+        hasDataToSend = true;
34
+        this.property = property;
35
+        this.value = value;
36
+    }
37
+
38
+    @Override
39
+    public void exec(IO io) {
40
+        io.handleCommand(this);
41
+        if (responseCode == Response.DeviceBusy) {
42
+            camera.onDeviceBusy(this, true);
43
+            return;
44
+        }
45
+    }
46
+
47
+    @Override
48
+    public void encodeCommand(ByteBuffer b) {
49
+        encodeCommand(b, Operation.EosSetDevicePropValue);
50
+    }
51
+
52
+    @Override
53
+    public void encodeData(ByteBuffer b) {
54
+        // header
55
+        b.putInt(24);
56
+        b.putShort((short) Type.Data);
57
+        b.putShort((short) Operation.EosSetDevicePropValue);
58
+        b.putInt(camera.currentTransactionId());
59
+        // specific block
60
+        b.putInt(0x0C);
61
+        b.putInt(property);
62
+        b.putInt(value);
63
+    }
64
+}

+ 43 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/eos/EosTakePictureCommand.java

@@ -0,0 +1,43 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.eos;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.EosCamera;
21
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
22
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
23
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
24
+
25
+public class EosTakePictureCommand extends EosCommand {
26
+
27
+    public EosTakePictureCommand(EosCamera camera) {
28
+        super(camera);
29
+    }
30
+
31
+    @Override
32
+    public void exec(IO io) {
33
+        io.handleCommand(this);
34
+        if (responseCode == Response.DeviceBusy) {
35
+            camera.onDeviceBusy(this, true);
36
+        }
37
+    }
38
+
39
+    @Override
40
+    public void encodeCommand(ByteBuffer b) {
41
+        encodeCommand(b, Operation.EosTakePicture);
42
+    }
43
+}

+ 47 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonAfDriveCommand.java

@@ -0,0 +1,47 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.nikon;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.NikonCamera;
21
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
22
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
23
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
24
+
25
+public class NikonAfDriveCommand extends NikonCommand {
26
+
27
+    public NikonAfDriveCommand(NikonCamera camera) {
28
+        super(camera);
29
+    }
30
+
31
+    @Override
32
+    public void exec(IO io) {
33
+        //        if (camera.isInActivationTypePhase()) {
34
+        //            return;
35
+        //        }
36
+        io.handleCommand(this);
37
+        if (getResponseCode() == Response.Ok) {
38
+            camera.onFocusStarted();
39
+            camera.enqueue(new NikonAfDriveDeviceReadyCommand(camera), 200);
40
+        }
41
+    }
42
+
43
+    @Override
44
+    public void encodeCommand(ByteBuffer b) {
45
+        encodeCommand(b, Operation.NikonAfDrive);
46
+    }
47
+}

+ 46 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonAfDriveDeviceReadyCommand.java

@@ -0,0 +1,46 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.nikon;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.NikonCamera;
21
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
22
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
23
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
24
+
25
+public class NikonAfDriveDeviceReadyCommand extends NikonCommand {
26
+
27
+    public NikonAfDriveDeviceReadyCommand(NikonCamera camera) {
28
+        super(camera);
29
+    }
30
+
31
+    @Override
32
+    public void exec(IO io) {
33
+        io.handleCommand(this);
34
+        if (getResponseCode() == Response.DeviceBusy) {
35
+            reset();
36
+            camera.enqueue(this, 200);
37
+        } else {
38
+            camera.onFocusEnded(getResponseCode() == Response.Ok);
39
+        }
40
+    }
41
+
42
+    @Override
43
+    public void encodeCommand(ByteBuffer b) {
44
+        encodeCommand(b, Operation.NikonDeviceReady);
45
+    }
46
+}

+ 54 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonCloseSessionAction.java

@@ -0,0 +1,54 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.nikon;
17
+
18
+import com.remoteyourcam.usb.ptp.NikonCamera;
19
+import com.remoteyourcam.usb.ptp.PtpAction;
20
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
21
+import com.remoteyourcam.usb.ptp.PtpConstants.Datatype;
22
+import com.remoteyourcam.usb.ptp.PtpConstants.Property;
23
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
24
+import com.remoteyourcam.usb.ptp.commands.CloseSessionCommand;
25
+import com.remoteyourcam.usb.ptp.commands.SetDevicePropValueCommand;
26
+
27
+public class NikonCloseSessionAction implements PtpAction {
28
+
29
+    private final NikonCamera camera;
30
+
31
+    public NikonCloseSessionAction(NikonCamera camera) {
32
+        this.camera = camera;
33
+    }
34
+
35
+    @Override
36
+    public void exec(IO io) {
37
+        SetDevicePropValueCommand setRecordingMedia = new SetDevicePropValueCommand(camera,
38
+                Property.NikonRecordingMedia, 0,
39
+                Datatype.uint8);
40
+        io.handleCommand(setRecordingMedia);
41
+
42
+        if (setRecordingMedia.getResponseCode() == Response.DeviceBusy) {
43
+            camera.onDeviceBusy(this, true);
44
+            return;
45
+        }
46
+
47
+        io.handleCommand(new CloseSessionCommand(camera));
48
+        camera.onSessionClosed();
49
+    }
50
+
51
+    @Override
52
+    public void reset() {
53
+    }
54
+}

+ 29 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonCommand.java

@@ -0,0 +1,29 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.nikon;
17
+
18
+import com.remoteyourcam.usb.ptp.NikonCamera;
19
+import com.remoteyourcam.usb.ptp.commands.Command;
20
+
21
+public abstract class NikonCommand extends Command {
22
+
23
+    protected NikonCamera camera;
24
+
25
+    public NikonCommand(NikonCamera camera) {
26
+        super(camera);
27
+        this.camera = camera;
28
+    }
29
+}

+ 81 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonEventCheckCommand.java

@@ -0,0 +1,81 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.nikon;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import android.util.Log;
21
+
22
+import com.remoteyourcam.usb.AppConfig;
23
+import com.remoteyourcam.usb.ptp.NikonCamera;
24
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
25
+import com.remoteyourcam.usb.ptp.PtpConstants;
26
+import com.remoteyourcam.usb.ptp.PtpConstants.Event;
27
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
28
+
29
+public class NikonEventCheckCommand extends NikonCommand {
30
+
31
+    private static final String TAG = NikonEventCheckCommand.class.getSimpleName();
32
+
33
+    public NikonEventCheckCommand(NikonCamera camera) {
34
+        super(camera);
35
+    }
36
+
37
+    @Override
38
+    public void exec(IO io) {
39
+        io.handleCommand(this);
40
+    }
41
+
42
+    @Override
43
+    public void encodeCommand(ByteBuffer b) {
44
+        encodeCommand(b, Operation.NikonGetEvent);
45
+    }
46
+
47
+    @Override
48
+    protected void decodeData(ByteBuffer b, int length) {
49
+        int count = b.getShort();
50
+
51
+        while (count > 0) {
52
+            --count;
53
+
54
+            int eventCode = b.getShort();
55
+            int eventParam = b.getInt();
56
+
57
+            if (AppConfig.LOG) {
58
+                Log.i(TAG,
59
+                        String.format("event %s value %s(%04x)", PtpConstants.eventToString(eventCode),
60
+                                PtpConstants.propertyToString(eventParam), eventParam));
61
+            }
62
+
63
+            switch (eventCode) {
64
+            case Event.ObjectAdded:
65
+                camera.onEventObjectAdded(eventParam);
66
+                break;
67
+            case Event.DevicePropChanged:
68
+                camera.onEventDevicePropChanged(eventParam);
69
+                break;
70
+            case Event.CaptureComplete:
71
+                camera.onEventCaptureComplete();
72
+                break;
73
+            case Event.NikonObjectAddedInSdram:
74
+                //libgphoto2 相关处理
75
+                if (eventParam == 0) { eventParam = 0xffff001; }
76
+                camera.onEventObjectAdded(eventParam);
77
+                break;
78
+            }
79
+        }
80
+    }
81
+}

+ 70 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonGetLiveViewImageAction.java

@@ -0,0 +1,70 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.nikon;
17
+
18
+import com.remoteyourcam.usb.ptp.NikonCamera;
19
+import com.remoteyourcam.usb.ptp.PtpAction;
20
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
21
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
22
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
23
+import com.remoteyourcam.usb.ptp.commands.SimpleCommand;
24
+import com.remoteyourcam.usb.ptp.model.LiveViewData;
25
+
26
+public class NikonGetLiveViewImageAction implements PtpAction {
27
+
28
+    private final NikonCamera camera;
29
+    private final LiveViewData reuse;
30
+
31
+    public NikonGetLiveViewImageAction(NikonCamera camera, LiveViewData reuse) {
32
+        this.camera = camera;
33
+        this.reuse = reuse;
34
+    }
35
+
36
+    @Override
37
+    public void exec(IO io) {
38
+        SimpleCommand simpleCmd = new SimpleCommand(camera, Operation.NikonStartLiveView);
39
+        io.handleCommand(simpleCmd);
40
+
41
+        if (simpleCmd.getResponseCode() != Response.Ok) {
42
+            return;
43
+        }
44
+
45
+        SimpleCommand deviceReady = new SimpleCommand(camera, Operation.NikonDeviceReady);
46
+        for (int i = 0; i < 10; ++i) {
47
+            try {
48
+                Thread.sleep(300);
49
+            } catch (InterruptedException e) {
50
+                // nop
51
+            }
52
+
53
+            deviceReady.reset();
54
+            io.handleCommand(deviceReady);
55
+            if (deviceReady.getResponseCode() == Response.DeviceBusy) {
56
+                // still waiting
57
+            } else if (deviceReady.getResponseCode() == Response.Ok) {
58
+                camera.onLiveViewRestarted();
59
+                io.handleCommand(new NikonGetLiveViewImageCommand(camera, reuse));
60
+                return;
61
+            } else {
62
+                return;
63
+            }
64
+        }
65
+    }
66
+
67
+    @Override
68
+    public void reset() {
69
+    }
70
+}

+ 158 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonGetLiveViewImageCommand.java

@@ -0,0 +1,158 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.nikon;
17
+
18
+import android.graphics.BitmapFactory;
19
+import android.graphics.BitmapFactory.Options;
20
+import android.util.Log;
21
+
22
+import com.remoteyourcam.usb.AppConfig;
23
+import com.remoteyourcam.usb.ptp.NikonCamera;
24
+import com.remoteyourcam.usb.ptp.PacketUtil;
25
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
26
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
27
+import com.remoteyourcam.usb.ptp.PtpConstants.Product;
28
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
29
+import com.remoteyourcam.usb.ptp.model.LiveViewData;
30
+
31
+import java.nio.ByteBuffer;
32
+import java.nio.ByteOrder;
33
+
34
+public class NikonGetLiveViewImageCommand extends NikonCommand {
35
+
36
+    private static boolean haveAddedDumpToAcra = false;
37
+
38
+    private static final String TAG = NikonGetLiveViewImageCommand.class.getSimpleName();
39
+    private static byte[] tmpStorage = new byte[0x4000];
40
+    private final Options options;
41
+    private LiveViewData data;
42
+
43
+    public NikonGetLiveViewImageCommand(NikonCamera camera, LiveViewData data) {
44
+        super(camera);
45
+        this.data = data;
46
+        if (data == null) {
47
+            this.data = new LiveViewData();
48
+            //this.data.histogram = ByteBuffer.allocate(1024 * 4);
49
+            //this.data.histogram.order(ByteOrder.LITTLE_ENDIAN);
50
+        } else {
51
+            this.data = data;
52
+        }
53
+        options = new BitmapFactory.Options();
54
+        options.inBitmap = this.data.bitmap;
55
+        options.inSampleSize = 1;
56
+        options.inTempStorage = tmpStorage;
57
+        this.data.bitmap = null;
58
+    }
59
+
60
+    @Override
61
+    public void exec(IO io) {
62
+        if (!camera.isLiveViewOpen()) {
63
+            return;
64
+        }
65
+        io.handleCommand(this);
66
+        if (responseCode == Response.DeviceBusy) {
67
+            camera.onDeviceBusy(this, true);
68
+            return;
69
+        }
70
+        data.hasHistogram = false;
71
+        if (this.data.bitmap != null && responseCode == Response.Ok) {
72
+            camera.onLiveViewReceived(data);
73
+        } else {
74
+            camera.onLiveViewReceived(null);
75
+        }
76
+    }
77
+
78
+    @Override
79
+    public void encodeCommand(ByteBuffer b) {
80
+        encodeCommand(b, Operation.NikonGetLiveViewImage);
81
+    }
82
+
83
+    @Override
84
+    protected void decodeData(ByteBuffer b, int length) {
85
+        if (length <= 128) {
86
+            return;
87
+        }
88
+
89
+        data.hasAfFrame = false;
90
+
91
+        int productId = camera.getProductId();
92
+        int start = b.position();
93
+        int pictureOffset;
94
+
95
+        switch (productId) {
96
+        case Product.NikonD5000:
97
+        case Product.NikonD3S:
98
+        case Product.NikonD90:
99
+            pictureOffset = 128;
100
+            break;
101
+        case Product.NikonD3X:
102
+        case Product.NikonD300S:
103
+        case Product.NikonD3:
104
+        case Product.NikonD300:
105
+        case Product.NikonD700:
106
+            pictureOffset = 64;
107
+            break;
108
+        case Product.NikonD7000:
109
+        case Product.NikonD5100:
110
+            pictureOffset = 384;
111
+            break;
112
+        default:
113
+            return;
114
+        }
115
+
116
+        b.order(ByteOrder.BIG_ENDIAN);
117
+
118
+        // read af frame
119
+        {
120
+            data.hasAfFrame = true;
121
+
122
+            int jpegImageWidth = b.getShort() & 0xFFFF;
123
+            int jpegImageHeight = b.getShort() & 0xFFFF;
124
+            int wholeWidth = b.getShort() & 0xFFFF;
125
+            int wholeHeight = b.getShort() & 0xFFFF;
126
+
127
+            float multX = jpegImageWidth / (float) wholeWidth;
128
+            float multY = jpegImageHeight / (float) wholeHeight;
129
+
130
+            b.position(start + 16);
131
+            data.nikonWholeWidth = wholeWidth;
132
+            data.nikonWholeHeight = wholeHeight;
133
+            data.nikonAfFrameWidth = (int) ((b.getShort() & 0xFFFF) * multX);
134
+            data.nikonAfFrameHeight = (int) ((b.getShort() & 0xFFFF) * multY);
135
+            data.nikonAfFrameCenterX = (int) ((b.getShort() & 0xFFFF) * multX);
136
+            data.nikonAfFrameCenterY = (int) ((b.getShort() & 0xFFFF) * multY);
137
+        }
138
+
139
+        b.order(ByteOrder.LITTLE_ENDIAN);
140
+
141
+        b.position(start + pictureOffset);
142
+
143
+        if (b.remaining() <= 128) {
144
+            data.bitmap = null;
145
+            return;
146
+        }
147
+
148
+        try {
149
+            data.bitmap = BitmapFactory.decodeByteArray(b.array(), b.position(), length - b.position(), options);
150
+        } catch (RuntimeException e) {
151
+            Log.e(TAG, "decoding failed " + e.toString());
152
+            Log.e(TAG, e.getLocalizedMessage());
153
+            if (AppConfig.LOG) {
154
+                PacketUtil.logHexdump(TAG, b.array(), start, 512);
155
+            }
156
+        }
157
+    }
158
+}

+ 51 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonGetVendorPropCodesCommand.java

@@ -0,0 +1,51 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.nikon;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.NikonCamera;
21
+import com.remoteyourcam.usb.ptp.PacketUtil;
22
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
23
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
24
+
25
+public class NikonGetVendorPropCodesCommand extends NikonCommand {
26
+
27
+    private int[] propertyCodes = new int[0];
28
+
29
+    public NikonGetVendorPropCodesCommand(NikonCamera camera) {
30
+        super(camera);
31
+    }
32
+
33
+    public int[] getPropertyCodes() {
34
+        return propertyCodes;
35
+    }
36
+
37
+    @Override
38
+    public void exec(IO io) {
39
+        throw new UnsupportedOperationException();
40
+    }
41
+
42
+    @Override
43
+    public void encodeCommand(ByteBuffer b) {
44
+        encodeCommand(b, Operation.NikonGetVendorPropCodes);
45
+    }
46
+
47
+    @Override
48
+    protected void decodeData(ByteBuffer b, int length) {
49
+        propertyCodes = PacketUtil.readU16Array(b);
50
+    }
51
+}

+ 69 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonOpenSessionAction.java

@@ -0,0 +1,69 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.nikon;
17
+
18
+import com.remoteyourcam.usb.ptp.NikonCamera;
19
+import com.remoteyourcam.usb.ptp.PtpAction;
20
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
21
+import com.remoteyourcam.usb.ptp.PtpConstants;
22
+import com.remoteyourcam.usb.ptp.PtpConstants.Datatype;
23
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
24
+import com.remoteyourcam.usb.ptp.PtpConstants.Property;
25
+import com.remoteyourcam.usb.ptp.commands.OpenSessionCommand;
26
+import com.remoteyourcam.usb.ptp.commands.SetDevicePropValueCommand;
27
+
28
+public class NikonOpenSessionAction implements PtpAction {
29
+
30
+    private final NikonCamera camera;
31
+
32
+    public NikonOpenSessionAction(NikonCamera camera) {
33
+        this.camera = camera;
34
+    }
35
+
36
+    @Override
37
+    public void exec(IO io) {
38
+        OpenSessionCommand openSession = new OpenSessionCommand(camera);
39
+        io.handleCommand(openSession);
40
+        if (openSession.getResponseCode() == PtpConstants.Response.Ok) {
41
+            if (camera.hasSupportForOperation(Operation.NikonGetVendorPropCodes)) {
42
+                NikonGetVendorPropCodesCommand getPropCodes = new NikonGetVendorPropCodesCommand(camera);
43
+                io.handleCommand(getPropCodes);
44
+                SetDevicePropValueCommand c = new SetDevicePropValueCommand(camera, Property.NikonRecordingMedia, 1,
45
+                        Datatype.uint8);
46
+                io.handleCommand(c);
47
+                if (getPropCodes.getResponseCode() == PtpConstants.Response.Ok
48
+                        && c.getResponseCode() == PtpConstants.Response.Ok) {
49
+                    camera.setVendorPropCodes(getPropCodes.getPropertyCodes());
50
+                    camera.onSessionOpened();
51
+                } else {
52
+                    camera.onPtpError(String.format(
53
+                            "Couldn't read device property codes! Open session command failed with error code \"%s\"",
54
+                            PtpConstants.responseToString(getPropCodes.getResponseCode())));
55
+                }
56
+            } else {
57
+                camera.onSessionOpened();
58
+            }
59
+        } else {
60
+            camera.onPtpError(String.format(
61
+                    "Couldn't open session! Open session command failed with error code \"%s\"",
62
+                    PtpConstants.responseToString(openSession.getResponseCode())));
63
+        }
64
+    }
65
+
66
+    @Override
67
+    public void reset() {
68
+    }
69
+}

+ 66 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonStartLiveViewAction.java

@@ -0,0 +1,66 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.nikon;
17
+
18
+import com.remoteyourcam.usb.ptp.NikonCamera;
19
+import com.remoteyourcam.usb.ptp.PtpAction;
20
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
21
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
22
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
23
+import com.remoteyourcam.usb.ptp.commands.SimpleCommand;
24
+
25
+public class NikonStartLiveViewAction implements PtpAction {
26
+
27
+    private final NikonCamera camera;
28
+
29
+    public NikonStartLiveViewAction(NikonCamera camera) {
30
+        this.camera = camera;
31
+    }
32
+
33
+    @Override
34
+    public void exec(IO io) {
35
+        SimpleCommand simpleCmd = new SimpleCommand(camera, Operation.NikonStartLiveView);
36
+        io.handleCommand(simpleCmd);
37
+
38
+        if (simpleCmd.getResponseCode() != Response.Ok) {
39
+            return;
40
+        }
41
+
42
+        SimpleCommand deviceReady = new SimpleCommand(camera, Operation.NikonDeviceReady);
43
+        for (int i = 0; i < 10; ++i) {
44
+            try {
45
+                Thread.sleep(300);
46
+            } catch (InterruptedException e) {
47
+                // nop
48
+            }
49
+
50
+            deviceReady.reset();
51
+            io.handleCommand(deviceReady);
52
+            if (deviceReady.getResponseCode() == Response.DeviceBusy) {
53
+                // still waiting
54
+            } else if (deviceReady.getResponseCode() == Response.Ok) {
55
+                camera.onLiveViewStarted();
56
+                return;
57
+            } else {
58
+                return;
59
+            }
60
+        }
61
+    }
62
+
63
+    @Override
64
+    public void reset() {
65
+    }
66
+}

+ 54 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/commands/nikon/NikonStopLiveViewAction.java

@@ -0,0 +1,54 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.commands.nikon;
17
+
18
+import com.remoteyourcam.usb.ptp.NikonCamera;
19
+import com.remoteyourcam.usb.ptp.PtpAction;
20
+import com.remoteyourcam.usb.ptp.PtpCamera.IO;
21
+import com.remoteyourcam.usb.ptp.PtpConstants.Operation;
22
+import com.remoteyourcam.usb.ptp.PtpConstants.Response;
23
+import com.remoteyourcam.usb.ptp.commands.SimpleCommand;
24
+
25
+public class NikonStopLiveViewAction implements PtpAction {
26
+
27
+    private final NikonCamera camera;
28
+    private final boolean notifyUser;
29
+
30
+    public NikonStopLiveViewAction(NikonCamera camera, boolean notifyUser) {
31
+        this.camera = camera;
32
+        this.notifyUser = notifyUser;
33
+    }
34
+
35
+    @Override
36
+    public void exec(IO io) {
37
+        SimpleCommand simpleCmd = new SimpleCommand(camera, Operation.NikonEndLiveView);
38
+        io.handleCommand(simpleCmd);
39
+
40
+        if (simpleCmd.getResponseCode() == Response.DeviceBusy) {
41
+            camera.onDeviceBusy(this, true);
42
+        } else {
43
+            if (notifyUser) {
44
+                camera.onLiveViewStopped();
45
+            } else {
46
+                camera.onLiveViewStoppedInternal();
47
+            }
48
+        }
49
+    }
50
+
51
+    @Override
52
+    public void reset() {
53
+    }
54
+}

+ 113 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/model/DeviceInfo.java

@@ -0,0 +1,113 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.model;
17
+
18
+import java.nio.ByteBuffer;
19
+import java.util.Arrays;
20
+
21
+import com.remoteyourcam.usb.ptp.PacketUtil;
22
+import com.remoteyourcam.usb.ptp.PtpConstants;
23
+
24
+/**
25
+ * Device info data set as defined by PTP standard.
26
+ */
27
+public class DeviceInfo {
28
+
29
+    public short standardVersion;
30
+    public int vendorExtensionId;
31
+    public short vendorExtensionVersion;
32
+    public String vendorExtensionDesc;
33
+    public short functionalMode;
34
+    public int[] operationsSupported;
35
+    public int[] eventsSupported;
36
+    public int[] devicePropertiesSupported;
37
+    public int[] captureFormats;
38
+    public int[] imageFormats;
39
+    public String manufacture;
40
+    public String model;
41
+    public String deviceVersion;
42
+    public String serialNumber;
43
+
44
+    public DeviceInfo(ByteBuffer b, int length) {
45
+        decode(b, length);
46
+    }
47
+
48
+    public DeviceInfo() {
49
+    }
50
+
51
+    public void decode(ByteBuffer b, int length) {
52
+        standardVersion = b.getShort();
53
+        vendorExtensionId = b.getInt();
54
+        vendorExtensionVersion = b.getShort();
55
+        vendorExtensionDesc = PacketUtil.readString(b);
56
+        functionalMode = b.getShort();
57
+        operationsSupported = PacketUtil.readU16Array(b);
58
+        eventsSupported = PacketUtil.readU16Array(b);
59
+        devicePropertiesSupported = PacketUtil.readU16Array(b);
60
+        captureFormats = PacketUtil.readU16Array(b);
61
+        imageFormats = PacketUtil.readU16Array(b);
62
+        manufacture = PacketUtil.readString(b);
63
+        model = PacketUtil.readString(b);
64
+        deviceVersion = PacketUtil.readString(b);
65
+        serialNumber = PacketUtil.readString(b);
66
+    }
67
+
68
+    public void encode(ByteBuffer b) {
69
+        b.putShort(standardVersion);
70
+        b.putInt(vendorExtensionId);
71
+        b.putInt(vendorExtensionVersion);
72
+        PacketUtil.writeString(b, "");
73
+        b.putShort(functionalMode);
74
+        PacketUtil.writeU16Array(b, new int[0]);
75
+        PacketUtil.writeU16Array(b, new int[0]);
76
+        PacketUtil.writeU16Array(b, new int[0]);
77
+        PacketUtil.writeU16Array(b, new int[0]);
78
+        PacketUtil.writeU16Array(b, new int[0]);
79
+        PacketUtil.writeString(b, "");
80
+        PacketUtil.writeString(b, "");
81
+        PacketUtil.writeString(b, "");
82
+    }
83
+
84
+    @Override
85
+    public String toString() {
86
+        // Changes here have to reflect changes in PtpConstants.main()
87
+        StringBuilder b = new StringBuilder();
88
+        b.append("DeviceInfo\n");
89
+        b.append("StandardVersion: ").append(standardVersion).append('\n');
90
+        b.append("VendorExtensionId: ").append(vendorExtensionId).append('\n');
91
+        b.append("VendorExtensionVersion: ").append(vendorExtensionVersion).append('\n');
92
+        b.append("VendorExtensionDesc: ").append(vendorExtensionDesc).append('\n');
93
+        b.append("FunctionalMode: ").append(functionalMode).append('\n');
94
+        appendU16Array(b, "OperationsSupported", PtpConstants.Operation.class, operationsSupported);
95
+        appendU16Array(b, "EventsSupported", PtpConstants.Event.class, eventsSupported);
96
+        appendU16Array(b, "DevicePropertiesSupported", PtpConstants.Property.class, devicePropertiesSupported);
97
+        appendU16Array(b, "CaptureFormats", PtpConstants.ObjectFormat.class, captureFormats);
98
+        appendU16Array(b, "ImageFormats", PtpConstants.ObjectFormat.class, imageFormats);
99
+        b.append("Manufacture: ").append(manufacture).append('\n');
100
+        b.append("Model: ").append(model).append('\n');
101
+        b.append("DeviceVersion: ").append(deviceVersion).append('\n');
102
+        b.append("SerialNumber: ").append(serialNumber).append('\n');
103
+        return b.toString();
104
+    }
105
+
106
+    private static void appendU16Array(StringBuilder b, String name, Class<?> cl, int[] a) {
107
+        Arrays.sort(a);
108
+        b.append(name).append(":\n");
109
+        for (int i = 0; i < a.length; ++i) {
110
+            b.append("    ").append(PtpConstants.constantToString(cl, a[i])).append('\n');
111
+        }
112
+    }
113
+}

+ 102 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/model/DevicePropDesc.java

@@ -0,0 +1,102 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.model;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.PacketUtil;
21
+import com.remoteyourcam.usb.ptp.PtpConstants.Datatype;
22
+
23
+public class DevicePropDesc {
24
+
25
+    public int code;
26
+    public int datatype;
27
+    public boolean readOnly;
28
+    public int factoryDefault;
29
+    public int currentValue;
30
+    public int[] description;
31
+
32
+    public DevicePropDesc() {
33
+    }
34
+
35
+    public DevicePropDesc(ByteBuffer b, int length) {
36
+        decode(b, length);
37
+    }
38
+
39
+    public void decode(ByteBuffer b, int length) {
40
+        code = b.getShort() & 0xFFFF;
41
+        datatype = b.getShort() & 0xFFFF;
42
+        readOnly = b.get() == 0;
43
+
44
+        if (datatype == Datatype.int8 || datatype == Datatype.uint8) {
45
+            factoryDefault = b.get() & 0xFF;
46
+            currentValue = b.get() & 0xFF;
47
+            int form = b.get();
48
+            if (form == 2) {
49
+                description = PacketUtil.readU8Enumeration(b);
50
+            } else if (form == 1) {
51
+                int mini = b.get();
52
+                int maxi = b.get();
53
+                int step = b.get();
54
+                description = new int[(maxi - mini) / step + 1];
55
+                for (int i = 0; i < description.length; ++i) {
56
+                    description[i] = mini + step * i;
57
+                }
58
+            }
59
+        } else if (datatype == Datatype.uint16) {
60
+            factoryDefault = b.getShort() & 0xFFFF;
61
+            currentValue = b.getShort() & 0xFFFF;
62
+            int form = b.get();
63
+            if (form == 2) {
64
+                description = PacketUtil.readU16Enumeration(b);
65
+            } else if (form == 1) {
66
+                int mini = b.getShort() & 0xFFFF;
67
+                int maxi = b.getShort() & 0xFFFF;
68
+                int step = b.getShort() & 0xFFFF;
69
+                description = new int[(maxi - mini) / step + 1];
70
+                for (int i = 0; i < description.length; ++i) {
71
+                    description[i] = mini + step * i;
72
+                }
73
+            }
74
+        } else if (datatype == Datatype.int16) {
75
+            factoryDefault = b.getShort();
76
+            currentValue = b.getShort();
77
+            int form = b.get();
78
+            if (form == 2) {
79
+                description = PacketUtil.readS16Enumeration(b);
80
+            } else if (form == 1) {
81
+                int mini = b.getShort();
82
+                int maxi = b.getShort();
83
+                int step = b.getShort();
84
+                description = new int[(maxi - mini) / step + 1];
85
+                for (int i = 0; i < description.length; ++i) {
86
+                    description[i] = mini + step * i;
87
+                }
88
+            }
89
+        } else if (datatype == Datatype.int32 || datatype == Datatype.uint32) {
90
+            factoryDefault = b.getInt();
91
+            currentValue = b.getInt();
92
+            int form = b.get();
93
+            if (form == 2) {
94
+                description = PacketUtil.readU32Enumeration(b);
95
+            }
96
+        }
97
+
98
+        if (description == null) {
99
+            description = new int[0];
100
+        }
101
+    }
102
+}

+ 44 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/model/LiveViewData.java

@@ -0,0 +1,44 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.model;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import android.graphics.Bitmap;
21
+
22
+public class LiveViewData {
23
+
24
+    public Bitmap bitmap;
25
+
26
+    public int zoomFactor;
27
+    public int zoomRectLeft;
28
+    public int zoomRectTop;
29
+    public int zoomRectRight;
30
+    public int zoomRectBottom;
31
+
32
+    public boolean hasHistogram;
33
+    public ByteBuffer histogram;
34
+
35
+    // dimensions are in bitmap size
36
+    public boolean hasAfFrame;
37
+    public int nikonAfFrameCenterX;
38
+    public int nikonAfFrameCenterY;
39
+    public int nikonAfFrameWidth;
40
+    public int nikonAfFrameHeight;
41
+
42
+    public int nikonWholeWidth;
43
+    public int nikonWholeHeight;
44
+}

+ 101 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/model/ObjectInfo.java

@@ -0,0 +1,101 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.model;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.PacketUtil;
21
+import com.remoteyourcam.usb.ptp.PtpConstants;
22
+
23
+/**
24
+ * Object info data set as defined by the PTP standard.
25
+ */
26
+public class ObjectInfo {
27
+
28
+    public int storageId;
29
+    public int objectFormat;
30
+    public int protectionStatus;
31
+    public int objectCompressedSize;
32
+    public int thumbFormat;
33
+    public int thumbCompressedSize;
34
+    public int thumbPixWidth;
35
+    public int thumbPixHeight;
36
+    public int imagePixWidth;
37
+    public int imagePixHeight;
38
+    public int imageBitDepth;
39
+    public int parentObject;
40
+    public int associationType;
41
+    public int associationDesc;
42
+    public int sequenceNumber;
43
+    public String filename;
44
+    public String captureDate;
45
+    public String modificationDate;
46
+    public int keywords;
47
+
48
+    public ObjectInfo() {
49
+    }
50
+
51
+    public ObjectInfo(ByteBuffer b, int length) {
52
+        decode(b, length);
53
+    }
54
+
55
+    public void decode(ByteBuffer b, int length) {
56
+        storageId = b.getInt();
57
+        objectFormat = b.getShort();
58
+        protectionStatus = b.getShort();
59
+        objectCompressedSize = b.getInt();
60
+        thumbFormat = b.getShort();
61
+        thumbCompressedSize = b.getInt();
62
+        thumbPixWidth = b.getInt();
63
+        thumbPixHeight = b.getInt();
64
+        imagePixWidth = b.getInt();
65
+        imagePixHeight = b.getInt();
66
+        imageBitDepth = b.getInt();
67
+        parentObject = b.getInt();
68
+        associationType = b.getShort();
69
+        associationDesc = b.getInt();
70
+        sequenceNumber = b.getInt();
71
+        filename = PacketUtil.readString(b);
72
+        captureDate = PacketUtil.readString(b);
73
+        modificationDate = PacketUtil.readString(b);
74
+        keywords = b.get(); // string, not used on camera?
75
+    }
76
+
77
+    @Override
78
+    public String toString() {
79
+        StringBuilder b = new StringBuilder();
80
+        b.append("ObjectInfo\n");
81
+        b.append("StorageId: ").append(String.format("0x%08x\n", storageId));
82
+        b.append("ObjectFormat: ").append(PtpConstants.objectFormatToString(objectFormat)).append('\n');
83
+        b.append("ProtectionStatus: ").append(protectionStatus).append('\n');
84
+        b.append("ObjectCompressedSize: ").append(objectCompressedSize).append('\n');
85
+        b.append("ThumbFormat: ").append(PtpConstants.objectFormatToString(thumbFormat)).append('\n');
86
+        b.append("ThumbCompressedSize: ").append(thumbCompressedSize).append('\n');
87
+        b.append("ThumbPixWdith: ").append(thumbPixWidth).append('\n');
88
+        b.append("ThumbPixHeight: ").append(thumbPixHeight).append('\n');
89
+        b.append("ImagePixWidth: ").append(imagePixWidth).append('\n');
90
+        b.append("ImagePixHeight: ").append(imagePixHeight).append('\n');
91
+        b.append("ImageBitDepth: ").append(imageBitDepth).append('\n');
92
+        b.append("ParentObject: ").append(String.format("0x%08x", parentObject)).append('\n');
93
+        b.append("AssociationType: ").append(associationType).append('\n');
94
+        b.append("AssociatonDesc: ").append(associationDesc).append('\n');
95
+        b.append("Filename: ").append(filename).append('\n');
96
+        b.append("CaptureDate: ").append(captureDate).append('\n');
97
+        b.append("ModificationDate: ").append(modificationDate).append('\n');
98
+        b.append("Keywords: ").append(keywords).append('\n');
99
+        return b.toString();
100
+    }
101
+}

+ 47 - 0
ryc/src/main/java/com/remoteyourcam/usb/ptp/model/StorageInfo.java

@@ -0,0 +1,47 @@
1
+/**
2
+ * Copyright 2013 Nils Assbeck, Guersel Ayaz and Michael Zoech
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ *     http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+package com.remoteyourcam.usb.ptp.model;
17
+
18
+import java.nio.ByteBuffer;
19
+
20
+import com.remoteyourcam.usb.ptp.PacketUtil;
21
+
22
+public class StorageInfo {
23
+
24
+    public int storageType;
25
+    public int filesystemType;
26
+    public int accessCapability;
27
+    public long maxCapacity;
28
+    public long freeSpaceInBytes;
29
+    public int freeSpaceInImages;
30
+    public String storageDescription;
31
+    public String volumeLabel;
32
+
33
+    public StorageInfo(ByteBuffer b, int length) {
34
+        decode(b, length);
35
+    }
36
+
37
+    private void decode(ByteBuffer b, int length) {
38
+        storageType = b.getShort() & 0xffff;
39
+        filesystemType = b.getShort() & 0xffff;
40
+        accessCapability = b.getShort() & 0xff;
41
+        maxCapacity = b.getLong();
42
+        freeSpaceInBytes = b.getLong();
43
+        freeSpaceInImages = b.getInt();
44
+        storageDescription = PacketUtil.readString(b);
45
+        volumeLabel = PacketUtil.readString(b);
46
+    }
47
+}

+ 3 - 0
ryc/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
1
+<resources>
2
+    <string name="app_name">ryc</string>
3
+</resources>

+ 1 - 1
settings.gradle

@@ -1 +1 @@
1
-include ':app', ':common', ':views'
1
+include ':app', ':common', ':views', ':ryc'