1// SPDX-License-Identifier: GPL-2.0-only
2/* Counter - example userspace application
3 *
4 * The userspace application opens /dev/counter0, configures the
5 * COUNTER_EVENT_INDEX event channel 0 to gather Count 0 count and Count
6 * 1 count, and prints out the data as it becomes available on the
7 * character device node.
8 *
9 * Copyright (C) 2021 William Breathitt Gray
10 */
11#include <errno.h>
12#include <fcntl.h>
13#include <linux/counter.h>
14#include <stdio.h>
15#include <string.h>
16#include <sys/ioctl.h>
17#include <unistd.h>
18
19static struct counter_watch watches[2] = {
20	{
21		/* Component data: Count 0 count */
22		.component.type = COUNTER_COMPONENT_COUNT,
23		.component.scope = COUNTER_SCOPE_COUNT,
24		.component.parent = 0,
25		/* Event type: Index */
26		.event = COUNTER_EVENT_INDEX,
27		/* Device event channel 0 */
28		.channel = 0,
29	},
30	{
31		/* Component data: Count 1 count */
32		.component.type = COUNTER_COMPONENT_COUNT,
33		.component.scope = COUNTER_SCOPE_COUNT,
34		.component.parent = 1,
35		/* Event type: Index */
36		.event = COUNTER_EVENT_INDEX,
37		/* Device event channel 0 */
38		.channel = 0,
39	},
40};
41
42int main(void)
43{
44	int fd;
45	int ret;
46	int i;
47	struct counter_event event_data[2];
48
49	fd = open("/dev/counter0", O_RDWR);
50	if (fd == -1) {
51		perror("Unable to open /dev/counter0");
52		return 1;
53	}
54
55	for (i = 0; i < 2; i++) {
56		ret = ioctl(fd, COUNTER_ADD_WATCH_IOCTL, watches + i);
57		if (ret == -1) {
58			fprintf(stderr, "Error adding watches[%d]: %s\n", i,
59				strerror(errno));
60			return 1;
61		}
62	}
63	ret = ioctl(fd, COUNTER_ENABLE_EVENTS_IOCTL);
64	if (ret == -1) {
65		perror("Error enabling events");
66		return 1;
67	}
68
69	for (;;) {
70		ret = read(fd, event_data, sizeof(event_data));
71		if (ret == -1) {
72			perror("Failed to read event data");
73			return 1;
74		}
75
76		if (ret != sizeof(event_data)) {
77			fprintf(stderr, "Failed to read event data\n");
78			return -EIO;
79		}
80
81		printf("Timestamp 0: %llu\tCount 0: %llu\n"
82		       "Error Message 0: %s\n"
83		       "Timestamp 1: %llu\tCount 1: %llu\n"
84		       "Error Message 1: %s\n",
85		       event_data[0].timestamp, event_data[0].value,
86		       strerror(event_data[0].status),
87		       event_data[1].timestamp, event_data[1].value,
88		       strerror(event_data[1].status));
89	}
90
91	return 0;
92}
93