mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-19 12:12:16 +00:00
misc: totally remove misc folder
misc now has a new home: https://github.com/intel/ioc-cbc-tools. The "Execstop" patch will be synced to new git tree soon. ioc-cbc-tools was just added to Clear Linux, and will be added to software-defined-cockpit bundle after this patch merged. Merging this patch may cause some IOC releated feature block until we get a new Clear Linux release. This is the switch window ... Signed-off-by: Alek Du <alek.du@intel.com>
This commit is contained in:
parent
49322ac002
commit
2a656812df
14
Makefile
14
Makefile
@ -9,14 +9,13 @@ ROOT_OUT := $(shell mkdir -p $(O);cd $(O);pwd)
|
|||||||
HV_OUT := $(ROOT_OUT)/hypervisor
|
HV_OUT := $(ROOT_OUT)/hypervisor
|
||||||
DM_OUT := $(ROOT_OUT)/devicemodel
|
DM_OUT := $(ROOT_OUT)/devicemodel
|
||||||
TOOLS_OUT := $(ROOT_OUT)/tools
|
TOOLS_OUT := $(ROOT_OUT)/tools
|
||||||
MISC_OUT := $(ROOT_OUT)/misc
|
|
||||||
DOC_OUT := $(ROOT_OUT)/doc
|
DOC_OUT := $(ROOT_OUT)/doc
|
||||||
BUILD_VERSION ?=
|
BUILD_VERSION ?=
|
||||||
BUILD_TAG ?=
|
BUILD_TAG ?=
|
||||||
export TOOLS_OUT
|
export TOOLS_OUT
|
||||||
|
|
||||||
.PHONY: all hypervisor devicemodel tools misc doc
|
.PHONY: all hypervisor devicemodel tools doc
|
||||||
all: hypervisor devicemodel tools misc
|
all: hypervisor devicemodel tools
|
||||||
|
|
||||||
hypervisor:
|
hypervisor:
|
||||||
make -C $(T)/hypervisor HV_OBJDIR=$(HV_OUT) PLATFORM=$(PLATFORM) RELEASE=$(RELEASE) clean
|
make -C $(T)/hypervisor HV_OBJDIR=$(HV_OUT) PLATFORM=$(PLATFORM) RELEASE=$(RELEASE) clean
|
||||||
@ -35,10 +34,6 @@ tools:
|
|||||||
mkdir -p $(TOOLS_OUT)
|
mkdir -p $(TOOLS_OUT)
|
||||||
make -C $(T)/tools OUT_DIR=$(TOOLS_OUT) RELEASE=$(RELEASE)
|
make -C $(T)/tools OUT_DIR=$(TOOLS_OUT) RELEASE=$(RELEASE)
|
||||||
|
|
||||||
misc: tools
|
|
||||||
mkdir -p $(MISC_OUT)
|
|
||||||
make -C $(T)/misc OUT_DIR=$(MISC_OUT)
|
|
||||||
|
|
||||||
doc:
|
doc:
|
||||||
make -C $(T)/doc html BUILDDIR=$(DOC_OUT)
|
make -C $(T)/doc html BUILDDIR=$(DOC_OUT)
|
||||||
|
|
||||||
@ -49,7 +44,7 @@ clean:
|
|||||||
rm -rf $(ROOT_OUT)
|
rm -rf $(ROOT_OUT)
|
||||||
|
|
||||||
.PHONY: install
|
.PHONY: install
|
||||||
install: hypervisor-install devicemodel-install tools-install misc-install
|
install: hypervisor-install devicemodel-install tools-install
|
||||||
|
|
||||||
hypervisor-install:
|
hypervisor-install:
|
||||||
make -C $(T)/hypervisor HV_OBJDIR=$(HV_OUT) PLATFORM=$(PLATFORM) RELEASE=$(RELEASE) install
|
make -C $(T)/hypervisor HV_OBJDIR=$(HV_OUT) PLATFORM=$(PLATFORM) RELEASE=$(RELEASE) install
|
||||||
@ -62,6 +57,3 @@ devicemodel-install:
|
|||||||
|
|
||||||
tools-install:
|
tools-install:
|
||||||
make -C $(T)/tools OUT_DIR=$(TOOLS_OUT) install
|
make -C $(T)/tools OUT_DIR=$(TOOLS_OUT) install
|
||||||
|
|
||||||
misc-install:
|
|
||||||
make -C $(T)/misc OUT_DIR=$(MISC_OUT) install
|
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
T := $(CURDIR)
|
|
||||||
|
|
||||||
.PHONY: all cbc_lifecycle cbc_attach
|
|
||||||
all: cbc_lifecycle cbc_attach
|
|
||||||
|
|
||||||
cbc_lifecycle:
|
|
||||||
make -C $(T)/cbc_lifecycle OUT_DIR=$(OUT_DIR)
|
|
||||||
cbc_attach:
|
|
||||||
make -C $(T)/cbc_attach OUT_DIR=$(OUT_DIR)
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
clean:
|
|
||||||
make -C $(T)/cbc_lifecycle clean
|
|
||||||
make -C $(T)/cbc_attach clean
|
|
||||||
rm -rf $(OUT_DIR)
|
|
||||||
|
|
||||||
.PHONY: install
|
|
||||||
install: cbc_lifecycle-install cbc_attach-install
|
|
||||||
|
|
||||||
cbc_lifecycle-install:
|
|
||||||
make -C $(T)/cbc_lifecycle OUT_DIR=$(OUT_DIR) install
|
|
||||||
|
|
||||||
cbc_attach-install:
|
|
||||||
make -C $(T)/cbc_attach OUT_DIR=$(OUT_DIR) install
|
|
@ -1,13 +0,0 @@
|
|||||||
OUT_DIR ?= .
|
|
||||||
|
|
||||||
all:
|
|
||||||
gcc -o $(OUT_DIR)/cbc_attach cbc_attach.c
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf $(OUT_DIR)/cbc_attach
|
|
||||||
|
|
||||||
install: $(OUT_DIR)/cbc_attach cbc_attach.service
|
|
||||||
install -d $(DESTDIR)/usr/bin
|
|
||||||
install -t $(DESTDIR)/usr/bin $(OUT_DIR)/cbc_attach
|
|
||||||
install -d $(DESTDIR)/usr/lib/systemd/system/
|
|
||||||
install -p -m 0644 cbc_attach.service $(DESTDIR)/usr/lib/systemd/system/
|
|
@ -1,412 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) <2018> Intel Corporation
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* The cbc_attach tool is a tool similar to ldattach or slcand.
|
|
||||||
* It configures the given serial line for cbc and loads the cbc
|
|
||||||
* line discipline. On exit it switches the line discipline to n_tty.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <termios.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#ifndef ANDROID_BUILD
|
|
||||||
#define APP_INFO "v" VERSION_STRING
|
|
||||||
#else
|
|
||||||
#define APP_INFO ""
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <linux/tty.h>
|
|
||||||
#ifndef N_CBCCORE
|
|
||||||
#define N_CBCCORE 27
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define VERSION_MAJOR 4
|
|
||||||
#define VERSION_MINOR 2
|
|
||||||
#define VERSION_REVISON 2
|
|
||||||
|
|
||||||
#define VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}"
|
|
||||||
|
|
||||||
char const *const cDEFAULT_DEVICE_NAME = "/dev/ttyS1";
|
|
||||||
|
|
||||||
static struct option longOpts[] = {
|
|
||||||
{"help", no_argument, 0, 'h'},
|
|
||||||
{"baudrate", required_argument, 0, 'b'},
|
|
||||||
{"hardwareFlowControl", no_argument, 0, 'f'},
|
|
||||||
{"min-receive-bytes", required_argument, 0, 'm'},
|
|
||||||
{0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
/* granularity is currently a module parameter -> not set from this tool. */
|
|
||||||
|
|
||||||
void printMainUsage(void)
|
|
||||||
{
|
|
||||||
printf("cbc_attach tool %s - attach cbc line discpline ", APP_INFO);
|
|
||||||
printf("to serial line\n\n");
|
|
||||||
printf("Usage: cbc_attach [OPTION]... [TTY-DEVICE]...\n\n");
|
|
||||||
printf("-h , --help Help\n");
|
|
||||||
printf("-b , --baudrate=<Baudrate> Baudrate e.g.:4000000\n");
|
|
||||||
printf("-f , --hardwareFlowControl Use hardware flow control\n");
|
|
||||||
printf("-m , --min-receive-bytes Minimum number of bytes to ");
|
|
||||||
printf("receive from the serial device ");
|
|
||||||
printf("(range:0-255, default:255)\n");
|
|
||||||
printf("<tty-device> Name of the serial line. ");
|
|
||||||
printf("default: %s\n", cDEFAULT_DEVICE_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool convertBaudRate(const uint32_t baudRateInt, speed_t *baudRate)
|
|
||||||
{
|
|
||||||
switch (baudRateInt) {
|
|
||||||
case 50:
|
|
||||||
*baudRate = B50;
|
|
||||||
break;
|
|
||||||
case 75:
|
|
||||||
*baudRate = B75;
|
|
||||||
break;
|
|
||||||
case 110:
|
|
||||||
*baudRate = B110;
|
|
||||||
break;
|
|
||||||
case 134:
|
|
||||||
*baudRate = B134;
|
|
||||||
break;
|
|
||||||
case 150:
|
|
||||||
*baudRate = B150;
|
|
||||||
break;
|
|
||||||
case 200:
|
|
||||||
*baudRate = B200;
|
|
||||||
break;
|
|
||||||
case 300:
|
|
||||||
*baudRate = B300;
|
|
||||||
break;
|
|
||||||
case 600:
|
|
||||||
*baudRate = B600;
|
|
||||||
break;
|
|
||||||
case 1200:
|
|
||||||
*baudRate = B1200;
|
|
||||||
break;
|
|
||||||
case 1800:
|
|
||||||
*baudRate = B1800;
|
|
||||||
break;
|
|
||||||
case 2400:
|
|
||||||
*baudRate = B2400;
|
|
||||||
break;
|
|
||||||
case 4800:
|
|
||||||
*baudRate = B4800;
|
|
||||||
break;
|
|
||||||
case 9600:
|
|
||||||
*baudRate = B9600;
|
|
||||||
break;
|
|
||||||
case 19200:
|
|
||||||
*baudRate = B19200;
|
|
||||||
break;
|
|
||||||
case 38400:
|
|
||||||
*baudRate = B38400;
|
|
||||||
break;
|
|
||||||
case 57600:
|
|
||||||
*baudRate = B57600;
|
|
||||||
break;
|
|
||||||
case 115200:
|
|
||||||
*baudRate = B115200;
|
|
||||||
break;
|
|
||||||
case 230400:
|
|
||||||
*baudRate = B230400;
|
|
||||||
break;
|
|
||||||
case 460800:
|
|
||||||
*baudRate = B460800;
|
|
||||||
break;
|
|
||||||
case 500000:
|
|
||||||
*baudRate = B500000;
|
|
||||||
break;
|
|
||||||
case 576000:
|
|
||||||
*baudRate = B576000;
|
|
||||||
break;
|
|
||||||
case 921600:
|
|
||||||
*baudRate = B921600;
|
|
||||||
break;
|
|
||||||
case 1000000:
|
|
||||||
*baudRate = B1000000;
|
|
||||||
break;
|
|
||||||
case 1152000:
|
|
||||||
*baudRate = B1152000;
|
|
||||||
break;
|
|
||||||
case 1500000:
|
|
||||||
*baudRate = B1500000;
|
|
||||||
break;
|
|
||||||
case 2000000:
|
|
||||||
*baudRate = B2000000;
|
|
||||||
break;
|
|
||||||
case 2500000:
|
|
||||||
*baudRate = B2500000;
|
|
||||||
break;
|
|
||||||
case 3000000:
|
|
||||||
*baudRate = B3000000;
|
|
||||||
break;
|
|
||||||
case 3500000:
|
|
||||||
*baudRate = B3500000;
|
|
||||||
break;
|
|
||||||
case 4000000:
|
|
||||||
*baudRate = B4000000;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool initTerminal(int deviceFd, const uint32_t baudRateInt,
|
|
||||||
const bool useHardwareFlowControl,
|
|
||||||
const uint8_t minReceiveBytes)
|
|
||||||
{
|
|
||||||
bool success = true;
|
|
||||||
struct termios terminalSettings;
|
|
||||||
|
|
||||||
speed_t baudRate = B0;
|
|
||||||
|
|
||||||
if (!convertBaudRate(baudRateInt, &baudRate)) {
|
|
||||||
printf("Invalid baud rate given %i\n", baudRateInt);
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
int res = tcgetattr(deviceFd, &terminalSettings);
|
|
||||||
|
|
||||||
if (res < 0) {
|
|
||||||
printf("Failed to get terminal settings (error: %s)\n",
|
|
||||||
strerror(errno));
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
terminalSettings.c_cflag = 0;
|
|
||||||
terminalSettings.c_iflag = 0;
|
|
||||||
|
|
||||||
/* set 8n1 */
|
|
||||||
terminalSettings.c_cflag &= ~(PARENB | CSTOPB | CSIZE);
|
|
||||||
terminalSettings.c_cflag |= CS8 | CLOCAL | CREAD;
|
|
||||||
terminalSettings.c_iflag |= IGNPAR;
|
|
||||||
|
|
||||||
if (useHardwareFlowControl)
|
|
||||||
/* Enable hardware flow control. */
|
|
||||||
terminalSettings.c_cflag |= CRTSCTS;
|
|
||||||
else
|
|
||||||
/* Disable hardware flow control.*/
|
|
||||||
terminalSettings.c_cflag &= ~CRTSCTS;
|
|
||||||
|
|
||||||
/* Disable software flow control. */
|
|
||||||
terminalSettings.c_iflag &= ~(IXON | IXOFF | IXANY);
|
|
||||||
|
|
||||||
/* Set raw mode. */
|
|
||||||
cfmakeraw(&terminalSettings);
|
|
||||||
|
|
||||||
/* Set VTIME to 1 to get a read() timeout of 100ms. */
|
|
||||||
terminalSettings.c_cc[VTIME] = 1u;
|
|
||||||
|
|
||||||
/* Set VMIN. */
|
|
||||||
terminalSettings.c_cc[VMIN] = minReceiveBytes;
|
|
||||||
|
|
||||||
/* Set baudrate. */
|
|
||||||
int res = cfsetspeed(&terminalSettings, baudRate);
|
|
||||||
|
|
||||||
if (res != 0) {
|
|
||||||
printf("Failed to set serial speed (error: %s)\n",
|
|
||||||
strerror(errno));
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
int res = cfsetospeed(&terminalSettings, baudRate);
|
|
||||||
|
|
||||||
if (res != 0) {
|
|
||||||
printf("Failed to set o/p serial speed (error: %s)\n",
|
|
||||||
strerror(errno));
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
(void)tcflush(deviceFd, TCIFLUSH);
|
|
||||||
int res = tcsetattr(deviceFd, TCSANOW, &terminalSettings);
|
|
||||||
|
|
||||||
if (res != 0) {
|
|
||||||
printf("Failed to set terminal settings (error: %s)\n",
|
|
||||||
strerror(errno));
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void cbc_attach_shutdown(int *const deviceFd)
|
|
||||||
{
|
|
||||||
if (*deviceFd > 0) {
|
|
||||||
int disc = N_TTY;
|
|
||||||
int res = ioctl(*deviceFd, TIOCSETD, &disc);
|
|
||||||
|
|
||||||
if (res != 0)
|
|
||||||
printf("Failed to set line disc tty (error: %s)\n",
|
|
||||||
strerror(errno));
|
|
||||||
|
|
||||||
res = close(*deviceFd);
|
|
||||||
if (res != 0)
|
|
||||||
printf("Failed to close serial device (error: %s)\n",
|
|
||||||
strerror(errno));
|
|
||||||
else
|
|
||||||
*deviceFd = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool openDevice(int *const deviceFd, char const *const deviceName)
|
|
||||||
{
|
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
*deviceFd = open(deviceName, O_RDONLY | O_NOCTTY);
|
|
||||||
if (*deviceFd < 0) {
|
|
||||||
printf("Failed to open serial device %s, error: %s\n",
|
|
||||||
deviceName, strerror(errno));
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool init(int *const deviceFd,
|
|
||||||
char const *const deviceName,
|
|
||||||
uint32_t const baudRateInt,
|
|
||||||
bool const useHardwareFlowControl,
|
|
||||||
uint8_t const minReceiveBytes)
|
|
||||||
{
|
|
||||||
/* TODO check whether VMIN/VTIME handling is necessary */
|
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
success = openDevice(deviceFd, deviceName);
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
success = initTerminal(*deviceFd, baudRateInt,
|
|
||||||
useHardwareFlowControl,
|
|
||||||
minReceiveBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
/* Set line discipline. N_CBCCORE is unknown on host.
|
|
||||||
* Use magic number instead of define.
|
|
||||||
*/
|
|
||||||
int disc = N_CBCCORE;
|
|
||||||
int res = ioctl(*deviceFd, TIOCSETD, &disc);
|
|
||||||
|
|
||||||
if (res != 0) {
|
|
||||||
printf("Failed to set line disc cbc (error: %s)\n",
|
|
||||||
strerror(errno));
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close the device if initialization has failed. */
|
|
||||||
if (!success)
|
|
||||||
cbc_attach_shutdown(deviceFd);
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int optionIndex;
|
|
||||||
int c;
|
|
||||||
bool success;
|
|
||||||
|
|
||||||
char const *deviceName = cDEFAULT_DEVICE_NAME;
|
|
||||||
int baudrate = 4000000;
|
|
||||||
bool useHwFlowControl = false;
|
|
||||||
uint8_t minReceiveBytes = 255;
|
|
||||||
int deviceFd = 0;
|
|
||||||
|
|
||||||
/* Retry times and uint */
|
|
||||||
int retry_time = 30;
|
|
||||||
int retry_uint = 2;
|
|
||||||
|
|
||||||
/* Try to get the CBC device name from an environment variable. */
|
|
||||||
char const *envDeviceName = getenv("CBC_TTY");
|
|
||||||
|
|
||||||
if (envDeviceName)
|
|
||||||
deviceName = envDeviceName;
|
|
||||||
|
|
||||||
/* Parse command line options. */
|
|
||||||
if (argc == 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
c = getopt_long(argc, argv, "hb:f", longOpts, &optionIndex);
|
|
||||||
if (c == -1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
switch (c) {
|
|
||||||
case 'h':
|
|
||||||
printMainUsage();
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case 'b':
|
|
||||||
if (optarg != NULL) {
|
|
||||||
baudrate = atoi(optarg);
|
|
||||||
if (baudrate == 0) {
|
|
||||||
printf("Unknown baudrate %s,exiting\n",
|
|
||||||
optarg);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'f':
|
|
||||||
useHwFlowControl = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (optind < argc)
|
|
||||||
deviceName = argv[optind];
|
|
||||||
|
|
||||||
printf("%s " APP_INFO "Started (pid: %i, CBC device: %s,", argv[0],
|
|
||||||
getpid(), deviceName);
|
|
||||||
printf("baudrate: %i, hw flow control: %s)\n", baudrate,
|
|
||||||
useHwFlowControl ? "on" : "off");
|
|
||||||
do {
|
|
||||||
/* set up serial line */
|
|
||||||
success = init(&deviceFd, deviceName, baudrate,
|
|
||||||
useHwFlowControl, minReceiveBytes);
|
|
||||||
if (success)
|
|
||||||
break;
|
|
||||||
|
|
||||||
sleep(retry_uint);
|
|
||||||
retry_time -= retry_uint;
|
|
||||||
printf("Init failed, retry time is %d seconds\n", retry_time);
|
|
||||||
|
|
||||||
} while (retry_time > 0);
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
pause();
|
|
||||||
cbc_attach_shutdown(&deviceFd);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=cbc attach
|
|
||||||
DefaultDependencies=no
|
|
||||||
After=sysinit.target local.target
|
|
||||||
Before=basic.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
ExecStart=/usr/bin/cbc_attach /dev/ttyS2
|
|
||||||
Restart=no
|
|
||||||
Type=simple
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=basic.target
|
|
@ -1,14 +0,0 @@
|
|||||||
|
|
||||||
OUT_DIR ?= .
|
|
||||||
|
|
||||||
$(OUT_DIR)/cbc_lifecycle: cbc_lifecycle.c $(TOOLS_OUT)/libacrn-mngr.a
|
|
||||||
gcc -o $@ cbc_lifecycle.c -pthread -L$(TOOLS_OUT) -lacrn-mngr
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm $(OUT_DIR)/cbc_lifecycle
|
|
||||||
|
|
||||||
install: $(OUT_DIR)/cbc_lifecycle cbc_lifecycle.service
|
|
||||||
install -d $(DESTDIR)/usr/bin
|
|
||||||
install -t $(DESTDIR)/usr/bin $<
|
|
||||||
install -d $(DESTDIR)/usr/lib/systemd/system/
|
|
||||||
install -p -m 0644 cbc_lifecycle.service $(DESTDIR)/usr/lib/systemd/system/
|
|
@ -1,490 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2018 Intel Corporation
|
|
||||||
*
|
|
||||||
* Author: Alek Du <alek.du@intel.com>
|
|
||||||
*
|
|
||||||
* SPDX-License-identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* CBC lifecycle state machine transition flow
|
|
||||||
*
|
|
||||||
* .-------------------------------------------
|
|
||||||
* -------------+-------------- |
|
|
||||||
* | IOC V IOC | |
|
|
||||||
* (default) ==> (Active) ==> (shutdown) ==> (shutdown delay) (Off)
|
|
||||||
* |_____________|__________________|
|
|
||||||
* _________|________ (ACRN select) ^
|
|
||||||
* ACRN/ ACRN| ACRN\ |
|
|
||||||
* (reboot) (suspend) (shutdown) |
|
|
||||||
* | | | |
|
|
||||||
* ------------------------------------------------------
|
|
||||||
*
|
|
||||||
* IOC: state transition due to cbc-lifecycle wakeup reason
|
|
||||||
* ACRN: state transition due to ACRND IPC request
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Basic cbc-lifecycle workflow on Service OS
|
|
||||||
* ____________________
|
|
||||||
* | sos lifecycle |
|
|
||||||
* | service |
|
|
||||||
* | |
|
|
||||||
* |*incoming request |(Listen on server socket @ /run/acrn/sos-lcs.socket)
|
|
||||||
* | wakeup reason |
|
|
||||||
* | shutdown |
|
|
||||||
* | reboot |(Requests from ACRN VM manager)
|
|
||||||
* | suspend |
|
|
||||||
* | RTC set wakeup |
|
|
||||||
* | |
|
|
||||||
* |*out events |(Send to ACRN VM manager @ /run/acrn/acrnd.socket)
|
|
||||||
* | vm start |
|
|
||||||
* | vm stop |(Events from /dev/cbc-lifecycle port)
|
|
||||||
* ~~~~~~~~~~~~~~~~~~~~
|
|
||||||
*
|
|
||||||
* 3 threads: 1. wake on /dev/cbc-lifecycle and receive wakeup reasons
|
|
||||||
* 2. heartbeat thread to send heartbeat msg to /dev/cbc-lifecycle
|
|
||||||
* 3. server socket handler thread to handle incoming msg
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <termios.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <linux/tty.h>
|
|
||||||
#include "../../tools/acrn-manager/acrn_mngr.h"
|
|
||||||
|
|
||||||
static char cbcd_name[] = "sos-lcs";
|
|
||||||
static char acrnd_name[] = "acrnd";
|
|
||||||
static char cbc_lifecycle_dev[] = "/dev/cbc-lifecycle";
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
S_DEFAULT = 0, /* default, not receiving any status */
|
|
||||||
S_ALIVE = 1, /* receive wakeup_reason bit 0~22 not all 0 */
|
|
||||||
S_SHUTDOWN, /* receive wakeup_reason bit 0~22 off 23 on */
|
|
||||||
S_SHUTDOWN_DELAY, /* before ACRND confirm off, sent delay to IOC */
|
|
||||||
S_ACRND_SHUTDOWN, /* ACRND confirm ioc can off */
|
|
||||||
S_IOC_SHUTDOWN, /* receiving wakeup_reason bit 0~23 off */
|
|
||||||
S_ACRND_REBOOT, /* receive request from ACRND to go reboot */
|
|
||||||
S_ACRND_SUSPEND, /* receive request from ACRND to go S3 */
|
|
||||||
S_MAX,
|
|
||||||
} state_machine_t;
|
|
||||||
|
|
||||||
/* state machine valid transition table */
|
|
||||||
char valid_map[S_MAX][S_MAX] = {
|
|
||||||
{ 1, 1, 1, 0, 0, 0, 0, 0 }, /* default can go alive or shutdown */
|
|
||||||
{ 0, 1, 1, 0, 1, 0, 1, 1 }, /* alive can go S_ACRND_* state */
|
|
||||||
{ 0, 0, 1, 1, 1, 1, 1, 1 }, /* shutdown can go upper states */
|
|
||||||
{ 0, 0, 0, 1, 1, 1, 1, 1 }, /* delay can go upper states */
|
|
||||||
{ 0, 0, 0, 0, 1, 1, 0, 0 }, /* acrnd shutdown can go ioc_shutdown */
|
|
||||||
{ 0, 1, 0, 0, 0, 1, 0, 0 }, /* ioc_shutdown can go alive (s3 case) */
|
|
||||||
{ 0, 0, 0, 0, 0, 1, 1, 0 }, /* acrnd_reboot can only go ioc_shutdown */
|
|
||||||
{ 0, 1, 0, 0, 0, 1, 0, 1 }, /* acrnd_suspend can go alive/ioc_shutdown */
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *state_name[] = {
|
|
||||||
"default",
|
|
||||||
"keep_alive",
|
|
||||||
"shutdown",
|
|
||||||
"shutdown_delay",
|
|
||||||
"acrnd_shutdown",
|
|
||||||
"ioc_shutdown",
|
|
||||||
"acrnd_reboot",
|
|
||||||
"acrnd_suspend",
|
|
||||||
};
|
|
||||||
|
|
||||||
static state_machine_t state;
|
|
||||||
static pthread_mutex_t state_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t header;
|
|
||||||
uint8_t wakeup[3];
|
|
||||||
} __attribute__((packed)) wakeup_reason_frame;
|
|
||||||
|
|
||||||
typedef pthread_t cbc_thread_t;
|
|
||||||
typedef void* (*cbc_thread_func_t)(void *arg);
|
|
||||||
|
|
||||||
/* cbc suppress heartbeat is not used so far, keep here for future use */
|
|
||||||
static char cbc_suppress_heartbeat_1min[] = {0x04, 0x60, 0xEA, 0x00};
|
|
||||||
static char cbc_suppress_heartbeat_5min[] = {0x04, 0xE0, 0x93, 0x04};
|
|
||||||
static char cbc_suppress_heartbeat_10min[] = {0x04, 0xC0, 0x27, 0x09};
|
|
||||||
static char cbc_suppress_heartbeat_30min[] = {0x04, 0x40, 0x77, 0x1B};
|
|
||||||
static char cbc_heartbeat_shutdown[] = {0x02, 0x00, 0x01, 0x00};
|
|
||||||
static char cbc_heartbeat_reboot[] = {0x02, 0x00, 0x02, 0x00};
|
|
||||||
/* hearbeat shutdown ignore number is not used so far for non-native case */
|
|
||||||
static char cbc_heartbeat_shutdown_ignore_1[] = {0x02, 0x00, 0x03, 0x00};
|
|
||||||
static char cbc_heartbeat_reboot_ignore_1[] = {0x02, 0x00, 0x04, 0x00};
|
|
||||||
static char cbc_heartbeat_shutdown_ignore_2[] = {0x02, 0x00, 0x05, 0x00};
|
|
||||||
static char cbc_heartbeat_reboot_ignore_2[] = {0x02, 0x00, 0x06, 0x00};
|
|
||||||
static char cbc_heartbeat_s3[] = {0x02, 0x00, 0x07, 0x00};
|
|
||||||
static char cbc_heartbeat_active[] = {0x02, 0x01, 0x00, 0x00};
|
|
||||||
static char cbc_heartbeat_shutdown_delay[] = {0x02, 0x02, 0x00, 0x00};
|
|
||||||
static char cbc_heartbeat_init[] = {0x02, 0x03, 0x00, 0x00};
|
|
||||||
|
|
||||||
static int cbc_lifecycle_fd = -1;
|
|
||||||
|
|
||||||
static int wakeup_reason;
|
|
||||||
|
|
||||||
static void wait_for_device(const char *dev_name)
|
|
||||||
{
|
|
||||||
int loop = 360; // 180 seconds
|
|
||||||
if (dev_name == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (loop--) {
|
|
||||||
if (access(dev_name, F_OK)) {
|
|
||||||
fprintf(stderr, "waiting for %s\n", dev_name);
|
|
||||||
usleep(500000);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int open_cbc_device(const char *cbc_device)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
wait_for_device(cbc_device);
|
|
||||||
|
|
||||||
if ((fd = open(cbc_device, O_RDWR | O_NOCTTY)) < 0) {
|
|
||||||
fprintf(stderr, "%s failed to open %s\n", __func__, cbc_device);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void close_cbc_device(int fd)
|
|
||||||
{
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cbc_send_data(int fd, const char *payload, int len)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
ret = write(fd, payload, len);
|
|
||||||
if (ret <= 0) {
|
|
||||||
if (errno == EDQUOT) {
|
|
||||||
usleep(1000);
|
|
||||||
break;
|
|
||||||
} else if (errno == EINTR) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "%s issue : %d", __func__,
|
|
||||||
errno);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cbc_read_data(int fd, char *payload, int len)
|
|
||||||
{
|
|
||||||
int nbytes = 0;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
nbytes = read(fd, payload, len);
|
|
||||||
|
|
||||||
if (nbytes < 0) {
|
|
||||||
if (errno == EINTR)
|
|
||||||
continue;
|
|
||||||
fprintf(stderr, "%s issue %d", __func__, errno);
|
|
||||||
usleep(5000);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return nbytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __inline__ int cbc_thread_create(cbc_thread_t *pthread,
|
|
||||||
cbc_thread_func_t start, void *arg)
|
|
||||||
{
|
|
||||||
pthread_attr_t attr;
|
|
||||||
pthread_attr_init(&attr);
|
|
||||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
|
||||||
|
|
||||||
return pthread_create(pthread, (const pthread_attr_t *)&attr,
|
|
||||||
start, arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
state_machine_t get_state(void)
|
|
||||||
{
|
|
||||||
state_machine_t _state;
|
|
||||||
pthread_mutex_lock(&state_mutex);
|
|
||||||
_state = state;
|
|
||||||
pthread_mutex_unlock(&state_mutex);
|
|
||||||
return _state;
|
|
||||||
}
|
|
||||||
|
|
||||||
state_machine_t state_transit(state_machine_t new)
|
|
||||||
{
|
|
||||||
state_machine_t _state;
|
|
||||||
pthread_mutex_lock(&state_mutex);
|
|
||||||
|
|
||||||
_state = state;
|
|
||||||
if (valid_map[state][new]) {
|
|
||||||
state = new;
|
|
||||||
pthread_mutex_unlock(&state_mutex);
|
|
||||||
if (_state != new) {
|
|
||||||
fprintf(stderr, "transit (%s to %s)\n",
|
|
||||||
state_name[_state], state_name[new]);
|
|
||||||
_state = new;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pthread_mutex_unlock(&state_mutex);
|
|
||||||
}
|
|
||||||
return _state;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int send_acrnd_stop(void);
|
|
||||||
static int send_acrnd_start(void);
|
|
||||||
|
|
||||||
void *cbc_heartbeat_loop(void)
|
|
||||||
{
|
|
||||||
state_machine_t last_state = S_DEFAULT;
|
|
||||||
const int p_size = sizeof(cbc_heartbeat_init);
|
|
||||||
cbc_send_data(cbc_lifecycle_fd, cbc_heartbeat_init, p_size);
|
|
||||||
fprintf(stderr, "send heartbeat init\n");
|
|
||||||
while (1) {
|
|
||||||
char *heartbeat;
|
|
||||||
state_machine_t cur_state = get_state();
|
|
||||||
|
|
||||||
switch (cur_state) {
|
|
||||||
case S_DEFAULT:
|
|
||||||
heartbeat = NULL;
|
|
||||||
break;
|
|
||||||
case S_ALIVE:
|
|
||||||
if (last_state != S_ALIVE) {
|
|
||||||
send_acrnd_start();
|
|
||||||
}
|
|
||||||
heartbeat = cbc_heartbeat_active;
|
|
||||||
break;
|
|
||||||
case S_SHUTDOWN:
|
|
||||||
/* when ACRND detects our off request, we must wait if
|
|
||||||
* UOS really accept the requst, thus we send shutdown
|
|
||||||
* delay */
|
|
||||||
send_acrnd_stop();
|
|
||||||
cur_state = state_transit(S_SHUTDOWN_DELAY);
|
|
||||||
// falling through
|
|
||||||
case S_SHUTDOWN_DELAY:
|
|
||||||
heartbeat = cbc_heartbeat_shutdown_delay;
|
|
||||||
break;
|
|
||||||
case S_ACRND_SHUTDOWN:
|
|
||||||
heartbeat = cbc_heartbeat_shutdown;
|
|
||||||
break;
|
|
||||||
case S_ACRND_REBOOT:
|
|
||||||
heartbeat = cbc_heartbeat_reboot;
|
|
||||||
break;
|
|
||||||
case S_ACRND_SUSPEND:
|
|
||||||
heartbeat = cbc_heartbeat_s3;
|
|
||||||
break;
|
|
||||||
case S_IOC_SHUTDOWN:
|
|
||||||
if (last_state == S_ACRND_SHUTDOWN)
|
|
||||||
system("shutdown 0");
|
|
||||||
else if (last_state == S_ACRND_REBOOT)
|
|
||||||
system("reboot");
|
|
||||||
else if (last_state == S_ACRND_SUSPEND)
|
|
||||||
system("echo mem > /sys/power/state");
|
|
||||||
//no heartbeat sent from now
|
|
||||||
heartbeat = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (heartbeat) {
|
|
||||||
cbc_send_data(cbc_lifecycle_fd, heartbeat, p_size);
|
|
||||||
fprintf(stderr, ".");
|
|
||||||
}
|
|
||||||
last_state = cur_state;
|
|
||||||
/* delay 1 second to send next heart beat */
|
|
||||||
sleep(1);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *cbc_wakeup_reason_thread(void *arg)
|
|
||||||
{
|
|
||||||
wakeup_reason_frame data;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
len = cbc_read_data(cbc_lifecycle_fd, (uint8_t *)&data, sizeof(data));
|
|
||||||
if (len > 0) {
|
|
||||||
if (data.header != 1) {
|
|
||||||
fprintf(stderr, "received wrong wakeup reason");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
wakeup_reason = data.wakeup[0] | data.wakeup[1] << 8 | data.wakeup[2] << 16;
|
|
||||||
if (!wakeup_reason)
|
|
||||||
state_transit(S_IOC_SHUTDOWN);
|
|
||||||
else if (!(wakeup_reason & ~(1 << 23)))
|
|
||||||
state_transit(S_SHUTDOWN);
|
|
||||||
else
|
|
||||||
state_transit(S_ALIVE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cbcd_fd;
|
|
||||||
|
|
||||||
static void handle_shutdown(struct mngr_msg *msg, int client_fd, void *param)
|
|
||||||
{
|
|
||||||
struct mngr_msg ack;
|
|
||||||
|
|
||||||
ack.magic = MNGR_MSG_MAGIC;
|
|
||||||
ack.msgid = msg->msgid;
|
|
||||||
ack.timestamp = msg->timestamp;
|
|
||||||
ack.data.err = 0;
|
|
||||||
|
|
||||||
fprintf(stderr, "acrnd agreed to shutdown\n");
|
|
||||||
state_transit(S_ACRND_SHUTDOWN);
|
|
||||||
mngr_send_msg(client_fd, &ack, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_suspend(struct mngr_msg *msg, int client_fd, void *param)
|
|
||||||
{
|
|
||||||
struct mngr_msg ack;
|
|
||||||
|
|
||||||
ack.magic = MNGR_MSG_MAGIC;
|
|
||||||
ack.msgid = msg->msgid;
|
|
||||||
ack.timestamp = msg->timestamp;
|
|
||||||
ack.data.err = 0;
|
|
||||||
|
|
||||||
state_transit(S_ACRND_SUSPEND);
|
|
||||||
mngr_send_msg(client_fd, &ack, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_reboot(struct mngr_msg *msg, int client_fd, void *param)
|
|
||||||
{
|
|
||||||
struct mngr_msg ack;
|
|
||||||
|
|
||||||
ack.magic = MNGR_MSG_MAGIC;
|
|
||||||
ack.msgid = msg->msgid;
|
|
||||||
ack.timestamp = msg->timestamp;
|
|
||||||
|
|
||||||
ack.data.err = 0;
|
|
||||||
|
|
||||||
state_transit(S_ACRND_REBOOT);
|
|
||||||
mngr_send_msg(client_fd, &ack, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_wakeup_reason(struct mngr_msg *msg, int client_fd, void *param)
|
|
||||||
{
|
|
||||||
struct mngr_msg ack;
|
|
||||||
|
|
||||||
ack.magic = MNGR_MSG_MAGIC;
|
|
||||||
ack.msgid = msg->msgid;
|
|
||||||
ack.timestamp = msg->timestamp;
|
|
||||||
|
|
||||||
ack.data.reason = wakeup_reason;
|
|
||||||
mngr_send_msg(client_fd, &ack, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_rtc(struct mngr_msg *msg, int client_fd, void *param)
|
|
||||||
{
|
|
||||||
struct mngr_msg ack;
|
|
||||||
|
|
||||||
ack.magic = MNGR_MSG_MAGIC;
|
|
||||||
ack.msgid = msg->msgid;
|
|
||||||
ack.timestamp = msg->timestamp;
|
|
||||||
|
|
||||||
fprintf(stderr, "%s request rtc timer at %lu, result will be %d\n",
|
|
||||||
msg->data.rtc_timer.vmname, msg->data.rtc_timer.t,
|
|
||||||
ack.data.err);
|
|
||||||
/* Need wait IOC firmware to support RTC */
|
|
||||||
ack.data.err = -1;
|
|
||||||
|
|
||||||
mngr_send_msg(client_fd, &ack, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int send_acrnd_start(void)
|
|
||||||
{
|
|
||||||
int acrnd_fd;
|
|
||||||
int ret;
|
|
||||||
struct mngr_msg req = {
|
|
||||||
.msgid = ACRND_RESUME,
|
|
||||||
.magic = MNGR_MSG_MAGIC,
|
|
||||||
};
|
|
||||||
struct mngr_msg ack;
|
|
||||||
|
|
||||||
req.timestamp = time(NULL);
|
|
||||||
acrnd_fd = mngr_open_un(acrnd_name, MNGR_CLIENT);
|
|
||||||
if (acrnd_fd < 0) {
|
|
||||||
fprintf(stderr, "cannot open %s socket\n", acrnd_name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ret = mngr_send_msg(acrnd_fd, &req, &ack, 2);
|
|
||||||
if (ret > 0)
|
|
||||||
fprintf(stderr, "result %d\n", ack.data.err);
|
|
||||||
mngr_close(acrnd_fd);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int send_acrnd_stop(void)
|
|
||||||
{
|
|
||||||
int acrnd_fd;
|
|
||||||
int ret;
|
|
||||||
struct mngr_msg req = {
|
|
||||||
.msgid = ACRND_STOP,
|
|
||||||
.magic = MNGR_MSG_MAGIC,
|
|
||||||
.data = {
|
|
||||||
.acrnd_stop = {
|
|
||||||
.force = 0,
|
|
||||||
.timeout = 20,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
struct mngr_msg ack;
|
|
||||||
|
|
||||||
req.timestamp = time(NULL);
|
|
||||||
acrnd_fd = mngr_open_un(acrnd_name, MNGR_CLIENT);
|
|
||||||
if (acrnd_fd < 0) {
|
|
||||||
fprintf(stderr, "cannot open %s socket\n", acrnd_name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ret = mngr_send_msg(acrnd_fd, &req, &ack, 2);
|
|
||||||
if (ret > 0)
|
|
||||||
fprintf(stderr, "result %d\n", ack.data.err);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
cbc_thread_t wakeup_reason_thread_ptr;
|
|
||||||
|
|
||||||
cbc_lifecycle_fd = open_cbc_device(cbc_lifecycle_dev);
|
|
||||||
if (cbc_lifecycle_fd < 0)
|
|
||||||
goto err_cbc;
|
|
||||||
/* the handle_* function may reply on a close fd, since the client
|
|
||||||
* can close the client_fd and ignore the ack */
|
|
||||||
signal(SIGPIPE, SIG_IGN);
|
|
||||||
cbcd_fd = mngr_open_un(cbcd_name, MNGR_SERVER);
|
|
||||||
if (cbcd_fd < 0) {
|
|
||||||
fprintf(stderr, "cannot open %s socket\n", cbcd_name);
|
|
||||||
goto err_un;
|
|
||||||
}
|
|
||||||
cbc_thread_create(&wakeup_reason_thread_ptr, cbc_wakeup_reason_thread,
|
|
||||||
NULL); // thread to handle wakeup_reason Rx data
|
|
||||||
|
|
||||||
mngr_add_handler(cbcd_fd, WAKEUP_REASON, handle_wakeup_reason, NULL);
|
|
||||||
mngr_add_handler(cbcd_fd, RTC_TIMER, handle_rtc, NULL);
|
|
||||||
mngr_add_handler(cbcd_fd, SHUTDOWN, handle_shutdown, NULL);
|
|
||||||
mngr_add_handler(cbcd_fd, SUSPEND, handle_suspend, NULL);
|
|
||||||
mngr_add_handler(cbcd_fd, REBOOT, handle_reboot, NULL);
|
|
||||||
cbc_heartbeat_loop();
|
|
||||||
// shouldn't be here
|
|
||||||
mngr_close(cbcd_fd);
|
|
||||||
err_un:
|
|
||||||
close_cbc_device(cbc_lifecycle_fd);
|
|
||||||
err_cbc:
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=CBC lifecycle service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
ExecStart=/usr/bin/cbc_lifecycle
|
|
||||||
Restart=no
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
Loading…
Reference in New Issue
Block a user