/* --------------------------------------- 关闭通讯接口 --------------------------------------- */ static bool_t qst_com_close ( __CR_IN__ void_t* parm, __CR_IN__ uint_t argc, __CR_IN__ ansi_t** argv ) { sQstComm* ctx; CR_NOUSE(argc); CR_NOUSE(argv); ctx = (sQstComm*)parm; if (ctx->comm.thrd == NULL) return (FALSE); ctx->comm.quit = TRUE; thread_wait(ctx->comm.thrd); thread_del(ctx->comm.thrd); ctx->comm.thrd = NULL; ctx->comm.quit = FALSE; SAFE_FREE(ctx->comm.title); qst_update_title(ctx); CR_VCALL(ctx->bufs)->reput(ctx->bufs, 0); ctx->size = 0; return (TRUE); }
/* --------------------------------------- 打开 UDPv4 通讯接口 --------------------------------------- */ static bool_t qst_com_udpv4 ( __CR_IN__ void_t* parm, __CR_IN__ uint_t argc, __CR_IN__ ansi_t** argv ) { uint_t port; socket_t netw; /* 参数解析 <目标地址> <端口号> */ if (argc < 3) return (FALSE); port = str2intxA(argv[2]); if (port > 65535) return (FALSE); sQstComm* ctx = (sQstComm*)parm; /* 关闭当前接口并打开 UDPv4 连接 */ netw = client_udp_open(argv[1], (int16u)port); if (netw == NULL) return (FALSE); socket_set_timeout(netw, QCOM_SNDTOUT, QCOM_CUTDOWN); /* 设置工作参数 */ qst_com_close(parm, argc, argv); ctx->comm.obj.netw = netw; ctx->comm.send = qst_udpv4_send; /* 启动接收线程 */ ctx->comm.thrd = thread_new(0, qst_udpv4_main, parm, FALSE); if (ctx->comm.thrd == NULL) { socket_close(netw); return (FALSE); } TRY_FREE(ctx->comm.title); ctx->comm.title = str_fmtA(" - UDPv4 \"%s\", %u", argv[1], port); qst_update_title(ctx); return (TRUE); }
/* --------------------------------------- 设置通讯接收模式 --------------------------------------- */ static bool_t qst_com_rtype ( __CR_IN__ void_t* parm, __CR_IN__ uint_t argc, __CR_IN__ ansi_t** argv ) { static ansi_t* name = NULL; /* 参数解析 <接收模式/插件名称> [函数名称] */ if (argc < 2) return (FALSE); sQstComm* ctx = (sQstComm*)parm; CTextOper* opr = (CTextOper*)ctx->oper; _ENTER_COM_SINGLE_ if (str_cmpA(argv[1], "text") == 0) { ctx->comm.text = TRUE; ctx->comm.render = qst_txt_show; ctx->comm.rtype = "text"; } else if (str_cmpA(argv[1], "html") == 0) { ctx->comm.text = TRUE; ctx->comm.render = qst_htm_show; ctx->comm.rtype = "html"; } else if (str_cmpA(argv[1], "hex") == 0) { ctx->comm.text = FALSE; ctx->comm.render = qst_hex_show; ctx->comm.rtype = "hex"; } else if (str_cmpA(argv[1], "ansi") == 0) { qst_csi_clear(); ctx->comm.text = TRUE; ctx->comm.render = qst_csi_show; ctx->comm.rtype = "ansi"; } else { sbin_t sbin; plugin_render_t func; /* 使用外部插件 */ if (argc < 3) goto _failure; sbin = sbin_loadA(argv[1]); if (sbin == NULL) goto _failure; func = sbin_exportT(sbin, argv[2], plugin_render_t); if (func == NULL) { sbin_unload(sbin); goto _failure; } ctx->comm.text = FALSE; ctx->comm.render = func; TRY_FREE(name); name = str_fmtA("%s|%s", argv[1], argv[2]); ctx->comm.rtype = (name == NULL) ? "null" : name; } opr->clear(); _LEAVE_COM_SINGLE_ qst_update_title(ctx); return (TRUE); _failure: _LEAVE_COM_SINGLE_ return (FALSE); }
/* --------------------------------------- 设置通讯发送模式 --------------------------------------- */ static bool_t qst_com_stype ( __CR_IN__ void_t* parm, __CR_IN__ uint_t argc, __CR_IN__ ansi_t** argv ) { static ansi_t* name = NULL; /* 参数解析 <发送模式/插件名称> [函数名称] */ if (argc < 2) return (FALSE); sQstComm* ctx = (sQstComm*)parm; if (str_cmpA(argv[1], "text") == 0) { ctx->comm.tran = NULL; ctx->comm.stype = "text"; } else if (str_cmpA(argv[1], "hex") == 0) { ctx->comm.tran = qst_hex_tran; ctx->comm.stype = "hex"; } else if (str_cmpA(argv[1], "esc") == 0) { ctx->comm.tran = qst_esc_tran; ctx->comm.stype = "esc"; } else if (str_cmpA(argv[1], "dos") == 0) { ctx->comm.tran = qst_dos_tran; ctx->comm.stype = "dos"; } else if (str_cmpA(argv[1], "unix") == 0) { ctx->comm.tran = qst_unx_tran; ctx->comm.stype = "unix"; } else if (str_cmpA(argv[1], "mac") == 0) { ctx->comm.tran = qst_mac_tran; ctx->comm.stype = "mac"; } else { sbin_t sbin; plugin_tran_t func; /* 使用外部插件 */ if (argc < 3) return (FALSE); sbin = sbin_loadA(argv[1]); if (sbin == NULL) return (FALSE); func = sbin_exportT(sbin, argv[2], plugin_tran_t); if (func == NULL) { sbin_unload(sbin); return (FALSE); } ctx->comm.tran = func; TRY_FREE(name); name = str_fmtA("%s|%s", argv[1], argv[2]); ctx->comm.stype = (name == NULL) ? "null" : name; } qst_update_title(ctx); return (TRUE); }
/* --------------------------------------- 打开 RS232 通讯接口 --------------------------------------- */ static bool_t qst_com_rs232 ( __CR_IN__ void_t* parm, __CR_IN__ uint_t argc, __CR_IN__ ansi_t** argv ) { int32u baud; uint_t port, bits; uint_t stop, parity; /* --------------- */ const ansi_t* sstop; const ansi_t* sparity; /* 参数解析 <串口号> [波特率] [数据位] [校验位] [停止位] */ if (argc < 2) return (FALSE); bits = 8; baud = 115200UL; stop = CR_SIO_STOP10; parity = CR_SIO_NOP; sstop = "1"; sparity = "no"; port = str2intxA(argv[1]); if (argc > 2) { baud = str2intx32A(argv[2]); if (argc > 3) { bits = str2intxA(argv[3]); if (argc > 4) { sparity = argv[4]; if (str_cmpA(argv[4], "no") == 0) parity = CR_SIO_NOP; else if (str_cmpA(argv[4], "odd") == 0) parity = CR_SIO_ODD; else if (str_cmpA(argv[4], "even") == 0) parity = CR_SIO_EVEN; else if (str_cmpA(argv[4], "mark") == 0) parity = CR_SIO_MARK; else if (str_cmpA(argv[4], "space") == 0) parity = CR_SIO_SPCE; else sparity = "no"; if (argc > 5) { sstop = argv[5]; if (str_cmpA(argv[5], "1") == 0) stop = CR_SIO_STOP10; else if (str_cmpA(argv[5], "1.5") == 0) stop = CR_SIO_STOP15; else if (str_cmpA(argv[5], "2") == 0) stop = CR_SIO_STOP20; else sstop = "1"; } } } } sQstComm* ctx = (sQstComm*)parm; /* 关闭当前接口并打开串口 */ if (!sio_open(port)) return (FALSE); sio_setup(port, baud, bits, parity, stop); sio_set_buffer(port, 1024, 1024); sio_set_rd_timeout(port, 0, 0, QCOM_CUTDOWN); sio_set_wr_timeout(port, 0, QCOM_SNDTOUT); sio_clear_error(port); sio_flush(port, CR_SIO_FLU_RT); /* 设置工作参数 */ qst_com_close(parm, argc, argv); ctx->comm.obj.port = port; ctx->comm.send = qst_rs232_send; /* 启动接收线程 */ ctx->comm.thrd = thread_new(0, qst_rs232_main, parm, FALSE); if (ctx->comm.thrd == NULL) { sio_close(port); return (FALSE); } TRY_FREE(ctx->comm.title); ctx->comm.title = str_fmtA(" - COM%u, %u, %u, %s, %s", port, baud, bits, sparity, sstop); qst_update_title(ctx); return (TRUE); }
/* ======================================= WinMain 程序入口 ======================================= */ int WINAPI WinMain ( __CR_IN__ HINSTANCE curt_app, __CR_IN__ HINSTANCE prev_app, __CR_IN__ LPSTR cmd_line, __CR_IN__ int cmd_show ) { uint_t argc; ansi_t** argv; CR_NOUSE(prev_app); CR_NOUSE(cmd_show); /* 只允许一个例程 */ if (misc_is_running(EXE_XNAME)) return (QST_ERROR); /* 建立 CrHack 系统 */ if (!set_app_type(CR_APP_GUI)) return (QST_ERROR); mem_zero(&s_wrk_ctx, sizeof(s_wrk_ctx)); int qt_argc; /* 获取命令行参数, 不包括进程文件名 */ argv = misc_get_param(cmd_line, &argc); qt_argc = (int)argc; QApplication qt_app(qt_argc, argv); qt_app.setApplicationName("QstComm"); qt_app.setOrganizationName("QuestLAB"); sint_t x1, y1; uint_t ww, hh; /* 生成一个可变大小的窗口 */ mtlock_init(&s_wrk_ctx.lock); qst_load_cfg(&s_wrk_ctx.cfgs); misc_desk_init(WIN_ICONF, &x1, &y1, &ww, &hh, QCOM_DEF_WIDTH, QCOM_DEF_HEIGHT); if (ww < QCOM_DEF_WIDTH) ww = QCOM_DEF_WIDTH; if (hh < QCOM_DEF_HEIGHT) hh = QCOM_DEF_HEIGHT; RECT w_rect; sint_t fw, fh; QMainWindow qt_win; /* Qt 里的宽高都不包括边框 需要自己用 Win32 API 获取 */ qt_win.setWindowFlags(qt_win.windowFlags() & (~Qt::WindowMaximizeButtonHint)); qt_win.move(x1, y1); qt_win.resize(ww, hh); s_wrk_ctx.hwnd = (HWND)qt_win.winId(); if (!GetWindowRect(s_wrk_ctx.hwnd, &w_rect)) return (QST_ERROR); fw = w_rect.right - w_rect.left - ww; fh = w_rect.bottom - w_rect.top - hh; qt_win.setMinimumSize(QCOM_DEF_WIDTH - fw, QCOM_DEF_HEIGHT - fh); qt_win.resize(ww - fw, hh - fh); QWidget* cent = new QWidget (&qt_win); CTextEdit* edit = new CTextEdit (cent); QHBoxLayout* hori = new QHBoxLayout (cent); /* 创建窗体里的控件 */ hori->setSpacing(6); hori->setContentsMargins(8, 8, 8, 8); hori->addWidget(edit); qt_win.setCentralWidget(cent); CTextOper oper(&qt_win, edit); s_wrk_ctx.oper = (void_t*)(&oper); SetClassLongPtr(s_wrk_ctx.hwnd, GCLP_HICON, (LONG_PTR) LoadIconA(curt_app, (ansi_t*)101)); /* 初始化 ANSI 上下文 */ if (!qst_csi_init()) return (QST_ERROR); qst_set_viewer(&s_wrk_ctx); /* 初始化网络 */ if (!socket_init()) return (QST_ERROR); s_wrk_ctx.netw = netw_cli_open(EXE_XNAME); if (s_wrk_ctx.netw == NULL) return (QST_ERROR); /* 读取需要超时, 不然线程无法退出 */ socket_set_timeout(s_wrk_ctx.netw, -1, QST_TCP_TOUT); thrd_t thrd; /* 生成工作线程 */ s_wrk_ctx.quit = FALSE; s_wrk_ctx.comm.quit = FALSE; s_wrk_ctx.comm.text = TRUE; s_wrk_ctx.comm.rtype = "text"; s_wrk_ctx.comm.stype = "text"; s_wrk_ctx.comm.title = NULL; s_wrk_ctx.comm.render = qst_txt_show; s_wrk_ctx.page = get_sys_codepage(); qst_update_title(&s_wrk_ctx); thrd = thread_new(0, qst_com_main, &s_wrk_ctx, FALSE); if (thrd == NULL) return (QST_ERROR); sio_init(); /* 开始 Qt 流程 */ qt_win.show(); qt_app.exec(); /* 关闭线程直接退出 */ if (!s_wrk_ctx.quit) s_wrk_ctx.quit = TRUE; thread_wait(thrd); thread_del(thrd); netw_cli_close(s_wrk_ctx.netw); sio_free(); qst_csi_free(); return (QST_OKAY); }