1
Cでシリアルポートプログラムを開発し、対応するコマンドを受信すると、プログラムはキーコードを送信します。私はadb経由でプログラムを実行し、完璧に動作します。しかし、init.rcを使ってプログラムを実行すると、uartデータを完全に受け取ることができません。私はselect()
の動作性能が、手動で実行され、init.rc.によって自動的に呼び出される間では異なることを疑う私のプログラムは起動時に自動的に実行される必要があるので、この問題を解決する必要があります。Android C Select()performance
ここに私のコードです。
main.cの
#include "ts_uart_common.h"
int ts_uart_main()
{
int i = 0;
fd_set readFds;
int retval;
struct timeval respTime;
struct timeval setTime;
struct timespec ts;
struct tm tm1;
unsigned char output_buf[bufsize];
int j, error = 0, dev_kb = 0, counter = 0;
time_t t1;
pthread_t socket_thread, send_thread, watchdog_thread;
struct timeval last_receive_time, diff_time;
/*
* to handle ctrl +c
*/
if(signal(SIGINT, signalHandler) == SIG_ERR) {
printf("ERROR : Failed to register signal handler\n");
exit(1);
}
if(pthread_create(&socket_thread , NULL , socket_receive_handler, (void*) 0) < 0) {
printf("pthread error\n");
exit(1);
}
timeout = read_ints(TIMEOUT_FILE);
printf("timeout = %d ms\n", timeout/1000);
pthread_mutex_init (¶ms.mutex , NULL);
pthread_cond_init (¶ms.done, NULL);
size = 0;
memset(output_buf, 0, bufsize);
ut.baudrate = 115200;
ut.flow_cntrl = 0;
ut.max_delay = 0;
ut.random_enable = 0;
ut.fd = open(UART_DEV_NAME, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
if (ut.fd == -1) {
exit(1);
}
else {
fcntl(ut.fd, F_SETFL, 0);
}
dev_kb = open(DEVICEKEYBOARD, O_RDWR);
if(dev_kb < 0){
exit(1);
}
printf("Open_port successful, existing port baud=%d\n", getbaud(ut.fd));
gettimeofday(&last_send_time, NULL);
tcgetattr(ut.fd, &oldtio);
initport(ut.fd, ut.baudrate, ut.flow_cntrl);
while (1) {
FD_ZERO(&readFds);
FD_SET(ut.fd, &readFds);
respTime.tv_sec = 0;
respTime.tv_usec = timeout;
retval = select(FD_SETSIZE, &readFds, NULL, NULL, &respTime);
if (retval == 0) {
//determine send heartbeat signal or not
struct timeval now_time, result;
gettimeofday(&now_time, NULL);
timeval_subtract(&result, &now_time, &last_send_time);
if(result.tv_sec > 5) {
int r = pthread_create(&watchdog_thread , NULL , send_watchdog , (void*) NULL);
gettimeofday(&last_send_time, NULL);
}
continue;
}
else if (retval == ERROR) {
printf("select: error :: %d\n", retval);
}
if (FD_ISSET(ut.fd, &readFds) != 0) {
//calculated from the previous command is received
struct timeval now_time, result;
gettimeofday(&now_time, NULL);
timeval_subtract(&result, &now_time, &last_receive_time);
printf("\n------Start------\n");
printf("Get Command!!! Diff = %08ld, timeout = %d\n", result.tv_usec, (result.tv_usec > timeout));
if(result.tv_usec > timeout) {
//clear the data if the time is over than timeout
printf("==> Timeout, clean data!!\n");
size = 0;
memset(output_buf, 0, bufsize);
}
size = readport(&ut.fd, output_buf);
if (ERROR == size){
printf("Read Port failed\n");
close_port();
}
}
//determine whether the instruction to be executed
for(i = 0; i < size; i++) {
if(i + 1 < size) {
if(output_buf[i] == 85 && (output_buf[i + 1] == 128 || output_buf[i + 1] == 130)) {
printf("==> Found command!\n");
break;
}
}
}
printf("Length = %d\n", size);
//we want to run a command
if(output_buf[i] == 85){
if(output_buf[i + 1] == 128) {
//KeyPress command
if(output_buf[i + 2] == 1) {
printf("==>Detect Enter\n");
uart_sendevent_keyboard(dev_kb, 1, 28, 1);
uart_sendevent_keyboard(dev_kb, 0, 0, 0);
uart_sendevent_keyboard(dev_kb, 1, 28, 0);
uart_sendevent_keyboard(dev_kb, 0, 0, 0);
}
else if(output_buf[i + 2] == 2) {
printf("==>Detect BACK\n");
uart_sendevent_keyboard(dev_kb, 1, 158, 1);
uart_sendevent_keyboard(dev_kb, 0, 0, 0);
uart_sendevent_keyboard(dev_kb, 1, 158, 0);
uart_sendevent_keyboard(dev_kb, 0, 0, 0);
}
else if(output_buf[i + 2] == 3) {
printf("==>Detect UP\n");
uart_sendevent_keyboard(dev_kb, 1, 103, 1);
uart_sendevent_keyboard(dev_kb, 0, 0, 0);
uart_sendevent_keyboard(dev_kb, 1, 103, 0);
uart_sendevent_keyboard(dev_kb, 0, 0, 0);
}
else if(output_buf[i + 2] == 4) {
printf("==>Detect DOWN\n");
uart_sendevent_keyboard(dev_kb, 1, 108, 1);
uart_sendevent_keyboard(dev_kb, 0, 0, 0);
uart_sendevent_keyboard(dev_kb, 1, 108, 0);
uart_sendevent_keyboard(dev_kb, 0, 0, 0);
}
else if(output_buf[i + 2] == 5) {
printf("==>Detect LEFT\n");
uart_sendevent_keyboard(dev_kb, 1, 105, 1);
uart_sendevent_keyboard(dev_kb, 0, 0, 0);
uart_sendevent_keyboard(dev_kb, 1, 105, 0);
uart_sendevent_keyboard(dev_kb, 0, 0, 0);
}
else if(output_buf[i + 2] == 6) {
printf("==>Detect RIGHT\n");
uart_sendevent_keyboard(dev_kb, 1, 106, 1);
uart_sendevent_keyboard(dev_kb, 0, 0, 0);
uart_sendevent_keyboard(dev_kb, 1, 106, 0);
uart_sendevent_keyboard(dev_kb, 0, 0, 0);
}
}
}
//record time
gettimeofday(&last_receive_time, NULL);
//if we get commands from uart, send it to the socket
pthread_create(&send_thread , NULL , socket_send_handler , (void*) output_buf);
}
FD_CLR(ut.fd, &readFds);
close_port();
return 0;
}
void *socket_receive_handler() {
int len_inet, i;
struct sockaddr_in adr_clnt;
unsigned char socket_buf[bufsize], socket_buf_show[bufsize];
struct sockaddr_in my_addr;
pthread_t write_thread;
my_addr.sin_family = AF_INET;
my_addr.sin_port=htons(10000);
my_addr.sin_addr.s_addr=htonl(INADDR_ANY);
bzero(&(my_addr.sin_zero), 8);
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
perror("socket");
exit(1);
}
if(bind(sockfd, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) == -1) {
perror("bind error");
exit(1);
}
while(1){
len_inet = sizeof adr_clnt;
memset(socket_buf, 0, bufsize);
udp_receive = recvfrom(sockfd, // Socket
socket_buf, // Receiving buffer
sizeof socket_buf, // Max recv buf size
0, // Flags: no options
(struct sockaddr *)&adr_clnt, // Addr
&len_inet); // Addr len, in & out
if (udp_receive < 0){
perror("recv");
exit(1);
}
else {
//write to uart
strncpy(socket_buf_show, socket_buf, udp_receive);
pthread_create(&write_thread , NULL , send_uart, (void*) socket_buf_show);
//print it
printf("UDP Socket Receive: ");
for(i = 0; i < udp_receive; i++) {
printf("0x%x", socket_buf_show[i]);
if(i != udp_receive - 1) {
printf(", ");
}
}
printf("\n");
}
}
}
void *socket_send_handler(void* arg) {
struct sockaddr_in addrDest;
addrDest.sin_family = AF_INET;
addrDest.sin_port = htons(10001);
addrDest.sin_addr.s_addr = inet_addr("127.0.0.1");
unsigned char *array = (unsigned char*) arg;
int result = sendto(sockfd, array, size, 0, (struct sockaddr*)&addrDest, sizeof addrDest);
printf("Send UDP bytes: %d\n", result);
printf("------END------\n\n");
return 0;
}
void *send_uart(void* arg) {
unsigned char *array = (unsigned char*) arg;
int new_timeout = array[2];
//if we get commands from app, send it to the uart
writeport(&ut.fd, array, udp_receive);
return 0;
}
void *send_watchdog(void* arg){
unsigned char command[3] = {0x55, 0xFF, 0x00};
writeport(&ut.fd, command, 3);
printf("==>Send heart beat Complete\n");
return 0;
}
ts_uart_common.c
#include "ts_uart_common.h"
int writeport(int *fd, unsigned char *chars,int len) {
int lock_result = -1;
/* Lock. */
do{
lock_result = pthread_mutex_lock(¶ms.mutex);
}while(lock_result != 0);
/* Work. */
int n = write(*fd, chars,len);
/* Unlock and signal completion. */
pthread_mutex_unlock(¶ms.mutex);
pthread_cond_signal (¶ms.done);
if (n < 0) {
fputs("write failed!\n", stderr);
return 0;
}
return n;
}
int readport(int *fd, unsigned char *result) {
int iIn=0;
iIn = read(*fd, result, bufsize);
tcflush(*fd, TCIFLUSH);
if (iIn < 0) {
if (errno == EAGAIN) {
//printf("SERIAL EAGAIN ERROR\n");
return 0;
} else {
//printf("SERIAL read error %d %s\n", errno, strerror(errno));
return 0;
}
}
return iIn;
}
int getbaud(int fd) {
struct termios termAttr;
int Speed = -1;
speed_t baudRate;
tcgetattr(fd, &termAttr);
/* Get the input speed. */
baudRate = cfgetispeed(&termAttr);
switch (baudRate) {
case B300: Speed = 300; break;
case B600: Speed = 600; break;
case B1200: Speed = 1200; break;
case B1800: Speed = 1800; break;
case B2400: Speed = 2400; break;
case B4800: Speed = 4800; break;
case B9600: Speed = 9600; break;
case B19200: Speed = 19200; break;
case B38400: Speed = 38400; break;
case B115200: Speed = 115200; break;
case B230400: Speed = 230400; break;
case B460800: Speed = 460800; break;
case B500000: Speed = 500000; break;
case B576000: Speed = 576000; break;
case B921600: Speed = 921600; break;
case B1000000:Speed = 1000000; break;
case B1152000:Speed = 1152000; break;
case B1500000:Speed = 1500000; break;
case B2000000:Speed = 2000000; break;
case B2500000:Speed = 2500000; break;
case B3000000:Speed = 3000000; break;
case B3500000:Speed = 3500000; break;
}
return Speed;
}
int initport(int fd,long baudrate,int flow_ctrl)
{
struct termios options;
memset(&options, 0 , sizeof(options));
if(ERROR == tcgetattr(fd, &options)) {
perror("tcgetattr: ");
return ERROR;
}
switch (baudrate) {
case 300: cfsetispeed(&options,B300);
cfsetospeed(&options,B300);
options.c_cflag |= B300 | CBAUD;
break;
case 600: cfsetispeed(&options,B600);
cfsetospeed(&options,B600);
options.c_cflag |= B600 | CBAUD;
break;
case 1200: cfsetispeed(&options,B1200);
cfsetospeed(&options,B1200);
options.c_cflag |= B1200 | CBAUD;
break;
case 1800: cfsetispeed(&options,B1800);
cfsetospeed(&options,B1800);
options.c_cflag |= B1800 | CBAUD;
break;
case 2400: cfsetispeed(&options,B2400);
cfsetospeed(&options,B2400);
options.c_cflag |= B2400 | CBAUD;
break;
case 4800: cfsetispeed(&options,B4800);
cfsetospeed(&options,B4800);
options.c_cflag |= B4800 | CBAUD;
break;
case 9600:
default: cfsetispeed(&options,B9600);
cfsetospeed(&options,B9600);
options.c_cflag |= B9600 | CBAUD;
break;
case 19200: cfsetispeed(&options,B19200);
cfsetospeed(&options,B19200);
options.c_cflag |= B19200 | CBAUD;
break;
case 38400: cfsetispeed(&options,B38400);
cfsetospeed(&options,B38400);
options.c_cflag |= B38400 | CBAUD;
break;
case 115200: cfsetispeed(&options,B115200);
cfsetospeed(&options,B115200);
options.c_cflag |= B115200 | CBAUDEX;
break;
case 230400: cfsetispeed(&options,B230400);
cfsetospeed(&options,B230400);
options.c_cflag |= B230400 | CBAUDEX;
break;
case 460800: cfsetispeed(&options,B460800);
cfsetospeed(&options,B460800);
options.c_cflag |= B460800 | CBAUDEX;
break;
case 500000: cfsetispeed(&options,B500000);
cfsetospeed(&options,B500000);
options.c_cflag |= B500000 | CBAUDEX;
break;
case 576000: cfsetispeed(&options,B576000);
cfsetospeed(&options,B576000);
options.c_cflag |= B576000 | CBAUDEX;
break;
case 921600: cfsetispeed(&options,B921600);
cfsetospeed(&options,B921600);
options.c_cflag |= B921600 | CBAUDEX;
break;
case 1000000: cfsetispeed(&options,B1000000);
cfsetospeed(&options,B1000000);
options.c_cflag |= B1000000 | CBAUDEX;
break;
case 1152000: cfsetispeed(&options,B1152000);
cfsetospeed(&options,B1152000);
options.c_cflag |= B1152000 | CBAUDEX;
break;
case 1500000: cfsetispeed(&options,B1500000);
cfsetospeed(&options,B1500000);
options.c_cflag |= B1500000 | CBAUDEX;
break;
case 2000000: cfsetispeed(&options,B2000000);
cfsetospeed(&options,B2000000);
options.c_cflag |= B2000000 | CBAUDEX;
break;
case 2500000: cfsetispeed(&options,B2500000);
cfsetospeed(&options,B2500000);
options.c_cflag |= B2500000 | CBAUDEX;
break;
case 3000000: cfsetispeed(&options,B3000000);
cfsetospeed(&options,B3000000);
options.c_cflag |= B3000000 | CBAUDEX;
break;
case 3500000: cfsetispeed(&options,B3500000);
cfsetospeed(&options,B3500000);
options.c_cflag |= B3500000 | CBAUDEX;
break;
}
/* Enable or Disable Hardware flow control. */
if(!flow_ctrl) {
options.c_cflag &= ~CRTSCTS;
//printf("Flow control disabled \n");
}
else {
options.c_cflag |= CRTSCTS;
//printf("Flow control enabled \n");
}
/* No Parity, 8N1. */
options.c_cflag &= ~PARENB; // No parity bit
options.c_cflag &= ~CSTOPB; // 1 stop bit
options.c_cflag &= ~CSIZE; // character size 8
options.c_cflag |= CS8 ;
/* Hardware Control Options - Set local mode and Enable receiver to receive characters */
options.c_cflag |= (CLOCAL | CREAD);
/* Terminal Control options */
/* - Disable signals. Disable canonical input processing. Disable echo. */
options.c_lflag &= ~(ICANON | IEXTEN | ECHO | ISIG); /* Line options - Raw input */
options.c_iflag &= ~(ICRNL | INPCK | ISTRIP | BRKINT | IXON | IXOFF | IXANY);
/* Output processing - Disable post processing of output. */
options.c_oflag &= ~OPOST; /* Output options - Raw output */
/* Control Characters - Min. no. of characters */
options.c_cc[VMIN] = 0;
/* Character/Packet timeouts. */
options.c_cc[VTIME] = 3;
if(ERROR == tcflush(fd,TCOFLUSH)) {
//printf("tcflush failed");
return ERROR;
}
if(ERROR == tcsetattr(fd, TCSANOW, &options)) {
//printf("Error: Couldn't configure Serial port ");
return ERROR;
}
/*
//printf("\n\n");
system("stty -F /dev/ttyS0 -a");
//printf("\n\n");
*/
return SUCCESS;
}
void signalHandler()
{
//printf("\n Closing device %s\n",UART_DEV_NAME);
close_port();
}
void close_port()
{
/* Destroy all synchronization primitives. */
pthread_mutex_destroy (¶ms.mutex);
pthread_cond_destroy (¶ms.done);
tcsetattr(ut.fd, TCSANOW, &oldtio);
if(tx_rx == 'r')
close(fd2);
else
close(fd1);
close(ut.fd);
exit(1);
}
int uart_sendevent_keyboard(int dev_kb, int type, int code, int value) {
int i;
int fd;
int ret;
int version;
struct input_event event;
if (ioctl(dev_kb, EVIOCGVERSION, &version)) {
return 1;
}
memset(&event, 0, sizeof(event));
event.type = type;
event.code = code;
event.value = value;
ret = write(dev_kb, &event, sizeof(event));
if(ret < sizeof(event)) {
return -1;
}
return 0;
}
int timeval_subtract (struct timeval * result, struct timeval * x, struct timeval * y) {
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec)/1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_usec - y->tv_usec > 1000000) {
int nsec = (x->tv_usec - y->tv_usec)/1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}
/* Compute the time remaining to wait.
tv_usec is certainly positive. */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;
/* Return 1 if result is negative. */
return x->tv_sec < y->tv_sec;
}
int read_ints (const char* file_name) {
int i = 50;
if(access(file_name, F_OK) == 0) {
FILE* file = fopen (file_name, "r");
fscanf (file, "%d", &i);
while (!feof (file)) {
fscanf (file, "%d", &i);
}
fclose (file);
}
return i * 1000;
}
void write_ints (const char* file_name, int value) {
FILE* file = fopen (file_name, "w+");
fprintf(file, "%d", value);
fclose (file);
}