上一篇文章做的那個(gè)稍微有點(diǎn)復(fù)雜了,還需要把板子的輸出拿回電腦處理再倒回去。這個(gè)就簡(jiǎn)單多了用法如下
建網(wǎng)站原本是網(wǎng)站策劃師、網(wǎng)絡(luò)程序員、網(wǎng)頁設(shè)計(jì)師等,應(yīng)用各種網(wǎng)絡(luò)程序開發(fā)技術(shù)和網(wǎng)頁設(shè)計(jì)技術(shù)配合操作的協(xié)同工作。創(chuàng)新互聯(lián)專業(yè)提供成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站、成都外貿(mào)網(wǎng)站建設(shè)公司,網(wǎng)頁設(shè)計(jì),網(wǎng)站制作(企業(yè)站、響應(yīng)式網(wǎng)站建設(shè)、電商門戶網(wǎng)站)等服務(wù),從網(wǎng)站深度策劃、搜索引擎友好度優(yōu)化到用戶體驗(yàn)的提升,我們力求做到極致!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字節(jié)的數(shù)據(jù)結(jié)構(gòu),添加了一個(gè)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)
//這是個(gè)計(jì)算時(shí)間差的函數(shù),對(duì)于一個(gè)timeval的數(shù)據(jù)結(jié)構(gòu),前面4字節(jié)秒,后面4字節(jié)微秒
//這個(gè)函數(shù)接受兩個(gè)這樣的結(jié)構(gòu),返回一個(gè)微秒單位的時(shí)間差{
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都打開準(zhǔn)備寫入 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));
//先讀取第一個(gè)event到event0中 timeval timetemp=event0.time;
//臨時(shí)存儲(chǔ)event中的時(shí)間,因?yàn)橥O(shè)備寫的時(shí)候,時(shí)間要清空 memset(&event0.time, 0, sizeof(struct timeval));
//清空時(shí)間 write(DeviceFile[event0.deviceID], &event0.time, sizeof(input_event));
//寫回設(shè)備 event0.time=timetemp;
//把剛剛保存的時(shí)間拿回來 while(read(fi,&event1,sizeof(myinputevent)))
//只要文件還能讀,就讀取下一個(gè)event到event1中 {
int sleeptime=timedif(event0.time,event1.time);
//計(jì)算event0和event1的時(shí)間差#ifdef DEBUG
std::cout<<"sleep"<<sleeptime<<std::endl;
#endif
usleep(sleeptime);
//進(jìn)行時(shí)間間隔 event0.time=event1.time;
//把event1的時(shí)間賦值給event0,這樣下次循環(huán)的時(shí)候繼續(xù)對(duì)比下一個(gè)時(shí)間差 memset(&event1.time, 0, sizeof(struct timeval));
//清空event1的時(shí)間 write(DeviceFile[event1.deviceID], &event1.time, sizeof(input_event));
//把event1寫回設(shè)備 }
for(int i=0;i<=9;++i)
{
if(DeviceFile[i]!=-1)
close(DeviceFile[i]);
//關(guān)閉所有設(shè)備
}
std::cout<<"Replay completed"<<std::endl;
}
record.cpp
#include "stdafx.h"#define DEBUG
inlinebool eventcmp(const myinputevent& a,const myinputevent& b)
//這個(gè)比較函數(shù)為了之后排序用,因?yàn)閮蓚€(gè)自定義的數(shù)據(jù)結(jié)構(gòu),你用標(biāo)準(zhǔn)排序函數(shù),排序肯定不知道你這倆結(jié)構(gòu)應(yīng)該怎么比大小
//定義了我的數(shù)據(jù)結(jié)構(gòu)之間如果做小于比較時(shí),時(shí)間小就算小。
//這樣就可以采用標(biāo)準(zhǔn)排序函數(shù)對(duì)事件進(jìn)行排序了。{
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;
//這里有個(gè)數(shù)組,用來添加所有錄制到的eventchar fn[200];
void afterstop(int x)
//按下ctrl+c和回車之后,錄制停止,做數(shù)據(jù)整理和保存工作
//主要是按時(shí)間順序?qū)κ录判?,然后保存{
#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;
//這是排序語句,對(duì)所有的錄制的event排序,排序時(shí)大小比較用eventcmp函數(shù),也就是根據(jù)時(shí)間先后排序啦
//因?yàn)橛械臅r(shí)候,設(shè)備的輸出并不按照時(shí)間順序,比如你按開機(jī)鍵,它涉及的不止一個(gè)event,有時(shí)會(huì)有微微的時(shí)間上的錯(cuò)序
//任何錯(cuò)序都會(huì)嚴(yán)重影響replay,所以這里必須排序啦,這里一定要stable_sort,也就是排序必須是穩(wěn)定的
//對(duì)于不穩(wěn)定的排序,有時(shí)兩個(gè)事件的時(shí)間完全相等,可能會(huì)使原來在后面的跑前面去 int f=open(fn,O_WRONLY | O_CREAT | O_TRUNC);
if(f==-1)
{
std::cout<<fn<<" cannot be opened!";
exit(0);
}
//打開一開始event record file中那個(gè)file文件進(jìn)行寫入 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也會(huì)收到命令從而終止adb shell,這樣達(dá)不到終止錄制的功能
//所以如果非要在windows中使用adb,就需要用這個(gè)命令busybox stty intr ^X,把板子的終止組合鍵注冊(cè)到ctrl-X上去
//這樣按ctrl-X再回車,就可以終止錄制 strcpy(fn,filename);
int f=open(fn,O_WRONLY | O_CREAT);
//先嘗試打開一下參數(shù)中的文件,若失敗就不繼續(xù)了 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);
//這里注冊(cè)了ctrl+c事件,這樣錄制過程中按下ctrl+c然后回車,可以執(zhí)行afterstop函數(shù)。 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是非阻塞。非阻塞的意思就是讀取的時(shí)候,如果設(shè)備里沒有,就返回-1。
//如果是阻塞的話,設(shè)備里沒有,read函數(shù)是不返回的,要等到有了才返回。
//所以阻塞肯定不行,因?yàn)槲矣幸欢言O(shè)備要循環(huán)讀取的,如果第一個(gè)設(shè)備沒數(shù)據(jù)就會(huì)卡住,后面的設(shè)備都讀不到。 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);
//不斷的循環(huán),把打開了的文件反復(fù)讀取,這里緩存區(qū)必須是16的倍數(shù),因?yàn)樯傻臄?shù)據(jù)是16字節(jié)的數(shù)據(jù)結(jié)構(gòu),這個(gè)基本結(jié)構(gòu)不能破壞了
//16字節(jié)的數(shù)據(jù)結(jié)構(gòu)中,前4字節(jié)是秒,然后4字節(jié)微秒,最后8字節(jié)是實(shí)際的設(shè)備發(fā)送的信息
//這里read會(huì)返回讀取到的字節(jié)數(shù)量,如果啥也沒讀到會(huì)返回-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里存儲(chǔ)了大量16字節(jié)的event,所以讓指針p是數(shù)據(jù)結(jié)構(gòu)指針,然后16字節(jié)16字節(jié)的挪動(dòng)
//我有一個(gè)自己的數(shù)據(jù)結(jié)構(gòu)叫myinputevent,比這個(gè)16字節(jié)來說,尾部添加了一個(gè)4字節(jié)的int,存儲(chǔ)設(shè)備的event號(hào)
//你可以在stdafx.h中看到這些數(shù)據(jù)結(jié)構(gòu)
//把那16字節(jié)的原封不動(dòng)的放到我的數(shù)據(jù)結(jié)構(gòu)中,再把我自己的設(shè)備號(hào)賦值,就完成了這一個(gè)事件的錄制。
//然后就存儲(chǔ)到AllRecordedEvent里面去。 }
}
}
}
}
新聞標(biāo)題:android按鍵精靈。C++編寫。-創(chuàng)新互聯(lián)
轉(zhuǎn)載來源:http://bm7419.com/article30/iiipo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、App設(shè)計(jì)、ChatGPT、響應(yīng)式網(wǎng)站、域名注冊(cè)、網(wǎng)站收錄
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容