#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <string.h>
#include <errno.h>
#include <linux/pci-doe.h>
#define DEV_PATH "/dev/avery_doe_chardev"
static const char *type_str(int t)
{
switch (t) {
case PCI_DOE_READ: return "READ";
case PCI_DOE_WRITE: return "WRITE";
default: return "UNKNOWN";
}
}
int main(void)
{
int fd;
struct pollfd pfd;
struct avery_pci_config_op op;
fd = open(DEV_PATH, O_RDWR);
if (fd < 0) {
perror("open");
return 1;
}
printf("Connected to %s\n", DEV_PATH);
pfd.fd = fd;
pfd.events = POLLIN;
while (1) {
int ret = poll(&pfd, 1, -1);
if (ret < 0) {
perror("poll");
break;
}
if (pfd.revents & POLLIN) {
ssize_t n = read(fd, &op, sizeof(op));
if (n < 0) {
perror("read");
break;
}
printf("REQ: type=%s offset=0x%x value=0x%x\n",
type_str(op.type), op.offset, op.value);
/* --- emulate remote root complex --- */
if (op.type == PCI_DOE_READ) {
op.value = 0x12345678; /* fake read value */
op.status = 0;
}
if (op.type == PCI_DOE_WRITE) {
printf("WRITE received value=0x%x\n", op.value);
op.status = 0;
}
if (write(fd, &op, sizeof(op)) < 0) {
perror("write");
break;
}
printf("RESP sent\n");
}
}
close(fd);
return 0;
}