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 19 static 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 42 int 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