/* * cmd_parser.c * * Created on: 16 01 2024 * Author: pvvx */ /********************************************************************* INCLUDES */ #include "bcomdef.h" #include "config.h" #include "OSAL.h" #include "linkdb.h" #include "att.h" #include "gatt.h" #include "gatt_uuid.h" #include "gattservapp.h" #include "gapbondmgr.h" #include "flash.h" #include "flash_eep.h" #include "thb2_main.h" #include "sbp_profile.h" #include "sensors.h" #include "cmd_parser.h" #include "devinfoservice.h" #include "gapgattserver.h" #include "ble_ota.h" #include "thb2_peripheral.h" #include "lcd.h" #include "logger.h" #include "trigger.h" #include "buzzer.h" #include "bthome_beacon.h" #include "findmy_beacon.h" /*********************************************************************/ extern gapPeriConnectParams_t periConnParameters; #define SEND_DATA_SIZE 16 const dev_id_t dev_id = { .pid = CMD_ID_DEVID, .revision = 1, .hw_version = DEVICE, .sw_version = APP_VERSION, .dev_spec_data = 0, .services = DEV_SERVICES }; #if (OTA_TYPE == OTA_TYPE_BOOT) #define FLASH_ADDR_RINFO FLASH_BASE_ADDR #define OFFSET_ADDR_RMAC 0x900 #define FLASH_ADDR_RMAC (FLASH_BASE_ADDR + OFFSET_ADDR_RMAC) static void write_fix_mac(uint32_t *pdata) { uint32_t idx, tmp; uint8_t buf_sector[FLASH_SECTOR_SIZE]; hal_flash_read(FLASH_ADDR_RINFO, buf_sector, FLASH_SECTOR_SIZE); memcpy(&buf_sector[OFFSET_ADDR_RMAC], pdata, CHIP_MADDR_LEN*4); tmp = phy_flash.Capacity; phy_flash.Capacity |= FLASH_MAX_SIZE; *(volatile int*) 0x1fff0898 = phy_flash.Capacity; hal_flash_unlock(); hal_flash_erase_sector(FLASH_ADDR_RINFO + phy_flash.Capacity); for(idx = 0; idx < FLASH_SECTOR_SIZE; idx += 256) hal_flash_write(FLASH_ADDR_RINFO + phy_flash.Capacity + idx, &buf_sector[idx], 256); phy_flash.Capacity = tmp; *(volatile int*) 0x1fff0898 = phy_flash.Capacity; } void fix_mac(int write) { int i; uint32_t data[CHIP_MADDR_LEN]; if(write) { if(read_chip_mAddr((uint8_t *)data) == CHIP_ID_VALID) { if(memcmp(ownPublicAddr, data, CHIP_MADDR_LEN) == 0) return; } for (i = 0; i < CHIP_MADDR_LEN; i++) { data[CHIP_MADDR_LEN - 1 - i] = (1 << (((ownPublicAddr[i] & 0xf0) >> 4) + 16)) | (1 << (ownPublicAddr[i] & 0x0f)); } write_fix_mac(data); } else { // clear hal_flash_read(FLASH_ADDR_RMAC, (uint8_t *)data, sizeof(data)); for(i = 0; i < CHIP_MADDR_LEN; i++) { if(data[i] != 0xffffffff) { memset(&data, 0xff, sizeof(data)); write_fix_mac(data); break; } } } } #endif int cmd_parser(uint8_t * obuf, uint8_t * ibuf, uint32_t len) { int olen = 0; if (len) { uint8_t cmd = ibuf[0]; uint32_t tmp = ibuf[1] | (ibuf[2]<<8) | (ibuf[3]<<16) | (ibuf[4]<<24); obuf[0] = cmd; obuf[1] = 0; // no err if (cmd == CMD_ID_DEVID) { // Get DEV_ID memcpy(obuf, &dev_id, sizeof(dev_id)); #if (DEV_SERVICES & SERVICE_THS) dev_id_t * p = (dev_id_t *)&obuf; p->dev_spec_data = thsensor_cfg.sensor_type; #endif olen = sizeof(dev_id); } else if (cmd == CMD_ID_CFG) { // Get/Set device config if (--len > sizeof(cfg)) len = sizeof(cfg); if (len) { #if (DEV_SERVICES & SERVICE_SCREEN) && (OTA_TYPE == OTA_TYPE_APP) tmp ^= cfg.flg; #endif memcpy(&cfg, &ibuf[1], len); #if (DEV_SERVICES & SERVICE_SCREEN) && (OTA_TYPE == OTA_TYPE_APP) if(tmp & FLG_DISPLAY_OFF) init_lcd(); #endif test_config(); flash_write_cfg(&cfg, EEP_ID_CFG, sizeof(cfg)); } memcpy(&obuf[1], &cfg, sizeof(cfg)); olen = sizeof(cfg) + 1; } else if (cmd == CMD_ID_CFG_DEF) { // Set default device config #if (DEV_SERVICES & SERVICE_SCREEN) && (OTA_TYPE == OTA_TYPE_APP) tmp = cfg.flg ^ def_cfg.flg; #endif memcpy(&cfg, &def_cfg, sizeof(cfg)); #if (DEV_SERVICES & SERVICE_SCREEN) && (OTA_TYPE == OTA_TYPE_APP) if(tmp & FLG_DISPLAY_OFF) init_lcd(); #endif test_config(); flash_write_cfg(&cfg, EEP_ID_CFG, sizeof(cfg)); memcpy(&obuf[1], &cfg, sizeof(cfg)); olen = sizeof(cfg) + 1; #if (DEV_SERVICES & SERVICE_THS) } else if (cmd == CMD_ID_CFS) { // Get/Set sensor config if (--len > sizeof(thsensor_cfg.coef)) len = sizeof(thsensor_cfg.coef); if (len) { memcpy(&thsensor_cfg.coef, &ibuf[1], len); flash_write_cfg(&thsensor_cfg.coef, EEP_ID_CFS, sizeof(thsensor_cfg.coef)); } memcpy(&obuf[1], &thsensor_cfg, thsensor_cfg_send_size); olen = thsensor_cfg_send_size + 1; } else if (cmd == CMD_ID_CFS_DEF) { // Get/Set default sensor config memset(&thsensor_cfg, 0, thsensor_cfg_send_size); init_sensor(); memcpy(&obuf[1], &thsensor_cfg, thsensor_cfg_send_size); olen = thsensor_cfg_send_size + 1; } else if (cmd == CMD_ID_SEN_ID) { memcpy(&obuf[1], (uint8_t *)&thsensor_cfg.mid, 6); olen = 1 + 5; #if (OTA_TYPE == OTA_TYPE_APP) && ((DEV_SERVICES & SERVICE_TH_TRG) || (DEV_SERVICES & SERVICE_SCREEN)) } else if (cmd == CMD_ID_TRG) { // Get/Set tigger data config if (--len > trigger_send_size) len = trigger_send_size; if (len) { memcpy(&trg, &ibuf[1], len); flash_write_cfg(&trg, EEP_ID_TRG, trigger_send_size); } memcpy(&obuf[1], &trg, trigger_send_size); olen = trigger_send_size + 1; #endif #endif #if (DEV_SERVICES & SERVICE_HISTORY) } else if (cmd == CMD_ID_LOGGER && len > 2) { // Read memory measures rd_memo.cnt = ibuf[1] | (ibuf[2] << 8); if (rd_memo.cnt) { rd_memo.saved = memo; if (len > 4) rd_memo.cur = ibuf[3] | (ibuf[4] << 8); else rd_memo.cur = 0; } wrk_notify(); // osal_set_event(simpleBLEPeripheral_TaskID, WRK_NOTIFY_EVT); } else if (cmd == CMD_ID_CLRLOG && len > 2) { // Clear memory measures if (ibuf[1] == 0x12 && ibuf[2] == 0x34) { clear_memo(); olen = 2; } #endif #if (DEV_SERVICES & SERVICE_BINDKEY) } else if (cmd == CMD_ID_BKEY) { // Get/set beacon bindkey if (len == sizeof(bindkey) + 1) { if(memcmp(bindkey, &ibuf[1], sizeof(bindkey))) { memcpy(bindkey, &ibuf[1], sizeof(bindkey)); flash_write_cfg(&bindkey, EEP_ID_KEY, sizeof(bindkey)); bthome_beacon_init(); } } if (flash_read_cfg(&bindkey, EEP_ID_KEY, sizeof(bindkey)) == sizeof(bindkey)) { memcpy(&obuf[1], bindkey, sizeof(bindkey)); olen = sizeof(bindkey) + 1; } else { // No bindkey in EEP! obuf[1] = 0xff; olen = 2; } #endif #if (DEV_SERVICES & SERVICE_FINDMY) } else if (cmd == CMD_ID_FDMKEY) { // Get/set findmy key if (len == sizeof(findmy_key)/2 + 2) { if(ibuf[1] == 3) { memcpy(findmy_key_new, &ibuf[2], SIZE_FINDMY_KEY/2); memcpy(&obuf[2], findmy_key_new, SIZE_FINDMY_KEY/2); obuf[1] = 3; olen = SIZE_FINDMY_KEY/2 + 2; } else if(ibuf[1] == 4) { memcpy(&findmy_key_new[SIZE_FINDMY_KEY/2], &ibuf[2], SIZE_FINDMY_KEY/2); memcpy(&obuf[2], &findmy_key_new[SIZE_FINDMY_KEY/2], SIZE_FINDMY_KEY/2); if(memcmp(findmy_key, findmy_key_new, SIZE_FINDMY_KEY)) { memcpy(findmy_key, findmy_key_new, SIZE_FINDMY_KEY); flash_write_cfg(findmy_key, EEP_ID_FDK, sizeof(findmy_key)); findmy_key_new[0] |= 0xC0; swap_mac(findmy_key_new, findmy_key_new); if(memcmp(ownPublicAddr, findmy_key_new, MAC_LEN)) { memcpy(ownPublicAddr, findmy_key_new, MAC_LEN); flash_write_cfg(ownPublicAddr, EEP_ID_MAC, MAC_LEN); wrk.reboot |= 1; } } obuf[1] = 4; olen = SIZE_FINDMY_KEY/2 + 2; } else { obuf[1] = 0xff; olen = 2; } } else if (len == 2) { if(ibuf[1] == 1) { if (flash_read_cfg(findmy_key, EEP_ID_FDK, sizeof(findmy_key)) == sizeof(findmy_key)) { memcpy(&obuf[2], findmy_key, SIZE_FINDMY_KEY/2); obuf[1] = 1; olen = SIZE_FINDMY_KEY/2 + 2; } else { // No findmy key in EEP! obuf[1] = 0xfe; olen = 2; } } else if(ibuf[1] == 2) { if (flash_read_cfg(findmy_key, EEP_ID_FDK, sizeof(findmy_key)) == sizeof(findmy_key)) { memcpy(&obuf[2], &findmy_key[SIZE_FINDMY_KEY/2], SIZE_FINDMY_KEY/2); obuf[1] = 2; olen = SIZE_FINDMY_KEY/2 + 2; } else { // No findmy key in EEP! obuf[1] = 0xfe; olen = 2; } } else { obuf[1] = 0xff; olen = 2; } } else { obuf[1] = 0xff; olen = 2; } #endif #if defined(GPIO_BUZZER) && defined(PWM_CHL_BUZZER) } else if (cmd == CMD_ID_BUZZER) { if(len == 2 && ibuf[1] == 0) pwm_buzzer_stop(); else pwm_buzzer_start(); olen = 2; #endif } else if (cmd == CMD_ID_SERIAL) { memcpy(&obuf[1], devInfoSerialNumber, sizeof(devInfoSerialNumber)-1); olen = 1 + sizeof(devInfoSerialNumber)-1; } else if (cmd == CMD_ID_FLASH_ID) { memcpy(&obuf[1], (uint8_t *)&phy_flash.IdentificationID, 8); olen = 1 + 8; } else if (cmd == CMD_ID_MTU) { if(len >= 2) { if (ibuf[1] <= MTU_SIZE) { ATT_UpdateMtuSize(gapRole_ConnectionHandle, ibuf[1]); obuf[1] = gAttMtuSize[gapRole_ConnectionHandle]; } else obuf[1] = 0xff; } else obuf[1] = gAttMtuSize[gapRole_ConnectionHandle]; olen = 2; } else if (cmd == CMD_ID_REBOOT) { if(len >= 2) { wrk.reboot = ibuf[1]; obuf[1] = ibuf[1]; } else obuf[1] = wrk.reboot; olen = 2; } else if (cmd == CMD_ID_MEASURE) { olen = make_measure_msg(obuf); #if (DEV_SERVICES & SERVICE_SCREEN) } else if (cmd == CMD_ID_LCD_DUMP) { // Get/set lcd buf if (--len > sizeof(lcdd.display_buff)) len = sizeof(lcdd.display_buff); if (len) { lcdd.chow_ext_ut = clkt.utc_time_sec + 600; memcpy(lcdd.display_buff, &ibuf[1], len); update_lcd(); } else { lcdd.chow_ext_ut = 0; chow_lcd(1); } memcpy(&obuf[1], lcdd.display_buff, sizeof(lcdd.display_buff)); olen = 1 + sizeof(lcdd.display_buff); #endif #if (DEV_SERVICES & SERVICE_SCREEN) && (OTA_TYPE == OTA_TYPE_APP) } else if (cmd == CMD_ID_EXTDATA) { // Show ext. small and big number if (--len > sizeof(lcdd.ext)) len = sizeof(lcdd.ext); if (len) { memcpy(&lcdd.ext, &ibuf[1], len); if(lcdd.ext.vtime_sec == 0xffff) lcdd.chow_ext_ut = 0xffffffff; else lcdd.chow_ext_ut = clkt.utc_time_sec + lcdd.ext.vtime_sec; chow_ext_data(); } else { lcdd.chow_ext_ut = 0; chow_lcd(1); } memcpy(&obuf[1], &lcdd.ext, sizeof(lcdd.ext)); olen = 1 + sizeof(lcdd.ext); #endif } else if (cmd == CMD_ID_UTC_TIME) { // Get/set utc time if (len > 4) { clkt.utc_time_sec = tmp; #if (DEV_SERVICES & SERVICE_TIME_ADJUST) @TODO #endif clkt.utc_time_tik = clock_time_rtc(); //clkt.utc_time_add = 0; } tmp = get_utc_time_sec(); memcpy(&obuf[1], &tmp, 4); #if (DEV_SERVICES & SERVICE_TIME_ADJUST) memcpy(&obuf[4 + 1], &clkt.utc_set_time_sec, sizeof(clkt.utc_set_time_sec)); olen = 4 + sizeof(clkt.utc_set_time_sec) + 1; #else olen = 4 + 1; #endif // SERVICE_TIME_ADJUST #if (DEV_SERVICES & SERVICE_TIME_ADJUST) } else if (cmd == CMD_ID_TADJUST) { // Get/set adjust time clock delta (in 1/16 us for 1 sec) if (len > 4) { clkt.delta_time = tmp; flash_write_cfg(&clkt.delta_time, EEP_ID_TIM, sizeof(&clkt.delta_time)); } memcpy(&send_buf[1], &clkt.delta_time, sizeof(clkt.delta_time)); olen = sizeof(clkt.delta_time) + 1; #endif } else if (cmd == CMD_ID_DEV_MAC) { if (len > MAC_LEN) { if(memcmp(ownPublicAddr, &ibuf[1], MAC_LEN)) { memcpy(ownPublicAddr, &ibuf[1], MAC_LEN); flash_write_cfg(ownPublicAddr, EEP_ID_MAC, MAC_LEN); wrk.reboot |= 1; } } memcpy(&obuf[1], ownPublicAddr, MAC_LEN); olen = MAC_LEN + 1; #if (OTA_TYPE == OTA_TYPE_BOOT) } else if (cmd == CMD_ID_FIX_MAC && len > 1) { fix_mac(ibuf[1]); olen = 2; #endif } else if (cmd == CMD_ID_DNAME) { if (len > 1 && len <= GAP_DEVICE_NAME_LEN) { if(ibuf[1] == 0) set_def_name(); else { len--; memcpy(&gapRole_ScanRspData[2], &ibuf[1], len); flash_write_cfg(&gapRole_ScanRspData[2], EEP_ID_DVN, len); } set_dev_name(); } olen = gapRole_ScanRspData[0]; memcpy(&obuf[1], &gapRole_ScanRspData[2], olen - 1); //---------- Debug commands (unsupported in different versions!): } else if (cmd == CMD_ID_EEP_RW && len > 2) { obuf[1] = ibuf[1]; obuf[2] = ibuf[2]; uint16_t id = (uint16_t)tmp; if(len > 3) { flash_write_cfg(&ibuf[3], id, len - 3); } int16_t i = flash_read_cfg(&obuf[3], id, SEND_DATA_SIZE); if(i < 0) { obuf[1] = (uint8_t)(i & 0xff); // Error olen = 2; } else olen = i + 3; } else if (cmd == CMD_ID_MEM_RW && len > 4) { // Read/Write memory uint8_t *p = (uint8_t *)tmp; if(len > 5) { len -= 5; memcpy(p, &ibuf[5], len); } else len = SEND_DATA_SIZE; memcpy(obuf, ibuf, 5); memcpy(&obuf[5], p, len); olen = len + 1 + 4; } else if (cmd == CMD_ID_REG_RW && len > 4) { // Read/Write 32 bits register (aligned) volatile uint32_t *p = (volatile uint32_t *)tmp; if(len > 8) { tmp = ibuf[5] | (ibuf[6]<<8) | (ibuf[7]<<16) | (ibuf[8]<<24); *p = tmp; } else { obuf[1] = 0xfe; // Error size olen = 2; } tmp = *p; memcpy(obuf, ibuf, 5); memcpy(&obuf[5], &tmp, 4); olen = 1 + 4 + 4; #if (DEV_SERVICES & SERVICE_SCREEN) } else if (cmd == CMD_ID_DEBUG) { // debug - send to lcd if (--len) { send_to_lcd(&ibuf[1], len); } #endif } else { obuf[1] = 0xff; // Error cmd olen = 2; } } return olen; }