8

如何使用 jssc 获取 SerialPort 的设备描述符( java-simple-serial-connector)

getPortName()方法提供端口名称 ( e.g. COM2),但描述符会更有帮助。

如果需要修补此开源 API 以获取设备描述符,该怎么做?

4

3 回答 3

1

查看gohai/java-simple-serial-connectorSerialPortList类有一个getPortProperties(String portName)方法来获取端口属性,遗憾的是尚未在 windows 上实现,但很容易实现并重新编译以使其工作.

我希望这有帮助。

于 2016-04-06T15:32:31.533 回答
1

在 zamanillo 的帮助下,我现在可以自己回答这个问题。jssc 2.8.0 无法做到这一点。

正在采取一些措施来扩展 jssc,但我不知道发布时间表,也不知道如何解决这个问题。扩展是方法 SerialPortList->getPortProperties(String portName) 实现在 jssc 2.8.0 for linux 和 mac 的修改版本中可用。Windows 实现更难(找到)。

这是取自https://github.com/gohai/java-simple-serial-connector/blob/processing/src/cpp/_nix_based/jssc.cpp的 linux 和 mac 代码

JNIEXPORT jobjectArray JNICALL Java_jssc_SerialNativeInterface_getPortProperties
  (JNIEnv *env, jclass cls, jstring portName) {
    const char* portNameChar = (const char*)env->GetStringUTFChars(portName, NULL);
    jclass stringClass = env->FindClass("Ljava/lang/String;");
    jobjectArray ret = env->NewObjectArray(5, stringClass, NULL);

#ifdef __APPLE__

    // this code is based on QtSerialPort
    CFMutableDictionaryRef matching = IOServiceMatching(kIOSerialBSDServiceValue);
    io_iterator_t iter = 0;
    kern_return_t kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iter);
    if (kr != kIOReturnSuccess) {
        env->ReleaseStringUTFChars(portName, portNameChar);
        return ret;
    }

    io_registry_entry_t service;
    while ((service = IOIteratorNext(iter))) {

        // compare portName against cu and tty devices
        bool found = false;

        CFTypeRef cu = 0;
        cu = IORegistryEntrySearchCFProperty(service, kIOServicePlane, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
        if (cu) {
            char buffer[MAXPATHLEN];
            CFStringGetCString(CFStringRef(cu), buffer, sizeof(buffer), kCFStringEncodingUTF8);
            //fprintf(stdout, "getPortProperties: %s\n", buffer);
            //fflush(stdout);
            if (strcmp(portNameChar, buffer) == 0) {
                found = true;
            }
            CFRelease(cu);
        }

        CFTypeRef tty = 0;
        tty = IORegistryEntrySearchCFProperty(service, kIOServicePlane, CFSTR(kIODialinDeviceKey), kCFAllocatorDefault, 0);
        if (tty) {
            char buffer[MAXPATHLEN];
            CFStringGetCString(CFStringRef(tty), buffer, sizeof(buffer), kCFStringEncodingUTF8);
            //fprintf(stdout, "getPortProperties: %s\n", buffer);
            //fflush(stdout);
            if (strcmp(portNameChar, buffer) == 0) {
                found = true;
            }
            CFRelease(tty);
        }

        if (!found) {
            // not port we're looking for
            //fprintf(stderr, "getPortProperties: %s not found", portNameChar);
            //fflush(stderr);
            IOObjectRelease(service);
            continue;
        }

        io_registry_entry_t entry = service;
        do {
            int val = 0;
            char buffer[255];

            CFTypeRef idProduct = 0;
            idProduct = IORegistryEntrySearchCFProperty(entry, kIOServicePlane, CFSTR(kUSBProductID), kCFAllocatorDefault, 0);
            if (idProduct && !env->GetObjectArrayElement(ret, 0)) {
                CFNumberGetValue(CFNumberRef(idProduct), kCFNumberIntType, &val);
                sprintf(buffer, "%04x", val);
                jstring tmp = env->NewStringUTF(buffer);
                env->SetObjectArrayElement(ret, 0, tmp);
                env->DeleteLocalRef(tmp);
                CFRelease(idProduct);
            }

            CFTypeRef idVendor = 0;
            idVendor = IORegistryEntrySearchCFProperty(entry, kIOServicePlane, CFSTR(kUSBVendorID), kCFAllocatorDefault, 0);
            if (idVendor && !env->GetObjectArrayElement(ret, 1)) {
                CFNumberGetValue(CFNumberRef(idVendor), kCFNumberIntType, &val);
                sprintf(buffer, "%04x", val);
                jstring tmp = env->NewStringUTF(buffer);
                env->SetObjectArrayElement(ret, 1, tmp);
                env->DeleteLocalRef(tmp);
                CFRelease(idVendor);
            }

            CFTypeRef manufacturer = 0;
            manufacturer = IORegistryEntrySearchCFProperty(entry, kIOServicePlane, CFSTR(kUSBVendorString), kCFAllocatorDefault, 0);
            if (manufacturer && !env->GetObjectArrayElement(ret, 2)) {
                CFStringGetCString(CFStringRef(manufacturer), buffer, sizeof(buffer), kCFStringEncodingUTF8);
                jstring tmp = env->NewStringUTF(buffer);
                env->SetObjectArrayElement(ret, 2, tmp);
                env->DeleteLocalRef(tmp);
                CFRelease(manufacturer);
            }

            CFTypeRef product = 0;
            product = IORegistryEntrySearchCFProperty(entry, kIOServicePlane, CFSTR(kUSBProductString), kCFAllocatorDefault, 0);
            if (product && !env->GetObjectArrayElement(ret, 3)) {
                CFStringGetCString(CFStringRef(product), buffer, sizeof(buffer), kCFStringEncodingUTF8);
                jstring tmp = env->NewStringUTF(buffer);
                env->SetObjectArrayElement(ret, 3, tmp);
                env->DeleteLocalRef(tmp);
                CFRelease(product);
            }

            CFTypeRef serial = 0;
            serial = IORegistryEntrySearchCFProperty(entry, kIOServicePlane, CFSTR(kUSBSerialNumberString), kCFAllocatorDefault, 0);
            if (serial && !env->GetObjectArrayElement(ret, 4)) {
                CFStringGetCString(CFStringRef(serial), buffer, sizeof(buffer), kCFStringEncodingUTF8);
                jstring tmp = env->NewStringUTF(buffer);
                env->SetObjectArrayElement(ret, 4, tmp);
                env->DeleteLocalRef(tmp);
                CFRelease(serial);
            }

            kr = IORegistryEntryGetParentEntry(entry, kIOServicePlane, &entry);
        } while (kr == kIOReturnSuccess);

        IOObjectRelease(entry);

        IOObjectRelease(service);
    }

    IOObjectRelease(iter);

#endif  // __APPLE__

    env->ReleaseStringUTFChars(portName, portNameChar);
    return ret;
}

对于 Windows,我只在使用自定义 dll 的处理中找到了解决方案。

于 2016-04-06T15:47:14.900 回答
-1

设备描述符是描述符树的根,包含基本的设备信息。唯一编号 idVendor 和 idProduct 标识连接的设备。Windows 操作系统使用这些数字来确定要加载的设备驱动程序。

idVendor是分配给每家生产基于 USB 的设备的公司的编号。USB 实施者论坛负责管理供应商 ID 的分配。

idProduct是另一个 16 位字段,包含制造商分配的用于标识特定产品的编号。


从jantje的问题来看,

我需要的是 Windows 10 在连接的设备中显示的名称?

答:打开"Settings app"并点击设备。单击设备将打开一个选项卡,您可以在其中调整所有打印机、连接设备、蓝牙设备、鼠标和触摸板、打字设置和自动播放设置的设置。此连接的设备选项卡显示连接到您的 PC 的硬件。单击添加设备,您的 PC 将自动扫描连接的设备。蓝牙选项卡很简单,只需简单的设置即可通过蓝牙将设备连接到您的 PC。单击蓝牙按钮,设备将自动开始扫描范围内的任何蓝牙设备。

如果显示设备或赠品不可用有任何问题,那么我们需要以下工作。

  1. 扫描硬件和设备以找出驱动程序问题。
  2. 修复损坏、损坏或不兼容的蓝牙驱动程序。
  3. 更新到适用于 Windows 10 的最新蓝牙驱动程序。
  4. 在 Windows 10 中下载并安装最匹配的驱动程序。

顶部 2. 删除和添加蓝牙设备

顶部 3. 允许蓝牙设备连接到这台计算机

无法从您的蓝牙设备连接到计算机?确保您已允许蓝牙设备连接到您的计算机。请尝试以下步骤: 1. 进入控制面板。单击“硬件和声音”和“蓝牙设备”。2. 单击选项选项卡。3. 确保选中“允许蓝牙设备连接到这台计算机”复选框。


如何将蓝牙设备连接到您的 Windows 10 计算机?

连接蓝牙手机:

  1. 转到开始按钮,然后选择“设置”、“设备”和“蓝牙”。点击“添加”。
  2. 或者,转到控制面板,单击“硬件和声音”和“蓝牙设备”。点击“添加”。

资源链接:

  1. 在 Windows 10 更新问题后修复蓝牙不可用的前 3 种方法
  2. http://windows.microsoft.com/en-gb/windows-10/getstarted-connect-to-bluetooth-devices

修复网络连接问题

有 7 种方法可以解决网络连接问题:

  1. 更新网络适配器驱动程序
  2. 回滚网络适配器驱动程序
  3. 运行网络疑难解答,然后运行网络命令
  4. 暂时关闭防火墙
  5. 暂时关闭任何防病毒或恶意软件预防软件
  6. 卸载网络适配器驱动程序并重新启动
  7. 使用 netcfg –d 命令重新安装网络设备

更新:

您的答案如何链接到 jssc?

我正在检查你的问题。我知道在 Windows 7 中它工作正常,在 Windows 10 中,有一些与硬件相关的问题会导致问题。

开发人员正在研究这个领域。但它还没有修复。问题#63问题#85将澄清你。

/**
 * Get serial port names in Windows
 *
 * @since 2.3.0
 */
private static String[] getWindowsPortNames(Pattern pattern, Comparator<String> comparator) {
    String[] portNames = serialInterface.getSerialPortNames();
    if(portNames == null){
        return new String[]{};
    }
    TreeSet<String> ports = new TreeSet<String>(comparator);
    for(String portName : portNames){
        if(pattern.matcher(portName).find()){
            ports.add(portName);
        }
    }
    return ports.toArray(new String[ports.size()]);
}

我明白了,他们正在为各种操作系统使用一些模式。

OS_LINUX: Pattern.compile("(ttyS|ttyUSB|ttyACM|ttyAMA|rfcomm|ttyO)[0-9]{1,3}"); 

OS_SOLARIS: Pattern.compile("[0-9]*|[a-z]*");

OS_MAC_OS_X: Pattern.compile("tty.(serial|usbserial|usbmodem).*"); 

OS_WINDOWS: Pattern.compile("");

建议: 仅使用官方和最新的驱动程序。

jSSC-2.8.0 发布版 (24.01.2014)

修复:重要!修复了端口处理潜在泄漏的错误。

此版本包含适用于 Windows(x86, x86-64), Linux(x86, x86-64, ARM soft & hard float), Solaris(x86, x86-64), Mac OS X(x86, x86-64, PPC) 的原生库, PPC64)。所有本机库都包含在 jssc.jar 文件中,您不需要手动管理本机库。

资源链接:

  1. https://github.com/tcr/node-jssc/blob/master/jSSC-2.6.0-Release/src/src/jssc/SerialPortList.java
于 2016-04-05T18:51:21.493 回答