tx-gxx-linux/pc/code_twain/sln/usb_tools/usb_toolsDlg.cpp

1200 lines
28 KiB
C++
Raw Permalink Normal View History

2023-04-08 00:56:20 +00:00

// usb_toolsDlg.cpp: 实现文件
//
#include "pch.h"
#include "framework.h"
#include "usb_tools.h"
#include "usb_toolsDlg.h"
#include "afxdialogex.h"
#include "DlgScanner.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#include <chrono>
#include <coding/coding.h>
#include <win/win_util.h>
// CusbtoolsDlg 对话框
#pragma warning(disable: 4996)
#include <common/referer.h>
#include <common/log_util.h>
2023-04-08 00:56:20 +00:00
namespace usb
{
void enum_endpoints(libusb_device* device, std::vector<USBEP>& eps)
{
libusb_device_descriptor desc;
libusb_config_descriptor* conf = NULL;
int ret = libusb_get_device_descriptor(device, &desc);
if (ret != 0)
{
return;
}
for (int i = 0; i < (int)desc.bNumConfigurations; ++i)
{
ret = libusb_get_config_descriptor(device, i, &conf);
if (ret != 0)
{
continue;
}
for (int j = 0; j < conf->bNumInterfaces; ++j)
{
for (int k = 0; k < conf->interface[j].num_altsetting; ++k)
{
for (int l = 0; l < conf->interface[j].altsetting[k].bNumEndpoints; ++l)
{
USBEP ep;
ep.iface = j;
ep.type = conf->interface[j].altsetting[k].endpoint[l].bmAttributes;
ep.addr = conf->interface[j].altsetting[k].endpoint[l].bEndpointAddress;
ep.packet = conf->interface[j].altsetting[k].endpoint[l].wMaxPacketSize;
eps.push_back(std::move(ep));
}
}
}
libusb_free_config_descriptor(conf);
}
}
struct
{
BYTE type;
const wchar_t* str;
}g_ep_type[] = { {LIBUSB_TRANSFER_TYPE_BULK, L"Bulk"}
, {LIBUSB_TRANSFER_TYPE_BULK_STREAM, L"Bulk Stream"}
, {LIBUSB_TRANSFER_TYPE_CONTROL, L"Control"}
, {LIBUSB_TRANSFER_TYPE_INTERRUPT, L"Interrupt"}
, {LIBUSB_TRANSFER_TYPE_ISOCHRONOUS, L"Isochronous"}
};
const wchar_t* ep_type(BYTE type)
{
for (auto& v : g_ep_type)
{
if (v.type == type)
return v.str;
}
return L"Unknown type";
}
BYTE ep_type(const wchar_t* str)
{
for (auto& v : g_ep_type)
{
if (wcsicmp(v.str, str) == 0)
return v.type;
}
return -1;
}
BYTE from_hex_str(const wchar_t* str, bool* ok)
{
BYTE v = 0, cnt = 0;
if (ok)
*ok = false;
while (*str && cnt < 2)
{
if (*str >= L'0' && *str <= L'9')
{
v <<= 4;
v += *str - L'0';
}
else if (*str >= L'a' && *str <= L'f')
{
v <<= 4;
v += *str - L'a' + 10;
}
else if (*str >= L'A' && *str <= L'F')
{
v <<= 4;
v += *str - L'A' + 10;
}
else
{
break;
}
cnt++;
str++;
}
if (ok)
*ok = cnt == 2;
return v;
}
static int LIBUSB_CALL usb_pnp(libusb_context* ctx,
libusb_device* device,
libusb_hotplug_event event,
void* user_data)
{
LPUSBPNP pnp = new USBPNP;
HWND owner = (HWND)user_data;
libusb_device_descriptor desc;
pnp->arrive = event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED;
pnp->ctx = ctx;
pnp->device = libusb_ref_device(device);
libusb_get_device_descriptor(pnp->device, &desc);
pnp->vid = desc.idVendor;
pnp->pid = desc.idProduct;
// enum_endpoints(pnp->device, pnp->eps);
if (!PostMessage(owner, WM_USB_PNP, 0, (LPARAM)pnp))
{
libusb_unref_device(pnp->device);
delete pnp;
}
return 0;
}
static int transfer(libusb_device_handle* h, BYTE type, BYTE addr, unsigned char* buf, int *len, const wchar_t** desc = NULL, DWORD to = -1)
{
int ret = -1;
const wchar_t* tmp = NULL;
if (!desc)
desc = &tmp;
if (type == LIBUSB_TRANSFER_TYPE_BULK)
{
*desc = L"Bulk";
ret = libusb_bulk_transfer(h, addr, buf, *len, len, to);
}
else if (type == LIBUSB_TRANSFER_TYPE_CONTROL)
{
// ret = libusb_control_transfer()
}
else if (type == LIBUSB_TRANSFER_TYPE_INTERRUPT)
{
*desc = L"Interrupt";
ret = libusb_interrupt_transfer(h, addr, buf, *len, len, to);
}
return ret;
}
std::wstring now(void)
{
std::string cur(std::move(chronograph::now()));
return std::move(a2u(cur.c_str()));
//wchar_t buf[40] = { 0 };
//time_t t = time(NULL);
//tm* lt = localtime(&t);
//swprintf_s(buf, _countof(buf) - 1, L"%04d-%02d-%02d %02d:%02d:%02d", lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec);
//return buf;
}
const wchar_t* error_name(int err, wchar_t* unk)
{
#define RETURN_IF(e) \
if(err == e) \
return L###e;
RETURN_IF(LIBUSB_SUCCESS);
RETURN_IF(LIBUSB_ERROR_IO);
RETURN_IF(LIBUSB_ERROR_INVALID_PARAM);
RETURN_IF(LIBUSB_ERROR_ACCESS);
RETURN_IF(LIBUSB_ERROR_NO_DEVICE);
RETURN_IF(LIBUSB_ERROR_NOT_FOUND);
RETURN_IF(LIBUSB_ERROR_BUSY);
RETURN_IF(LIBUSB_ERROR_TIMEOUT);
RETURN_IF(LIBUSB_ERROR_OVERFLOW);
RETURN_IF(LIBUSB_ERROR_PIPE);
RETURN_IF(LIBUSB_ERROR_INTERRUPTED);
RETURN_IF(LIBUSB_ERROR_NO_MEM);
RETURN_IF(LIBUSB_ERROR_NOT_SUPPORTED);
RETURN_IF(LIBUSB_ERROR_OTHER);
RETURN_IF(LIBUSB_ERROR_TRY_AGAIN);
if (unk)
{
swprintf(unk, L"%d", err);
return unk;
}
wchar_t buf[20] = { 0 };
swprintf_s(buf, _countof(buf) - 1, L"%d", err);
return buf;
}
INTER_MODULE_CALLBACK(got_wstr)
{
*((std::wstring*)param) += std::wstring((const wchar_t*)data, len / 2);
return inter_module_data::SET_RESULT_CONTINUE;
}
INTER_MODULE_CALLBACK(got_str)
{
*((std::string*)param) += std::string(data, len);
return inter_module_data::SET_RESULT_CONTINUE;
}
std::wstring a2u(const char* ansi)
{
std::wstring u(L"");
coding_util::ansi_2_unicode(ansi, got_wstr, &u);
return std::move(u);
}
std::string u2a(const wchar_t* unic)
{
std::string a("");
coding_util::unicode_2_ansi(unic, got_str, &a);
return std::move(a);
}
static void register_tray(HWND owner, HICON icon, bool reg)
{
if(reg)
win_util::add_tray_icon(WM_TRAY_MSG, owner, WM_TRAY_MSG, L"Operate on USB device", icon);
else
win_util::remove_tray_icon(WM_TRAY_MSG, owner);
}
}
2023-05-02 01:50:55 +00:00
namespace test
{
enum data_type1
{
DATA_TYPE_BOOL = 0, // (bool*)
DATA_TYPE_INT1, // (uint8_t*)
DATA_TYPE_INT2, // (uint16_t*)
DATA_TYPE_INT4, // (uint32_t*)
DATA_TYPE_INT8, // (uint64_t*)
DATA_TYPE_FLOAT, // (double*)
DATA_TYPE_STRING, // (char*) with max_len space
DATA_TYPE_CUSTOM,
};
data_type1 type_from_string(const char* type_desc)
{
if (strcmp(type_desc, "bool") == 0)
return DATA_TYPE_BOOL;
if (strcmp(type_desc, "int") == 0)
return DATA_TYPE_INT4;
if (strcmp(type_desc, "float") == 0)
return DATA_TYPE_FLOAT;
if (strcmp(type_desc, "string") == 0)
return DATA_TYPE_STRING;
return DATA_TYPE_CUSTOM;
}
bool try_equal(std::string& exp, std::string* name, int* type, std::string* val, std::function<int32_t(const char* cfg_name, void* buf, size_t* len, const char* key)> get_opt, bool* result)
{
bool oper_not = false, calc = true, handled = false;
size_t pos = exp.find("==");
if (pos == std::string::npos)
{
pos = exp.find("!=");
if (pos != std::string::npos)
{
oper_not = true;
}
}
if (pos != std::string::npos)
{
handled = true;
if (pos)
{
std::string types("");
char buf[40] = { 0 }, * mem = nullptr;
size_t l = sizeof(buf) - 1;
*name = exp.substr(0, pos);
get_opt(name->c_str(), buf, &l, "type");
*type = type_from_string(buf);
l = 0;
get_opt(name->c_str(), mem, &l, "cur");
mem = new char[l + 4];
l += 4;
get_opt(name->c_str(), mem, &l, "cur");
*val = std::string(mem, l);
delete[] mem;
}
exp.erase(0, pos + 2);
if (*type == DATA_TYPE_BOOL)
{
calc = *(bool*)val->c_str() == (exp == "true");
}
else if (*type == DATA_TYPE_INT4)
{
// in range ?
if (exp[0] == '[')
{
int lower = atoi(exp.c_str() + 1),
upper = 0;
pos = exp.find(",");
if (pos++ != std::string::npos)
upper = atoi(exp.c_str() + pos);
calc = lower <= *(int*)val->c_str() && *(int*)val->c_str() <= upper;
}
else
{
calc == *(int*)val->c_str() == atoi(exp.c_str());
}
}
else if (*type == DATA_TYPE_FLOAT)
{
// in range ?
if (exp[0] == '[')
{
double lower = atof(exp.c_str() + 1),
upper = 0;
pos = exp.find(",");
if (pos++ != std::string::npos)
upper = atof(exp.c_str() + pos);
calc = lower <= *(double*)val->c_str() && *(double*)val->c_str() <= upper;
}
else
{
calc = IS_FLOAT_EQUAL(*(double*)val->c_str(), atof(exp.c_str()));
}
}
else if (*type == DATA_TYPE_STRING)
{
calc = *val == exp;
}
else
{
log_cls::log(LOG_LEVEL_FATAL, "Logic-operation error: un-supported type(%d) in '%s%s'\n", *type, oper_not ? "!=" : "==", exp.c_str());
}
*result = oper_not ^ calc;
}
return handled;
}
bool try_great(std::string& exp, std::string* name, int* type, std::string* val, std::function<int32_t(const char* cfg_name, void* buf, size_t* len, const char* key)> get_opt, bool* result)
{
bool oper_not = false, calc = true, handled = false;
size_t pos = exp.find(">");
if (pos == std::string::npos)
{
pos = exp.find("<=");
if (pos != std::string::npos)
{
oper_not = true;
}
}
if (pos != std::string::npos)
{
handled = true;
if (pos)
{
std::string types("");
char buf[40] = { 0 }, * mem = nullptr;
size_t l = sizeof(buf) - 1;
*name = exp.substr(0, pos);
get_opt(name->c_str(), buf, &l, "type");
*type = type_from_string(buf);
l = 0;
get_opt(name->c_str(), mem, &l, "cur");
mem = new char[l + 4];
l += 4;
get_opt(name->c_str(), mem, &l, "cur");
*val = std::string(mem, l);
delete[] mem;
}
exp.erase(0, pos + 1 + oper_not);
if (*type == DATA_TYPE_INT4)
{
calc == *(int*)val->c_str() > atoi(exp.c_str());
}
else if (*type == DATA_TYPE_FLOAT)
{
calc = *(double*)val->c_str() > atof(exp.c_str());
}
else
{
log_cls::log(LOG_LEVEL_FATAL, "Logic-operation error: un-supported type(%d) in '%s%s'\n", *type, oper_not ? "<=" : ">", exp.c_str());
}
*result = oper_not ^ calc;
}
return handled;
}
bool try_less(std::string& exp, std::string* name, int* type, std::string* val, std::function<int32_t(const char* cfg_name, void* buf, size_t* len, const char* key)> get_opt, bool* result)
{
bool oper_not = false, calc = true, handled = false;
size_t pos = exp.find("<");
if (pos == std::string::npos)
{
pos = exp.find(">=");
if (pos != std::string::npos)
{
oper_not = true;
}
}
if (pos != std::string::npos)
{
handled = true;
if (pos)
{
std::string types("");
char buf[40] = { 0 }, * mem = nullptr;
size_t l = sizeof(buf) - 1;
*name = exp.substr(0, pos);
get_opt(name->c_str(), buf, &l, "type");
*type = type_from_string(buf);
l = 0;
get_opt(name->c_str(), mem, &l, "cur");
mem = new char[l + 4];
l += 4;
get_opt(name->c_str(), mem, &l, "cur");
*val = std::string(mem, l);
delete[] mem;
}
exp.erase(0, pos + 1 + oper_not);
if (*type == DATA_TYPE_INT4)
{
calc == *(int*)val->c_str() < atoi(exp.c_str());
}
else if (*type == DATA_TYPE_FLOAT)
{
calc = *(double*)val->c_str() < atof(exp.c_str());
}
else
{
log_cls::log(LOG_LEVEL_FATAL, "Logic-operation error: un-supported type(%d) in '%s%s'\n", *type, oper_not ? ">=" : "<", exp.c_str());
}
*result = oper_not ^ calc;
}
return handled;
}
bool is_depends_item_ok(std::string& exp, std::string* name, int* type, std::string* val, std::function<int32_t(const char* cfg_name, void* buf, size_t* len, const char* key)> get_opt)
{
// ==, >, <
// !=, <=, >=
bool ok = true;
if (!try_equal(exp, name, type, val, get_opt, &ok))
{
if (!try_great(exp, name, type, val, get_opt, &ok))
{
try_less(exp, name, type, val, get_opt, &ok);
}
}
return ok;
}
}
2023-04-08 00:56:20 +00:00
CusbtoolsDlg::CusbtoolsDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_USB_TOOLS_DIALOG, pParent)
{
log_cls::initialize(NULL);
2023-04-13 06:42:43 +00:00
log_cls::log(LOG_LEVEL_DEBUG, "--------------------New instance started ...--------------------\r\n");
2023-04-08 00:56:20 +00:00
2023-05-02 01:50:55 +00:00
auto get_opt_val = [&](const char* cfg_name, void* buf, size_t* len, const char* key) -> int32_t
{
if (strcmp(key, "type") == 0)
strcpy((char*)buf, "bool");
else if (strcmp(key, "cur") == 0)
{
if (*len < 1)
{
*len = 1;
return ENOMEM;
}
*(bool*)buf = false;
*len = sizeof(bool);
}
return 0;
};
std::string exp("is-check-dog-ear==true"), name(""), val("");
int type = 0;
bool chk = test::is_depends_item_ok(exp, &name, &type, &val, get_opt_val);
2023-04-08 00:56:20 +00:00
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CusbtoolsDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST_DEVICES, devl_);
}
BEGIN_MESSAGE_MAP(CusbtoolsDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_CHECK_AUTO_MON, &CusbtoolsDlg::OnBnClickedCheckAutoMon)
ON_MESSAGE(WM_USB_PNP, &CusbtoolsDlg::OnUsbPnp)
ON_MESSAGE(WM_RCV_MSG, &CusbtoolsDlg::OnRcvMsg)
ON_MESSAGE(WM_OPENNING_DLG_CLOSED, &CusbtoolsDlg::OnDevDlgClosed)
ON_MESSAGE(WM_TRAY_MSG, &CusbtoolsDlg::OnTray)
ON_NOTIFY(NM_DBLCLK, IDC_LIST_DEVICES, &CusbtoolsDlg::OnNMDblclkListDevices)
ON_BN_CLICKED(IDC_BUTTON_CLEAR, &CusbtoolsDlg::OnBnClickedButtonClear)
ON_WM_SYSCOMMAND()
ON_COMMAND(ID_TRAY_EXIT, &CusbtoolsDlg::OnTrayExit)
ON_COMMAND_RANGE(ID_TRAY_EXIT + 1, ID_TRAY_EXIT + 100, &CusbtoolsDlg::OnTrayDevice)
ON_BN_CLICKED(IDOK, &CusbtoolsDlg::OnBnClickedOk)
ON_WM_SIZE()
END_MESSAGE_MAP()
// CusbtoolsDlg 消息处理程序
bool show_balloon(int tray_id, HWND main_wnd, const wchar_t* tips, const wchar_t* title, DWORD dwTimeout, HICON hIcon, DWORD dwInfoFlag)
{
NOTIFYICONDATAW nid = { 0 };
nid.cbSize = NOTIFYICONDATA_V2_SIZE; // KEY parameter to show balloon message!
//nid.uVersion = NOTIFYICON_VERSION;
nid.hWnd = main_wnd;
nid.uID = tray_id;
nid.uFlags = /*NIF_INFO |*/ NIF_TIP;
wcscpy_s(nid.szTip, _countof(nid.szTip) - 1, tips);
wcscpy_s(nid.szInfoTitle, _countof(nid.szInfoTitle) - 1, title);
nid.hIcon = hIcon ? hIcon : (HICON)SendMessageW(main_wnd, WM_GETICON, ICON_SMALL, 0);
nid.uTimeout = dwTimeout;
nid.dwInfoFlags = dwInfoFlag;
return Shell_NotifyIconW(NIM_MODIFY, &nid) == TRUE;
}
BOOL CusbtoolsDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
int ind = 0;
devl_.InsertColumn(ind++, TEXT("No."), 0, 51);
devl_.InsertColumn(ind++, TEXT("VID"), 0, 75);
devl_.InsertColumn(ind++, TEXT("PID"), 0, 75);
devl_.SetExtendedStyle(devl_.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_INFOTIP);
//SetDlgItemInt(IDC_EDIT_TYPE, 0x40);
//SetDlgItemInt(IDC_EDIT_REQ, 0x64);
//SetDlgItemInt(IDC_EDIT_VALUE, 16);
//SetDlgItemInt(IDC_EDIT_INDEX, 0);
//SetDlgItemInt(IDC_EDIT_LEN, 20);
OnBnClickedCheckAutoMon();
tray_ = LoadMenu(NULL, MAKEINTRESOURCE(IDR_MENU1));
desktop_ = ::FindWindowExW(NULL, NULL, L"Shell_TrayWnd", NULL);
usb::register_tray(m_hWnd, m_hIcon, true);
SetPropW(m_hWnd, L"task_usb", m_hWnd);
2023-04-13 06:42:43 +00:00
::SetDlgItemTextA(m_hWnd, IDC_EDIT_LOG_FILE, log_cls::get_log_file().c_str());
2023-04-08 00:56:20 +00:00
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CusbtoolsDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CusbtoolsDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CusbtoolsDlg::usb_monitor_thread(void)
{
while (mon_)
{
timeval tm = { 1,0 };
libusb_handle_events_timeout(ctx_, &tm);
}
}
void CusbtoolsDlg::enable_io_ui(bool enable)
{
GetDlgItem(IDC_BUTTON_SEND)->EnableWindow(enable);
GetDlgItem(IDC_CHECK_AUTO)->EnableWindow(enable);
enable &= ((CButton*)GetDlgItem(IDC_CHECK_AUTO))->GetCheck() != BST_CHECKED;
GetDlgItem(IDC_BUTTON_RECEIVE)->EnableWindow(enable);
//GetDlgItem(IDC_COMBO_EP2)->EnableWindow(enable);
//OnCbnSelchangeComboEp();
//GetDlgItem(IDC_EDIT_TYPE)->EnableWindow(enable);
//GetDlgItem(IDC_EDIT_REQ)->EnableWindow(enable);
//GetDlgItem(IDC_EDIT_VALUE)->EnableWindow(enable);
//GetDlgItem(IDC_EDIT_INDEX)->EnableWindow(enable);
//GetDlgItem(IDC_EDIT_LEN)->EnableWindow(enable);
}
void CusbtoolsDlg::add_pnp_que(usb::LPUSBPNP pnp)
{
int vid = pnp->vid,
pid = pnp->pid;
for (auto& v : pnp_que_)
{
if (v->ctx == pnp->ctx && v->device == pnp->device)
{
v->arrive = true;
libusb_unref_device(pnp->device);
if (v->dlg)
{
open_usb(v, false);
}
delete pnp;
pnp = NULL;
break;
}
}
if (pnp)
{
pnp_que_.push_back(pnp);
// add to UI ...
int item = devl_.InsertItem(devl_.GetItemCount(), std::to_wstring(devl_.GetItemCount() + 1).c_str());
TCHAR text[40] = { 0 };
libusb_device_descriptor desc;
libusb_get_device_descriptor(pnp->device, &desc);
_stprintf(text, TEXT("%04X"), desc.idVendor);
devl_.SetItemText(item, 1, text);
_stprintf(text, TEXT("%04X"), desc.idProduct);
devl_.SetItemText(item, 2, text);
devl_.SetItemData(item, (DWORD_PTR)pnp);
}
if (!IsWindowVisible())
{
wchar_t tips[128] = { 0 };
swprintf_s(tips, _countof(tips) - 1, L"%04X:%04X arrived", vid, pid);
show_balloon(WM_TRAY_MSG, m_hWnd, tips, L"USB", 1000, m_hIcon, NIF_TIP);
}
}
void CusbtoolsDlg::remove_pnp_que(usb::LPUSBPNP pnp)
{
for (size_t i = 0; i < pnp_que_.size(); ++i)
{
if (!pnp || (pnp_que_[i]->ctx == pnp->ctx && pnp_que_[i]->device == pnp->device))
{
for (int j = 0; j < devl_.GetItemCount(); ++j)
{
if (!pnp || devl_.GetItemData(j) == (DWORD_PTR)pnp_que_[i])
{
//if (devl_.GetItemState(j, LVIS_SELECTED))
// enable_io_ui(false);
if (pnp_que_[i]->dlg == NULL)
{
devl_.SetItemData(j, 0);
devl_.DeleteItem(j);
for (; pnp && j < devl_.GetItemCount(); ++j)
devl_.SetItemText(j, 0, std::to_wstring(j + 1).c_str());
}
else
pnp_que_[i]->arrive = false;
if (pnp)
break;
}
}
if (pnp_que_[i]->dlg)
{
pnp_que_[i]->dlg->set_device(NULL);
//if(!pnp)
//{
// pnp_que_[i]->dlg->DestroyWindow();
// delete pnp_que_[i]->dlg;
// pnp_que_[i]->dlg = NULL;
//}
}
else
{
close_device(pnp_que_[i]);
delete pnp_que_[i];
pnp_que_.erase(pnp_que_.begin() + i);
libusb_unref_device(pnp->device);
}
if(pnp)
break;
}
}
if (!IsWindowVisible() && pnp)
{
wchar_t tips[128] = { 0 };
swprintf_s(tips, _countof(tips) - 1, L"%04X:%04X left", pnp->vid, pnp->pid);
show_balloon(WM_TRAY_MSG, m_hWnd, tips, L"USB", 1000, m_hIcon, NIF_TIP);
}
}
void CusbtoolsDlg::append_log(const wchar_t* log, UINT id)
{
int len = ::GetWindowTextLength(GetDlgItem(id)->m_hWnd);
wchar_t* buf = new wchar_t[len + 128];
libusb_device_descriptor desc;
::GetDlgItemTextW(m_hWnd, id, buf, len + 20);
::SetDlgItemTextW(m_hWnd, id, (std::wstring(buf) + log).c_str());
while (::SendMessage(GetDlgItem(id)->m_hWnd, EM_SCROLL, SB_PAGEDOWN, 0));
delete[] buf;
}
void CusbtoolsDlg::log_pnp(usb::LPUSBPNP pnp)
{
wchar_t buf[128] = { 0 };
swprintf_s(buf + lstrlenW(buf), _countof(buf) - 1, L"%s: %04X:%04X %s\r\n", usb::now().c_str(),
pnp->vid, pnp->pid, pnp->arrive ? L"Arrive" : L"Left");
append_log(buf, IDC_EDIT_PNP_MSG);
2023-04-13 06:42:43 +00:00
log_cls::log(LOG_LEVEL_ALL, "%04X:%04X %s\r\n", pnp->vid, pnp->pid, pnp->arrive ? "Arrived" : "Left");
2023-04-08 00:56:20 +00:00
}
bool CusbtoolsDlg::endpoint_from_combo_text(wchar_t* text, BYTE& type, BYTE& addr)
{
wchar_t* ptr = wcsstr(text, L" ");
bool ret = false;
if (ptr)
{
*ptr++ = 0;
type = usb::ep_type(text);
if (type != -1)
{
ptr = wcsstr(ptr, L"-");
if (ptr++)
{
while (*ptr == L' ') ptr++;
addr = usb::from_hex_str(ptr, &ret);
}
}
}
return ret;
}
void CusbtoolsDlg::close_device(usb::LPUSBPNP pnp)
{
if (pnp->handle)
{
int face = -1;
for (auto& v : pnp->eps)
{
if (face != v.iface)
{
face = v.iface;
libusb_release_interface(pnp->handle, face);
}
}
libusb_close(pnp->handle);
pnp->handle = NULL;
}
wchar_t msg[128] = { 0 };
swprintf_s(msg, _countof(msg) - 1, L"%s: %04X:%04X closed.\r\n", usb::now().c_str(), pnp->vid, pnp->pid);
append_log(msg, IDC_EDIT_PNP_MSG);
}
usb::LPUSBPNP CusbtoolsDlg::get_cur_device(void)
{
for (int i = 0; i < devl_.GetItemCount(); ++i)
{
if (devl_.GetItemState(i, LVIS_SELECTED))
return (usb::LPUSBPNP)devl_.GetItemData(i);
}
return NULL;
}
void CusbtoolsDlg::open_usb(usb::LPUSBPNP pnp, bool from_list)
{
wchar_t msg[256] = { 0 }, errb[40] = { 0 };
int face = -1, ret = 0;
//*
if (pnp->dlg == NULL)
{
pnp->dlg = new CDlgScanner(this); // new CDlgOpenning(this);
pnp->dlg->Create(IDD_SCANNER); // (IDD_OPENNING);
}
pnp->dlg->set_device(pnp);
pnp->dlg->ShowWindow(SW_SHOW);
/*/
ret = libusb_open(pnp->device, &pnp->handle);
if (ret == LIBUSB_SUCCESS)
{
for (auto& v : pnp->eps)
{
if (face != v.iface)
{
face = v.iface;
ret = libusb_claim_interface(pnp->handle, face);
if (ret)
break;
}
}
if (ret == LIBUSB_SUCCESS)
{
if (pnp->dlg == NULL)
{
pnp->dlg = new CDlgOpenning(this);
pnp->dlg->Create(IDD_OPENNING);
}
if (pnp->eps.empty())
usb::enum_endpoints(pnp->device, pnp->eps);
pnp->dlg->set_device(pnp);
pnp->dlg->ShowWindow(SW_SHOW);
}
else
{
swprintf_s(msg, _countof(msg) - 1, L"%s: Claim interface %d of %04X:%04X failed: %s\r\n", usb::now().c_str()
, face, pnp->vid, pnp->pid, usb::error_name(ret, errb));
for (auto& v : pnp->eps)
{
if (v.iface == face)
break;
if (ret != v.iface)
{
ret = v.iface;
libusb_release_interface(pnp->handle, v.iface);
}
}
libusb_close(pnp->handle);
pnp->handle = NULL;
}
}
else
{
swprintf_s(msg, _countof(msg) - 1, L"%s: libusb_open(%04X:%04X) failed: %s\r\n", usb::now().c_str()
, pnp->vid, pnp->pid, usb::error_name(ret, errb));
}
////////////////////*///////////////////////////////////////////
if (!msg[0])
swprintf_s(msg, _countof(msg) - 1, L"%s: open %04X:%04X success\r\n", usb::now().c_str(), pnp->vid, pnp->pid);
else if (!from_list)
::MessageBoxW(m_hWnd, msg, L"Failed", MB_OK | MB_ICONERROR);
append_log(msg, IDC_EDIT_PNP_MSG);
}
LRESULT CusbtoolsDlg::OnUsbPnp(WPARAM wp, LPARAM lp)
{
usb::LPUSBPNP pnp = (usb::LPUSBPNP)lp;
log_pnp(pnp);
2023-04-13 06:42:43 +00:00
if (pnp->pid == 0 && pnp->vid == 0)
{
delete pnp;
return 0;
}
2023-04-08 00:56:20 +00:00
if (pnp->arrive)
{
////for (auto& v : pnp_que_)
////{
//// if (v->ctx == pnp->ctx && v->device == pnp->device)
//// {
//// libusb_unref_device(pnp->device);
//// v->arrive = true;
//// delete pnp;
//// pnp = NULL;
//// break;
//// }
////}
//if (pnp)
add_pnp_que(pnp);
}
else
{
remove_pnp_que(pnp);
// libusb_unref_device(pnp->device);
delete pnp;
}
return 0;
}
LRESULT CusbtoolsDlg::OnRcvMsg(WPARAM wp, LPARAM lp)
{
std::wstring* msg = (std::wstring*)lp;
//append_log(msg->c_str(), IDC_EDIT_REPLY);
delete msg;
return 0;
}
LRESULT CusbtoolsDlg::OnDevDlgClosed(WPARAM wp, LPARAM lp)
{
CDlgScanner* dlg = (CDlgScanner*)lp;
//CDlgOpenning* dlg = (CDlgOpenning*)lp;
for (int i = 0; i < pnp_que_.size(); ++i)
{
if (pnp_que_[i]->dlg == dlg)
{
pnp_que_[i]->dlg = NULL;
close_device(pnp_que_[i]);
if (!pnp_que_[i]->arrive)
{
for (int j = 0; j < devl_.GetItemCount(); ++j)
{
if (devl_.GetItemData(i) == (DWORD_PTR)pnp_que_[i])
{
devl_.DeleteItem(i);
for (; j < devl_.GetItemCount(); ++j)
devl_.SetItemText(j, 0, std::to_wstring(j + 1).c_str());
break;
}
}
delete pnp_que_[i];
pnp_que_.erase(pnp_que_.begin() + i);
}
break;
}
}
dlg->DestroyWindow();
delete dlg;
return 0;
}
LRESULT CusbtoolsDlg::OnTray(WPARAM wp, LPARAM lp)
{
UINT msg = (UINT)lp;
if (msg == WM_LBUTTONDBLCLK)
{
ShowWindow(SW_RESTORE);
SetForegroundWindow();
if (MAKELPARAM(MAKEWORD('P', 'O'), MAKEWORD('P', 'M')) == wp)
{
HWND taskwnd = ::FindWindowExW(NULL, NULL, L"Shell_TrayWnd", NULL);
if (desktop_ != taskwnd && IsWindow(taskwnd))
{
usb::register_tray(m_hWnd, m_hIcon, true);
desktop_ = taskwnd;
}
}
}
else if (msg == WM_RBUTTONDOWN)
{
// exit ...
POINT pt = { 0 };
HMENU hm = GetSubMenu(tray_, 0);
MENUITEMINFOW mi = { 0 };
mi.cbSize = sizeof(mi);
mi.fMask = MIIM_DATA;
while (GetMenuItemInfoW(hm, 0, TRUE, &mi) && mi.dwItemData)
DeleteMenu(hm, 0, MF_BYPOSITION);
for (int i = 0; i < devl_.GetItemCount(); ++i)
{
usb::LPUSBPNP pnp = (usb::LPUSBPNP)devl_.GetItemData(i);
wchar_t id[40] = { 0 };
swprintf_s(id, _countof(id) - 1, L"%04X:%04X", pnp->vid, pnp->pid);
InsertMenuW(hm, i, MF_BYPOSITION, ID_TRAY_EXIT + 1 + i, id);
mi.dwItemData = (LONG)pnp;
SetMenuItemInfoW(hm, i, TRUE, &mi);
if (pnp->dlg)
CheckMenuItem(hm, i, MF_CHECKED | MF_BYPOSITION);
}
GetCursorPos(&pt);
TrackPopupMenu(hm, TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0, m_hWnd, NULL);
}
return 0;
}
void CusbtoolsDlg::OnBnClickedCheckAutoMon()
{
// TODO: 在此添加控件通知处理程序代码
static libusb_hotplug_callback_handle handle = NULL;
if (ctx_)
{
libusb_context* cp = ctx_;
mon_ = false;
ctx_ = NULL;
if (mon_thrd_.get() && mon_thrd_->joinable())
mon_thrd_->join();
mon_thrd_.reset();
libusb_hotplug_deregister_callback(cp, handle);
libusb_exit(cp);
handle = NULL;
}
else
{
libusb_init(&ctx_);
int ret = libusb_hotplug_register_callback(ctx_, (libusb_hotplug_event)(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
(libusb_hotplug_flag)LIBUSB_HOTPLUG_ENUMERATE,
LIBUSB_HOTPLUG_MATCH_ANY,//LIBUSB_HOTPLUG_MATCH_ANY
LIBUSB_HOTPLUG_MATCH_ANY,//LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
&usb::usb_pnp,
m_hWnd,
&handle);
mon_ = true;
mon_thrd_.reset(new std::thread(&CusbtoolsDlg::usb_monitor_thread, this));
}
}
void CusbtoolsDlg::OnNMDblclkListDevices(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
*pResult = 0;
if (pNMItemActivate->iItem < 0 || pNMItemActivate->iItem >= devl_.GetItemCount())
return;
wchar_t msg[256] = { 0 }, unk[40] = { 0 };
usb::LPUSBPNP pnp = (usb::LPUSBPNP)devl_.GetItemData(pNMItemActivate->iItem);
int face = -1, ret = 0;
//CDlgScanner dlg;
//dlg.DoModal();
//return;
if (!pnp->dlg)
{
open_usb(pnp);
}
else
{
RECT r = { 0 };
pnp->dlg->GetWindowRect(&r);
::SetWindowPos(pnp->dlg->m_hWnd, HWND_TOPMOST, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOSENDCHANGING | SWP_SHOWWINDOW);
::SetTimer(pnp->dlg->m_hWnd, WM_TIMER_CANCEL_TOPMOST, 1000, NULL);
}
}
void CusbtoolsDlg::OnBnClickedButtonClear()
{
// TODO: 在此添加控件通知处理程序代码
SetDlgItemText(IDC_EDIT_PNP_MSG, TEXT(""));
}
void CusbtoolsDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (nID == SC_CLOSE)
{
ShowWindow(SW_MINIMIZE);
ShowWindow(SW_HIDE);
return;
}
CDialogEx::OnSysCommand(nID, lParam);
}
void CusbtoolsDlg::OnTrayExit()
{
// TODO: 在此添加命令处理程序代码
usb::register_tray(m_hWnd, m_hIcon, false);
PostQuitMessage(0);
}
void CusbtoolsDlg::OnTrayDevice(UINT id)
{
// TODO: 在此添加命令处理程序代码
HMENU hm = GetSubMenu(tray_, 0);
MENUITEMINFOW mi = { 0 };
mi.cbSize = sizeof(mi);
mi.fMask = MIIM_DATA | MIIM_STATE;
GetMenuItemInfoW(hm, id, FALSE, &mi);
if (mi.dwItemData)
{
usb::LPUSBPNP pnp = (usb::LPUSBPNP)mi.dwItemData;
if (pnp->dlg)
pnp->dlg->OnBnClickedOk();
else
open_usb(pnp, false);
}
}
void CusbtoolsDlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
OnTrayExit();
CDialogEx::OnOK();
}
void CusbtoolsDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
//if (cx == 0 && cy == 0 && ::IsWindow(devl_.m_hWnd))
//{
// for (int i = 0; i < devl_.GetItemCount(); ++i)
// {
// usb::LPUSBPNP pnp = (usb::LPUSBPNP)devl_.GetItemData(i);
// if (pnp && pnp->dlg)
// pnp->dlg->ShowWindow(SW_SHOW);
// }
//}
}