#include <string.h>
#include <stdio.h>
#include "atca_hal.h"
#include "hal_swi_uart.h"
#include "atca_device.h"
#include "atca_execution.h"
static ATCASWIMaster_t swi_hal_data[MAX_SWI_BUSES];
#ifdef DEBUG_HAL
static void print_array(uint8_t *data, uint32_t data_size)
{
uint32_t n;
for (n = 0; n < data_size; n++)
{
printf("%.2x ", data[n]);
if (((n + 1) % 16) == 0)
{
printf("\r\n");
if ((n + 1) != data_size)
{
printf(" ");
}
}
}
if (data_size % 16 != 0)
{
printf("\r\n");
}
}
#endif
ATCA_STATUS hal_swi_discover_buses(int swi_buses[], int max_buses)
{
swi_uart_discover_buses(swi_buses, max_buses);
return ATCA_SUCCESS;
}
ATCA_STATUS hal_swi_discover_devices(int bus_num, ATCAIfaceCfg cfg[], int *found)
{
ATCAIfaceCfg *head = cfg;
ATCADevice device;
#ifdef ATCA_NO_HEAP
struct atca_device disc_device;
struct atca_command disc_command;
struct atca_iface disc_iface;
#endif
ATCAPacket packet;
ATCA_STATUS status;
uint8_t revs608[][4] = { { 0x00, 0x00, 0x60, 0x01 }, { 0x00, 0x00, 0x60, 0x02 } };
uint8_t revs508[][4] = { { 0x00, 0x00, 0x50, 0x00 } };
uint8_t revs108[][4] = { { 0x80, 0x00, 0x10, 0x01 } };
uint8_t revs204[][4] = { { 0x00, 0x02, 0x00, 0x08 }, { 0x00, 0x02, 0x00, 0x09 }, { 0x00, 0x04, 0x05, 0x00 } };
unsigned int i;
ATCAIfaceCfg discoverCfg = {
.iface_type = ATCA_SWI_IFACE,
.devtype = ATECC508A,
.atcaswi.bus = bus_num,
.wake_delay = 800,
.rx_retries = 3
};
if (bus_num < 0)
{
return ATCA_COMM_FAIL;
}
#ifdef ATCA_NO_HEAP
disc_device.mCommands = &disc_command;
disc_device.mIface = &disc_iface;
status = initATCADevice(&discoverCfg, &disc_device);
if (status != ATCA_SUCCESS)
{
return status;
}
device = &disc_device;
#else
device = newATCADevice(&discoverCfg);
if (device == NULL)
{
return ATCA_COMM_FAIL;
}
#endif
memset(packet.data, 0x00, sizeof(packet.data));
packet.param1 = INFO_MODE_REVISION;
packet.param2 = 0;
atInfo(device->mCommands, &packet);
if ((status = atca_execute_command(&packet, device)) != ATCA_SUCCESS)
{
return status;
}
discoverCfg.devtype = ATCA_DEV_UNKNOWN;
for (i = 0; i < (int)sizeof(revs608) / 4; i++)
{
if (memcmp(&packet.data[1], &revs608[i], 4) == 0)
{
discoverCfg.devtype = ATECC608A;
break;
}
}
for (i = 0; i < sizeof(revs508) / 4; i++)
{
if (memcmp(&packet.data[1], &revs508[i], 4) == 0)
{
discoverCfg.devtype = ATECC508A;
break;
}
}
for (i = 0; i < sizeof(revs204) / 4; i++)
{
if (memcmp(&packet.data[1], &revs204[i], 4) == 0)
{
discoverCfg.devtype = ATSHA204A;
break;
}
}
for (i = 0; i < sizeof(revs108) / 4; i++)
{
if (memcmp(&packet.data[1], &revs108[i], 4) == 0)
{
discoverCfg.devtype = ATECC108A;
break;
}
}
if (discoverCfg.devtype != ATCA_DEV_UNKNOWN)
{
(*found)++;
memcpy( (uint8_t*)head, (uint8_t*)&discoverCfg, sizeof(ATCAIfaceCfg));
head->devtype = discoverCfg.devtype;
head++;
}
atca_delay_ms(15);
#ifdef ATCA_NO_HEAP
releaseATCADevice(device);
#else
deleteATCADevice(&device);
#endif
return ATCA_SUCCESS;
}
ATCA_STATUS hal_swi_init(void *hal, ATCAIfaceCfg *cfg)
{
if (cfg->atcaswi.bus >= MAX_SWI_BUSES)
{
return ATCA_COMM_FAIL;
}
ATCASWIMaster_t* data = &swi_hal_data[cfg->atcaswi.bus];
if (data->ref_ct <= 0)
{
swi_uart_init(data);
data->bus_index = cfg->atcaswi.bus;
data->ref_ct = 1;
}
else
{
data->ref_ct++;
}
((ATCAHAL_t*)hal)->hal_data = data;
return ATCA_SUCCESS;
}
ATCA_STATUS hal_swi_post_init(ATCAIface iface)
{
return ATCA_SUCCESS;
}
ATCA_STATUS hal_swi_send_flag(ATCAIface iface, uint8_t data)
{
ATCA_STATUS status = ATCA_SUCCESS;
ATCAIfaceCfg *cfg = atgetifacecfg(iface);
uint8_t bit_mask, bit_data;
for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1)
{
bit_data = (bit_mask & data) ? 0x7F : 0x7D;
status |= swi_uart_send_byte(&swi_hal_data[cfg->atcaswi.bus], bit_data);
}
if (status != ATCA_SUCCESS)
{
return ATCA_COMM_FAIL;
}
else
{
return ATCA_SUCCESS;
}
}
ATCA_STATUS hal_swi_send(ATCAIface iface, uint8_t *txdata, int txlength)
{
#ifdef DEBUG_HAL
printf("hal_swi_send()\r\n");
printf("\r\nCommand Packet (size:0x%.4x)\r\n", txlength);
printf("Count : %.2x\r\n", txdata[1]);
printf("Opcode : %.2x\r\n", txdata[2]);
printf("Param1 : %.2x\r\n", txdata[3]);
printf("Param2 : "); print_array(&txdata[4], 2);
if (txdata[1] > 7)
{
printf("Data : "); print_array(&txdata[6], txdata[1] - 7);
}
printf("CRC : "); print_array(&txdata[txdata[1] - 1], 2);
printf("\r\n");
#endif
ATCA_STATUS status = ATCA_SUCCESS;
ATCAIfaceCfg *cfg = atgetifacecfg(iface);
uint8_t i, bit_mask, bit_data;
txdata++;
status = hal_swi_send_flag(iface, SWI_FLAG_CMD);
if (status == ATCA_SUCCESS)
{
for (i = 0; i < txlength; i++)
{
for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1)
{
bit_data = (bit_mask & *txdata) ? 0x7F : 0x7D;
status = swi_uart_send_byte(&swi_hal_data[cfg->atcaswi.bus], bit_data);
if (status != ATCA_SUCCESS)
{
return ATCA_COMM_FAIL;
}
}
txdata++;
}
return ATCA_SUCCESS;
}
return ATCA_COMM_FAIL;
}
ATCA_STATUS hal_swi_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength)
{
#ifdef DEBUG_HAL
printf("hal_swi_receive()\r\n");
#endif
ATCA_STATUS status = !ATCA_SUCCESS;
ATCAIfaceCfg *cfg = atgetifacecfg(iface);
int bus = cfg->atcaswi.bus;
int retries = cfg->rx_retries;
uint8_t bit_mask, *head_buff, bit_data, count;
uint8_t i = 0;
uint16_t rxdata_max_size = *rxlength;
*rxlength = 0;
if (rxdata_max_size < 1)
{
return ATCA_SMALL_BUFFER;
}
head_buff = rxdata;
while (retries-- > 0 && status != ATCA_SUCCESS)
{
if ((status = hal_swi_send_flag(iface, SWI_FLAG_TX)) == ATCA_SUCCESS)
{
swi_uart_mode(&swi_hal_data[bus], RECEIVE_MODE);
*head_buff = 0x00;
for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1)
{
bit_data = 0;
status = swi_uart_receive_byte(&swi_hal_data[bus], &bit_data);
if (status != ATCA_SUCCESS)
{
break;
}
if ((bit_data ^ 0x7F) < 2)
{
*head_buff |= bit_mask;
}
}
if (status == ATCA_SUCCESS)
{
if (*head_buff < ATCA_RSP_SIZE_MIN)
{
swi_uart_mode(&swi_hal_data[bus], TRANSMIT_MODE);
atca_delay_us(TX_DELAY);
return ATCA_INVALID_SIZE;
}
if (*head_buff > rxdata_max_size)
{
swi_uart_mode(&swi_hal_data[bus], TRANSMIT_MODE);
atca_delay_us(TX_DELAY);
return ATCA_SMALL_BUFFER;
}
break;
}
else
{
swi_uart_mode(&swi_hal_data[bus], TRANSMIT_MODE);
}
}
}
count = (*head_buff) - 1;
head_buff++;
for (i = 0; i < count; i++)
{
*head_buff = 0x00;
for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1)
{
bit_data = 0;
status = swi_uart_receive_byte(&swi_hal_data[bus], &bit_data);
if (status != ATCA_SUCCESS)
{
swi_uart_mode(&swi_hal_data[bus], TRANSMIT_MODE);
atca_delay_us(TX_DELAY);
return status;
}
if ((bit_data ^ 0x7F) < 2)
{
*head_buff |= bit_mask;
}
}
head_buff++;
}
*rxlength = rxdata[0];
swi_uart_mode(&swi_hal_data[bus], TRANSMIT_MODE);
atca_delay_us(TX_DELAY);
#ifdef DEBUG_HAL
printf("\r\nResponse Packet (size:0x%.4x)\r\n", *rxlength);
printf("Count : %.2x\r\n", rxdata[0]);
if (rxdata[0] > 3)
{
printf("Data : "); print_array(&rxdata[1], rxdata[0] - 3);
printf("CRC : "); print_array(&rxdata[rxdata[0] - 2], 2);
}
printf("\r\n");
#endif
return status;
}
ATCA_STATUS hal_swi_wake(ATCAIface iface)
{
#ifdef DEBUG_HAL
printf("hal_swi_wake()\r\n");
#endif
ATCA_STATUS status = ATCA_COMM_FAIL;
ATCAIfaceCfg *cfg = atgetifacecfg(iface);
int bus = cfg->atcaswi.bus;
int retries = cfg->rx_retries;
uint16_t datalength = 4;
uint8_t data[4] = { 0x00, 0x00, 0x00, 0x00 };
while ((status != ATCA_SUCCESS) && (retries >= 0x00))
{
retries--;
swi_uart_setbaud(&swi_hal_data[bus], 115200);
status = swi_uart_send_byte(&swi_hal_data[bus], SWI_WAKE_TOKEN);
swi_uart_setbaud(&swi_hal_data[bus], 230400);
}
if (!status)
{
atca_delay_us(cfg->wake_delay); status = hal_swi_receive(iface, data, &datalength);
}
if ((retries == 0x00) && (status != ATCA_SUCCESS) )
{
return ATCA_TIMEOUT;
}
return hal_check_wake(data, 4);
}
ATCA_STATUS hal_swi_idle(ATCAIface iface)
{
return hal_swi_send_flag(iface, SWI_FLAG_IDLE);
}
ATCA_STATUS hal_swi_sleep(ATCAIface iface)
{
return hal_swi_send_flag(iface, SWI_FLAG_SLEEP);
}
ATCA_STATUS hal_swi_release(void *hal_data)
{
ATCASWIMaster_t *hal = (ATCASWIMaster_t*)hal_data;
if (hal && --(hal->ref_ct) <= 0)
{
swi_uart_deinit(&swi_hal_data[hal->bus_index]);
hal->ref_ct = 0;
}
return ATCA_SUCCESS;
}