OSDN Git Service

とりあえずつながるところまで。。。
authorMRSa <mrsa@myad.jp>
Mon, 16 Sep 2019 13:49:30 +0000 (22:49 +0900)
committerMRSa <mrsa@myad.jp>
Mon, 16 Sep 2019 13:49:30 +0000 (22:49 +0900)
app/src/main/java/net/osdn/gokigen/pkremote/camera/utils/SimpleLogDumper.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/pkremote/camera/vendor/ptpip/wrapper/PtpIpInterfaceProvider.java
app/src/main/java/net/osdn/gokigen/pkremote/camera/vendor/ptpip/wrapper/command/IPtpIpMessages.java
app/src/main/java/net/osdn/gokigen/pkremote/camera/vendor/ptpip/wrapper/command/PtpIpCommandPublisher.java
app/src/main/java/net/osdn/gokigen/pkremote/camera/vendor/ptpip/wrapper/command/messages/PtpIpCommandGeneric.java
app/src/main/java/net/osdn/gokigen/pkremote/camera/vendor/ptpip/wrapper/connection/CanonCameraConnectSequenceForPlayback.java
app/src/main/java/net/osdn/gokigen/pkremote/camera/vendor/ptpip/wrapper/connection/CanonConnection.java
app/src/main/java/net/osdn/gokigen/pkremote/camera/vendor/ptpip/wrapper/status/PtpIpStatusChecker.java

diff --git a/app/src/main/java/net/osdn/gokigen/pkremote/camera/utils/SimpleLogDumper.java b/app/src/main/java/net/osdn/gokigen/pkremote/camera/utils/SimpleLogDumper.java
new file mode 100644 (file)
index 0000000..8aecc54
--- /dev/null
@@ -0,0 +1,38 @@
+package net.osdn.gokigen.pkremote.camera.utils;
+
+import android.util.Log;
+
+import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.PtpIpCommandPublisher;
+
+public class SimpleLogDumper
+{
+    private static final String TAG = SimpleLogDumper.class.getSimpleName();
+
+    /**
+     *   デバッグ用:ログにバイト列を出力する
+     *
+     */
+    public static void dump_bytes(String header, byte[] data)
+    {
+        int index = 0;
+        StringBuffer message;
+        message = new StringBuffer();
+        for (byte item : data)
+        {
+            index++;
+            message.append(String.format("%02x ", item));
+            if (index >= 8)
+            {
+                Log.v(TAG, header + " " + message);
+                index = 0;
+                message = new StringBuffer();
+            }
+        }
+        if (index != 0)
+        {
+            Log.v(TAG, header + " " + message);
+        }
+        System.gc();
+    }
+
+}
index 86f7505..e759ce2 100644 (file)
@@ -46,6 +46,7 @@ public class PtpIpInterfaceProvider implements IPtpIpInterfaceProvider, IDisplay
     private static final int STREAM_PORT = 15742;   // ??
     private static final int ASYNC_RESPONSE_PORT = 15741;  // ??
     private static final int CONTROL_PORT = 15740;
+    private static final int EVENT_PORT = 15740;
     private static final String CAMERA_IP = "192.168.0.1";
 
     private final Activity activity;
@@ -70,9 +71,9 @@ public class PtpIpInterfaceProvider implements IPtpIpInterfaceProvider, IDisplay
         commandPublisher = new PtpIpCommandPublisher(CAMERA_IP, CONTROL_PORT);
         liveViewControl = new PtpIpLiveViewControl(context, CAMERA_IP, STREAM_PORT);
         asyncReceiver = new PtpIpAsyncResponseReceiver(CAMERA_IP, ASYNC_RESPONSE_PORT);
-        canonConnection = new CanonConnection(context, provider, this);
+        statusChecker = new PtpIpStatusChecker(activity, commandPublisher, CAMERA_IP, EVENT_PORT);
+        canonConnection = new CanonConnection(context, provider, this, statusChecker);
         zoomControl = new PtpIpZoomControl();
-        statusChecker = new PtpIpStatusChecker(activity, commandPublisher);
         this.statusListener = statusListener;
         this.runmode = new PtpIpRunMode();
         this.hardwareStatus = new PtpIpHardwareStatus();
index 3407342..9a4b9e2 100644 (file)
@@ -6,6 +6,9 @@ public interface IPtpIpMessages
     int SEQ_REGISTRATION = 1;
     int SEQ_EVENT_INITIALIZE = 2;
     int SEQ_OPEN_SESSION = 3;
+    int SEQ_INIT_SESSION = 4;
+    int SEQ_CHANGE_REMOTE = 5;
+    int SEQ_SET_EVENT_MODE = 6;
 
 
     int SEQ_STATUS_REQUEST = 9;
index 9bef67d..0a65c71 100644 (file)
@@ -1,6 +1,5 @@
 package net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command;
 
-
 import android.util.Log;
 
 import androidx.annotation.NonNull;
@@ -13,9 +12,11 @@ import java.util.ArrayDeque;
 import java.util.Arrays;
 import java.util.Queue;
 
+import static net.osdn.gokigen.pkremote.camera.utils.SimpleLogDumper.dump_bytes;
+
 public class PtpIpCommandPublisher implements IPtpIpCommandPublisher, IPtpIpCommunication
 {
-    private final String TAG = toString();
+    private static final String TAG = PtpIpCommandPublisher.class.getSimpleName();
 
     private static final int SEQUENCE_START_NUMBER = 1;
     private static final int BUFFER_SIZE = 1024 * 1024 + 8;
@@ -241,10 +242,10 @@ public class PtpIpCommandPublisher implements IPtpIpCommandPublisher, IPtpIpComm
             if (useSequenceNumber)
             {
                 // Sequence Number を反映させる
-                sendData[15] = (byte) ((0x000000ff & sequenceNumber));
-                sendData[16] = (byte) (((0x0000ff00 & sequenceNumber) >>> 8) & 0x000000ff);
-                sendData[17] = (byte) (((0x00ff0000 & sequenceNumber) >>> 16) & 0x000000ff);
-                sendData[18] = (byte) (((0xff000000 & sequenceNumber) >>> 24) & 0x000000ff);
+                sendData[14] = (byte) ((0x000000ff & sequenceNumber));
+                sendData[15] = (byte) (((0x0000ff00 & sequenceNumber) >>> 8) & 0x000000ff);
+                sendData[16] = (byte) (((0x00ff0000 & sequenceNumber) >>> 16) & 0x000000ff);
+                sendData[17] = (byte) (((0xff000000 & sequenceNumber) >>> 24) & 0x000000ff);
                 if (isDumpReceiveLog)
                 {
                     Log.v(TAG, "SEQ No. : " + sequenceNumber);
@@ -260,8 +261,6 @@ public class PtpIpCommandPublisher implements IPtpIpCommandPublisher, IPtpIpComm
             // (データを)送信
             dos.write(sendData);
             dos.flush();
-            //dos.close(); //  ← これが必要?
-            //dos = null; //  ← これが必要?
         }
         catch (Exception e)
         {
@@ -384,30 +383,4 @@ public class PtpIpCommandPublisher implements IPtpIpCommandPublisher, IPtpIpComm
         }
     }
 
-    /**
-     *   デバッグ用:ログにバイト列を出力する
-     *
-     */
-    private void dump_bytes(String header, byte[] data)
-    {
-        int index = 0;
-        StringBuffer message;
-        message = new StringBuffer();
-        for (byte item : data)
-        {
-            index++;
-            message.append(String.format("%02x ", item));
-            if (index >= 8)
-            {
-                Log.v(TAG, header + " " + message);
-                index = 0;
-                message = new StringBuffer();
-            }
-        }
-        if (index != 0)
-        {
-            Log.v(TAG, header + " " + message);
-        }
-        System.gc();
-    }
 }
index 6fe4882..d55fa1a 100644 (file)
@@ -78,10 +78,10 @@ public class PtpIpCommandGeneric extends PtpIpCommandBase
         data2 = ((byte)((0x00ff0000 & value) >> 16));
         data3 = ((byte)((0xff000000 & value) >> 24));
 
-        data4 = ((byte) (0x000000ff & value));
-        data5 = ((byte)((0x0000ff00 & value) >> 8));
-        data6 = ((byte)((0x00ff0000 & value) >> 16));
-        data7 = ((byte)((0xff000000 & value) >> 24));
+        data4 = 0; // ((byte) (0x000000ff & value));
+        data5 = 0; // ((byte)((0x0000ff00 & value) >> 8));
+        data6 = 0; // ((byte)((0x00ff0000 & value) >> 16));
+        data7 = 0; // ((byte)((0xff000000 & value) >> 24));
 
         data8 = 0; // ((byte) (0x000000ff & value3));
         data9 = 0; // ((byte)((0x0000ff00 & value3) >> 8));
index fdc2606..28223de 100644 (file)
@@ -1,12 +1,10 @@
 package net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.connection;
 
 import android.app.Activity;
-import android.content.SharedPreferences;
 import android.graphics.Color;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
-import androidx.preference.PreferenceManager;
 
 import net.osdn.gokigen.pkremote.R;
 import net.osdn.gokigen.pkremote.camera.interfaces.control.ICameraConnection;
@@ -16,10 +14,9 @@ import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.IPtpIpComma
 import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.IPtpIpCommandPublisher;
 import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.IPtpIpMessages;
 import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.messages.PtpIpCommandGeneric;
-import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.messages.specific.CanonInitEventRequest;
 import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.messages.specific.CanonRegistrationMessage;
 import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.status.IPtpIpRunModeHolder;
-import net.osdn.gokigen.pkremote.preference.IPreferencePropertyAccessor;
+import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.status.PtpIpStatusChecker;
 
 
 public class CanonCameraConnectSequenceForPlayback implements Runnable, IPtpIpCommandCallback, IPtpIpMessages
@@ -31,9 +28,10 @@ public class CanonCameraConnectSequenceForPlayback implements Runnable, IPtpIpCo
     private final ICameraStatusReceiver cameraStatusReceiver;
     private final IPtpIpInterfaceProvider interfaceProvider;
     private final IPtpIpCommandPublisher commandIssuer;
+    private final PtpIpStatusChecker statusChecker;
     private boolean isBothLiveView = false;
 
-    CanonCameraConnectSequenceForPlayback(@NonNull Activity context, @NonNull ICameraStatusReceiver statusReceiver, @NonNull final ICameraConnection cameraConnection, @NonNull IPtpIpInterfaceProvider interfaceProvider)
+    CanonCameraConnectSequenceForPlayback(@NonNull Activity context, @NonNull ICameraStatusReceiver statusReceiver, @NonNull final ICameraConnection cameraConnection, @NonNull IPtpIpInterfaceProvider interfaceProvider, @NonNull PtpIpStatusChecker statusChecker)
     {
         Log.v(TAG, " CanonCameraConnectSequenceForPlayback");
         this.context = context;
@@ -41,6 +39,7 @@ public class CanonCameraConnectSequenceForPlayback implements Runnable, IPtpIpCo
         this.cameraStatusReceiver = statusReceiver;
         this.interfaceProvider = interfaceProvider;
         this.commandIssuer = interfaceProvider.getCommandPublisher();
+        this.statusChecker = statusChecker;
     }
 
     @Override
@@ -132,7 +131,7 @@ public class CanonCameraConnectSequenceForPlayback implements Runnable, IPtpIpCo
                 if (checkEventInitialize(rx_body))
                 {
                     interfaceProvider.getInformationReceiver().updateMessage(context.getString(R.string.canon_connect_connecting1), false, false, 0);
-                    commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_OPEN_SESSION, 0x1002));
+                    commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_OPEN_SESSION, 0x1002, 4, 0x41));
                 }
                 else
                 {
@@ -142,9 +141,22 @@ public class CanonCameraConnectSequenceForPlayback implements Runnable, IPtpIpCo
 
             case SEQ_OPEN_SESSION:
                 interfaceProvider.getInformationReceiver().updateMessage(context.getString(R.string.canon_connect_connecting2), false, false, 0);
-                //commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_OPEN_SESSION));
+                commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_INIT_SESSION, 0x902f));
                 break;
 
+            case SEQ_INIT_SESSION:
+                interfaceProvider.getInformationReceiver().updateMessage(context.getString(R.string.canon_connect_connecting3), false, false, 0);
+                commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_CHANGE_REMOTE, 0x9114, 4, 0x15));
+                break;
+
+            case SEQ_CHANGE_REMOTE:
+                interfaceProvider.getInformationReceiver().updateMessage(context.getString(R.string.canon_connect_connecting4), false, false, 0);
+                commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_SET_EVENT_MODE, 0x902f, 4, 0x02));
+                break;
+
+            case SEQ_SET_EVENT_MODE:
+                interfaceProvider.getInformationReceiver().updateMessage(context.getString(R.string.canon_connect_connecting5), false, false, 0);
+                break;
 /*
             case SEQ_START_2ND_READ:
                 interfaceProvider.getInformationReceiver().updateMessage(context.getString(R.string.connect_connecting2), false, false, 0);
@@ -261,19 +273,23 @@ public class CanonCameraConnectSequenceForPlayback implements Runnable, IPtpIpCo
     {
         interfaceProvider.getInformationReceiver().updateMessage(context.getString(R.string.connect_start_2), false, false, 0);
         cameraStatusReceiver.onStatusNotify(context.getString(R.string.connect_start_2));
-        int connectionNumber = 0;
         try
         {
-            connectionNumber = (receiveData[8] & 0xff);
-            connectionNumber = connectionNumber + ((receiveData[9]  & 0xff) << 8);
-            connectionNumber = connectionNumber + ((receiveData[10] & 0xff) << 16);
-            connectionNumber = connectionNumber + ((receiveData[11] & 0xff) << 24);
+            int eventConnectionNumber = (receiveData[8] & 0xff);
+            eventConnectionNumber = eventConnectionNumber + ((receiveData[9]  & 0xff) << 8);
+            eventConnectionNumber = eventConnectionNumber + ((receiveData[10] & 0xff) << 16);
+            eventConnectionNumber = eventConnectionNumber + ((receiveData[11] & 0xff) << 24);
+            statusChecker.setEventConnectionNumber(eventConnectionNumber);
+            interfaceProvider.getCameraStatusWatcher().startStatusWatch(null);
+
+            commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_OPEN_SESSION, 0x1002, 4, 0x41));
         }
         catch (Exception e)
         {
             e.printStackTrace();
         }
-        commandIssuer.enqueueCommand(new CanonInitEventRequest(this, connectionNumber));
+        //commandIssuer.enqueueCommand(new CanonInitEventRequest(this, connectionNumber));
+        //commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_OPEN_SESSION, 0x1002, 4, 0x41));
     }
 
     private boolean checkRegistrationMessage(byte[] receiveData)
index 775e74e..e380d98 100644 (file)
@@ -19,6 +19,7 @@ import net.osdn.gokigen.pkremote.R;
 import net.osdn.gokigen.pkremote.camera.interfaces.control.ICameraConnection;
 import net.osdn.gokigen.pkremote.camera.interfaces.status.ICameraStatusReceiver;
 import net.osdn.gokigen.pkremote.camera.vendor.ptpip.IPtpIpInterfaceProvider;
+import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.status.PtpIpStatusChecker;
 
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
@@ -31,14 +32,16 @@ public class CanonConnection implements ICameraConnection
     private final IPtpIpInterfaceProvider interfaceProvider;
     private final BroadcastReceiver connectionReceiver;
     private final Executor cameraExecutor = Executors.newFixedThreadPool(1);
+    private final PtpIpStatusChecker statusChecker;
     private CameraConnectionStatus connectionStatus = CameraConnectionStatus.UNKNOWN;
 
-    public CanonConnection(@NonNull final Activity context, @NonNull final ICameraStatusReceiver statusReceiver, @NonNull IPtpIpInterfaceProvider interfaceProvider)
+    public CanonConnection(@NonNull final Activity context, @NonNull final ICameraStatusReceiver statusReceiver, @NonNull IPtpIpInterfaceProvider interfaceProvider, @NonNull PtpIpStatusChecker statusChecker)
     {
         Log.v(TAG, "CanonConnection()");
         this.context = context;
         this.statusReceiver = statusReceiver;
         this.interfaceProvider = interfaceProvider;
+        this.statusChecker = statusChecker;
         connectionReceiver = new BroadcastReceiver()
         {
             @Override
@@ -221,7 +224,7 @@ public class CanonConnection implements ICameraConnection
         connectionStatus = CameraConnectionStatus.CONNECTING;
         try
         {
-            cameraExecutor.execute(new CanonCameraConnectSequenceForPlayback(context, statusReceiver, this, interfaceProvider));
+            cameraExecutor.execute(new CanonCameraConnectSequenceForPlayback(context, statusReceiver, this, interfaceProvider, statusChecker));
         }
         catch (Exception e)
         {
index 54ff217..ece456a 100644 (file)
@@ -1,26 +1,35 @@
 package net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.status;
 
 import android.app.Activity;
-import android.content.SharedPreferences;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
-import androidx.preference.PreferenceManager;
 
 import net.osdn.gokigen.pkremote.camera.interfaces.liveview.ICameraStatusUpdateNotify;
 import net.osdn.gokigen.pkremote.camera.interfaces.status.ICameraStatus;
 import net.osdn.gokigen.pkremote.camera.interfaces.status.ICameraStatusWatcher;
+import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.IPtpIpCommand;
 import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.IPtpIpCommandCallback;
 import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.IPtpIpCommandPublisher;
+import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.IPtpIpMessages;
+import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.messages.specific.CanonInitEventRequest;
 import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.messages.specific.StatusRequestMessage;
-import net.osdn.gokigen.pkremote.preference.IPreferencePropertyAccessor;
 
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.net.Socket;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
+import static net.osdn.gokigen.pkremote.camera.utils.SimpleLogDumper.dump_bytes;
+
 public class PtpIpStatusChecker implements IPtpIpCommandCallback, ICameraStatusWatcher, ICameraStatus
 {
     private final String TAG = toString();
+
+    private static final int BUFFER_SIZE = 1024 * 1024 + 8;
     private static final int STATUS_MESSAGE_HEADER_SIZE = 14;
     private int sleepMs;
     private final IPtpIpCommandPublisher issuer;
@@ -28,12 +37,22 @@ public class PtpIpStatusChecker implements IPtpIpCommandCallback, ICameraStatusW
     private PtpIpStatusHolder statusHolder;
     private boolean whileFetching = false;
     private boolean logcat = false;
+    private final String ipAddress;
+    private final int portNumber;
 
+    private Socket socket = null;
+    private DataOutputStream dos = null;
+    private BufferedReader bufferedReader = null;
+    private int eventConnectionNumber = 0;
 
-    public PtpIpStatusChecker(@NonNull Activity activity, @NonNull IPtpIpCommandPublisher issuer)
+    public PtpIpStatusChecker(@NonNull Activity activity, @NonNull IPtpIpCommandPublisher issuer, @NonNull String ip, int portNumber)
     {
         this.issuer = issuer;
         this.statusHolder = new PtpIpStatusHolder();
+        this.ipAddress = ip;
+        this.portNumber = portNumber;
+
+/*
         try
         {
             SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
@@ -45,6 +64,7 @@ public class PtpIpStatusChecker implements IPtpIpCommandCallback, ICameraStatusW
             e.printStackTrace();
             this.sleepMs = 400;
         }
+*/
         Log.v(TAG, "POLLING WAIT : " + sleepMs);
     }
 
@@ -66,6 +86,12 @@ public class PtpIpStatusChecker implements IPtpIpCommandCallback, ICameraStatusW
         try
         {
             logcat("receivedMessage : " + id + ", length: " + data.length);
+            if (id == IPtpIpMessages.SEQ_EVENT_INITIALIZE)
+            {
+                // 終わる
+                Log.v(TAG, " ----- PTP-IP Connection is ESTABLISHED. -----");
+                return;
+            }
             if (data.length < STATUS_MESSAGE_HEADER_SIZE)
             {
                 Log.v(TAG, "received status length is short. (" + data.length + " bytes.)");
@@ -156,6 +182,16 @@ public class PtpIpStatusChecker implements IPtpIpCommandCallback, ICameraStatusW
             final IPtpIpCommandCallback callback = this;
             this.notifier = notifier;
             whileFetching = true;
+
+            // セッションをオープンする
+            boolean isConnect = connect();
+            if (!isConnect)
+            {
+                Log.v(TAG, "  CONNECT FAIL...(EVENT) : " + ipAddress + "  " + portNumber);
+            }
+            issueCommand(new CanonInitEventRequest(this, eventConnectionNumber));
+
+/*
             Thread thread = new Thread(new Runnable()
             {
                 @Override
@@ -178,6 +214,10 @@ public class PtpIpStatusChecker implements IPtpIpCommandCallback, ICameraStatusW
                 }
             });
             thread.start();
+
+            // 切断する
+            disconnect();
+*/
         }
         catch (Exception e)
         {
@@ -200,4 +240,215 @@ public class PtpIpStatusChecker implements IPtpIpCommandCallback, ICameraStatusW
             Log.v(TAG, message);
         }
     }
+
+    private boolean connect()
+    {
+        try
+        {
+            socket = new Socket(ipAddress, portNumber);
+            return (true);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            socket = null;
+        }
+        return (false);
+    }
+
+    private void disconnect()
+    {
+        // ストリームを全部閉じる
+        try
+        {
+            if (dos != null)
+            {
+                dos.close();
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        dos = null;
+
+        try
+        {
+            if (bufferedReader != null)
+            {
+                bufferedReader.close();
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        bufferedReader = null;
+
+        try
+        {
+            if (socket != null)
+            {
+                socket.close();
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        socket = null;
+        System.gc();
+    }
+
+
+    public void setEventConnectionNumber(int connectionNumber)
+    {
+        eventConnectionNumber = connectionNumber;
+    }
+
+    private void issueCommand(@NonNull IPtpIpCommand command)
+    {
+        try
+        {
+            //Log.v(TAG, "issueCommand : " + command.getId());
+            byte[] commandBody = command.commandBody();
+            if (commandBody != null)
+            {
+                // コマンドボディが入っていた場合には、コマンド送信(入っていない場合は受信待ち)
+                send_to_camera(command.dumpLog(), commandBody);
+            }
+            receive_from_camera(command.dumpLog(), command.getId(), command.responseCallback(), command.receiveAgainShortLengthMessage(), command.receiveDelayMs());
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     *    カメラにコマンドを送信する(メイン部分)
+     *
+     */
+    private void send_to_camera(boolean isDumpReceiveLog, byte[] byte_array)
+    {
+        try
+        {
+            dos = new DataOutputStream(socket.getOutputStream());  // ここにいたらいけない?
+
+            // メッセージボディを加工: 最初に4バイトのレングス長をつける
+            byte[] sendData = new byte[byte_array.length + 4];
+
+            sendData[0] = (byte) (byte_array.length + 4);
+            sendData[1] = 0x00;
+            sendData[2] = 0x00;
+            sendData[3] = 0x00;
+            System.arraycopy(byte_array,0,sendData,4, byte_array.length);
+
+            if (isDumpReceiveLog)
+            {
+                // ログに送信メッセージを出力する
+                dump_bytes("SEND[" + sendData.length + "] ", sendData);
+            }
+
+            // (データを)送信
+            dos.write(sendData);
+            dos.flush();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+
+    /**
+     *    カメラからにコマンドの結果を受信する(メイン部分)
+     *
+     */
+    private void receive_from_camera(boolean isDumpReceiveLog, int id, IPtpIpCommandCallback callback, boolean receiveAgain, int delayMs) {
+        try {
+            sleep(delayMs);
+            Log.v(TAG, "  ----- receive_from_camera() ----- : " + isDumpReceiveLog + "  " + receiveAgain);
+            boolean isFirstTime = true;
+            int totalReadBytes;
+            int receive_message_buffer_size = BUFFER_SIZE;
+            byte[] byte_array = new byte[receive_message_buffer_size];
+            InputStream is = socket.getInputStream();
+            if (is != null) {
+                int read_bytes = is.read(byte_array, 0, receive_message_buffer_size);
+                byte[] receive_body;
+                if (read_bytes > 4) {
+                    if (receiveAgain) {
+                        int length = ((((int) byte_array[3]) & 0xff) << 24) + ((((int) byte_array[2]) & 0xff) << 16) + ((((int) byte_array[1]) & 0xff) << 8) + (((int) byte_array[0]) & 0xff);
+                        if (length > receive_message_buffer_size) {
+                            Log.v(TAG, "+++++ TOTAL RECEIVE MESSAGE SIZE IS " + length + " +++++");
+                        }
+                        totalReadBytes = read_bytes;
+                        while ((length > totalReadBytes) || ((length == read_bytes) && ((int) byte_array[4] == 0x02))) {
+                            // データについて、もう一回受信が必要な場合...
+                            if (isDumpReceiveLog) {
+                                Log.v(TAG, "--- RECEIVE AGAIN --- [" + length + "(" + read_bytes + ") " + byte_array[4] + "] ");
+                            }
+                            sleep(delayMs);
+                            int read_bytes2 = is.read(byte_array, read_bytes, receive_message_buffer_size - read_bytes);
+                            if (read_bytes2 > 0) {
+                                read_bytes = read_bytes + read_bytes2;
+                                totalReadBytes = totalReadBytes + read_bytes2;
+                            } else {
+                                // よみだし終了。
+                                Log.v(TAG, "FINISHED RECEIVE... ");
+                                break;
+                            }
+                            if (callback != null) {
+                                if (callback.isReceiveMulti()) {
+                                    int offset = 0;
+                                    if (isFirstTime) {
+                                        // 先頭のヘッダ部分をカットして送る
+                                        offset = 12;
+                                        isFirstTime = false;
+                                        //Log.v(TAG, " FIRST TIME : " + read_bytes + " " + offset);
+                                    }
+                                    callback.onReceiveProgress(read_bytes - offset, length, Arrays.copyOfRange(byte_array, offset, read_bytes));
+                                    read_bytes = 0;
+                                } else {
+                                    callback.onReceiveProgress(read_bytes, length, null);
+                                }
+                            }
+                        }
+                    }
+                    receive_body = Arrays.copyOfRange(byte_array, 0, read_bytes);
+                } else {
+                    receive_body = new byte[1];
+                }
+                if (isDumpReceiveLog) {
+                    // ログに受信メッセージを出力する
+                    Log.v(TAG, " receive_from_camera() : " + read_bytes + " bytes. [" + receive_message_buffer_size + "]");
+                    dump_bytes("RECV[" + receive_body.length + "] ", receive_body);
+                }
+                if (callback != null) {
+                    if (callback.isReceiveMulti()) {
+                        callback.receivedMessage(id, null);
+                    } else {
+                        callback.receivedMessage(id, receive_body);
+                        //callback.receivedMessage(id, Arrays.copyOfRange(receive_body, 0, receive_body.length));
+                    }
+                }
+            }
+        } catch (Throwable e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void sleep(int delayMs)
+    {
+        try
+        {
+            Thread.sleep(delayMs);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
 }