private void ParsePacket(IPacket pk)
        {
            switch ((Cmd)pk.Cmd)
            {
            case Cmd.A_DotData:
            {
                long time  = pk.GetByteToInt();
                int  x     = pk.GetShort();
                int  y     = pk.GetShort();
                int  fx    = pk.GetByteToInt();
                int  fy    = pk.GetByteToInt();
                int  force = pk.GetByteToInt();

                long timeLong = mPrevDotTime + time;

                Dot.Builder builder = new Dot.Builder(MaxForce);

                builder.owner(mOwnerId)
                .section(mSectionId)
                .note(mNoteId)
                .page(mPageId)
                .timestamp(timeLong)
                .coord(x, fx, y, fy)
                .force(force)
                .color(mCurrentColor);


                if (!IsStartWithDown)
                {
                    if (!IsStartWithPaperInfo)
                    {
                        //펜 다운 없이 페이퍼 정보 없고 무브가 오는 현상(다운 - 무브 - 업 - 다운X - 무브)
                        Callback.onErrorDetected(this, ErrorType.MissingPenDown, -1, null, null);
                    }
                    else
                    {
                        //펜 다운 없이 페이퍼 정보 있고 무브가 오는 현상(다운 - 무브 - 업 - 다운X - 무브)
                        builder.dotType(DotTypes.PEN_ERROR);
                        var errorDot = builder.Build();
                        Callback.onErrorDetected(this, ErrorType.MissingPenDown, -1, errorDot, null);
                        IsStartWithDown = true;
                        builder.timestamp(Time.GetUtcTimeStamp());
                    }
                }

                if (!IsStartWithDown)
                {
                    if (!IsStartWithPaperInfo)
                    {
                        //펜 다운 없이 페이퍼 정보 없고 무브가 오는 현상(다운 - 무브 - 업 - 다운X - 무브)
                        Callback.onErrorDetected(this, ErrorType.MissingPenDown, -1, null, null);
                    }
                    else
                    {
                        timeLong    = Time.GetUtcTimeStamp();
                        PenDownTime = timeLong;
                        //펜 다운 없이 페이퍼 정보 있고 무브가 오는 현상(다운 - 무브 - 업 - 다운X - 무브)
                        builder.dotType(DotTypes.PEN_ERROR);
                        var errorDot = builder.Build();
                        Callback.onErrorDetected(this, ErrorType.MissingPenDown, PenDownTime, errorDot, null);
                        IsStartWithDown = true;
                        builder.timestamp(timeLong);
                    }
                }

                if (timeLong < 10000)
                {
                    // 타임스템프가 10000보다 작을 경우 도트 필터링
                    builder.dotType(DotTypes.PEN_ERROR);
                    var errorDot = builder.Build();
                    Callback.onErrorDetected(this, ErrorType.InvalidTime, PenDownTime, errorDot, null);
                }

                Dot dot = null;

                if (IsStartWithDown && IsStartWithPaperInfo && IsBeforePaperInfo)
                {
                    // 펜다운의 경우 시작 도트로 저장
                    dot = builder.timestamp(PenDownTime).dotType(DotTypes.PEN_DOWN).Build();
                }
                else if (IsStartWithDown && IsStartWithPaperInfo && !IsBeforePaperInfo && IsBeforeMiddle)
                {
                    // 펜다운이 아닌 경우 미들 도트로 저장
                    dot = builder.dotType(DotTypes.PEN_MOVE).Build();
                }
                else if (IsStartWithDown && !IsStartWithPaperInfo)
                {
                    //펜 다운 이후 페이지 체인지 없이 도트가 들어왔을 경우
                    Callback.onErrorDetected(this, ErrorType.MissingPageChange, PenDownTime, null, null);
                }

                if (dot != null)
                {
                    ProcessDot(dot);
                }

                mPrevDot          = dot;
                mPrevDotTime      = timeLong;
                IsBeforeMiddle    = true;
                IsBeforePaperInfo = false;
            }
            break;

            case Cmd.A_DotUpDownDataNew:
            case Cmd.A_DotUpDownData:
            {
                long updownTime = pk.GetLong();

                int updown = pk.GetByteToInt();

                byte[] cbyte = pk.GetBytes(3);

                mCurrentColor = ByteConverter.ByteToInt(new byte[] { cbyte[2], cbyte[1], cbyte[0], (byte)0xFF });

                if (updown == 0x00)
                {
                    // 펜 다운 일 경우 Start Dot의 timestamp 설정
                    mPrevDotTime = updownTime;
                    //IsPrevDotDown = true;

                    if (IsBeforeMiddle && mPrevDot != null)
                    {
                        // 펜업이 넘어오지 않는 경우
                        //var errorDot = mPrevDot.Clone();
                        //errorDot.DotType = DotTypes.PEN_ERROR;
                        //Callback.onErrorDetected(this, ErrorType.MissingPenUp, PenDownTime, errorDot, null);

                        MakeUpDot();
                    }

                    IsStartWithDown = true;

                    PenDownTime = updownTime;
                    //Callback.onUpDown( this, false );
                }
                else if (updown == 0x01)
                {
                    mPrevDotTime = -1;

                    if (IsStartWithDown && IsBeforeMiddle && mPrevDot != null)
                    {
                        MakeUpDot(false);
                    }
                    else if (!IsStartWithDown && !IsBeforeMiddle)
                    {
                        Callback.onErrorDetected(this, ErrorType.MissingPenDownPenMove, PenDownTime, null, null);
                    }
                    else if (!IsBeforeMiddle)
                    {
                        // 무브없이 다운-업만 들어올 경우 UP dot을 보내지 않음
                        Callback.onErrorDetected(this, ErrorType.MissingPenMove, PenDownTime, null, null);
                    }

                    IsStartWithDown = false;

                    PenDownTime = -1;
                }

                IsBeforeMiddle       = false;
                IsStartWithPaperInfo = false;

                mPrevDot = null;
            }
            break;

            case Cmd.A_DotIDChange:

                if (IsStartWithDown && IsBeforeMiddle && mPrevDot != null)
                {
                    MakeUpDot(false);
                }

                byte[] rb = pk.GetBytes(4);

                mSectionId = (int)(rb[3] & 0xFF);
                mOwnerId   = ByteConverter.ByteToInt(new byte[] { rb[0], rb[1], rb[2], (byte)0x00 });
                mNoteId    = pk.GetInt();
                mPageId    = pk.GetInt();

                //IsPrevDotDown = true;

                IsBeforePaperInfo    = true;
                IsStartWithPaperInfo = true;

                break;

            case Cmd.A_PenOnState:

                pk.Move(8);

                int STATUS = pk.GetByteToInt();

                int FORCE_MAX = pk.GetByteToInt();

                MaxForce = (short)FORCE_MAX;

                string SW_VER = pk.GetString(5);

                if (STATUS == 0x00)
                {
                    SendPenOnOffData();
                    Clean();
                }
                else if (STATUS == 0x01)
                {
                    Reset();

                    SendPenOnOffData();
                    SendRTCData();
                    needToInputDefaultPassword = true;
                    mOfflineworker.PenMaxForce = FORCE_MAX;
                    Callback.onConnected(this, FORCE_MAX, SW_VER);
                }

                break;

            case Cmd.A_RTCsetResponse:
                break;

            case Cmd.A_PenStatusResponse:

                if (!Authenticated)
                {
                    Authenticated = true;
                    needToInputDefaultPassword = false;
                    Callback.onPenAuthenticated(this);
                }

                pk.Move(2);

                int  stat_timezone = pk.GetInt();
                long stat_timetick = pk.GetLong();
                int  stat_forcemax = pk.GetByteToInt();
                int  stat_battery  = pk.GetByteToInt();
                int  stat_usedmem  = pk.GetByteToInt();
                int  stat_pencolor = pk.GetInt();

                bool stat_autopower = pk.GetByteToInt() == 2 ? false : true;
                bool stat_accel     = pk.GetByteToInt() == 2 ? false : true;
                bool stat_hovermode = pk.GetByteToInt() == 2 ? false : true;
                bool stat_beep      = pk.GetByteToInt() == 2 ? false : true;

                short stat_autoshutdowntime = pk.GetShort();
                short stat_pensensitivity   = pk.GetShort();

                string model_name = string.Empty;
                if (pk.CheckMoreData())
                {
                    int model_name_length = pk.GetByte();
                    model_name = pk.GetString(model_name_length);
                }

                Callback.onReceivedPenStatus(this, stat_timezone, stat_timetick, stat_forcemax, stat_battery, stat_usedmem, stat_pencolor, stat_autopower, stat_accel, stat_hovermode, stat_beep, stat_autoshutdowntime, stat_pensensitivity, model_name);

                break;

            // 오프라인 데이터 크기,갯수 전송
            case Cmd.A_OfflineDataInfo:

                mOfflineTotalFileCount = pk.GetInt();
                mOfflineTotalDataSize  = pk.GetInt();

                System.Console.WriteLine("[PenCommCore] A_OfflineDataInfo : {0}, {1}", mOfflineTotalFileCount, mOfflineTotalDataSize);

                Callback.onStartOfflineDownload(this);

                IsStartOfflineTask = true;

                break;

            // 오프라인 전송 최종 결과 응답
            case Cmd.A_OfflineResultResponse:

                int result = pk.GetByteToInt();

                //System.Console.WriteLine( "[PenCommCore] A_OfflineDataResponse : {0}", result );

                IsStartOfflineTask = false;

                Callback.onFinishedOfflineDownload(this, result == 0x00 ? false : true);

                mOfflineworker.onFinishDownload();

                mOfflineRcvDataSize = 0;

                break;

            // 오프라인 파일 정보
            case Cmd.A_OfflineFileInfo:

                mOfflineFileName    = pk.GetString(128);
                mOfflineFileSize    = pk.GetInt();
                mOfflinePacketCount = pk.GetShort();
                mOfflinePacketSize  = pk.GetShort();

                System.Console.WriteLine("[PenCommCore] offline file transfer is started ( name : " + mOfflineFileName + ", size : " + mOfflineFileSize + ", packet_qty : " + mOfflinePacketCount + ", packet_size : " + mOfflinePacketSize + " )");

                mOfflineDataBuilder = null;
                mOfflineDataBuilder = new OfflineDataSerializer(mOfflineFileName, mOfflinePacketCount, mOfflineFileName.Contains(".zip") ? true : false);

                SendOfflineInfoResponse();

                break;

            // 오프라인 파일 조각 전송
            case Cmd.A_OfflineChunk:

                int index = pk.GetShort();

                // 체크섬 필드
                byte cs = pk.GetByte();

                // 체크섬 계산
                byte calcChecksum = pk.GetChecksum();

                // 오프라인 데이터
                byte[] data = pk.GetBytes();

                // 체크섬이 틀리거나, 카운트, 사이즈 정보가 맞지 않으면 버린다.
                if (cs == calcChecksum && mOfflinePacketCount > index && mOfflinePacketSize >= data.Length)
                {
                    mOfflineDataBuilder.Put(data, index);

                    // 만약 Chunk를 다 받았다면 offline data를 처리한다.
                    if (mOfflinePacketCount == mOfflineDataBuilder.chunks.Count)
                    {
                        string output = mOfflineDataBuilder.MakeFile();

                        if (output != null)
                        {
                            SendOfflineChunkResponse((short)index);
                            mOfflineworker.onCreateFile(mOfflineDataBuilder.sectionId, mOfflineDataBuilder.ownerId, mOfflineDataBuilder.noteId, output);
                        }

                        mOfflineDataBuilder = null;
                    }
                    else
                    {
                        SendOfflineChunkResponse((short)index);
                    }

                    mOfflineRcvDataSize += data.Length;

                    if (mOfflineTotalDataSize > 0)
                    {
                        System.Console.WriteLine("[PenCommCore] mOfflineRcvDataSize : " + mOfflineRcvDataSize);

                        Callback.onUpdateOfflineDownload(this, mOfflineTotalDataSize, mOfflineRcvDataSize);
                    }
                }
                else
                {
                    System.Console.WriteLine("[PenCommCore] offline data file verification failed ( index : " + index + " )");
                }

                break;

            case Cmd.A_UsingNoteNotifyResponse:
            {
                bool accepted = pk.GetByteToInt() == 0x01;

                Callback.onAvailableNoteAccepted(this, accepted);
            }
            break;

            case Cmd.A_OfflineNoteListResponse:
            {
                int status = pk.GetByteToInt();

                byte[] rxb = pk.GetBytes(4);

                int section = (int)(rxb[3] & 0xFF);

                int owner = ByteConverter.ByteToInt(new byte[] { rxb[0], rxb[1], rxb[2], (byte)0x00 });

                int noteCnt = pk.GetByteToInt();

                for (int i = 0; i < noteCnt; i++)
                {
                    int note = pk.GetInt();
                    mOfflineNotes.Add(new OfflineDataInfo(section, owner, note));
                }

                if (status == 0x01)
                {
                    OfflineDataInfo[] array = mOfflineNotes.ToArray();

                    Callback.onOfflineDataList(this, array);
                    mOfflineNotes.Clear();
                }
                else
                {
                    Callback.onOfflineDataList(this, new OfflineDataInfo[0]);
                }
            }
            break;

            case Cmd.A_OfflineDataRemoveResponse:
                //System.Console.WriteLine( "[PenCommCore] CMD.A_OfflineDataRemoveResponse" );
                break;

            case Cmd.A_PasswordRequest:
            {
                int countRetry = pk.GetByteToInt();
                int countReset = pk.GetByteToInt();

                System.Console.WriteLine("[PenCommCore] A_PasswordRequest ( " + countRetry + " / " + countReset + " )");

                if (needToInputDefaultPassword)
                {
                    _ReqInputPassword(DEFAULT_PASSWORD);
                    needToInputDefaultPassword = false;
                }
                else
                {
                    Callback.onPenPasswordRequest(this, countRetry, countReset);
                }
            }
            break;


            case Cmd.A_PasswordSetResponse:
            {
                int setResult = pk.GetByteToInt();

                //System.Console.WriteLine( "[PenCommCore] A_PasswordSetResponse => " + setResult );
                if (setResult == 0x00)
                {
                    needToInputDefaultPassword = true;
                }

                Callback.onPenPasswordSetUpResponse(this, setResult == 0x00 ? true : false);
            }
            break;

            case Cmd.A_PenSensitivityResponse:
            case Cmd.A_AutoShutdownTimeResponse:
            case Cmd.A_AutoPowerOnResponse:
            case Cmd.A_BeepSetResponse:
            case Cmd.A_PenColorSetResponse:
            case Cmd.A_HoverOnOffResponse:
                ResPenSetup((Cmd)pk.Cmd, pk.GetByteToInt() == 0x01);
                break;

            case Cmd.A_PenSWUpgradeRequest:

                short idx = pk.GetShort();

                ResponseChunkRequest(idx);

                break;

            case Cmd.A_PenSWUpgradeStatus:
            {
                int upgStatus = pk.GetByteToInt();

                if (upgStatus == 0x02)
                {
                    return;
                }

                Callback.onReceivedFirmwareUpdateResult(this, upgStatus == 0x01);
                mFwChunk = null;
            }
            break;
            }
        }
Esempio n. 2
0
        public void ParsePacket(Packet packet)
        {
            //Debug.WriteLine("[PenCommCore] ParsePacket : " + packet.Cmd);

            switch ((Cmd)packet.Cmd)
            {
            case Cmd.A_DotData:
            {
                long time  = packet.GetByteToInt();
                int  x     = packet.GetShort();
                int  y     = packet.GetShort();
                int  fx    = packet.GetByteToInt();
                int  fy    = packet.GetByteToInt();
                int  force = packet.GetByteToInt();

                long timeLong = mPrevDotTime + time;

                if (!IsStartWithDown || timeLong < 10000)
                {
                    Debug.WriteLine("[PenCommCore] this stroke start with middle dot.");
                    return;
                }

                if (IsPrevDotDown)
                {
                    // 펜업의 경우 시작 도트로 저장
                    IsPrevDotDown = false;
                    ProcessDot(mOwnerId, mSectionId, mNoteId, mPageId, timeLong, x, y, fx, fy, force, DotTypes.PEN_DOWN, mCurrentColor);
                }
                else
                {
                    // 펜업이 아닌 경우 미들 도트로 저장
                    ProcessDot(mOwnerId, mSectionId, mNoteId, mPageId, timeLong, x, y, fx, fy, force, DotTypes.PEN_MOVE, mCurrentColor);
                }

                mPrevDotTime = timeLong;
                mPrevPacket  = packet;
            }
            break;

            case Cmd.A_DotUpDownDataNew:
            case Cmd.A_DotUpDownData:
            {
                // TODO Check
                long updownTime = packet.GetLong();

                int updown = packet.GetByteToInt();

                byte[] cbyte = packet.GetBytes(3);

                mCurrentColor = ByteConverter.ByteToInt(new byte[] { cbyte[2], cbyte[1], cbyte[0], (byte)0 });

                if (updown == 0x00)
                {
                    // 펜 다운 일 경우 Start Dot의 timestamp 설정
                    mPrevDotTime    = updownTime;
                    IsPrevDotDown   = true;
                    IsStartWithDown = true;

                    //Callback.onUpDown(this, false);
                }
                else if (updown == 0x01)
                {
                    if (mPrevPacket != null)
                    {
                        mPrevPacket.Reset();

                        // 펜 업 일 경우 바로 이전 도트를 End Dot로 삽입
                        int time  = mPrevPacket.GetByteToInt();
                        int x     = mPrevPacket.GetShort();
                        int y     = mPrevPacket.GetShort();
                        int fx    = mPrevPacket.GetByteToInt();
                        int fy    = mPrevPacket.GetByteToInt();
                        int force = mPrevPacket.GetByteToInt();

                        ProcessDot(mOwnerId, mSectionId, mNoteId, mPageId, updownTime, x, y, fx, fy, force, DotTypes.PEN_UP, mCurrentColor);
                    }

                    //Callback.onUpDown(this, true);

                    IsStartWithDown = false;
                }

                mPrevPacket = null;
            }
            break;

            case Cmd.A_DotIDChange:

                byte[] rb = packet.GetBytes(4);

                mSectionId = (int)(rb[3] & 0xFF);
                mOwnerId   = ByteConverter.ByteToInt(new byte[] { rb[0], rb[1], rb[2], (byte)0x00 });
                mNoteId    = packet.GetInt();
                mPageId    = packet.GetInt();

                break;

            case Cmd.A_PenOnState:

                packet.Move(8);

                int STATUS = packet.GetByteToInt();

                int FORCE_MAX = packet.GetByteToInt();

                string SW_VER = packet.GetString(5);

                if (STATUS == 0x00)
                {
                    SendPenOnOffData();
                }
                else if (STATUS == 0x01)
                {
                    Reset();

                    SendPenOnOffData();
                    SendRTCData();

                    PenController.onConnected(new ConnectedEventArgs(SW_VER, FORCE_MAX));
                    PenMaxForce = FORCE_MAX;
                    mOfflineworker.PenMaxForce = FORCE_MAX;
                }

                break;

            case Cmd.A_RTCsetResponse:
                break;

            case Cmd.A_PenStatusResponse:

                if (!Authenticated)
                {
                    Authenticated = true;
                    PenController.onPenAuthenticated();
                }

                packet.Move(2);

                int  stat_timezone = packet.GetInt();
                long stat_timetick = packet.GetLong();
                int  stat_forcemax = packet.GetByteToInt();
                int  stat_battery  = packet.GetByteToInt();
                int  stat_usedmem  = packet.GetByteToInt();
                int  stat_pencolor = packet.GetInt();

                bool stat_autopower = packet.GetByteToInt() == 2 ? false : true;
                bool stat_accel     = packet.GetByteToInt() == 2 ? false : true;
                bool stat_hovermode = packet.GetByteToInt() == 2 ? false : true;
                bool stat_beep      = packet.GetByteToInt() == 2 ? false : true;

                short stat_autoshutdowntime = packet.GetShort();
                short stat_pensensitivity   = packet.GetShort();

                PenController.onReceivePenStatus(new PenStatusReceivedEventArgs(stat_timezone, stat_timetick, stat_forcemax, stat_battery, stat_usedmem, stat_pencolor, stat_autopower, stat_accel, stat_hovermode, stat_beep, stat_autoshutdowntime, stat_pensensitivity));
                break;

            // 오프라인 데이터 크기,갯수 전송
            case Cmd.A_OfflineDataInfo:

                mOfflineTotalFileCount = packet.GetInt();
                mOfflineTotalDataSize  = packet.GetInt();

                Debug.WriteLine("[PenCommCore] A_OfflineDataInfo : {0}, {1}", mOfflineTotalFileCount, mOfflineTotalDataSize);

                PenController.onStartOfflineDownload();

                IsStartOfflineTask = true;

                break;

            // 오프라인 전송 최종 결과 응답
            case Cmd.A_OfflineResultResponse:

                int result = packet.GetByteToInt();

                //System.Console.WriteLine( "[PenCommCore] A_OfflineDataResponse : {0}", result );

                IsStartOfflineTask = false;

                PenController.onFinishedOfflineDownload(new SimpleResultEventArgs(result == 0x00));

                mOfflineworker.onFinishDownload();

                break;

            // 오프라인 파일 정보
            case Cmd.A_OfflineFileInfo:

                mOfflineFileName    = packet.GetString(128);
                mOfflineFileSize    = packet.GetInt();
                mOfflinePacketCount = packet.GetShort();
                mOfflinePacketSize  = packet.GetShort();

                Debug.WriteLine("[PenCommCore] offline file transfer is started ( name : " + mOfflineFileName + ", size : " + mOfflineFileSize + ", packet_qty : " + mOfflinePacketCount + ", packet_size : " + mOfflinePacketSize + " )");

                mOfflineDataBuilder = null;
                mOfflineDataBuilder = new OfflineDataSerializer(mOfflineFileName, mOfflinePacketCount, mOfflineFileName.Contains(".zip") ? true : false);

                SendOfflineInfoResponse();

                break;

            // 오프라인 파일 조각 전송
            case Cmd.A_OfflineChunk:

                int index = packet.GetShort();

                // 체크섬 필드
                byte cs = packet.GetByte();

                // 체크섬 계산
                byte calcChecksum = packet.GetChecksum();

                // 오프라인 데이터
                byte[] data = packet.GetBytes();

                // 체크섬이 틀리거나, 카운트, 사이즈 정보가 맞지 않으면 버린다.
                if (cs == calcChecksum && mOfflinePacketCount > index && mOfflinePacketSize >= data.Length)
                {
                    mOfflineDataBuilder.Put(data, index);

                    // 만약 Chunk를 다 받았다면 offline data를 처리한다.
                    if (mOfflinePacketCount == mOfflineDataBuilder.chunks.Count)
                    {
                        string output = mOfflineDataBuilder.MakeFile();

                        if (output != null)
                        {
                            SendOfflineChunkResponse((short)index);
                            mOfflineworker.onCreateFile(mOfflineDataBuilder.sectionId, mOfflineDataBuilder.ownerId, mOfflineDataBuilder.noteId, output, mOfflineTotalDataSize, mOfflineRcvDataSize);
                        }

                        mOfflineDataBuilder = null;
                    }
                    else
                    {
                        SendOfflineChunkResponse((short)index);
                    }

                    mOfflineRcvDataSize += data.Length;

                    // TODO Check
                    //if (mOfflineTotalDataSize > 0)
                    //{
                    //	Debug.WriteLine("[PenCommCore] mOfflineRcvDataSize : " + mOfflineRcvDataSize);

                    //	//Callback.onUpdateOfflineDownload(this, mOfflineTotalDataSize, mOfflineRcvDataSize);
                    //}
                }
                else
                {
                    Debug.WriteLine("[PenCommCore] offline data file verification failed ( index : " + index + " )");
                }

                break;

            case Cmd.A_UsingNoteNotifyResponse:
                PenController.onAvailableNoteAdded();
                break;

            case Cmd.A_OfflineNoteListResponse:
            {
                int status = packet.GetByteToInt();

                byte[] rxb = packet.GetBytes(4);

                int section = (int)(rxb[3] & 0xFF);

                int owner = ByteConverter.ByteToInt(new byte[] { rxb[0], rxb[1], rxb[2], (byte)0x00 });

                int noteCnt = packet.GetByteToInt();

                for (int i = 0; i < noteCnt; i++)
                {
                    int note = packet.GetInt();
                    mOfflineNotes.Add(new OfflineDataInfo(section, owner, note));
                }

                if (status == 0x01)
                {
                    OfflineDataInfo[] array = mOfflineNotes.ToArray();

                    PenController.onReceiveOfflineDataList(new OfflineDataListReceivedEventArgs(array));
                    mOfflineNotes.Clear();
                }
                else
                {
                    PenController.onReceiveOfflineDataList(new OfflineDataListReceivedEventArgs(new OfflineDataInfo[0]));
                }
            }
            break;

            case Cmd.A_OfflineDataRemoveResponse:
                //System.Console.WriteLine( "[PenCommCore] CMD.A_OfflineDataRemoveResponse" );
                break;

            case Cmd.A_PasswordRequest:
            {
                int countRetry = packet.GetByteToInt();
                int countReset = packet.GetByteToInt();

                Debug.WriteLine("[PenCommCore] A_PasswordRequest ( " + countRetry + " / " + countReset + " )");

                PenController.onPenPasswordRequest(new PasswordRequestedEventArgs(countRetry, countReset));
            }
            break;


            case Cmd.A_PasswordSetResponse:
            {
                int setResult = packet.GetByteToInt();

                //System.Console.WriteLine( "[PenCommCore] A_PasswordSetResponse => " + setResult );

                PenController.onPenPasswordSetupResponse(new SimpleResultEventArgs(setResult == 0x00));
            }
            break;

            case Cmd.A_PenSensitivityResponse:
            case Cmd.A_AutoShutdownTimeResponse:
            case Cmd.A_AutoPowerOnResponse:
            case Cmd.A_BeepSetResponse:
            case Cmd.A_PenColorSetResponse:
                ResPenSetup((Cmd)packet.Cmd, packet.GetByteToInt() == 0x01);
                break;

            case Cmd.A_PenSWUpgradeRequest:

                short idx = packet.GetShort();

                Debug.WriteLine("[PenCommCore] A_PenSWUpgradeRequest => " + idx);

                ResponseChunkRequest(idx);

                break;

            case Cmd.A_PenSWUpgradeStatus:
            {
                int upgStatus = packet.GetByteToInt();

                if (upgStatus == 0x02)
                {
                    return;
                }

                PenController.onReceiveFirmwareUpdateResult(new SimpleResultEventArgs(upgStatus == 0x01));
                mFwChunk = null;
            }
            break;
            }
        }