brintos

brintos / linux-shallow public Read only

0
0
Text · 3.9 KiB · 655b6c9 Raw
164 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Dell AIO Serial Backlight board emulator for testing4 * the Linux dell-uart-backlight driver.5 *6 * Copyright (C) 2024 Hans de Goede <hansg@kernel.org>7 */8#include <errno.h>9#include <fcntl.h>10#include <signal.h>11#include <stdio.h>12#include <stdlib.h>13#include <string.h>14#include <sys/ioctl.h>15#include <sys/stat.h>16#include <sys/types.h>17#include <sys/un.h>18#include <termios.h>19#include <unistd.h>20 21int serial_fd;22int brightness = 50;23 24static unsigned char dell_uart_checksum(unsigned char *buf, int len)25{26	unsigned char val = 0;27 28	while (len-- > 0)29		val += buf[len];30 31	return val ^ 0xff;32}33 34/* read() will return -1 on SIGINT / SIGTERM causing the mainloop to cleanly exit */35void signalhdlr(int signum)36{37}38 39int main(int argc, char *argv[])40{41	struct sigaction sigact = { .sa_handler = signalhdlr };42	unsigned char buf[4], csum, response[32];43	const char *version_str = "PHI23-V321";44	struct termios tty, saved_tty;45	int ret, idx, len = 0;46 47	if (argc != 2) {48		fprintf(stderr, "Invalid or missing arguments\n");49		fprintf(stderr, "Usage: %s <serial-port>\n", argv[0]);50		return 1;51	}52 53	serial_fd = open(argv[1], O_RDWR | O_NOCTTY);54	if (serial_fd == -1) {55		fprintf(stderr, "Error opening %s: %s\n", argv[1], strerror(errno));56		return 1;57	}58 59	ret = tcgetattr(serial_fd, &tty);60	if (ret == -1) {61		fprintf(stderr, "Error getting tcattr: %s\n", strerror(errno));62		goto out_close;63	}64	saved_tty = tty;65 66	cfsetspeed(&tty, 9600);67	cfmakeraw(&tty);68	tty.c_cflag &= ~CSTOPB;69	tty.c_cflag &= ~CRTSCTS;70	tty.c_cflag |= CLOCAL | CREAD;71 72	ret = tcsetattr(serial_fd, TCSANOW, &tty);73	if (ret == -1) {74		fprintf(stderr, "Error setting tcattr: %s\n", strerror(errno));75		goto out_restore;76	}77 78	sigaction(SIGINT, &sigact, 0);79	sigaction(SIGTERM, &sigact, 0);80 81	idx = 0;82	while (read(serial_fd, &buf[idx], 1) == 1) {83		if (idx == 0) {84			switch (buf[0]) {85			/* 3 MSB bits: cmd-len + 01010 SOF marker */86			case 0x6a: len = 3; break;87			case 0x8a: len = 4; break;88			default:89				fprintf(stderr, "Error unexpected first byte: 0x%02x\n", buf[0]);90				continue; /* Try to sync up with sender */91			}92		}93 94		/* Process msg when len bytes have been received */95		if (idx != (len - 1)) {96			idx++;97			continue;98		}99 100		/* Reset idx for next command */101		idx = 0;102 103		csum = dell_uart_checksum(buf, len - 1);104		if (buf[len - 1] != csum) {105			fprintf(stderr, "Error checksum mismatch got 0x%02x expected 0x%02x\n",106				buf[len - 1], csum);107			continue;108		}109 110		switch ((buf[0] << 8) | buf[1]) {111		case 0x6a06: /* cmd = 0x06, get version */112			len = strlen(version_str);113			strcpy((char *)&response[2], version_str);114			printf("Get version, reply: %s\n", version_str);115			break;116		case 0x8a0b: /* cmd = 0x0b, set brightness */117			if (buf[2] > 100) {118				fprintf(stderr, "Error invalid brightness param: %d\n", buf[2]);119				continue;120			}121 122			len = 0;123			brightness = buf[2];124			printf("Set brightness %d\n", brightness);125			break;126		case 0x6a0c: /* cmd = 0x0c, get brightness */127			len = 1;128			response[2] = brightness;129			printf("Get brightness, reply: %d\n", brightness);130			break;131		case 0x8a0e: /* cmd = 0x0e, set backlight power */132			if (buf[2] != 0 && buf[2] != 1) {133				fprintf(stderr, "Error invalid set power param: %d\n", buf[2]);134				continue;135			}136 137			len = 0;138			printf("Set power %d\n", buf[2]);139			break;140		default:141			fprintf(stderr, "Error unknown cmd 0x%04x\n",142				(buf[0] << 8) | buf[1]);143			continue;144		}145 146		/* Respond with <total-len> <cmd> <data...> <csum> */147		response[0] = len + 3; /* response length in bytes */148		response[1] = buf[1];  /* ack cmd */149		csum = dell_uart_checksum(response, len + 2);150		response[len + 2] = csum;151		ret = write(serial_fd, response, response[0]);152		if (ret != (response[0]))153			fprintf(stderr, "Error writing %d bytes: %d\n",154				response[0], ret);155	}156 157	ret = 0;158out_restore:159	tcsetattr(serial_fd, TCSANOW, &saved_tty);160out_close:161	close(serial_fd);162	return ret;163}164