// transfer a byte for the monitor download, with or without acknowledge int DownloadByte(tUartHandle serial_handle, unsigned char byte, bool bAck) { unsigned char received; while (1) { UartWrite(serial_handle, &byte, 1); if (bAck) { UartRead(serial_handle, &received, 1); if (received == byte) { UartWrite(serial_handle, (UINT8*)"\x01", 1); // ack success break; // exit the loop } else { printf("Error transmitting monitor byte 0x%02X, got 0x%0X\n", byte, received); UartWrite(serial_handle, (UINT8*)"\x00", 1); // ack fail, try again } } else break; // no loop } return 1; }
// change baudrate using target monitor int SetTargetBaudrate(tUartHandle serial_handle, long lClock, long lBaudrate) { UINT8 send; UINT8 received; UINT8 brr; long lBRR; lBRR = lClock / lBaudrate; lBRR = ((lBRR + 16) / 32) - 1; // with rounding brr = (UINT8)lBRR; // send the command send = BAUDRATE; UartWrite(serial_handle, &send, 1); UartWrite(serial_handle, &brr, 1); // send the BRR value UartRead(serial_handle, &received, 1); // response ack if (received != BAUDRATE) { // bad situation, now we're unclear about the baudrate of the target printf("Protocol error!\n"); return 1; } SLEEP(100); // give it some time to settle // change our baudrate, too UartConfig(serial_handle, lBaudrate, eNOPARITY, eONESTOPBIT, 8); return 0; }
// write many bytes using the target monitor int FlashByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer) { UINT8 send, received; // send the address command send = ADDRESS; UartWrite(serial_handle, &send, 1); // transmit the address, big endian send = (UINT8)((addr>>24) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)((addr>>16) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)((addr>>8) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)(addr & 0xFF); UartWrite(serial_handle, &send, 1); UartRead(serial_handle, &received, 1); // response if (received != ADDRESS) { printf("Protocol error!\n"); return 1; } while (size) { if (size >= 16) { // we can use a "burst" command send = BYTE_FLASH16; UartWrite(serial_handle, &send, 1); // send the write command UartWrite(serial_handle, pBuffer, 16); // transmit the data UartRead(serial_handle, &received, 1); // response if (received != BYTE_FLASH16) { printf("Protocol error!\n"); return 1; } pBuffer += 16; size -= 16; } else { // use single byte command send = BYTE_FLASH; UartWrite(serial_handle, &send, 1); // send the write command UartWrite(serial_handle, pBuffer++, 1); // transmit the data UartRead(serial_handle, &received, 1); // response if (received != BYTE_FLASH) { printf("Protocol error!\n"); return 1; } size--; } } return 0; }
// do the baudrate configuration for the Player int ConfigFirstlevelPlayer (tUartHandle serial_handle) { UINT32 result_nbr; if(!UartConfig(serial_handle, 4800, eMARKPARITY, eTWOSTOPBITS, 8)) { UINT32 dwErr = GET_LAST_ERR(); printf("Error %lu setting up COM params for baudrate byte\n", dwErr); exit(1); } // this will read as 0x19 when viewed with 2300 baud like the player does result_nbr = UartWrite(serial_handle, (UINT8*)"\x86\xC0", 2); if (result_nbr != 2) { UINT32 dwErr = GET_LAST_ERR(); printf("Error %lu setting up COM params for baudrate byte\n", dwErr); } SLEEP(100); // wait for the chars to be sent, is there a better way? // the read 0x19 means 14423 baud with 12 MHz if(!UartConfig(serial_handle, 14400, eNOPARITY, eONESTOPBIT, 8)) { printf("Error setting up COM params for 1st level loader\n"); exit(1); } return 0; }
/*----------------------------------------------------------------------------* * NAME * SendDataToUart * * DESCRIPTION * Sends the received data over UART. * * RETURNS * Nothing * *----------------------------------------------------------------------------*/ extern void SendDataToUart(uint8 *data, uint16 size) { /* We initially attempt to directly write to the UART and from there on * we send the data using callback mechanism, whenever the UART is ready * to accept more incoming data. This is to avoid data loss. The data is * buffered and sent to UART using callback mechanism. */ if(!g_trigger_write_callback) { UartWrite(data, size); g_trigger_write_callback = TRUE; return; } /* Queue the incoming data to the queue. will be written when UART is ready */ if(g_trigger_write_callback) { /* First copy all the bytes received into the byte queue */ BQSafeQueueBytes((const uint8 *)data, size,RECV_QUEUE_ID); /*Send Pending Data */ sendPendingData(); } }
// do the baudrate configuration for the Recoder/FM int ConfigFirstlevelRecorder (tUartHandle serial_handle) { UINT32 result_nbr; if(!UartConfig(serial_handle, 4800, eNOPARITY, eTWOSTOPBITS, 8)) { UINT32 dwErr = GET_LAST_ERR(); printf("Error %lu setting up COM params for baudrate byte\n", dwErr); exit(1); } // this will read as 0x08 when viewed with 2120 baud like the recorder does result_nbr = UartWrite(serial_handle, (UINT8*)"\x00\x00", 2); if(result_nbr != 2) { printf("Error transmitting baudrate byte\n"); exit(1); } SLEEP(100); // wait for the chars to be sent, is there a better way? // the read 0x08 means 38400 baud with 11.0592 MHz if(!UartConfig(serial_handle, 38400, eNOPARITY, eONESTOPBIT, 8)) { UINT32 dwErr = GET_LAST_ERR(); printf("Error %lu setting up COM params for 1st level loader\n", dwErr); exit(1); } return 0; }
/*----------------------------------------------------------------------------* * NAME * sendPendingData * * DESCRIPTION * Send buffered data over UART that was waiting to be sent. Perform some * translation to ensured characters are properly displayed. * * PARAMETERS * None * * RETURNS * Nothing *----------------------------------------------------------------------------*/ static void sendPendingData(void) { /* Loop until the byte queue is empty */ uint8 data[SERIAL_RX_DATA_LENGTH]; /* Data to be sent */ uint16 size_val; /* Length of the data to be sent */ /* Length of data available in the queue */ uint16 length = BQGetDataSize(RECV_QUEUE_ID); /* Proceed only if byte queue is not empty */ while (BQGetDataSize(RECV_QUEUE_ID) > 0) { /* Make sure that the maximum data length is not exceeded */ size_val = length > SERIAL_RX_DATA_LENGTH ? SERIAL_RX_DATA_LENGTH : length; if (BQPeekBytes(data, size_val,RECV_QUEUE_ID) > 0) { /* Check whether we are able to write */ bool ok_to_commit = UartWrite( data,size_val ); if(!ok_to_commit) { /* exit on failure */ break; } else /* Pop the data out */ BQPopBytes(data, size_val,RECV_QUEUE_ID); } } }
/* ** 向串口读写数据. ** @buf: 发送与接收数据缓冲区 ** @bufSize: 缓冲区长度 */ U8 logic_sendAndRead(U8* buf, U16* bufSize, U32 timeout) { UartWrite(buf, *bufSize, timeout, gpu); *bufSize = UartRead(buf, 100, timeout, gpu); if (*bufSize == 0) {//如果超时后没有读到数据, 返回错误 return ERROR; } return NO_ERR; }
// read a byte using the target monitor UINT8 ReadByte(tUartHandle serial_handle, UINT32 addr) { UINT8 send; UINT8 received; // send the address command send = ADDRESS; UartWrite(serial_handle, &send, 1); // transmit the address, big endian send = (UINT8)((addr>>24) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)((addr>>16) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)((addr>>8) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)(addr & 0xFF); UartWrite(serial_handle, &send, 1); UartRead(serial_handle, &received, 1); // response if (received != ADDRESS) { printf("Protocol error!\n"); return 1; } // send the read command send = BYTE_READ; UartWrite(serial_handle, &send, 1); UartRead(serial_handle, &received, 1); // response return received; }
// write a 16bit halfword using the target monitor int WriteHalfword(tUartHandle serial_handle, UINT32 addr, UINT16 halfword) { UINT8 send; UINT8 received; // send the address command send = ADDRESS; UartWrite(serial_handle, &send, 1); // transmit the address, big endian send = (UINT8)((addr>>24) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)((addr>>16) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)((addr>>8) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)(addr & 0xFF); UartWrite(serial_handle, &send, 1); UartRead(serial_handle, &received, 1); // response if (received != ADDRESS) { printf("Protocol error!\n"); return 1; } // send the write command send = HALFWORD_WRITE; UartWrite(serial_handle, &send, 1); // transmit the data send = halfword >> 8; // highbyte UartWrite(serial_handle, &send, 1); send = halfword & 0xFF; // lowbyte UartWrite(serial_handle, &send, 1); UartRead(serial_handle, &received, 1); // response if (received != HALFWORD_WRITE) { printf("Protocol error!\n"); return 1; } return 0; }
// send a sting and check the echo int SendWithEcho(tUartHandle serial_handle, char* pszSend) { int i = 0; unsigned char received; while(pszSend[i] != '\0') { UartWrite(serial_handle, (unsigned char*)(pszSend + i), 1); // send char do { UartRead(serial_handle, &received, 1); // receive echo printf("%c", received); // debug } while (received != pszSend[i]); // should normally be equal i++; // next char } return 0; }
/* Echo back recevied data in upper case */ int UartTest1( IN const char *pszPort ) { int Retval; uhandle_t hUart; char Buff[256]; unsigned int BytesRead; unsigned int BytesWritten; DBG_MSG(DBG_TRACE, "%s\n", __FUNCTION__); Retval = UartCtor(&hUart); CHECK_RETVAL(Retval, ExitOnFailure); Retval = UartOpen(hUart, pszPort, UART_RATE_57600, UART_DATA_BITS_8, UART_PARITY_NONE, UART_STOP_1); CHECK_RETVAL(Retval, ExitOnFailure); for ( ; ; ) { Retval = UartRead(hUart, Buff, sizeof(Buff), &BytesRead, 1000); if (BytesRead) { UartTestToUpper(Buff, BytesRead); Retval = UartWrite(hUart, Buff, BytesRead, &BytesWritten, 1000); CHECK_RETVAL(Retval, ExitOnFailure); } } ExitOnFailure: UartDtor(hUart); return Retval; }
// write a byte using the target monitor int WriteByte(tUartHandle serial_handle, UINT32 addr, UINT8 byte) { UINT8 send; UINT8 received; // send the address command send = ADDRESS; UartWrite(serial_handle, &send, 1); // transmit the address, big endian send = (UINT8)((addr>>24) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)((addr>>16) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)((addr>>8) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)(addr & 0xFF); UartWrite(serial_handle, &send, 1); UartRead(serial_handle, &received, 1); // response if (received != ADDRESS) { printf("Protocol error, receiced 0x%02X!\n", received); return 1; } // send the write command send = BYTE_WRITE; UartWrite(serial_handle, &send, 1); // transmit the data UartWrite(serial_handle, &byte, 1); UartRead(serial_handle, &received, 1); // response if (received != BYTE_WRITE) { printf("Protocol error!\n"); return 1; } return 0; }
// call a subroutine using the target monitor int Execute(tUartHandle serial_handle, UINT32 addr, bool bReturns) { UINT8 send; UINT8 received; // send the address command send = ADDRESS; UartWrite(serial_handle, &send, 1); // transmit the address, big endian send = (UINT8)((addr>>24) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)((addr>>16) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)((addr>>8) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)(addr & 0xFF); UartWrite(serial_handle, &send, 1); UartRead(serial_handle, &received, 1); // response if (received != ADDRESS) { printf("Protocol error!\n"); return 1; } // send the execute command send = EXECUTE; UartWrite(serial_handle, &send, 1); if (bReturns) { // we expect the call to return control to minimon UartRead(serial_handle, &received, 1); // response if (received != EXECUTE) { printf("Protocol error!\n"); return 1; } } return 0; }
// read a 16bit halfword using the target monitor UINT16 ReadHalfword(tUartHandle serial_handle, UINT32 addr) { UINT8 send; UINT8 received; UINT16 halfword; // send the address command send = ADDRESS; UartWrite(serial_handle, &send, 1); // transmit the address, big endian send = (UINT8)((addr>>24) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)((addr>>16) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)((addr>>8) & 0xFF); UartWrite(serial_handle, &send, 1); send = (UINT8)(addr & 0xFF); UartWrite(serial_handle, &send, 1); UartRead(serial_handle, &received, 1); // response if (received != ADDRESS) { printf("Protocol error!\n"); return 1; } // send the read command send = HALFWORD_READ; UartWrite(serial_handle, &send, 1); UartRead(serial_handle, &received, 1); // response halfword = received << 8; // highbyte UartRead(serial_handle, &received, 1); halfword |= received; // lowbyte return halfword; }
/*! \brief Test the spi communication \param[in] none \return upon successful, the function shall return 0. Otherwise, -1 shall be returned \warning */ static int TestSpi() { const _SlSyncPattern_t H2NCnysPattern = H2N_CNYS_PATTERN; _SlFd_t FD = 0; unsigned int irqCheck = 0; unsigned char pBuf[8] = {'\0'}; unsigned char SyncCnt = 0; unsigned char ShiftIdx = 0; /* Start the state machine */ SetTestStage(TEST_STAGE_SPI_TEST_BEGIN); /* Initialize the Spi interface */ FD = sl_IfOpen(0, 0); SetTestStage(TEST_STAGE_SPI_OPEN_PASSED); /* Register IRQ handler */ sl_IfRegIntHdlr((P_EVENT_HANDLER)DiagIrqHandler, 0); /*Make Sure that the device is turned off */ sl_DeviceDisable(); SetTestStage(TEST_STAGE_DISABLE_PASSED); /* Save IRQ counter before activating the Device */ irqCheck = g_irqCounter; /* Turn on the device */ sl_DeviceEnable(); SetTestStage(TEST_STAGE_ENABLE_PASSED); /* Wait until we get an increment on IRQ value */ while( irqCheck == g_irqCounter ) { } SetTestStage(TEST_STAGE_SPI_IRQ_PASSED); /* Generate the sync pattern for getting the response */ sl_IfWrite(FD, (unsigned char *)&H2NCnysPattern, SYNC_PATTERN_LEN); SetTestStage(TEST_STAGE_SPI_WRITE_PASSED); /* Read 4 bytes from the Spi */ sl_IfRead(FD, &pBuf[0], 4); /* Sync on read pattern */ while ( ! N2H_SYNC_PATTERN_MATCH(pBuf, TxSeqNum)) { /* Read next 4 bytes to Low 4 bytes of buffer */ if(0 == (SyncCnt % SYNC_PATTERN_LEN)) { sl_IfRead(FD, &pBuf[4], 4); } /* Shift Buffer Up for checking if the sync is shifted */ for(ShiftIdx = 0; ShiftIdx < 7; ShiftIdx++) { pBuf[ShiftIdx] = pBuf[ShiftIdx+1]; } pBuf[7] = 0; SyncCnt++; } /*Sync pattern found. If needed, complete number of read bytes to multiple * of 4 (protocol align) */ SyncCnt %= SYNC_PATTERN_LEN; if(SyncCnt > 0) { *(UINT32 *)&pBuf[0] = *(UINT32 *)&pBuf[4]; sl_IfRead(FD, &pBuf[SYNC_PATTERN_LEN - SyncCnt], SyncCnt); } else { sl_IfRead(FD, &pBuf[0], 4); } /* Scan for possible double pattern */ while( N2H_SYNC_PATTERN_MATCH(pBuf, TxSeqNum)) { sl_IfRead(FD, &pBuf[0], SYNC_PATTERN_LEN); } /* Read the Resp Specific header (4 more bytes) */ sl_IfRead(FD, &pBuf[SYNC_PATTERN_LEN], 4); SetTestStage(TEST_STAGE_SPI_READ_PASSED); /* Check the init complete message opcode */ if(SL_OPCODE_DEVICE_INITCOMPLETE != (*(unsigned short*)(pBuf))) { UartWrite((unsigned char *)"Error in Spi Testing\r\n"); return -1; /* failed to read init complete */ } SetTestStage(TEST_STAGE_INIT_COMPLETE_READ_PASSED); SetTestStage(TEST_STAGE_SPI_TEST_COMPLETE); return SUCCESS; }
/*! \brief Update the state machine and write the output on Application UART \param[in] stage - New state of the application \return none \warning */ static void SetTestStage(testStage_e stage) { g_testStage = stage; switch(stage) { case TEST_STAGE_SPI_TEST_BEGIN: UartWrite((unsigned char *)TEST_SPI_BEGIN); UartWrite((unsigned char *)"\r\n"); break; case TEST_STAGE_SPI_OPEN_PASSED: UartWrite((unsigned char *)TEST_SPI_OPEN_PASSED); UartWrite((unsigned char *)"\r\n"); break; case TEST_STAGE_DISABLE_PASSED: UartWrite((unsigned char *)TEST_DEVICE_DISABLE_PASSED); UartWrite((unsigned char *)"\r\n"); break; case TEST_STAGE_ENABLE_PASSED: UartWrite((unsigned char *)TEST_DEVICE_ENABLE_PASSED); UartWrite((unsigned char *)"\r\n"); break; case TEST_STAGE_SPI_WRITE_PASSED: UartWrite((unsigned char *)TEST_SPI_WRITE_PASSED); UartWrite((unsigned char *)"\r\n"); break; case TEST_STAGE_SPI_READ_PASSED: UartWrite((unsigned char *)TEST_SPI_READ_PASSED); UartWrite((unsigned char *)"\r\n"); break; case TEST_STAGE_SPI_IRQ_PASSED: UartWrite((unsigned char *)TEST_SPI_IRQ_PASSED); UartWrite((unsigned char *)"\r\n"); break; case TEST_STAGE_INIT_COMPLETE_READ_PASSED: UartWrite((unsigned char *)SPI_INIT_COMPLETE_READ_PASSED); UartWrite((unsigned char *)"\r\n"); break; case TEST_STAGE_SPI_TEST_COMPLETE: UartWrite((unsigned char *)SPI_TEST_COMPLETED); UartWrite((unsigned char *)"\r\n\r\n"); break; } }
/*----------------------------------------------------------------------------* * NAME * handleOperand * * DESCRIPTION * This function processes the received operand and the associated data. * It calls the application handler function for the supported operands * and send an appropriate response over the UART * * PARAMETERS * Nothing * * RETURNS * Nothing *----------------------------------------------------------------------------*/ static void handleOperand(void) { uint8 response[MAX_RESPONSE_LEN]; uint8 length = 0; BD_ADDR_T bd_addr; uint16 key[SIZE_LTK_IN_WORDS]; /* Check is it's a SET command or a GET command. */ if(g_command == SET_REQUEST_CMD) { /* It's a SET command, Start preparing response for it. * The reponse will contain three fields: * 1. SET_RESPONSE_CMD [1 octet] * 2. OPERAND [1 octet] * 3. STATUS- RESPONSE_SUCCESS or RESPONSE_FAILURE [1 octet] */ response[0] = SET_RESPONSE_CMD; response[1] = g_operand; /* Check which operand the SET request is for. */ switch(g_operand) { /* Trunk Open or close request has been received. */ case OPERAND_TRUNK_OPERATION: { /* This request will never fail. * The following two operations can be done: * 0x00 - Open Trunk * 0x01 - Close Trunk * * The remote connected keyfob can also send an Open trunk * request to the automotive Host application. In this case, * the application shall send a notification about the trunk * status over the UART interface. */ if(SetVehicleInformationData(index_trunk_status, g_operandData)) { response[2] = RESPONSE_SUCCESS; } else { response[2] = RESPONSE_FAILURE; /* This error code will * never be returned for * this SET rquest. */ } } break; #ifdef ENABLE_INFACTORY_PAIRING /* The request is for setting LTK for the connection */ case OPERAND_LTK: { /* Pack the LTK into the key and pass it to the application */ MemCopyPack(key, g_operandData, SIZE_LTK_IN_WORDS *2); if(SetLTKForTheConnection(key)) { /* Return Success for the Set request. */ response[2] = RESPONSE_SUCCESS; } else { /* Return Failure for the Set request. */ response[2] = RESPONSE_FAILURE; } } break; /* The request is for setting the IRK of the paired keyfob */ case OPERAND_IRK: { /* Pack the IRK into the key and pass it to the application */ MemCopyPack(key, g_operandData, SIZE_IRK_IN_WORDS *2); if(SetIRKForTheConnection(key)) { /* Return Success for the Set request. */ response[2] = RESPONSE_SUCCESS; } else { /* Return Failure for the Set request. */ response[2] = RESPONSE_FAILURE; } } break; /* The request is for setting the Bluetooth device address of the * bonded keyfob. */ case OPERAND_FOB_BDADDR: { /* Copy the BD Address of the Vehicle into the BD_ADDR_T * stucture and pass it application */ /* LAP part is of 24 bits. */ bd_addr.lap = ((uint24)g_operandData[0]) | (((uint24)g_operandData[1]) << 8) | (((uint24)g_operandData[2]) << 16); /* UAP is of 8bits */ bd_addr.uap = g_operandData[3]; /* NAP is of 16bits */ bd_addr.nap = ((uint16)g_operandData[4]) | (((uint16)g_operandData[5]) << 8); if(SetBondedKeyFobAddress(&bd_addr)) { /* Return success for the SET REQUEST */ response[2] = RESPONSE_SUCCESS; } else { /* Return failure for the SET REQUEST */ response[2] = RESPONSE_FAILURE; } } break; #endif /* ENABLE_INFACTORY_PAIRING */ /* The request is for deleting phone-keyfob pairing information * present on the keyfob */ case OPERAND_DELETE_PAIRING: { if(!DeletePhoneKeyFobPairing()) { /* Pairing deletion has failed. Return a failure. */ response[2] = RESPONSE_FAILURE; } else { /* The application has written to the remote keyfob's * Delete pairing characteristic. Don't send any response * here. Once the application receives a response for the * write request, it will send a SET RESPONSE * over the UART interface. */ return; } } break; /* A handle hold has been detectecd. * For demo purposes, A SET REQUEST over UART with the handle hold * operand will act as a trigger */ case OPERAND_CAR_HNDL_HOLD: { /* A success result in a SET RESPONSE shall be immediately sent * for this operand. */ response[2] = RESPONSE_SUCCESS; length = 3; UartWrite(response, length); /* For this operand, the application implements a passive entry * mechanism where the Automotive Host application will do some * proximity measurements. If it finds the keyfob in range, it * will execute the Special Authentication Challenge Response * procedure. If the Special Authentication Challenge Response * procedures completes with a success, the application will * unlock the doors. */ if(AppIsDeviceConnected() && IsVehicleLocked()&& CheckProximity()) { #ifdef ENABLE_SPECIAL_AUTHENTICATION SetUnlockRequestReceivedFlag(); ExecuteServiceDiscoverySplAuthProcedureOnHandleHold(); #else UnlockTheVehicle(); #endif } return; } break; /* A Lock/Unlock command has been received over the UART interface. */ case OPERAND_LOCK_STATUS: { /* This is a request from inside the vehicle itself. This * request shall never fail. */ if(SetVehicleInformationData(index_lock_unlock , g_operandData)) { /* Return success for the SET REQUEST */ response[2] = RESPONSE_SUCCESS; } else { /* Return failure for the SET REQUEST */ response[2] = RESPONSE_FAILURE; } /* Depending upon the data received in the command, take * action. */ if(g_operandData[0] == door_locked) { LockTheVehicle(); } else if(g_operandData[0] == door_unlocked) { UnlockTheVehicle(); } } break; /* This command is for Radio setting */ case OPERAND_RADIO_SETTING: { /* Store the Radio setting received. */ if(SetVehicleInformationData(index_radio_setting, g_operandData)) { /* Return success for the SET REQUEST */ response[2] = RESPONSE_SUCCESS; } else { /* Return failure for the SET REQUEST */ response[2] = RESPONSE_FAILURE; } } break; /* Latitude location of the vehicle is being set */ case OPERAND_LATITUDE: { /* Store the new latitude location. */ if(SetVehicleInformationData(index_location_latitude, g_operandData)) { /* Return success for the SET REQUEST */ response[2] = RESPONSE_SUCCESS; } else { /* Return failure for the SET REQUEST */ response[2] = RESPONSE_FAILURE; } } break; /* Longitude location of the vehicle is being set. */ case OPERAND_LONGITUDE: { /* Store the new longitude location */ if(SetVehicleInformationData(index_location_longitude, g_operandData)) { /* Return success for the SET REQUEST */ response[2] = RESPONSE_SUCCESS; } else { /* Return failure for the SET REQUEST */ response[2] = RESPONSE_FAILURE; } } break; /* Speed limit of the vehicle is being set */ case OPERAND_SPEED_LIMIT: { /* Store the new speed limit. */ if(SetVehicleInformationData(index_speed_limit, g_operandData)) { /* Return success for the SET REQUEST */ response[2] = RESPONSE_SUCCESS; } else { /* Return failure for the SET REQUEST */ response[2] = RESPONSE_FAILURE; } } break; /* Tyre pressure information is being fed to the vehicle * information service. */ case OPERAND_TYRE_PRESSURE: { /* Store the tyre pressure information in the corresponding * characteristic in the Vehicle Information service. */ if(SetVehicleInformationData(index_tyre_pressure, g_operandData)) { /* Return success for the SET REQUEST */ response[2] = RESPONSE_SUCCESS; } else { /* Return failure for the SET REQUEST */ response[2] = RESPONSE_FAILURE; } } break; /* Licence number of the driver is being stored in the vehicle. */ case OPERAND_LIC_NUMBER: { /* Store the licence number of the driver in the corresponding * characteristic */ if(SetVehicleInformationData(index_licence_plate, g_operandData)) { /* Return success for the SET REQUEST */ response[2] = RESPONSE_SUCCESS; } else { /* Return failure for the SET REQUEST */ response[2] = RESPONSE_FAILURE; } } break; /* Fuel level information is being stored in the Vehicle * Information service. This information will be transferred to the * keyfob and a user will be able to know the fuel level using his * mobile phone even when he is not near the vehicle. */ case OPERAND_FUEL_LEVEL: { /* Store the Fuel level information in the Vehicle Information * service. */ if(SetVehicleInformationData(index_fuel_info, g_operandData)) { /* Return success for the SET REQUEST */ response[2] = RESPONSE_SUCCESS; } else { /* Return failure for the SET REQUEST */ response[2] = RESPONSE_FAILURE; } } break; /* Mileage information is being stored in the Vehicle Information * Service which will be transferred to the keyfob so that a user * can see the mileage from his mobile phone even when he is not * near the vehicle. */ case OPERAND_MILEAGE: { /* Store the mileage information in the vehicle Information * service. */ if(SetVehicleInformationData(index_mileage_info, g_operandData)) { /* Return success for the SET REQUEST */ response[2] = RESPONSE_SUCCESS; } else { /* Return failure for the SET REQUEST */ response[2] = RESPONSE_FAILURE; } } break; case OPERAND_CONN_CHANNEL_MAP: { /* Set the connection channel map */ if(GapSetConnChanMask(g_operandData) == ls_err_none) { /* Return success for the SET REQUEST */ response[2] = RESPONSE_SUCCESS; } else { /* Return failure for the SET REQUEST */ response[2] = RESPONSE_FAILURE; } } break; default: { /* No other opcode is supported for a SET REQUEST, return * failure */ response[2] = RESPONSE_FAILURE; } break; } /* Total length of the response is 3 octets */ length = 3; } /* A GET REQUEST has been received over the UART */ else if(g_command == GET_REQUEST_CMD) { /* Prepare a GET RESPONSE. The response will have the following format: * 1. GET_RESPONSE_CMD [1 octet] * 2. OPERAND [1 octet] * 3. DATA [Variable number of octets] */ response[0] = GET_RESPONSE_CMD; response[1] = g_operand; switch(g_operand) { case OPERAND_LOCK_STATUS: { /* Return 0x00- Unlocked * 0x01- Locked * Depending upon whether doors are locked or unlocked. */ GetVehicleInformationData(index_lock_unlock, &response[2]); length = 2 + LENGTH_LOCK_UNLOCK_STATUS; } break; /* The received request is for Battery Level of the keyfob. */ case OPERAND_BATTERY_LEVEL: { /* The application shall return the current stored Battery * level in a GET Response. */ response[2] = GetStoredKeyfobBatteryLevel(); length = 3; } break; /* The received request is for Radio setting. */ case OPERAND_RADIO_SETTING: { /* The application shall return the current radio setting from * the characteristic. */ GetVehicleInformationData(index_radio_setting, &response[2]); length = 2 + LENGTH_RADIO_SETTING; } break; /* The received request is for Latitude location */ case OPERAND_LATITUDE: { /* Return the currently stored latitude location from the * Vehicle Information service. */ GetVehicleInformationData(index_location_latitude, &response[2]); length = 2 + LENGTH_LATITUDE_LOCATION; } break; /* The received request is for longitude location */ case OPERAND_LONGITUDE: { /* Return the currently stored longitude location from the * Vehicle Information service. */ GetVehicleInformationData(index_location_longitude, &response[2]); length = 2 + LENGTH_LONGITUDE_LOCATION; } break; /* The received request is for the Speed Limit currently set in the * Vehicle Information Service. */ case OPERAND_SPEED_LIMIT: { /* Return the currently stored Speed Limit value from the * Vehicle Information service. */ GetVehicleInformationData(index_speed_limit, &response[2]); length = 2 + LENGTH_SPEED_LIMIT; } break; /* The received request is for Tyre pressure. */ case OPERAND_TYRE_PRESSURE: { /* Return the current stored value from the Vehicle Information * Service. */ GetVehicleInformationData(index_tyre_pressure, &response[2]); length = 2 + LENGTH_TYRE_PRESSURE; } break; /* The received request is for the Licese number stored in the * Vehicle Information Service. */ case OPERAND_LIC_NUMBER: { /* Store the Licence number information stored in the Vehicle * Information Service. */ GetVehicleInformationData(index_licence_plate, &response[2]); length = 2 + LENGTH_LICENCE_PLATE_INFO; } break; /* The request is for the Fuel level */ case OPERAND_FUEL_LEVEL: { /* Return the Fuel Level information from the Vehicle * Information Service. */ GetVehicleInformationData(index_fuel_info, &response[2]); length = 2 + LENGTH_FUEL_LEVEL_INFO; } break; /* The received request is for the mileage information */ case OPERAND_MILEAGE: { /* Return the current mileage information stored in the Vehicle * information service. */ GetVehicleInformationData(index_mileage_info, &response[2]); length = 2 + LENGTH_MILEAGE_INFO; } break; /* Device role has been requested. */ case OPERAND_DEVICE_ROLE: { /* Device role has been requested.*/ response[2] = DEVICE_ROLE_VEHICLE; length = 3; } break; /* The request is for getting the Bluetooth device address of the * Automotive Host. */ case OPERAND_CAR_BDADDR: { #ifdef USE_RESOLVABLE_RANDOM_ADDRESS /* If privacy is enabled generate Resolvable random address * and use it as advAddress. */ SMPrivacyRegenerateAddress(NULL); GapGetRandomAddress(&bd_addr); #else /* Read the public BD address */ CSReadBdaddr(&bd_addr); #endif /* USE_RESOLVABLE_RANDOM_ADDRESS */ /* First LAP part of the bluetooth address into the response * buffer. (LSB first). */ response[2] = (uint8 )bd_addr.lap; response[3] = (uint8 )(bd_addr.lap >> 8); response[4] = (uint8 )(bd_addr.lap >> 16); /* Copy UAP part into the response buffer */ response[5] = (uint8 )(bd_addr.uap); /* Copy NAP part into the response buffer(LSB first) */ response[6] = (uint8 )(bd_addr.nap); response[7] = (uint8 )(bd_addr.nap >> 8); length = 8; } break; case OPERAND_IRK: { #ifdef USE_RESOLVABLE_RANDOM_ADDRESS uint16 irk[SIZE_IRK_IN_WORDS]; /* Read the device IRK */ SMPrivacyGetOwnIrk(irk); /* Copy IRK to the response buffer */ MemCopyUnPack(&response[2], irk, SIZE_IRK_IN_WORDS * 2); length = 18; #else /* Respond with operand un-supported if random address is * not supported */ response[0] = GET_RESPONSE_CMD; response[1] = OPERAND_ERROR_STATUS; response[2] = ERR_OPERAND_NOT_SUPPORTED; response[3] = OPERAND_IRK; length = 4; #endif /* USE_RESOLVABLE_RANDOM_ADDRESS */ } break; /* The received request is for connection status. */ case OPERAND_CONNECTION_STATUS: { /* The application shall return the current connection state. */ if(AppIsDeviceConnected()) { response[2] = conn_status_connected; } else { response[2] = conn_status_disconnected; } length = 3; } break; default: { /* No other GET REQUEST is supported, Ignore the received * request. */ length = 0; } break; } }
// download our little monitor, the box must have been just freshly switched on for this to work int DownloadMonitor(tUartHandle serial_handle, bool bRecorder, char* szFilename) { FILE* pFile; size_t filesize; UINT8 byte; unsigned i; // hard-coded parameters bool bAck = true; // configure if acknowledged download (without useful for remote pin boot) UINT32 TargetLoad = 0x0FFFF000; // target load address pFile = fopen(szFilename, "rb"); if (pFile == NULL) { printf("\nMonitor file %s not found, exiting\n", szFilename); exit(1); } // determine file size fseek(pFile, 0, SEEK_END); filesize = ftell(pFile); fseek(pFile, 0, SEEK_SET); // This is _really_ tricky! The box expects a BRR value in a nonstandard baudrate, // which a PC can't generate. I'm using a higher one with some wild settings // to generate a pulse series that: // 1) looks like a stable byte when sampled with the nonstandard baudrate // 2) gives a BRR value to the box which results in a baudrate the PC can also use if (bRecorder) { ConfigFirstlevelRecorder(serial_handle); } else { ConfigFirstlevelPlayer(serial_handle); } UartWrite(serial_handle, bAck ? (UINT8*)"\x01" : (UINT8*)"\x00", 1); // ACK mode // transmit the size, little endian DownloadByte(serial_handle, (UINT8)( filesize & 0xFF), bAck); DownloadByte(serial_handle, (UINT8)((filesize>>8) & 0xFF), bAck); DownloadByte(serial_handle, (UINT8)((filesize>>16) & 0xFF), bAck); DownloadByte(serial_handle, (UINT8)((filesize>>24) & 0xFF), bAck); // transmit the load address, little endian DownloadByte(serial_handle, (UINT8)( TargetLoad & 0xFF), bAck); DownloadByte(serial_handle, (UINT8)((TargetLoad>>8) & 0xFF), bAck); DownloadByte(serial_handle, (UINT8)((TargetLoad>>16) & 0xFF), bAck); DownloadByte(serial_handle, (UINT8)((TargetLoad>>24) & 0xFF), bAck); // transmit the command byte DownloadByte(serial_handle, 0xFF, bAck); // 0xFF means execute the transferred image // transmit the image for (i=0; i<filesize; i++) { fread(&byte, 1, 1, pFile); DownloadByte(serial_handle, byte, bAck); } fclose (pFile); // now the image should have been started, red LED off return 0; }
// rarely used variant: download our monitor using the built-in Archos monitor int DownloadArchosMonitor(tUartHandle serial_handle, char* szFilename) { FILE* pFile; size_t filesize; UINT8 byte; UINT16 checksum = 0; unsigned i; // the onboard monitor uses 115200 baud if(!UartConfig(serial_handle, 115200, eNOPARITY, eONESTOPBIT, 8)) { UINT32 dwErr = GET_LAST_ERR(); printf("Error %lu setting up COM params for baudrate %d\n", dwErr, 115200); exit(1); } // wait for receiving "#SERIAL#" WaitForString(serial_handle, "#SERIAL#"); // send magic "SRL" command to get interactive mode SendWithEcho(serial_handle, "SRL\r"); // wait for menu completion: "ROOT>" at the end WaitForString(serial_handle, "ROOT>"); // send upload command "UP" SendWithEcho(serial_handle, "UP\r"); pFile = fopen(szFilename, "rb"); if (pFile == NULL) { printf("\nMonitor file %s not found, exiting\n", szFilename); exit(1); } // determine file size fseek(pFile, 0, SEEK_END); filesize = ftell(pFile); fseek(pFile, 0, SEEK_SET); // calculate checksum for (i=0; i<filesize; i++) { fread(&byte, 1, 1, pFile); checksum += byte; } fseek(pFile, 0, SEEK_SET); // send header // size as 32 bit little endian byte = (UINT8)( filesize & 0xFF); UartWrite(serial_handle, &byte, 1); byte = (UINT8)((filesize>>8) & 0xFF); UartWrite(serial_handle, &byte, 1); byte = (UINT8)((filesize>>16) & 0xFF); UartWrite(serial_handle, &byte, 1); byte = (UINT8)((filesize>>24) & 0xFF); UartWrite(serial_handle, &byte, 1); // checksum as 16 bit little endian byte = (UINT8)( checksum & 0xFF); UartWrite(serial_handle, &byte, 1); byte = (UINT8)((checksum>>8) & 0xFF); UartWrite(serial_handle, &byte, 1); UartWrite(serial_handle, (unsigned char*)"\x00", 1); // kind (3 means flash) UartWrite(serial_handle, (unsigned char*)"\x00", 1); // ignored byte // wait for monitor to accept data WaitForString(serial_handle, "#OKCTRL#"); // transmit the image for (i=0; i<filesize; i++) { fread(&byte, 1, 1, pFile); UartWrite(serial_handle, &byte, 1); // payload } fclose (pFile); UartWrite(serial_handle, (unsigned char*)"\x00", 1); // ignored byte // wait for menu completion: "ROOT>" at the end WaitForString(serial_handle, "ROOT>"); // send start program command "SPRO" SendWithEcho(serial_handle, "SPRO\r"); SLEEP(100); // wait a little while for startup return 0; }