// 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 #include #include // CusbtoolsDlg 对话框 #pragma warning(disable: 4996) #include #include namespace usb { void enum_endpoints(libusb_device* device, std::vector& 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); } } 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 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 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 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 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; } } CusbtoolsDlg::CusbtoolsDlg(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_USB_TOOLS_DIALOG, pParent) { log_cls::initialize(NULL); log_cls::log(LOG_LEVEL_DEBUG, "--------------------New instance started ...--------------------\r\n"); 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); 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); ::SetDlgItemTextA(m_hWnd, IDC_EDIT_LOG_FILE, log_cls::get_log_file().c_str()); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void CusbtoolsDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast(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(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); log_cls::log(LOG_LEVEL_ALL, "%04X:%04X %s\r\n", pnp->vid, pnp->pid, pnp->arrive ? "Arrived" : "Left"); } 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); if (pnp->pid == 0 && pnp->vid == 0) { delete pnp; return 0; } 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(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); // } //} }