#include "atca_basic.h"
#include "atca_version.h"
#include "host/atca_host.h"
#if defined(ATCA_USE_CONSTANT_HOST_NONCE)
#if defined(_MSC_VER)
#pragma message("Warning : Using a constant host nonce with atcab_read_enc, atcab_write_enc, etcc., can allow spoofing of a device by replaying previously recorded messages")
#else
#warning "Using a constant host nonce with atcab_read_enc, atcab_write_enc, etcc., can allow spoofing of a device by replaying previously recorded messages"
#endif
#endif
const char atca_version[] = ATCA_LIBRARY_VERSION_DATE;
ATCADevice _gDevice = NULL;
#ifdef ATCA_NO_HEAP
struct atca_command g_atcab_command;
struct atca_iface g_atcab_iface;
struct atca_device g_atcab_device;
#endif
#define MAX_BUSES 4
ATCA_STATUS atcab_version(char *ver_str)
{
strcpy(ver_str, atca_version);
return ATCA_SUCCESS;
}
ATCA_STATUS atcab_init(ATCAIfaceCfg *cfg)
{
ATCA_STATUS status = ATCA_GEN_FAIL;
if (_gDevice)
{
atcab_release();
}
#ifdef ATCA_NO_HEAP
g_atcab_device.mCommands = &g_atcab_command;
g_atcab_device.mIface = &g_atcab_iface;
status = initATCADevice(cfg, &g_atcab_device);
if (status != ATCA_SUCCESS)
{
return status;
}
_gDevice = &g_atcab_device;
#else
_gDevice = newATCADevice(cfg);
if (_gDevice == NULL)
{
return ATCA_GEN_FAIL;
}
#endif
if (cfg->devtype == ATECC608A)
{
if ((status = atcab_read_bytes_zone(ATCA_ZONE_CONFIG, 0, ATCA_CHIPMODE_OFFSET, &_gDevice->mCommands->clock_divider, 1)) != ATCA_SUCCESS)
{
return status;
}
_gDevice->mCommands->clock_divider &= ATCA_CHIPMODE_CLOCK_DIV_MASK;
}
return ATCA_SUCCESS;
}
ATCA_STATUS atcab_init_device(ATCADevice ca_device)
{
if (ca_device == NULL)
{
return ATCA_BAD_PARAM;
}
if (atGetCommands(ca_device) == NULL || atGetIFace(ca_device) == NULL)
{
return ATCA_GEN_FAIL;
}
if (_gDevice)
{
atcab_release();
}
_gDevice = ca_device;
return ATCA_SUCCESS;
}
ATCA_STATUS atcab_release(void)
{
#ifdef ATCA_NO_HEAP
ATCA_STATUS status = releaseATCADevice(_gDevice);
if (status != ATCA_SUCCESS)
{
return status;
}
_gDevice = NULL;
#else
deleteATCADevice(&_gDevice);
#endif
return ATCA_SUCCESS;
}
ATCADevice atcab_get_device(void)
{
return _gDevice;
}
ATCADeviceType atcab_get_device_type(void)
{
if (_gDevice)
{
return _gDevice->mIface->mIfaceCFG->devtype;
}
else
{
return ATCA_DEV_UNKNOWN;
}
}
ATCA_STATUS atcab_wakeup(void)
{
if (_gDevice == NULL)
{
return ATCA_GEN_FAIL;
}
return atwake(_gDevice->mIface);
}
ATCA_STATUS atcab_idle(void)
{
if (_gDevice == NULL)
{
return ATCA_GEN_FAIL;
}
return atidle(_gDevice->mIface);
}
ATCA_STATUS atcab_sleep(void)
{
if (_gDevice == NULL)
{
return ATCA_GEN_FAIL;
}
return atsleep(_gDevice->mIface);
}
ATCA_STATUS atcab_cfg_discover(ATCAIfaceCfg cfg_array[], int max_ifaces)
{
int iface_num = 0;
int found = 0;
int i = 0;
#ifdef ATCA_HAL_I2C
int i2c_buses[MAX_BUSES];
memset(i2c_buses, -1, sizeof(i2c_buses));
hal_i2c_discover_buses(i2c_buses, MAX_BUSES);
for (i = 0; i < MAX_BUSES && iface_num < max_ifaces; i++)
{
if (i2c_buses[i] != -1)
{
hal_i2c_discover_devices(i2c_buses[i], &cfg_array[iface_num], &found);
iface_num += found;
}
}
#endif
#ifdef ATCA_HAL_SWI
int swi_buses[MAX_BUSES];
memset(swi_buses, -1, sizeof(swi_buses));
hal_swi_discover_buses(swi_buses, MAX_BUSES);
for (i = 0; i < MAX_BUSES && iface_num < max_ifaces; i++)
{
if (swi_buses[i] != -1)
{
hal_swi_discover_devices(swi_buses[i], &cfg_array[iface_num], &found);
iface_num += found;
}
}
#endif
#ifdef ATCA_HAL_UART
int uart_buses[MAX_BUSES];
memset(uart_buses, -1, sizeof(uart_buses));
hal_uart_discover_buses(uart_buses, MAX_BUSES);
for (i = 0; i < MAX_BUSES && iface_num < max_ifaces; i++)
{
if (uart_buses[i] != -1)
{
hal_uart_discover_devices(uart_buses[i], &cfg_array[iface_num], &found);
iface_num += found;
}
}
#endif
#ifdef ATCA_HAL_KIT_CDC
int cdc_buses[MAX_BUSES];
memset(cdc_buses, -1, sizeof(cdc_buses));
hal_kit_cdc_discover_buses(cdc_buses, MAX_BUSES);
for (i = 0; i < MAX_BUSES && iface_num < max_ifaces; i++)
{
if (cdc_buses[i] != -1)
{
hal_kit_cdc_discover_devices(cdc_buses[i], &cfg_array[iface_num++], &found);
iface_num += found;
}
}
#endif
#ifdef ATCA_HAL_KIT_HID
int hid_buses[MAX_BUSES];
memset(hid_buses, -1, sizeof(hid_buses));
hal_kit_hid_discover_buses(hid_buses, MAX_BUSES);
for (i = 0; i < MAX_BUSES && iface_num < max_ifaces; i++)
{
if (hid_buses[i] != -1)
{
hal_kit_hid_discover_devices(hid_buses[i], &cfg_array[iface_num++], &found);
iface_num += found;
}
}
#endif
return ATCA_SUCCESS;
}
ATCA_STATUS _atcab_exit(void)
{
return atcab_idle();
}
ATCA_STATUS atcab_get_addr(uint8_t zone, uint16_t slot, uint8_t block, uint8_t offset, uint16_t* addr)
{
ATCA_STATUS status = ATCA_SUCCESS;
uint8_t mem_zone = zone & 0x03;
if (addr == NULL)
{
return ATCA_BAD_PARAM;
}
if ((mem_zone != ATCA_ZONE_CONFIG) && (mem_zone != ATCA_ZONE_DATA) && (mem_zone != ATCA_ZONE_OTP))
{
return ATCA_BAD_PARAM;
}
do
{
*addr = 0;
offset = offset & (uint8_t)0x07;
if ((mem_zone == ATCA_ZONE_CONFIG) || (mem_zone == ATCA_ZONE_OTP))
{
*addr = block << 3;
*addr |= offset;
}
else {
*addr = slot << 3;
*addr |= offset;
*addr |= block << 8;
}
}
while (0);
return status;
}
ATCA_STATUS atcab_get_zone_size(uint8_t zone, uint16_t slot, size_t* size)
{
ATCA_STATUS status = ATCA_SUCCESS;
if (size == NULL)
{
return ATCA_BAD_PARAM;
}
if (_gDevice->mIface->mIfaceCFG->devtype == ATSHA204A)
{
switch (zone)
{
case ATCA_ZONE_CONFIG: *size = 88; break;
case ATCA_ZONE_OTP: *size = 64; break;
case ATCA_ZONE_DATA: *size = 32; break;
default: status = ATCA_BAD_PARAM; break;
}
}
else if (_gDevice->mIface->mIfaceCFG->devtype == ATSHA206A)
{
switch (zone)
{
case ATCA_ZONE_CONFIG: *size = 88; break;
case ATCA_ZONE_OTP: *size = 0; break;
case ATCA_ZONE_DATA: *size = 32; break;
default: status = ATCA_BAD_PARAM; break;
}
}
else
{
switch (zone)
{
case ATCA_ZONE_CONFIG: *size = 128; break;
case ATCA_ZONE_OTP: *size = 64; break;
case ATCA_ZONE_DATA:
if (slot < 8)
{
*size = 36;
}
else if (slot == 8)
{
*size = 416;
}
else if (slot < 16)
{
*size = 72;
}
else
{
status = ATCA_BAD_PARAM;
}
break;
default: status = ATCA_BAD_PARAM; break;
}
}
return status;
}