// // Date init 14.12.2004 // // Revision date $Date: 8-09-08 14:11 $ // // Filename $Workfile:: c_comm.c $ // // Version $Revision: 7 $ // // Archive $Archive:: /LMS2006/Sys01/Main_V02/Firmware/Source/c_comm $ // // Platform C // #include "stdconst.h" #include "modules.h" #include "c_comm.iom" #include "c_loader.iom" #include "c_ioctrl.iom" #include "c_ui.iom" #include "c_cmd.iom" #include "c_display.iom" #include "c_comm.h" #include "d_usb.h" #include "d_hispeed.h" #include "d_bt.h" #include #include #ifdef __ARMDEBUG__ #include "debug_stub.h" #endif enum { DEVICE_VERIFIED, DEVICE_UPDATED, DEVICE_INSERTED }; #define DEFAULTBTADR "\x00\x16\x53\xFF\xFF\xFF" #define BTSTREAMTOUT 610 #define LOOKUPNO 3 #define CLEARExtMode {\ UBYTE Tmp;\ for(Tmp = 0; Tmp < NO_OF_CHANNELS; Tmp++)\ {\ VarsComm.ExtMode[Tmp].Status = FALSE;\ }\ } #define CHNumber(Bit) (Bit>>1) #define SETBtStateIdle VarsComm.ActiveUpdate = UPD_IDLE;\ VarsComm.UpdateState = 0;\ VarsComm.StreamStateCnt = 0;\ VarsComm.CmdSwitchCnt = 0;\ VarsComm.CloseConn0Cnt = 0;\ VarsComm.DiscAllCnt = 0;\ VarsComm.ResetBtCnt = 0 #define SETBtCmdState VarsComm.BtState = BT_ARM_CMD_MODE;\ IOMapComm.BtInBuf.InPtr = 0;\ CLEARExtMode;\ dBtClearArm7CmdSignal();\ dBtInitReceive(VarsComm.BtModuleInBuf.Buf, (UBYTE)CMD_MODE); #define SETBtDataState IOMapComm.BtInBuf.InPtr = 0;\ VarsComm.BtState = BT_ARM_DATA_MODE;\ dBtClearTimeOut(); /* stop cmd timeout because in datamode */\ dBtSetArm7CmdSignal();\ dBtInitReceive(VarsComm.BtModuleInBuf.Buf, (UBYTE)STREAM_MODE) #define SETBtOff VarsComm.BtState = BT_ARM_OFF;\ dBtSetBcResetPinLow() #define CLEARConnEntry(Index) memset((IOMapComm.BtConnectTable[Index].BdAddr), 0, SIZE_OF_BDADDR);\ memset(IOMapComm.BtConnectTable[Index].Name, 0, SIZE_OF_BT_NAME);\ memset((IOMapComm.BtConnectTable[Index].ClassOfDevice), 0, SIZE_OF_CLASS_OF_DEVICE);\ memset((IOMapComm.BtConnectTable[Index].PinCode), 0, SIZE_OF_BT_PINCODE);\ IOMapComm.BtConnectTable[Index].HandleNr = BLUETOOTH_HANDLE_UNDEFIEND;\ IOMapComm.BtConnectTable[Index].StreamStatus = 0;\ IOMapComm.BtConnectTable[Index].LinkQuality = 0 #define FILETXTOUT 30000 const UBYTE BootString[] = {"Let's dance: SAMBA"}; const UBYTE NoName[SIZE_OF_BT_NAME] = {"No Name"}; static IOMAPCOMM IOMapComm; static VARSCOMM VarsComm; static HEADER **pHeaders; const HEADER cComm = { 0x00050001L, "Comm", cCommInit, cCommCtrl, cCommExit, (void *)&IOMapComm, (void *)&VarsComm, (UWORD)sizeof(IOMapComm), (UWORD)sizeof(VarsComm), 0x0000 /* Code size - not used so far */ }; UWORD cCommReceivedBtData(void); void cCommBtCmdInterpreter(void); UWORD cCommInterprete(UBYTE *pInBuf, UBYTE *pOutBuf, UBYTE *pLength, UBYTE CmdBit, UWORD MsgLength); UWORD cCommInterpreteCmd(UBYTE Cmd, UBYTE *pInBuf, UBYTE *pOutBuf, UBYTE *pLength, UBYTE CmdBit, UWORD MsgLength); void cCommCpyToUpper(UBYTE *pDst, UBYTE *pSrc, UBYTE Length); void cCommCopyFileName(UBYTE *pDst, UBYTE *pSrc); void cCommSendHiSpeedData(void); void cCommReceivedHiSpeedData(void); UWORD cCommReq(UBYTE Cmd, UBYTE Param1, UBYTE Param2, UBYTE Param3, UBYTE *pName, UWORD *pRetVal); UBYTE cCommBtValidateCmd(void); void cCommClearStreamStatus(void); void cCommUpdateBt(void); UWORD cCommCopyBdaddr(UBYTE *pDst, UBYTE *pSrc); UWORD cCommInsertBtName(UBYTE *pDst, UBYTE *pSrc); UWORD cCommCheckBdaddr(UBYTE *pAdr, UBYTE *pSrc); UWORD cCommInsertDevice(UBYTE *pBdaddr, UBYTE *pName, UBYTE *pCod, UBYTE DeviceStatus, UBYTE *pAddInfo); void cCommsSetCmdMode(UBYTE *pNextState); void cCommsOpenStream(UBYTE *pNextState); void cCommsCloseConn0(UBYTE *pNextState); void cCommsDisconnectAll(UBYTE *pNextState); void cCommsBtReset(UBYTE *pNextState); void cCommPinCode(UBYTE *pPinCode); void cCommClrConnTable(void); SBYTE cCommSearchBTDevTableForName(UBYTE*); void cCommInit(void* pHeader) { UBYTE Tmp; pHeaders = pHeader; IOMapComm.pFunc = &cCommReq; IOMapComm.pFunc2 = &cCommPinCode; IOMapComm.UsbState = FALSE; IOMapComm.UsbOutBuf.OutPtr = 0; CLEARExtMode; dUsbInit(); dBtInit(); SETBtStateIdle; VarsComm.BtModuleInBuf.InPtr = 0; VarsComm.BtWaitTimeCnt = 0; /* Force a reset sequence on the BC4 */ VarsComm.pRetVal = &(VarsComm.RetVal); VarsComm.ActiveUpdate = UPD_RESET; VarsComm.BtState = BT_ARM_CMD_MODE; IOMapComm.BrickData.BtHwStatus = BT_DISABLE; for (Tmp = 0; Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++) { IOMapComm.BtDeviceTable[Tmp].DeviceStatus = BT_DEVICE_EMPTY; } IOMapComm.BtDeviceCnt = 0; IOMapComm.BrickData.BtStateStatus = 0; cCommClrConnTable(); dBtInitReceive(VarsComm.BtModuleInBuf.Buf, (UBYTE)CMD_MODE); dBtStartADConverter(); dHiSpeedInit(); VarsComm.HsState = 0; IOMapComm.UsbPollBuf.InPtr = 0; IOMapComm.UsbPollBuf.OutPtr = 0; VarsComm.BtAdrStatus = COLDBOOT; } void cCommCtrl(void) { if (FALSE == cCommReceivedBtData()) { /* there has been a timeout on the BC4 channel */ SETBtStateIdle; *(VarsComm.pRetVal) = BTTIMEOUT; if (COLDBOOT == VarsComm.BtAdrStatus) { /* there is an BT fatal error - set default bt adr and name*/ strcpy((char*)IOMapComm.BrickData.Name, (char*)UI_NAME_DEFAULT); dUsbStoreBtAddress((UBYTE*)DEFAULTBTADR); pMapUi->Flags |= UI_REDRAW_STATUS; dBtSetBcResetPinLow(); VarsComm.BtAdrStatus = BTADRERROR; } } cCommUpdateBt(); VarsComm.BtBcPinLevel = dBtGetBc4CmdSignal(); if (UPD_IDLE == VarsComm.ActiveUpdate) { switch (VarsComm.BtState) { /* Bluetooth device can either be in CMD, DATA or OFF state at top level */ case BT_ARM_OFF: { } break; case BT_ARM_CMD_MODE: { if (VarsComm.BtBcPinLevel) { SETBtDataState; } } break; case BT_ARM_DATA_MODE: { if (!(VarsComm.BtBcPinLevel)) { SETBtCmdState; } } break; } } IOMapComm.BtInBuf.Buf[BT_CMD_BYTE] = 0; /* Here comes the the HIGHSPEED_PORT implementation */ if (IOMapComm.HsFlags & HS_UPDATE) { IOMapComm.HsFlags &= ~HS_UPDATE; switch (IOMapComm.HsState) { case HS_INITIALISE: { dHiSpeedSetupUart(); IOMapComm.HsState = HS_INIT_RECEIVER; IOMapComm.HsFlags |= HS_UPDATE; } break; case HS_INIT_RECEIVER: { dHiSpeedInitReceive(VarsComm.HsModuleInBuf.Buf); VarsComm.HsState = 0x01; } break; case HS_SEND_DATA: { cCommSendHiSpeedData(); } break; case HS_DISABLE: { VarsComm.HsState = 0x00; dHiSpeedExit(); } break; } } if (VarsComm.HsState != 0) { cCommReceivedHiSpeedData(); } /* Here comes the the USB implementation */ ULONG Length; UWORD Status; if (0 != IOMapComm.UsbOutBuf.OutPtr) { dUsbWrite((const UBYTE *)IOMapComm.UsbOutBuf.Buf, (ULONG)IOMapComm.UsbOutBuf.OutPtr); IOMapComm.UsbOutBuf.OutPtr = 0; } Length = 0; if (TRUE == dUsbCheckConnection()) { pMapUi->UsbState = 1; if (TRUE == dUsbIsConfigured()) { Length = dUsbRead(IOMapComm.UsbInBuf.Buf, sizeof(IOMapComm.UsbInBuf.Buf)); IOMapComm.UsbState = TRUE; pMapUi->UsbState = 2; } } else { pMapUi->UsbState = 0; dUsbResetConfig(); if (TRUE == IOMapComm.UsbState) { IOMapComm.UsbState = FALSE; Status = dUsbGetFirstHandle(); while(0 == LOADER_ERR(Status)) { IOMapComm.UsbInBuf.Buf[0] = LOADER_HANDLE(Status); pMapLoader->pFunc(CLOSE, &(IOMapComm.UsbInBuf.Buf[0]), &(IOMapComm.UsbInBuf.Buf[2]), &Length); dUsbRemoveHandle(IOMapComm.UsbInBuf.Buf[0]); Status = dUsbGetNextHandle(); } } } if (0 != Length) { cCommInterprete(IOMapComm.UsbInBuf.Buf, IOMapComm.UsbOutBuf.Buf, (UBYTE*)&Length, USB_CMD_READY, (UWORD)Length); if (Length) { dUsbWrite((const UBYTE *)IOMapComm.UsbOutBuf.Buf, Length); } } dBtStartADConverter(); } void cCommExit(void) { dUsbExit(); dHiSpeedExit(); dBtExit(); } UBYTE cCommCheckSysFileType(UBYTE *pName) { UBYTE RtnVal; UBYTE TmpFilename[FILENAME_LENGTH + 1]; RtnVal = FALSE; cCommCpyToUpper(TmpFilename, &pName[1], (UBYTE)(FILENAME_LENGTH + 1)); if ((0 != strstr((PSZ)(TmpFilename), ".RXE")) || (0 != strstr((PSZ)(TmpFilename), ".SYS")) || (0 != strstr((PSZ)(TmpFilename), ".RTM"))) { RtnVal = TRUE; } return(RtnVal); } UWORD cCommInterprete(UBYTE *pInBuf, UBYTE *pOutBuf, UBYTE *pLength, UBYTE CmdBit, UWORD MsgLength) { UWORD ReturnStatus; UBYTE Channel; Channel = CHNumber(CmdBit); if (FALSE == VarsComm.ExtMode[Channel].Status) { switch (((pInBuf[0]) & ~NO_REPLY_BIT)) { case SYSTEM_CMD: { ReturnStatus = cCommInterpreteCmd(pInBuf[1], &(pInBuf[1]), &(pOutBuf[2]), pLength, CmdBit, MsgLength); /* Check if reply is requested */ if ((pInBuf[0]) & NO_REPLY_BIT) { /* Sender has choosen no reply */ *pLength = 0; /* if extended mode then remember the reply bit */ VarsComm.ExtMode[Channel].Type |= NO_REPLY_BIT; } else { /* Check if receiver wants to reply */ if (*pLength) { (*pLength)+= 2; pOutBuf[0] = REPLY_CMD; pOutBuf[1] = pInBuf[1]; } } } break; case DIRECT_CMD: { /* Adjust length to account for cmd type byte */ (*pLength) -= 1; /* If no reply requested, pass NULL output buffer pointer and clear *pLength */ if ((pInBuf[0]) & NO_REPLY_BIT) { pMapCmd->pRCHandler(&(pInBuf[0]), NULL, pLength); } else { pMapCmd->pRCHandler(&(pInBuf[0]), &(pOutBuf[2]), pLength); if (*pLength) { (*pLength) += 2; pOutBuf[0] = REPLY_CMD; pOutBuf[1] = pInBuf[1]; } } } break; case REPLY_CMD: { /* If this is a reply to a direct command opcode, pRCHandler will handle it */ if (pInBuf[1] < NUM_RC_OPCODES) pMapCmd->pRCHandler(&(pInBuf[0]), NULL, pLength); /* No Reply ever required on REPLY_CMD messages */ *pLength = 0; } break; #ifdef __ARMDEBUG__ case DEBUG_CMD: { ReturnStatus = cCommHandleDebug(&(pInBuf[0]), CmdBit, MsgLength); /* Pass everything (incl. message command byte) to function */ /* Check that Debug Command does not expect reply */ ReturnStatus = (0 == ((pInBuf[0]) & NO_REPLY_BIT)); *pLength = 0; } break; #endif default: { /* UNSUPPORTED - don't reply on these messages */ *pLength = 0; } break; } } else { switch (VarsComm.ExtMode[Channel].Type & ~NO_REPLY_BIT) { case SYSTEM_CMD: { ReturnStatus = cCommInterpreteCmd(VarsComm.ExtMode[Channel].Cmd, &(pInBuf[0]), &(pOutBuf[2]), pLength, CmdBit, MsgLength); if ((VarsComm.ExtMode[Channel].Type) & NO_REPLY_BIT) { /* Sender has choosen no reply */ *pLength = 0; } else { /* Check if receiver wants to reply */ if (*pLength) { (*pLength) += 2; pOutBuf[0] = REPLY_CMD; pOutBuf[1] = VarsComm.ExtMode[Channel].Cmd; } } } break; case DIRECT_CMD: { } break; case REPLY_CMD: { } break; default: { } break; } } return(ReturnStatus); } UWORD cCommInterpreteCmd(UBYTE Cmd, UBYTE *pInBuf, UBYTE *pOutBuf, UBYTE *pLength, UBYTE CmdBit, UWORD MsgLength) { ULONG FileLength; UWORD Status; UBYTE Channel; Channel = CHNumber(CmdBit); switch(Cmd) { case OPENWRITE: { FileLength = pInBuf[21]; FileLength += (ULONG)pInBuf[22] << 8; FileLength += (ULONG)pInBuf[23] << 16; FileLength += (ULONG)pInBuf[24] << 24; if(TRUE == cCommCheckSysFileType(&pInBuf[1])) { Status = pMapLoader->pFunc(OPENWRITELINEAR, &pInBuf[1], NULL, &FileLength); } else { Status = pMapLoader->pFunc(OPENWRITE, &pInBuf[1], NULL, &FileLength); } pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[1] = LOADER_HANDLE(Status); *pLength = 2; if ((SUCCESS == LOADER_ERR(Status)) && (CmdBit & USB_CMD_READY)) { dUsbInsertHandle(LOADER_HANDLE(Status)); } } break; case WRITE: { if (FALSE == VarsComm.ExtMode[Channel].Status) { FileLength = *pLength - 3; Status = pMapLoader->pFunc(WRITE, &(pInBuf[1]), &(pInBuf[2]), &FileLength); pOutBuf[2] = (UBYTE)(FileLength); pOutBuf[3] = (UBYTE)(FileLength >> 8); if ((*pLength != MsgLength) && (MsgLength != 0)) { /* This is the beginnig of and extended write command*/ VarsComm.ExtMode[Channel].Cmd = WRITE; VarsComm.ExtMode[Channel].Type = SYSTEM_CMD; VarsComm.ExtMode[Channel].Status = TRUE; VarsComm.ExtMode[Channel].Handle = LOADER_HANDLE(Status); *pLength = 0; } else { /* Normal write */ pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[1] = LOADER_HANDLE(Status); *pLength = 4; } } else { UWORD TmpLen; FileLength = *pLength; Status = pMapLoader->pFunc(WRITE, &(VarsComm.ExtMode[Channel].Handle), &(pInBuf[0]), &FileLength); TmpLen = pOutBuf[3]; TmpLen <<= 8; TmpLen |= pOutBuf[2]; TmpLen += FileLength; pOutBuf[2] = (UBYTE)(TmpLen); pOutBuf[3] = (UBYTE)(TmpLen >> 8); if (MsgLength) { /* Don't answer before complete message has been received */ *pLength = 0; } else { /* Complete msg has been received */ VarsComm.ExtMode[Channel].Status = FALSE; pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[1] = LOADER_HANDLE(Status); *pLength = 4; /* Remember the 2 length bytes */ } } } break; case OPENWRITEDATA: { FileLength = pInBuf[21]; FileLength += (ULONG)pInBuf[22] << 8; FileLength += (ULONG)pInBuf[23] << 16; FileLength += (ULONG)pInBuf[24] << 24; if(TRUE == cCommCheckSysFileType(&pInBuf[1])) { Status = ILLEGALFILENAME; } else { Status = pMapLoader->pFunc(OPENWRITEDATA, &pInBuf[1], NULL, &FileLength); } pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[1] = LOADER_HANDLE(Status); *pLength = 2; if ((SUCCESS == LOADER_ERR(Status)) && (CmdBit & USB_CMD_READY)) { dUsbInsertHandle(LOADER_HANDLE(Status)); } } break; case OPENAPPENDDATA: { Status = pMapLoader->pFunc(OPENAPPENDDATA, &pInBuf[1], NULL, &FileLength); pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[1] = LOADER_HANDLE(Status); pOutBuf[2] = (UBYTE)FileLength; pOutBuf[3] = (UBYTE)(FileLength >> 8); pOutBuf[4] = (UBYTE)(FileLength >> 16); pOutBuf[5] = (UBYTE)(FileLength >> 24); *pLength = 6; if ((SUCCESS == LOADER_ERR(Status)) && (CmdBit & USB_CMD_READY)) { dUsbInsertHandle(LOADER_HANDLE(Status)); } } break; case CLOSE: { if (CmdBit & USB_CMD_READY) { dUsbRemoveHandle(pInBuf[1]); } Status = pMapLoader->pFunc(CLOSE, &(pInBuf[1]), NULL, &FileLength); pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[1] = LOADER_HANDLE(Status); *pLength = 2; } break; case CROPDATAFILE: { Status = pMapLoader->pFunc(CROPDATAFILE, &(pInBuf[1]), NULL, &FileLength); pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[1] = LOADER_HANDLE(Status); *pLength = 2; } break; case OPENREAD: { Status = pMapLoader->pFunc(OPENREAD, &pInBuf[1], NULL, &FileLength); pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[1] = LOADER_HANDLE(Status); pOutBuf[2] = (UBYTE)FileLength; pOutBuf[3] = (UBYTE)(FileLength >> 8); pOutBuf[4] = (UBYTE)(FileLength >> 16); pOutBuf[5] = (UBYTE)(FileLength >> 24); *pLength = 6; if ((SUCCESS == LOADER_ERR(Status)) && (CmdBit & USB_CMD_READY)) { dUsbInsertHandle(LOADER_HANDLE(Status)); } } break; case READ: { ULONG Length; FileLength = pInBuf[3]; FileLength <<= 8; FileLength |= pInBuf[2]; Length = FileLength; /* Here test for channel - USB can only handle a 64 byte return (- wrapping )*/ if (CmdBit & USB_CMD_READY) { if (FileLength > (SIZE_OF_USBBUF - 6)) { /* Buffer cannot hold the requested data adjust to buffer size */ FileLength = (SIZE_OF_USBBUF - 6); } *pLength = FileLength + 4; Status = pMapLoader->pFunc(READ, &pInBuf[1], &pOutBuf[4], &FileLength); pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[1] = LOADER_HANDLE(Status); pOutBuf[2] = (UBYTE)Length; pOutBuf[3] = (UBYTE)(Length >> 8); if (FileLength < Length) { /* End of file is detcted - add up with zeros to the requested msg length */ Length -= FileLength; memset(&(pOutBuf[(FileLength + 4)]),0x00,Length); } } else { /* This is a BT request - BT can handle large packets */ if (FileLength > (SIZE_OF_BTBUF - 6)) { /* Read length exceeds buffer length check for extended read back */ if (SUCCESS == cCommReq(EXTREAD, 0x00, 0x00, 0x00, NULL, &(VarsComm.RetVal))) { /* More data requested than buffer can hold .... go into extended mode */ VarsComm.ExtTx.RemMsgSize = FileLength; VarsComm.ExtTx.SrcHandle = pInBuf[1]; VarsComm.ExtTx.Cmd = READ; *pLength = 0; } else { /* We were not able to go into extended mode bt was busy */ /* for now do not try to reply as it is not possible to */ /* return the requested bytes */ *pLength = 0; } } else { *pLength = FileLength + 4; Status = pMapLoader->pFunc(READ, &pInBuf[1], &pOutBuf[4], &FileLength); pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[1] = LOADER_HANDLE(Status); pOutBuf[2] = (UBYTE)Length; pOutBuf[3] = (UBYTE)(Length >> 8); if (FileLength < Length) { /* End of file is detcted - add up with zeros to the requested msg length */ Length -= FileLength; memset(&(pOutBuf[(FileLength + 4)]),0x00,Length); } } } } break; case DELETE: { Status = pMapLoader->pFunc(DELETE, &pInBuf[1], NULL, &FileLength); pOutBuf[0] = LOADER_ERR_BYTE(Status); cCommCopyFileName(&pOutBuf[1], &pInBuf[1]); *pLength = FILENAME_LENGTH + 1 + 1; /*Filemname + 0 terminator + error byte */ } break; case FINDFIRST: { Status = pMapLoader->pFunc(FINDFIRST, &(pInBuf[1]), &(pOutBuf[2]), &FileLength); pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[1] = LOADER_HANDLE(Status); if (LOADER_ERR_BYTE(SUCCESS) == pOutBuf[0]) { pOutBuf[22] = (UBYTE)FileLength; pOutBuf[23] = (UBYTE)(FileLength >> 8); pOutBuf[24] = (UBYTE)(FileLength >> 16); pOutBuf[25] = (UBYTE)(FileLength >> 24); if (CmdBit & USB_CMD_READY) { dUsbInsertHandle(pOutBuf[1]); } } else { /* ERROR - Fill with zeros */ memset(&(pOutBuf[2]),0x00,24); } *pLength = 26; } break; case FINDNEXT: { Status = pMapLoader->pFunc(FINDNEXT, &(pInBuf[1]), &(pOutBuf[2]), &FileLength); pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[1] = LOADER_HANDLE(Status); if (LOADER_ERR_BYTE(SUCCESS) == pOutBuf[0]) { pOutBuf[22] = (UBYTE)FileLength; pOutBuf[23] = (UBYTE)(FileLength >> 8); pOutBuf[24] = (UBYTE)(FileLength >> 16); pOutBuf[25] = (UBYTE)(FileLength >> 24); } else { /* ERROR - Fill with zeros */ memset(&(pOutBuf[2]),0x00,24); } *pLength = 26; } break; case OPENREADLINEAR: { /* For internal use only */ } break; case VERSIONS: { pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS); pOutBuf[1] = (UBYTE)PROTOCOLVERSION; pOutBuf[2] = (UBYTE)(PROTOCOLVERSION>>8); pOutBuf[3] = (UBYTE)FIRMWAREVERSION; pOutBuf[4] = (UBYTE)(FIRMWAREVERSION>>8); *pLength = 5; } break; case OPENWRITELINEAR: { FileLength = pInBuf[21]; FileLength += (ULONG)pInBuf[22] << 8; FileLength += (ULONG)pInBuf[23] << 16; FileLength += (ULONG)pInBuf[24] << 24; Status = pMapLoader->pFunc(OPENWRITELINEAR, &pInBuf[1], NULL, &FileLength); pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[1] = LOADER_HANDLE(Status); *pLength = 2; if ((SUCCESS == LOADER_ERR(Status)) && (CmdBit & USB_CMD_READY)) { dUsbInsertHandle(LOADER_HANDLE(Status)); } } break; case FINDFIRSTMODULE: { Status = pMapLoader->pFunc(FINDFIRSTMODULE, &pInBuf[1], &pOutBuf[2], &FileLength); pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[1] = 0; if (LOADER_ERR_BYTE(SUCCESS) != pOutBuf[0]) { memset(&pOutBuf[2], 0x00, 30); } *pLength = 32; } break; case FINDNEXTMODULE: { Status = pMapLoader->pFunc(FINDNEXTMODULE, pInBuf, &pOutBuf[2], &FileLength); pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[1] = 0; if (LOADER_ERR_BYTE(SUCCESS) != pOutBuf[0]) { memset(&pOutBuf[2], 0x00, 30); } *pLength = 32; } break; case CLOSEMODHANDLE: { Status = pMapLoader->pFunc(CLOSEMODHANDLE, NULL, NULL, NULL); pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[1] = 0; *pLength = 2; } break; case IOMAPREAD: { ULONG ModuleId; UWORD Length; ModuleId = pInBuf[1]; ModuleId |= (ULONG)pInBuf[2] << 8; ModuleId |= (ULONG)pInBuf[3] << 16; ModuleId |= (ULONG)pInBuf[4] << 24; /* Transfer the Module id */ pOutBuf[1] = pInBuf[1]; pOutBuf[2] = pInBuf[2]; pOutBuf[3] = pInBuf[3]; pOutBuf[4] = pInBuf[4]; /* Transfer the offset into the iomap (pOutBuf[6] is intended...)*/ pOutBuf[5] = pInBuf[5]; pOutBuf[6] = pInBuf[6]; /* Get the read *pLength */ FileLength = pInBuf[8]; FileLength <<= 8; FileLength |= pInBuf[7]; if (CmdBit & USB_CMD_READY) { /* test for USB buffer overrun */ if (FileLength > (SIZE_OF_USBBUF - 9)) { FileLength = SIZE_OF_USBBUF - 9; } } else { /* test for BT buffer overrun */ if (FileLength > (SIZE_OF_BTBUF - 9)) { FileLength = SIZE_OF_BTBUF - 9; } } Length = FileLength; *pLength = Length + 7; Status = pMapLoader->pFunc(IOMAPREAD, (UBYTE *)&ModuleId, &pOutBuf[5], &FileLength); pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[5] = (UBYTE)FileLength; pOutBuf[6] = (UBYTE)(FileLength >> 8); if (Length > FileLength) { Length -= FileLength; memset(&(pOutBuf[FileLength + 7]), 0x00, Length); } } break; case IOMAPWRITE: { ULONG ModuleId; pOutBuf[1] = pInBuf[1]; pOutBuf[2] = pInBuf[2]; pOutBuf[3] = pInBuf[3]; pOutBuf[4] = pInBuf[4]; ModuleId = pInBuf[1]; ModuleId |= (ULONG)pInBuf[2] << 8; ModuleId |= (ULONG)pInBuf[3] << 16; ModuleId |= (ULONG)pInBuf[4] << 24; FileLength = pInBuf[8]; FileLength <<= 8; FileLength |= pInBuf[7]; /* Place offset right before data */ pInBuf[8] = pInBuf[6]; pInBuf[7] = pInBuf[5]; Status = pMapLoader->pFunc(IOMAPWRITE, (UBYTE *)&ModuleId, &pInBuf[7], &FileLength); pOutBuf[0] = LOADER_ERR_BYTE(Status); pOutBuf[5] = (UBYTE)FileLength; pOutBuf[6] = (UBYTE)(FileLength >> 8); *pLength = 7; } break; case BOOTCMD: { UBYTE Tmp; /* The boot command is only allowed by USB - as firmware download can ONLY */ /* be send by USB */ pOutBuf[0] = LOADER_ERR_BYTE(UNDEFINEDERROR); memset(&(pOutBuf[1]), 0, 4); *pLength = 5; if (CmdBit & USB_CMD_READY) { Tmp = 0; while((Tmp < (sizeof(BootString) - 1)) && (BootString[Tmp] == pInBuf[Tmp+1])) { Tmp++; } if (Tmp == (sizeof(BootString) - 1)) { /* Yes valid boot sequence */ pMapDisplay->Flags &= ~DISPLAY_ON; pMapDisplay->Flags |= DISPLAY_REFRESH; pMapIoCtrl->PowerOn = BOOT; pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS); pOutBuf[1] = 'Y'; pOutBuf[2] = 'e'; pOutBuf[3] = 's'; pOutBuf[4] = '\0'; } } } break; case SETBRICKNAME: { UWORD RtnVal; *pLength = 1; /* Update the name in the BT device - reply for this command is send */ /* before command is actually executed */ if (SUCCESS == cCommReq(SETBTNAME, 0, 0, 0, &pInBuf[1], &RtnVal)) { pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS); cCommInsertBtName(IOMapComm.BrickData.Name, &pInBuf[1]); pMapUi->Flags |= UI_REDRAW_STATUS; } else { pOutBuf[0] = LOADER_ERR_BYTE(BTBUSY); } } break; case BTGETADR: { UBYTE Tmp; UBYTE *pAdr; pAdr = (IOMapComm.BrickData.BdAddr); for (Tmp = 0; Tmp < 7; Tmp++) { pOutBuf[Tmp + 1] = pAdr[Tmp]; } pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS); *pLength = 8; } break; case DEVICEINFO: { pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS); /* Brick name */ memcpy(&(pOutBuf[1]), IOMapComm.BrickData.Name, 15); /* BT address */ cCommCopyBdaddr(&(pOutBuf[16]), (IOMapComm.BrickData.BdAddr)); /* Link quality of the 4 possible connected devices */ pOutBuf[23] = IOMapComm.BtConnectTable[0].LinkQuality; pOutBuf[24] = IOMapComm.BtConnectTable[1].LinkQuality; pOutBuf[25] = IOMapComm.BtConnectTable[2].LinkQuality; pOutBuf[26] = IOMapComm.BtConnectTable[3].LinkQuality; /* Free user flash */ memcpy(&(pOutBuf[27]), &(pMapLoader->FreeUserFlash), sizeof(pMapLoader->FreeUserFlash)); /* Set answer length */ *pLength = 31; } break; case DELETEUSERFLASH: { Status = pMapLoader->pFunc(DELETEUSERFLASH, NULL, NULL, NULL); pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS); *pLength = 1; } break; case POLLCMDLEN: { pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS); pOutBuf[1] = pInBuf[1]; /* This is the Buf Number */ if (0 == pInBuf[1]) { /* USB poll buffer */ pOutBuf[2] = ((IOMapComm.UsbPollBuf.InPtr - IOMapComm.UsbPollBuf.OutPtr) & (SIZE_OF_USBBUF - 1)); } else { /* HI speed poll buffer */ pOutBuf[2] = ((IOMapComm.HsInBuf.InPtr - IOMapComm.HsInBuf.OutPtr) & (SIZE_OF_HSBUF - 1)); } *pLength = 3; } break; case POLLCMD: { UBYTE Tmp; UBYTE MaxBufData; pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS); pOutBuf[1] = pInBuf[1]; *pLength = pInBuf[2]; if (CmdBit & USB_CMD_READY) { MaxBufData = (SIZE_OF_USBDATA - 5); /* Substract wrapping */ } else { MaxBufData = (SIZE_OF_BTBUF - 7); /* Substract wrapping + length bytes for BT*/ } if (0x00 == pInBuf[1]) { /* Data from USB poll buffer are requested */ if (*pLength <= MaxBufData) { for (Tmp = 0; ((Tmp < (*pLength)) && (IOMapComm.UsbPollBuf.InPtr != IOMapComm.UsbPollBuf.OutPtr)); Tmp++) { pOutBuf[3 + Tmp] = IOMapComm.UsbPollBuf.Buf[IOMapComm.UsbPollBuf.OutPtr]; IOMapComm.UsbPollBuf.OutPtr = ((IOMapComm.UsbPollBuf.OutPtr) + 1) % SIZE_OF_USBBUF; } pOutBuf[2] = Tmp; /* if end of buffer has been reached fill up with zeros */ memset(&(pOutBuf[Tmp + 3]), 0x00, (*pLength - Tmp)); } else { /* if more data requested than possible to return */ pOutBuf[0] = LOADER_ERR_BYTE(UNDEFINEDERROR); pOutBuf[1] = pInBuf[1]; /* This is buffer number */ pOutBuf[2] = 0; /* no of bytes returned */ *pLength = 0; } } else { /* Data from hi speed buffer are requested */ if (*pLength <= MaxBufData) { for (Tmp = 0; ((Tmp < (*pLength)) && (IOMapComm.HsInBuf.InPtr != IOMapComm.HsInBuf.OutPtr)); Tmp++) { pOutBuf[3 + Tmp] = IOMapComm.HsInBuf.Buf[IOMapComm.HsInBuf.OutPtr]; IOMapComm.HsInBuf.OutPtr = ((IOMapComm.HsInBuf.OutPtr) + 1) % SIZE_OF_USBBUF; } pOutBuf[2] = Tmp; /* if end of buffer has been reached fill up with zeros */ memset(&(pOutBuf[Tmp + 3]), 0x00, (*pLength - Tmp)); } else { /* if more data requested than possible to return */ pOutBuf[0] = LOADER_ERR_BYTE(UNDEFINEDERROR); pOutBuf[1] = pInBuf[1]; /* This is buffer number */ pOutBuf[2] = 0; /* no of bytes returned */ *pLength = 0; } } (*pLength) += 3; /* Add 3 bytes for the status byte, length byte and Buf no */ } break; case BTFACTORYRESET: { UWORD RtnVal; if (CmdBit & USB_CMD_READY) { if (SUCCESS == cCommReq(FACTORYRESET, 0, 0, 0, NULL, &RtnVal)) { /* Request success */ pOutBuf[0] = LOADER_ERR_BYTE(SUCCESS); } else { /* BT request error */ pOutBuf[0] = LOADER_ERR_BYTE(UNDEFINEDERROR); } } else { /* Factory reset request cannot be done by bluetooth */ pOutBuf[0] = LOADER_ERR_BYTE(UNDEFINEDERROR); } *pLength = 1; } break; default: { } break; } return(Status); } UWORD cCommReceivedBtData(void) { UWORD NumberOfBytes; UWORD BytesToGo; UWORD RtnVal; RtnVal = dBtReceivedData(&NumberOfBytes, &BytesToGo); if (TRUE == RtnVal) { /* Everything is fine go on */ if (NumberOfBytes != 0) { /* Copy the bytes into the IOMapBuffer */ memcpy((IOMapComm.BtInBuf.Buf), (VarsComm.BtModuleInBuf.Buf), NumberOfBytes); if (VarsComm.BtState == BT_ARM_CMD_MODE) { /* Call the BC4 command interpreter */ cCommBtCmdInterpreter(); IOMapComm.BtInBuf.InPtr = 0; } else { /* ActiveUpdate has to be idle because BC4 can send stream data even if CMD */ /* mode has been requested - dont try to interprete the data */ /* VarsComm.CmdSwitchCnt != 0 if a transition to Cmd mode is in process */ if ((VarsComm.BtState == BT_ARM_DATA_MODE) && (0 == VarsComm.CmdSwitchCnt)) { /* Move the inptr ahead */ IOMapComm.BtInBuf.InPtr = NumberOfBytes; /* using the outbuf inptr in order to get the number of bytes in the return answer at the right place*/ IOMapComm.BtOutBuf.InPtr = NumberOfBytes; /* call the data stream interpreter */ cCommInterprete(IOMapComm.BtInBuf.Buf, IOMapComm.BtOutBuf.Buf, &(IOMapComm.BtOutBuf.InPtr), (UBYTE) BT_CMD_READY, BytesToGo); /* if there is a reply to be send then send it */ if (IOMapComm.BtOutBuf.InPtr) { dBtSendMsg(IOMapComm.BtOutBuf.Buf, IOMapComm.BtOutBuf.InPtr, IOMapComm.BtOutBuf.InPtr); IOMapComm.BtOutBuf.InPtr = 0; } } } } } return(RtnVal); } void cCommBtCmdInterpreter(void) { /* this function handles all bluecode commands that can be */ /* initiated from the outside, meaning from other devices */ if(cCommBtValidateCmd()) { switch (IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { case MSG_REQUEST_PIN_CODE: { /* Pass the pin request on to cCommReq it'l handle it */ cCommReq(PINREQ, 0x00, 0x00, 0x00, NULL, &(VarsComm.RetVal)); } break; case MSG_REQUEST_CONNECTION: { /* Connect request from the outside */ cCommReq(CONNECTREQ, 0x00, 0x00, 0x00, NULL, &(VarsComm.RetVal)); } break; case MSG_LIST_RESULT: { switch (IOMapComm.BtInBuf.Buf[2]) { case LR_SUCCESS: { } break; case LR_ENTRY_REMOVED: { } break; /* case LR_COULD_NOT_SAVE: case LR_STORE_IS_FULL: case LR_UNKOWN_ADDR: */ default: { pMapUi->Error = (UBYTE)IOMapComm.BtInBuf.Buf[2]; pMapUi->BluetoothState |= BT_ERROR_ATTENTION; } break; } } break; case MSG_CLOSE_CONNECTION_RESULT: { UBYTE ConnNo; for (ConnNo = 0; ConnNo < SIZE_OF_BT_CONNECT_TABLE; ConnNo++) { if (IOMapComm.BtConnectTable[ConnNo].HandleNr == IOMapComm.BtInBuf.Buf[3]) { IOMapComm.BrickData.BtStateStatus &= ~(BT_CONNECTION_0_ENABLE<BluetoothState &= ~BT_STATE_CONNECTED; } pMapUi->Flags |= UI_REDRAW_STATUS; } break; case MSG_PORT_OPEN_RESULT: { if (IOMapComm.BtInBuf.Buf[2] == 1) { IOMapComm.BtConnectTable[0].HandleNr = IOMapComm.BtInBuf.Buf[3]; IOMapComm.BrickData.BtStateStatus |= BT_BRICK_PORT_OPEN; } else { /* There was an error setting up the OpenPort command in BC4 */ IOMapComm.BtConnectTable[0].HandleNr = BLUETOOTH_HANDLE_UNDEFIEND; IOMapComm.BrickData.BtStateStatus &= ~BT_BRICK_PORT_OPEN; } } break; case MSG_CLOSE_PORT_RESULT: { if (IOMapComm.BtInBuf.Buf[2] == 1) { IOMapComm.BtConnectTable[0].HandleNr = BLUETOOTH_HANDLE_UNDEFIEND; IOMapComm.BrickData.BtStateStatus &= ~BT_BRICK_PORT_OPEN; } } break; case MSG_PIN_CODE_ACK: { pMapUi->BluetoothState &= ~BT_PIN_REQUEST; } break; case MSG_DISCOVERABLE_ACK: { if (VarsComm.BtCmdData.ParamOne == 1) { IOMapComm.BrickData.BtStateStatus |= BT_BRICK_VISIBILITY; pMapUi->BluetoothState |= BT_STATE_VISIBLE; } else { IOMapComm.BrickData.BtStateStatus &= ~BT_BRICK_VISIBILITY; pMapUi->BluetoothState &= ~BT_STATE_VISIBLE; } } break; case MSG_RESET_INDICATION: { if ((UPD_RESET != VarsComm.ActiveUpdate) && (UPD_BRICKNAME != VarsComm.ActiveUpdate) && (UPD_FACTORYRESET != VarsComm.ActiveUpdate)) { /* Not intended reset indication - restart the bluecore */ if (VarsComm.ActiveUpdate != UPD_IDLE) { /* Something was ongoing send error message */ *(VarsComm.pRetVal) = (UWORD)ERR_COMM_BUS_ERR; *(VarsComm.pRetVal) |= 0x8000; } SETBtStateIdle; VarsComm.pRetVal = &(VarsComm.RetVal); VarsComm.ActiveUpdate = UPD_RESET; } } break; } } else { /* Receive a message with wrong checkSum ! */ } } void cCommCpyToUpper(UBYTE *pDst, UBYTE *pSrc, UBYTE Length) { UBYTE Tmp; for(Tmp = 0; Tmp < Length; Tmp++) { pDst[Tmp] =(UBYTE)toupper((UWORD)pSrc[Tmp]); } /* The requried length has been copied - now fill with zeros */ for(Tmp = Length; Tmp < (FILENAME_LENGTH + 1); Tmp++) { pDst[Tmp] = '\0'; } } void cCommCopyFileName(UBYTE *pDst, UBYTE *pSrc) { UBYTE Tmp; for(Tmp = 0; Tmp < (FILENAME_LENGTH + 1); Tmp++, pDst++) { if ('\0' != *pSrc) { *pDst = *pSrc; pSrc++; } else { *pDst = '\0'; } } } void cCommSendHiSpeedData(void) { VarsComm.HsModuleOutBuf.OutPtr = 0; for (VarsComm.HsModuleOutBuf.InPtr = 0; VarsComm.HsModuleOutBuf.InPtr < IOMapComm.HsOutBuf.InPtr; VarsComm.HsModuleOutBuf.InPtr++) { VarsComm.HsModuleOutBuf.Buf[VarsComm.HsModuleOutBuf.InPtr] = IOMapComm.HsOutBuf.Buf[IOMapComm.HsOutBuf.OutPtr]; IOMapComm.HsOutBuf.OutPtr++; } dHiSpeedSendData(VarsComm.HsModuleOutBuf.Buf, (VarsComm.HsModuleOutBuf.InPtr - VarsComm.HsModuleOutBuf.OutPtr)); } void cCommReceivedHiSpeedData(void) { UWORD NumberOfBytes; UWORD Tmp; dHiSpeedReceivedData(&NumberOfBytes); if (NumberOfBytes != 0) { for (Tmp = 0; Tmp < NumberOfBytes; Tmp++) { IOMapComm.HsInBuf.Buf[IOMapComm.HsInBuf.InPtr] = VarsComm.HsModuleInBuf.Buf[Tmp]; IOMapComm.HsInBuf.InPtr++; if (IOMapComm.HsInBuf.InPtr > (SIZE_OF_HSBUF - 1)) { IOMapComm.HsInBuf.InPtr = 0; } VarsComm.HsModuleInBuf.Buf[Tmp] = 0; } /* Now new data is available from the HIGH SPEED port ! */ } } UBYTE cCommBtValidateCmd(void) { UWORD CheckSumTmp = 0; UBYTE Tmp, CheckSumHigh, CheckSumLow; for (Tmp = 0; Tmp < (IOMapComm.BtInBuf.Buf[0] - 1);Tmp++) { CheckSumTmp += IOMapComm.BtInBuf.Buf[Tmp]; } CheckSumTmp = (UWORD) (1 + (0xFFFF - CheckSumTmp)); CheckSumHigh = (UBYTE)((CheckSumTmp & 0xFF00)>>8); CheckSumLow = (UBYTE)(CheckSumTmp & 0x00FF); if ((CheckSumHigh == IOMapComm.BtInBuf.Buf[IOMapComm.BtInBuf.Buf[0] - 1]) && (CheckSumLow == IOMapComm.BtInBuf.Buf[IOMapComm.BtInBuf.Buf[0]])) { return(TRUE); } else { return(FALSE); } } void cCommClearStreamStatus(void) { IOMapComm.BtConnectTable[0].StreamStatus = 0; IOMapComm.BtConnectTable[1].StreamStatus = 0; IOMapComm.BtConnectTable[2].StreamStatus = 0; IOMapComm.BtConnectTable[3].StreamStatus = 0; } void cCommUpdateBt(void) { UBYTE Tmp, Tmp2, Handle; Tmp = 0; Tmp2 = 0; switch(VarsComm.ActiveUpdate) { case UPD_RESET: { switch(VarsComm.UpdateState) { case 0: { /* Setup Reset sequence */ pMapUi->BluetoothState = BT_STATE_OFF; VarsComm.UpdateState = 1; } break; case 1: { cCommsBtReset(&(VarsComm.UpdateState)); } break; case 2: { (VarsComm.UpdateState)++; dBtSendBtCmd((UBYTE)MSG_GET_LOCAL_ADDR, 0, 0, NULL, NULL, NULL, NULL); } break; case 3: { if (MSG_GET_LOCAL_ADDR_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { cCommCopyBdaddr((IOMapComm.BrickData.BdAddr), &(IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 1])); dUsbStoreBtAddress( &(IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 1])); dBtSendBtCmd((UBYTE)MSG_GET_FRIENDLY_NAME, 0, 0, NULL, NULL, NULL, NULL); VarsComm.BtAdrStatus = INITIALIZED; (VarsComm.UpdateState)++; } } break; case 4: { if (MSG_GET_FRIENDLY_NAME_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { memcpy(IOMapComm.BrickData.Name, &(IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 1]), SIZE_OF_BRICK_NAME); pMapUi->Flags |= UI_REDRAW_STATUS; IOMapComm.BtDeviceCnt = 0; IOMapComm.BtDeviceNameCnt = 0; dBtSendBtCmd((UBYTE)MSG_DUMP_LIST, 0, 0, NULL, NULL, NULL, NULL); (VarsComm.UpdateState)++; } } break; case 5: { if (MSG_LIST_ITEM == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { cCommCopyBdaddr((IOMapComm.BtDeviceTable[IOMapComm.BtDeviceCnt].BdAddr), &(IOMapComm.BtInBuf.Buf[2])); cCommInsertBtName(IOMapComm.BtDeviceTable[IOMapComm.BtDeviceCnt].Name, &(IOMapComm.BtInBuf.Buf[9])); IOMapComm.BtDeviceTable[IOMapComm.BtDeviceCnt].DeviceStatus = BT_DEVICE_KNOWN; memcpy(IOMapComm.BtDeviceTable[IOMapComm.BtDeviceCnt].ClassOfDevice, &(IOMapComm.BtInBuf.Buf[9+SIZE_OF_BT_NAME]), sizeof(IOMapComm.BtDeviceTable[IOMapComm.BtDeviceCnt].ClassOfDevice)); IOMapComm.BtDeviceCnt++; IOMapComm.BtDeviceNameCnt++; } if (MSG_LIST_DUMP_STOPPED == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { dBtSendBtCmd((UBYTE)MSG_GET_VERSION, 0, 0, NULL, NULL, NULL, NULL); (VarsComm.UpdateState)++; } IOMapComm.BtInBuf.Buf[BT_CMD_BYTE] = 0; } break; case 6: { if (MSG_GET_VERSION_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { IOMapComm.BrickData.BluecoreVersion[0] = IOMapComm.BtInBuf.Buf[3]; IOMapComm.BrickData.BluecoreVersion[1] = IOMapComm.BtInBuf.Buf[2]; /* BtHwStatus indicates cold boot or user interaction */ if (BT_DISABLE == IOMapComm.BrickData.BtHwStatus) { /* This is from brick turning on */ dBtSendBtCmd((UBYTE)MSG_GET_BRICK_STATUSBYTE, 0, 0, NULL, NULL, NULL, NULL); } else { /* this is user interaction setting the brick on */ dBtSendBtCmd((UBYTE)MSG_SET_BRICK_STATUSBYTE, BT_ENABLE, 0, NULL, NULL, NULL, NULL); } (VarsComm.UpdateState)++; pMapUi->Flags |= UI_REDRAW_STATUS; } } break; case 7: { if (MSG_GET_BRICK_STATUSBYTE_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { IOMapComm.BrickData.TimeOutValue = IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 2]; /* Check for brick to be on or off */ if (BT_ENABLE == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 1]) { pMapUi->BluetoothState &= ~BT_STATE_OFF; IOMapComm.BrickData.BtHwStatus = BT_ENABLE; dBtSendBtCmd((UBYTE)MSG_GET_DISCOVERABLE, 0, 0, NULL, NULL, NULL, NULL); (VarsComm.UpdateState)++; } else { SETBtOff; IOMapComm.BrickData.BtHwStatus = BT_ENABLE; SETBtStateIdle; *(VarsComm.pRetVal) = SUCCESS; } } if (MSG_SET_BRICK_STATUSBYTE_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { /* brick to be on*/ pMapUi->BluetoothState &= ~BT_STATE_OFF; IOMapComm.BrickData.BtHwStatus = BT_ENABLE; dBtSendBtCmd((UBYTE)MSG_GET_DISCOVERABLE, 0, 0, NULL, NULL, NULL, NULL); (VarsComm.UpdateState)++; } } break; case 8: { if (MSG_GET_DISCOVERABLE_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { if (IOMapComm.BtInBuf.Buf[2] & 0x01) { IOMapComm.BrickData.BtStateStatus |= BT_BRICK_VISIBILITY; pMapUi->BluetoothState |= BT_STATE_VISIBLE; } else { IOMapComm.BrickData.BtStateStatus &= ~BT_BRICK_VISIBILITY; pMapUi->BluetoothState &= ~BT_STATE_VISIBLE; } dBtSendBtCmd((UBYTE)MSG_OPEN_PORT, 0, 0, NULL, NULL, NULL, NULL); (VarsComm.UpdateState)++; } } break; case 9: { if (MSG_PORT_OPEN_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { if (IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 1] & 0x01) { IOMapComm.BrickData.BtStateStatus |= BT_BRICK_PORT_OPEN; } else { IOMapComm.BrickData.BtStateStatus &= ~BT_BRICK_PORT_OPEN; } SETBtStateIdle; *(VarsComm.pRetVal) = SUCCESS; } } break; } } break; case UPD_FACTORYRESET: { switch(VarsComm.UpdateState) { case 0: { if (BT_STATE_OFF & (pMapUi->BluetoothState)) { /* Bluetooth is off - now start it up */ (VarsComm.UpdateState)++; } else { /* BT is already on - continue */ (VarsComm.UpdateState) += 2; } } break; case 1: { cCommsBtReset(&(VarsComm.UpdateState)); } break; case 2: { cCommsSetCmdMode(&(VarsComm.UpdateState)); } break; case 3: { cCommsDisconnectAll(&(VarsComm.UpdateState)); } break; case 4: { /* Now bc4 is in cmd mode now factory can be sent */ /* Just leave the BC4 in cmd mode */ dBtSendBtCmd((UBYTE)MSG_SET_FACTORY_SETTINGS, 0, 0, NULL, NULL, NULL, NULL); (VarsComm.UpdateState)++; } break; case 5: { if (MSG_SET_FACTORY_SETTINGS_ACK == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { SETBtStateIdle; IOMapComm.BrickData.BtHwStatus = BT_DISABLE; /* Boot BT like cold boot*/ VarsComm.ActiveUpdate = UPD_RESET; } } break; } } break; case UPD_BRICKNAME: { switch(VarsComm.UpdateState) { case 0: { if (BT_STATE_OFF & (pMapUi->BluetoothState)) { /* Bluetooth is off - now start it up */ (VarsComm.UpdateState)++; } else { VarsComm.UpdateState = 2; } } break; case 1: { cCommsBtReset(&(VarsComm.UpdateState)); } break; case 2: { VarsComm.BtUpdateDataConnectNr = 0; if (BT_ARM_DATA_MODE == VarsComm.BtState) { for (Tmp = 0; Tmp < SIZE_OF_BT_CONNECT_TABLE; Tmp++) { if (IOMapComm.BtConnectTable[Tmp].StreamStatus) { VarsComm.BtUpdateDataConnectNr = Tmp | 0x80; } } (VarsComm.UpdateState)++; } else { (VarsComm.UpdateState) += 2; } } break; case 3: { cCommsSetCmdMode(&(VarsComm.UpdateState)); } break; case 4: { /* Brick name has been updated prior to this */ dBtSendBtCmd((UBYTE)MSG_SET_FRIENDLY_NAME, 0, 0, NULL, IOMapComm.BrickData.Name, NULL, NULL); (VarsComm.UpdateState)++; } break; case 5: { if (MSG_SET_FRIENDLY_NAME_ACK == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { /* Set name has been executed */ if (VarsComm.BtUpdateDataConnectNr & 0x80) { dBtSendBtCmd((UBYTE)MSG_OPEN_STREAM, IOMapComm.BtConnectTable[(VarsComm.BtUpdateDataConnectNr & ~0x80)].HandleNr, 0, NULL, NULL, NULL, NULL); (VarsComm.UpdateState)++; } else { if (BT_STATE_OFF & (pMapUi->BluetoothState)) { SETBtOff; } SETBtStateIdle; *(VarsComm.pRetVal) = SUCCESS; } pMapUi->Flags |= UI_REDRAW_STATUS; } } break; case 6: { if (VarsComm.BtBcPinLevel) { IOMapComm.BtConnectTable[(VarsComm.BtUpdateDataConnectNr & ~0x80)].StreamStatus = 1; *(VarsComm.pRetVal) = SUCCESS; SETBtDataState; SETBtStateIdle; } } break; } } break; case UPD_REQCMDMODE: { switch(VarsComm.UpdateState) { case 0: { cCommsSetCmdMode(&(VarsComm.UpdateState)); } break; case 1: { *(VarsComm.pRetVal) = SUCCESS; SETBtStateIdle; } break; } } break; case UPD_OPENSTREAM: { switch(VarsComm.UpdateState) { case 0: { cCommsOpenStream(&(VarsComm.UpdateState)); } break; case 1: { *(VarsComm.pRetVal) = SUCCESS; SETBtStateIdle; } break; } } break; case UPD_SENDFILE: { switch (VarsComm.UpdateState) { case 0: { cCommsOpenStream(&(VarsComm.UpdateState)); } break; case 1: { /* Here we wait for the open stream to succeed*/ if (IOMapComm.BtConnectTable[VarsComm.ExtTx.SlotNo].StreamStatus) { /* Stream has been opened send the openwrite command */ VarsComm.BtModuleOutBuf.Buf[0] = SYSTEM_CMD; VarsComm.BtModuleOutBuf.Buf[1] = OPENWRITE; memcpy((UBYTE*)&(VarsComm.BtModuleOutBuf.Buf[2]),(UBYTE*)VarsComm.ExtTx.FileName, FILENAME_LENGTH + 1); memcpy((UBYTE*)&(VarsComm.BtModuleOutBuf.Buf[22]),(UBYTE*)&(VarsComm.ExtTx.RemFileSize), sizeof(VarsComm.ExtTx.RemFileSize)); dBtSendMsg(VarsComm.BtModuleOutBuf.Buf, 26, 26); VarsComm.ExtTx.Timer = 0; VarsComm.UpdateState = 2; } else { if (VarsComm.ExtTx.Timer >= FILETXTOUT) { *(VarsComm.pRetVal) = FILETX_STREAMERROR; VarsComm.UpdateState = 8; } else { (VarsComm.ExtTx.Timer)++; } } } break; case 2: { if (4 == IOMapComm.BtInBuf.InPtr) { /* Data has been received - examine the answer */ if ((REPLY_CMD == IOMapComm.BtInBuf.Buf[0]) && (OPENWRITE == IOMapComm.BtInBuf.Buf[1])) { /* OpenWrite answer */ if (LOADER_ERR_BYTE(SUCCESS) == IOMapComm.BtInBuf.Buf[2]) { /* save the handle from the other brick */ VarsComm.ExtTx.DstHandle = IOMapComm.BtInBuf.Buf[3]; VarsComm.UpdateState = 3; IOMapComm.BtInBuf.InPtr = 0; } else { /* Open write failiure - terminate file transfer */ *(VarsComm.pRetVal) = IOMapComm.BtInBuf.Buf[2]; VarsComm.UpdateState = 8; } } } if (VarsComm.ExtTx.Timer >= FILETXTOUT) { *(VarsComm.pRetVal) = FILETX_TIMEOUT; VarsComm.UpdateState = 8; } else { (VarsComm.ExtTx.Timer)++; } } break; case 3: /*SENDWRITE:*/ { ULONG Length; UWORD MsgSize; VarsComm.ExtTx.Timer = 0; if (VarsComm.ExtTx.RemFileSize > (MAX_BT_MSG_SIZE - 5)) { /* need to use the maximum size available - approx 64K */ VarsComm.ExtTx.RemMsgSize = (MAX_BT_MSG_SIZE - 5); } else { /* Message can hold the remaining message */ VarsComm.ExtTx.RemMsgSize = VarsComm.ExtTx.RemFileSize; } if (VarsComm.ExtTx.RemMsgSize > (SIZE_OF_BTBUF - 5)) { Length = SIZE_OF_BTBUF - 5; VarsComm.UpdateState = 4; } else { Length = VarsComm.ExtTx.RemMsgSize; VarsComm.UpdateState = 5; } Handle = (UBYTE)(VarsComm.ExtTx.SrcHandle); pMapLoader->pFunc(READ, &Handle, &(VarsComm.BtModuleOutBuf.Buf[3]), &Length); MsgSize = VarsComm.ExtTx.RemMsgSize + 3; VarsComm.BtModuleOutBuf.Buf[0] = SYSTEM_CMD; VarsComm.BtModuleOutBuf.Buf[1] = WRITE; VarsComm.BtModuleOutBuf.Buf[2] = VarsComm.ExtTx.DstHandle; dBtSendMsg(VarsComm.BtModuleOutBuf.Buf, Length + 3, MsgSize); VarsComm.ExtTx.RemMsgSize -= Length; VarsComm.ExtTx.RemFileSize -= Length; } break; case 4: /* CONTINOUSWRITE:*/ { ULONG Length; UWORD Status; if(dBtCheckForTxBuf()) { /* do only send more data if buffer is empty */ VarsComm.ExtTx.Timer = 0; if (VarsComm.ExtTx.RemMsgSize >= SIZE_OF_BTBUF) { Length = SIZE_OF_BTBUF; } else { Length = VarsComm.ExtTx.RemMsgSize; } VarsComm.ExtTx.RemMsgSize -= Length; VarsComm.ExtTx.RemFileSize -= Length; Handle = (UBYTE)(VarsComm.ExtTx.SrcHandle); Status = pMapLoader->pFunc(READ, &Handle, &(VarsComm.BtModuleOutBuf.Buf[0]), &Length); if (Status >= 0x8000) { Length = 0; } dBtSend(VarsComm.BtModuleOutBuf.Buf, Length); if (!(VarsComm.ExtTx.RemMsgSize)) { /* at this point due to large write command acknowledge is expected */ VarsComm.UpdateState = 5; VarsComm.ExtTx.Timer = 0; IOMapComm.BtInBuf.InPtr = 0; } } } break; case 5: /* WRITEACK: */ { if (6 == IOMapComm.BtInBuf.InPtr) { if ((WRITE == IOMapComm.BtInBuf.Buf[1]) && (REPLY_CMD == IOMapComm.BtInBuf.Buf[0]) && (VarsComm.ExtTx.DstHandle == IOMapComm.BtInBuf.Buf[3])) { /* Ok the the return reply is for me - was it ok? */ if (LOADER_ERR_BYTE(SUCCESS) == IOMapComm.BtInBuf.Buf[2]) { /* Ok send next write*/ if (VarsComm.ExtTx.RemFileSize) { VarsComm.UpdateState = 3; } else { VarsComm.UpdateState = 6; } IOMapComm.BtInBuf.InPtr = 0; } } } if (VarsComm.ExtTx.Timer >= FILETXTOUT) { *(VarsComm.pRetVal) = FILETX_TIMEOUT; VarsComm.UpdateState = 8; } else { (VarsComm.ExtTx.Timer)++; } } break; case 6: /*TERMINATESEND: */ { /* Stream still open close the receiver handle */ VarsComm.BtModuleOutBuf.Buf[0] = SYSTEM_CMD; VarsComm.BtModuleOutBuf.Buf[1] = CLOSE; VarsComm.BtModuleOutBuf.Buf[2] = VarsComm.ExtTx.DstHandle; dBtSendMsg(VarsComm.BtModuleOutBuf.Buf, 3, 3); VarsComm.ExtTx.Timer = 0; VarsComm.UpdateState = 7; } break; case 7: /* TERMINATEACK:*/ { if (4 == IOMapComm.BtInBuf.InPtr) { if ((CLOSE == IOMapComm.BtInBuf.Buf[1]) && (REPLY_CMD == IOMapComm.BtInBuf.Buf[0]) && (VarsComm.ExtTx.DstHandle == IOMapComm.BtInBuf.Buf[3])) { if (LOADER_ERR_BYTE(SUCCESS) == IOMapComm.BtInBuf.Buf[2]) { *(VarsComm.pRetVal) = SUCCESS; VarsComm.UpdateState = 8; } else { *(VarsComm.pRetVal) = FILETX_CLOSEERROR; VarsComm.UpdateState = 8; } IOMapComm.BtInBuf.InPtr = 0; } } if (VarsComm.ExtTx.Timer >= FILETXTOUT) { *(VarsComm.pRetVal) = FILETX_TIMEOUT; VarsComm.UpdateState = 8; } else { (VarsComm.ExtTx.Timer)++; } } break; case 8: { UBYTE Handle; Handle = (UBYTE)(VarsComm.ExtTx.SrcHandle); pMapLoader->pFunc(CLOSE, &Handle, NULL, NULL); (VarsComm.UpdateState)++; } break; case 9: { cCommsSetCmdMode(&(VarsComm.UpdateState)); } break; case 10: { SETBtStateIdle; } break; } } break; case UPD_EXTREAD: { switch (VarsComm.UpdateState) { case 0: { ULONG MsgLength; UWORD Status; MsgLength = (SIZE_OF_BTBUF - 8); Handle =(UBYTE)(VarsComm.ExtTx.SrcHandle); Status = pMapLoader->pFunc(READ, &Handle, &(VarsComm.BtModuleOutBuf.Buf[6]), &MsgLength); VarsComm.BtModuleOutBuf.Buf[0] = (UBYTE) (REPLY_CMD); VarsComm.BtModuleOutBuf.Buf[1] = (UBYTE) (VarsComm.ExtTx.Cmd); VarsComm.BtModuleOutBuf.Buf[2] = LOADER_ERR_BYTE(Status); VarsComm.BtModuleOutBuf.Buf[3] = LOADER_HANDLE(Status); VarsComm.BtModuleOutBuf.Buf[4] = (UBYTE)VarsComm.ExtTx.RemMsgSize; VarsComm.BtModuleOutBuf.Buf[5] = (UBYTE)(VarsComm.ExtTx.RemMsgSize >> 8); dBtSendMsg(VarsComm.BtModuleOutBuf.Buf, (UBYTE)(SIZE_OF_BTBUF - 2), (VarsComm.ExtTx.RemMsgSize + 6)); VarsComm.ExtTx.RemMsgSize -= (SIZE_OF_BTBUF - 8); VarsComm.UpdateState = 1; } break; case 1: { ULONG Length; if(dBtCheckForTxBuf()) { if (VarsComm.ExtTx.RemMsgSize > (SIZE_OF_BTBUF)) { /* Send max number of bytes */ VarsComm.ExtTx.RemMsgSize -= SIZE_OF_BTBUF; Length = SIZE_OF_BTBUF; } else { /* Buffer can hold the last part of the requested data */ Length = VarsComm.ExtTx.RemMsgSize; VarsComm.ExtTx.RemMsgSize = 0; *(VarsComm.pRetVal) = SUCCESS; SETBtStateIdle; } Handle =(UBYTE)(VarsComm.ExtTx.SrcHandle); pMapLoader->pFunc(READ, &Handle, (VarsComm.BtModuleOutBuf.Buf), &Length); dBtSend(VarsComm.BtModuleOutBuf.Buf, Length); } } break; } } break; case UPD_SEARCH: { switch (VarsComm.UpdateState) { case 0: { cCommsSetCmdMode(&(VarsComm.UpdateState)); } break; case 1: { cCommsCloseConn0(&(VarsComm.UpdateState)); } break; case 2: { /* Now ready for the actual search */ for (Tmp = 0; Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++) { if ((IOMapComm.BtDeviceTable[Tmp].DeviceStatus) & BT_DEVICE_KNOWN) { (IOMapComm.BtDeviceTable[Tmp].DeviceStatus) = (BT_DEVICE_AWAY | BT_DEVICE_KNOWN); } else { IOMapComm.BtDeviceTable[Tmp].DeviceStatus = BT_DEVICE_EMPTY; } } dBtSendBtCmd((UBYTE)MSG_BEGIN_INQUIRY, (UBYTE)BT_DEFAULT_INQUIRY_MAX, BT_DEFAULT_INQUIRY_TIMEOUT_LO, NULL, NULL, NULL, NULL); (VarsComm.UpdateState)++; } break; case 3: { /* this is the stop search flag */ /* - meaning that the search should be stopped */ if (1 == VarsComm.BtCmdData.ParamOne) { dBtSendBtCmd((UBYTE)MSG_CANCEL_INQUIRY, 0, 0, NULL, NULL, NULL, NULL); (VarsComm.UpdateState) = 7; } else { /* when inquiry is running there is 2 alloable return answers */ /* either inquiry result or inquiry stopped */ if (MSG_INQUIRY_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { dBtResetTimeOut(); /* reset the cmd timeout */ Tmp = cCommInsertDevice(&(IOMapComm.BtInBuf.Buf[2]), &(IOMapComm.BtInBuf.Buf[9]), &(IOMapComm.BtInBuf.Buf[25]), (UBYTE) BT_DEVICE_UNKNOWN, &Tmp2); if (SIZE_OF_BT_DEVICE_TABLE > Tmp) { /* Remember to check for already existing entry ....*/ if (DEVICE_VERIFIED != Tmp2) { (IOMapComm.BtDeviceTable[Tmp].DeviceStatus) &= ~BT_DEVICE_AWAY; IOMapComm.BtDeviceCnt++; } } else { /* We will send a stop inquiry cmd as the table is full! */ dBtSendBtCmd((UBYTE)MSG_CANCEL_INQUIRY, 0, 0, NULL, NULL, NULL, NULL); } } if (MSG_INQUIRY_STOPPED == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { VarsComm.BtDeviceIndex = 0; /* Start looking for found devices at index 0 */ VarsComm.LookUpCnt = 0; /* how many times should we try to ask for the name */ (VarsComm.UpdateState)++; } } IOMapComm.BtInBuf.Buf[BT_CMD_BYTE] = 0; } break; case 4: { /* this is the stop search flag */ /* - meaning that the search should be stopped */ if (1 == VarsComm.BtCmdData.ParamOne) { (VarsComm.UpdateState) = 8; } else { /* Needs to run through the hole list as found devices can be placed anywhere */ /* in the table */ for (Tmp = (VarsComm.BtDeviceIndex); Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++) { if ((BT_DEVICE_UNKNOWN == IOMapComm.BtDeviceTable[Tmp].DeviceStatus) || (BT_DEVICE_KNOWN == IOMapComm.BtDeviceTable[Tmp].DeviceStatus)) { VarsComm.BtDeviceIndex = (Tmp + 1); (VarsComm.UpdateState)++; dBtSendBtCmd((UBYTE)MSG_LOOKUP_NAME, 0, 0, (IOMapComm.BtDeviceTable[Tmp].BdAddr), NULL, NULL, NULL); break; } } if (SIZE_OF_BT_DEVICE_TABLE == Tmp) { (VarsComm.LookUpCnt)++; if (((VarsComm.LookUpCnt) < LOOKUPNO) && ((IOMapComm.BtDeviceNameCnt) != (IOMapComm.BtDeviceCnt))) { VarsComm.BtDeviceIndex = 0; } else { // all done SETBtStateIdle; *(VarsComm.pRetVal) = SUCCESS; } } } } break; case 5: { if (MSG_LOOKUP_NAME_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { Tmp2 = FALSE; /* Tmp2 used to indicate name change */ (IOMapComm.BtDeviceNameCnt)++; /* Try look the most obvious place in the device table */ Tmp = VarsComm.BtDeviceIndex - 1; if (TRUE != cCommCheckBdaddr((IOMapComm.BtDeviceTable[Tmp].BdAddr), &(IOMapComm.BtInBuf.Buf[2]))) { /* there was no match - now look the complete table */ for (Tmp = 0; Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++) { if (TRUE == cCommCheckBdaddr((IOMapComm.BtDeviceTable[Tmp].BdAddr), &(IOMapComm.BtInBuf.Buf[2]))) { break; } } } if (Tmp < SIZE_OF_BT_DEVICE_TABLE) { /* Valid index with matching device adress found */ if (0 == IOMapComm.BtInBuf.Buf[9]) { if (0 == IOMapComm.BtDeviceTable[Tmp].Name[0]) { /* No valid name recvd and no valid name in table -> insert "No Name" */ cCommInsertBtName(IOMapComm.BtDeviceTable[Tmp].Name, (UBYTE*)NoName); } } else { /* Valid Name - check it against the one allready stored in the device table */ /* if it differs then update */ if (0 != strcmp((char const*)IOMapComm.BtDeviceTable[Tmp].Name, (char const*)&(IOMapComm.BtInBuf.Buf[9]))) { cCommInsertBtName(IOMapComm.BtDeviceTable[Tmp].Name, &(IOMapComm.BtInBuf.Buf[9])); Tmp2 = TRUE; } } if ((BT_DEVICE_KNOWN == (IOMapComm.BtDeviceTable[Tmp].DeviceStatus)) && (TRUE == Tmp2)) { dBtSendBtCmd((UBYTE)MSG_ADD_DEVICE, 0, 0, (IOMapComm.BtDeviceTable[Tmp].BdAddr), (IOMapComm.BtDeviceTable[Tmp].Name), (IOMapComm.BtDeviceTable[Tmp].ClassOfDevice), NULL); (VarsComm.UpdateState)++; } else { (VarsComm.UpdateState)--; } } /* Update devicestatus (name found) so it doesn't look up the name anymore */ IOMapComm.BtDeviceTable[Tmp].DeviceStatus |= BT_DEVICE_NAME; } if (MSG_LOOKUP_NAME_FAILURE == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { if ((LOOKUPNO - 1) == VarsComm.LookUpCnt) { /* This is the last time we ask this device -> we will not get a valid name */ /* Try look the most obvious place in the device table */ Tmp = VarsComm.BtDeviceIndex - 1; if (TRUE != cCommCheckBdaddr((IOMapComm.BtDeviceTable[Tmp].BdAddr), &(IOMapComm.BtInBuf.Buf[2]))) { for (Tmp = 0; Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++) { if (TRUE == cCommCheckBdaddr((IOMapComm.BtDeviceTable[Tmp].BdAddr), &(IOMapComm.BtInBuf.Buf[2]))) { break; } } if ((Tmp < SIZE_OF_BT_DEVICE_TABLE) && (BT_DEVICE_UNKNOWN == (IOMapComm.BtDeviceTable[Tmp].DeviceStatus))) { cCommInsertBtName(IOMapComm.BtDeviceTable[Tmp].Name, (UBYTE*) NoName); } } (IOMapComm.BtDeviceNameCnt)++; } (VarsComm.UpdateState)--; } IOMapComm.BtInBuf.Buf[BT_CMD_BYTE] = 0; } break; case 6: { /* Waiting for reply on add device command - List result */ if (MSG_LIST_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { if (LR_SUCCESS == IOMapComm.BtInBuf.Buf[2]) { /* Return and go through the list*/ (VarsComm.UpdateState) -= 2; } else { pMapUi->Error = (UBYTE)IOMapComm.BtInBuf.Buf[2]; pMapUi->BluetoothState |= BT_ERROR_ATTENTION; } } } break; case 7: { /* here because search has been stopped by user during inquiry */ if (MSG_INQUIRY_STOPPED == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { /* table should be cleared as no names hes been inquired */ for (Tmp = 0; Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++) { if ((IOMapComm.BtDeviceTable[Tmp].DeviceStatus) & BT_DEVICE_KNOWN) { (IOMapComm.BtDeviceTable[Tmp].DeviceStatus) = BT_DEVICE_KNOWN; } else { (IOMapComm.BtDeviceTable[Tmp].DeviceStatus) = BT_DEVICE_EMPTY; } IOMapComm.BtDeviceCnt = 0; IOMapComm.BtDeviceNameCnt = 0; } SETBtStateIdle; *(VarsComm.pRetVal) = SUCCESS; } } break; case 8: { for (Tmp = (VarsComm.BtDeviceIndex); Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++) { if (BT_DEVICE_UNKNOWN == IOMapComm.BtDeviceTable[Tmp].DeviceStatus) { IOMapComm.BtDeviceTable[Tmp].DeviceStatus = BT_DEVICE_EMPTY; } } SETBtStateIdle; *(VarsComm.pRetVal) = SUCCESS; } break; } } break; case UPD_CONNECTREQ: { switch (VarsComm.UpdateState) { case 0: { dBtSendBtCmd((UBYTE)MSG_ACCEPT_CONNECTION, 1, 0, NULL, NULL, NULL, NULL); cCommCopyBdaddr((IOMapComm.BtConnectTable[0].BdAddr), &(IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 1])); (VarsComm.UpdateState)++; } break; case 1: { if (MSG_CONNECT_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { /* Check for successfull connection */ if (1 == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 1]) { /* Save the handle number and look up the name of the master */ IOMapComm.BtConnectTable[0].HandleNr = IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 2]; pMapUi->BluetoothState |= BT_STATE_CONNECTED; dBtSendBtCmd((UBYTE)MSG_LOOKUP_NAME, 0, 0, (IOMapComm.BtConnectTable[0].BdAddr), NULL, NULL, NULL); (VarsComm.UpdateState)++; } else { /* Unsuccessful connection */ SETBtStateIdle; *(VarsComm.pRetVal) = BTCONNECTFAIL; } } } break; case 2: { /* a close connection can happen during connection sequence - if this */ /* occurs for connection 0 then abort the rest of the sequence - OxFF */ /* is unused handle */ if ((MSG_CLOSE_CONNECTION_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) && (0xFF == IOMapComm.BtConnectTable[0].HandleNr)) { SETBtStateIdle; *(VarsComm.pRetVal) = BTCONNECTFAIL; } else { if (MSG_LOOKUP_NAME_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { Tmp = cCommInsertDevice(&(IOMapComm.BtInBuf.Buf[2]), &(IOMapComm.BtInBuf.Buf[9]), &(IOMapComm.BtInBuf.Buf[25]), (UBYTE) BT_DEVICE_KNOWN, &Tmp2); if (SIZE_OF_BT_DEVICE_TABLE > Tmp) { /* entry has been added or is allready existing in the devicetable */ cCommInsertBtName(IOMapComm.BtConnectTable[0].Name, &(IOMapComm.BtInBuf.Buf[9])); cCommCopyBdaddr((IOMapComm.BtConnectTable[0].BdAddr), &(IOMapComm.BtInBuf.Buf[2])); memcpy(IOMapComm.BtConnectTable[0].ClassOfDevice, IOMapComm.BtDeviceTable[Tmp].ClassOfDevice, SIZE_OF_CLASS_OF_DEVICE); dBtSendBtCmd((UBYTE)MSG_ADD_DEVICE, 0, 0, (IOMapComm.BtDeviceTable[Tmp].BdAddr), (IOMapComm.BtDeviceTable[Tmp].Name), (IOMapComm.BtDeviceTable[Tmp].ClassOfDevice), NULL); (VarsComm.UpdateState)++; } else { /* no room in the devicetable -> reject the request. Param2 is index in connect table */ dBtSendBtCmd((UBYTE)MSG_CLOSE_CONNECTION, IOMapComm.BtConnectTable[0].HandleNr, 0, NULL, NULL, NULL, NULL); SETBtStateIdle; *(VarsComm.pRetVal) = BTCONNECTFAIL; } } if (MSG_LOOKUP_NAME_FAILURE == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { /* not able to get the name - disconnect*/ dBtSendBtCmd((UBYTE)MSG_CLOSE_CONNECTION, IOMapComm.BtConnectTable[0].HandleNr, 0, NULL, NULL, NULL, NULL); *(VarsComm.pRetVal) = BTCONNECTFAIL; SETBtStateIdle; } } } break; case 3: { if (MSG_LIST_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { if (LR_SUCCESS == IOMapComm.BtInBuf.Buf[2]) { /* All success - open stream (Data mode) */ dBtSendBtCmd((UBYTE)MSG_OPEN_STREAM, IOMapComm.BtConnectTable[0].HandleNr, 0, NULL, NULL, NULL, NULL); (VarsComm.UpdateState)++; } else { /* no room in the BC4 -> reject the request */ dBtSendBtCmd((UBYTE)MSG_CLOSE_CONNECTION, IOMapComm.BtConnectTable[0].HandleNr, 0, NULL, NULL, NULL, NULL); *(VarsComm.pRetVal) = BTCONNECTFAIL; SETBtStateIdle; } } } break; case 4: { if (VarsComm.BtBcPinLevel) { IOMapComm.BtConnectTable[0].StreamStatus = 1; *(VarsComm.pRetVal) = SUCCESS; SETBtDataState; SETBtStateIdle; } } break; } } break; case UPD_CONNECT: { switch (VarsComm.UpdateState) { case 0: { cCommsSetCmdMode(&(VarsComm.UpdateState)); } break; case 1: { cCommsCloseConn0(&(VarsComm.UpdateState)); } break; case 2: { dBtSendBtCmd((UBYTE)MSG_CONNECT, 0, 0, IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].BdAddr, NULL, NULL, NULL); (VarsComm.UpdateState)++; } break; case 3: { if (MSG_CONNECT_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { if (IOMapComm.BtInBuf.Buf[2] == 1) { IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].HandleNr = IOMapComm.BtInBuf.Buf[3]; pMapUi->BluetoothState |= BT_STATE_CONNECTED; //Now we need to copy the data to the connectiontable memcpy((IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].BdAddr), (IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].BdAddr), SIZE_OF_BDADDR); cCommInsertBtName(IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].Name, IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].Name); memcpy((IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].ClassOfDevice), (IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].ClassOfDevice), SIZE_OF_CLASS_OF_DEVICE); IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].DeviceStatus = BT_DEVICE_KNOWN; if (VarsComm.BtCmdData.ParamTwo == 1) { IOMapComm.BrickData.BtStateStatus |= BT_CONNECTION_1_ENABLE; } else { if (VarsComm.BtCmdData.ParamTwo == 2) { IOMapComm.BrickData.BtStateStatus |= BT_CONNECTION_2_ENABLE; } else { if (VarsComm.BtCmdData.ParamTwo == 3) { IOMapComm.BrickData.BtStateStatus |= BT_CONNECTION_3_ENABLE; } } } dBtSendBtCmd((UBYTE)MSG_ADD_DEVICE, 0, 0, (IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].BdAddr), (IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].Name), (IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].ClassOfDevice), NULL); (VarsComm.UpdateState)+=3; /* skip the pin code part */ } else { /* Connect request denied */ *(VarsComm.pRetVal) = BTCONNECTFAIL; SETBtStateIdle; } } if (MSG_REQUEST_PIN_CODE == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { *(VarsComm.pRetVal) = REQPIN; VarsComm.pValidPinCode = NULL; (VarsComm.UpdateState)++; } } break; case 4: { if (NULL != VarsComm.pValidPinCode) { memcpy((IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].PinCode), VarsComm.pValidPinCode, SIZE_OF_BT_PINCODE); dBtSendBtCmd((UBYTE)MSG_PIN_CODE, 0, 0, IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].BdAddr, NULL, NULL, (VarsComm.pValidPinCode)); (VarsComm.UpdateState)++; } if (MSG_CONNECT_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { /* if no pin code has been accepted then timeout indicated */ /* by connect failiure - it can only be failiure here */ *(VarsComm.pRetVal) = BTCONNECTFAIL; SETBtStateIdle; } } break; case 5: { if (MSG_CONNECT_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { /* Connect failiure can happen at any time */ *(VarsComm.pRetVal) = BTCONNECTFAIL; SETBtStateIdle; } if (MSG_PIN_CODE_ACK == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { /* return back and wait for connect ack */ (VarsComm.UpdateState) = 3; } } break; case 6: { if (MSG_LIST_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { *(VarsComm.pRetVal) = SUCCESS; SETBtStateIdle; } } break; } } break; case UPD_DISCONNECT: { switch (VarsComm.UpdateState) { case 0: { cCommsSetCmdMode(&(VarsComm.UpdateState)); } break; case 1: { if (BLUETOOTH_HANDLE_UNDEFIEND != IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamOne].HandleNr) { VarsComm.BtCmdData.ParamOne = IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamOne].HandleNr; dBtSendBtCmd((UBYTE)MSG_CLOSE_CONNECTION, VarsComm.BtCmdData.ParamOne, 0, NULL, NULL, NULL, NULL); (VarsComm.UpdateState)++; } else { *(VarsComm.pRetVal) = SUCCESS; SETBtStateIdle; } } break; case 2: { /* look for right message and right handle */ if ((MSG_CLOSE_CONNECTION_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) && (VarsComm.BtCmdData.ParamOne == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE + 2])) { *(VarsComm.pRetVal) = SUCCESS; SETBtStateIdle; } } break; } } break; case UPD_DISCONNECTALL: { switch (VarsComm.UpdateState) { case 0: { cCommsSetCmdMode(&(VarsComm.UpdateState)); } break; case 1: { cCommsDisconnectAll(&(VarsComm.UpdateState)); } break; case 2: { *(VarsComm.pRetVal) = SUCCESS; SETBtStateIdle; } break; } } break; case UPD_REMOVEDEVICE: { switch (VarsComm.UpdateState) { case 0: { cCommsSetCmdMode(&(VarsComm.UpdateState)); } break; case 1: { cCommsCloseConn0(&(VarsComm.UpdateState)); } break; case 2: { dBtSendBtCmd((UBYTE)MSG_REMOVE_DEVICE, 0, 0, IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].BdAddr, NULL, NULL, NULL); IOMapComm.BtDeviceTable[VarsComm.BtCmdData.ParamOne].DeviceStatus = BT_DEVICE_EMPTY; (VarsComm.UpdateState)++; } break; case 3: { if (MSG_LIST_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { *(VarsComm.pRetVal) = SUCCESS; SETBtStateIdle; } } break; } } break; case UPD_PINREQ: { /* This is pincode request from the outside - always conn 0*/ switch (VarsComm.UpdateState) { case 0: { if (NULL != VarsComm.pValidPinCode) { memcpy((IOMapComm.BtConnectTable[0].PinCode), VarsComm.pValidPinCode, SIZE_OF_BT_PINCODE); dBtSendBtCmd((UBYTE)MSG_PIN_CODE, 0, 0, (IOMapComm.BtConnectTable[0].BdAddr), NULL, NULL, (VarsComm.pValidPinCode)); (VarsComm.UpdateState)++; } } break; case 1: { if (MSG_PIN_CODE_ACK == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { SETBtStateIdle; } } break; } } break; case UPD_VISIBILITY: { switch (VarsComm.UpdateState) { case 0: { cCommsSetCmdMode(&(VarsComm.UpdateState)); } break; case 1: { cCommsCloseConn0(&(VarsComm.UpdateState)); } break; case 2: { dBtSendBtCmd((UBYTE)MSG_SET_DISCOVERABLE, VarsComm.BtCmdData.ParamOne, 0, NULL, NULL, NULL, NULL); (VarsComm.UpdateState)++; } break; case 3: { if (MSG_DISCOVERABLE_ACK == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { if (VarsComm.BtCmdData.ParamOne == 1) { IOMapComm.BrickData.BtStateStatus |= BT_BRICK_VISIBILITY; pMapUi->BluetoothState |= BT_STATE_VISIBLE; } else { IOMapComm.BrickData.BtStateStatus &= ~BT_BRICK_VISIBILITY; pMapUi->BluetoothState &= ~BT_STATE_VISIBLE; } *(VarsComm.pRetVal) = SUCCESS; SETBtStateIdle; } } break; } } break; case UPD_OFF: { switch (VarsComm.UpdateState) { case 0: { cCommsSetCmdMode(&(VarsComm.UpdateState)); } break; case 1: { cCommsDisconnectAll(&(VarsComm.UpdateState)); } break; case 2: { dBtSendBtCmd((UBYTE)MSG_SET_BRICK_STATUSBYTE, BT_DISABLE, 0, NULL, NULL, NULL, NULL); (VarsComm.UpdateState)++; } break; case 3: { if (MSG_SET_BRICK_STATUSBYTE_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { if (IOMapComm.BtInBuf.Buf[2] == LR_SUCCESS) { SETBtOff; pMapUi->BluetoothState = BT_STATE_OFF; pMapUi->Flags |= UI_REDRAW_STATUS; } *(VarsComm.pRetVal) = SUCCESS; SETBtStateIdle; } } break; } } break; case UPD_SENDDATA: { switch (VarsComm.UpdateState) { case 0: { if (1 == IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].StreamStatus) { /* Stream is allready open for the requested channel */ (VarsComm.UpdateState) += 2; } else { /* Stream not open - try open it*/ (VarsComm.UpdateState)++; } } break; case 1: { cCommsOpenStream(&(VarsComm.UpdateState)); } break; case 2: { /* Stream is now opened now send the data */ IOMapComm.BtInBuf.Buf[0] = 0; dBtSendMsg((VarsComm.BtModuleOutBuf.Buf), VarsComm.BtCmdData.ParamOne, (UWORD)(VarsComm.BtCmdData.ParamOne)); (VarsComm.UpdateState)++; } break; case 3: { if(dBtCheckForTxBuf()) { if (VarsComm.BtCmdData.ParamThree) { VarsComm.ExtTx.Timer = 0; (VarsComm.UpdateState)++; } else { *(VarsComm.pRetVal) = SUCCESS; SETBtStateIdle; } } } break; case 4: { if (0x02 == IOMapComm.BtInBuf.Buf[0]) { /* a reply has been received now release the send sequence */ *(VarsComm.pRetVal) = SUCCESS; SETBtStateIdle; } else { if (++VarsComm.ExtTx.Timer > BTSTREAMTOUT) { *(VarsComm.pRetVal) = BTTIMEOUT; SETBtStateIdle; } } } break; } } break; default: { /* This is idle */ VarsComm.UpdateState = 0; } break; } } UWORD cCommCopyBdaddr(UBYTE *pDst, UBYTE *pSrc) { memcpy(pDst, pSrc, SIZE_OF_BDADDR); return((UWORD) SIZE_OF_BDADDR); } UWORD cCommCheckBdaddr(UBYTE *pAdr, UBYTE *pSrc) { UWORD RetVal; RetVal = FALSE; if (0 == memcmp((UBYTE*)pAdr, pSrc, SIZE_OF_BDADDR)) { RetVal = TRUE; } return(RetVal); } UWORD cCommInsertBtName(UBYTE *pDst, UBYTE *pSrc) { UBYTE Cnt; Cnt = 0; /* Complete brick name */ while ((pSrc[Cnt]) && (Cnt < (SIZE_OF_BT_NAME - 1))) { pDst[Cnt] = pSrc[Cnt]; Cnt++; } /* Fill remaining up with zeros */ while (Cnt < SIZE_OF_BT_NAME) { pDst[Cnt] = 0; Cnt++; } return((UWORD)SIZE_OF_BT_NAME); } UWORD cCommInsertDevice(UBYTE *pBdaddr, UBYTE *pName, UBYTE *pCod, UBYTE DeviceStatus, UBYTE *pAddInfo) { UWORD Tmp; UWORD RtnVal; RtnVal = FALSE; *pAddInfo = DEVICE_VERIFIED; for (Tmp = 0; Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++) { if ((TRUE == cCommCheckBdaddr((IOMapComm.BtDeviceTable[Tmp].BdAddr), pBdaddr)) && (IOMapComm.BtDeviceTable[Tmp].DeviceStatus != BT_DEVICE_EMPTY)) { if ((IOMapComm.BtDeviceTable[Tmp].DeviceStatus) & BT_DEVICE_AWAY) { *pAddInfo = DEVICE_UPDATED; (IOMapComm.BtDeviceTable[Tmp].DeviceStatus) &= ~BT_DEVICE_AWAY; } if (BT_DEVICE_UNKNOWN == IOMapComm.BtDeviceTable[Tmp].DeviceStatus) { /* Former unknown adresses can be upgraded - downgrading is not possible */ IOMapComm.BtDeviceTable[Tmp].DeviceStatus = DeviceStatus; } if (pCod != NULL) { /* Class of device can also upgraded - never downgraded to 0 */ memcpy(&(IOMapComm.BtDeviceTable[Tmp].ClassOfDevice), pCod, SIZE_OF_CLASS_OF_DEVICE); } if ((*pName) != 0) { /* Only upgrade name if name is received */ cCommInsertBtName(IOMapComm.BtDeviceTable[Tmp].Name, pName); } RtnVal = TRUE; /* Break out - entry can only be found once */ break; } } if (FALSE == RtnVal) { for (Tmp = 0; Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++) { if (IOMapComm.BtDeviceTable[Tmp].DeviceStatus == BT_DEVICE_EMPTY) { *pAddInfo = DEVICE_INSERTED; IOMapComm.BtDeviceTable[Tmp].DeviceStatus = DeviceStatus; cCommCopyBdaddr((IOMapComm.BtDeviceTable[Tmp].BdAddr), pBdaddr); cCommInsertBtName(IOMapComm.BtDeviceTable[Tmp].Name, pName); if (NULL != pCod) { memcpy((IOMapComm.BtDeviceTable[Tmp].ClassOfDevice), pCod, SIZE_OF_CLASS_OF_DEVICE); } else { memset((IOMapComm.BtDeviceTable[Tmp].ClassOfDevice), 0, SIZE_OF_CLASS_OF_DEVICE); } RtnVal = TRUE; break; } } } /* Function returns SIZE_OF_BT_DEVICE_TABLE if device is not in the list */ return(Tmp); } void cCommsSetCmdMode(UBYTE *pNextState) { switch(VarsComm.CmdSwitchCnt) { case 0: { if (BT_ARM_CMD_MODE != VarsComm.BtState) { cCommClearStreamStatus(); VarsComm.BtCmdModeWaitCnt = 0; VarsComm.CmdSwitchCnt++; } else { /* allready in CMD mode - Exit */ VarsComm.CmdSwitchCnt = 0; (*pNextState)++; } } break; case 1: { /* stream status has been cleared now wait until buffers has been emptied */ if (TRUE == dBtTxEnd()) { /* Wait 100 ms after last byte has been sent to BC4 - else BC4 can crash */ if (++(VarsComm.BtCmdModeWaitCnt) > 100) { dBtClearArm7CmdSignal(); VarsComm.CmdSwitchCnt++; } } } break; case 2: { if (VarsComm.BtBcPinLevel == 0) { /* Bluecore has entered cmd mode */ SETBtCmdState; VarsComm.CmdSwitchCnt = 0; (*pNextState)++; } } break; default: { VarsComm.CmdSwitchCnt = 0; } break; } } void cCommsOpenStream(UBYTE *pNextState) { switch(VarsComm.StreamStateCnt) { case 0: { if (SIZE_OF_BT_CONNECT_TABLE > VarsComm.BtCmdData.ParamTwo) { /* first check if there is a connection on the requested channel */ if ('\0' != IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].Name[0]) { if (1 == IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].StreamStatus) { /* Stream is allready open - continue */ (*pNextState)++; } else { /* There is a connection on requested channel proceed */ VarsComm.StreamStateCnt = 1; } } else { /* Error - no connecteion on requested channel - exit */ *(VarsComm.pRetVal) = (UWORD)ERR_COMM_CHAN_NOT_READY; *(VarsComm.pRetVal) |= 0x8000; SETBtStateIdle; } } else { /* Error - Illegal channel no - exit */ *(VarsComm.pRetVal) = (UWORD)ERR_COMM_CHAN_INVALID; *(VarsComm.pRetVal) |= 0x8000; SETBtStateIdle; } } break; case 1: { cCommsSetCmdMode(&(VarsComm.StreamStateCnt)); } break; case 2: { cCommsCloseConn0(&(VarsComm.StreamStateCnt)); } break; case 3: { /* Open stream on the specified channel */ VarsComm.StreamStateCnt = 4; dBtSendBtCmd((UBYTE)MSG_OPEN_STREAM, IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].HandleNr, 0, NULL, NULL, NULL, NULL); } break; case 4: { if (VarsComm.BtBcPinLevel) { SETBtDataState; IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamTwo].StreamStatus = 1; VarsComm.StreamStateCnt = 0; (*pNextState)++; } } break; default: { VarsComm.StreamStateCnt = 0; } break; } } void cCommsCloseConn0(UBYTE *pNextState) { switch(VarsComm.CloseConn0Cnt) { case 0: { if ('\0' != IOMapComm.BtConnectTable[0].Name[0]) { /* now disconnect channel 0 */ VarsComm.CloseConn0Cnt = 1; dBtSendBtCmd((UBYTE)MSG_CLOSE_CONNECTION, IOMapComm.BtConnectTable[0].HandleNr, 0, NULL, NULL, NULL, NULL); } else { (*pNextState)++; } } break; case 1: { if (MSG_CLOSE_CONNECTION_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { VarsComm.CloseConn0Cnt = 0; (*pNextState)++; } } break; default: { VarsComm.CloseConn0Cnt = 0; } break; } } void cCommsDisconnectAll(UBYTE *pNextState) { switch(VarsComm.DiscAllCnt) { case 0: { VarsComm.BtCmdData.ParamOne = 0; (VarsComm.DiscAllCnt)++; } break; case 1: { while (('\0' == IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamOne].Name[0]) && (VarsComm.BtCmdData.ParamOne < 4)) { VarsComm.BtCmdData.ParamOne++; } if (VarsComm.BtCmdData.ParamOne < 4) { /* now disconnect selected channel */ dBtSendBtCmd((UBYTE)MSG_CLOSE_CONNECTION, IOMapComm.BtConnectTable[VarsComm.BtCmdData.ParamOne].HandleNr, 0, NULL, NULL, NULL, NULL); VarsComm.BtCmdData.ParamOne++; (VarsComm.DiscAllCnt)++; } else { /* no more connections - move on */ (VarsComm.DiscAllCnt) = 0; (*pNextState)++; } } break; case 2: { if (MSG_CLOSE_CONNECTION_RESULT == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE]) { /* Go back and check for more connections to close */ (VarsComm.DiscAllCnt)--; } } break; } } void cCommsBtReset(UBYTE *pNextState) { switch(VarsComm.ResetBtCnt) { case 0: { /* Setup Reset sequence */ VarsComm.BtResetTimeCnt = 0; VarsComm.ResetBtCnt = 1; dBtSetBcResetPinLow(); } break; case 1: { /* Reset should be held low for a certain time "BLUECORE_RESET_TIME" */ VarsComm.BtResetTimeCnt++; if (VarsComm.BtResetTimeCnt > BLUECORE_RESET_TIME) { dBtSetBcResetPinHigh(); VarsComm.BtWaitTimeCnt = 0; VarsComm.ResetBtCnt = 2; } } break; case 2: { /* Wait after reset is released either wait a minimum time or wait for the reset indication telegram */ VarsComm.BtWaitTimeCnt++; if ((VarsComm.BtWaitTimeCnt > BLUECORE_WAIT_BEFORE_INIT) || (MSG_RESET_INDICATION == IOMapComm.BtInBuf.Buf[BT_CMD_BYTE])) { memset(&(IOMapComm.BtDeviceTable), 0, sizeof(IOMapComm.BtDeviceTable)); cCommClrConnTable(); VarsComm.ResetBtCnt = 3; } } break; case 3: { SETBtCmdState; VarsComm.ResetBtCnt = 0; (*pNextState)++; } break; } } UWORD cCommReq(UBYTE Cmd, UBYTE Param1, UBYTE Param2, UBYTE Param3, UBYTE *pName, UWORD *pRetVal) { ULONG Length; UWORD ReturnVal; SBYTE foundIndex= 0; ReturnVal = BTBUSY; *pRetVal = BTBUSY; if ((UPD_IDLE == (VarsComm.ActiveUpdate)) || ((UPD_SEARCH == (VarsComm.ActiveUpdate)) && (STOPSEARCH == Cmd))) { ReturnVal = SUCCESS; *pRetVal = INPROGRESS; VarsComm.pRetVal = pRetVal; switch(Cmd) { case SENDFILE: { ReturnVal = SUCCESS; /* No file is currently beeing send - Now open the file */ VarsComm.ExtTx.SrcHandle = pMapLoader->pFunc(OPENREAD, pName, NULL, &Length); VarsComm.ExtTx.RemFileSize = Length; VarsComm.ExtTx.SlotNo = Param1; VarsComm.BtCmdData.ParamTwo = Param1; /* This is used to open the correct stream */ if (0x8000 > VarsComm.ExtTx.SrcHandle) { /* Source file is ok - go ahead */ VarsComm.ActiveUpdate = UPD_SENDFILE; VarsComm.ExtTx.Timer = 0; VarsComm.ExtTx.Cmd = WRITE; cCommCopyFileName(VarsComm.ExtTx.FileName, pName); } else { /* Error in opening source file for read - file do not exist */ ReturnVal = FILETX_SRCMISSING; } } break; case CONNECTBYNAME: // redo Param1, then fall through existing CONNECT code foundIndex= cCommSearchBTDevTableForName(pName); if(foundIndex != -1) Param1= foundIndex; case CONNECT: { if (BLUETOOTH_HANDLE_UNDEFIEND == IOMapComm.BtConnectTable[Param2].HandleNr && foundIndex != -1) { /* Connection not occupied */ VarsComm.ActiveUpdate = UPD_CONNECT; VarsComm.BtCmdData.ParamOne = Param1; VarsComm.BtCmdData.ParamTwo = Param2; } else { /* Connection occupied */ ReturnVal = BTCONNECTFAIL; *pRetVal = BTCONNECTFAIL; } } break; case DISCONNECT: { VarsComm.ActiveUpdate = UPD_DISCONNECT; VarsComm.BtCmdData.ParamOne = Param1; } break; case DISCONNECTALL: { VarsComm.ActiveUpdate = UPD_DISCONNECTALL; } break; case SEARCH: { VarsComm.ActiveUpdate = UPD_SEARCH; IOMapComm.BtDeviceNameCnt = 0; IOMapComm.BtDeviceCnt = 0; VarsComm.BtCmdData.ParamOne = 0; } break; case STOPSEARCH: { if (UPD_SEARCH == (VarsComm.ActiveUpdate)) { VarsComm.BtCmdData.ParamOne = 1; } else { *pRetVal = SUCCESS; } } break; case REMOVEDEVICE: { VarsComm.ActiveUpdate = UPD_REMOVEDEVICE; VarsComm.BtCmdData.ParamOne = Param1; } break; case VISIBILITY: { VarsComm.ActiveUpdate = UPD_VISIBILITY; VarsComm.BtCmdData.ParamOne = Param1; } break; case SETCMDMODE: { VarsComm.ActiveUpdate = UPD_REQCMDMODE; } break; case FACTORYRESET: { VarsComm.ActiveUpdate = UPD_FACTORYRESET; } break; case BTON: { if (BT_STATE_OFF & (pMapUi->BluetoothState)) { VarsComm.ActiveUpdate = UPD_RESET; } else { /* Device is already on*/ *pRetVal = SUCCESS; } } break; case BTOFF: { VarsComm.ActiveUpdate = UPD_OFF; } break; case SENDDATA: { /* Param2 indicates the port that the data should be */ /* be sent on - param1 indicates the number of data */ /* to be sent. pName is the pointer to the data */ if (Param1 <= sizeof(VarsComm.BtModuleOutBuf.Buf)) { if ('\0' != IOMapComm.BtConnectTable[Param2].Name[0]) { VarsComm.BtCmdData.ParamOne = Param1; VarsComm.BtCmdData.ParamTwo = Param2; VarsComm.BtCmdData.ParamThree = Param3; memcpy((VarsComm.BtModuleOutBuf.Buf), pName, Param1); VarsComm.ActiveUpdate = UPD_SENDDATA; } else { ReturnVal = (UWORD)ERR_COMM_CHAN_NOT_READY; ReturnVal |= 0x8000; } } else { ReturnVal = (UWORD)ERR_COMM_BUFFER_FULL; ReturnVal |= 0x8000; } } break; case OPENSTREAM: { VarsComm.BtCmdData.ParamTwo = Param2; VarsComm.ActiveUpdate = UPD_OPENSTREAM; } break; case SETBTNAME: { VarsComm.ActiveUpdate = UPD_BRICKNAME; } break; case EXTREAD: { VarsComm.ActiveUpdate = UPD_EXTREAD; } break; case PINREQ: { /* This is an incomming pinrequest for connection on connection 0 because */ /* ActiveUpdate is idle (if it was incomming it is not idle) */ cCommCopyBdaddr((IOMapComm.BtConnectTable[0].BdAddr), &(IOMapComm.BtInBuf.Buf[2])); pMapUi->BluetoothState |= (BT_CONNECT_REQUEST | BT_PIN_REQUEST); VarsComm.pValidPinCode = NULL; VarsComm.ActiveUpdate = UPD_PINREQ; } break; case CONNECTREQ: { VarsComm.ActiveUpdate = UPD_CONNECTREQ; } break; } } return(ReturnVal); } void cCommPinCode(UBYTE *pPinCode) { VarsComm.pValidPinCode = pPinCode; if (REQPIN == (*(VarsComm.pRetVal))) { *(VarsComm.pRetVal) = INPROGRESS; } } void cCommClrConnTable(void) { UBYTE Tmp; for (Tmp = 0; Tmp < SIZE_OF_BT_CONNECT_TABLE; Tmp++) { CLEARConnEntry(Tmp); } IOMapComm.BrickData.BtStateStatus &= ~(BT_CONNECTION_0_ENABLE | BT_CONNECTION_1_ENABLE | BT_CONNECTION_2_ENABLE | BT_CONNECTION_3_ENABLE); pMapUi->BluetoothState &= ~BT_STATE_CONNECTED; pMapUi->Flags |= UI_REDRAW_STATUS; } /* search the BT table */ SBYTE cCommSearchBTDevTableForName(UBYTE *name) { UBYTE Tmp; for (Tmp = 0; Tmp < SIZE_OF_BT_DEVICE_TABLE; Tmp++) { if (0 == strcmp((char*)(IOMapComm.BtDeviceTable[Tmp].Name), (char*)name)) return Tmp; } return -1; }