1 /**
2 @file Connection_uLimeSDREntry.cpp
3 @author Lime Microsystems
4 @brief Implementation of uLimeSDR board connection.
5 */
6
7 #include "ConnectionFT601.h"
8 #include "Logger.h"
9 #include "threadHelper.h"
10 using namespace lime;
11
12 #ifdef __unix__
handle_libusb_events()13 void ConnectionFT601Entry::handle_libusb_events()
14 {
15 struct timeval tv;
16 tv.tv_sec = 0;
17 tv.tv_usec = 250000;
18 while(mProcessUSBEvents.load() == true)
19 {
20 int r = libusb_handle_events_timeout_completed(ctx, &tv, NULL);
21 if(r != 0) lime::error("error libusb_handle_events %s", libusb_strerror(libusb_error(r)));
22 }
23 }
24 #endif // __UNIX__
25
26 //! make a static-initialized entry in the registry
__loadConnectionFT601Entry(void)27 void __loadConnectionFT601Entry(void) //TODO fixme replace with LoadLibrary/dlopen
28 {
29 static ConnectionFT601Entry FTDIEntry;
30 }
31
ConnectionFT601Entry(void)32 ConnectionFT601Entry::ConnectionFT601Entry(void):
33 ConnectionRegistryEntry("FT601")
34 {
35 #ifndef __unix__
36 //m_pDriver = new CDriverInterface();
37 #else
38 int r = libusb_init(&ctx); //initialize the library for the session we just declared
39 if(r < 0)
40 lime::error("Init Error %i", r); //there was an error
41 #if LIBUSBX_API_VERSION < 0x01000106
42 libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation
43 #else
44 libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, 3); //set verbosity level to 3, as suggested in the documentation
45 #endif
46 mProcessUSBEvents.store(true);
47 mUSBProcessingThread = std::thread(&ConnectionFT601Entry::handle_libusb_events, this);
48 SetOSThreadPriority(ThreadPriority::NORMAL, ThreadPolicy::REALTIME, &mUSBProcessingThread);
49 #endif
50 }
51
~ConnectionFT601Entry(void)52 ConnectionFT601Entry::~ConnectionFT601Entry(void)
53 {
54 #ifndef __unix__
55 //delete m_pDriver;
56 #else
57 mProcessUSBEvents.store(false);
58 mUSBProcessingThread.join();
59 libusb_exit(ctx);
60 #endif
61 }
62
enumerate(const ConnectionHandle & hint)63 std::vector<ConnectionHandle> ConnectionFT601Entry::enumerate(const ConnectionHandle &hint)
64 {
65 std::vector<ConnectionHandle> handles;
66
67 #ifndef __unix__
68 FT_STATUS ftStatus=FT_OK;
69 static DWORD numDevs = 0;
70
71 ftStatus = FT_CreateDeviceInfoList(&numDevs);
72
73 if (!FT_FAILED(ftStatus) && numDevs > 0)
74 {
75 DWORD Flags = 0;
76 char SerialNumber[16] = { 0 };
77 char Description[32] = { 0 };
78 for (DWORD i = 0; i < numDevs; i++)
79 {
80 ftStatus = FT_GetDeviceInfoDetail(i, &Flags, nullptr, nullptr, nullptr, SerialNumber, Description, nullptr);
81 if (!FT_FAILED(ftStatus))
82 {
83 ConnectionHandle handle;
84 handle.media = Flags & FT_FLAGS_SUPERSPEED ? "USB 3" : Flags & FT_FLAGS_HISPEED ? "USB 2" : "USB";
85 handle.name = Description;
86 handle.index = i;
87 handle.serial = SerialNumber;
88 //add handle conditionally, filter by serial number
89 if (hint.serial.empty() || handle.serial.find(hint.serial) != std::string::npos)
90 handles.push_back(handle);
91 }
92 }
93 }
94 #else
95 libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
96 int usbDeviceCount = libusb_get_device_list(ctx, &devs);
97
98 if (usbDeviceCount < 0) {
99 lime::error("failed to get libusb device list: %s", libusb_strerror(libusb_error(usbDeviceCount)));
100 return handles;
101 }
102
103 libusb_device_descriptor desc;
104 for(int i=0; i<usbDeviceCount; ++i)
105 {
106 int r = libusb_get_device_descriptor(devs[i], &desc);
107 if(r<0)
108 lime::error("failed to get device description");
109 int pid = desc.idProduct;
110 int vid = desc.idVendor;
111
112 if( vid == 0x0403)
113 {
114 if(pid == 0x601F)
115 {
116 libusb_device_handle *tempDev_handle(nullptr);
117 if(libusb_open(devs[i], &tempDev_handle) != 0 || tempDev_handle == nullptr)
118 continue;
119
120 ConnectionHandle handle;
121 //check operating speed
122 int speed = libusb_get_device_speed(devs[i]);
123 if(speed == LIBUSB_SPEED_HIGH)
124 handle.media = "USB 2.0";
125 else if(speed == LIBUSB_SPEED_SUPER)
126 handle.media = "USB 3.0";
127 else
128 handle.media = "USB";
129 //read device name
130 char data[255];
131 memset(data, 0, 255);
132 int st = libusb_get_string_descriptor_ascii(tempDev_handle, LIBUSB_CLASS_COMM, (unsigned char*)data, 255);
133 if(st < 0)
134 lime::error("Error getting usb descriptor");
135 else
136 handle.name = std::string(data, size_t(st));
137 handle.addr = std::to_string(int(pid))+":"+std::to_string(int(vid));
138
139 if (desc.iSerialNumber > 0)
140 {
141 r = libusb_get_string_descriptor_ascii(tempDev_handle,desc.iSerialNumber,(unsigned char*)data, sizeof(data));
142 if(r<0)
143 lime::error("failed to get serial number");
144 else
145 handle.serial = std::string(data, size_t(r));
146 }
147 libusb_close(tempDev_handle);
148
149 //add handle conditionally, filter by serial number
150 if (hint.serial.empty() or handle.serial.find(hint.serial) != std::string::npos)
151 {
152 handles.push_back(handle);
153 }
154 }
155 }
156 }
157
158 libusb_free_device_list(devs, 1);
159 #endif
160 return handles;
161 }
162
make(const ConnectionHandle & handle)163 IConnection *ConnectionFT601Entry::make(const ConnectionHandle &handle)
164 {
165 #ifndef __unix__
166 return new ConnectionFT601(mFTHandle, handle);
167 #else
168 return new ConnectionFT601(ctx, handle);
169 #endif
170 }
171