- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
你好,我是 xCode 和 Mac OS 编程的新手,在使用 USB 和串行设备时有点迷茫。
我实际上尝试编写一个 max/msp 外部程序,列出与特定产品 ID、供应商 ID 和名称匹配的 USB 设备的串行 BSD 路径。
就我而言,我得到了这个列出串行 BSD 路径的程序:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <paths.h>
#include <termios.h>
#include <sysexits.h>
#include <sys/param.h>
#include <sys/select.h>
#include <sys/time.h>
#include <time.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/serial/IOSerialKeys.h>
#include <IOKit/serial/ioss.h>
#include <IOKit/IOBSD.h>
// Function prototypes
static kern_return_t findModems(io_iterator_t *matchingServices);
static kern_return_t getModemPath(io_iterator_t serialPortIterator, char *bsdPath, CFIndex maxPathSize);
// Returns an iterator across all known modems. Caller is responsible for
// releasing the iterator when iteration is complete.
static kern_return_t findModems(io_iterator_t *matchingServices)
{
kern_return_t kernResult;
CFMutableDictionaryRef classesToMatch;
// Serial devices are instances of class IOSerialBSDClient.
// Create a matching dictionary to find those instances.
classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
if (classesToMatch == NULL) {
printf("IOServiceMatching returned a NULL dictionary.\n");
}
else {
// Look for devices that claim to be modems.
CFDictionarySetValue(classesToMatch,
CFSTR(kIOSerialBSDTypeKey),
CFSTR(kIOSerialBSDAllTypes));
}
// Get an iterator across all matching devices.
kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, matchingServices);
if (KERN_SUCCESS != kernResult) {
printf("IOServiceGetMatchingServices returned %d\n", kernResult);
goto exit;
}
exit:
return kernResult;
}
static kern_return_t getModemPath(io_iterator_t serialPortIterator, char *bsdPath, CFIndex maxPathSize)
{
io_object_t modemService;
kern_return_t kernResult = KERN_FAILURE;
Boolean modemFound = false;
// Initialize the returned path
*bsdPath = '\0';
// Iterate across all modems found. In this example, we bail after finding the first modem.
while ((modemService = IOIteratorNext(serialPortIterator))) {
CFTypeRef bsdPathAsCFString;
bsdPathAsCFString = IORegistryEntryCreateCFProperty(modemService,
CFSTR(kIOCalloutDeviceKey),
kCFAllocatorDefault,
0);
if (bsdPathAsCFString) {
Boolean result;
result = CFStringGetCString(bsdPathAsCFString,
bsdPath,
maxPathSize,
kCFStringEncodingUTF8);
CFRelease(bsdPathAsCFString);
if (result) {
printf("Modem found with BSD path: %s", bsdPath);
modemFound = true;
kernResult = KERN_SUCCESS;
}
}
printf("\n");
// Release the io_service_t now that we are done with it.
(void) IOObjectRelease(modemService);
}
return kernResult;
}
int main(int argc, const char * argv[])
{
kern_return_t kernResult;
io_iterator_t serialPortIterator;
char bsdPath[MAXPATHLEN];
kernResult = findModems(&serialPortIterator);
if (KERN_SUCCESS != kernResult) {
printf("No modems were found.\n");
}
kernResult = getModemPath(serialPortIterator, bsdPath, sizeof(bsdPath));
if (KERN_SUCCESS != kernResult) {
printf("Could not get path for modem.\n");
}
IOObjectRelease(serialPortIterator);
return EX_OK;
}
以及搜索具有特定 ID 的 USB 的其他代码:
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOMessage.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/usb/IOUSBLib.h>
// Change these two constants to match your device's idVendor and idProduct.
// Or, just pass your idVendor and idProduct as command line arguments when running this sample.
#define kMyVendorID 0x04D8
#define kMyProductID 0x000A
typedef struct MyPrivateData {
io_object_t notification;
IOUSBDeviceInterface **deviceInterface;
CFStringRef deviceName;
unsigned int locationID;
} MyPrivateData;
static IONotificationPortRef gNotifyPort;
static io_iterator_t gAddedIter;
static CFRunLoopRef gRunLoop;
//================================================================================================
//
// DeviceNotification
//
// This routine will get called whenever any kIOGeneralInterest notification happens. We are
// interested in the kIOMessageServiceIsTerminated message so that's what we look for. Other
// messages are defined in IOMessage.h.
//
//================================================================================================
void DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument)
{
kern_return_t kr;
MyPrivateData *privateDataRef = (MyPrivateData *) refCon;
if (messageType == kIOMessageServiceIsTerminated) {
fprintf(stderr, "Device removed.\n");
// Dump our private data to stderr just to see what it looks like.
fprintf(stderr, "privateDataRef->deviceName: ");
CFShow(privateDataRef->deviceName);
fprintf(stderr, "privateDataRef->locationID: 0x%x.\n\n", privateDataRef->locationID);
// Free the data we're no longer using now that the device is going away
CFRelease(privateDataRef->deviceName);
if (privateDataRef->deviceInterface) {
kr = (*privateDataRef->deviceInterface)->Release(privateDataRef->deviceInterface);
}
kr = IOObjectRelease(privateDataRef->notification);
free(privateDataRef);
}
}
//================================================================================================
//
// DeviceAdded
//
// This routine is the callback for our IOServiceAddMatchingNotification. When we get called
// we will look at all the devices that were added and we will:
//
// 1. Create some private data to relate to each device (in this case we use the service's name
// and the location ID of the device
// 2. Submit an IOServiceAddInterestNotification of type kIOGeneralInterest for this device,
// using the refCon field to store a pointer to our private data. When we get called with
// this interest notification, we can grab the refCon and access our private data.
//
//================================================================================================
void DeviceAdded(void *refCon, io_iterator_t iterator)
{
kern_return_t kr;
io_service_t usbDevice;
IOCFPlugInInterface **plugInInterface = NULL;
SInt32 score;
HRESULT res;
while ((usbDevice = IOIteratorNext(iterator))) {
io_name_t deviceName;
CFStringRef deviceNameAsCFString;
MyPrivateData *privateDataRef = NULL;
unsigned int locationID;
printf("Device added.\n");
// Add some app-specific information about this device.
// Create a buffer to hold the data.
privateDataRef = malloc(sizeof(MyPrivateData));
bzero(privateDataRef, sizeof(MyPrivateData));
// Get the USB device's name.
kr = IORegistryEntryGetName(usbDevice, deviceName);
if (KERN_SUCCESS != kr) {
deviceName[0] = '\0';
}
deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, deviceName,
kCFStringEncodingASCII);
// Dump our data to stderr just to see what it looks like.
fprintf(stderr, "deviceName: ");
CFShow(deviceNameAsCFString);
// Save the device's name to our private data.
privateDataRef->deviceName = deviceNameAsCFString;
// Now, get the locationID of this device. In order to do this, we need to create an IOUSBDeviceInterface
// for our device. This will create the necessary connections between our userland application and the
// kernel object for the USB Device.
kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
&plugInInterface, &score);
if ((kIOReturnSuccess != kr) || !plugInInterface) {
fprintf(stderr, "IOCreatePlugInInterfaceForService returned 0x%08x.\n", kr);
continue;
}
// Use the plugin interface to retrieve the device interface.
res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
(LPVOID*) &privateDataRef->deviceInterface);
// Now done with the plugin interface.
(*plugInInterface)->Release(plugInInterface);
if (res || privateDataRef->deviceInterface == NULL) {
fprintf(stderr, "QueryInterface returned %d.\n", (int) res);
continue;
}
// Now that we have the IOUSBDeviceInterface, we can call the routines in IOUSBLib.h.
// In this case, fetch the locationID. The locationID uniquely identifies the device
// and will remain the same, even across reboots, so long as the bus topology doesn't change.
kr = (*privateDataRef->deviceInterface)->GetLocationID(privateDataRef->deviceInterface, &locationID);
if (KERN_SUCCESS != kr) {
fprintf(stderr, "GetLocationID returned 0x%08x.\n", kr);
continue;
}
else {
fprintf(stderr, "Location ID: 0x%x\n\n", locationID);
}
privateDataRef->locationID = locationID;
// Register for an interest notification of this device being removed. Use a reference to our
// private data as the refCon which will be passed to the notification callback.
kr = IOServiceAddInterestNotification(gNotifyPort, // notifyPort
usbDevice, // service
kIOGeneralInterest, // interestType
DeviceNotification, // callback
privateDataRef, // refCon
&(privateDataRef->notification) // notification
);
if (KERN_SUCCESS != kr) {
printf("IOServiceAddInterestNotification returned 0x%08x.\n", kr);
}
// Done with this USB device; release the reference added by IOIteratorNext
kr = IOObjectRelease(usbDevice);
}
}
//================================================================================================
//
// SignalHandler
//
// This routine will get called when we interrupt the program (usually with a Ctrl-C from the
// command line).
//
//================================================================================================
void SignalHandler(int sigraised)
{
fprintf(stderr, "\nInterrupted.\n");
exit(0);
}
//================================================================================================
// main
//================================================================================================
int main(int argc, const char *argv[])
{
CFMutableDictionaryRef matchingDict;
CFRunLoopSourceRef runLoopSource;
CFNumberRef numberRef;
kern_return_t kr;
long usbVendor = kMyVendorID;
long usbProduct = kMyProductID;
sig_t oldHandler;
// Set up a signal handler so we can clean up when we're interrupted from the command line
// Otherwise we stay in our run loop forever.
oldHandler = signal(SIGINT, SignalHandler);
if (oldHandler == SIG_ERR) {
fprintf(stderr, "Could not establish new signal handler.");
}
fprintf(stderr, "Looking for devices matching vendor ID=%ld and product ID=%ld.\n", usbVendor, usbProduct);
// Set up the matching criteria for the devices we're interested in. The matching criteria needs to follow
// the same rules as kernel drivers: mainly it needs to follow the USB Common Class Specification, pp. 6-7.
// See also Technical Q&A QA1076 "Tips on USB driver matching on Mac OS X"
// <http://developer.apple.com/qa/qa2001/qa1076.html>.
// One exception is that you can use the matching dictionary "as is", i.e. without adding any matching
// criteria to it and it will match every IOUSBDevice in the system. IOServiceAddMatchingNotification will
// consume this dictionary reference, so there is no need to release it later on.
matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class
// IOUSBDevice and its subclasses
if (matchingDict == NULL) {
fprintf(stderr, "IOServiceMatching returned NULL.\n");
return -1;
}
// We are interested in all USB devices (as opposed to USB interfaces). The Common Class Specification
// tells us that we need to specify the idVendor, idProduct, and bcdDevice fields, or, if we're not interested
// in particular bcdDevices, just the idVendor and idProduct. Note that if we were trying to match an
// IOUSBInterface, we would need to set more values in the matching dictionary (e.g. idVendor, idProduct,
// bInterfaceNumber and bConfigurationValue.
// Create a CFNumber for the idVendor and set the value in the dictionary
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor);
CFDictionarySetValue(matchingDict,
CFSTR(kUSBVendorID),
numberRef);
CFRelease(numberRef);
// Create a CFNumber for the idProduct and set the value in the dictionary
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct);
CFDictionarySetValue(matchingDict,
CFSTR(kUSBProductID),
numberRef);
CFRelease(numberRef);
numberRef = NULL;
// Create a notification port and add its run loop event source to our run loop
// This is how async notifications get set up.
gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault);
runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort);
gRunLoop = CFRunLoopGetCurrent();
CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode);
// Now set up a notification to be called when a device is first matched by I/O Kit.
kr = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort
kIOFirstMatchNotification, // notificationType
matchingDict, // matching
DeviceAdded, // callback
NULL, // refCon
&gAddedIter // notification
);
// Iterate once to get already-present devices and arm the notification
DeviceAdded(NULL, gAddedIter);
// Start the run loop. Now we'll receive notifications.
fprintf(stderr, "Starting run loop.\n\n");
CFRunLoopRun();
// We should never get here
fprintf(stderr, "Unexpectedly back from CFRunLoopRun()!\n");
return 0;
}
但我没有成功合并两者。任何帮助将不胜感激。
最佳答案
好的,通过进一步搜索,我发现了 IORegistryExplorer,您可以从 Apple Developper 网站将其作为硬件 IO 工具的一部分下载。据我所知,第一个代码隔离了 IOSerialBSDClient 节点,它是第二个代码找到的 USB 设备的子节点。所以我需要找到一个解决方案来访问我的 USB 设备的子属性,或者我的 BSD 节点的父属性。
这就是我最终在这两个库的开源中找到的:libserialport & libusb .
在 MacOS 上,以下代码可以解决问题:
// Variable declaration
int pid, vid;
CFTypeRef cf_vendor, cf_product;
// Search properties among parents of the current modemService
cf_vendor = IORegistryEntrySearchCFProperty(modemService, kIOServicePlane,
CFSTR("idVendor"),
kCFAllocatorDefault,
kIORegistryIterateRecursively
| kIORegistryIterateParents);
cf_product = IORegistryEntrySearchCFProperty(modemService, kIOServicePlane,
CFSTR("idProduct"),
kCFAllocatorDefault,
kIORegistryIterateRecursively
| kIORegistryIterateParents);
// Decode & print VID & PID
if (cf_vendor && cf_product &&
CFNumberGetValue(cf_vendor , kCFNumberIntType, &vid) &&
CFNumberGetValue(cf_product, kCFNumberIntType, &pid)) {
printf("\nFound matching USB VID: %04X PID: %04X", vid, pid);
}
// Release CFTypeRef
if (cf_vendor) CFRelease(cf_vendor);
if (cf_product) CFRelease(cf_product);
希望它能对 future 的人有所帮助。
关于c - 列出具有特定 ID 的串行 USB 设备,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34464672/
这是代码片段。 请说出这种用小内存存储大数据的算法是什么。 public static void main(String[] args) { long longValue = 21474836
所以我使用 imap 从 gmail 和 outlook 接收电子邮件。 Gmail 像这样编码 =?UTF-8?B?UmU6IM69zq3OvyDOtc68zrHOuc67IG5ldyBlbWFpb
很久以前就学会了 C 代码;想用 Scheme 尝试一些新的和不同的东西。我正在尝试制作一个接受两个参数并返回两者中较大者的过程,例如 (define (larger x y) (if (> x
Azure 恢复服务保管库有两个备份配置选项 - LRS 与 GRS 这是一个有关 Azure 恢复服务保管库的问题。 当其驻留区域发生故障时,如何处理启用异地冗余的恢复服务保管库?如果未为恢复服务启
说,我有以下实体: @Entity public class A { @Id @GeneratedValue private Long id; @Embedded private
我有下一个问题。 我有下一个标准: criteria.add(Restrictions.in("entity.otherEntity", getOtherEntitiesList())); 如果我的
如果这是任何类型的重复,我会提前申请,但我找不到任何可以解决我的具体问题的内容。 这是我的程序: import java.util.Random; public class CarnivalGame{
我目前正在使用golang创建一个聚合管道,在其中使用“$ or”运算符查询文档。 结果是一堆需要分组的未分组文档,这样我就可以进入下一阶段,找到两个数据集之间的交集。 然后将其用于在单独的集合中进行
是否可以在正则表达式中创建 OR 条件。 我正在尝试查找包含此类模式的文件名列表的匹配项 第一个案例 xxxxx-hello.file 或者案例二 xxxx-hello-unasigned.file
该程序只是在用户输入行数时创建菱形的形状,因此它有 6 个 for 循环; 3 个循环创建第一个三角形,3 个循环创建另一个三角形,通过这 2 个三角形和 6 个循环,我们得到了一个菱形,这是整个程序
我有一个像这样的查询字符串 www.google.com?Department=Education & Finance&Department=Health 我有这些 li 标签,它们的查询字符串是这样
我有一个带有静态构造函数的类,我用它来读取 app.config 值。如何使用不同的配置值对类进行单元测试。我正在考虑在不同的应用程序域中运行每个测试,这样我就可以为每个测试执行静态构造函数 - 但我
我正在寻找一个可以容纳多个键的容器,如果我为其中一个键值输入保留值(例如 0),它会被视为“或”搜索。 map, int > myContainer; myContainer.insert(make_
我正在为 Web 应用程序创建数据库,并正在寻找一些建议来对可能具有多种类型的单个实体进行建模,每种类型具有不同的属性。 作为示例,假设我想为“数据源”对象创建一个关系模型。所有数据源都会有一些共享属
(1) =>CREATE TABLE T1(id BIGSERIAL PRIMARY KEY, name TEXT); CREATE TABLE (2) =>INSERT INTO T1 (name)
我不确定在使用别名时如何解决不明确的列引用。 假设有两个表,a 和 b,它们都有一个 name 列。如果我加入这两个表并为结果添加别名,我不知道如何为这两个表引用 name 列。我已经尝试了一些变体,
我的查询是: select * from table where id IN (1,5,4,3,2) 我想要的与这个顺序完全相同,不是从1...5,而是从1,5,4,3,2。我怎样才能做到这一点? 最
我正在使用 C# 代码执行动态生成的 MySQL 查询。抛出异常: CREATE TABLE dump ("@employee_OID" VARCHAR(50)); "{"You have an er
我有日期 2016-03-30T23:59:59.000000+0000。我可以知道它的格式是什么吗?因为如果我使用 yyyy-MM-dd'T'HH:mm:ss.SSS,它会抛出异常 最佳答案 Sim
我有一个示例模式,它的 SQL Fiddle 如下: http://sqlfiddle.com/#!2/6816b/2 这个 fiddle 只是根据 where 子句中的条件查询示例数据库,如下所示:
我是一名优秀的程序员,十分优秀!