#include #include #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); // 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(); }