我已经实现了检测USB设备的功能。它有效,现在我需要发送/读取数据。
我开始查看了许多obj-c
来源,并在Apple文档中发现了一个很好的article,它描述了如何将软件包发送到我们的USB设备:
IOReturn WriteToDevice(IOUSBDeviceInterface **dev, UInt16 deviceAddress,
UInt16 length, UInt8 writeBuffer[])
{
IOUSBDevRequest request;
request.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBVendor,
kUSBDevice);
request.bRequest = 0xa0;
request.wValue = deviceAddress;
request.wIndex = 0;
request.wLength = length;
request.pData = writeBuffer;
return (*dev)->DeviceRequest(dev, &request);
}
但是我没有找到一种使用
Swift
创建和发送数据的方法。 Swift
上的结构如下:public struct IOUSBDevRequest {
public var bmRequestType: UInt8
public var bRequest: UInt8
public var wValue: UInt16
public var wIndex: UInt16
public var wLength: UInt16
public var pData: UnsafeMutableRawPointer!
public var wLenDone: UInt32
public init()
public init(bmRequestType: UInt8, bRequest: UInt8, wValue: UInt16, wIndex: UInt16, wLength: UInt16, pData: UnsafeMutableRawPointer!, wLenDone: UInt32)
}
我不知道
pData
和zwLenDone
是什么参数。这是我需要发送的数据:
{
'direction':'in',
'recipient':'device',
'requestType': 'standard',
'request': 6,
'value': 0x300,
'index': 0,
'length': 255
}
下一个问题是:我如何接收数据。我知道答案在本文中,但我无法将其转换为Swift。
这是我可以在
Swift 3
上转换的内容。我的课检测到USB
设备,获取他的配置:class DFUDevice: NSObject {
let vendorId = 0x0483
let productId = 0xdf11
static let sharedInstance = DFUDevice()
var deviceName:String = ""
private func deviceAdded(iterator: io_iterator_t) {
var plugInInterfacePtrPtr: UnsafeMutablePointer<UnsafeMutablePointer<IOCFPlugInInterface>?>?
var deviceInterfacePtrPtr: UnsafeMutablePointer<UnsafeMutablePointer<IOUSBDeviceInterface>?>?
var configPtr:IOUSBConfigurationDescriptorPtr?
var score: Int32 = 0
while case let usbDevice = IOIteratorNext(iterator), usbDevice != 0 {
// io_name_t imports to swift as a tuple (Int8, ..., Int8) 128 ints
// although in device_types.h it's defined:
// typedef char io_name_t[128];
var deviceNameCString: [CChar] = [CChar](repeating: 0, count: 128)
let deviceNameResult = IORegistryEntryGetName(usbDevice, &deviceNameCString)
if(deviceNameResult != kIOReturnSuccess) {
print("Error getting device name")
}
self.deviceName = String.init(cString: &deviceNameCString)
print("usb Device Name: \(deviceName)")
// Get plugInInterface for current USB device
let plugInInterfaceResult = IOCreatePlugInInterfaceForService(
usbDevice,
kIOUSBDeviceUserClientTypeID,
kIOCFPlugInInterfaceID,
&plugInInterfacePtrPtr,
&score)
// dereference pointer for the plug in interface
guard plugInInterfaceResult == kIOReturnSuccess,
let plugInInterface = plugInInterfacePtrPtr?.pointee?.pointee else {
print("Unable to get Plug-In Interface")
continue
}
// use plug in interface to get a device interface
let deviceInterfaceResult = withUnsafeMutablePointer(to: &deviceInterfacePtrPtr) {
$0.withMemoryRebound(to: Optional<LPVOID>.self, capacity: 1) {
plugInInterface.QueryInterface(
plugInInterfacePtrPtr,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
$0)
}
}
// dereference pointer for the device interface
guard deviceInterfaceResult == kIOReturnSuccess,
let deviceInterface = deviceInterfacePtrPtr?.pointee?.pointee else {
print("Unable to get Device Interface")
continue
}
var ret = deviceInterface.USBDeviceOpen(deviceInterfacePtrPtr)
if (ret == kIOReturnSuccess)
{
// set first configuration as active
ret = deviceInterface.GetConfigurationDescriptorPtr(deviceInterfacePtrPtr, 0, &configPtr)
if (ret != kIOReturnSuccess)
{
print("Could not set active configuration (error: %x)\n", ret);
continue
}
guard let config = configPtr?.pointee else {
continue
}
if config.bLength > 0 {
//HERE I NEED SEND DATA
} else {
print("ConfigurationDescriptor not valid")
}
print(config.bLength)
}
else if (ret == kIOReturnExclusiveAccess)
{
// this is not a problem as we can still do some things
}
else
{
print("Could not open device (error: %x)\n", ret)
continue
}
IOObjectRelease(usbDevice)
}
}
func initUsb() {
var matchedIterator:io_iterator_t = 0
var removalIterator:io_iterator_t = 0
let notifyPort:IONotificationPortRef = IONotificationPortCreate(kIOMasterPortDefault)
IONotificationPortSetDispatchQueue(notifyPort, DispatchQueue(label: "IODetector"))
let matchingDict = IOServiceMatching(kIOUSBDeviceClassName)
as NSMutableDictionary
matchingDict[kUSBVendorID] = NSNumber(value: self.vendorId)
matchingDict[kUSBProductID] = NSNumber(value: self.productId)
let matchingCallback:IOServiceMatchingCallback = { (userData, iterator) in
let this = Unmanaged<DFUDevice>
.fromOpaque(userData!).takeUnretainedValue()
this.deviceAdded(iterator: iterator)
this.connected(iterator: iterator)
}
let removalCallback: IOServiceMatchingCallback = {
(userData, iterator) in
let this = Unmanaged<DFUDevice>
.fromOpaque(userData!).takeUnretainedValue()
this.disconnected(iterator: iterator)
}
let selfPtr = Unmanaged.passUnretained(self).toOpaque()
IOServiceAddMatchingNotification(notifyPort, kIOFirstMatchNotification, matchingDict, matchingCallback, selfPtr, &matchedIterator)
IOServiceAddMatchingNotification(notifyPort, kIOTerminatedNotification, matchingDict, removalCallback, selfPtr, &removalIterator)
self.deviceAdded(iterator: matchedIterator)
self.deviceAdded(iterator: removalIterator)
RunLoop.current.run()
}
}
我这样称呼它:
let DFUDeviceDaemon = Thread(target: DFUDevice.sharedInstance, selector:#selector(DFUDevice.initUsb), object: nil)
DFUDeviceDaemon.start()
最佳答案
您引用的文章具有一个称为WriteToDevice的函数。它的参数之一是
UInt8 writeBuffer[]
您要发送的数据writeBuffer是一个C字节数组:
uint8_t msgLength = 3;
uint8_t writeBuffer[msgLength];
writeBuffer[0] = 0x41; // ASCII 'A'
writeBuffer[1] = 0x42; // ASCII 'B'
writeBuffer[2] = 0x43; // ASCII 'C'
您需要发送什么字节?这实际上取决于另一端的设备-制造商的技术数据应该告诉您。
要将C数组作为NSData传递(可能就是pData),可以使用:
NSData *data = [NSData dataWithBytes:&writeBuffer length:3];
(z)wLenDone可能就是我所说的msgLength,3。C数组不知道它们自己的长度,因此大多数函数都将长度作为单独的参数。
至于接收数据,我想这会发生在matchingCallback中:您使用迭代器接收字节,然后解析它们。
评论的答案:
我不熟悉C#,而且我也不是C++专家,但这也许会有所帮助:
var package = new UsbSetupPacket(
(byte)(UsbCtrlFlags.Direction_In |
UsbCtrlFlags.Recipient_Device |
UsbCtrlFlags.RequestType_Standard), // Index
6, // length of data, second phase
0x200, // Request
0, // RequestType
(short)length); // Value
一些观察:对C#一无所知,但是不应该将程序包键入为struct吗? RequestType为0,因此您将不会收到任何响应-这就是您想要的吗?还是要发送UsbCtrlFlags.RequestType_Standard作为第四个参数?为什么将长度作为值发送?
无论如何,您现在要做的就是将软件包发送到USB设备,然后看看会发生什么。
关于objective-c - USB设备发送/接收数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41038150/