/* * Cleans up resources and set exception that will get thrown upon return to java layer. */ static jstring clean_throw_exp_usbenumeration(JNIEnv *env, int task, int subtask, DWORD error_code, const char *expmsg, struct jstrarray_list *list, struct hiddev_instance_list *hiddevinst_list, HDEVINFO *usb_dev_info_set, HDEVINFO *hid_dev_info_set) { (*env)->ExceptionClear(env); if (task == 1) { SetupDiDestroyDeviceInfoList(*hid_dev_info_set); free_hiddev_instance_list(hiddevinst_list); }else if (task == 2) { free_hiddev_instance_list(hiddevinst_list); }else if (task == 3) { free_jstrarraylist(list); free_hiddev_instance_list(hiddevinst_list); SetupDiDestroyDeviceInfoList(*usb_dev_info_set); } if (subtask == 1) { throw_serialcom_exception(env, 3, 0, expmsg); }else if (subtask == 2) { throw_serialcom_exception(env, 4, error_code, NULL); }else { } return NULL; }
/* * Find the address and IRQ number associated with the given handle of serial port. */ jstring find_address_irq_for_given_com_port(JNIEnv *env, jlong fd) { char serial_info[256]; jstring addressIRQInfo = NULL; int ret = 0; struct serial_struct port_info; memset(serial_info, '\0', 256); port_info.reserved_char[0] = 0; errno = 0; ret = ioctl(fd, TIOCGSERIAL, &port_info); if(ret < 0) { throw_serialcom_exception(env, 1, errno, NULL); return NULL; } snprintf(serial_info, 256, "Port: 0x%.4x, IRQ: %d", port_info.port, port_info.irq); addressIRQInfo = (*env)->NewStringUTF(env, serial_info); if((addressIRQInfo == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR); return NULL; } return addressIRQInfo; }
/* * Set the latency timer value for ftdi devices to fine tune performance. */ jint set_latency_timer_value(JNIEnv *env, jstring comPortName, jbyte timerValue) { const char *com_port_to_match = NULL; com_port_to_match = (*env)->GetStringUTFChars(env, comPortName, NULL); if ((com_port_to_match == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { throw_serialcom_exception(env, 3, 0, E_GETSTRUTFCHARSTR); return -1; } (*env)->ReleaseStringUTFChars(env, comPortName, com_port_to_match); /* reaching here means given com port does not represent ftdi device, throw exception */ throw_serialcom_exception(env, 3, 0, E_NOTFTDIPORT); return -1; }
/* * Class: com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge * Method: readEEPROM * Signature: (I)I * * @return eeprom value read on success or -1 if an error occurs. * @throws SerialComException if any JNI function, Win API call or C function fails. */ JNIEXPORT jint JNICALL Java_com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge_readEEPROM(JNIEnv *env, jobject obj, jint uiEEPAddress) { int value = 0; value = scm_ReadEEPROM(uiEEPAddress); if (value < 0) { if (value == -3) { throw_serialcom_exception(env, 3, 0, "E_WRONG_ADDRESS"); }else if (value == -4) { throw_serialcom_exception(env, 3, 0, "E_CANNOT_SEND_DATA"); }else { throw_serialcom_exception(env, 3, 0, "ReadEEPROM() failed to read eeprom value !"); } return -1; } return (jint)value; }
/* * Class: com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge * Method: writeEEPROM * Signature: (IS)I * * @return 0 on success or -1 if an error occurs. * @throws SerialComException if any JNI function, Win API call or C function fails. */ JNIEXPORT jint JNICALL Java_com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge_writeEEPROM(JNIEnv *env, jobject obj, jint uiEEPAddress, jshort ucValue) { int ret = 0; ret = scm_WriteEEPROM(uiEEPAddress, (unsigned char)ucValue); if (ret < 0) { if (ret == -3) { throw_serialcom_exception(env, 3, 0, "E_WRONG_ADDRESS"); }else if (ret == -4) { throw_serialcom_exception(env, 3, 0, "E_CANNOT_SEND_DATA"); }else { throw_serialcom_exception(env, 3, 0, "WriteEEPROM() failed to write eeprom value !"); } return -1; } return 0; }
/* * Class: com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge * Method: selectDevice * Signature: (I)I * * @return 0 on success or -1 if an error occurs. * @throws SerialComException if any JNI function, Win API call or C function fails. */ JNIEXPORT jint JNICALL Java_com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge_selectDevice(JNIEnv *env, jobject obj, jint uiDeviceNumber) { int ret = 0; ret = scm_SelectDevice(uiDeviceNumber); if (ret = 0) { if (ret == -1) { throw_serialcom_exception(env, 3, 0, "E_WRONG_DEVICE_ID"); }else if (ret == -2) { throw_serialcom_exception(env, 3, 0, "E_INACTIVE_DEVICE"); }else { throw_serialcom_exception(env, 3, 0, "SelectDevice() failed !"); } return -1; } return 0; }
/* * Class: com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge * Method: clearPin * Signature: (I)I * * @return 0 on success or -1 if an error occurs. * @throws SerialComException if any JNI function, Win API call or C function fails. */ JNIEXPORT jint JNICALL Java_com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge_clearPin(JNIEnv *env, jobject obj, jint pinNumber) { BOOL ret = FALSE; ret = scm_ClearPin(pinNumber); if (ret = FALSE) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } return 0; }
/* * Class: com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge * Method: readPinValue * Signature: (I)I * * @return pin value read on success or -1 if an error occurs. * @throws SerialComException if any JNI function, Win API call or C function fails. */ JNIEXPORT jint JNICALL Java_com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge_readPinValue(JNIEnv *env, jobject obj, jint pinNumber) { int ret = 0; ret = scm_ReadPinValue(pinNumber); if (ret = 0x8000) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } return (jint)ret; }
/* * @return number of bytes read if function succeeds otherwise -1 if an error occurs. * @throws SerialComException if any JNI function, system call or C function fails. */ jint mac_get_feature_report(JNIEnv *env, jlong fd, jbyte reportID, jbyteArray report, jint length) { IOReturn ret = -1; int num_bytes_to_read = 0; int report_id = -1; jbyte* buffer = NULL; if(reportID < 0) { buffer = (jbyte *) calloc(length, sizeof(unsigned char)); if(buffer == NULL) { throw_serialcom_exception(env, 3, 0, E_CALLOCSTR); return -1; } (*env)->GetByteArrayRegion(env, report, 0, length, &buffer[0]); num_bytes_to_read = length; report_id = 0x00; }else { buffer = (jbyte *) calloc((length + 1), sizeof(unsigned char)); if(buffer == NULL) { throw_serialcom_exception(env, 3, 0, E_CALLOCSTR); return -1; } buffer[0] = reportID; (*env)->GetByteArrayRegion(env, report, 0, length, &buffer[1]); num_bytes_to_read = length + 1; report_id = reportID; } if((*env)->ExceptionOccurred(env) != NULL) { throw_serialcom_exception(env, 3, 0, E_GETBYTEARRREGIONSTR); return -1; } /* after completion num_bytes_to_read will contain number of bytes read. */ ret = IOHIDDeviceGetReport(fd, kIOHIDReportTypeFeature, report_id, buffer, &num_bytes_to_read); if(ret != kIOReturnSuccess) { /* to error throw_serialcom_exception(env, 1, errno, NULL);*/ return -1; } return num_bytes_to_read; }
/* * @return number of bytes read if function succeeds otherwise -1 if an error occurs. * @throws SerialComException if any JNI function, system call or C function fails. */ jint linux_get_feature_report(JNIEnv *env, jlong fd, jbyte reportID, jbyteArray report, jint length) { int ret = -1; jbyte* buffer = NULL;; /* allocate and clear buffer */ buffer = (jbyte *) calloc((length), sizeof(unsigned char)); if(buffer == NULL) { throw_serialcom_exception(env, 3, 0, E_CALLOCSTR); return -1; } if(reportID < 0) { /* set 0x00 as 1st byte if device does not support report ID */ buffer[0] = 0x00; }else { /* The first byte of SFEATURE and GFEATURE is the report number */ buffer[0] = reportID; } errno = 0; /* this ioctl returns number of bytes read from the device */ ret = ioctl(fd, HIDIOCGFEATURE(length), buffer); if(ret < 0) { free(buffer); throw_serialcom_exception(env, 1, errno, NULL); return -1; } /* copy data from native buffer to Java buffer */ (*env)->SetByteArrayRegion(env, report, 0, ret, buffer); if((*env)->ExceptionOccurred(env)) { free(buffer); throw_serialcom_exception(env, 3, 0, E_SETBYTEARRREGIONSTR); return -1; } free(buffer); return ret; }
/* * Class: com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge * Method: writePort * Signature: (I)I * * @return 0 on success or -1 if an error occurs. * @throws SerialComException if any JNI function, Win API call or C function fails. */ JNIEXPORT jint JNICALL Java_com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge_writePort(JNIEnv *env, jobject obj, jint portValue) { BOOL ret = FALSE; ret = scm_WritePort(portValue); if (ret = FALSE) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } return 0; }
/* * Class: com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge * Method: configureIoDefaultOutput * Signature: (SS)I * * 1 - GPIO configured as input * 0 - GPIO configured as output * MSB - - - - - - LSB * GP7 GP6 GP5 GP4 GP3 GP2 GP1 GP0 * * @return 0 on success or -1 if an error occurs. * @throws SerialComException if any JNI function, Win API call or C function fails. */ JNIEXPORT jint JNICALL Java_com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge_configureIoDefaultOutput(JNIEnv *env, jobject obj, jshort ioMap, jshort ucDefValue) { BOOL ret = FALSE; ret = scm_ConfigureIoDefaultOutput((unsigned char)ioMap, (unsigned char)ucDefValue); if (ret == FALSE) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } return 0; }
/* * Class: com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge * Method: fnSetBaudRate * Signature: (J)I * * @return 0 on success or -1 if an error occurs. * @throws SerialComException if any JNI function, Win API call or C function fails. */ JNIEXPORT jint JNICALL Java_com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge_fnSetBaudRate(JNIEnv *env, jobject obj, jlong baudRateParam) { BOOL ret = FALSE; ret = scm_fnSetBaudRate((unsigned long)baudRateParam); if (ret == FALSE) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } return 0; }
/* * Class: com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge * Method: readPortValue * Signature: ()I * * @return port value read on success or -1 if an error occurs. * @throws SerialComException if any JNI function, Win API call or C function fails. */ JNIEXPORT jint JNICALL Java_com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge_readPortValue(JNIEnv *env, jobject obj) { int value = 0; value = scm_ReadPortValue(); if (value = 0x8000) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } return (jint)value; }
/* * Class: com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge * Method: fnInvertUartPol * Signature: (I)I * * @return 0 on success or -1 if an error occurs. * @throws SerialComException if any JNI function, Win API call or C function fails. */ JNIEXPORT jint JNICALL Java_com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge_fnInvertUartPol(JNIEnv *env, jobject obj, jint onOff) { BOOL ret = FALSE; ret = scm_fnInvertUartPol(onOff); if (ret == FALSE) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } return 0; }
/* * Class: com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge * Method: readPort * Signature: ()I * * @return port value read on success or -1 if an error occurs. * @throws SerialComException if any JNI function, Win API call or C function fails. */ JNIEXPORT jint JNICALL Java_com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge_readPort(JNIEnv *env, jobject obj) { BOOL ret = FALSE; unsigned int value = 0; ret = scm_ReadPort(&value); if (ret = FALSE) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } return (jint)value; }
/* * Class: com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge * Method: getSelectedDeviceInfo * Signature: ()Ljava/lang/String; * * @return string returned by SelectedDeviceInfo() on success or NULL if an error occurs. * @throws SerialComException if any JNI function, Win API call or C function fails. */ JNIEXPORT jstring JNICALL Java_com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge_getSelectedDeviceInfo(JNIEnv *env, jobject obj) { char buffer[256]; jstring info = NULL; memset(buffer, '\0', 256); scm_GetSelectedDeviceInfo(buffer); info = (*env)->NewStringUTF(env, buffer); if ((info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR); return NULL; } return info; }
/* * Class: com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge * Method: configureMCP2200 * Signature: (BJIIZZZZ)I * * @return 0 on success or -1 if an error occurs. * @throws SerialComException if any JNI function, Win API call or C function fails. */ JNIEXPORT jint JNICALL Java_com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge_configureMCP2200(JNIEnv *env, jobject obj, jbyte ioMap, jlong baudRateParam, jint rxLEDMode, jint txLEDMode, jboolean flow, jboolean uload, jboolean sspnd, jboolean invert) { BOOL ret = FALSE; BOOL flowval = FALSE; BOOL uloadval = FALSE; BOOL sspndval = FALSE; BOOL invertval = FALSE; if (flow == JNI_TRUE) { flowval = TRUE; }else { flowval = FALSE; } if (uload == JNI_TRUE) { uloadval = TRUE; }else { uloadval = FALSE; } if (sspnd == JNI_TRUE) { sspndval = TRUE; }else { sspndval = FALSE; } if (invert == JNI_TRUE) { invertval = TRUE; }else { invertval = FALSE; } ret = scm_ConfigureMCP2200(ioMap, (unsigned long)baudRateParam, rxLEDMode, txLEDMode, flowval, uloadval, sspndval, invertval); if (ret = FALSE) { throw_serialcom_exception(env, 3, 0, "ConfigureMCP2200() returned FALSE !"); return -1; } return 0; }
/* * Find the name of the driver which is currently associated with the given HID device. * * A HID device can be on usb, bluetooth or pseudo. For Linux we walk down the * sysfs tree until a driver is found for the given device node. */ jstring linux_find_driver_for_given_hiddevice(JNIEnv *env, jstring hidDevNode) { const char* hid_name_to_match = NULL; jstring driver_name = NULL; int check_for_parent = -1; struct udev *udev_ctx; struct udev_enumerate *enumerator; struct udev_list_entry *devices, *dev_list_entry; const char *prop_val_driver_name; const char *device_node; const char *path; struct udev_device *udev_device; struct udev_device *parent_device; hid_name_to_match = (*env)->GetStringUTFChars(env, hidDevNode, NULL); if((hid_name_to_match == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { throw_serialcom_exception(env, 3, 0, E_GETSTRUTFCHARSTR); return NULL; } udev_ctx = udev_new(); enumerator = udev_enumerate_new(udev_ctx); udev_enumerate_add_match_subsystem(enumerator, "hidraw"); udev_enumerate_scan_devices(enumerator); devices = udev_enumerate_get_list_entry(enumerator); udev_list_entry_foreach(dev_list_entry, devices) { /* from the sysfs filename create a udev_device object representing it. */ path = udev_list_entry_get_name(dev_list_entry); udev_device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerator), path); if(udev_device == NULL) { continue; } /* get the device node for this udev device. */ device_node = udev_device_get_devnode(udev_device); /* If the device node name matches what we are looking for get driver for it. * if we fail to get driver name than return empty string (prop_val_driver_name * will be NULL when control reaches at the end of this function). */ if(device_node != NULL) { if(strcmp(hid_name_to_match, device_node) == 0) { prop_val_driver_name = udev_device_get_driver(udev_device); if(prop_val_driver_name != NULL) { driver_name = (*env)->NewStringUTF(env, prop_val_driver_name); if((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); udev_device_unref(udev_device); udev_enumerate_unref(enumerator); udev_unref(udev_ctx); (*env)->ReleaseStringUTFChars(env, hidDevNode, hid_name_to_match); throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR); return NULL; } check_for_parent = -1; }else { check_for_parent = 1; } if(check_for_parent == 1) { parent_device = udev_device_get_parent(udev_device); if(parent_device != NULL) { prop_val_driver_name = udev_device_get_driver(parent_device); if(prop_val_driver_name != NULL) { driver_name = (*env)->NewStringUTF(env, prop_val_driver_name); if((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); udev_device_unref(udev_device); udev_enumerate_unref(enumerator); udev_unref(udev_ctx); (*env)->ReleaseStringUTFChars(env, hidDevNode, hid_name_to_match); throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR); return NULL; }else { /* if both the parent and driver found, return driver name to caller. */ check_for_parent = -1; } }else { /* if the parent is found but driver not found then analyze next parent device. */ check_for_parent = 1; } }else { /* if the parent does not exist, make no more attempts to analyze parent devices further down the tree. */ check_for_parent = -1; } } if(check_for_parent == 1) { parent_device = udev_device_get_parent(parent_device ); if(parent_device != NULL) { prop_val_driver_name = udev_device_get_driver(parent_device); if(prop_val_driver_name != NULL) { driver_name = (*env)->NewStringUTF(env, prop_val_driver_name); if((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); udev_device_unref(udev_device); udev_enumerate_unref(enumerator); udev_unref(udev_ctx); (*env)->ReleaseStringUTFChars(env, hidDevNode, hid_name_to_match); throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR); return NULL; }else { check_for_parent = -1; } }else { check_for_parent = 1; } }else { check_for_parent = -1; } } if(check_for_parent == 1) { parent_device = udev_device_get_parent(parent_device); if(parent_device != NULL) { prop_val_driver_name = udev_device_get_driver(parent_device); if(prop_val_driver_name != NULL) { driver_name = (*env)->NewStringUTF(env, prop_val_driver_name); if((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); udev_device_unref(udev_device); udev_enumerate_unref(enumerator); udev_unref(udev_ctx); (*env)->ReleaseStringUTFChars(env, hidDevNode, hid_name_to_match); throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR); return NULL; }else { check_for_parent = -1; } }else { check_for_parent = 1; } }else { check_for_parent = -1; } } if(check_for_parent == 1) { parent_device = udev_device_get_parent(udev_device); if(parent_device != NULL) { prop_val_driver_name = udev_device_get_driver(parent_device ); if(prop_val_driver_name != NULL) { driver_name = (*env)->NewStringUTF(env, prop_val_driver_name); if((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); udev_device_unref(udev_device); udev_enumerate_unref(enumerator); udev_unref(udev_ctx); (*env)->ReleaseStringUTFChars(env, hidDevNode, hid_name_to_match); throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR); return NULL; }else { check_for_parent = -1; } }else { check_for_parent = 1; } }else { check_for_parent = -1; } } if(check_for_parent == 1) { parent_device = udev_device_get_parent(parent_device); if(parent_device != NULL) { prop_val_driver_name = udev_device_get_driver(parent_device); if(prop_val_driver_name != NULL) { driver_name = (*env)->NewStringUTF(env, prop_val_driver_name); if((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); udev_device_unref(udev_device); udev_enumerate_unref(enumerator); udev_unref(udev_ctx); (*env)->ReleaseStringUTFChars(env, hidDevNode, hid_name_to_match); throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR); return NULL; } } } } /* whether prop_val_driver_name is NULL (return empty string) or not * (return driver name found), no more iteration is needed. */ udev_device_unref(udev_device); break; } } /* released only after desired property value has been saved to some * other memory region like one got from NewStringUTF(). */ udev_device_unref(udev_device); }
/* * Class: com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge * Method: loadAndLinkSimpleIODLL * Signature: (Ljava/lang/String;)I * * @return 0 on success or -1 if an error occurs. * @throws SerialComException if any JNI function, Win API call or C function fails. */ JNIEXPORT jint JNICALL Java_com_embeddedunveiled_serial_internal_SerialComMCHPSIOJNIBridge_loadAndLinkSimpleIODLL (JNIEnv *env, jobject obj, jstring vendorLibraryWithAbsolutePath) { const jchar* vlib = NULL; FARPROC function_address = 0; throw_serialcom_exception(env, 4, 193, NULL); return -1; vlib = (*env)->GetStringChars(env, vendorLibraryWithAbsolutePath, JNI_FALSE); if ((vlib == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { throw_serialcom_exception(env, 3, 0, E_GETSTRUTFCHARSTR); return -1; } /* load vendor supplied shared library */ DLL_handle = LoadLibrary(vlib); if (DLL_handle == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } /* resolve references to all the exported functions */ scm_InitMCP2200 = (void(__stdcall *)(unsigned int, unsigned int)) GetProcAddress(DLL_handle, "InitMCP2200"); if (scm_InitMCP2200 == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_IsConnected = (BOOL(__stdcall *)(void)) GetProcAddress(DLL_handle, "IsConnected"); if (scm_IsConnected == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_ConfigureMCP2200 = (BOOL(__stdcall *)(unsigned char, unsigned long, unsigned int, unsigned int, BOOL, BOOL, BOOL, BOOL)) GetProcAddress(DLL_handle, "ConfigureMCP2200"); if (scm_ConfigureMCP2200 == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_SetPin = (BOOL(__stdcall *)(unsigned int)) GetProcAddress(DLL_handle, "SetPin"); if (scm_SetPin == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_ClearPin = (BOOL(__stdcall *)(unsigned int)) GetProcAddress(DLL_handle, "ClearPin"); if (scm_ClearPin == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_ReadPinValue = (int(__stdcall *)(unsigned int)) GetProcAddress(DLL_handle, "ReadPinValue"); if (scm_ReadPinValue == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_ReadPin = (BOOL(__stdcall *)(unsigned int, unsigned int *)) GetProcAddress(DLL_handle, "ReadPin"); if (scm_ReadPin == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_WritePort = (BOOL(__stdcall *)(unsigned int)) GetProcAddress(DLL_handle, "WritePort"); if (scm_WritePort == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_ReadPort = (BOOL(__stdcall *)(unsigned int *)) GetProcAddress(DLL_handle, "ReadPort"); if (scm_ReadPort == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_ReadPortValue = (int(__stdcall *)(void)) GetProcAddress(DLL_handle, "ReadPortValue"); if (scm_ReadPortValue == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_SelectDevice = (int(__stdcall *)(unsigned int)) GetProcAddress(DLL_handle, "SelectDevice"); if (scm_SelectDevice == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_GetSelectedDevice = (int(__stdcall *)(void)) GetProcAddress(DLL_handle, "GetSelectedDevice"); if (scm_GetSelectedDevice == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_GetNoOfDevices = (unsigned int(__stdcall *)(void)) GetProcAddress(DLL_handle, "GetNoOfDevices"); if (scm_GetNoOfDevices == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_GetDeviceInfo = (BOOL(__stdcall *)(unsigned int, LPSTR)) GetProcAddress(DLL_handle, "GetDeviceInfo"); if (scm_GetDeviceInfo == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_GetSelectedDeviceInfo = (int(__stdcall *)(LPSTR)) GetProcAddress(DLL_handle, "GetSelectedDeviceInfo"); if (scm_GetSelectedDeviceInfo == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_ReadEEPROM = (int(__stdcall *)(unsigned int)) GetProcAddress(DLL_handle, "ReadEEPROM"); if (scm_ReadEEPROM == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_WriteEEPROM = (int(__stdcall *)(unsigned int, unsigned char)) GetProcAddress(DLL_handle, "WriteEEPROM"); if (scm_WriteEEPROM == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_fnRxLED = (BOOL(__stdcall *)(unsigned int)) GetProcAddress(DLL_handle, "fnRxLED"); if (scm_fnRxLED == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_fnTxLED = (BOOL(__stdcall *)(unsigned int)) GetProcAddress(DLL_handle, "fnTxLED"); if (scm_fnTxLED == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_fnHardwareFlowControl = (BOOL(__stdcall *)(unsigned int)) GetProcAddress(DLL_handle, "fnHardwareFlowControl"); if (scm_fnHardwareFlowControl == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_fnULoad = (BOOL(__stdcall *)(unsigned int)) GetProcAddress(DLL_handle, "fnULoad"); if (scm_fnULoad == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_fnSuspend = (BOOL(__stdcall *)(unsigned int)) GetProcAddress(DLL_handle, "fnSuspend"); if (scm_fnSuspend == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_fnInvertUartPol = (BOOL(__stdcall *)(unsigned int)) GetProcAddress(DLL_handle, "fnInvertUartPol"); if (scm_fnInvertUartPol == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_fnSetBaudRate = (BOOL(__stdcall *)(unsigned long)) GetProcAddress(DLL_handle, "fnSetBaudRate"); if (scm_fnSetBaudRate == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_ConfigureIO = (BOOL(__stdcall *)(unsigned char)) GetProcAddress(DLL_handle, "ConfigureIO"); if (scm_ConfigureIO == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } scm_ConfigureIoDefaultOutput = (BOOL(__stdcall *)(unsigned char, unsigned char)) GetProcAddress(DLL_handle, "ConfigureIoDefaultOutput"); if (scm_ConfigureIoDefaultOutput == NULL) { throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } return 0; }
/* * Last pass to find driver name. Iterate over all the devices associated with "Ports" class. * One by one get their device ID and check if this device has COM port we are searching. * If matched get the driver name and return to caller. Note that not all devices might have * "PortName" registry associated with them, so ignore them. * * Return 1 if found, 0 if not found, -1 if an error occurs (also throws exception in this case). */ int get_driver_com_port_others(JNIEnv *env, const jchar *port_name, TCHAR *driver_name) { int x = 0; BOOL ret = FALSE; CONFIGRET cmret = 0; LONG status = 0; DWORD error_code = 0; DWORD charbuffer_size = 0; DWORD com_member_index = 0; HDEVINFO com_dev_info_set; SP_DEVINFO_DATA com_dev_instance; /* size of these buffers is hardcoded in functions using them */ TCHAR buffer[1024]; TCHAR keybuf[1024]; TCHAR charbuffer[128]; char cmerror[256]; /* get information set for all multi port serial adaptor devices matching the GUID */ com_dev_info_set = SetupDiGetClassDevs(&GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, NULL, NULL, DIGCF_ALLCLASSES); if (com_dev_info_set == INVALID_HANDLE_VALUE) { SetupDiDestroyDeviceInfoList(com_dev_info_set); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL); return -1; } /* enumerate all devices in this information set */ com_member_index = 0; while (1) { ZeroMemory(&com_dev_instance, sizeof(com_dev_instance)); com_dev_instance.cbSize = sizeof(com_dev_instance); /* from information set, get device by index */ ret = SetupDiEnumDeviceInfo(com_dev_info_set, com_member_index, &com_dev_instance); if (ret == FALSE) { error_code = GetLastError(); if (error_code == ERROR_NO_MORE_ITEMS) { break; }else { SetupDiDestroyDeviceInfoList(com_dev_info_set); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(error_code), NULL); return -1; } } cmret = CM_Get_Device_ID(com_dev_instance.DevInst, buffer, 1024, 0); if (cmret != CR_SUCCESS) { SetupDiDestroyDeviceInfoList(com_dev_info_set); _snprintf_s(cmerror, 256, 256, "CM_Get_Device_ID CR_xxxx error code : 0x%X\0", cmret); throw_serialcom_exception(env, 3, 0, cmerror); return -1; } /* get its COM port name/number for this device */ memset(keybuf, '\0', 1024); _stprintf_s(keybuf, 1024, TEXT("SYSTEM\\CurrentControlSet\\Enum\\%s\\Device Parameters"), buffer); charbuffer_size = sizeof(charbuffer); memset(charbuffer, '\0', 128); /* ignore error as some devices might not have portname registry key */ status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("PortName"), RRF_RT_REG_SZ, NULL, (PVOID)charbuffer, &charbuffer_size); if (status == ERROR_SUCCESS) { /* match port name */ ret = _tcsicmp(charbuffer, port_name); if (ret == 0) { /* get driver name */ memset(keybuf, '\0', 1024); _stprintf_s(keybuf, 1024, TEXT("SYSTEM\\CurrentControlSet\\Enum\\%s"), buffer); /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\XXXX\XXX\XXX\Service */ charbuffer_size = sizeof(charbuffer); memset(charbuffer, '\0', 128); status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("Service"), RRF_RT_REG_SZ, NULL, (PVOID)charbuffer, &charbuffer_size); if (status != ERROR_SUCCESS) { SetupDiDestroyDeviceInfoList(com_dev_info_set); throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } /* populate array to be returned to caller */ memset(driver_name, '\0', 128); for (x = 0; x < _tcslen(charbuffer); x++) { driver_name[x] = charbuffer[x]; } /* clean up and return 1 to indicate driver found */ SetupDiDestroyDeviceInfoList(com_dev_info_set); return 1; } } /* increment to get and examine the next device instance */ com_member_index++; } /* reaching here means given COM port's driver not found */ SetupDiDestroyDeviceInfoList(com_dev_info_set); return 0; }
/* * Find the name of the driver which is currently associated with the given serial port. * * Typically, a driver service is a type of kernel-level filter driver implemented as a Windows service that * enables applications to work with devices. Windows copies the .sys file to the %SystemRoot%\system32\drivers * directory. * * The GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR is not used for USB devices due to 2 reasons : * (1) Some devices may not have 'upper-level device filter driver (for ex. serenum)' that is used in conjunction with * Serial (or a vendor-supplied function driver) to provide the functionality of a Plug and Play bus driver for an * RS-232 port. * (2) For composite devices CDC/ACM interface specific function driver is to be found. * * Return driver name string if driver found, empty string if not found, NULL if an error occur. */ jstring find_driver_for_given_com_port(JNIEnv *env, jstring comPortName) { int x = 0; const jchar* port_name = NULL; jstring driverfound = NULL; TCHAR driver_name[128]; /* extract com port name to match (as an array of Unicode characters) */ port_name = (*env)->GetStringChars(env, comPortName, JNI_FALSE); if ((port_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { throw_serialcom_exception(env, 3, 0, E_GETSTRUTFCHARSTR); return NULL; } /* first pass : loop over USB-UART device enteries */ x = get_driver_com_port_usb(env, port_name, driver_name); if (x == 1) { driverfound = (*env)->NewString(env, driver_name, (jsize) _tcslen(driver_name)); if ((driverfound == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR); return NULL; } return driverfound; }else if (x < 0) { return NULL; }else { } /* reaching here means given COM port does not belong to USB device. second pass : loop over multiport serial adaptor device enteries */ x = get_driver_com_port_multiportadaptor(env, port_name, driver_name); if (x == 1) { driverfound = (*env)->NewString(env, driver_name, (jsize) _tcslen(driver_name)); if ((driverfound == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR); return NULL; } return driverfound; }else if (x < 0) { return NULL; }else { } /* reaching here means given COM port does not belong to USB device. last pass : loop over other device entires */ x = get_driver_com_port_others(env, port_name, driver_name); if (x == 1) { driverfound = (*env)->NewString(env, driver_name, (jsize) _tcslen(driver_name)); if ((driverfound == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR); return NULL; } return driverfound; }else if (x < 0) { return NULL; }else { } /* reaching here means that the no driver was found for given COM port name. return empty string */ driverfound = (*env)->NewStringUTF(env, ""); if ((driverfound == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR); return NULL; } return driverfound; }
/* * The sequence of entries in array must match with what java layer expect (6 informations * per USB device). If a particular USB attribute is not set in descriptor or can not be * obtained "---" is placed in its place. * * Returns array of USB device's information found, empty array if no USB device is found, * NULL if an error occurs (additionally throws exception). */ jobjectArray list_usb_devices(JNIEnv *env, jint vendor_to_match) { int x = 0; int i = 0; int vid = 0; BOOL ret = FALSE; DWORD error_code = 0; DWORD size = 0; TCHAR *ptrend; DWORD usb_member_index = 0; HDEVINFO usb_dev_info_set; SP_DEVINFO_DATA usb_dev_instance; DEVPROPTYPE proptype; DWORD regproptype; TCHAR buffer[1024]; TCHAR charbuffer[1024]; struct jstrarray_list list = { 0 }; jstring usb_dev_info; jclass strClass = NULL; jobjectArray usbDevicesFound = NULL; init_jstrarraylist(&list, 50); /* get information set for all usb devices matching the GUID */ usb_dev_info_set = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (usb_dev_info_set == INVALID_HANDLE_VALUE) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); free_jstrarraylist(&list); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL); return NULL; } /* enumerate all devices in this information set */ usb_member_index = 0; while (1) { ZeroMemory(&usb_dev_instance, sizeof(usb_dev_instance)); usb_dev_instance.cbSize = sizeof(usb_dev_instance); /* from information set, get device by index */ ret = SetupDiEnumDeviceInfo(usb_dev_info_set, usb_member_index, &usb_dev_instance); if (ret == FALSE) { error_code = GetLastError(); if (error_code == ERROR_NO_MORE_ITEMS) { break; } else { SetupDiDestroyDeviceInfoList(usb_dev_info_set); free_jstrarraylist(&list); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(error_code), NULL); return NULL; } } /* for this device find its instance ID (USB\VID_04D8&PID_00DF\000098037) * this is the variable 'Device Instance Path' in device manager. */ memset(buffer, '\0', sizeof(buffer)); ret = SetupDiGetDeviceInstanceId(usb_dev_info_set, &usb_dev_instance, buffer, sizeof(buffer), &size); if (ret == FALSE) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); free_jstrarraylist(&list); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL); return NULL; } /* USB-IF vendor ID, extract and match, if matched continue further otherwise loop back */ x = 0; while (buffer[x] != '\0') { if((buffer[x] == 'V') && (buffer[x + 1] == 'I') && (buffer[x + 2] == 'D') && (buffer[x + 3] == '_')) { break; } x++; } x = x + 4; i = 0; while (buffer[x] != '&') { charbuffer[i] = buffer[x]; i++; x++; } charbuffer[i] = '\0'; /* indicate end of string */ vid = (int)_tcstol(charbuffer, &ptrend, 16); if(vendor_to_match != 0) { /* we need to apply filter for identify specific vendor */ if(vid != vendor_to_match) { usb_member_index++; continue; } } usb_dev_info = (*env)->NewString(env, charbuffer, (jsize) _tcslen(charbuffer)); if((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); SetupDiDestroyDeviceInfoList(usb_dev_info_set); free_jstrarraylist(&list); throw_serialcom_exception(env, 3, 0, E_NEWSTRSTR); return NULL; } insert_jstrarraylist(&list, usb_dev_info); /* USB product ID */ x = 6; while (buffer[x] != '\0') { if ((buffer[x] == 'P') && (buffer[x + 1] == 'I') && (buffer[x + 2] == 'D') && (buffer[x + 3] == '_')) { break; } x++; } x = x + 4; i = 0; while (buffer[x] != '\\') { charbuffer[i] = buffer[x]; i++; x++; } charbuffer[i] = '\0'; usb_dev_info = (*env)->NewString(env, charbuffer, (jsize) _tcslen(charbuffer)); if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); SetupDiDestroyDeviceInfoList(usb_dev_info_set); free_jstrarraylist(&list); throw_serialcom_exception(env, 3, 0, E_NEWSTRSTR); return NULL; } insert_jstrarraylist(&list, usb_dev_info); /* SERIAL NUMBER */ x++; i = 0; while (buffer[x] != '\0') { charbuffer[i] = buffer[x]; i++; x++; } charbuffer[i] = '\0'; usb_dev_info = (*env)->NewString(env, charbuffer, (jsize) _tcslen(charbuffer)); if ((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); SetupDiDestroyDeviceInfoList(usb_dev_info_set); free_jstrarraylist(&list); throw_serialcom_exception(env, 3, 0, E_NEWSTRSTR); return NULL; } insert_jstrarraylist(&list, usb_dev_info); /* PRODUCT (idProduct field of USB device descriptor) */ memset(buffer, '\0', sizeof(buffer)); ret = SetupDiGetDeviceProperty(usb_dev_info_set, &usb_dev_instance, &DEVPKEY_Device_BusReportedDeviceDesc, &proptype, (BYTE *)buffer, sizeof(buffer), &size, 0); if (ret == FALSE) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); free_jstrarraylist(&list); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL); return NULL; } usb_dev_info = (*env)->NewString(env, buffer, (jsize) _tcslen(buffer)); insert_jstrarraylist(&list, usb_dev_info); /* MANUFACTURER */ memset(buffer, '\0', sizeof(buffer)); ret = SetupDiGetDeviceProperty(usb_dev_info_set, &usb_dev_instance, &DEVPKEY_Device_Manufacturer, &proptype, (BYTE *)buffer, sizeof(buffer), &size, 0); if (ret == FALSE) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); free_jstrarraylist(&list); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL); return NULL; } usb_dev_info = (*env)->NewString(env, buffer, (jsize) _tcslen(buffer)); insert_jstrarraylist(&list, usb_dev_info); /* LOCATION (Location paths + Location info, get separately and then create a single string) */ memset(buffer, '\0', sizeof(buffer)); ret = SetupDiGetDeviceRegistryProperty(usb_dev_info_set, &usb_dev_instance, SPDRP_LOCATION_PATHS, ®proptype, (BYTE *)buffer, sizeof(buffer), &size); if (ret == FALSE) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); free_jstrarraylist(&list); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL); return NULL; } memset(charbuffer, '\0', sizeof(charbuffer)); ret = SetupDiGetDeviceRegistryProperty(usb_dev_info_set, &usb_dev_instance, SPDRP_LOCATION_INFORMATION, ®proptype, (BYTE *)charbuffer, sizeof(charbuffer), &size); if (ret == FALSE) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); free_jstrarraylist(&list); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL); return NULL; } i = 0; x = (int)_tcslen(buffer); buffer[x] = '-'; x++; for (i = 0; i < (int)_tcslen(charbuffer); i++) { buffer[x] = charbuffer[i]; x++; } buffer[x] = '\0'; usb_dev_info = (*env)->NewString(env, buffer, (jsize)_tcslen(buffer)); insert_jstrarraylist(&list, usb_dev_info); /* loop to get next USB device */ usb_member_index++; } SetupDiDestroyDeviceInfoList(usb_dev_info_set); strClass = (*env)->FindClass(env, JAVALSTRING); if((strClass == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); free_jstrarraylist(&list); throw_serialcom_exception(env, 3, 0, E_FINDCLASSSSTRINGSTR); return NULL; } usbDevicesFound = (*env)->NewObjectArray(env, (jsize)list.index, strClass, NULL); if((usbDevicesFound == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); free_jstrarraylist(&list); throw_serialcom_exception(env, 3, 0, E_NEWOBJECTARRAYSTR); return NULL; } for (x = 0; x < list.index; x++) { (*env)->SetObjectArrayElement(env, usbDevicesFound, x, list.base[x]); if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); free_jstrarraylist(&list); throw_serialcom_exception(env, 3, 0, E_SETOBJECTARRAYSTR); return NULL; } } free_jstrarraylist(&list); return usbDevicesFound; }
/* * Find the name of the most specific driver which is currently associated with the * given HID device instance. * * A HID device can be on USB, I2C, BLUETOOTH or pseudo. */ jstring find_driver_for_given_hiddevice(JNIEnv *env, jstring hidDevNode) { int x = 0; BOOL ret = FALSE; LONG status = 0; DWORD error_code = 0; DWORD errorVal = 0; DWORD size = 0; DWORD charbuffer_size = 0; DWORD driver_name_size = 0; ULONG buffer_size = 0; DWORD hid_member_index = 0; HDEVINFO hid_dev_info_set; SP_DEVINFO_DATA hid_dev_instance; ULONG devprop_buffer_size = 0; const jchar* device_node = NULL; jstring driver_name = NULL; /* size of these buffers is hardcoded in functions using them */ TCHAR buffer[1024]; TCHAR keybuf[1024]; TCHAR charbuffer[128]; /* extract HID device name to match (as an array of Unicode characters) */ device_node = (*env)->GetStringChars(env, hidDevNode, JNI_FALSE); if ((device_node == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { throw_serialcom_exception(env, 3, 0, E_GETSTRCHARSTR); return NULL; } /* get information set for all usb devices matching the GUID */ hid_dev_info_set = SetupDiGetClassDevs(&GUID_DEVINTERFACE_HID, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (hid_dev_info_set == INVALID_HANDLE_VALUE) { SetupDiDestroyDeviceInfoList(hid_dev_info_set); (*env)->ReleaseStringChars(env, hidDevNode, device_node); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL); return NULL; } /* enumerate all devices in this information set */ hid_member_index = 0; while (1) { ZeroMemory(&hid_dev_instance, sizeof(hid_dev_instance)); hid_dev_instance.cbSize = sizeof(hid_dev_instance); /* from information set, get device by index */ ret = SetupDiEnumDeviceInfo(hid_dev_info_set, hid_member_index, &hid_dev_instance); if (ret == FALSE) { error_code = GetLastError(); if (error_code == ERROR_NO_MORE_ITEMS) { break; }else { SetupDiDestroyDeviceInfoList(hid_dev_info_set); (*env)->ReleaseStringChars(env, hidDevNode, device_node); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(error_code), NULL); return NULL; } } /* for this device find its instance ID, for example; HID\VID_04D8&PID_00DF&MI_02\7&33842C3F&0&0000 * this is variable 'Device Instance Path' in device manager. */ memset(buffer, '\0', 1024); ret = SetupDiGetDeviceInstanceId(hid_dev_info_set, &hid_dev_instance, buffer, 1024, &size); if (ret == FALSE) { SetupDiDestroyDeviceInfoList(hid_dev_info_set); (*env)->ReleaseStringChars(env, hidDevNode, device_node); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL); return NULL; } /* match device path */ ret = _tcsicmp(device_node, buffer); if (ret != 0) { hid_member_index++; continue; } /* reaching here means this is the device for which driver is to be found. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\HID\VID_VID+PID_PID\Serial_Number */ memset(keybuf, '\0', 1024); _stprintf_s(keybuf, 1024, TEXT("SYSTEM\\CurrentControlSet\\Enum\\%s"), buffer); /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\HID\VID_VID+PID_PID\Serial_Number\Service */ charbuffer_size = sizeof(charbuffer); memset(charbuffer, '\0', 128); status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("Service"), RRF_RT_REG_SZ, NULL, (PVOID)charbuffer, &charbuffer_size); if (status != ERROR_SUCCESS) { errorVal = GetLastError(); if (errorVal == 0x00) { /* this indicates Service registery entry does not exist, we assume windows provided default HidClass driver is driving this device */ driver_name = (*env)->NewStringUTF(env, "HidClass"); if ((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); SetupDiDestroyDeviceInfoList(hid_dev_info_set); (*env)->ReleaseStringChars(env, hidDevNode, device_node); throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR); return NULL; } return driver_name; }else { SetupDiDestroyDeviceInfoList(hid_dev_info_set); (*env)->ReleaseStringChars(env, hidDevNode, device_node); throw_serialcom_exception(env, 4, errorVal, NULL); return NULL; } } /* return the driver name found as indicated by Service registry entry */ driver_name = (*env)->NewString(env, charbuffer, (jsize)_tcslen(charbuffer)); if ((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); SetupDiDestroyDeviceInfoList(hid_dev_info_set); (*env)->ReleaseStringChars(env, hidDevNode, device_node); throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR); return NULL; } SetupDiDestroyDeviceInfoList(hid_dev_info_set); (*env)->ReleaseStringChars(env, hidDevNode, device_node); return driver_name; } /* reaching here means that the no driver was found for given device path, return empty string */ driver_name = (*env)->NewStringUTF(env, ""); if ((driver_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { (*env)->ExceptionClear(env); throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR); return NULL; } return driver_name; }
/* * Get the current latency timer value for ftdi devices. * return value read on success or -1 if any error occurs. */ jint get_latency_timer_value(JNIEnv *env, jstring comPortName) { const jchar* port_name = NULL; int x = 0; BOOL ret = FALSE; LONG status = 0; DWORD error_code = 0; DWORD size = 0; DWORD regproptype; DWORD charbuffer_size = 0; DWORD driver_name_size = 0; ULONG buffer_size = 0; DWORD usb_member_index = 0; HDEVINFO usb_dev_info_set; SP_DEVINFO_DATA usb_dev_instance; ULONG devprop_buffer_size = 0; DEVPROPTYPE proptype; CONFIGRET cmret = 0; DEVINST firstchild = 0; DEVINST next_sibling = 0; DEVINST current_sibling = 0; DWORD timer_value; DWORD timervalue_size; /* size of these buffers is hardcoded in functions using them */ TCHAR buffer[1024]; TCHAR devprop_buffer[1024]; TCHAR keybuf[1024]; TCHAR charbuffer[128]; char cmerror[256]; /* extract com port name to match (as an array of Unicode characters) */ port_name = (*env)->GetStringChars(env, comPortName, JNI_FALSE); if ((port_name == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { throw_serialcom_exception(env, 3, 0, E_GETSTRUTFCHARSTR); return -1; } /* get information set for all usb devices matching the GUID */ usb_dev_info_set = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (usb_dev_info_set == INVALID_HANDLE_VALUE) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); (*env)->ReleaseStringChars(env, comPortName, port_name); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL); return -1; } /* enumerate all devices in this information set */ usb_member_index = 0; while (1) { ZeroMemory(&usb_dev_instance, sizeof(usb_dev_instance)); usb_dev_instance.cbSize = sizeof(usb_dev_instance); /* from information set, get device by index */ ret = SetupDiEnumDeviceInfo(usb_dev_info_set, usb_member_index, &usb_dev_instance); if (ret == FALSE) { error_code = GetLastError(); if (error_code == ERROR_NO_MORE_ITEMS) { break; } else { SetupDiDestroyDeviceInfoList(usb_dev_info_set); (*env)->ReleaseStringChars(env, comPortName, port_name); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(error_code), NULL); return -1; } } /* for this device find its instance ID (USB\VID_04D8&PID_00DF\000098037) * this is variable 'Device Instance Path' in device manager. */ memset(buffer, '\0', 1024); ret = SetupDiGetDeviceInstanceId(usb_dev_info_set, &usb_dev_instance, buffer, 1024, &size); if (ret == FALSE) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); (*env)->ReleaseStringChars(env, comPortName, port_name); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL); return -1; } cmret = CM_Get_Child(&firstchild, usb_dev_instance.DevInst, 0); if (cmret != CR_SUCCESS) { if (cmret == CR_NO_SUCH_DEVNODE) { /* this device does not have any child, so check if this device itself is a "Ports" class device or not */ memset(devprop_buffer, '\0', 1024); ret = SetupDiGetDeviceRegistryProperty(usb_dev_info_set, &usb_dev_instance, SPDRP_CLASSGUID, ®proptype, (BYTE *)devprop_buffer, sizeof(devprop_buffer), &size); if (ret == FALSE) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); (*env)->ReleaseStringChars(env, comPortName, port_name); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL); return -1; } /* match GUID */ ret = _tcsicmp(devprop_buffer, TEXT("{4D36E978-E325-11CE-BFC1-08002BE10318}")); if (ret != 0) { usb_member_index++; continue; } /* reaching here means that the device is COM port device (CDC/ACM), get its COM port name/number * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\FTDIBUS\VID_VID+PID_PID+Serial_Number\0000\DeviceParameters\PortName * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_VID+PID_PID\Serial_Number\DeviceParameters\PortName */ memset(keybuf, '\0', 1024); _stprintf_s(keybuf, 1024, TEXT("SYSTEM\\CurrentControlSet\\Enum\\%s\\Device Parameters"), buffer); charbuffer_size = sizeof(charbuffer); memset(charbuffer, '\0', 128); status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("PortName"), RRF_RT_REG_SZ, NULL, (PVOID)charbuffer, &charbuffer_size); if (status != ERROR_SUCCESS) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); (*env)->ReleaseStringChars(env, comPortName, port_name); throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } /* match port name */ ret = _tcsicmp(charbuffer, port_name); if (ret != 0) { usb_member_index++; continue; } /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\FTDIBUS\VID_VID+PID_PID+Serial_Number\0000\DeviceParameters\LatencyTimer */ status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("LatencyTimer"), RRF_RT_REG_DWORD, NULL, &timer_value, &timervalue_size); if (status != ERROR_SUCCESS) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); (*env)->ReleaseStringChars(env, comPortName, port_name); throw_serialcom_exception(env, 4, status, NULL); return -1; } SetupDiDestroyDeviceInfoList(usb_dev_info_set); (*env)->ReleaseStringChars(env, comPortName, port_name); return (jint)timer_value; }else { SetupDiDestroyDeviceInfoList(usb_dev_info_set); (*env)->ReleaseStringChars(env, comPortName, port_name); _snprintf_s(cmerror, 256, 256, "CM_Get_DevNode_Registry_Property CR_xxxx error code : 0x%X\0", cmret); throw_serialcom_exception(env, 3, 0, cmerror); return -1; } } /* reaching here means that this USB device has at-least one child device node, examine child now */ devprop_buffer_size = sizeof(devprop_buffer); memset(devprop_buffer, '\0', sizeof(devprop_buffer)); cmret = CM_Get_DevNode_Registry_Property(firstchild, CM_DRP_CLASSGUID, &proptype, (PVOID)devprop_buffer, &devprop_buffer_size, 0); if (cmret != CR_SUCCESS) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); (*env)->ReleaseStringChars(env, comPortName, port_name); _snprintf_s(cmerror, 256, 256, "CM_Get_DevNode_Registry_Property CR_xxxx error code : 0x%X\0", cmret); throw_serialcom_exception(env, 3, 0, cmerror); return -1; } /* match GUID */ ret = _tcsicmp(devprop_buffer, TEXT("{4D36E978-E325-11CE-BFC1-08002BE10318}")); if (ret == 0) { /* reaching here means that the child device is COM port device (CDC/ACM), get its COM port name/number */ memset(buffer, '\0', 1024); cmret = CM_Get_Device_ID(firstchild, buffer, 1024, 0); if (cmret != CR_SUCCESS) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); (*env)->ReleaseStringChars(env, comPortName, port_name); _snprintf_s(cmerror, 256, 256, "CM_Get_Device_ID CR_xxxx error code : 0x%X\0", cmret); throw_serialcom_exception(env, 3, 0, cmerror); return -1; } memset(keybuf, '\0', 1024); _stprintf_s(keybuf, 1024, TEXT("SYSTEM\\CurrentControlSet\\Enum\\%s\\Device Parameters"), buffer); charbuffer_size = sizeof(charbuffer); memset(charbuffer, '\0', 128); status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("PortName"), RRF_RT_REG_SZ, NULL, (PVOID)charbuffer, &charbuffer_size); if (status != ERROR_SUCCESS) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); (*env)->ReleaseStringChars(env, comPortName, port_name); throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } /* match port name */ ret = _tcsicmp(charbuffer, port_name); if (ret == 0) { status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("LatencyTimer"), RRF_RT_REG_DWORD, NULL, &timer_value, &timervalue_size); if (status != ERROR_SUCCESS) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); (*env)->ReleaseStringChars(env, comPortName, port_name); throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } /* clean up and return timer value found */ SetupDiDestroyDeviceInfoList(usb_dev_info_set); (*env)->ReleaseStringChars(env, comPortName, port_name); return (jint)timer_value; } } /* reaching here means first child of this USB device was not CDC/ACM interface, need to iterate over all the interfaces (siblings) this device has examining them for matching our criteria */ current_sibling = firstchild; while (1) { cmret = CM_Get_Sibling(&next_sibling, current_sibling, 0); if (cmret != CR_SUCCESS) { if (cmret == CR_NO_SUCH_DEVNODE) { /* done iterating over all interfaces, move to next examine next USB device */ break; } else { SetupDiDestroyDeviceInfoList(usb_dev_info_set); _snprintf_s(cmerror, 256, 256, "CM_Get_Sibling failed with CR_xxxx error code : 0x%X\0", cmret); (*env)->ReleaseStringChars(env, comPortName, port_name); throw_serialcom_exception(env, 3, 0, cmerror); return -1; } } /* reaching here means USB device has more than 1 interfaces, get class of this interface (sibling) */ devprop_buffer_size = sizeof(devprop_buffer); memset(devprop_buffer, '\0', sizeof(devprop_buffer)); cmret = CM_Get_DevNode_Registry_Property(next_sibling, CM_DRP_CLASSGUID, &proptype, (VOID *)devprop_buffer, &devprop_buffer_size, 0); if (cmret != CR_SUCCESS) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); _snprintf_s(cmerror, 256, 256, "CM_Get_DevNode_Registry_Property failed with CR_xxxx error code : 0x%X\0", cmret); (*env)->ReleaseStringChars(env, comPortName, port_name); throw_serialcom_exception(env, 3, 0, cmerror); return -1; } /* match GUID for this sibling */ ret = _tcsicmp(devprop_buffer, TEXT("{4D36E978-E325-11CE-BFC1-08002BE10318}")); if (ret != 0) { /* this interface is not CDC/ACM, loop over to next interface */ current_sibling = next_sibling; continue; } /* reaching here means that this sibling (interface) is a CDC/ACM type, get its COM port name/number */ buffer_size = (ULONG)_tcslen(buffer); memset(buffer, '\0', 1024); cmret = CM_Get_Device_ID(next_sibling, buffer, 1024, 0); if (cmret != CR_SUCCESS) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); _snprintf_s(cmerror, 256, 256, "CM_Get_Device_ID failed with CR_xxxx error code : 0x%X\0", cmret); (*env)->ReleaseStringChars(env, comPortName, port_name); throw_serialcom_exception(env, 3, 0, cmerror); return -1; } memset(keybuf, '\0', 1024); _stprintf_s(keybuf, 1024, TEXT("SYSTEM\\CurrentControlSet\\Enum\\%s\\Device Parameters"), buffer); charbuffer_size = sizeof(charbuffer); memset(charbuffer, '\0', 128); status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("PortName"), RRF_RT_REG_SZ, NULL, (PVOID)charbuffer, &charbuffer_size); if (status != ERROR_SUCCESS) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); (*env)->ReleaseStringChars(env, comPortName, port_name); throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } /* match port name */ ret = _tcsicmp(charbuffer, port_name); if (ret == 0) { status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("LatencyTimer"), RRF_RT_REG_DWORD, NULL, &timer_value, &timervalue_size); if (status != ERROR_SUCCESS) { SetupDiDestroyDeviceInfoList(usb_dev_info_set); (*env)->ReleaseStringChars(env, comPortName, port_name); throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } /* clean up and return timer value found */ SetupDiDestroyDeviceInfoList(usb_dev_info_set); (*env)->ReleaseStringChars(env, comPortName, port_name); return (jint)timer_value; } /* set this sibling as base sibling for fetching next sibling, loop over to get and check next interface (sibling) */ current_sibling = next_sibling; } /* increment to get and examine the next usb device for COM ports class */ usb_member_index++; } /* reaching here means that probably given com port does not represent ftdi device or does not exist at all */ SetupDiDestroyDeviceInfoList(usb_dev_info_set); (*env)->ReleaseStringChars(env, comPortName, port_name); throw_serialcom_exception(env, 3, 0, E_NOTFTDIPORT); return -1; }
/* * get the current latency timer value for ftdi devices. * return value read on success or -1 if any error occurs. */ jint get_latency_timer_value(JNIEnv *env, jstring comPortName) { struct udev *udev_ctx; struct udev_enumerate *enumerator; struct udev_list_entry *devices, *dev_list_entry; const char *device_path; const char *device_node; const char *path; struct udev_device *udev_device; const char *com_port_to_match = NULL; char buffer[512]; int fd = 0; int ret = 0; char *endptr; jint timer_value = 0; udev_ctx = udev_new(); enumerator = udev_enumerate_new(udev_ctx); udev_enumerate_add_match_subsystem(enumerator, "tty"); udev_enumerate_scan_devices(enumerator); devices = udev_enumerate_get_list_entry(enumerator); com_port_to_match = (*env)->GetStringUTFChars(env, comPortName, NULL); if((com_port_to_match == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { throw_serialcom_exception(env, 3, 0, E_GETSTRUTFCHARSTR); return -1; } udev_list_entry_foreach(dev_list_entry, devices) { path = udev_list_entry_get_name(dev_list_entry); udev_device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerator), path); if(udev_device == NULL) { continue; } /* match the device node, if matched get device path, and create absolute path to * latency file and read its value */ device_node = udev_device_get_devnode(udev_device); if(device_node != NULL) { if(strcmp(device_node, com_port_to_match) == 0) { device_path = udev_device_get_devpath(udev_device); if(device_path != NULL) { memset(buffer, '\0', sizeof(buffer)); snprintf(buffer, 512, "/sys%s/device/latency_timer", device_path); errno = 0; fd = open(buffer, O_RDONLY); if(fd < 0) { (*env)->ReleaseStringUTFChars(env, comPortName, com_port_to_match); throw_serialcom_exception(env, 1, errno, NULL); return -1; } memset(buffer, '\0', sizeof(buffer)); errno = 0; ret = read(fd, buffer, 512); if(ret < 0) { (*env)->ReleaseStringUTFChars(env, comPortName, com_port_to_match); throw_serialcom_exception(env, 1, errno, NULL); return -1; } close(fd); timer_value = (jint) strtol(buffer, &endptr, 10); (*env)->ReleaseStringUTFChars(env, comPortName, com_port_to_match); udev_device_unref(udev_device); udev_enumerate_unref(enumerator); udev_unref(udev_ctx); return timer_value; } } } udev_device_unref(udev_device); }
jobjectArray getusb_firmware_version(JNIEnv *env, jint usbvid_to_match, jint usbpid_to_match, jstring serial_number) { int x = 0; int vid = 0; int pid = 0; struct udev *udev_ctx; struct udev_enumerate *enumerator; struct udev_list_entry *devices, *dev_list_entry; const char *sysattr_val; const char *path; struct udev_device *udev_device; char *endptr; char buffer[128]; const char* serial = NULL; const char *prop_val; struct jstrarray_list list = {0}; jstring usb_dev_info; jclass strClass = NULL; jobjectArray usbDevicesFwVerFound = NULL; if(serial_number != NULL) { serial = (*env)->GetStringUTFChars(env, serial_number, NULL); if((serial == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { throw_serialcom_exception(env, 3, 0, E_GETSTRUTFCHARSTR); return NULL; } } init_jstrarraylist(&list, 10); /* libudev is reference counted. Memory is freed when counts reach to zero. */ udev_ctx = udev_new(); enumerator = udev_enumerate_new(udev_ctx); udev_enumerate_add_match_subsystem(enumerator, "usb"); udev_enumerate_scan_devices(enumerator); devices = udev_enumerate_get_list_entry(enumerator); udev_list_entry_foreach(dev_list_entry, devices) { path = udev_list_entry_get_name(dev_list_entry); udev_device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerator), path); if(udev_device == NULL) { continue; } if(strcmp("usb_device", udev_device_get_devtype(udev_device)) == 0) { /* match vid */ sysattr_val = udev_device_get_sysattr_value(udev_device, "idVendor"); if(sysattr_val != NULL) { vid = 0x0000FFFF & (int)strtol(sysattr_val, &endptr, 16); if(vid != usbvid_to_match) { udev_device_unref(udev_device); continue; } }else { udev_device_unref(udev_device); continue; } /* match pid */ sysattr_val = udev_device_get_sysattr_value(udev_device, "idProduct"); if(sysattr_val != NULL) { pid = 0x0000FFFF & (int)strtol(sysattr_val, &endptr, 16); if(pid != usbpid_to_match) { udev_device_unref(udev_device); continue; } }else { udev_device_unref(udev_device); continue; } /* match serial number if requested by application */ if (serial != NULL) { sysattr_val = udev_device_get_sysattr_value(udev_device, "serial"); if(sysattr_val != NULL) { if(strcasecmp(sysattr_val, serial) != 0) { udev_device_unref(udev_device); continue; } }else { udev_device_unref(udev_device); continue; } } /* reaching here means that this is the device whose firmware version application need to know. */ prop_val = udev_device_get_property_value(udev_device, "ID_REVISION"); memset(buffer, '\0', sizeof(buffer)); snprintf(buffer, 128, "%d", (0x0000FFFF & (int)strtol(prop_val, &endptr, 16))); usb_dev_info = (*env)->NewStringUTF(env, buffer); if((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { free_jstrarraylist(&list); udev_device_unref(udev_device); udev_enumerate_unref(enumerator); udev_unref(udev_ctx); throw_serialcom_exception(env, 3, 0, E_NEWSTRUTFSTR); return NULL; } insert_jstrarraylist(&list, usb_dev_info); } udev_device_unref(udev_device); }
/* * Finds if a USB device whose VID, PID and serial number is given is connected to system * or not using platform specific APIs. * * Returns 1 if device is connected, returns 0 if not connected, -1 if an error occurs. */ jint is_usb_dev_connected(JNIEnv *env, jint usbvid_to_match, jint usbpid_to_match, jstring serial_number) { int vid = 0; int pid = 0; struct udev *udev_ctx; struct udev_enumerate *enumerator; struct udev_list_entry *devices, *dev_list_entry; const char *sysattr_val; const char *path; struct udev_device *udev_device; char *endptr; const char* serial = NULL; if(serial_number != NULL) { serial = (*env)->GetStringUTFChars(env, serial_number, NULL); if((serial == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { throw_serialcom_exception(env, 3, 0, E_GETSTRUTFCHARSTR); return -1; } } /* libudev is reference counted. Memory is freed when counts reach to zero. */ udev_ctx = udev_new(); enumerator = udev_enumerate_new(udev_ctx); udev_enumerate_add_match_subsystem(enumerator, "usb"); udev_enumerate_scan_devices(enumerator); devices = udev_enumerate_get_list_entry(enumerator); udev_list_entry_foreach(dev_list_entry, devices) { path = udev_list_entry_get_name(dev_list_entry); udev_device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerator), path); if(udev_device == NULL) { continue; } if(strcmp("usb_device", udev_device_get_devtype(udev_device)) == 0) { /* match vid */ sysattr_val = udev_device_get_sysattr_value(udev_device, "idVendor"); if(sysattr_val != NULL) { vid = 0x0000FFFF & (int)strtol(sysattr_val, &endptr, 16); if(vid != usbvid_to_match) { udev_device_unref(udev_device); continue; } }else { udev_device_unref(udev_device); continue; } /* match pid */ sysattr_val = udev_device_get_sysattr_value(udev_device, "idProduct"); if(sysattr_val != NULL) { pid = 0x0000FFFF & (int)strtol(sysattr_val, &endptr, 16); if(pid != usbpid_to_match) { udev_device_unref(udev_device); continue; } }else { udev_device_unref(udev_device); continue; } /* match serial number if requested by application */ if (serial != NULL) { sysattr_val = udev_device_get_sysattr_value(udev_device, "serial"); if(sysattr_val != NULL) { if(strcasecmp(sysattr_val, serial) != 0) { udev_device_unref(udev_device); continue; } }else { udev_device_unref(udev_device); continue; } } /* reaching here means device is connected to system at present which matches given criteria. */ udev_device_unref(udev_device); udev_enumerate_unref(enumerator); udev_unref(udev_ctx); return 1; } udev_device_unref(udev_device); }
/* * Check if the given COM port name belongs to a multi port serial adaptor device. If yes, get its driver name * and return to caller. * * Return 1 if found, 0 if not found, -1 if an error occurs (also throws exception in this case). */ int get_driver_com_port_multiportadaptor(JNIEnv *env, const jchar *port_name, TCHAR *driver_name) { int x = 0; BOOL ret = FALSE; LONG status = 0; DWORD error_code = 0; DWORD size = 0; DWORD regproptype; DWORD charbuffer_size = 0; DWORD driver_name_size = 0; ULONG buffer_size = 0; DWORD multiport_member_index = 0; HDEVINFO multiport_dev_info_set; SP_DEVINFO_DATA multiport_dev_instance; ULONG devprop_buffer_size = 0; DEVPROPTYPE proptype; CONFIGRET cmret = 0; DEVINST firstchild = 0; DEVINST next_sibling = 0; DEVINST current_sibling = 0; /* size of these buffers is hardcoded in functions using them */ TCHAR buffer[1024]; TCHAR devprop_buffer[1024]; TCHAR keybuf[1024]; TCHAR charbuffer[128]; char cmerror[256]; /* get information set for all multi port serial adaptor devices matching the GUID */ multiport_dev_info_set = SetupDiGetClassDevs(&GUID_MULTIPORT_SERIAL_ADAPTOR_DEVICE, NULL, NULL, DIGCF_DEVICEINTERFACE); if (multiport_dev_info_set == INVALID_HANDLE_VALUE) { SetupDiDestroyDeviceInfoList(multiport_dev_info_set); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(GetLastError()), NULL); return -1; } /* enumerate all devices in this information set */ multiport_member_index = 0; while (1) { ZeroMemory(&multiport_dev_instance, sizeof(multiport_dev_instance)); multiport_dev_instance.cbSize = sizeof(multiport_dev_instance); /* from information set, get device by index */ ret = SetupDiEnumDeviceInfo(multiport_dev_info_set, multiport_member_index, &multiport_dev_instance); if (ret == FALSE) { error_code = GetLastError(); if (error_code == ERROR_NO_MORE_ITEMS) { break; }else { SetupDiDestroyDeviceInfoList(multiport_dev_info_set); throw_serialcom_exception(env, 4, HRESULT_FROM_SETUPAPI(error_code), NULL); return -1; } } /* for this device find its instance ID (USB\VID_04D8&PID_00DF\000098037) * this is variable 'Device Instance Path' in device manager. */ cmret = CM_Get_Device_ID(multiport_dev_instance.DevInst, buffer, 1024, 0); if (cmret != CR_SUCCESS) { SetupDiDestroyDeviceInfoList(multiport_dev_info_set); _snprintf_s(cmerror, 256, 256, "CM_Get_Device_ID CR_xxxx error code : 0x%X\0", cmret); throw_serialcom_exception(env, 3, 0, cmerror); return -1; } /* get its COM port name/number for this device */ memset(keybuf, '\0', 1024); _stprintf_s(keybuf, 1024, TEXT("SYSTEM\\CurrentControlSet\\Enum\\%s\\Device Parameters"), buffer); charbuffer_size = sizeof(charbuffer); memset(charbuffer, '\0', 128); /* ignore error as some devices might not have portname registry key */ status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("PortName"), RRF_RT_REG_SZ, NULL, (PVOID)charbuffer, &charbuffer_size); if (status == ERROR_SUCCESS) { /* match port name */ ret = _tcsicmp(charbuffer, port_name); if (ret == 0) { /* get driver name */ memset(keybuf, '\0', 1024); _stprintf_s(keybuf, 1024, TEXT("SYSTEM\\CurrentControlSet\\Enum\\%s"), buffer); /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\XXXX\XXX\XXX\Service */ charbuffer_size = sizeof(charbuffer); memset(charbuffer, '\0', 128); status = RegGetValue(HKEY_LOCAL_MACHINE, keybuf, TEXT("Service"), RRF_RT_REG_SZ, NULL, (PVOID)charbuffer, &charbuffer_size); if (status != ERROR_SUCCESS) { SetupDiDestroyDeviceInfoList(multiport_dev_info_set); throw_serialcom_exception(env, 4, GetLastError(), NULL); return -1; } /* populate array to be returned to caller */ memset(driver_name, '\0', 128); for (x = 0; x < _tcslen(charbuffer); x++) { driver_name[x] = charbuffer[x]; } /* clean up and return 1 to indicate driver found */ SetupDiDestroyDeviceInfoList(multiport_dev_info_set); return 1; } } /* increment to get and examine the next multiport device for COM ports class */ multiport_member_index++; } /* reaching here means given COM port does not belong to multi-port serial adaptor device */ SetupDiDestroyDeviceInfoList(multiport_dev_info_set); return 0; }