moved libs to the lib directory

This commit is contained in:
2025-11-13 18:40:06 +03:00
parent 4678ff1690
commit dda7ed6db8
634 changed files with 3 additions and 2 deletions

507
lib/l502/win/l502_spec.c Normal file
View File

@ -0,0 +1,507 @@
#include <Windows.h>
#include <SetupAPI.h>
#include <initguid.h>
#include <stddef.h>
#include <tchar.h>
#include "../l502api_private.h"
#include <winioctl.h>
/* GUID интерфейса устройств lpcie для связи приложения с драйвером */
DEFINE_GUID (GUID_LPCIE_INTERFACE,
0x53869b9a, 0x7875, 0x4fd3, 0x9e, 0x04, 0xbe, 0xc8, 0x1a, 0x92, 0xf9, 0xa9);
#define L502_IOCTL_TIMEOUT 500
typedef struct {
int32_t size;
SP_DEVICE_INTERFACE_DETAIL_DATA *intf_detail;
} t_lpcie_devlst_intptr;
static int32_t f_ioctl(HANDLE hDevice,
uint32_t dwIoControlCode, // control code of operation to perform
void* lpInBuffer, // pointer to buffer to supply input data
uint32_t nInBufferSize, // size of input buffer in bytes
void* lpOutBuffer, // pointer to buffer to receive output data
uint32_t nOutBufferSize, // size of output buffer in bytes
uint32_t* rx_size,
uint32_t TimeOut) { // таймаут в мс
uint32_t RealBytesTransferred;
uint32_t BytesReturned;
OVERLAPPED Ov;
int32_t err = X502_ERR_OK;
uint32_t syserr = 0;
// инициализируем OVERLAPPED структуру
memset(&Ov, 0x0, sizeof(OVERLAPPED));
// создаём событие для асинхронного запроса
Ov.hEvent = CreateEvent(NULL, FALSE , FALSE, NULL);
if(!Ov.hEvent) {
err = X502_ERR_MEMORY_ALLOC;
} else {
// посылаем требуемый запрос
if(!DeviceIoControl( hDevice, dwIoControlCode,
lpInBuffer, nInBufferSize,
lpOutBuffer, nOutBufferSize,
&BytesReturned, &Ov)) {
syserr = GetLastError();
if(syserr != ERROR_IO_PENDING) {
CloseHandle(Ov.hEvent);
err = X502_ERR_IOCTL_FAILD;
GetOverlappedResult(hDevice, &Ov, &RealBytesTransferred, TRUE);
}
}
}
if (err == X502_ERR_OK) {
// ждём окончания выполнения запроса
if (WaitForSingleObject(Ov.hEvent, TimeOut) == WAIT_TIMEOUT) {
CancelIo(hDevice);
CloseHandle(Ov.hEvent);
err = X502_ERR_IOCTL_TIMEOUT;
GetOverlappedResult(hDevice, &Ov, &RealBytesTransferred, TRUE);
}
}
// попробуем получить кол-во реально переданных байт данных
if (err == X502_ERR_OK) {
if(!GetOverlappedResult(hDevice, &Ov, &RealBytesTransferred, TRUE)) {
syserr = GetLastError();
CancelIo(hDevice);
CloseHandle(Ov.hEvent);
err = X502_ERR_IOCTL_FAILD;
} else if(nOutBufferSize != RealBytesTransferred) {
CancelIo(hDevice);
CloseHandle(Ov.hEvent);
} else {
CloseHandle(Ov.hEvent);
}
}
if ((err == X502_ERR_OK) && (rx_size != NULL)) {
*rx_size = RealBytesTransferred;
}
if (err==X502_ERR_IOCTL_FAILD) {
if (syserr == ERROR_NO_SYSTEM_RESOURCES)
err = X502_ERR_INSUFFICIENT_SYSTEM_RESOURCES;
}
return err;
}
int32_t l502_port_fpga_reg_write(t_x502_hnd hnd, uint32_t reg, uint32_t val) {
t_lpcie_mem_rw mem_wr = {reg,val};
return f_ioctl (L502_PCI_IFACE_FILE(hnd),
LPCIE_IOCTL_MEMFPGA_WR, &mem_wr, sizeof(mem_wr),
NULL, 0, NULL, L502_IOCTL_TIMEOUT) ?
X502_ERR_FPGA_REG_READ : 0;
}
int32_t l502_port_fpga_reg_read(t_x502_hnd hnd, uint32_t reg, uint32_t *val) {
uint32_t rd_val;
int32_t err = f_ioctl (L502_PCI_IFACE_FILE(hnd),
LPCIE_IOCTL_MEMFPGA_RD, &reg, sizeof(reg),
&rd_val, sizeof(rd_val), NULL, L502_IOCTL_TIMEOUT);
if (err != X502_ERR_OK) {
err = X502_ERR_FPGA_REG_READ;
} else if (val != NULL) {
*val = rd_val;
}
return err;
}
int32_t l502_port_stream_set_params(t_x502_hnd hnd, t_lpcie_stream_ch_params *par) {
return f_ioctl(L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_STREAM_SET_PARAMS, par,
sizeof(t_lpcie_stream_ch_params), NULL, 0, NULL,
L502_IOCTL_TIMEOUT);
}
int32_t l502_port_stream_start(t_x502_hnd hnd, uint32_t ch, uint32_t single) {
return f_ioctl(L502_PCI_IFACE_FILE(hnd), single ? LPCIE_IOCTL_STREAM_START_SINGLE :
LPCIE_IOCTL_STREAM_START,
&ch, sizeof(ch), NULL, 0, NULL,
L502_IOCTL_TIMEOUT);
}
int32_t l502_port_stream_stop(t_x502_hnd hnd, uint32_t ch, uint32_t flags) {
return f_ioctl(L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_STREAM_STOP, &ch, sizeof(ch), NULL, 0, NULL,
L502_IOCTL_TIMEOUT);
}
int32_t l502_port_stream_free(t_x502_hnd hnd, uint32_t ch, uint32_t flags) {
return f_ioctl(L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_STREAM_FREE, &ch, sizeof(ch), NULL, 0, NULL,
L502_IOCTL_TIMEOUT);
}
int32_t l502_port_stream_rdy_size(t_x502_hnd hnd, uint32_t ch, uint32_t *rdy_size) {
uint32_t rd_val;
int32_t err = f_ioctl (L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_STREAM_GET_RDY_SIZE, &ch, sizeof(ch),
&rd_val, sizeof(rd_val), NULL, L502_IOCTL_TIMEOUT);
if ((err == X502_ERR_OK) && (rdy_size != NULL))
*rdy_size = rd_val;
return err;
}
int32_t l502_port_cycle_load_start(t_x502_hnd hnd, uint32_t ch, uint32_t size, uint32_t min_irq_step) {
t_lpcie_cycle_set_par par;
memset(&par, 0, sizeof(par));
par.ch = ch;
par.size = size;
par.irq_step = min_irq_step;
return f_ioctl (L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_CYCLE_LOAD, &par, sizeof(par), NULL, 0,
NULL, L502_IOCTL_TIMEOUT);
}
int32_t l502_port_cycle_setup(t_x502_hnd hnd, uint32_t ch, uint32_t evt) {
t_lpcie_cycle_evt_par par;
memset(&par, 0, sizeof(par));
par.ch = ch;
par.evt = evt;
return f_ioctl (L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_CYCLE_SWITCH, &par, sizeof(par), NULL, 0,
NULL, L502_IOCTL_TIMEOUT);
}
int32_t l502_port_cycle_stop(t_x502_hnd hnd, uint32_t ch, uint32_t evt) {
t_lpcie_cycle_evt_par par;
memset(&par, 0, sizeof(par));
par.ch = ch;
par.evt = evt;
return f_ioctl (L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_CYCLE_STOP, &par, sizeof(par), NULL, 0,
NULL, L502_IOCTL_TIMEOUT);
}
int32_t l502_port_cycle_check_setup(t_x502_hnd hnd, uint32_t ch, uint32_t *done) {
uint32_t rd_val;
int32_t err = f_ioctl (L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_CYCLE_CHECK_SETUP, &ch, sizeof(ch),
&rd_val, sizeof(rd_val), NULL, L502_IOCTL_TIMEOUT);
if ((err == X502_ERR_OK) && (done != NULL))
*done = rd_val;
return err;
}
int32_t l502_port_renew_info(t_x502_hnd hnd) {
return f_ioctl(L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_RELOAD_DEVINFO, NULL, 0, NULL, 0, NULL,
L502_IOCTL_TIMEOUT);
}
int32_t l502_port_get_drv_ver(t_x502_hnd hnd, uint32_t *ver) {
uint32_t rd_val;
int32_t err = f_ioctl (L502_PCI_IFACE_FILE(hnd), LPCIE_IOCTL_GET_DRV_VERSION, NULL, 0,
&rd_val, sizeof(rd_val), NULL, L502_IOCTL_TIMEOUT);
if ((err == X502_ERR_OK) && (ver != NULL))
*ver = rd_val;
return err;
}
int32_t l502_port_stream_read(t_x502_hnd hnd, uint32_t* buff, uint32_t size, uint32_t timeout) {
int send_size = 4*size;
uint32_t NumberOfBytesRead = 0;
int32_t err = X502_ERR_OK;
OVERLAPPED Ov;
// инициализируем OVERLAPPED структуру
memset(&Ov, 0, sizeof(OVERLAPPED));
Ov.hEvent = CreateEvent(NULL, FALSE , FALSE, NULL);
if(!Ov.hEvent) {
err = X502_ERR_MEMORY_ALLOC;
}
if (err == X502_ERR_OK) {
// посылаем асинхронный запрос на сбор необходимого кол-ва данных
if(!ReadFile(L502_PCI_IFACE_FILE(hnd), buff, send_size, NULL, &Ov)) {
if(GetLastError() != ERROR_IO_PENDING) {
CancelIo(L502_PCI_IFACE_FILE(hnd));
CloseHandle(Ov.hEvent);
err = X502_ERR_RECV;
GetOverlappedResult(L502_PCI_IFACE_FILE(hnd), &Ov, &NumberOfBytesRead, TRUE);
}
}
}
// ждём окончания выполнения запроса
if (err == X502_ERR_OK) {
if (WaitForSingleObject(Ov.hEvent, timeout) == WAIT_TIMEOUT) {
CancelIo(L502_PCI_IFACE_FILE(hnd));
CloseHandle(Ov.hEvent);
GetOverlappedResult(L502_PCI_IFACE_FILE(hnd), &Ov, &NumberOfBytesRead, TRUE);
} else if(!GetOverlappedResult(L502_PCI_IFACE_FILE(hnd), &Ov, &NumberOfBytesRead, TRUE)) {
CancelIo(L502_PCI_IFACE_FILE(hnd));
CloseHandle(Ov.hEvent);
err = X502_ERR_RECV;
} else {
CloseHandle(Ov.hEvent);
}
}
return err != X502_ERR_OK ? err : NumberOfBytesRead/4;
}
int32_t l502_port_stream_write(t_x502_hnd hnd, const uint32_t* buff,
uint32_t size, uint32_t timeout) {
int send_size = 4*size;
uint32_t NumberOfBytesRead = 0;
int32_t err = X502_ERR_OK;
OVERLAPPED Ov;
// инициализируем OVERLAPPED структуру
memset(&Ov, 0, sizeof(OVERLAPPED));
Ov.hEvent = CreateEvent(NULL, FALSE , FALSE, NULL);
if(!Ov.hEvent) {
err = X502_ERR_MEMORY_ALLOC;
}
if (err == X502_ERR_OK) {
// посылаем асинхронный запрос на сбор необходимого кол-ва данных
if(!WriteFile(L502_PCI_IFACE_FILE(hnd), buff, send_size, NULL, &Ov)) {
if(GetLastError() != ERROR_IO_PENDING) {
CancelIo(L502_PCI_IFACE_FILE(hnd));
CloseHandle(Ov.hEvent);
err = X502_ERR_SEND;
GetOverlappedResult(L502_PCI_IFACE_FILE(hnd), &Ov, &NumberOfBytesRead, TRUE);
}
}
}
// ждём окончания выполнения запроса
if (err == X502_ERR_OK) {
if (WaitForSingleObject(Ov.hEvent, timeout) == WAIT_TIMEOUT) {
CancelIo(L502_PCI_IFACE_FILE(hnd));
CloseHandle(Ov.hEvent);
GetOverlappedResult(L502_PCI_IFACE_FILE(hnd), &Ov, &NumberOfBytesRead, TRUE);
} else if(!GetOverlappedResult(L502_PCI_IFACE_FILE(hnd), &Ov, &NumberOfBytesRead, TRUE)) {
CancelIo(L502_PCI_IFACE_FILE(hnd));
CloseHandle(Ov.hEvent);
err = X502_ERR_SEND;
} else {
CloseHandle(Ov.hEvent);
}
}
return err != X502_ERR_OK ? err : NumberOfBytesRead/4;
}
static int32_t f_get_file_par(SP_DEVICE_INTERFACE_DETAIL_DATA *detail, TCHAR* filebuf,
const TCHAR* file, char* res, uint32_t req_size,
uint32_t* read_size) {
HANDLE ifile;
int32_t err = 0;
_tcscpy(filebuf, TEXT(detail->DevicePath));
_tcscat(filebuf, file);
ifile = CreateFile(filebuf, GENERIC_READ,
FILE_SHARE_READ,
NULL, OPEN_EXISTING,
0, NULL);
if (ifile != INVALID_HANDLE_VALUE) {
DWORD read_cnt=0;
if (!ReadFile(ifile, res, req_size, &read_cnt, NULL)) {
err = X502_ERR_GET_INFO;
} else {
if (read_size!=NULL)
*read_size = read_cnt;
}
CloseHandle(ifile);
} else {
err = X502_ERR_GET_INFO;
}
return err;
}
static int f_fill_devlist(SP_DEVICE_INTERFACE_DETAIL_DATA *detail,
t_x502_devrec *info) {
int32_t err = X502_ERR_OK;
TCHAR *filename = malloc(sizeof(TCHAR)*21 + _tcslen(detail->DevicePath));
if (filename == NULL) {
err = X502_ERR_MEMORY_ALLOC;
} else {
err = f_get_file_par(detail, filename, TEXT("\\name"), info->devname,
sizeof(info->devname), NULL);
if (err == X502_ERR_OK) {
/* получаем серийный номер устройства */
err = f_get_file_par(detail, filename, TEXT("\\sn"), info->serial,
sizeof(info->serial), NULL);
}
/* получаем информацию, открыто ли устройство */
if (err == X502_ERR_OK) {
char val = '0';
f_get_file_par(detail, filename, TEXT("\\opened"), &val, 1, NULL);
if (!err && (val!='0'))
info->flags |= X502_DEVFLAGS_DEVREC_OPENED;
}
/* получаем информацию, присутствует ли BlackFin */
if (err == X502_ERR_OK) {
char val = '0';
if ((f_get_file_par(detail, filename, TEXT("\\bf"), &val, 1, NULL)==0)
&& (val != '0')) {
info->flags |= X502_DEVFLAGS_BF_PRESENT;
}
if ((f_get_file_par(detail, filename, TEXT("\\dac"), &val, 1, NULL)==0)
&& (val != '0')) {
info->flags |= X502_DEVFLAGS_DAC_PRESENT;
}
if ((f_get_file_par(detail, filename, TEXT("\\gal"), &val, 1, NULL)==0)
&& (val != '0')) {
info->flags |= X502_DEVFLAGS_GAL_PRESENT;
}
}
if (err == X502_ERR_OK) {
err = l502_devlist_gen(info, detail);
}
free(filename);
}
return err;
}
int32_t l502_port_free_iface_data(void *intptr) {
free(intptr);
return X502_ERR_OK;
}
int32_t l502_port_open(t_x502_hnd hnd, const t_x502_devrec *devinfo) {
SP_DEVICE_INTERFACE_DETAIL_DATA *detail = (SP_DEVICE_INTERFACE_DETAIL_DATA *)devinfo->internal->iface_data;
int32_t err = X502_ERR_OK;
HANDLE file = CreateFile(detail->DevicePath, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, NULL);
if (file != INVALID_HANDLE_VALUE) {
hnd->iface_data = malloc(sizeof(t_pci_iface_data));
if (hnd->iface_data == NULL) {
err = X502_ERR_MEMORY_ALLOC;
CloseHandle(file);
} else {
L502_PCI_IFACE_FILE(hnd) = file;
}
} else {
DWORD syserr = GetLastError();
if (syserr == ERROR_ACCESS_DENIED) {
err = X502_ERR_DEVICE_ACCESS_DENIED;
} else if (syserr == ERROR_FILE_NOT_FOUND) {
err = X502_ERR_DEVICE_NOT_FOUND;
} else {
err = X502_ERR_DEVICE_OPEN;
}
}
return err;
}
int32_t l502_port_close(t_x502_hnd hnd) {
if (hnd->iface_data !=NULL) {
CloseHandle(L502_PCI_IFACE_FILE(hnd));
free(hnd->iface_data);
hnd->iface_data = NULL;
}
return X502_ERR_OK;
}
X502_EXPORT(int32_t) L502_GetDevRecordsList(t_x502_devrec *list, uint32_t size,
uint32_t flags, uint32_t *devcnt) {
HDEVINFO infoSet;
SP_DEVINFO_DATA infoData;
DWORD index=0;
uint32_t curcnt=0;
int32_t err = X502_ERR_OK;
infoData.cbSize = sizeof(SP_DEVINFO_DATA);
/* получаем список устройств с подержкой интерфейса lpcie */
infoSet = SetupDiGetClassDevs(&GUID_LPCIE_INTERFACE,NULL,
NULL,
DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
/* проходимся по всем устройствам из списка */
while (SetupDiEnumDeviceInfo(infoSet, index, &infoData)) {
SP_DEVICE_INTERFACE_DATA intfData;
intfData.cbSize = sizeof(intfData);
/* получаем информацию о интерфейсе */
if (SetupDiEnumDeviceInterfaces(infoSet, &infoData, &GUID_LPCIE_INTERFACE,
0, &intfData)) {
DWORD req_size;
/* узнаем резмер детальной информации о интерфейсе (нужна для
получения имени устройства) */
if (!SetupDiGetDeviceInterfaceDetail(infoSet, &intfData, NULL,
0, &req_size, NULL)
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
SP_DEVICE_INTERFACE_DETAIL_DATA* detail =
(SP_DEVICE_INTERFACE_DETAIL_DATA*) malloc(req_size);
if (detail != NULL) {
int detail_used = 0;
/* пытаемся получить всю информацию */
detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (SetupDiGetDeviceInterfaceDetail(infoSet, &intfData,
detail, req_size,
NULL, NULL)) {
t_x502_devrec info;
int info_used = 0;
detail_used = 1;
X502_DevRecordInit(&info);
/* получаем информацию о устройстве из служебных файлов,
* предоставляемых драйвером */
if (f_fill_devlist(detail, &info) == X502_ERR_OK) {
/* если нужны только не открытые, то уже открытое
* устройство пропускаем */
if (!(flags & X502_GETDEVS_FLAGS_ONLY_NOT_OPENED) ||
!(info.flags & X502_DEVFLAGS_DEVREC_OPENED)) {
/* если есть место в списке - то сохраняем
* полученную информацию */
if ((list!=NULL) && (curcnt < size)) {
list[curcnt] = info;
info_used = 1;
}
curcnt++;
}
}
if (!info_used)
X502_FreeDevRecordList(&info,1);
}
if (!detail_used) {
free(detail);
}
} else {
err = X502_ERR_MEMORY_ALLOC;
}
}
}
index++;
}
if (infoSet != NULL) {
SetupDiDestroyDeviceInfoList(infoSet);
}
if (devcnt != NULL)
*devcnt = curcnt;
return err != X502_ERR_OK ? err : curcnt > size ? size : curcnt ;
}