/*
* Author:他叫小黑
* CSDN:https://blog.csdn.net/u013082948
*/
#define LOG_TAG "android.hardware.fingerprint@1.0-impl"
#include <stdbool.h>
#include <stdlib.h>
#include <pthread.h>
#include <fcntl.h>
#include <signal.h>
#include <semaphore.h>
#include <log/log.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include "Fingerprint.h"
#define REMOTE_MESSAGE_BUFFER_SIZE 36
#define REMOTE_MESSAGE_PRINT_BUFFER_SIZE 256
#define REMOTE_MESSAGE_PRINT_MAX_COUNT 64
namespace android {
namespace hardware {
namespace fingerprint {
namespace V1_0 {
namespace implementation {
struct hw_fingerprint_device_impl {
int fd;
sem_t sem_tx;
sem_t sem_rx;
};
struct hw_fingerprint_recv_thread
{
pthread_t t_id;
pthread_attr_t t_attr;
bool t_exitflag;
};
static sp<IFingerprintCallback> mCallback = 0;
static struct hw_fingerprint_device_impl g_fingerprint_impl =
{
.fd = -1,
};
static struct hw_fingerprint_recv_thread g_fingerprint_recv_thread =
{
.t_id = 0,
.t_exitflag = false,
};
static void remote_message_to_string(char* dest_str,unsigned int str_len_max, const unsigned char* msg, unsigned int msg_length)
{
unsigned int str_idx = 0;
unsigned int uiMsgLen = (msg_length <= REMOTE_MESSAGE_PRINT_MAX_COUNT ? msg_length : REMOTE_MESSAGE_PRINT_MAX_COUNT);
unsigned int i = 0;
for(; i < uiMsgLen; ++i){
if (str_idx < str_len_max - 4){
snprintf(dest_str + str_idx, 4, "%02X ", msg[i]);
str_idx += 3;
}
}
if(str_idx < str_len_max){
dest_str[str_idx] = 0; //EOS
}else{
dest_str[str_len_max - 1] = 0; //EOS
}
}
static unsigned long get_tick_count()
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC,&ts);
return (ts.tv_sec*1000 + ts.tv_nsec/1000000 /*(1000*1000)*/);
}
static void* fingerprint_message_recv_thread_proc(void *arg)
{
ALOGD("%s", __FUNCTION__);
unsigned char data[REMOTE_MESSAGE_BUFFER_SIZE];
FingerprintValue fingerprintValue;
while (g_fingerprint_recv_thread.t_exitflag == false)
{
if(g_fingerprint_impl.fd != -1)
{
memset(data, 0, REMOTE_MESSAGE_BUFFER_SIZE);
int len = read(g_fingerprint_impl.fd, data, REMOTE_MESSAGE_BUFFER_SIZE);
//ALOGD("%s read len:%d , fd:%d", __FUNCTION__,len,g_fingerprint_impl);
if (len > 0){
if( data[0] != 0 ){
//printf message
char acMsg[REMOTE_MESSAGE_PRINT_BUFFER_SIZE] = {0};
remote_message_to_string(acMsg, REMOTE_MESSAGE_PRINT_BUFFER_SIZE, data, len);
ALOGD("%010lu | Read: %s", get_tick_count(), acMsg);
//report message
fingerprintValue.values.resize(len);
for(int i = 0; i < len ; i++){
fingerprintValue.values[i] = data[i];
//ALOGD("%s fingerprintValue.values[%d]:%d", __FUNCTION__, i , fingerprintValue.values[i]);
}
//fingerprintValue.propId = 1;
if(mCallback != 0)
{
mCallback->onFingerprintEvent(fingerprintValue);
}else{
ALOGE("Try to mCallback->onFingerprintEvent but mCallback==0!!!");
}
}else{
usleep(100000);
}
}
}
else
{
ALOGE("Device has not been initialized!");
}
}
ALOGD("%s END!", __FUNCTION__);
return NULL;
}
Fingerprint::Fingerprint()
{
ALOGD("%s", __FUNCTION__);
if(-1 == g_fingerprint_impl.fd)
{
//fingerprint_message_recv_thread_init();
g_fingerprint_impl.fd = open("/dev/i2c-6",O_RDWR); //| O_NOCTTY | O_NDELAY
if (ioctl(g_fingerprint_impl.fd, I2C_SLAVE_FORCE, 0x1A) < 0) {
printf("ioctl:set slave address failed\n");
}
if(-1 == g_fingerprint_impl.fd)
{
ALOGE("Open device \"/dev/i2c-6\" failed!");
}
}
}
Fingerprint::~Fingerprint() {
if(-1 != g_fingerprint_impl.fd)
{
//fingerprint_message_recv_thread_destroy();
close(g_fingerprint_impl.fd);
g_fingerprint_impl.fd = -1;
}
}
/*void Fingerprint::fingerprint_message_recv_thread_init() //构造函数调用
{
ALOGD("%s", __FUNCTION__);
//pthread_attr_t
pthread_attr_init(&g_fingerprint_recv_thread.t_attr);
pthread_attr_setschedpolicy(&g_fingerprint_recv_thread.t_attr, SCHED_RR);
};
void Fingerprint::fingerprint_message_recv_thread_destroy() //析构函数调用
{
ALOGD("%s", __FUNCTION__);
//pthread_attr_t
pthread_attr_destroy(&g_fingerprint_recv_thread.t_attr);
};*/
void Fingerprint::fingerprint_message_recv_thread_subscribe()
{
ALOGD("%s", __FUNCTION__);
g_fingerprint_recv_thread.t_exitflag = false;
if (pthread_create(&g_fingerprint_recv_thread.t_id,
/*&g_fingerprint_recv_thread.t_attr*/NULL,
fingerprint_message_recv_thread_proc,
NULL))
{
g_fingerprint_recv_thread.t_id = 0;
}
}
void Fingerprint::fingerprint_message_recv_thread_unsubscribe()
{
ALOGD("%s", __FUNCTION__);
if(g_fingerprint_recv_thread.t_id != 0)
{
g_fingerprint_recv_thread.t_exitflag = true;
void* lpv = NULL;
pthread_join(g_fingerprint_recv_thread.t_id, &lpv);
g_fingerprint_recv_thread.t_id = 0;
}
}
// Methods from ::android::hardware::fingerprint::V1_0::IFingerprint follow.
Return<bool> Fingerprint::subscribe(const sp<IFingerprintCallback>& callback) {
ALOGD("%s", __FUNCTION__);
mCallback = callback;
if(-1 != g_fingerprint_impl.fd)
{
fingerprint_message_recv_thread_subscribe();//创建线程read数据
return true;
}
return false;
}
Return<bool> Fingerprint::unsubscribe() {
ALOGD("%s", __FUNCTION__);
//signal(SIGIO, SIG_IGN);
if(-1 != g_fingerprint_impl.fd)
{
fingerprint_message_recv_thread_unsubscribe();
}
return true;
}
Return<bool> Fingerprint::set(const FingerprintValue& fingerprintValue) {
ALOGD("%s", __FUNCTION__);
std::vector<uint8_t> vecData;
unsigned int write_size = 0;
for (auto value : fingerprintValue.values) {
vecData.push_back((uint8_t)value); //static_cast<int32_t>(msg.size())
ALOGD("%s , value : %d", __FUNCTION__,value);
}
int msg_length = vecData.size();
if(-1 != g_fingerprint_impl.fd){
//for(int i = 0 ; i < vecData.size(); i++){
// ALOGD("%s , write ~vecData[%d]:%d ", __FUNCTION__, i , vecData[i]);
//}
write_size = write(g_fingerprint_impl.fd, (char *)vecData.data(), msg_length);
ALOGE("Fingerprint Send message write_size: %d ", write_size);
if(msg_length != write_size){
ALOGE("Fingerprint Send message failed! write_size: %d != msg_length: %d !", write_size, msg_length);
return false;
}
}else{
ALOGE("Fingerprint Device has not been initialized!");
return false;
}
return true;
}
IFingerprint* HIDL_FETCH_IFingerprint(const char* /* name */) {
return new Fingerprint();
}
} // namespace implementation
} // namespace V1_0
} // namespace fingerprint
} // namespace hardware
} // namespace android