// single
if (selectedBodyLengthPosition == 0)
{
- commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, isDumpLog, 999, id));
+ commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, 999, isDumpLog, 0, id));
}
else if (selectedBodyLengthPosition == 5)
{
- commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, isDumpLog, 999, id, 16, value1, value2, value3, value4));
+ commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, 999, isDumpLog, 0, id, 16, value1, value2, value3, value4));
}
else if (selectedBodyLengthPosition == 4)
{
- commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, isDumpLog, 999, id, 12, value1, value2, value3));
+ commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, 999, isDumpLog, 0, id, 12, value1, value2, value3));
}
else if (selectedBodyLengthPosition == 3)
{
- commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, isDumpLog, 999, id, 8, value1, value2));
+ commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, 999, isDumpLog, 0, id, 8, value1, value2));
}
else if (selectedBodyLengthPosition == 2)
{
- commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, isDumpLog, 999, id, 4, value1));
+ commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, 999, isDumpLog, 0, id, 4, value1));
}
else
{
- commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, isDumpLog, 999, id, 2, value1));
+ commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, 999, isDumpLog, 0, id, 2, value1));
}
}
else
// multi
if (selectedBodyLengthPosition == 0)
{
- commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, isDumpLog, 999, id));
+ commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, 999, isDumpLog, 0, id));
}
else if (selectedBodyLengthPosition == 5)
{
- commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, isDumpLog, 999, id, 16, value1, value2, value3, value4));
+ commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, 999, isDumpLog, 0, id, 16, value1, value2, value3, value4));
}
else if (selectedBodyLengthPosition == 4)
{
- commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, isDumpLog, 999, id, 12, value1, value2, value3));
+ commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, 999, isDumpLog, 0, id, 12, value1, value2, value3));
}
else if (selectedBodyLengthPosition == 3)
{
- commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, isDumpLog, 999, id, 8, value1, value2));
+ commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, 999, isDumpLog, 0, id, 8, value1, value2));
}
else if (selectedBodyLengthPosition == 2)
{
- commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, isDumpLog, 999, id, 4, value1));
+ commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, 999, isDumpLog, 0, id, 4, value1));
}
else
{
- commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, isDumpLog, 999, id, 2, value1));
+ commandPublisher.enqueueCommand(new PtpIpCommandGeneric(responseReceiver, 999, isDumpLog, 0, id, 2, value1));
}
}
}
// コマンド送信結果(応答)の通知先
IPtpIpCommandCallback responseCallback();
+ // 特定シーケンスを特定するID
+ int getHoldId();
+
+ // 特定シーケンスに入るか?
+ boolean isHold();
+
+ // 特定シーケンスから出るか?
+ boolean isRelease();
+
// デバッグ用: ログ(logcat)に通信結果を残すかどうか
boolean dumpLog();
}
private final int portNumber;
private boolean isStart = false;
+ private boolean isHold = false;
+ private int holdId = 0;
private Socket socket = null;
private DataOutputStream dos = null;
private BufferedReader bufferedReader = null;
private int sequenceNumber = SEQUENCE_START_NUMBER;
private Queue<IPtpIpCommand> commandQueue;
-
+ private Queue<IPtpIpCommand> holdCommandQueue;
public PtpIpCommandPublisher(@NonNull String ip, int portNumber)
{
this.ipAddress = ip;
this.portNumber = portNumber;
this.commandQueue = new ArrayDeque<>();
+ this.holdCommandQueue = new ArrayDeque<>();
commandQueue.clear();
+ holdCommandQueue.clear();
}
@Override
{
try
{
+ if (isHold) {
+ if (holdId == command.getHoldId()) {
+ if (command.isRelease()) {
+ // コマンドをキューに積んだ後、リリースする
+ boolean ret = commandQueue.offer(command);
+ isHold = false;
+
+ // 溜まっているキューを積みなおす
+ while (holdCommandQueue.size() != 0) {
+ IPtpIpCommand queuedCommand = holdCommandQueue.poll();
+ commandQueue.offer(queuedCommand);
+ if ((queuedCommand != null)&&(queuedCommand.isHold()))
+ {
+ // 特定シーケンスに入った場合は、そこで積みなおすのをやめる
+ isHold = true;
+ holdId = queuedCommand.getHoldId();
+ break;
+ }
+ }
+ return (ret);
+ }
+ return (commandQueue.offer(command));
+ } else {
+ // 特定シーケンスではなかったので HOLD
+ return (holdCommandQueue.offer(command));
+ }
+ }
+ if (command.isHold())
+ {
+ isHold = true;
+ holdId = command.getHoldId();
+ }
+
//Log.v(TAG, "Enqueue : " + command.getId());
return (commandQueue.offer(command));
}
{
int lenlen = 0;
int len = ((((int) byte_array[3]) & 0xff) << 24) + ((((int) byte_array[2]) & 0xff) << 16) + ((((int) byte_array[1]) & 0xff) << 8) + (((int) byte_array[0]) & 0xff);
- if ((read_bytes > 20)&&((int) byte_array[5] == 9))
+ message_length = len;
+ if ((read_bytes > 20)&&((int) byte_array[4] == 0x09))
{
lenlen = ((((int) byte_array[15]) & 0xff) << 24) + ((((int) byte_array[14]) & 0xff) << 16) + ((((int) byte_array[13]) & 0xff) << 8) + (((int) byte_array[12]) & 0xff);
+ message_length = lenlen;
}
Log.v(TAG, " RECEIVED MESSAGE LENGTH (" + len + ") [" + lenlen + "]. : " + read_bytes);
}
}
@Override
+ public int getHoldId()
+ {
+ return (0);
+ }
+
+ @Override
+ public boolean isHold()
+ {
+ return (false);
+ }
+
+ @Override
+ public boolean isRelease()
+ {
+ return (false);
+ }
+
+ @Override
public boolean dumpLog()
{
return (true);
private final boolean isDumpLog;
private final int bodySize;
private final int id;
+ private final int holdId;
private final byte opCode0;
private final byte opCode1;
private final byte dataE;
private final byte dataF;
- public PtpIpCommandGeneric(@NonNull IPtpIpCommandCallback callback, boolean isDumpLog, int id, int opcode)
+ public PtpIpCommandGeneric(@NonNull IPtpIpCommandCallback callback, int id, boolean isDumpLog, int holdId, int opcode)
{
this.callback = callback;
this.bodySize = 0;
this.isDumpLog = isDumpLog;
this.id = id;
+ this.holdId = holdId;
opCode0 = ((byte) (0x000000ff & opcode));
opCode1 = ((byte)((0x0000ff00 & opcode) >> 8));
dataF = 0; // ((byte)((0xff000000 & value4) >> 24));
}
- public PtpIpCommandGeneric(@NonNull IPtpIpCommandCallback callback, boolean isDumpLog, int id, int opcode, int bodySize, int value)
+ public PtpIpCommandGeneric(@NonNull IPtpIpCommandCallback callback, int id, boolean isDumpLog, int holdId, int opcode, int bodySize, int value)
{
this.callback = callback;
this.bodySize = bodySize;
this.isDumpLog = isDumpLog;
this.id = id;
+ this.holdId = holdId;
opCode0 = ((byte) (0x000000ff & opcode));
opCode1 = ((byte)((0x0000ff00 & opcode) >> 8));
dataF = 0; // ((byte)((0xff000000 & value4) >> 24));
}
- public PtpIpCommandGeneric(@NonNull IPtpIpCommandCallback callback, boolean isDumpLog, int id, int opcode, int bodySize, int value, int value2)
+ public PtpIpCommandGeneric(@NonNull IPtpIpCommandCallback callback, int id, boolean isDumpLog, int holdId, int opcode, int bodySize, int value, int value2)
{
this.callback = callback;
this.bodySize = bodySize;
this.isDumpLog = isDumpLog;
this.id = id;
+ this.holdId = holdId;
opCode0 = ((byte) (0x000000ff & opcode));
opCode1 = ((byte)((0x0000ff00 & opcode) >> 8));
dataF = 0; // ((byte)((0xff000000 & value4) >> 24));
}
- public PtpIpCommandGeneric(@NonNull IPtpIpCommandCallback callback, boolean isDumpLog, int id, int opcode, int bodySize, int value, int value2, int value3)
+ public PtpIpCommandGeneric(@NonNull IPtpIpCommandCallback callback, int id, boolean isDumpLog, int holdId, int opcode, int bodySize, int value, int value2, int value3)
{
this.callback = callback;
this.bodySize = bodySize;
this.isDumpLog = isDumpLog;
this.id = id;
+ this.holdId = holdId;
opCode0 = ((byte) (0x000000ff & opcode));
opCode1 = ((byte)((0x0000ff00 & opcode) >> 8));
}
- public PtpIpCommandGeneric(@NonNull IPtpIpCommandCallback callback, boolean isDumpLog, int id, int opcode, int bodySize, int value, int value2, int value3, int value4)
+ public PtpIpCommandGeneric(@NonNull IPtpIpCommandCallback callback, int id, boolean isDumpLog, int holdId, int opcode, int bodySize, int value, int value2, int value3, int value4)
{
this.callback = callback;
this.bodySize = bodySize;
this.isDumpLog = isDumpLog;
this.id = id;
+ this.holdId = holdId;
opCode0 = ((byte) (0x000000ff & opcode));
opCode1 = ((byte)((0x0000ff00 & opcode) >> 8));
}
@Override
+ public int getHoldId()
+ {
+ return (holdId);
+ }
+
+ @Override
public boolean dumpLog()
{
return (isDumpLog);
private final IPtpIpCommandCallback callback;
private final boolean isDumpLog;
private final int id;
+ private final int holdId;
- public CanonRequestInnerDevelopEnd(@NonNull IPtpIpCommandCallback callback, boolean isDumpLog, int id)
+ public CanonRequestInnerDevelopEnd(@NonNull IPtpIpCommandCallback callback, int id, boolean isDumpLog, int holdId)
{
this.callback = callback;
this.isDumpLog = isDumpLog;
this.id = id;
+ this.holdId = holdId;
}
@Override
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
});
}
+ @Override
+ public int getHoldId()
+ {
+ return (holdId);
+ }
+
+ @Override
+ public boolean isHold()
+ {
+ return (false);
+ }
+
+ @Override
+ public boolean isRelease()
+ {
+ return (true);
+ }
}
private final IPtpIpCommandCallback callback;
private final boolean isDumpLog;
private final int id;
+ private final int holdId;
private final byte data0;
private final byte data1;
private final byte data2;
private final byte data3;
- public CanonRequestInnerDevelopStart(@NonNull IPtpIpCommandCallback callback, boolean isDumpLog, int id, int objectId)
+ public CanonRequestInnerDevelopStart(@NonNull IPtpIpCommandCallback callback, int id, boolean isDumpLog, int holdId, int objectId)
{
this.callback = callback;
this.isDumpLog = isDumpLog;
this.id = id;
+ this.holdId = holdId;
data0 = ((byte) (0x000000ff & objectId));
data1 = ((byte)((0x0000ff00 & objectId) >> 8));
});
}
+ @Override
+ public int getHoldId()
+ {
+ return (holdId);
+ }
+
+ @Override
+ public boolean isHold()
+ {
+ return (true);
+ }
+
+ @Override
+ public boolean isRelease()
+ {
+ return (false);
+ }
+
+
}
if (checkEventInitialize(rx_body))
{
interfaceProvider.getInformationReceiver().updateMessage(context.getString(R.string.canon_connect_connecting1), false, false, 0);
- commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, isDumpLog, SEQ_OPEN_SESSION, 0x1002, 4, 0x41));
+ commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_OPEN_SESSION, isDumpLog, 0, 0x1002, 4, 0x41));
}
else
{
case SEQ_OPEN_SESSION:
interfaceProvider.getInformationReceiver().updateMessage(context.getString(R.string.canon_connect_connecting2), false, false, 0);
- commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, isDumpLog, SEQ_INIT_SESSION, 0x902f));
+ commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_INIT_SESSION, isDumpLog, 0, 0x902f));
break;
case SEQ_INIT_SESSION:
interfaceProvider.getInformationReceiver().updateMessage(context.getString(R.string.canon_connect_connecting3), false, false, 0);
- commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, isDumpLog, SEQ_CHANGE_REMOTE, 0x9114, 4, 0x15));
+ commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_CHANGE_REMOTE, isDumpLog, 0, 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, isDumpLog, SEQ_SET_EVENT_MODE, 0x902f, 4, 0x02));
+ commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_SET_EVENT_MODE, isDumpLog, 0, 0x902f, 4, 0x02));
break;
case SEQ_SET_EVENT_MODE:
statusChecker.setEventConnectionNumber(eventConnectionNumber);
interfaceProvider.getCameraStatusWatcher().startStatusWatch(null);
- commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, isDumpLog, SEQ_OPEN_SESSION, 0x1002, 4, 0x41));
+ commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_OPEN_SESSION, isDumpLog, 0, 0x1002, 4, 0x41));
}
catch (Exception e)
{
{
case GET_STORAGE_ID:
// TODO: ストレージのIDを 0x00100010 で固定にしている。複数スロットある場合もあるので、このタイミングでちゃんと応答を parse してループさせる必要がある
- publisher.enqueueCommand(new PtpIpCommandGeneric(this,isDumpLog, GET_STORAGE_INFO, 0x9102, 4, 0x00010001));
+ publisher.enqueueCommand(new PtpIpCommandGeneric(this, GET_STORAGE_INFO, isDumpLog, 0, 0x9102, 4, 0x00010001));
subDirectoriesCount = -1; // ここから画像取得シーケンスに入るので、、、
break;
case GET_STORAGE_INFO:
// TODO: (要検討) ストレージの情報を取得しているが、本当に使わなくてもよい?
- publisher.enqueueCommand(new PtpIpCommandGeneric(this, isDumpLog, GET_OBJECT_INFO_EX, 0x9109, 12, 0x00010001, 0xffffffff, 0x00200000));
+ publisher.enqueueCommand(new PtpIpCommandGeneric(this, GET_OBJECT_INFO_EX, isDumpLog, 0, 0x9109, 12, 0x00010001, 0xffffffff, 0x00200000));
break;
case GET_OBJECT_INFO_EX:
// サブディレクトリの情報を拾う
for (PtpIpImageContentInfo contentInfo : directries)
{
- publisher.enqueueCommand(new PtpIpCommandGeneric(this, isDumpLog, GET_OBJECT_INFO_EX_2, 0x9109, 12, 0x00010001, contentInfo.getId(), 0x00200000));
+ publisher.enqueueCommand(new PtpIpCommandGeneric(this, GET_OBJECT_INFO_EX_2, isDumpLog, 0, 0x9109, 12, 0x00010001, contentInfo.getId(), 0x00200000));
}
}
break;
// 画像の情報を拾う
for (PtpIpImageContentInfo contentInfo : subDirectries)
{
- publisher.enqueueCommand(new PtpIpCommandGeneric(this, isDumpLog, GET_OBJECT_INFO_EX_3, 0x9109, 12, 0x00010001, contentInfo.getId(), 0x00200000));
+ publisher.enqueueCommand(new PtpIpCommandGeneric(this, GET_OBJECT_INFO_EX_3, isDumpLog, 0, 0x9109, 12, 0x00010001, contentInfo.getId(), 0x00200000));
}
subDirectoriesCount = subDirectries.size();
receivedSubDirectoriesCount = 0;
// オブジェクト一覧をクリアする
this.imageObjectList.clear();
this.ptpIpImageObjectList.clear();
- publisher.enqueueCommand(new PtpIpCommandGeneric(this, isDumpLog, GET_STORAGE_ID, 0x9101));
+ publisher.enqueueCommand(new PtpIpCommandGeneric(this, GET_STORAGE_ID, isDumpLog, 0, 0x9101));
this.callback = callback;
}
}
int objectId = content.getId();
// Log.v(TAG, "downloadContentThumbnail() " + indexStr + " [" + objectId + "] (" + storageId + ")");
- // 一連の画像取得シーケンス(RequestInnerDevelopStart, GetPartialObject, TransferComplete, RequestInnerDevelopEnd )を送信キューに積み込む
+ // 画像を取得する
PtpIpScreennailImageReceiver receiver = new PtpIpScreennailImageReceiver(activity, objectId, publisher, callback);
- publisher.enqueueCommand(new CanonRequestInnerDevelopStart(receiver, true, objectId, objectId)); // 0x9141 : RequestInnerDevelopStart
- publisher.enqueueCommand(new PtpIpCommandGeneric(receiver, true, (objectId + 1), 0x9107, 12, 0x01, 0x00, 0x00200000)); // 0x9107 : GetPartialObject (元は 0x00020000)
- publisher.enqueueCommand(new PtpIpCommandGeneric(receiver, true, (objectId + 2), 0x9117, 4,0x01)); // 0x9117 : TransferComplete
- publisher.enqueueCommand(new CanonRequestInnerDevelopEnd(receiver, true, (objectId + 3))); // 0x9143 : RequestInnerDevelopEnd
+ publisher.enqueueCommand(new CanonRequestInnerDevelopStart(receiver, objectId, true, objectId, objectId)); // 0x9141 : RequestInnerDevelopStart
}
}
catch (Exception e)
int storageId = content.getStorageId();
int objectId = content.getId();
// Log.v(TAG, "downloadContentThumbnail() " + indexStr + " [" + objectId + "] (" + storageId + ")");
- publisher.enqueueCommand(new PtpIpCommandGeneric(new PtpIpThumbnailImageReceiver(activity, callback), false, objectId, 0x910a, 8, objectId, 0x00032000));
+ publisher.enqueueCommand(new PtpIpCommandGeneric(new PtpIpThumbnailImageReceiver(activity, callback), objectId, false, 0, 0x910a, 8, objectId, 0x00032000));
}
}
catch (Exception e)
import android.app.Activity;
import android.graphics.BitmapFactory;
-import android.os.Environment;
import android.util.Log;
-import net.osdn.gokigen.pkremote.R;
import net.osdn.gokigen.pkremote.camera.interfaces.playback.IDownloadThumbnailImageCallback;
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.messages.specific.CanonRequestInnerDevelopEnd;
import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Locale;
import static net.osdn.gokigen.pkremote.camera.utils.SimpleLogDumper.binaryOutputToFile;
}
if (id == objectId)
{
- requestGetPartialObject();
+ getRequestStatusEvent(rx_body);
}
else if (id == objectId + 1)
{
{
Log.v(TAG, " RECEIVED : " + id);
}
+ else if (id == objectId + 5)
+ {
+ Log.v(TAG, " RECEIVED STATUS EVENT : " + id);
+ requestGetPartialObject(rx_body);
+ }
else
{
Log.v(TAG, " RECEIVED UNKNOWN ID : " + id);
return (false);
}
- private void requestGetPartialObject()
+ private void requestGetPartialObject(byte[] rx_body)
{
Log.v(TAG, " requestGetPartialObject() : " + objectId);
- //publisher.enqueueCommand(new PtpIpCommandGeneric(this, false, (objectId + 1), 0x9107, 12, 0x01, 0x00, 0x00200000));
+
+ // 0x9107 : GetPartialObject (元は 0x00020000)
+ int pictureLength = 0x00200000;
+ if (rx_body.length > 52)
+ {
+ int dataIndex = 48;
+ pictureLength = (rx_body[dataIndex] & 0xff);
+ pictureLength = pictureLength + ((rx_body[dataIndex + 1] & 0xff) << 8);
+ pictureLength = pictureLength + ((rx_body[dataIndex + 2] & 0xff) << 16);
+ pictureLength = pictureLength + ((rx_body[dataIndex + 3] & 0xff) << 24);
+ }
+ publisher.enqueueCommand(new PtpIpCommandGeneric(this, (objectId + 1), true, objectId, 0x9107, 12, 0x01, 0x00, pictureLength));
+ }
+
+ private void getRequestStatusEvent(byte[] rx_body)
+ {
+ Log.v(TAG, " getRequestStatusEvent : " + objectId);
+ publisher.enqueueCommand(new PtpIpCommandGeneric(this, (objectId + 5), true, objectId, 0x9116));
}
private void getPartialObject(byte[] rx_body)
{
Log.v(TAG, " getPartialObject(), id : " + objectId + " size: " + rx_body.length);
callback.onCompleted(BitmapFactory.decodeStream(new ByteArrayInputStream(rx_body)), null);
- //publisher.enqueueCommand(new PtpIpCommandGeneric(this, false, (objectId + 2), 0x9117, 4,0x01));
+ publisher.enqueueCommand(new PtpIpCommandGeneric(this, (objectId + 2), true, objectId, 0x9117, 4,0x01)); // 0x9117 : TransferComplete
// ファイルにバイナリデータをダンプする
- //binaryOutputToFile(activity, objectId + "_", rx_body);
+ binaryOutputToFile(activity, objectId + "_", rx_body);
}
private void requestInnerDevelopEnd()
{
Log.v(TAG, " requestInnerDevelopEnd() : " + objectId);
- //publisher.enqueueCommand(new CanonRequestInnerDevelopEnd(this, true, (objectId + 3)));
+ publisher.enqueueCommand(new CanonRequestInnerDevelopEnd(this, (objectId + 3), true, objectId)); // 0x9143 : RequestInnerDevelopEnd
}
private void finishedGetScreeennail()
Log.v(TAG, " --- SCREENNAIL RECV FINISHED. : " + objectId + " --- ");
// リセットコマンドを送ってみる
- publisher.enqueueCommand(new PtpIpCommandGeneric(this, false, (objectId + 4), 0x902f));
+ publisher.enqueueCommand(new PtpIpCommandGeneric(this, (objectId + 4), false, objectId, 0x902f));
}
}