|
|
@ -1,35 +1,48 @@
|
|
|
|
#include <assert.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <cerrno>
|
|
|
|
#include <cerrno>
|
|
|
|
#include <cstring>
|
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include "mesa/util/os_socket.h"
|
|
|
|
#include "mesa/util/os_socket.h"
|
|
|
|
#include "overlay.h"
|
|
|
|
#include "overlay.h"
|
|
|
|
|
|
|
|
#include "version.h"
|
|
|
|
#ifdef MANGOAPP
|
|
|
|
#ifdef MANGOAPP
|
|
|
|
#include "app/mangoapp.h"
|
|
|
|
#include "app/mangoapp.h"
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace std;
|
|
|
|
static void parse_command(struct instance_data *instance_data,
|
|
|
|
static void parse_command(overlay_params ¶ms,
|
|
|
|
const char *cmd, unsigned cmdlen,
|
|
|
|
const char *cmd, unsigned cmdlen,
|
|
|
|
const char *param, unsigned paramlen)
|
|
|
|
const char *param, unsigned paramlen)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (!strncmp(cmd, "hud", cmdlen)) {
|
|
|
|
if (!strncmp(cmd, "hud", cmdlen)) {
|
|
|
|
#ifdef MANGOAPP
|
|
|
|
#ifdef MANGOAPP
|
|
|
|
{
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lk(mangoapp_m);
|
|
|
|
std::lock_guard<std::mutex> lk(mangoapp_m);
|
|
|
|
instance_data->params.no_display = !instance_data->params.no_display;
|
|
|
|
params.no_display = !params.no_display;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mangoapp_cv.notify_one();
|
|
|
|
mangoapp_cv.notify_one();
|
|
|
|
#else
|
|
|
|
#else
|
|
|
|
instance_data->params.no_display = !instance_data->params.no_display;
|
|
|
|
params.no_display = !params.no_display;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
} else if (!strncmp(cmd, "logging", cmdlen)) {
|
|
|
|
if (!strncmp(cmd, "logging", cmdlen)) {
|
|
|
|
if (param && param[0])
|
|
|
|
if (logger->is_active())
|
|
|
|
{
|
|
|
|
logger->stop_logging();
|
|
|
|
int value = atoi(param);
|
|
|
|
|
|
|
|
if (!value && logger->is_active())
|
|
|
|
|
|
|
|
logger->stop_logging();
|
|
|
|
|
|
|
|
else if (value > 0 && !logger->is_active())
|
|
|
|
|
|
|
|
logger->start_logging();
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
logger->start_logging();
|
|
|
|
{
|
|
|
|
|
|
|
|
if (logger->is_active())
|
|
|
|
}
|
|
|
|
logger->stop_logging();
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
logger->start_logging();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (!strncmp(cmd, "fcat", cmdlen)) {
|
|
|
|
|
|
|
|
params.enabled[OVERLAY_PARAM_ENABLED_fcat] = !params.enabled[OVERLAY_PARAM_ENABLED_fcat];
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define BUFSIZE 4096
|
|
|
|
#define BUFSIZE 4096
|
|
|
@ -43,7 +56,7 @@ static void parse_command(struct instance_data *instance_data,
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* :cmd=param;
|
|
|
|
* :cmd=param;
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static void process_char(struct instance_data *instance_data, char c)
|
|
|
|
static void process_char(const int control_client, overlay_params ¶ms, char c)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
static char cmd[BUFSIZE];
|
|
|
|
static char cmd[BUFSIZE];
|
|
|
|
static char param[BUFSIZE];
|
|
|
|
static char param[BUFSIZE];
|
|
|
@ -65,7 +78,7 @@ static void process_char(struct instance_data *instance_data, char c)
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
cmd[cmdpos++] = '\0';
|
|
|
|
cmd[cmdpos++] = '\0';
|
|
|
|
param[parampos++] = '\0';
|
|
|
|
param[parampos++] = '\0';
|
|
|
|
parse_command(instance_data, cmd, cmdpos, param, parampos);
|
|
|
|
parse_command(params, cmd, cmdpos, param, parampos);
|
|
|
|
reading_cmd = false;
|
|
|
|
reading_cmd = false;
|
|
|
|
reading_param = false;
|
|
|
|
reading_param = false;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
@ -99,7 +112,7 @@ static void process_char(struct instance_data *instance_data, char c)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void control_send(struct instance_data *instance_data,
|
|
|
|
static void control_send(int control_client,
|
|
|
|
const char *cmd, unsigned cmdlen,
|
|
|
|
const char *cmd, unsigned cmdlen,
|
|
|
|
const char *param, unsigned paramlen)
|
|
|
|
const char *param, unsigned paramlen)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -120,42 +133,37 @@ static void control_send(struct instance_data *instance_data,
|
|
|
|
buffer[msglen++] = ';';
|
|
|
|
buffer[msglen++] = ';';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
os_socket_send(instance_data->control_client, buffer, msglen, 0);
|
|
|
|
os_socket_send(control_client, buffer, msglen, MSG_NOSIGNAL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void control_send_connection_string(struct device_data *device_data)
|
|
|
|
static void control_send_connection_string(int control_client, const std::string& deviceName)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct instance_data *instance_data = device_data->instance;
|
|
|
|
const char *controlVersionCmd = "MangoHudControlVersion";
|
|
|
|
|
|
|
|
|
|
|
|
const char *controlVersionCmd = "MesaOverlayControlVersion";
|
|
|
|
|
|
|
|
const char *controlVersionString = "1";
|
|
|
|
const char *controlVersionString = "1";
|
|
|
|
|
|
|
|
|
|
|
|
control_send(instance_data, controlVersionCmd, strlen(controlVersionCmd),
|
|
|
|
control_send(control_client, controlVersionCmd, strlen(controlVersionCmd),
|
|
|
|
controlVersionString, strlen(controlVersionString));
|
|
|
|
controlVersionString, strlen(controlVersionString));
|
|
|
|
|
|
|
|
|
|
|
|
const char *deviceCmd = "DeviceName";
|
|
|
|
const char *deviceCmd = "DeviceName";
|
|
|
|
const char *deviceName = device_data->properties.deviceName;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
control_send(instance_data, deviceCmd, strlen(deviceCmd),
|
|
|
|
control_send(control_client, deviceCmd, strlen(deviceCmd),
|
|
|
|
deviceName, strlen(deviceName));
|
|
|
|
deviceName.c_str(), deviceName.size());
|
|
|
|
|
|
|
|
|
|
|
|
const char *mesaVersionCmd = "MesaVersion";
|
|
|
|
const char *versionCmd = "MangoHudVersion";
|
|
|
|
const char *mesaVersionString = "Mesa";
|
|
|
|
const char *versionString = "MangoHud " MANGOHUD_VERSION;
|
|
|
|
|
|
|
|
|
|
|
|
control_send(instance_data, mesaVersionCmd, strlen(mesaVersionCmd),
|
|
|
|
control_send(control_client, versionCmd, strlen(versionCmd),
|
|
|
|
mesaVersionString, strlen(mesaVersionString));
|
|
|
|
versionString, strlen(versionString));
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void control_client_check(struct device_data *device_data)
|
|
|
|
void control_client_check(int control, int& control_client, const std::string& deviceName)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct instance_data *instance_data = device_data->instance;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Already connected, just return. */
|
|
|
|
/* Already connected, just return. */
|
|
|
|
if (instance_data->control_client >= 0)
|
|
|
|
if (control_client >= 0)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
int socket = os_socket_accept(instance_data->params.control);
|
|
|
|
int socket = os_socket_accept(control);
|
|
|
|
if (socket == -1) {
|
|
|
|
if (socket == -1) {
|
|
|
|
if (errno != EAGAIN && errno != EWOULDBLOCK && errno != ECONNABORTED)
|
|
|
|
if (errno != EAGAIN && errno != EWOULDBLOCK && errno != ECONNABORTED)
|
|
|
|
fprintf(stderr, "ERROR on socket: %s\n", strerror(errno));
|
|
|
|
fprintf(stderr, "ERROR on socket: %s\n", strerror(errno));
|
|
|
@ -164,25 +172,24 @@ void control_client_check(struct device_data *device_data)
|
|
|
|
|
|
|
|
|
|
|
|
if (socket >= 0) {
|
|
|
|
if (socket >= 0) {
|
|
|
|
os_socket_block(socket, false);
|
|
|
|
os_socket_block(socket, false);
|
|
|
|
instance_data->control_client = socket;
|
|
|
|
control_client = socket;
|
|
|
|
control_send_connection_string(device_data);
|
|
|
|
control_send_connection_string(control_client, deviceName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void control_client_disconnected(struct instance_data *instance_data)
|
|
|
|
static void control_client_disconnected(int& control_client)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
os_socket_close(instance_data->control_client);
|
|
|
|
os_socket_close(control_client);
|
|
|
|
instance_data->control_client = -1;
|
|
|
|
control_client = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void process_control_socket(struct instance_data *instance_data)
|
|
|
|
void process_control_socket(int& control_client, overlay_params ¶ms)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const int client = instance_data->control_client;
|
|
|
|
if (control_client >= 0) {
|
|
|
|
if (client >= 0) {
|
|
|
|
|
|
|
|
char buf[BUFSIZE];
|
|
|
|
char buf[BUFSIZE];
|
|
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
while (true) {
|
|
|
|
ssize_t n = os_socket_recv(client, buf, BUFSIZE, 0);
|
|
|
|
ssize_t n = os_socket_recv(control_client, buf, BUFSIZE, 0);
|
|
|
|
|
|
|
|
|
|
|
|
if (n == -1) {
|
|
|
|
if (n == -1) {
|
|
|
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
|
|
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
|
|
@ -193,14 +200,14 @@ void process_control_socket(struct instance_data *instance_data)
|
|
|
|
if (errno != ECONNRESET)
|
|
|
|
if (errno != ECONNRESET)
|
|
|
|
fprintf(stderr, "ERROR on connection: %s\n", strerror(errno));
|
|
|
|
fprintf(stderr, "ERROR on connection: %s\n", strerror(errno));
|
|
|
|
|
|
|
|
|
|
|
|
control_client_disconnected(instance_data);
|
|
|
|
control_client_disconnected(control_client);
|
|
|
|
} else if (n == 0) {
|
|
|
|
} else if (n == 0) {
|
|
|
|
/* recv() returns 0 when the client disconnects */
|
|
|
|
/* recv() returns 0 when the client disconnects */
|
|
|
|
control_client_disconnected(instance_data);
|
|
|
|
control_client_disconnected(control_client);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (ssize_t i = 0; i < n; i++) {
|
|
|
|
for (ssize_t i = 0; i < n; i++) {
|
|
|
|
process_char(instance_data, buf[i]);
|
|
|
|
process_char(control_client, params, buf[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* If we try to read BUFSIZE and receive BUFSIZE bytes from the
|
|
|
|
/* If we try to read BUFSIZE and receive BUFSIZE bytes from the
|
|
|
|