23 #define DEBUG_MTL_USBTMC_INSTRUMENT 0
24 #define DEBUG_MTL_USBTMC_INSTRUMENT_ERRORS_ONLY 0
25 #if (defined(_DEBUG) && defined(DEBUG_MTL_USBTMC_INSTRUMENT) && DEBUG_MTL_USBTMC_INSTRUMENT)
26 #if (defined(DEBUG_MTL_USBTMC_INSTRUMENT_ERRORS_ONLY) && DEBUG_MTL_USBTMC_INSTRUMENT_ERRORS_ONLY)
27 #define MTL_USBTMC_INSTRUMENT_DEBUG_COUT(__X__)
29 #define MTL_USBTMC_INSTRUMENT_DEBUG_COUT(__X__) COUT(__X__)
31 #define MTL_USBTMC_INSTRUMENT_DEBUG_CERR(__X__) CERR(__X__)
33 #define MTL_USBTMC_INSTRUMENT_DEBUG_COUT(__X__)
34 #define MTL_USBTMC_INSTRUMENT_DEBUG_CERR(__X__)
36 #define MTL_USBTMC_PAUSE_BETWEEN_READS 2 // ms
54 for (
auto l_pDeviceListEntry = m_DeviceList.begin(); l_pDeviceListEntry != m_DeviceList.end(); l_pDeviceListEntry++)
56 if (l_pDeviceListEntry->pDevice !=
nullptr)
57 libusb_unref_device(l_pDeviceListEntry->pDevice);
62 if (m_pContext !=
nullptr)
63 libusb_exit(m_pContext);
77 m_Status = libusb_init (&m_pContext);
82 m_Status = libusb_set_option (m_pContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_WARNING);
92 if (m_pContext !=
nullptr)
93 libusb_exit (m_pContext);
108 libusb_device ** l_USBDeviceList =
nullptr;
109 libusb_device_handle * l_hDevice =
nullptr;
110 tUSBTMCDeviceListEntry l_NewDeviceListEntry;
111 l_NewDeviceListEntry.clear();
117 for (
auto l_pDeviceListEntry = m_DeviceList.begin(); l_pDeviceListEntry != m_DeviceList.end(); l_pDeviceListEntry++)
118 l_pDeviceListEntry->PluggedIn =
false;
121 const std::regex l_RegexVID_PID(
"([0-9]+):([0-9]+)");
122 std::smatch l_MatchVID_PID;
123 if (!std::regex_match(Filter, l_MatchVID_PID, l_RegexVID_PID) ||
124 l_MatchVID_PID.size() != 3)
127 U16 l_VID =
static_cast<U16>(stoi(l_MatchVID_PID[1].str()));
128 U16 l_PID =
static_cast<U16>(stoi(l_MatchVID_PID[2].str()));
131 ssize_t l_DeviceCount = libusb_get_device_list(
nullptr, &l_USBDeviceList);
132 if (l_DeviceCount < 0)
136 for (ssize_t i = 0; i < l_DeviceCount; i++)
139 l_NewDeviceListEntry.clear();
142 libusb_device * l_pUSBDevice = l_USBDeviceList[i];
143 struct libusb_device_descriptor l_USBDeviceDescriptor;
144 m_Status = libusb_get_device_descriptor(l_pUSBDevice, &l_USBDeviceDescriptor);
149 if (l_USBDeviceDescriptor.idVendor != l_VID ||
150 l_USBDeviceDescriptor.idProduct != l_PID)
156 if (l_PathLength < 0)
158 std::vector<U8> l_PortPath;
159 for (
I32 i = 0; i < l_PathLength; i++)
160 l_PortPath.push_back(l_PortNumbers[i]);
164 auto l_pDeviceListEntry = m_DeviceList.begin();
165 for (; l_pDeviceListEntry != m_DeviceList.end(); l_pDeviceListEntry++)
166 if (l_PortPath == l_pDeviceListEntry->PortPath)
break;
167 if (l_pDeviceListEntry != m_DeviceList.end())
169 rList.push_back(l_pDeviceListEntry->ResourceName);
170 l_pDeviceListEntry->PluggedIn =
true;
176 m_Status = libusb_open(l_pUSBDevice, &l_hDevice);
181 libusb_ref_device(l_pUSBDevice);
182 l_NewDeviceListEntry.pDevice = l_pUSBDevice;
183 l_NewDeviceListEntry.PortPath = l_PortPath;
184 l_NewDeviceListEntry.PluggedIn =
true;
189 l_StringLength = libusb_get_string_descriptor_ascii (l_hDevice, l_USBDeviceDescriptor.iManufacturer, l_String,
USB_DESCRIPTOR_STRING_LENGTH);
190 if (l_StringLength < 0)
192 std::string l_Manufacturer = std::string(
reinterpret_cast<char *
>(l_String),
static_cast<size_t>(l_StringLength));
194 l_StringLength = libusb_get_string_descriptor_ascii (l_hDevice, l_USBDeviceDescriptor.iProduct, l_String,
USB_DESCRIPTOR_STRING_LENGTH);
195 if (l_StringLength < 0)
197 std::string l_Product = std::string(
reinterpret_cast<char *
>(l_String),
static_cast<size_t>(l_StringLength));
199 l_StringLength = libusb_get_string_descriptor_ascii (l_hDevice, l_USBDeviceDescriptor.iSerialNumber, l_String,
USB_DESCRIPTOR_STRING_LENGTH);
200 if (l_StringLength < 0)
202 std::string l_SerialNumber = std::string(
reinterpret_cast<char *
>(l_String),
static_cast<size_t>(l_StringLength));
204 l_NewDeviceListEntry.ResourceName = l_Manufacturer +
" " + l_Product +
" " + l_SerialNumber;
207 libusb_close(l_hDevice);
211 m_DeviceList.push_back(l_NewDeviceListEntry);
212 rList.push_back(l_NewDeviceListEntry.ResourceName);
217 libusb_free_device_list(l_USBDeviceList, 1);
220 for (
auto l_pDeviceListEntry = m_DeviceList.begin(); l_pDeviceListEntry != m_DeviceList.end();)
222 if (!l_pDeviceListEntry->PluggedIn)
224 libusb_unref_device(l_pDeviceListEntry->pDevice);
225 l_pDeviceListEntry = m_DeviceList.erase(l_pDeviceListEntry);
229 ++l_pDeviceListEntry;
234 if (rList.size() == 0)
245 if (l_USBDeviceList !=
nullptr)
246 libusb_free_device_list(l_USBDeviceList, 1);
247 if (l_hDevice !=
nullptr)
248 libusb_close(l_hDevice);
249 if (l_NewDeviceListEntry.pDevice !=
nullptr)
250 libusb_unref_device(l_NewDeviceListEntry.pDevice);
252 for (
auto l_pDeviceListEntry = m_DeviceList.begin(); l_pDeviceListEntry != m_DeviceList.end(); l_pDeviceListEntry++)
254 libusb_unref_device(l_pDeviceListEntry->pDevice);
256 m_DeviceList.clear();
266 bool CUSBTMCResourceManager::GetDeviceListEntry(
const tResourceName ResourceName, libusb_device * & pDevice)
272 tUSBTMCDeviceListEntry * l_pDeviceListEntry =
nullptr;
273 for (
auto l_pDeviceList = m_DeviceList.begin(); l_pDeviceList != m_DeviceList.end(); l_pDeviceList++)
275 if (l_pDeviceList->ResourceName == ResourceName)
277 l_pDeviceListEntry = &(*l_pDeviceList);
283 if (l_pDeviceListEntry ==
nullptr)
292 pDevice = l_pDeviceListEntry->pDevice;
293 libusb_ref_device(pDevice);
306 return libusb_error_name(
Status);
317 return (
m_Status == LIBUSB_ERROR_TIMEOUT);
338 return (
R8(pResponse + 0) == USBTMC_status &&
339 R8(pResponse + 1) == bTag &&
340 R8(pResponse + 2) == StatusByte);
347 U8 bmTransferAttributes,
350 W8 (pHeader + 0, MsgID);
351 W8 (pHeader + 1, bTag);
352 W8 (pHeader + 2, ~bTag);
354 WL32(pHeader + 4, TransferSize);
355 W8 (pHeader + 8, bmTransferAttributes);
356 W8 (pHeader + 9, TermChar);
357 WL16(pHeader + 10, 0);
364 U8 & bmTransferAttributes)
366 if (
R8(pHeader + 0) != MsgID ||
367 R8(pHeader + 1) != bTag ||
368 R8(pHeader + 2) != (
unsigned char)~bTag)
370 TransferSize =
RL32(pHeader + 4);
371 bmTransferAttributes =
R8(pHeader + 8);
386 { assert (0 == UseCount); }
389 static class:
public std::map<libusb_device *, tControlRecord *>
397 auto l_pClaimCheck = find(pDevice);
398 if (l_pClaimCheck != end())
400 l_pClaimCheck->second->UseCount++;
405 emplace(pDevice, l_pNewControlRecord);
406 libusb_ref_device(pDevice);
412 auto l_pClaimCheck = find(pDevice);
413 if (l_pClaimCheck != end())
415 l_pClaimCheck->second->UseCount--;
416 if (0 == l_pClaimCheck->second->UseCount)
418 delete l_pClaimCheck->second;
419 erase(l_pClaimCheck);
420 libusb_unref_device(pDevice);
429 bool Claim(libusb_device * pDevice,
U32 Timeout = 0)
432 auto l_pClaimCheck = find(pDevice);
433 if (l_pClaimCheck == end())
436 return l_pClaimCheck->second->Mutex.try_lock_for(std::chrono::milliseconds(Timeout));
441 auto l_pClaimCheck = find(pDevice);
442 if (l_pClaimCheck != end())
444 l_pClaimCheck->second->Mutex.unlock();
457 m_ConfigurationNo(0), m_InterfaceNo(0), m_InterruptEndpoint(0), m_BulkInEndpoint(0), m_BulkOutEndpoint(0),
458 m_BulkInMaxPacketSize(0), m_bTag(0), m_ExclusiveLock(false)
480 struct libusb_config_descriptor * l_pConfig =
nullptr;
485 if (
IsOpen())
return true;
492 struct libusb_device_descriptor l_USBDeviceDescriptor;
493 m_Status = libusb_get_device_descriptor(m_pDevice, &l_USBDeviceDescriptor);
498 bool l_FoundInterface =
false;
499 for (
U8 l_iConf = 0; l_iConf < l_USBDeviceDescriptor.bNumConfigurations; l_iConf++)
501 int l_ReturnValue = libusb_get_config_descriptor(m_pDevice, l_iConf, &l_pConfig);
502 if (l_ReturnValue < 0 && l_ReturnValue != LIBUSB_ERROR_NOT_FOUND)
506 for (
int l_iIntfc = 0; l_iIntfc < l_pConfig->bNumInterfaces; l_iIntfc++)
508 const struct libusb_interface_descriptor * l_pIntfc = l_pConfig->interface[l_iIntfc].altsetting;
509 if (l_pIntfc->bInterfaceClass != LIBUSB_CLASS_APPLICATION ||
513 m_ConfigurationNo = l_pConfig->bConfigurationValue;
514 m_InterfaceNo = l_pIntfc->bInterfaceNumber;
517 for (
int l_iEP = 0; l_iEP < l_pIntfc->bNumEndpoints; l_iEP++)
519 const struct libusb_endpoint_descriptor * l_pEndpoint = &l_pIntfc->endpoint[l_iEP];
520 if (l_pEndpoint->bmAttributes == LIBUSB_TRANSFER_TYPE_BULK &&
521 !(l_pEndpoint->bEndpointAddress & (LIBUSB_ENDPOINT_DIR_MASK)))
523 m_BulkOutEndpoint = l_pEndpoint->bEndpointAddress;
525 if (l_pEndpoint->bmAttributes == LIBUSB_TRANSFER_TYPE_BULK &&
526 l_pEndpoint->bEndpointAddress & (LIBUSB_ENDPOINT_DIR_MASK))
528 m_BulkInEndpoint = l_pEndpoint->bEndpointAddress;
530 if (l_pEndpoint->bmAttributes == LIBUSB_TRANSFER_TYPE_INTERRUPT &&
531 l_pEndpoint->bEndpointAddress & (LIBUSB_ENDPOINT_DIR_MASK))
533 m_InterruptEndpoint = l_pEndpoint->bEndpointAddress;
538 m_BulkInMaxPacketSize = libusb_get_max_packet_size(m_pDevice, m_BulkInEndpoint);
541 l_FoundInterface =
true;
546 libusb_free_config_descriptor(l_pConfig);
548 if (l_FoundInterface)
break;
553 if (!l_FoundInterface)
557 m_Status = libusb_open(m_pDevice, &m_hDevice);
563 libusb_set_auto_detach_kernel_driver (m_hDevice, 1);
567 m_Status = libusb_get_configuration(m_hDevice, &l_CurrentConfig);
570 if (l_CurrentConfig != m_ConfigurationNo)
572 m_Status =libusb_set_configuration(m_hDevice, m_ConfigurationNo);
587 if (l_pConfig !=
nullptr)
588 libusb_free_config_descriptor(l_pConfig);
590 if (m_hDevice !=
nullptr)
592 libusb_close(m_hDevice);
596 if (m_pDevice !=
nullptr)
598 libusb_unref_device(m_pDevice);
601 m_ConfigurationNo = 0;
603 m_InterruptEndpoint = 0;
604 m_BulkInEndpoint = 0;
605 m_BulkOutEndpoint = 0;
606 m_BulkInMaxPacketSize = 0;
630 if (m_hDevice !=
nullptr)
632 libusb_close(m_hDevice);
637 if (m_pDevice !=
nullptr)
639 libusb_unref_device(m_pDevice);
647 m_ConfigurationNo = 0;
649 m_InterruptEndpoint = 0;
650 m_BulkInEndpoint = 0;
651 m_BulkOutEndpoint = 0;
652 m_BulkInMaxPacketSize = 0;
662 return (m_pDevice !=
nullptr && m_hDevice !=
nullptr);
674 return libusb_error_name(
Status);
685 return (
m_Status == LIBUSB_ERROR_TIMEOUT);
692 bool CUSBTMCInstrument::USBTMCWrite(
U8 MessageID,
const char * pData,
const size_t Size,
U8 TransferAttributes)
697 bool l_InitialLockState = m_ExclusiveLock;
698 U8 * l_pBuffer =
nullptr;
710 I32 l_Size = pData ?
static_cast<I32>(Size) : 0;
712 l_pBuffer =
new U8[
static_cast<size_t>(l_PaddedSize)];
717 if (++m_bTag < 2 || m_bTag > 127)
727 m_Status = libusb_bulk_transfer(m_hDevice,
735 USBTMCClearBulkOut(m_bTag);
739 if (l_Transferred != l_PaddedSize)
750 if (!l_InitialLockState)
Unlock();
756 if (!l_InitialLockState)
Unlock();
759 if (l_pBuffer)
delete l_pBuffer;
799 bool l_InitialLockState = m_ExclusiveLock;
811 if (!Append) rBuf.
clear();
823 I32 l_BufferLength = m_BulkInMaxPacketSize;
826 I32 l_Transferred = 0;
829 m_Status = libusb_bulk_transfer(m_hDevice,
837 USBTMCClearBulkIn(m_bTag);
840 }
while (l_Transferred == 0);
846 U8 l_TransferAttributes;
848 !(l_TransferAttributes &
EOM))
852 size_t l_BufSize = rBuf.
size();
853 size_t l_BufCapacity = rBuf.
capacity();
854 if (l_MessageSize >
static_cast<I32>(l_BufCapacity - l_BufSize))
855 rBuf.
reserve(l_BufSize +
static_cast<size_t>(l_MessageSize));
859 if (l_MessageReceived > 0)
863 size_t l_MessagePending =
static_cast<size_t>(l_MessageSize) - l_MessageReceived;
864 if (l_MessagePending > 0)
869 U8 * l_pData =
reinterpret_cast<U8 *
>(rBuf.
data() + l_BufSize + l_MessageReceived);
870 m_Status = libusb_bulk_transfer(m_hDevice,
873 static_cast<I32>(l_MessagePending),
878 USBTMCClearBulkIn(m_bTag);
881 if (l_Transferred !=
static_cast<I32>(l_MessagePending))
886 rBuf.
resize(l_BufSize +
static_cast<size_t>(l_MessageSize));
896 if (!l_InitialLockState)
Unlock();
902 if (!l_InitialLockState)
Unlock();
910 bool CUSBTMCInstrument::USBTMCClearBulkIn(
U8 bTag)
923 libusb_control_transfer(m_hDevice,
926 static_cast<U16>(bTag),
933 if (l_ReturnValue < 0)
940 I32 l_BufferLength = m_BulkInMaxPacketSize;
945 libusb_bulk_transfer(m_hDevice,
951 if (l_ReturnValue < 0)
953 }
while (l_Transferred >= l_BufferLength);
960 libusb_control_transfer(m_hDevice,
969 if (l_ReturnValue < 0)
973 l_ReadBuffer[1] != 0 ||
974 l_ReadBuffer[2] != 0 ||
975 l_ReadBuffer[3] != 0)
982 l_ReturnValue = libusb_clear_halt(m_hDevice, m_BulkInEndpoint);
983 if (l_ReturnValue < 0)
999 bool CUSBTMCInstrument::USBTMCClearBulkOut(
U8 bTag)
1011 libusb_control_transfer(m_hDevice,
1014 static_cast<U16>(bTag),
1021 if (l_ReturnValue < 0)
1032 libusb_control_transfer(m_hDevice,
1041 if (l_ReturnValue < 0)
1045 l_ReadBuffer[1] != 0 ||
1046 l_ReadBuffer[2] != 0 ||
1047 l_ReadBuffer[3] != 0)
1054 l_ReturnValue = libusb_clear_halt(m_hDevice, m_BulkOutEndpoint);
1055 if (l_ReturnValue < 0)
1077 bool l_InitialLockState = m_ExclusiveLock;
1093 libusb_control_transfer(m_hDevice,
1103 if (l_ReturnValue < 0)
1110 U8 l_Status, l_Clear;
1114 libusb_control_transfer(m_hDevice,
1123 if (l_ReturnValue < 0)
1135 l_ReturnValue = libusb_clear_halt(m_hDevice, m_BulkOutEndpoint);
1136 if (l_ReturnValue < 0)
1141 USBTMCClearBulkIn(m_bTag);
1151 if (!l_InitialLockState)
Unlock();
1157 if (!l_InitialLockState)
Unlock();
1168 bool l_InitialLockState = m_ExclusiveLock;
1185 bool l_GotSTB =
false;
1189 if (++m_bTag < 2 || m_bTag > 127)
1194 libusb_control_transfer(m_hDevice,
1204 if (l_ReturnValue < 0)
1209 !(l_Success || l_InterruptInBusy))
1215 libusb_interrupt_transfer(m_hDevice,
1216 m_InterruptEndpoint,
1223 if (l_ReturnValue < 0)
1229 if (l_InterruptInBusy && l_ReadBuffer[0] == 0x81)
1233 if (l_ReadBuffer[0] != (0x80 | m_bTag))
1237 }
while (!l_GotSTB);
1240 rSTB = l_ReadBuffer[1];
1250 if (!l_InitialLockState)
Unlock();
1256 if (!l_InitialLockState)
Unlock();
1267 bool l_InitialLockState = m_ExclusiveLock;
1279 if (++m_bTag < 2 || m_bTag > 127)
1288 m_Status = libusb_bulk_transfer(m_hDevice,
1296 USBTMCClearBulkOut(m_bTag);
1311 if (!l_InitialLockState)
Unlock();
1317 if (!l_InitialLockState)
Unlock();
1331 if (m_ExclusiveLock)
return true;
1341 I32 l_ReturnCode = libusb_claim_interface(m_hDevice, m_InterfaceNo);
1342 if (l_ReturnCode != LIBUSB_SUCCESS)
1350 m_ExclusiveLock =
true;
1361 if (!m_ExclusiveLock)
return true;
1364 I32 l_ReturnCode = libusb_release_interface(m_hDevice, m_InterfaceNo);
1365 if (l_ReturnCode != LIBUSB_SUCCESS)
1374 m_ExclusiveLock =
false;
1381 return m_ExclusiveLock;