Очевидно, что вам нужно написать разные реализации для разных операционных систем, если вы не хотите создавать поток для непрерывной работы:
FT_ListDevices(&numDevs, nullptr, FT_LIST_NUMBER_ONLY);
и перечислить устройства, если numDevs изменился по сравнению с предыдущими проверками.
Если вы похожи на меня и не очень любите проводить такие непрерывные опросы на своих USB-устройствах, вам придется настроить свою операционную систему.
Вот ссылка на пример кода из FTDI:
http://www.ftdichip.com/Support/SoftwareExamples/CodeExamples/VC.htm
Пример 7 показывает, как обнаружить USB-вставку и удаление в Windows:
http://www.ftdichip.com/Support/Documents/AppNotes/AN_152_Detecting_USB_%20Device_Insertion_and_Removal.pdf
В Linux я лично могу порекомендовать использовать udev.
Этот код для перечисления устройств:
#include <sys/types.h>
#include <dirent.h>
#include <cstdlib>
#include <libudev.h>
#include <fcntl.h>
struct udev *udev = udev_new();
if (!udev) {
cout << "Can't create udev" <<endl;
}
struct udev_enumerate *enumerate = udev_enumerate_new(udev);
udev_enumerate_add_match_subsystem(enumerate, "usb");
udev_enumerate_scan_devices(enumerate);
struct udev_list_entry *dev_list_entry, *devices = udev_enumerate_get_list_entry(enumerate);
struct udev_device *dev;
udev_list_entry_foreach(dev_list_entry, devices) {
const char *path;
path = udev_list_entry_get_name(dev_list_entry);
dev = udev_device_new_from_syspath(udev, path);
if( udev_device_get_devnode(dev) != nullptr ){
string vendor = (std::string) udev_device_get_sysattr_value(dev, "idVendor");
string product = (std::string) udev_device_get_sysattr_value(dev, "idProduct");
string description = (std::string)udev_device_get_sysattr_value(dev, "product");
cout << vendor << product << description << endl;
}
udev_device_unref(dev);
}
udev_enumerate_unref(enumerate);
Этот код я поместил в отдельную ветку, которая ожидает получения вставки или события удаления
struct udev_device *dev;
struct udev_monitor *mon = udev_monitor_new_from_netlink(udev, "udev");
udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", NULL);
udev_monitor_enable_receiving(mon);
int fd = udev_monitor_get_fd(mon);
int flags = fcntl(fd, F_GETFL, 0);
if (flags == -1){
debugError("Can't get flags for fd");
}
flags &= ~O_NONBLOCK;
fcntl(fd, F_SETFL, flags);
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
while( _running ){
cout << "waiting for udev" << endl;
dev = udev_monitor_receive_device(mon);
if (dev && udev_device_get_devnode(dev) != nullptr ) {
string action = (std::string)udev_device_get_action(dev);
if( action == "add" ){
cout << "do something with your device... " << endl;
} else {
string path = (std::string)udev_device_get_devnode(dev);
for( auto device : _DevicesList ){
if( device.getPath() == path ){
_DevicesList.erase(iter);
cout << "Erased Device from list" << endl;
break;
}
}
}
udev_device_unref(dev);
}
}
udev_monitor_unref(mon);
некоторые функции и переменные явно не определены при копировании / вставке этого кода.
Я веду список обнаруженных устройств для проверки пути и другую информацию, например, идентификатор местоположения вставленного устройства. Позже мне нужен идентификатор местоположения для FT_OpenEx через FT_OPEN_BY_LOCATION. Чтобы получить идентификатор местоположения, я прочитал содержимое следующих файлов:
string getFileContent(string file ){
string content = "";
ifstream readfile( file );
if( readfile.is_open() ){
getline(readfile, content );
readfile.close();
}
return content;
}
string usbdirectory = "/sys/bus/usb/devices";
string dev1content = getFileContent(usbdirectory+"/usb"+udev_device_get_sysattr_value(dev, "busnum" )+"/dev");
int dev1num = std::atoi(dev1content.substr(dev1content.find_first_of(":")+1).c_str());
string dev2content = (std::string)udev_device_get_sysattr_value(dev, "dev");
int dev2num = std::atoi(dev2content.substr(dev2content.find_first_of(":")+1).c_str());
int locationid = dev1num+dev2num+257;
Я не могу гарантировать, что locationid правильный, но мне показалось, что он работал до сих пор.