#include "key-emulator.h" #include KeyEmulator::~KeyEmulator() { onewire_slave->stop(); } KeyEmulator::KeyEmulator(OneWireSlave* _onewire_slave) : dallas_key{0, 0, 0, 0, 0, 0, 0} { onewire_slave = _onewire_slave; auto cb = cbc::obtain_connector(this, &KeyEmulator::result_callback); onewire_slave->set_result_callback(cb, this); } void KeyEmulator::start(iButtonKey* key) { anything_emulated = false; stop(); switch(key->get_key_type()) { case iButtonKeyType::KeyDallas: start_dallas_emulate(key); break; case iButtonKeyType::KeyCyfral: start_cyfral_emulate(key); break; case iButtonKeyType::KeyMetakom: start_metakom_emulate(key); break; } } bool KeyEmulator::emulated() { bool result = false; if(anything_emulated) { anything_emulated = false; result = true; } return result; } void KeyEmulator::stop() { onewire_slave->stop(); pulser.stop(); } void KeyEmulator::start_cyfral_emulate(iButtonKey* key) { furi_assert(key->get_key_type() == iButtonKeyType::KeyCyfral); furi_assert(key->get_type_data_size() == 2); const uint32_t cyfral_period_full = 8000; const uint32_t cyfral_period_one[2] = { uint32_t(cyfral_period_full * 0.33f), uint32_t(cyfral_period_full * 0.66f)}; const uint32_t cyfral_period_zero[2] = { uint32_t(cyfral_period_full * 0.66f), uint32_t(cyfral_period_full * 0.33f)}; uint8_t pd_index = 0; uint8_t* key_data = key->get_data(); // start nibble set_pulse_data_cyfral(pd_index, cyfral_period_zero); pd_index++; set_pulse_data_cyfral(pd_index, cyfral_period_zero); pd_index++; set_pulse_data_cyfral(pd_index, cyfral_period_zero); pd_index++; set_pulse_data_cyfral(pd_index, cyfral_period_one); pd_index++; // data nibbles x 8 for(int8_t i = key->get_type_data_size() - 1; i >= 0; i--) { for(int8_t j = 3; j >= 0; j--) { switch((key_data[i] >> (j * 2)) & 0b00000011) { case 0b11: set_pulse_data_cyfral(pd_index, cyfral_period_one); pd_index++; set_pulse_data_cyfral(pd_index, cyfral_period_one); pd_index++; set_pulse_data_cyfral(pd_index, cyfral_period_one); pd_index++; set_pulse_data_cyfral(pd_index, cyfral_period_zero); pd_index++; break; case 0b10: set_pulse_data_cyfral(pd_index, cyfral_period_one); pd_index++; set_pulse_data_cyfral(pd_index, cyfral_period_one); pd_index++; set_pulse_data_cyfral(pd_index, cyfral_period_zero); pd_index++; set_pulse_data_cyfral(pd_index, cyfral_period_one); pd_index++; break; case 0b01: set_pulse_data_cyfral(pd_index, cyfral_period_one); pd_index++; set_pulse_data_cyfral(pd_index, cyfral_period_zero); pd_index++; set_pulse_data_cyfral(pd_index, cyfral_period_one); pd_index++; set_pulse_data_cyfral(pd_index, cyfral_period_one); pd_index++; break; case 0b00: set_pulse_data_cyfral(pd_index, cyfral_period_zero); pd_index++; set_pulse_data_cyfral(pd_index, cyfral_period_one); pd_index++; set_pulse_data_cyfral(pd_index, cyfral_period_one); pd_index++; set_pulse_data_cyfral(pd_index, cyfral_period_one); pd_index++; break; default: // cannot be anyway furi_check(false); break; } } } // 4 (nibbles) x (8 data + 1 start) = 4 x 9 = 36 if(pd_index != 36) { // something is very wrong furi_check(false); } pulser.set_periods(pulse_data, 72, false); pulser.start(); } void KeyEmulator::start_metakom_emulate(iButtonKey* key) { furi_assert(key->get_key_type() == iButtonKeyType::KeyMetakom); furi_assert(key->get_type_data_size() == 4); const uint32_t metakom_period_full = 8000; const uint32_t metakom_period_zero[2] = { uint32_t(metakom_period_full * 0.33f), uint32_t(metakom_period_full * 0.66f)}; const uint32_t metakom_period_one[2] = { uint32_t(metakom_period_full * 0.66f), uint32_t(metakom_period_full * 0.33f)}; uint8_t pd_index = 0; uint8_t* key_data = key->get_data(); // start pulse pulse_data[0] = metakom_period_full * 4; // start triplet set_pulse_data_metakom(pd_index, metakom_period_zero); pd_index++; set_pulse_data_metakom(pd_index, metakom_period_one); pd_index++; set_pulse_data_metakom(pd_index, metakom_period_zero); pd_index++; for(int8_t i = key->get_type_data_size() - 1; i >= 0; i--) { for(int8_t j = 7; j >= 0; j--) { if(((key_data[i] >> j) & 0b00000001) == 1) { set_pulse_data_metakom(pd_index, metakom_period_one); pd_index++; } else { set_pulse_data_metakom(pd_index, metakom_period_zero); pd_index++; } } } // 4 byte x 8 bits + 3 start bits = 35 if(pd_index != 35) { // something is very wrong furi_check(false); } pulser.set_periods(pulse_data, 71, false); pulser.start(); } void KeyEmulator::start_dallas_emulate(iButtonKey* key) { furi_assert(key->get_key_type() == iButtonKeyType::KeyDallas); furi_assert(key->get_type_data_size() == 8); onewire_slave->deattach(); memcpy(dallas_key.id_storage, key->get_data(), key->get_type_data_size()); onewire_slave->attach(&dallas_key); onewire_slave->start(); } void KeyEmulator::set_pulse_data_cyfral(uint8_t index, const uint32_t* data) { pulse_data[index * 2] = data[0]; pulse_data[index * 2 + 1] = data[1]; } void KeyEmulator::set_pulse_data_metakom(uint8_t index, const uint32_t* data) { // damn start pulse pulse_data[(index * 2) + 1] = data[0]; pulse_data[(index * 2) + 2] = data[1]; } void KeyEmulator::result_callback(bool success, void* ctx) { KeyEmulator* _this = static_cast(ctx); _this->anything_emulated = true; }