mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-12-24 19:53:08 +00:00
8582670a34
Co-authored-by: あく <alleteam@gmail.com> Co-authored-by: gornekich <n.gorbadey@gmail.com>
298 lines
8.1 KiB
C
298 lines
8.1 KiB
C
#include <furi.h>
|
|
#include <furi_hal.h>
|
|
#include "ibutton_writer.h"
|
|
#include "ibutton_key_command.h"
|
|
|
|
/*********************** PRIVATE ***********************/
|
|
|
|
struct iButtonWriter {
|
|
OneWireHost* host;
|
|
};
|
|
|
|
static void writer_write_one_bit(iButtonWriter* writer, bool value, uint32_t delay) {
|
|
onewire_host_write_bit(writer->host, value);
|
|
furi_delay_us(delay);
|
|
}
|
|
|
|
static void writer_write_byte_ds1990(iButtonWriter* writer, uint8_t data) {
|
|
for(uint8_t n_bit = 0; n_bit < 8; n_bit++) {
|
|
onewire_host_write_bit(writer->host, data & 1);
|
|
furi_delay_us(5000);
|
|
data = data >> 1;
|
|
}
|
|
}
|
|
|
|
static bool writer_compare_key_ds1990(iButtonWriter* writer, iButtonKey* key) {
|
|
bool result = false;
|
|
|
|
if(ibutton_key_get_type(key) == iButtonKeyDS1990) {
|
|
FURI_CRITICAL_ENTER();
|
|
bool presence = onewire_host_reset(writer->host);
|
|
|
|
if(presence) {
|
|
onewire_host_write(writer->host, DS1990_CMD_READ_ROM);
|
|
|
|
result = true;
|
|
for(uint8_t i = 0; i < ibutton_key_get_data_size(key); i++) {
|
|
if(ibutton_key_get_data_p(key)[i] != onewire_host_read(writer->host)) {
|
|
result = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
FURI_CRITICAL_EXIT();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static bool writer_write_TM2004(iButtonWriter* writer, iButtonKey* key) {
|
|
uint8_t answer;
|
|
bool result = true;
|
|
|
|
if(ibutton_key_get_type(key) == iButtonKeyDS1990) {
|
|
FURI_CRITICAL_ENTER();
|
|
|
|
// write rom, addr is 0x0000
|
|
onewire_host_reset(writer->host);
|
|
onewire_host_write(writer->host, TM2004_CMD_WRITE_ROM);
|
|
onewire_host_write(writer->host, 0x00);
|
|
onewire_host_write(writer->host, 0x00);
|
|
|
|
// write key
|
|
for(uint8_t i = 0; i < ibutton_key_get_data_size(key); i++) {
|
|
// write key byte
|
|
onewire_host_write(writer->host, ibutton_key_get_data_p(key)[i]);
|
|
answer = onewire_host_read(writer->host);
|
|
// TODO: check answer CRC
|
|
|
|
// pulse indicating that data is correct
|
|
furi_delay_us(600);
|
|
writer_write_one_bit(writer, 1, 50000);
|
|
|
|
// read written key byte
|
|
answer = onewire_host_read(writer->host); //-V519
|
|
|
|
// check that written and read are same
|
|
if(ibutton_key_get_data_p(key)[i] != answer) {
|
|
result = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!writer_compare_key_ds1990(writer, key)) {
|
|
result = false;
|
|
}
|
|
|
|
onewire_host_reset(writer->host);
|
|
|
|
FURI_CRITICAL_EXIT();
|
|
} else {
|
|
result = false;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static bool writer_write_1990_1(iButtonWriter* writer, iButtonKey* key) {
|
|
bool result = false;
|
|
|
|
if(ibutton_key_get_type(key) == iButtonKeyDS1990) {
|
|
FURI_CRITICAL_ENTER();
|
|
|
|
// unlock
|
|
onewire_host_reset(writer->host);
|
|
onewire_host_write(writer->host, RW1990_1_CMD_WRITE_RECORD_FLAG);
|
|
furi_delay_us(10);
|
|
writer_write_one_bit(writer, 0, 5000);
|
|
|
|
// write key
|
|
onewire_host_reset(writer->host);
|
|
onewire_host_write(writer->host, RW1990_1_CMD_WRITE_ROM);
|
|
for(uint8_t i = 0; i < ibutton_key_get_data_size(key); i++) {
|
|
// inverted key for RW1990.1
|
|
writer_write_byte_ds1990(writer, ~ibutton_key_get_data_p(key)[i]);
|
|
furi_delay_us(30000);
|
|
}
|
|
|
|
// lock
|
|
onewire_host_write(writer->host, RW1990_1_CMD_WRITE_RECORD_FLAG);
|
|
writer_write_one_bit(writer, 1, 10000);
|
|
|
|
FURI_CRITICAL_EXIT();
|
|
|
|
if(writer_compare_key_ds1990(writer, key)) {
|
|
result = true;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static bool writer_write_1990_2(iButtonWriter* writer, iButtonKey* key) {
|
|
bool result = false;
|
|
|
|
if(ibutton_key_get_type(key) == iButtonKeyDS1990) {
|
|
FURI_CRITICAL_ENTER();
|
|
|
|
// unlock
|
|
onewire_host_reset(writer->host);
|
|
onewire_host_write(writer->host, RW1990_2_CMD_WRITE_RECORD_FLAG);
|
|
furi_delay_us(10);
|
|
writer_write_one_bit(writer, 1, 5000);
|
|
|
|
// write key
|
|
onewire_host_reset(writer->host);
|
|
onewire_host_write(writer->host, RW1990_2_CMD_WRITE_ROM);
|
|
for(uint8_t i = 0; i < ibutton_key_get_data_size(key); i++) {
|
|
writer_write_byte_ds1990(writer, ibutton_key_get_data_p(key)[i]);
|
|
furi_delay_us(30000);
|
|
}
|
|
|
|
// lock
|
|
onewire_host_write(writer->host, RW1990_2_CMD_WRITE_RECORD_FLAG);
|
|
writer_write_one_bit(writer, 0, 10000);
|
|
|
|
FURI_CRITICAL_EXIT();
|
|
|
|
if(writer_compare_key_ds1990(writer, key)) {
|
|
result = true;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
// TODO: adapt and test
|
|
static bool writer_write_TM01(
|
|
iButtonWriter* writer,
|
|
iButtonKey type,
|
|
const uint8_t* key,
|
|
uint8_t key_length) {
|
|
bool result = true;
|
|
|
|
{
|
|
// TODO test and encoding
|
|
FURI_CRITICAL_ENTER();
|
|
|
|
// unlock
|
|
onewire_host_reset(writer->host);
|
|
onewire_host_write(writer->host, TM01::CMD_WRITE_RECORD_FLAG);
|
|
onewire_write_one_bit(1, 10000);
|
|
|
|
// write key
|
|
onewire_host_reset(writer->host);
|
|
onewire_host_write(writer->host, TM01::CMD_WRITE_ROM);
|
|
|
|
// TODO: key types
|
|
//if(type == KEY_METAKOM || type == KEY_CYFRAL) {
|
|
//} else {
|
|
for(uint8_t i = 0; i < key->get_type_data_size(); i++) {
|
|
write_byte_ds1990(key->get_data()[i]);
|
|
furi_delay_us(10000);
|
|
}
|
|
//}
|
|
|
|
// lock
|
|
onewire_host_write(writer->host, TM01::CMD_WRITE_RECORD_FLAG);
|
|
onewire_write_one_bit(0, 10000);
|
|
|
|
FURI_CRITICAL_EXIT();
|
|
}
|
|
|
|
if(!compare_key_ds1990(key)) {
|
|
result = false;
|
|
}
|
|
|
|
{
|
|
FURI_CRITICAL_ENTER();
|
|
|
|
if(key->get_key_type() == iButtonKeyType::KeyMetakom ||
|
|
key->get_key_type() == iButtonKeyType::KeyCyfral) {
|
|
onewire_host_reset(writer->host);
|
|
if(key->get_key_type() == iButtonKeyType::KeyCyfral)
|
|
onewire_host_write(writer->host, TM01::CMD_SWITCH_TO_CYFRAL);
|
|
else
|
|
onewire_host_write(writer->host, TM01::CMD_SWITCH_TO_METAKOM);
|
|
onewire_write_one_bit(1);
|
|
}
|
|
|
|
FURI_CRITICAL_EXIT();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
*/
|
|
|
|
static iButtonWriterResult writer_write_DS1990(iButtonWriter* writer, iButtonKey* key) {
|
|
iButtonWriterResult result = iButtonWriterNoDetect;
|
|
bool same_key = writer_compare_key_ds1990(writer, key);
|
|
|
|
if(!same_key) {
|
|
// currently we can write:
|
|
// RW1990_1, TM08v2, TM08vi-2 by write_1990_1()
|
|
// RW1990_2 by write_1990_2()
|
|
// RW2004, RW2004, TM2004 with EEPROM by write_TM2004();
|
|
|
|
bool write_result = true;
|
|
do {
|
|
if(writer_write_1990_1(writer, key)) break;
|
|
if(writer_write_1990_2(writer, key)) break;
|
|
if(writer_write_TM2004(writer, key)) break;
|
|
write_result = false;
|
|
} while(false);
|
|
|
|
if(write_result) {
|
|
result = iButtonWriterOK;
|
|
} else {
|
|
result = iButtonWriterCannotWrite;
|
|
}
|
|
} else {
|
|
result = iButtonWriterSameKey;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*********************** PUBLIC ***********************/
|
|
|
|
iButtonWriter* ibutton_writer_alloc(OneWireHost* host) {
|
|
iButtonWriter* writer = malloc(sizeof(iButtonWriter));
|
|
writer->host = host;
|
|
return writer;
|
|
}
|
|
|
|
void ibutton_writer_free(iButtonWriter* writer) {
|
|
free(writer);
|
|
}
|
|
|
|
iButtonWriterResult ibutton_writer_write(iButtonWriter* writer, iButtonKey* key) {
|
|
iButtonWriterResult result = iButtonWriterNoDetect;
|
|
|
|
furi_kernel_lock();
|
|
bool blank_present = onewire_host_reset(writer->host);
|
|
furi_kernel_unlock();
|
|
|
|
if(blank_present) {
|
|
switch(ibutton_key_get_type(key)) {
|
|
case iButtonKeyDS1990:
|
|
result = writer_write_DS1990(writer, key);
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void ibutton_writer_start(iButtonWriter* writer) {
|
|
furi_hal_power_enable_otg();
|
|
onewire_host_start(writer->host);
|
|
}
|
|
|
|
void ibutton_writer_stop(iButtonWriter* writer) {
|
|
onewire_host_stop(writer->host);
|
|
furi_hal_power_disable_otg();
|
|
}
|