Загрузка данных
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <signal.h>
#include <errno.h>
/* Constants matching the M7 core definitions */
#define SRTM_SERVICE_CAMERA_ID (0x7F)
#define SRTM_VERSION (0x01)
#define SRTM_CMD_CAMERA_ON (0x01)
#define SRTM_CMD_CAMERA_OFF (0x02)
/* SRTM Message Types */
#define SRTM_TYPE_REQUEST (0x00)
#define SRTM_TYPE_RESPONSE (0x01)
/* Return codes for response packets (checked by M7 as asyncReq->retCode) */
#define SRTM_CAMERA_RETURN_CODE_SUCCESS (0x00)
#define SRTM_CAMERA_RETURN_CODE_ERROR (0x01)
/* Macro for poll timeout in milliseconds (-1 means block indefinitely) */
#define POLL_TIMEOUT_MS (1000)
/* Global flag for graceful daemon shutdown on signals */
static volatile sig_atomic_t keep_running = 1;
/* Standard SRTM packet header layout */
struct srtm_header {
uint8_t category;
uint8_t version;
uint8_t command;
uint8_t type;
} __attribute__((packed));
/* Incoming request packet structure from M7 */
struct camera_request {
struct srtm_header head;
uint8_t camera_id;
} __attribute__((packed));
/* Outgoing response packet structure to unblock M7 sync execution */
struct camera_response {
struct srtm_header head;
uint8_t ret_code;
} __attribute__((packed));
/* Signal handler for graceful termination */
void signal_handler(int signum) {
(void)signum;
keep_running = 0;
}
/* Handler for turning the selected camera stream ON */
void handle_camera_on(uint8_t camera_id) {
printf("[Linux] Received command: TURN ON camera ID: %d\n", camera_id);
}
/* Handler for turning the selected camera stream OFF */
void handle_camera_off(uint8_t camera_id) {
printf("[Linux] Received command: TURN OFF camera ID: %d\n", camera_id);
}
int main(int argc, char *argv[]) {
const char *device = "/dev/rpmsg0";
struct pollfd fds[1];
int ret;
if (argc > 1) {
device = argv[1];
}
/* Register signal handlers for clean exit */
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = signal_handler;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
/* Open the RPMSG device in non-blocking mode */
int fd = open(device, O_RDWR | O_NONBLOCK);
if (fd < 0) {
perror("Failed to open RPMSG device channel");
return EXIT_FAILURE;
}
/* Configure the poll structural array for monitoring incoming data */
fds[0].fd = fd;
fds[0].events = POLLIN; /* Monitor for read events */
printf("SRTM Camera Daemon (Poll-based) initialized on %s. Monitoring requests...\n", device);
uint8_t rx_buffer[512];
while (keep_running) {
/* Wait for data on the RPMSG descriptor with a defined timeout */
ret = poll(fds, 1, POLL_TIMEOUT_MS);
if (ret < 0) {
if (errno == EINTR) {
/* Poll was interrupted by a signal, loop back and check keep_running */
continue;
}
perror("Poll system call execution failed");
break;
}
if (ret == 0) {
/* Timeout reached with no data; perfect place for periodic background tasks */
continue;
}
/* Verify if the observed descriptor reports readable incoming payload data */
if (fds[0].revents & POLLIN) {
ssize_t bytes_read = read(fd, rx_buffer, sizeof(rx_buffer));
if (bytes_read < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
continue; /* No actual data available, false event trigger */
}
perror("Error while reading data from the RPMSG channel");
break;
}
if (bytes_read < (ssize_t)sizeof(struct srtm_header)) {
fprintf(stderr, "Received a malformed packet (too short: %ld bytes)\n", bytes_read);
continue;
}
struct camera_request *req = (struct camera_request *)rx_buffer;
/* Verify the service category and check if the packet type is an active Request */
if (req->head.category == SRTM_SERVICE_CAMERA_ID && req->head.type == SRTM_TYPE_REQUEST) {
uint8_t cam_id = req->camera_id;
uint8_t cmd = req->head.command;
uint8_t status_to_send = SRTM_CAMERA_RETURN_CODE_SUCCESS;
/* Parse and route command IDs */
if (cmd == SRTM_CMD_CAMERA_ON) {
handle_camera_on(cam_id);
} else if (cmd == SRTM_CMD_CAMERA_OFF) {
handle_camera_off(cam_id);
} else {
fprintf(stderr, "Unrecognized Camera Command ID: 0x%02X\n", cmd);
status_to_send = SRTM_CAMERA_RETURN_CODE_ERROR;
}
/* Construct the mandatory sync Response packet to avoid M7 timeout loops */
struct camera_response resp;
resp.head.category = SRTM_SERVICE_CAMERA_ID;
resp.head.version = SRTM_VERSION;
resp.head.command = cmd;
resp.head.type = SRTM_TYPE_RESPONSE;
resp.ret_code = status_to_send;
/* Transmit the response payload back to the M7 endpoint link */
ssize_t bytes_written = write(fd, &resp, sizeof(resp));
if (bytes_written < 0) {
perror("Failed to transmit synchronization response to M7");
}
}
}
/* Intercept error conditions reported on the monitored file descriptor */
if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
fprintf(stderr, "RPMSG file descriptor reported an error or hangup event\n");
break;
}
}
printf("Shutting down SRTM Camera Daemon cleanly...\n");
close(fd);
return EXIT_SUCCESS;
}