1 /* The license of this program follows the GNU license recommendations at */
2 /* https://www.gnu.org/licenses/license-recommendations.en.html. They */
3 /* recommend that small programs, < 300 lines, be licensed under the */
4 /* Apache License 2.0. This file contains or is part of one or more small */
7 /* Copyright (C) 2016 Ian Kelling */
9 /* Licensed under the Apache License, Version 2.0 (the "License"); */
10 /* you may not use this file except in compliance with the License. */
11 /* You may obtain a copy of the License at */
13 /* http://www.apache.org/licenses/LICENSE-2.0 */
15 /* Unless required by applicable law or agreed to in writing, software */
16 /* distributed under the License is distributed on an "AS IS" BASIS, */
17 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
18 /* See the License for the specific language governing permissions and */
19 /* limitations under the License. */
22 #include <linux/input.h>
31 typedef struct event_s
{
36 unsigned long long prev_time
;
46 int main(int argc
, char *argv
[]) {
49 event_t events
[EVENTS
];
53 while((optch
= getopt(argc
, argv
, "hn")) != -1) {
56 printf("Usage: %s [-n|-h]\n", argv
[0]);
57 printf("-n nonverbose\n");
68 printf("%s must be used as superuser\n", argv
[0]);
72 signal(SIGINT
, sigint
);
74 printf("Press CTRL-C to exit.\n\n");
76 memset(events
, 0, sizeof(events
));
79 for(i
= 0; i
< EVENTS
; i
++) {
80 // 20 is needed for 3 digits of event devs under the expected format, but
81 // just give it some extra in case.
84 sprintf(device
, "/dev/input/event%i", i
);
85 events
[i
].fd
= open(device
, O_RDONLY
);
87 if(events
[i
].fd
!= -1) {
89 ioctl(events
[i
].fd
, EVIOCGNAME(sizeof(events
[i
].name
)), events
[i
].name
);
90 if(verbose
) printf("event%i: %s\n", i
, events
[i
].name
);
99 for(i
= 0; i
<= max_event
; i
++) {
100 if(events
[i
].fd
!= -1) {
101 FD_SET(events
[i
].fd
, &set
);
105 if(select(FD_SETSIZE
, &set
, NULL
, NULL
, NULL
) <= 0) {
110 struct input_event event
;
112 for(i
= 0; i
<= max_event
; i
++) {
113 if(events
[i
].fd
== -1 || !FD_ISSET(events
[i
].fd
, &set
)) {
117 bytes
= read(events
[i
].fd
, &event
, sizeof(event
));
119 if(bytes
!= sizeof(event
)) {
123 if(event
.type
== EV_REL
|| event
.type
== EV_ABS
) {
124 unsigned long long time
, timediff
;
127 time
= (unsigned long long)event
.time
.tv_sec
* 1000000ULL;
128 time
+= (unsigned long long)event
.time
.tv_usec
;
130 timediff
= time
- events
[i
].prev_time
;
133 hz
= 1000000ULL / timediff
;
139 events
[i
].hz
[events
[i
].count
& (HZ_LIST
- 1)] = hz
;
143 maxavg
= (events
[i
].count
> HZ_LIST
) ? HZ_LIST
: events
[i
].count
;
145 for(j
= 0; j
< maxavg
; j
++) {
146 events
[i
].avghz
+= events
[i
].hz
[j
];
149 events
[i
].avghz
/= maxavg
;
151 if(verbose
) printf("%s: Latest % 5iHz, Average % 5iHz\n", events
[i
].name
, hz
, events
[i
].avghz
);
154 events
[i
].prev_time
= time
;
159 for(i
= 0; i
< max_event
; i
++) {
160 if(events
[i
].fd
!= -1) {
161 if (events
[i
].avghz
!= 0) {
162 printf("\nAverage for %s: % 5iHz\n", events
[i
].name
, events
[i
].avghz
);