mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-11-03 21:20:31 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			202 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			202 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/**
 | 
						|
    @file ConnectionSTREAMEntry.cpp
 | 
						|
    @author Lime Microsystems
 | 
						|
    @brief Implementation of STREAM board connection.
 | 
						|
*/
 | 
						|
 | 
						|
#include "ConnectionSTREAM.h"
 | 
						|
#include "Logger.h"
 | 
						|
 | 
						|
using namespace lime;
 | 
						|
 | 
						|
#ifdef __unix__
 | 
						|
void ConnectionSTREAMEntry::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) lime::error("error libusb_handle_events %s", libusb_strerror(libusb_error(r)));
 | 
						|
    }
 | 
						|
}
 | 
						|
#endif // __UNIX__
 | 
						|
 | 
						|
//! make a static-initialized entry in the registry
 | 
						|
void __loadConnectionSTREAMEntry(void) //TODO fixme replace with LoadLibrary/dlopen
 | 
						|
{
 | 
						|
static ConnectionSTREAMEntry STREAMEntry;
 | 
						|
}
 | 
						|
 | 
						|
int USBTransferContext::idCounter = 0;
 | 
						|
 | 
						|
ConnectionSTREAMEntry::ConnectionSTREAMEntry(void):
 | 
						|
    ConnectionRegistryEntry("STREAM")
 | 
						|
{
 | 
						|
#ifdef __unix__
 | 
						|
    int r = libusb_init(&ctx); //initialize the library for the session we just declared
 | 
						|
    if(r < 0)
 | 
						|
        lime::error("Init Error %i", 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(&ConnectionSTREAMEntry::handle_libusb_events, this);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
ConnectionSTREAMEntry::ConnectionSTREAMEntry(const std::string entryName):
 | 
						|
    ConnectionRegistryEntry(entryName)
 | 
						|
{
 | 
						|
#ifdef __unix__
 | 
						|
    int r = libusb_init(&ctx); //initialize the library for the session we just declared
 | 
						|
    if(r < 0)
 | 
						|
        lime::error("Init Error %i", 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(&ConnectionSTREAMEntry::handle_libusb_events, this);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
ConnectionSTREAMEntry::~ConnectionSTREAMEntry(void)
 | 
						|
{
 | 
						|
#ifdef __unix__
 | 
						|
    mProcessUSBEvents.store(false);
 | 
						|
    mUSBProcessingThread.join();
 | 
						|
    libusb_exit(ctx);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
#ifndef __unix__
 | 
						|
/** @return name of usb device as string.
 | 
						|
    @param index device index in list
 | 
						|
*/
 | 
						|
std::string ConnectionSTREAMEntry::DeviceName(unsigned int index)
 | 
						|
{
 | 
						|
    std::string name;
 | 
						|
    char tempName[USB_STRING_MAXLEN];
 | 
						|
    CCyUSBDevice device;
 | 
						|
    if (index >= device.DeviceCount())
 | 
						|
        return "";
 | 
						|
 | 
						|
    for (int i = 0; i < USB_STRING_MAXLEN; ++i)
 | 
						|
            tempName[i] = device.DeviceName[i];
 | 
						|
    if (device.bSuperSpeed == true)
 | 
						|
        name = "USB 3.0";
 | 
						|
    else if (device.bHighSpeed == true)
 | 
						|
        name = "USB 2.0";
 | 
						|
    else
 | 
						|
        name = "USB";
 | 
						|
    name += " (";
 | 
						|
    name += tempName;
 | 
						|
    name += ")";
 | 
						|
    return name;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
std::vector<ConnectionHandle> ConnectionSTREAMEntry::enumerate(const ConnectionHandle &hint)
 | 
						|
{
 | 
						|
    std::vector<ConnectionHandle> handles;
 | 
						|
 | 
						|
#ifndef __unix__
 | 
						|
	CCyUSBDevice device;
 | 
						|
	if (device.DeviceCount())
 | 
						|
    {
 | 
						|
		for (int i = 0; i<device.DeviceCount(); ++i)
 | 
						|
        {
 | 
						|
			if (hint.index >= 0 && hint.index != i)
 | 
						|
				continue;
 | 
						|
			if (device.IsOpen())
 | 
						|
				device.Close();
 | 
						|
            device.Open(i);
 | 
						|
            ConnectionHandle handle;
 | 
						|
            handle.media = "USB";
 | 
						|
            handle.name = DeviceName(i);
 | 
						|
            handle.index = i;
 | 
						|
            std::wstring ws(device.SerialNumber);
 | 
						|
            handle.serial = std::string(ws.begin(),ws.end());
 | 
						|
            if (hint.serial.empty() or hint.serial == handle.serial)
 | 
						|
            {
 | 
						|
                handles.push_back(handle); //filter on serial
 | 
						|
            }
 | 
						|
            device.Close();
 | 
						|
        }
 | 
						|
    }
 | 
						|
#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) {
 | 
						|
        lime::error("failed to get libusb device list: %s", libusb_strerror(libusb_error(usbDeviceCount)));
 | 
						|
        return handles;
 | 
						|
    }
 | 
						|
 | 
						|
    for(int i=0; i<usbDeviceCount; ++i)
 | 
						|
    {
 | 
						|
        libusb_device_descriptor desc;
 | 
						|
        int r = libusb_get_device_descriptor(devs[i], &desc);
 | 
						|
        if(r<0)
 | 
						|
            lime::error("failed to get device description");
 | 
						|
        int pid = desc.idProduct;
 | 
						|
        int vid = desc.idVendor;
 | 
						|
 | 
						|
        if(vid == 1204 && pid == 34323)
 | 
						|
        {
 | 
						|
            ConnectionHandle handle;
 | 
						|
            handle.media = "USB";
 | 
						|
            handle.name = "DigiGreen";
 | 
						|
            handle.addr = std::to_string(int(pid))+":"+std::to_string(int(vid));
 | 
						|
            handles.push_back(handle);
 | 
						|
        }
 | 
						|
        else if((vid == 1204 && pid == 241) || (vid == 1204 && pid == 243) || (vid == 7504 && pid == 24840))
 | 
						|
        {
 | 
						|
            libusb_device_handle *tempDev_handle(nullptr);
 | 
						|
            if(libusb_open(devs[i], &tempDev_handle) != 0 || tempDev_handle == nullptr)
 | 
						|
                continue;
 | 
						|
 | 
						|
            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];
 | 
						|
            r = libusb_get_string_descriptor_ascii(tempDev_handle,  LIBUSB_CLASS_COMM, (unsigned char*)data, sizeof(data));
 | 
						|
            if(r > 0) handle.name = std::string(data, size_t(r));
 | 
						|
 | 
						|
            r = std::sprintf(data, "%.4x:%.4x", int(vid), int(pid));
 | 
						|
            if (r > 0) handle.addr = std::string(data, size_t(r));
 | 
						|
 | 
						|
            if (desc.iSerialNumber > 0)
 | 
						|
            {
 | 
						|
                r = libusb_get_string_descriptor_ascii(tempDev_handle,desc.iSerialNumber,(unsigned char*)data, sizeof(data));
 | 
						|
                if(r<0)
 | 
						|
                    lime::error("failed to get serial number");
 | 
						|
                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 *ConnectionSTREAMEntry::make(const ConnectionHandle &handle)
 | 
						|
{
 | 
						|
    return new ConnectionSTREAM(ctx, handle.addr, handle.serial, handle.index);
 | 
						|
}
 |