// DriverClient.cpp - 驱动通信封装实现 #include "pch.h" #include "DriverClient.h" #include "Logger.h" namespace commkit { DriverClient::DriverClient() {} DriverClient::~DriverClient() { Close(); } bool DriverClient::Open() { if (IsOpen()) { return true; } // 打开驱动控制设备 \\.\CommModifyKit handle_ = CreateFileW( COMMKIT_USER_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (handle_ == INVALID_HANDLE_VALUE) { DWORD err = ::GetLastError(); LOG_ERROR("DriverClient::Open failed, Win32 error=" + std::to_string(err)); return false; } LOG_INFO("DriverClient opened \\\\.\\CommModifyKit"); return true; } void DriverClient::Close() { if (handle_ != INVALID_HANDLE_VALUE) { CloseHandle(handle_); handle_ = INVALID_HANDLE_VALUE; LOG_INFO("DriverClient closed"); } } bool DriverClient::SyncIoctl(DWORD ioctl_code, void* in_buf, DWORD in_size, void* out_buf, DWORD out_size, DWORD* returned) { if (!IsOpen()) { LOG_ERROR("SyncIoctl: driver not open"); return false; } DWORD bytes_returned = 0; BOOL ok = DeviceIoControl( handle_, ioctl_code, in_buf, in_size, out_buf, out_size, &bytes_returned, nullptr); if (!ok) { DWORD err = ::GetLastError(); LOG_ERROR("SyncIoctl 0x" + std::to_string(ioctl_code) + " failed, Win32 error=" + std::to_string(err)); return false; } if (returned) { *returned = bytes_returned; } return true; } bool DriverClient::RegisterCallback() { // 注册回调管道:无输入输出参数,仅通知驱动开始工作 return SyncIoctl(IOCTL_COMMKIT_REGISTER_CALLBACK, nullptr, 0, nullptr, 0, nullptr); } bool DriverClient::AttachPort(DWORD com_number) { COMMKIT_PORT_REQUEST req; req.ComNumber = com_number; return SyncIoctl(IOCTL_COMMKIT_ATTACH_PORT, &req, sizeof(req), nullptr, 0, nullptr); } bool DriverClient::DetachPort(DWORD com_number) { COMMKIT_PORT_REQUEST req; req.ComNumber = com_number; return SyncIoctl(IOCTL_COMMKIT_DETACH_PORT, &req, sizeof(req), nullptr, 0, nullptr); } bool DriverClient::WritePort(DWORD com_number, const void* data, int len) { if (len < 0 || (!data && len > 0)) { return false; } // METHOD_BUFFERED:输入缓冲为 COMMKIT_DATA_REQUEST + 数据 // 总长度 = 固定头部 + 数据长度(Data 字段为 1,已含 1 字节) DWORD total_size = sizeof(COMMKIT_DATA_REQUEST) - 1 + static_cast(len); std::vector buf(total_size); auto* req = reinterpret_cast(buf.data()); req->ComNumber = com_number; req->DataLen = static_cast(len); if (len > 0) { memcpy(req->Data, data, len); } return SyncIoctl(IOCTL_COMMKIT_WRITE_PORT, buf.data(), total_size, nullptr, 0, nullptr); } bool DriverClient::ReadPort(DWORD com_number, const void* data, int len) { if (len < 0) { return false; } // METHOD_BUFFERED:发起读请求,数据通过 OP_READ 事件回调上抛 DWORD total_size = sizeof(COMMKIT_DATA_REQUEST) - 1 + static_cast(len); std::vector buf(total_size); auto* req = reinterpret_cast(buf.data()); req->ComNumber = com_number; req->DataLen = static_cast(len); if (len > 0 && data) { memcpy(req->Data, data, len); } return SyncIoctl(IOCTL_COMMKIT_READ_PORT, buf.data(), total_size, nullptr, 0, nullptr); } int DriverClient::ReadEvents(COMMKIT_EVENT* events_out, int max_count) { if (!IsOpen() || !events_out || max_count <= 0) { return -1; } DWORD out_size = static_cast(sizeof(COMMKIT_EVENT) * max_count); DWORD returned = 0; BOOL ok = DeviceIoControl( handle_, IOCTL_COMMKIT_READ_EVENTS, nullptr, 0, events_out, out_size, &returned, nullptr); if (!ok) { DWORD err = ::GetLastError(); // ERROR_NO_DATA 等可视为"暂无事件",返回 0 if (err == ERROR_NO_DATA) { return 0; } LOG_ERROR("ReadEvents failed, Win32 error=" + std::to_string(err)); return -1; } return static_cast(returned / sizeof(COMMKIT_EVENT)); } bool DriverClient::FreeAll() { return SyncIoctl(IOCTL_COMMKIT_FREE_ALL, nullptr, 0, nullptr, 0, nullptr); } } // namespace commkit