sdrangel/liblimesuite/srcmw/Connection_uLimeSDR/Connection_uLimeSDREntry.cpp

168 wiersze
5.6 KiB
C++

/**
@file Connection_uLimeSDREntry.cpp
@author Lime Microsystems
@brief Implementation of uLimeSDR board connection.
*/
#include "Connection_uLimeSDR.h"
using namespace lime;
#ifdef __unix__
void Connection_uLimeSDREntry::handle_libusb_events()
{
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 250000;
while(mProcessUSBEvents.load() == true)
{
int r = libusb_handle_events_timeout_completed(ctx, &tv, NULL);
if(r != 0) printf("error libusb_handle_events %s\n", libusb_strerror(libusb_error(r)));
}
}
#endif // __UNIX__
int Connection_uLimeSDR::USBTransferContext::idCounter=0;
//! make a static-initialized entry in the registry
void __loadConnection_uLimeSDREntry(void) //TODO fixme replace with LoadLibrary/dlopen
{
static Connection_uLimeSDREntry uLimeSDREntry;
}
Connection_uLimeSDREntry::Connection_uLimeSDREntry(void):
ConnectionRegistryEntry("uLimeSDR")
{
#ifndef __unix__
//m_pDriver = new CDriverInterface();
#else
int r = libusb_init(&ctx); //initialize the library for the session we just declared
if(r < 0)
printf("Init Error %i\n", r); //there was an error
libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation
mProcessUSBEvents.store(true);
mUSBProcessingThread = std::thread(&Connection_uLimeSDREntry::handle_libusb_events, this);
#endif
}
Connection_uLimeSDREntry::~Connection_uLimeSDREntry(void)
{
#ifndef __unix__
//delete m_pDriver;
#else
mProcessUSBEvents.store(false);
mUSBProcessingThread.join();
libusb_exit(ctx);
#endif
}
std::vector<ConnectionHandle> Connection_uLimeSDREntry::enumerate(const ConnectionHandle &hint)
{
std::vector<ConnectionHandle> handles;
#ifndef __unix__
DWORD devCount = 0;
FT_STATUS ftStatus = FT_OK;
ftStatus = FT_ListDevices(&devCount, NULL, FT_LIST_NUMBER_ONLY);
if(FT_FAILED(ftStatus))
return handles;
if (devCount > 0)
{
for(int i = 0; i<devCount; ++i)
{
ConnectionHandle handle;
handle.media = "USB";
handle.name = "uLimeSDR";
handle.index = i;
handles.push_back(handle);
}
}
#else
libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
int usbDeviceCount = libusb_get_device_list(ctx, &devs);
if (usbDeviceCount < 0) {
printf("failed to get libusb device list: %s\n", libusb_strerror(libusb_error(usbDeviceCount)));
return handles;
}
libusb_device_descriptor desc;
for(int i=0; i<usbDeviceCount; ++i)
{
int r = libusb_get_device_descriptor(devs[i], &desc);
if(r<0)
printf("failed to get device description\n");
int pid = desc.idProduct;
int vid = desc.idVendor;
if( vid == 0x0403)
{
if(pid == 0x601F)
{
libusb_device_handle *tempDev_handle;
tempDev_handle = libusb_open_device_with_vid_pid(ctx, vid, pid);
if(libusb_kernel_driver_active(tempDev_handle, 0) == 1) //find out if kernel driver is attached
{
if(libusb_detach_kernel_driver(tempDev_handle, 0) == 0) //detach it
printf("Kernel Driver Detached!\n");
}
if(libusb_claim_interface(tempDev_handle, 0) < 0) //claim interface 0 (the first) of device
{
printf("Cannot Claim Interface\n");
}
ConnectionHandle handle;
//check operating speed
int speed = libusb_get_device_speed(devs[i]);
if(speed == LIBUSB_SPEED_HIGH)
handle.media = "USB 2.0";
else if(speed == LIBUSB_SPEED_SUPER)
handle.media = "USB 3.0";
else
handle.media = "USB";
//read device name
char data[255];
memset(data, 0, 255);
int st = libusb_get_string_descriptor_ascii(tempDev_handle, 2, (unsigned char*)data, 255);
if(st < 0)
printf("Error getting usb descriptor\n");
if(strlen(data) > 0)
handle.name = std::string(data, size_t(st));
handle.addr = std::to_string(int(pid))+":"+std::to_string(int(vid));
if (desc.iSerialNumber > 0)
{
r = libusb_get_string_descriptor_ascii(tempDev_handle,desc.iSerialNumber,(unsigned char*)data, sizeof(data));
if(r<0)
printf("failed to get serial number\n");
else
handle.serial = std::string(data, size_t(r));
}
libusb_close(tempDev_handle);
//add handle conditionally, filter by serial number
if (hint.serial.empty() or hint.serial == handle.serial)
{
handles.push_back(handle);
}
}
}
}
libusb_free_device_list(devs, 1);
#endif
return handles;
}
IConnection *Connection_uLimeSDREntry::make(const ConnectionHandle &handle)
{
#ifndef __unix__
return new Connection_uLimeSDR(mFTHandle, handle.index);
#else
const auto pidvid = handle.addr;
const auto splitPos = pidvid.find(":");
const auto pid = std::stoi(pidvid.substr(0, splitPos));
const auto vid = std::stoi(pidvid.substr(splitPos+1));
return new Connection_uLimeSDR(ctx, handle.index, vid, pid);
#endif
}