mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-11-03 21:20:31 -05:00 
			
		
		
		
	
		
			
	
	
		
			168 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			168 lines
		
	
	
		
			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
							 | 
						||
| 
								 | 
							
								}
							 |