You will obviously have to write different implementations for different operating systems if you do not want to create a thread for continuous launch:
FT_ListDevices(&numDevs, nullptr, FT_LIST_NUMBER_ONLY);
and list devices if numDevs has changed from previous checks.
If you are like me and donβt really like doing such a continuous survey on your USB devices, you need to target your specific operating system.
Here is a link to some sample code from FTDI: http://www.ftdichip.com/Support/SoftwareExamples/CodeExamples/VC.htm
Example 7 shows how to determine the insertion and removal of USB in windows: http://www.ftdichip.com/Support/Documents/AppNotes/AN_152_Detecting_USB_%20Device_Insertion_and_Removal.pdf
On Linux, I personally recommend using udev.
This code is for listing devices:
#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);
I put this code in a separate thread, which is waiting for an insert or delete event
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);
some functions and variables are obviously not defined when copying / pasting this code. I keep a list of discovered devices for checking the path and other information, such as the location identifier of the inserted device. I need a location identifier later to FT_OpenEx via FT_OPEN_BY_LOCATION. To get the location id, I read the contents of the following files:
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;
I cannot guarantee the correct location, but it seems to have worked so far.