Skip to content

Commit

Permalink
support socket communication with client and systemd integration
Browse files Browse the repository at this point in the history
  • Loading branch information
Sian Cao committed May 9, 2014
1 parent ed852ed commit eb77c20
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 18 deletions.
22 changes: 19 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 2.8.11)

set(target prometheus)
set(target prometheusd)
set(client prometheus)

project(${target})

SET( CMAKE_CXX_COMPILER "clang++")
Expand Down Expand Up @@ -34,9 +36,10 @@ include_directories(${FT2_INCLUDE_DIRS})


configure_file(${PROJECT_SOURCE_DIR}/config.h.in ${PROJECT_BINARY_DIR}/config.h)
configure_file(${PROJECT_SOURCE_DIR}/prometheus-quit.service.in
${PROJECT_BINARY_DIR}/prometheus-quit.service)

file(GLOB SRCS "${PROJECT_SOURCE_DIR}/*.cc")

set(SRCS atlas.cc driver.cc glutil.cc options.cc scene.cc)

# make all shaders built into executable
file(GLOB SHADERS RELATIVE ${PROJECT_SOURCE_DIR} "*.glsl")
Expand All @@ -59,5 +62,18 @@ endforeach()
add_executable(${target} ${SRCS} ${SHADER_OBJS})
add_dependencies(${target} ${SHADER_OBJS})

add_executable(${client} client.cc)

target_link_libraries(${target} ${GLESV2_LIBRARIES} ${EGL_LIBRARIES}
${GBM_LIBRARIES} ${LIBDRM_LIBRARIES} ${FT2_LIBRARIES})

# install stage
install(TARGETS ${target} ${client} RUNTIME DESTINATION sbin)
install(FILES initrd/prometheus.initrd_hook
DESTINATION lib/initcpio/hooks RENAME prometheus)
install(FILES initrd/prometheus.initrd_install
DESTINATION lib/initcpio/install RENAME prometheus)
# quit service
install(FILES ${PROJECT_BINARY_DIR}/prometheus-quit.service
DESTINATION /usr/lib/systemd/system
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
67 changes: 67 additions & 0 deletions client.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <stdlib.h>
#include <unistd.h>

#include <iostream>
#include <unordered_map>
#include <fstream>

using namespace std;

static int id;

int dispatch(std::string cmd) {
std::unordered_map<string, string> tb {
{"quit", "Q"},
{"pause", "P"},
{"resume", "R"},
};

if (tb.find(cmd) == tb.end()) return -1;

if (write(id, tb[cmd].c_str(), tb[cmd].size()) < 0) {
perror("write");
return -1;
}
std::cerr << "write " << tb[cmd].size() << " bytes" << std::endl;
return 0;
}

int main(int argc, char *argv[])
{
const char *sock_path = ":prometheus.sock";

if (argc < 2) {
std::cerr << "no command specified" << std::endl;
return 0;
}

id = socket(AF_UNIX, SOCK_STREAM, 0);
if (id < 0) {
perror("socket");
return -1;
}

struct sockaddr_un un2;
memset(&un2, 0, sizeof un2);
un2.sun_family = AF_UNIX;
strncpy(&un2.sun_path[1], sock_path, strlen(sock_path));
if (connect(id, (struct sockaddr*)&un2, sizeof un2) < 0) {
perror("connect");
close(id);
return -1;
}

dispatch(argv[1]);
close(id);

ofstream ofs{"/tmp/prometheus.done"};
ofs << "";

// bad way to wait for server to finish
sleep(1);
return 0;
}

120 changes: 107 additions & 13 deletions driver.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/time.h>
#include <string.h>
#include <fcntl.h>
Expand Down Expand Up @@ -69,7 +71,7 @@ static void render()
}

struct gbm_bo *bo = dc.next_bo = gbm_surface_lock_front_buffer(dc.gbm_surface);
printf("next_bo = %lu\n", (unsigned long)bo);
//printf("next_bo = %lu\n", (unsigned long)bo);
if (!bo) {
printf("cannot lock front buffer during creation");
exit(-1);
Expand All @@ -81,9 +83,9 @@ static void render()
} else {
dc.next_fb_id = bo_to_fb(bo);
}
printf("dc.next_fb_id = %u\n", dc.next_fb_id);
//printf("dc.next_fb_id = %u\n", dc.next_fb_id);

if (dc.vt_activated) {
if (dc.vt_activated && !dc.paused) {
auto ret = drmModePageFlip(dc.fd, dc.crtc, dc.next_fb_id,
DRM_MODE_PAGE_FLIP_EVENT, NULL);
if (ret) {
Expand All @@ -94,18 +96,18 @@ static void render()
}
}

gettimeofday(&tm_end, NULL);
float timeval = (tm_end.tv_sec - tm_start.tv_sec) +
(tm_end.tv_usec - tm_start.tv_usec) / 1000000.0;
std::cerr << "frame render duration: " << timeval << std::endl;
//gettimeofday(&tm_end, NULL);
//float timeval = (tm_end.tv_sec - tm_start.tv_sec) +
//(tm_end.tv_usec - tm_start.tv_usec) / 1000000.0;
//std::cerr << "frame render duration: " << timeval << std::endl;
}

static void modeset_page_flip_event(int fd, unsigned int frame,
unsigned int sec, unsigned int usec,
void *data)
{
std::cerr << __func__ << " frame: " << frame << std::endl;
if (dc.vt_activated)
//std::cerr << __func__ << " frame: " << frame << std::endl;
if (dc.vt_activated && !dc.paused)
dc.pflip_pending = false;
else
std::cerr << "vt is deactivated, wait" << std::endl;
Expand All @@ -117,6 +119,52 @@ static void modeset_vblank_handler(int fd, unsigned int sequence,
std::cerr << __func__ << " sequence: " << sequence << std::endl;
}

// return true if event ask for break of event loop due to error
static bool handleClientEvent()
{
struct sockaddr_un un;
socklen_t len = sizeof un;
int cfd = accept(dc.commid, (struct sockaddr*)&un, &len);
if (cfd < 0) {
perror("accept");
return false;
}

char buf[20];
int n = read(cfd, buf, sizeof buf);
if (n <= 0) {
std::cerr << strerror(errno) << std::endl;
close(cfd);
return false;
}

close(cfd);
buf[n] = '\0';
std::cerr << "received command(" << n << "): " << buf << std::endl;
if (string(buf) == "Q") {
dc.cleanup = true;
return true;

} else if (string(buf) == "P") {
if (!dc.paused) {
dc.paused = true;
drmDropMaster(dc.fd);
}

} else if (string(buf) == "R") {
if (dc.paused) {
dc.paused = false;
if (dc.vt_activated && dc.pflip_pending)
dc.pflip_pending = false;
drmSetMaster(dc.fd);
drmModeSetCrtc(dc.fd, dc.crtc, dc.next_fb_id, 0, 0, &dc.conn, 1, &dc.mode);
}
}


return false;
}

static void run_loop()
{
int fd = dc.fd;
Expand All @@ -137,15 +185,22 @@ static void run_loop()
while (dc.pflip_pending) {
FD_SET(0, &fds);
FD_SET(fd, &fds);
FD_SET(dc.commid, &fds);

struct timeval tv { 0, 100 };
ret = select(fd + 1, &fds, NULL, NULL, &tv);
if (ret < 0) {
fprintf(stderr, "select() failed with %d: %m\n", errno);
std::cerr << "select: " << strerror(errno) << std::endl;
break;

} else if (FD_ISSET(0, &fds)) {
fprintf(stderr, "exit due to user-input\n");
return;
std::cerr << "exit due to user-input" << std::endl;
dc.cleanup = true;
break;

} else if (FD_ISSET(dc.commid, &fds)) {
if (handleClientEvent())
break;

} else if (FD_ISSET(fd, &fds)) {
drmHandleEvent(fd, &ev);
Expand All @@ -156,6 +211,8 @@ static void run_loop()
gbm_surface_release_buffer(dc.gbm_surface, dc.bo);
dc.bo = dc.next_bo;
}

if (dc.cleanup) break;
}
}

Expand Down Expand Up @@ -317,9 +374,9 @@ static void setup_egl()
static void on_leave_vt(int sig)
{
std::cerr << __func__ << std::endl;
ioctl (dc.vtfd, VT_RELDISP, 1);
dc.vt_activated = false;
drmDropMaster(dc.fd);
ioctl (dc.vtfd, VT_RELDISP, 1);
}

static void on_enter_vt(int sig)
Expand Down Expand Up @@ -354,8 +411,43 @@ static void setup_vt()
dc.vt_activated = true;
}

static const char *comm_path = ":prometheus.sock";
static void setup_comm()
{
struct sockaddr_un un;
memset(&un, 0, sizeof un);
un.sun_family = AF_UNIX;
strncpy(&un.sun_path[1], comm_path, strlen(comm_path));

int id = socket(AF_UNIX, SOCK_STREAM, 0);
if (id < 0) {
perror("socket");
return;
}

if (bind(id, (struct sockaddr*)&un, sizeof un) < 0) {
perror("bind");
close(id);
return;
}

if (listen(id, 1) < 0) {
perror("listen");
close(id);
return;
}

dc.commid = id;
std::cerr << "commid = " << dc.commid << std::endl;
}

static void cleanup()
{
std::cerr << __func__ << std::endl;
if (dc.commid) {
close(dc.commid);
}

if (dc.vtfd > 0)
close(dc.vtfd);

Expand Down Expand Up @@ -387,6 +479,8 @@ int main(int argc, char* argv[])
}

std::setlocale(LC_ALL, "en_US.UTF-8");

setup_comm();
setup_drm();
setup_egl();
setup_vt();
Expand Down
4 changes: 4 additions & 0 deletions driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,15 @@ struct DisplayContext {

bool pflip_pending;
bool cleanup;
bool paused;

//vt
int vtfd;
bool vt_activated;

//communication id
int commid;

ActionMode* action_mode;
};

Expand Down
2 changes: 1 addition & 1 deletion initrd/prometheus.initrd_hook
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/ash

run_hook() {
prometheus -m text
prometheusd -m text
}

# vim: set ft=sh:
5 changes: 4 additions & 1 deletion initrd/prometheus.initrd_install
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ build() {
add_binary /usr/lib/xorg/modules/dri/swrast_dri.so
add_binary /usr/lib/xorg/modules/dri/vmwgfx_dri.so

add_binary /usr/sbin/prometheus
add_binary /usr/lib/egl/egl_gallium.so
add_binary /usr/lib/gbm/gbm_gallium_drm.so

add_binary /usr/sbin/prometheus
add_binary /usr/sbin/prometheusd

add_runscript
}

Expand Down
13 changes: 13 additions & 0 deletions lightdm-prometheus.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[Unit]
Description=Light Display Manager
Conflicts[email protected] prometheus-quit.service
After=systemd-user-sessions.service [email protected] prometheus-quit.service

[Service]
ExecStart=/usr/bin/lightdm
Restart=always
IgnoreSIGPIPE=no
BusName=org.freedesktop.DisplayManager

[Install]
Alias=display-manager.service
9 changes: 9 additions & 0 deletions prometheus-quit.service.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[Unit]
Description=Terminate Prometheus Boot Screen
After=rc-local.service systemd-user-sessions.service
[email protected]

[Service]
ExecStart=-@CMAKE_INSTALL_PREFIX@/sbin/prometheus quit
Type=oneshot
TimeoutSec=20

0 comments on commit eb77c20

Please sign in to comment.