|
|
@@ -14,16 +14,78 @@
|
|
|
#include <iomanip>
|
|
|
|
|
|
// 定义JNI层通信TAG
|
|
|
-#define TAG "native_iscs_can"
|
|
|
+const char *TAG = "ISCS_CAN_NATIVE";
|
|
|
|
|
|
-#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
|
|
|
-#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
|
|
|
|
|
|
-static void throwIOException(JNIEnv *env, const char *msg) {
|
|
|
- jclass ex = env->FindClass("java/io/IOException");
|
|
|
- if (ex) env->ThrowNew(ex, msg);
|
|
|
+/**
|
|
|
+ * 打印常规级别的日志
|
|
|
+ *
|
|
|
+ * @param env
|
|
|
+ * @param msg
|
|
|
+ */
|
|
|
+void log_i(JNIEnv *env, const char *fmt, ...) {
|
|
|
+ // 获取类
|
|
|
+ jclass clazz = env->FindClass("com/iscs/comm/utils/ISCSLog");
|
|
|
+ if (clazz == nullptr) return;
|
|
|
+
|
|
|
+ // 获取静态方法
|
|
|
+ jmethodID methodId = env->GetStaticMethodID(clazz, "i", "(Ljava/lang/String;Ljava/lang/String;)V");
|
|
|
+ if (methodId == nullptr) return;
|
|
|
+
|
|
|
+ // 转换需要传递的数据
|
|
|
+ // 创建缓存区域
|
|
|
+ char buffer[1024];
|
|
|
+ // 获取参数列表
|
|
|
+ va_list args;
|
|
|
+ va_start(args, fmt);
|
|
|
+ vsnprintf(buffer, sizeof(buffer), fmt, args);
|
|
|
+ va_end(args);
|
|
|
+
|
|
|
+ jstring msg = env->NewStringUTF(buffer);
|
|
|
+
|
|
|
+ // 调用静态方法传递参数
|
|
|
+ env->CallStaticVoidMethod(clazz, methodId, env->NewStringUTF(TAG), msg);
|
|
|
+
|
|
|
+ // 资源释放
|
|
|
+ env->DeleteLocalRef(clazz);
|
|
|
+ env->DeleteLocalRef(msg);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 打印错误级别的日志
|
|
|
+ *
|
|
|
+ * @param env
|
|
|
+ * @param msg
|
|
|
+ */
|
|
|
+void log_e(JNIEnv *env, const char *fmt, ...) {
|
|
|
+ // 获取类
|
|
|
+ jclass clazz = env->FindClass("com/iscs/comm/utils/ISCSLog");
|
|
|
+ if (clazz == nullptr) return;
|
|
|
+
|
|
|
+ // 获取静态方法
|
|
|
+ jmethodID methodId = env->GetStaticMethodID(clazz, "e", "(Ljava/lang/String;Ljava/lang/String;)V");
|
|
|
+ if (methodId == nullptr) return;
|
|
|
+
|
|
|
+ // 转换需要传递的数据
|
|
|
+ // 创建缓存区域
|
|
|
+ char buffer[1024];
|
|
|
+ // 获取参数列表
|
|
|
+ va_list args;
|
|
|
+ va_start(args, fmt);
|
|
|
+ vsnprintf(buffer, sizeof(buffer), fmt, args);
|
|
|
+ va_end(args);
|
|
|
+
|
|
|
+ jstring msg = env->NewStringUTF(buffer);
|
|
|
+
|
|
|
+ // 调用静态方法传递参数
|
|
|
+ env->CallStaticVoidMethod(clazz, methodId, env->NewStringUTF(TAG), msg);
|
|
|
+
|
|
|
+ // 资源释放
|
|
|
+ env->DeleteLocalRef(clazz);
|
|
|
+ env->DeleteLocalRef(msg);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
/**
|
|
|
* 将字节数组转化为16进制字符串
|
|
|
*
|
|
|
@@ -55,6 +117,15 @@ std::string bytesToHexString(JNIEnv *env, jbyteArray array, bool uppercase = tru
|
|
|
return oss.str();
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * 字符串拼接操作
|
|
|
+ *
|
|
|
+ * @param env
|
|
|
+ * @param can_id
|
|
|
+ * @param jdata
|
|
|
+ * @param len
|
|
|
+ * @return
|
|
|
+ */
|
|
|
jbyteArray append_can_id_to_data(JNIEnv *env, jint can_id, const void *jdata, jint len) {
|
|
|
if (env == nullptr || jdata == nullptr || len <= 0) {
|
|
|
return nullptr;
|
|
|
@@ -85,11 +156,11 @@ jbyteArray append_can_id_to_data(JNIEnv *env, jint can_id, const void *jdata, ji
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
|
|
Java_com_iscs_comm_jni_NativeCan_canOpen(JNIEnv *env, jobject thiz, jstring can_port) {
|
|
|
const char *can_name = env->GetStringUTFChars(can_port, nullptr);
|
|
|
- LOGI("CAN ---> opening %s", can_name);
|
|
|
+ log_i(env, "CAN ---> opening %s", can_name);
|
|
|
|
|
|
int s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
|
|
if (s < 0) {
|
|
|
- LOGE("CAN ---> socket failed: %s", strerror(errno));
|
|
|
+ log_e(env, "CAN ---> socket failed: %s", strerror(errno));
|
|
|
env->ReleaseStringUTFChars(can_port, can_name);
|
|
|
return -1;
|
|
|
}
|
|
|
@@ -97,7 +168,7 @@ Java_com_iscs_comm_jni_NativeCan_canOpen(JNIEnv *env, jobject thiz, jstring can_
|
|
|
struct ifreq ifr{};
|
|
|
strncpy(ifr.ifr_name, can_name, IFNAMSIZ - 1);
|
|
|
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
|
|
|
- LOGE("CAN ---> ioctl(SIOCGIFINDEX) failed: %s", strerror(errno));
|
|
|
+ log_e(env, "CAN ---> ioctl(SIOCGIFINDEX) failed: %s", strerror(errno));
|
|
|
close(s);
|
|
|
env->ReleaseStringUTFChars(can_port, can_name);
|
|
|
return -2;
|
|
|
@@ -108,7 +179,7 @@ Java_com_iscs_comm_jni_NativeCan_canOpen(JNIEnv *env, jobject thiz, jstring can_
|
|
|
addr.can_ifindex = ifr.ifr_ifindex;
|
|
|
|
|
|
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
|
|
- LOGE("CAN ---> bind %s failed: %s", can_name, strerror(errno));
|
|
|
+ log_e(env, "CAN ---> bind %s failed: %s", can_name, strerror(errno));
|
|
|
close(s);
|
|
|
env->ReleaseStringUTFChars(can_port, can_name);
|
|
|
return -3;
|
|
|
@@ -117,7 +188,7 @@ Java_com_iscs_comm_jni_NativeCan_canOpen(JNIEnv *env, jobject thiz, jstring can_
|
|
|
// 可选: 非阻塞模式
|
|
|
// fcntl(s, F_SETFL, O_NONBLOCK);
|
|
|
|
|
|
- LOGI("CAN ---> opened %s port_id %d", can_name, s);
|
|
|
+ log_i(env, "CAN ---> opened %s port_id %d", can_name, s);
|
|
|
env->ReleaseStringUTFChars(can_port, can_name);
|
|
|
return s;
|
|
|
}
|
|
|
@@ -131,7 +202,7 @@ Java_com_iscs_comm_jni_NativeCan_canOpen(JNIEnv *env, jobject thiz, jstring can_
|
|
|
*/
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
|
|
Java_com_iscs_comm_jni_NativeCan_canClose(JNIEnv *env, jobject thiz, jint fd) {
|
|
|
- LOGI("CAN ---> close %d", fd);
|
|
|
+ log_i(env, "CAN ---> close %d", fd);
|
|
|
if (fd >= 0) close(fd);
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -166,7 +237,7 @@ Java_com_iscs_comm_jni_NativeCan_canWrite(
|
|
|
if (is_rtr) f.can_id |= CAN_RTR_FLAG;
|
|
|
f.can_dlc = (uint8_t) ((len > 8) ? 8 : len);
|
|
|
memcpy(f.data, data, f.can_dlc);
|
|
|
- LOGI("CAN ---> %s", bytesToHexString(env, append_can_id_to_data(env, f.can_id, f.data, f.can_dlc)).c_str());
|
|
|
+ log_i(env, "CAN ---> %s", bytesToHexString(env, append_can_id_to_data(env, f.can_id, f.data, f.can_dlc)).c_str());
|
|
|
ret = write(fd, &f, sizeof(f));
|
|
|
} else {
|
|
|
struct canfd_frame f{};
|
|
|
@@ -175,11 +246,11 @@ Java_com_iscs_comm_jni_NativeCan_canWrite(
|
|
|
if (is_rtr) f.can_id |= CAN_RTR_FLAG;
|
|
|
f.len = (uint8_t) ((len > 64) ? 64 : len);
|
|
|
memcpy(f.data, data, f.len);
|
|
|
- LOGI("CAN ---> %s", bytesToHexString(env, append_can_id_to_data(env, f.can_id, f.data, f.len)).c_str());
|
|
|
+ log_i(env, "CAN ---> %s", bytesToHexString(env, append_can_id_to_data(env, f.can_id, f.data, f.len)).c_str());
|
|
|
ret = write(fd, &f, sizeof(f));
|
|
|
}
|
|
|
|
|
|
- if (ret < 0) LOGE("CAN ---> write failed: %s", strerror(errno));
|
|
|
+ if (ret < 0) log_e(env, "CAN ---> write failed: %s", strerror(errno));
|
|
|
|
|
|
env->ReleaseByteArrayElements(jdata, data, JNI_ABORT);
|
|
|
return ret;
|
|
|
@@ -198,18 +269,18 @@ Java_com_iscs_comm_jni_NativeCan_canRead(JNIEnv *env, jobject thiz, jint fd, jin
|
|
|
struct pollfd pfd{.fd = fd, .events = POLLIN, .revents = 0};
|
|
|
int pr = poll(&pfd, 1, timeout_millis); // 确保 timeoutMs > 0
|
|
|
if (pr <= 0) {
|
|
|
- if (pr < 0) LOGE("CAN ---> poll error: %s", strerror(errno)); // 打印 poll 错误
|
|
|
+ if (pr < 0) log_e(env, "CAN ---> poll error: %s", strerror(errno)); // 打印 poll 错误
|
|
|
return env->NewByteArray(0); // 没有数据或超时
|
|
|
}
|
|
|
|
|
|
struct can_frame f{};
|
|
|
int r = read(fd, &f, sizeof(f)); // 读取 CAN 帧
|
|
|
if (r < 0) {
|
|
|
- LOGE("CAN ---> read failed: %s", strerror(errno)); // 读取失败的错误日志
|
|
|
+ log_e(env, "CAN ---> read failed: %s", strerror(errno)); // 读取失败的错误日志
|
|
|
return env->NewByteArray(0); // 返回空数组表示没有数据
|
|
|
}
|
|
|
|
|
|
jbyteArray out = append_can_id_to_data(env, f.can_id, f.data, f.can_dlc);
|
|
|
- LOGI("CAN <--- %s", bytesToHexString(env, out).c_str());
|
|
|
+ log_i(env, "CAN <--- %s", bytesToHexString(env, out).c_str());
|
|
|
return out;
|
|
|
}
|