上一篇文章做的那個稍微有點復雜了,還需要把板子的輸出拿回電腦處理再倒回去。這個就簡單多了用法如下
建網站原本是網站策劃師、網絡程序員、網頁設計師等,應用各種網絡程序開發技術和網頁設計技術配合操作的協同工作。創新互聯專業提供成都網站設計、做網站、成都外貿網站建設公司,網頁設計,網站制作(企業站、響應式網站建設、電商門戶網站)等服務,從網站深度策劃、搜索引擎友好度優化到用戶體驗的提升,我們力求做到極致!usage:
event record /path/file1
event replay /path/file1
給我女友寫的程序直接搬過來了,所以注釋有些冗余。
"stdafx.h"
#include <sys/types.h>
#include<sys/stat.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdint.h>
#include<fcntl.h>
#include<sys/ioctl.h>
#include<errno.h>
#include<asm/types.h>
#include<unistd.h>
#include<iostream>
#include<vector>
struct input_event {
timeval time;
__u16 type;
__u16 code;
__s32 value;
};
struct myinputevent:public input_event
//繼承了16字節的數據結構,添加了一個deviceID{
int deviceID;
};
main.cpp
#include "stdafx.h"void record(char* filename);
void replay(char* filename);
int main(int argc, char *argv[])
{
if(argc!=3 || (strcmp(argv[1],"record") & strcmp(argv[1],"replay")))
{
std::cout<<
"usage:"<<std::endl<<
"event record /path/file1"<<std::endl<<
"event replay /path/file1"<<std::endl;
return 0;
}
if(!strcmp(argv[1],"record"))
record(argv[2]);
else
replay(argv[2]);
return 0;
}
replay.cpp
#include "stdafx.h"http://#define DEBUGint timedif(timeval& a,timeval& b)
//這是個計算時間差的函數,對于一個timeval的數據結構,前面4字節秒,后面4字節微秒
//這個函數接受兩個這樣的結構,返回一個微秒單位的時間差{
return (b.tv_sec-a.tv_sec)*1000000+(b.tv_usec-a.tv_usec);
}
void replay(char* filename)
{
int fi = open(filename,O_RDONLY);
if(fi==-1)
{
std::cout<<filename<<" cannot be opened"<<std::endl;
exit(0);
}
char dev[40]="/dev/input/eventX";
int DeviceFile[10];
for(char i='0';i<='9';++i)
{
dev[16]=i;
int f=open(dev,O_RDWR);
//把所有的event都打開準備寫入 DeviceFile[i-'0']=f;
//把句柄保存下來,如果打不開的話f值是-1#ifdef DEBUG
if(f!=-1)
std::cout<<"Device opened:"<<i<<std::endl;
#endif
}
myinputevent event0,event1;
read(fi,&event0,sizeof(myinputevent));
//先讀取第一個event到event0中 timeval timetemp=event0.time;
//臨時存儲event中的時間,因為往設備寫的時候,時間要清空 memset(&event0.time, 0, sizeof(struct timeval));
//清空時間 write(DeviceFile[event0.deviceID], &event0.time, sizeof(input_event));
//寫回設備 event0.time=timetemp;
//把剛剛保存的時間拿回來 while(read(fi,&event1,sizeof(myinputevent)))
//只要文件還能讀,就讀取下一個event到event1中 {
int sleeptime=timedif(event0.time,event1.time);
//計算event0和event1的時間差#ifdef DEBUG
std::cout<<"sleep"<<sleeptime<<std::endl;
#endif
usleep(sleeptime);
//進行時間間隔 event0.time=event1.time;
//把event1的時間賦值給event0,這樣下次循環的時候繼續對比下一個時間差 memset(&event1.time, 0, sizeof(struct timeval));
//清空event1的時間 write(DeviceFile[event1.deviceID], &event1.time, sizeof(input_event));
//把event1寫回設備 }
for(int i=0;i<=9;++i)
{
if(DeviceFile[i]!=-1)
close(DeviceFile[i]);
//關閉所有設備
}
std::cout<<"Replay completed"<<std::endl;
}
record.cpp
#include "stdafx.h"#define DEBUG
inlinebool eventcmp(const myinputevent& a,const myinputevent& b)
//這個比較函數為了之后排序用,因為兩個自定義的數據結構,你用標準排序函數,排序肯定不知道你這倆結構應該怎么比大小
//定義了我的數據結構之間如果做小于比較時,時間小就算小。
//這樣就可以采用標準排序函數對事件進行排序了。{
if(a.time.tv_sec<b.time.tv_sec)
return 1;
if(a.time.tv_sec>b.time.tv_sec)
return 0;
if(a.time.tv_usec<b.time.tv_usec)
return 1;
else return 0;
}
std::vector<myinputevent> AllRecordedEvent;
//這里有個數組,用來添加所有錄制到的eventchar fn[200];
void afterstop(int x)
//按下ctrl+c和回車之后,錄制停止,做數據整理和保存工作
//主要是按時間順序對事件排序,然后保存{
#ifdef DEBUG
std::cout<<"Recorded events:"<<AllRecordedEvent.size()<<std::endl;
#endif
std::cout<<"Sorting & saving..."<<std::endl;
std::stable_sort(AllRecordedEvent.begin(),AllRecordedEvent.end(),eventcmp);
std::cout<<"Sort completed"<<std::endl;
//這是排序語句,對所有的錄制的event排序,排序時大小比較用eventcmp函數,也就是根據時間先后排序啦
//因為有的時候,設備的輸出并不按照時間順序,比如你按開機鍵,它涉及的不止一個event,有時會有微微的時間上的錯序
//任何錯序都會嚴重影響replay,所以這里必須排序啦,這里一定要stable_sort,也就是排序必須是穩定的
//對于不穩定的排序,有時兩個事件的時間完全相等,可能會使原來在后面的跑前面去 int f=open(fn,O_WRONLY | O_CREAT | O_TRUNC);
if(f==-1)
{
std::cout<<fn<<" cannot be opened!";
exit(0);
}
//打開一開始event record file中那個file文件進行寫入 for(unsigned int i=0;i<AllRecordedEvent.size();++i)
{
write(f,&AllRecordedEvent[i],sizeof(myinputevent));
}
close(f);
std::cout<<"Record completed. Filename:"<<fn<<std::endl;
exit(0);
}
void record(char* filename)
{
std::cout<<"If using windows adb, you have to "busybox stty intr ^X" to change the INTR from Ctrl-C to Ctrl-X"<<std::endl;
std::cout<<"And the stop recording command will be ctrl-X."<<std::endl
<<"If using linux adb, you are fine."<<std::endl;
//注意如果用windows中的adb,按下ctrl+c之后windows的shell也會收到命令從而終止adb shell,這樣達不到終止錄制的功能
//所以如果非要在windows中使用adb,就需要用這個命令busybox stty intr ^X,把板子的終止組合鍵注冊到ctrl-X上去
//這樣按ctrl-X再回車,就可以終止錄制 strcpy(fn,filename);
int f=open(fn,O_WRONLY | O_CREAT);
//先嘗試打開一下參數中的文件,若失敗就不繼續了 if(f==-1)
{
std::cout<<fn<<" cannot be opened!";
exit(0);
}
close(f);
struct sigaction act;
act.sa_handler=afterstop;
sigemptyset(&act.sa_mask);
act.sa_flags= 0;
sigaction(SIGINT,&act, NULL);
//這里注冊了ctrl+c事件,這樣錄制過程中按下ctrl+c然后回車,可以執行afterstop函數。 char dev[40]="/dev/input/eventX";
int DeviceFile[10];
for(char i='0';i<='9';++i)
{
dev[16]=i;
int f=open(dev,O_RDONLY | O_NONBLOCK);
//把所有的event都打開,這樣保證能包括鍵盤和屏幕
//這里O_RDONLY是只讀,O_NONBLOCK是非阻塞。非阻塞的意思就是讀取的時候,如果設備里沒有,就返回-1。
//如果是阻塞的話,設備里沒有,read函數是不返回的,要等到有了才返回。
//所以阻塞肯定不行,因為我有一堆設備要循環讀取的,如果第一個設備沒數據就會卡住,后面的設備都讀不到。 DeviceFile[i-'0']=f;
//把句柄保存下來,如果打不開的話f值是-1#ifdef DEBUG
if(f!=-1)
std::cout<<"Device opened:"<<i<<std::endl;
#endif
}
char buffer[2048];
std::cout<<"Recording started, press Ctrl+C then press ENTER to stop recording"<<std::endl;
while(1)
{
for(int i=0;i<10;++i)
{
if(DeviceFile[i]==-1)
continue;
int ReadSize=read(DeviceFile[i],buffer,2048);
//不斷的循環,把打開了的文件反復讀取,這里緩存區必須是16的倍數,因為生成的數據是16字節的數據結構,這個基本結構不能破壞了
//16字節的數據結構中,前4字節是秒,然后4字節微秒,最后8字節是實際的設備發送的信息
//這里read會返回讀取到的字節數量,如果啥也沒讀到會返回-1 if(ReadSize!=-1)
{
#ifdef DEBUG
std::cout<<"device"<<i<<"read"<<ReadSize<<std::endl;
#endif for(input_event *p=(input_event*)buffer;(char*)p<buffer+ReadSize;++p)
{
myinputevent my;
my.code=p->code;
my.type=p->type;
my.value=p->value;
my.time=p->time;
my.deviceID=i;
AllRecordedEvent.push_back(my);
//這里可能難理解,buffer里存儲了大量16字節的event,所以讓指針p是數據結構指針,然后16字節16字節的挪動
//我有一個自己的數據結構叫myinputevent,比這個16字節來說,尾部添加了一個4字節的int,存儲設備的event號
//你可以在stdafx.h中看到這些數據結構
//把那16字節的原封不動的放到我的數據結構中,再把我自己的設備號賦值,就完成了這一個事件的錄制。
//然后就存儲到AllRecordedEvent里面去。 }
}
}
}
}
新聞標題:android按鍵精靈。C++編寫。-創新互聯
轉載來源:http://vcdvsql.cn/article30/iiipo.html
成都網站建設公司_創新互聯,為您提供服務器托管、App設計、ChatGPT、響應式網站、域名注冊、網站收錄
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯