* Furi: rename and move core * Furi: drop CMSIS_OS header and unused api, partially refactor and cleanup the rest * Furi: CMSIS_OS drop and refactoring. * Furi: refactoring, remove cmsis legacy * Furi: fix incorrect assert on queue deallocation, cleanup timer * Furi: improve delay api, get rid of floats * hal: dropped furi_hal_crc * Furi: move DWT based delay to cortex HAL * Furi: update core documentation Co-authored-by: hedger <hedger@nanode.su>
		
			
				
	
	
		
			299 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			299 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);
 | 
						|
 | 
						|
            // 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();
 | 
						|
}
 |