#include "atca_hal.h"
#include "kit_phy.h"
#include "hal_win_kit_cdc.h"
#include "kit_protocol.h"
#include <SetupAPI.h>
#include <stdlib.h>
#include <tchar.h>
#include <stdio.h>
atcacdc_t _gCdc;
ATCA_STATUS hal_kit_cdc_init(void* hal, ATCAIfaceCfg* cfg)
{
ATCA_STATUS status = ATCA_SUCCESS;
ATCAHAL_t *phal = NULL;
GUID *pcdc_guid = NULL;
HDEVINFO dev_info;
SP_DEVINFO_DATA dev_data;
DWORD device_index = 0;
DWORD required_size = 0;
HKEY reg_key;
DWORD reg_type = 0;
TCHAR reg_data[256];
TCHAR cdc_data[256];
BOOL result = FALSE;
LONG reg_result = 0;
DCB dcb_settings;
COMMTIMEOUTS comm_timeouts;
int i = 0;
int index = 0;
if ((hal == NULL) || (cfg == NULL))
{
return ATCA_BAD_PARAM;
}
phal = (ATCAHAL_t*)hal;
memset(&_gCdc, 0, sizeof(_gCdc));
for (i = 0; i < CDC_DEVICES_MAX; i++)
{
_gCdc.kits[i].read_handle = INVALID_HANDLE_VALUE;
_gCdc.kits[i].write_handle = INVALID_HANDLE_VALUE;
}
_gCdc.num_kits_found = 0;
result = SetupDiClassGuidsFromName(_T("Ports"), NULL, 0, &required_size);
if (required_size == 0)
{
return ATCA_COMM_FAIL;
}
pcdc_guid = malloc(required_size * sizeof(GUID));
result = SetupDiClassGuidsFromName(_T("Ports"), pcdc_guid, required_size, &required_size);
if (result == TRUE)
{
dev_info = SetupDiGetClassDevs(pcdc_guid, NULL, NULL, DIGCF_PRESENT);
if (dev_info != INVALID_HANDLE_VALUE)
{
memset(&dev_data, 0, sizeof(SP_DEVINFO_DATA));
dev_data.cbSize = sizeof(SP_DEVINFO_DATA);
while (SetupDiEnumDeviceInfo(dev_info, device_index, &dev_data))
{
required_size = sizeof(reg_data);
result = SetupDiGetDeviceRegistryProperty(dev_info, &dev_data, SPDRP_FRIENDLYNAME, ®_type,
(PBYTE)reg_data, required_size, &required_size);
if (result == TRUE)
{
if ((_tcsstr(reg_data, _T("AT90USB"))) ||
(_tcsstr(reg_data, _T("XPLAINED"))) ||
(_tcsstr(reg_data, _T("Class ASF"))))
{
reg_key = SetupDiOpenDevRegKey(dev_info, &dev_data, DICS_FLAG_GLOBAL,
0, DIREG_DEV, KEY_QUERY_VALUE);
if (reg_key != INVALID_HANDLE_VALUE)
{
required_size = sizeof(reg_data);
reg_result = RegQueryValueEx(reg_key, _T("PortName"), NULL, NULL,
(LPBYTE)reg_data, &required_size);
if (reg_result == ERROR_SUCCESS)
{
_sntprintf_s(cdc_data, sizeof(cdc_data) / sizeof(cdc_data[0]), _TRUNCATE, _T("\\\\.\\%s"), reg_data);
if (_gCdc.kits[index].read_handle != INVALID_HANDLE_VALUE)
{
CloseHandle(_gCdc.kits[index].read_handle);
}
_gCdc.kits[index].read_handle = INVALID_HANDLE_VALUE;
_gCdc.kits[index].write_handle = INVALID_HANDLE_VALUE;
_gCdc.kits[index].read_handle = CreateFile(cdc_data,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
_gCdc.kits[index].write_handle = _gCdc.kits[index].read_handle;
if (_gCdc.kits[index].read_handle != INVALID_HANDLE_VALUE)
{
dcb_settings.DCBlength = sizeof(DCB);
result = GetCommState(_gCdc.kits[index].read_handle, &dcb_settings);
if (result == FALSE)
{
continue;
}
dcb_settings.BaudRate = cfg->atcauart.baud;
dcb_settings.ByteSize = cfg->atcauart.wordsize;
dcb_settings.StopBits = cfg->atcauart.stopbits;
switch (cfg->atcauart.parity)
{
case 0: dcb_settings.Parity = EVENPARITY;
case 1: dcb_settings.Parity = ODDPARITY;
case 2: dcb_settings.Parity = NOPARITY;
default: dcb_settings.Parity = NOPARITY;
}
result = SetCommState(_gCdc.kits[index].read_handle, &dcb_settings);
if (result == FALSE)
{
continue;
}
comm_timeouts.ReadIntervalTimeout = 3;
comm_timeouts.ReadTotalTimeoutMultiplier = 3;
comm_timeouts.ReadTotalTimeoutConstant = 2;
comm_timeouts.WriteTotalTimeoutMultiplier = 3;
comm_timeouts.WriteTotalTimeoutConstant = 2;
SetCommTimeouts(_gCdc.kits[index].read_handle, &comm_timeouts);
}
index++;
}
RegCloseKey(reg_key);
}
}
}
if (index == CDC_DEVICES_MAX)
{
break;
}
device_index++;
}
}
SetupDiDestroyDeviceInfoList(dev_info);
}
free(pcdc_guid);
if (index > 0)
{
_gCdc.num_kits_found = index;
phal->hal_data = &_gCdc;
return status;
}
return ATCA_NO_DEVICES;
}
ATCA_STATUS hal_cdc_discover_buses(int i2c_buses[], int max_buses)
{
return ATCA_UNIMPLEMENTED;
}
ATCA_STATUS hal_cdc_discover_devices(int bus_num, ATCAIfaceCfg cfg[], int *found)
{
return ATCA_UNIMPLEMENTED;
}
ATCA_STATUS hal_kit_cdc_post_init(ATCAIface iface)
{
ATCA_STATUS status = ATCA_SUCCESS;
atcacdc_t* pHalDat = atgetifacehaldat(iface);
ATCAIfaceCfg *pCfg = atgetifacecfg(iface);
int i = 0;
do
{
if (pHalDat == NULL || pCfg == NULL)
{
status = ATCA_BAD_PARAM;
BREAK(status, "NULL pointers in hal_kit_cdc_post_init");
}
for (i = 0; i < pHalDat->num_kits_found; i++)
{
pCfg->atcauart.port = i;
status = kit_init(iface);
if (status != ATCA_SUCCESS)
{
BREAK(status, "kit_init() Failed");
}
}
}
while (0);
return status;
}
ATCA_STATUS kit_phy_send(ATCAIface iface, const char* txdata, int txlength)
{
ATCA_STATUS status = ATCA_SUCCESS;
ATCAIfaceCfg *cfg = atgetifacecfg(iface);
int cdcid = cfg->atcauart.port;
atcacdc_t* pCdc = (atcacdc_t*)atgetifacehaldat(iface);
uint8_t buffer[CDC_BUFFER_MAX];
DWORD bytes_to_send = 0;
DWORD bytes_left = 0;
DWORD bytes_sent = 0;
BOOL result = FALSE;
if ((txdata == NULL) || (pCdc == NULL))
{
return ATCA_BAD_PARAM;
}
if (pCdc->kits[cdcid].write_handle == INVALID_HANDLE_VALUE)
{
return ATCA_COMM_FAIL;
}
bytes_left = txlength;
while (bytes_left > 0)
{
memset(buffer, 0, CDC_BUFFER_MAX);
if (bytes_left >= CDC_BUFFER_MAX)
{
bytes_to_send = CDC_BUFFER_MAX;
}
else
{
bytes_to_send = bytes_left;
}
memcpy(&buffer[0], &txdata[(txlength - bytes_left)], bytes_to_send);
result = WriteFile(pCdc->kits[cdcid].write_handle, buffer, bytes_to_send, &bytes_sent, NULL);
if (result == FALSE)
{
return ATCA_TX_FAIL;
}
bytes_left -= bytes_sent;
}
return status;
}
ATCA_STATUS kit_phy_receive(ATCAIface iface, char* rxdata, int* rxsize)
{
ATCAIfaceCfg *cfg = atgetifacecfg(iface);
int cdcid = cfg->atcauart.port;
atcacdc_t* pCdc = (atcacdc_t*)atgetifacehaldat(iface);
uint8_t buffer[CDC_BUFFER_MAX] = { 0 };
BOOL continue_read = TRUE;
DWORD bytes_read = 0;
DWORD total_bytes = 0;
BOOL result = true;
uint8_t* location = NULL;
int bytes_remain = 0;
int bytes_to_copy = 0;
int size_adjust = 0;
if ((rxdata == NULL) || (rxsize == NULL) || (pCdc == NULL))
{
return ATCA_BAD_PARAM;
}
if (pCdc->kits[cdcid].read_handle == INVALID_HANDLE_VALUE)
{
return ATCA_COMM_FAIL;
}
DWORD start_time_ms = GetTickCount();
while (continue_read == true)
{
if (GetTickCount() - start_time_ms > 3000)
{
CloseHandle(pCdc->kits[cdcid].read_handle);
pCdc->kits[cdcid].read_handle = INVALID_HANDLE_VALUE;
pCdc->kits[cdcid].write_handle = INVALID_HANDLE_VALUE;
return ATCA_COMM_FAIL;
}
result = ReadFile(pCdc->kits[cdcid].read_handle, buffer, CDC_BUFFER_MAX, &bytes_read, NULL);
if (result == FALSE)
{
return ATCA_RX_FAIL;
}
location = strchr((char*)&buffer[0], '\n');
if (location == NULL)
{
bytes_to_copy = bytes_read;
}
else
{
bytes_to_copy = (int)(location - (char*)buffer);
continue_read = false;
}
memcpy(&rxdata[total_bytes], &buffer[0], bytes_to_copy);
total_bytes += bytes_to_copy - size_adjust;
}
*rxsize = total_bytes;
return ATCA_SUCCESS;
}
ATCA_STATUS hal_kit_phy_num_found(int8_t* num_found)
{
*num_found = _gCdc.num_kits_found;
return ATCA_SUCCESS;
}
ATCA_STATUS hal_kit_cdc_send(ATCAIface iface, uint8_t* txdata, int txlength)
{
return kit_send(iface, txdata, txlength);
}
ATCA_STATUS hal_kit_cdc_receive(ATCAIface iface, uint8_t* rxdata, uint16_t* rxsize)
{
return kit_receive(iface, rxdata, rxsize);
}
ATCA_STATUS hal_kit_cdc_wake(ATCAIface iface)
{
return kit_wake(iface);
}
ATCA_STATUS hal_kit_cdc_idle(ATCAIface iface)
{
return kit_idle(iface);
}
ATCA_STATUS hal_kit_cdc_sleep(ATCAIface iface)
{
return kit_sleep(iface);
}
ATCA_STATUS hal_kit_cdc_release(void* hal_data)
{
int i = 0;
atcacdc_t* phaldat = (atcacdc_t*)hal_data;
if ((hal_data == NULL))
{
return ATCA_BAD_PARAM;
}
for (i = 0; i < phaldat->num_kits_found; i++)
{
if (phaldat->kits[i].read_handle != INVALID_HANDLE_VALUE)
{
CloseHandle(phaldat->kits[i].read_handle);
phaldat->kits[i].read_handle = INVALID_HANDLE_VALUE;
phaldat->kits[i].write_handle = INVALID_HANDLE_VALUE;
}
}
return ATCA_SUCCESS;
}
ATCA_STATUS hal_kit_cdc_discover_buses(int cdc_buses[], int max_buses)
{
return ATCA_UNIMPLEMENTED;
}
ATCA_STATUS hal_kit_cdc_discover_devices(int bus_num, ATCAIfaceCfg *cfg, int *found)
{
*found = 0;
return ATCA_UNIMPLEMENTED;
}