C++写控制台HID收发程序

C++写控制台HID收发程序:
1循环查找厂商号:2E3C 产品号:5745的设备,超时3秒,超时或没找到就退出
2找到就连接
3发送Hex指令:5AA5000200A1000801FFFFFF0000DF45
4接收有超时3秒,如果收到hex:5AA5000200A10001AAC1DD0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000就退出返回0
5发送与接收可以写成一个函数
6有详细的提示

#include "./hidapi-win/include/hidapi.h" //#include 是以当前文件所在路径为当前目录
#pragma comment(lib,"./hidapi-win/x86/hidapi.lib") //#pragma comment 是以当前工程所在路径为当前目录 多线程静态MT


#include <iostream>
#include <iomanip>
#include <vector>
#include <chrono>
#include <thread>
#include <fstream>
#include <cstring>


using namespace std;

#define VID 0x2E3C
#define PID 0x5745
#define DEVICE_TYPE 0x0002

// ---------------- CRC16-CCITT ----------------
uint16_t CRC16CCITT(const uint8_t* buf, size_t len) {
    uint32_t i, j;
    uint16_t CrcReg = 0xFFFF;
    uint16_t CurVal;
    for (i = 0; i < len; i++) {
        CurVal = buf[i] << 8;
        for (j = 0; j < 8; j++) {
            if ((short)(CrcReg ^ CurVal) < 0)
                CrcReg = (CrcReg << 1) ^ 0x1021;
            else
                CrcReg <<= 1;
            CurVal <<= 1;
        }
    }
    return CrcReg;
}

// ---------------- 工具函数 ----------------
void print_hex(const string& prefix, const vector<uint8_t>& data) {
    cout << prefix;
    for (auto b : data)
        cout << hex << setw(2) << setfill('0') << (int)b << " ";
    cout << dec << endl;
}

// 封装发送
bool sendPacket(hid_device* dev, uint16_t cmd, const vector<uint8_t>& data) {
    vector<uint8_t> pkt;
    // header
    pkt.push_back(0x5A);
    pkt.push_back(0xA5);
    // device type
    pkt.push_back((DEVICE_TYPE >> 8) & 0xFF);
    pkt.push_back(DEVICE_TYPE & 0xFF);
    // cmd
    pkt.push_back((cmd >> 8) & 0xFF);
    pkt.push_back(cmd & 0xFF);
    // length
    uint16_t len = data.size();
    pkt.push_back((len >> 8) & 0xFF);
    pkt.push_back(len & 0xFF);
    // data
    pkt.insert(pkt.end(), data.begin(), data.end());
    // crc
    uint16_t crc = CRC16CCITT(pkt.data() + 2, pkt.size() - 2);
    pkt.push_back((crc >> 8) & 0xFF);
    pkt.push_back(crc & 0xFF);

    print_hex("待发送: ", pkt);

    // 拆分发送,每帧 64 字节数据
    size_t offset = 0;
    while (offset < pkt.size()) {
        size_t chunkSize = min((size_t)64, pkt.size() - offset);
        vector<uint8_t> buf(65, 0); // report ID + 64字节
        memcpy(buf.data() + 1, pkt.data() + offset, chunkSize);

        int res = hid_write(dev, buf.data(), buf.size());
        if (res < 0) {
            cerr << "发送失败: " << hid_error(dev) << endl;
            return false;
        }

        cout << "发送帧: " << (offset / 64) + 1 << " (" << res << "字节)" << endl;
        offset += chunkSize;
    }

    return true;
}


// 接收
bool recvPacket(hid_device* dev, vector<uint8_t>& out, int timeout_ms) {
    vector<uint8_t> buf(65);
    int res = hid_read_timeout(dev, buf.data(), buf.size(), timeout_ms);
    if (res <= 0) {
        cerr << "接收超时/错误" << endl;
        return false;
    }
    out.assign(buf.begin(), buf.begin() + res);
    print_hex("接收: ", out);
    return true;
}

// ---------------- 协议功能 ----------------
string getVersion(hid_device* dev) {
    sendPacket(dev, 0x0000, {});
    vector<uint8_t> resp;
    if (!recvPacket(dev, resp, 3000)) return "";
    // 简单解析:去掉头尾,提取ASCII
    uint16_t len = (resp[6] << 8) | resp[7];
    string ver(resp.begin() + 8, resp.begin() + 8+len);
    cout << "版本信息: " << ver << endl;
    return ver;
}

bool rebootDevice(hid_device* dev) {
    sendPacket(dev, 0x0005, {});
    vector<uint8_t> resp;
    if (!recvPacket(dev, resp, 3000)) return false;
    return resp[8] == 0xAA;
}

bool setColor(hid_device* dev, uint8_t r, uint8_t g, uint8_t b, uint8_t mode, uint8_t period) {
    vector<uint8_t> data = { 0x01, r, g, b, mode, period };
    sendPacket(dev, 0x00A1, data);
    vector<uint8_t> resp;
    if (!recvPacket(dev, resp, 3000)) return false;
    return resp[8] == 0xAA;
}

bool saveColor(hid_device* dev) {
    sendPacket(dev, 0x00A2, {});
    vector<uint8_t> resp;
    if (!recvPacket(dev, resp, 3000)) return false;
    return resp[8] == 0xAA;
}

bool setBrightness(hid_device* dev, uint8_t val) {
    vector<uint8_t> data = { val };
    sendPacket(dev, 0x00A3, data);
    vector<uint8_t> resp;
    if (!recvPacket(dev, resp, 3000)) return false;
    return resp[8] == 0xAA;
}

bool upgradeFirmware(hid_device* dev, const string& filepath) {
    ifstream fin(filepath, ios::binary);
    if (!fin) {
        cerr << "无法打开固件文件: " << filepath << endl;
        return false;
    }
    vector<uint8_t> fw((istreambuf_iterator<char>(fin)), {});
    size_t packet_size = 1024; // 可调,每包需4字节对齐
    uint16_t total = (fw.size() + packet_size - 1) / packet_size;
    cout << "固件大小=" << fw.size() << " 总包数=" << total << endl;

    for (uint16_t i = 0; i < total; i++) {
        size_t off = i * packet_size;
        vector<uint8_t> chunk(fw.begin() + off, fw.begin() + min(off + packet_size, fw.size()));
        while (chunk.size() % 4) chunk.push_back(0xFF);
        vector<uint8_t> data;
        data.push_back((total >> 8) & 0xFF);
        data.push_back(total & 0xFF);
        data.push_back((i >> 8) & 0xFF);
        data.push_back(i & 0xFF);
        data.push_back(0x01); // 固定类型
        data.insert(data.end(), chunk.begin(), chunk.end());

        cout << "发送升级包 " << i + 1 << "/" << total << endl;
        sendPacket(dev, 0x0003, data);
        vector<uint8_t> resp;
        if (!recvPacket(dev, resp, 5000)) return false;
        // 校验包号
        uint16_t ack = (resp[8] << 8) | resp[9];
        if (ack != i) {
            cerr << "升级失败: 返回包号错误" << endl;
            return false;
        }
    }
    cout << "升级传输完成" << endl;
    return true;
}

// ---------------- 主函数 ----------------
int main() {
    if (hid_init()) {
        cerr << "hidapi 初始化失败" << endl;
        return -1;
    }

    cout << "查找设备..." << endl;
    hid_device* dev = hid_open(VID, PID, nullptr);
    if (!dev) {
        cerr << "未找到设备" << endl;
        return -1;
    }

    cout << "=== 测试获取版本 ===" << endl;
    string ver = getVersion(dev);


    cout << "=== 测试升级流程 ===" << endl;
    cout << "重启设备进入Boot..." << endl;
    if (!rebootDevice(dev)) { cerr << "重启设备失败" << endl; hid_exit(); return -1; }
    hid_close(dev);

    this_thread::sleep_for(chrono::seconds(3));
    cout << "等待设备重连..." << endl;
    dev = nullptr;
    for (int i = 0; i < 10; i++) {
        dev = hid_open(VID, PID, nullptr);
        if (dev) break;
        this_thread::sleep_for(chrono::seconds(1));
    }
    if (!dev) {
        cerr << "重连失败" << endl;
        return -1;
    }

    cout << "开始升级..." << endl;
    if (!upgradeFirmware(dev, "Light_HID_(X001)_20250917_V1.00_upgrade.bin")) { cerr << "升级失败" << endl; /*hid_exit(); return -1;*/ }

loop:    
    cout << "延时10秒 等待设备进入APP..." << endl;
    hid_close(dev);
    this_thread::sleep_for(chrono::seconds(10));
    dev = hid_open(VID, PID, nullptr);
    if (dev) {
        string newver = getVersion(dev);
        if (newver.find("Boot") != string::npos) {
            cerr << "设备仍处于Boot模式: " << newver << endl;
            goto loop;
        }
        else {
            cout << "升级成功,新版本: " << newver << endl;
        }
    }

    cout << "=== 测试设置颜色 (红色常亮) ===" << endl;
    if (!setColor(dev, 255, 0, 0, 0, 0)) { cerr << "设置颜色失败" << endl; hid_exit(); return -1; }

    cout << "=== 设置亮度=80 ===" << endl;
    setBrightness(dev, 80);

    cout << "=== 保存设置 ===" << endl;
    saveColor(dev);

    hid_exit();
    cout << "=== 正常退出 ===" << endl;
    return 0;
}

在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小黄人软件

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值