一、前言
最近需要做Windows平台 + Qt MinGW编译器做上位机与USB通信,USB芯片使用Cypress芯片。试了libusb,只能在Linux平台下使用,Windows平台用不了。所以只能使用Cypress提供的官方库CyAPI,但是Cypress官网只提供了vs版本的源码编译,在Qt下使用需要重新编译,苦于没有找到现成的资源只能自己编译,搞了一天,不过真心不难,只是没有注意细节。在此记录一下编译过程,也分享给需要的小伙伴。
不想自己编译的同学可以直接跳到下载地址: 静态库工程下载地址
二、 准备
需要准备好CyAPI源码,我是在官网下载的 官网下载地址 到这个链接下找到以下文件下载即可。 官网下载需要注册登录,觉得麻烦的小伙伴可以到这个地址下载(我自己上传的,也是想赚点积分。。): CyAPI源码下载地址
三、 编译
-
使用Qt Creator建立一个新工程,选择C++库,我选择了静态库,动态库应该也可以,但是我没试,有兴趣的同学可以试一下。 -
建好工程以后直接把下载好的源码导入到工程中来,然后把不需要的文件移除掉,以下是我建好的工程目录: -
然后在pro文件中加入以下内容:
# 引入包含目录
INCLUDEPATH += $$PWD/inc
#添加依赖库
LIBS+=-L$$PWD -lsetupapi
#配置文件输出路径
greaterThan(QT_MAJOR_VERSION,4){
TARGET_ARCH=$${QT_ARCH}
}else{
TARGET_ARCH=$${QMAKE_HOST.arch}
}
contains(TARGET_ARCH, x86_64){
CONFIG(debug,debug|release){
MOC_DIR = build/x64/tmp_debug/moc
RCC_DIR = build/x64/tmp_debug/rcc
OBJECTS_DIR = build/x64/tmp_debug/obj
DESTDIR = build/x64/bin/debug/
}else{
MOC_DIR = build/x64/tmp_release/moc
RCC_DIR = build/x64/tmp_release/rcc
OBJECTS_DIR = build/x64/tmp_release/obj
DESTDIR = build/x64/bin/release/
}
}else{
CONFIG(debug,debug|release){
MOC_DIR = build/x86/tmp_debug/moc
RCC_DIR = build/x86/tmp_debug/rcc
OBJECTS_DIR = build/x86/tmp_debug/obj
DESTDIR = build/x86/bin/debug/
}else{
MOC_DIR = build/x86/tmp_release/moc
RCC_DIR = build/x86/tmp_release/rcc
OBJECTS_DIR = build/x86/tmp_release/obj
DESTDIR = build/x86/bin/release/
}
}
- 在Qt安装目录下找到libsetupapi.a库,拷贝到工程目录。我的路径在以下位置。
编译库的时候我只用了64位的setupapi库,实际测试程序时才需要根据实际情况替换32位或者64位的setupapi库。
D:\Qt\Qt5.12.10\Tools\mingw730_32\i686-w64-mingw32\lib\libsetupapi.a
D:\Qt\Qt5.12.10\Tools\mingw730_64\x86_64-w64-mingw32\lib\libsetupapi.a
- 以上几步完成后就可以开始编译了。
5.1 头文件中会显示很多错误,类似下图,不用理会,不会影响编译结果。 cpp文件中也会报错,以下错误不用理会 5.2 需要修改的地方
MessageBox(NULL,"Please correct firmware descriptor table","Wrong Device Configuration",NULL);
改为:
MessageBoxA(NULL,"Please correct firmware descriptor table","Wrong Device Configuration",NULL);
就是把MessageBox改成MessageBoxA,因为默认调用MessageBoxW,参数不匹配,所以会报错。报错的地方改一下就可以。这个错误应该是有两处,都在Open函数中。
5.3 然后找到以下函数整体替换,其实也是CHAR和WCHAR参数不匹配的问题:
bool CCyUSBDevice::CreateHandle(UCHAR dev){
Devices = DeviceCount();
if (!Devices) return false;
if (dev > (Devices - 1)) return false;
SP_DEVINFO_DATA devInfoData;
SP_DEVICE_INTERFACE_DATA devInterfaceData;
PSP_INTERFACE_DEVICE_DETAIL_DATA_A functionClassDeviceData;
SP_INTERFACE_DEVICE_DETAIL_DATA_A tmpInterfaceDeviceDetailData;
ULONG requiredLength = 0;
int deviceNumber = dev;
HANDLE hFile;
HDEVINFO hwDeviceInfo = SetupDiGetClassDevsA ( (LPGUID) &DrvGuid,
NULL,
NULL,
DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);
if (hwDeviceInfo != INVALID_HANDLE_VALUE) {
devInterfaceData.cbSize = sizeof(devInterfaceData);
if (SetupDiEnumDeviceInterfaces ( hwDeviceInfo, 0, (LPGUID) &DrvGuid,
deviceNumber, &devInterfaceData)) {
SetupDiGetInterfaceDeviceDetailA ( hwDeviceInfo, &devInterfaceData, NULL, 0,
&requiredLength, NULL);
ULONG predictedLength = requiredLength;
functionClassDeviceData = (PSP_INTERFACE_DEVICE_DETAIL_DATA_A) malloc (predictedLength);
functionClassDeviceData->cbSize = sizeof (SP_INTERFACE_DEVICE_DETAIL_DATA_A);
devInfoData.cbSize = sizeof(devInfoData);
if (SetupDiGetInterfaceDeviceDetailA (hwDeviceInfo,
&devInterfaceData,
functionClassDeviceData,
predictedLength,
&requiredLength,
&devInfoData)) {
int pathLen = requiredLength - (sizeof (tmpInterfaceDeviceDetailData.cbSize)+sizeof (tmpInterfaceDeviceDetailData.DevicePath));
memcpy (DevPath, functionClassDeviceData->DevicePath, pathLen);
DevPath[pathLen] = 0;
hFile = CreateFileA (DevPath,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
DWORD errCode = GetLastError();
free(functionClassDeviceData);
SetupDiDestroyDeviceInfoList(hwDeviceInfo);
if (hFile == INVALID_HANDLE_VALUE)
{
LastError = GetLastError();
return false;
}
hDevice = hFile;
return true;
}
}
SetupDiDestroyDeviceInfoList(hwDeviceInfo);
}
hDevice = INVALID_HANDLE_VALUE;
DevNum = 0;
return false;
}
5.4 DeviceCount函数修改一行或者直接替换:
UCHAR CCyUSBDevice::DeviceCount(void){
SP_DEVICE_INTERFACE_DATA devInterfaceData;
HDEVINFO hwDeviceInfo = SetupDiGetClassDevsA ( (LPGUID) &DrvGuid,
NULL,
NULL,
DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);
Devices = 0;
if (hwDeviceInfo != INVALID_HANDLE_VALUE) {
devInterfaceData.cbSize = sizeof(devInterfaceData);
int i=0;
Devices = 0;
bool bDone = false;
while (!bDone) {
BOOL bRetVal = SetupDiEnumDeviceInterfaces (hwDeviceInfo, 0, (LPGUID) &DrvGuid,
i, &devInterfaceData);
if (bRetVal)
Devices++;
else {
DWORD dwLastError = GetLastError();
if (dwLastError == ERROR_NO_MORE_ITEMS) bDone = TRUE;
}
i++;
}
SetupDiDestroyDeviceInfoList(hwDeviceInfo);
}
return Devices;
}
到此就修改完毕可以成功编译了,编译完成后到配置好的路径下找到编译好的库文件就可以使用了。
四、下载
我的工程上传到此,需要的可以下载。 静态库工程下载地址
五、测试
篇幅太长,下一篇写测试过程
|