98 lines
2.6 KiB
C++
98 lines
2.6 KiB
C++
|
#include "SMXDeviceSearchThreaded.h"
|
||
|
#include "SMXDeviceSearch.h"
|
||
|
#include "SMXDeviceConnection.h"
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <memory>
|
||
|
using namespace std;
|
||
|
using namespace SMX;
|
||
|
|
||
|
SMX::SMXDeviceSearchThreaded::SMXDeviceSearchThreaded()
|
||
|
{
|
||
|
m_hEvent = make_shared<AutoCloseHandle>(CreateEvent(NULL, false, false, NULL));
|
||
|
m_pDeviceList = make_shared<SMXDeviceSearch>();
|
||
|
|
||
|
// Start the thread.
|
||
|
DWORD id;
|
||
|
m_hThread = CreateThread(NULL, 0, ThreadMainStart, this, 0, &id);
|
||
|
SMX::SetThreadName(id, "SMXDeviceSearch");
|
||
|
}
|
||
|
|
||
|
SMX::SMXDeviceSearchThreaded::~SMXDeviceSearchThreaded()
|
||
|
{
|
||
|
// Shut down the thread, if it's still running.
|
||
|
Shutdown();
|
||
|
}
|
||
|
|
||
|
void SMX::SMXDeviceSearchThreaded::Shutdown()
|
||
|
{
|
||
|
if(m_hThread == INVALID_HANDLE_VALUE)
|
||
|
return;
|
||
|
|
||
|
// Tell the thread to shut down, and wait for it before returning.
|
||
|
m_bShutdown = true;
|
||
|
SetEvent(m_hEvent->value());
|
||
|
|
||
|
WaitForSingleObject(m_hThread, INFINITE);
|
||
|
m_hThread = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
|
||
|
DWORD WINAPI SMX::SMXDeviceSearchThreaded::ThreadMainStart(void *self_)
|
||
|
{
|
||
|
SMXDeviceSearchThreaded *self = (SMXDeviceSearchThreaded *) self_;
|
||
|
self->ThreadMain();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void SMX::SMXDeviceSearchThreaded::UpdateDeviceList()
|
||
|
{
|
||
|
m_Lock.AssertNotLockedByCurrentThread();
|
||
|
|
||
|
// Tell m_pDeviceList about closed devices, so it knows that any device on the
|
||
|
// same path is new.
|
||
|
m_Lock.Lock();
|
||
|
for(auto pDevice: m_apClosedDevices)
|
||
|
m_pDeviceList->DeviceWasClosed(pDevice);
|
||
|
m_apClosedDevices.clear();
|
||
|
m_Lock.Unlock();
|
||
|
|
||
|
// Get the current device list.
|
||
|
wstring sError;
|
||
|
vector<shared_ptr<AutoCloseHandle>> apDevices = m_pDeviceList->GetDevices(sError);
|
||
|
if(!sError.empty())
|
||
|
{
|
||
|
Log(ssprintf("Error listing USB devices: %ls", sError.c_str()));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Update the device list returned by GetDevices.
|
||
|
m_Lock.Lock();
|
||
|
m_apDevices = apDevices;
|
||
|
m_Lock.Unlock();
|
||
|
}
|
||
|
|
||
|
void SMX::SMXDeviceSearchThreaded::ThreadMain()
|
||
|
{
|
||
|
while(!m_bShutdown)
|
||
|
{
|
||
|
UpdateDeviceList();
|
||
|
WaitForSingleObjectEx(m_hEvent->value(), 250, true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void SMX::SMXDeviceSearchThreaded::DeviceWasClosed(shared_ptr<AutoCloseHandle> pDevice)
|
||
|
{
|
||
|
// Add pDevice to the list of closed devices. We'll call m_pDeviceList->DeviceWasClosed
|
||
|
// on these from the scanning thread.
|
||
|
m_apClosedDevices.push_back(pDevice);
|
||
|
}
|
||
|
|
||
|
vector<shared_ptr<AutoCloseHandle>> SMX::SMXDeviceSearchThreaded::GetDevices()
|
||
|
{
|
||
|
// Lock to make a copy of the device list.
|
||
|
m_Lock.Lock();
|
||
|
vector<shared_ptr<AutoCloseHandle>> apResult = m_apDevices;
|
||
|
m_Lock.Unlock();
|
||
|
return apResult;
|
||
|
}
|