You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

macOS下Swift向USB HID设备发送7字节报告异常求助

macOS下Swift移植USB HID报告发送问题解决

问题概述

将旧C程序移植到Swift时,向USB HID设备发送7字节固定报告的功能始终失效。C代码可正常工作,但Swift中出现两个核心问题:

  • 错误计算报告长度,始终得到8字节而非7字节
  • 位运算结果与C不一致

正常工作的C代码

int size;
char report[7] = {0x81, 0x61, 0xf5, 0x33, 0x04, 0x00, 0x28};
size = sizeof(report); // 返回7
result = (*myhidInterface)->setReport(myhidInterface, kIOHIDReportTypeOutput, 0, report, sizeof(report), 1000, NULL, NULL, NULL); // IOReturn返回0

Swift尝试的方案及问题

方案一:使用数组存储报告

var report = [UInt8](repeating: 0, count: 7)
report = [0x81, 0x61, 0xf5, 0x33, 0x04, 0x00, 0x28] // 字节内容正确
let mySize = MemoryLayout.size(ofValue: report) // 返回8(错误:这是Swift数组对象的内存大小,不是元素总字节数)
result = myHIDDevInt!.setReport(hidDevInterface, kIOHIDReportTypeOutput, 0, &report, mySize, 1000, nil, nil, nil) // 无报错但功能失效

方案二:使用指针操作

// 指针初始化代码(片段)
let ptr = UnsafeMutablePointer<UInt8>.allocate(capacity: 7)
ptr.initializeMemory(as: UInt8.self, repeating: 0, count: 7)

// 填充字节代码(片段)
ptr.storeBytes(of: 0x81, as: UInt8.self)
var offsetPointer = ptr + 1
offsetPointer.storeBytes(of: 0x61, as: UInt8.self)
offsetPointer = ptr + 2
offsetPointer.storeBytes(of: 0xf5, as: UInt8.self)
// ... 其余字节填充

let mySize = UInt32(MemoryLayout.size(ofValue: ptr)) // 返回8(错误:这是指针本身的内存大小,不是指向的缓冲区大小)
result = myHIDDevInt!.setReport(hidDevInterface, kIOHIDReportTypeOutput, 0, ptr, mySize, 1000, nil, nil, nil) // 无报错但功能失效

位运算差异问题

C代码(结果符合预期)

int arg; // 32位整数
unsigned char theByte2; // 1字节
arg = 1813; // 注:此处arg值存在笔误,实际应传入24853(0x6115)才能得到0x61
theByte2 = (arg >> 8) & 0xff; // 返回0x61

Swift代码(结果错误)

var theByte2: UInt8 = 0
var arg: Int = 0 // macOS默认64位整数
arg = 1813
theByte2 = UInt8(((arg >> 8) & 0xff)) // 返回0x07

解决方案

1. 修正报告长度计算

无论使用数组还是指针,都需要直接指定实际的报告字节数(7),而非计算对象/指针的内存大小:

  • 数组方式:用report.count直接获取元素个数(每个UInt8占1字节),转换为UInt32传入setReport
  • 指针方式:直接传入UInt32(7)作为长度

修正后的数组方案代码:

var report: [UInt8] = [0x81, 0x61, 0xf5, 0x33, 0x04, 0x00, 0x28]
let mySize = UInt32(report.count) // 正确得到7
result = myHIDDevInt!.setReport(hidDevInterface, kIOHIDReportTypeOutput, 0, &report, mySize, 1000, nil, nil, nil)

2. 统一位运算的整数类型

将Swift中的arg类型改为Int32,匹配C中int的32位宽度,确保移位运算逻辑一致:

var theByte2: UInt8 = 0
var arg: Int32 = 24853 // 对应0x6115,与C逻辑匹配
theByte2 = UInt8(((arg >> 8) & 0xff)) // 返回0x61

内容的提问来源于stack exchange,提问作者Karterilla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 04:47:03