无法快速发送字节到 USB HID 设备,总是得到错误的报告大小

问题描述 投票:0回答:1

我正在将旧的 C 程序移植到 macOS 上的 Swift。我的问题是向 USB HID 设备发送固定的 7 字节报告。在 C 中,这工作正常,但我无法使其在 Swift 中工作。我注意到,在 C 中,数据包的大小是正确的,7,在 swift 中总是多 1 个字节。

这里是原始的C代码:

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

这有效并更改字节的值,使设备反应良好。

在 Swift 中我尝试了不同的解决方案,但我无法使其工作,大小始终是 8 个字节。

其中之一是:

var report = [UInt8](repeating: 0, count: 7)
report = [0x81, 0x61, 0xf5, 0x33, 0x04, 0x00, 0x28] // the bytes are there if a print the report
let mySize = MemoryLayout.size(ofValue: report) // this return always 8 and not 7
result = myHIDDevInt!.setReport(hidDevInterface, kIOHIDReportTypeOutput, zero, &report, mySize, athousand, nil, nil, nil) // even in this case the return is 0, so no error
but it is not working.

我也尝试过获取一个指针并将其传递给设备调用的 setReport 函数,但没有成功:

MemoryLayout<UInt8>.alignment)
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)
....
mySize =  UInt32(MemoryLayout.size(ofValue: ptr)) // even this reports 8 and not 7.
result = myHIDDevInt!.setReport(hidDevInterface, kIOHIDReportTypeOutput, zero, &report, mySize, athousand, nil, nil, nil)

即使在这种情况下,对设备的调用也不会报告错误。

我也尝试在设备调用中写入 7,但没有成功。

我想像 C 中那样发送 7 的大小。我认为它会很快改变报告的内容,更好的字节顺序。

我也注意到,与 swift 相比,下面这样的二元运算在 C 中给出了不同的结果:

int arg; // size id 4 bytes
unsigned char theByte2; // size is 1 byte
arg = 1813;
theByte2 = (arg >> 8) & 0xff; // this return 0x61

在 Swift 中

var UInt8: theByte2 = 0 // size 1 byte
var arg: Int = 0 // size 4 bytes
arg = 1813
theByte2 = UInt8(((arg >> 8) & 0xff)) // this report 0x07

我在这里做错了什么?有没有办法在 swift 中发送 7 个字节而不是 8 个字节?

c swift macos type-conversion
1个回答
0
投票

您错误地计算了缓冲区的大小。

  • MemoryLayout.size(ofValue: report)
    正在计算Array结构体实例的大小,它只是包装了一个指针,而不是指向的缓冲区。无论指向的缓冲区大小如何,在 64 位机器上它始终是 64 位。
  • MemoryLayout.size(ofValue: ptr)
    正在计算指针本身的大小。同样,它也将始终是 64 位。

您可以使用类似

report * MemoryLayout<UInt8>.stride
的内容,但没有必要,因为
Array
上有更好的 API 可以为您计算此值。查看数组文档的“访问底层存储”部分

我不知道

IOHIDDevice.setReport
如何导入 Swift 的具体细节,但使用它应该看起来像这样:

let report: [UInt8] = [0x81, 0x61, 0xf5, 0x33, 0x04, 0x00, 0x28]

report.withUnsafeBytes { buffer in
    myHIDDevInt!.setReport(
        hidDevInterface,
        kIOHIDReportTypeOutput,
        zero,
        buffer.baseAddress,
        buffer.count,
        athousand, nil, nil, nil
    )
}
© www.soinside.com 2019 - 2024. All rights reserved.