fix(camera,sms,dwm): fix CAMSS AXI frame-boundary stop, SMS draft button label, and post-reboot softkey responsiveness

This commit is contained in:
Luxferre
2026-10-21 16:00:41 +03:00
parent 55b20c5b85
commit 4bb95d42b0
26 changed files with 152 additions and 33 deletions
+7 -4
View File
@@ -161,9 +161,7 @@ int runCameraApp(int argc, char** argv) {
std::string daemonPidPath = getPluginDaemonPidPath("camera");
std::string activePidPath = getRuntimeFile("xcamera.pid");
int existingDaemon = readIntFile(daemonPidPath, -1);
if (existingDaemon > 0 && existingDaemon != static_cast<int>(::getpid()) &&
::kill(existingDaemon, 0) == 0) {
if (isPluginDaemonAlive("camera")) {
if (!isPreload) {
sendPluginCommand("camera",
initArg.empty() ? "OPEN" : ("OPEN " + initArg));
@@ -422,6 +420,7 @@ int runCameraApp(int argc, char** argv) {
{
std::lock_guard<std::mutex> lk(frameMutex);
vfFront.swap(vfBack);
xImgVf->data = reinterpret_cast<char*>(vfFront.data());
cameraReady = true;
cameraStatus.clear();
if (!savedName.empty()) {
@@ -434,8 +433,12 @@ int runCameraApp(int argc, char** argv) {
char c = 'F';
(void)::write(writePipe, &c, 1);
}
for (int s = 0; s < 5 && !vfShouldStop && gRunning && !snapRequested.load(); ++s) {
struct timespec ts {0, 20 * 1000 * 1000};
nanosleep(&ts, nullptr);
}
} else {
struct timespec ts {0, 30 * 1000 * 1000};
struct timespec ts {0, 50 * 1000 * 1000};
nanosleep(&ts, nullptr);
}
}
+1 -3
View File
@@ -72,9 +72,7 @@ int runContactsApp(int argc, char** argv) {
std::string daemonPidPath = getPluginDaemonPidPath("contacts");
std::string activePidPath = getRuntimeFile("xcontacts.pid");
int existingDaemon = readIntFile(daemonPidPath, -1);
if (existingDaemon > 0 && existingDaemon != static_cast<int>(::getpid()) &&
::kill(existingDaemon, 0) == 0) {
if (isPluginDaemonAlive("contacts")) {
if (!isPreload) {
sendPluginCommand("contacts",
initArg.empty() ? "OPEN" : ("OPEN " + initArg));
+1 -3
View File
@@ -208,9 +208,7 @@ int runFilesApp(int argc, char** argv) {
std::string daemonPidPath = getPluginDaemonPidPath("files");
std::string activePidPath = getRuntimeFile("xfiles.pid");
int existingDaemon = readIntFile(daemonPidPath, -1);
if (existingDaemon > 0 && existingDaemon != static_cast<int>(::getpid()) &&
::kill(existingDaemon, 0) == 0) {
if (isPluginDaemonAlive("files")) {
if (!isPreload) {
sendPluginCommand("files", initDir.empty() ? "OPEN" : ("OPEN " + initDir));
}
+30 -1
View File
@@ -125,11 +125,40 @@ inline std::string getPluginDaemonPidPath(const char* name) {
return std::string("/tmp/dwm_plugin_") + name + ".pid";
}
inline bool sendPluginCommand(const char* name, const std::string& cmdLine) {
inline bool isPluginDaemonAlive(const char* name) {
if (!name || !name[0]) {
return false;
}
int pid = readIntFile(getPluginDaemonPidPath(name), -1);
if (pid <= 0 || pid == static_cast<int>(::getpid()) || ::kill(pid, 0) != 0) {
return false;
}
char cmdPath[64];
std::snprintf(cmdPath, sizeof(cmdPath), "/proc/%d/cmdline", pid);
int fd = ::open(cmdPath, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
return false;
}
char buf[256];
ssize_t n = ::read(fd, buf, sizeof(buf) - 1);
::close(fd);
if (n <= 0) {
return false;
}
for (ssize_t i = 0; i < n; ++i) {
if (buf[i] == '\0') {
buf[i] = ' ';
}
}
buf[n] = '\0';
return (std::strstr(buf, "dwm-plugin") != nullptr &&
std::strstr(buf, name) != nullptr);
}
inline bool sendPluginCommand(const char* name, const std::string& cmdLine) {
if (!isPluginDaemonAlive(name)) {
return false;
}
std::string fifoPath = getPluginFifoPath(name);
int fd = ::open(fifoPath.c_str(), O_WRONLY | O_NONBLOCK | O_CLOEXEC);
if (fd < 0) {
+8 -5
View File
@@ -94,9 +94,7 @@ int runSmsApp(int argc, char** argv) {
std::string daemonPidPath = getPluginDaemonPidPath("sms");
std::string activePidPath = getRuntimeFile("xsms.pid");
int existingDaemon = readIntFile(daemonPidPath, -1);
if (existingDaemon > 0 && existingDaemon != static_cast<int>(::getpid()) &&
::kill(existingDaemon, 0) == 0) {
if (isPluginDaemonAlive("sms")) {
if (!isPreload) {
sendPluginCommand("sms", initArg.empty() ? "OPEN" : ("OPEN " + initArg));
}
@@ -767,11 +765,16 @@ int runSmsApp(int argc, char** argv) {
drawPango(layoutMain, &colYellow, 146, 234, 30, "Draft", 84);
if (composeField == 0) {
drawSoftkeyBar("Contacts", "Next",
drawSoftkeyBar("Contacts",
composeRecipient.empty() ? "Contacts" : "Next",
composeRecipient.empty() ? "Cancel" : "Clear");
} else {
} else if (composeField == 1) {
drawSoftkeyBar("Send", "Send",
composeText.empty() ? "Cancel" : "Del");
} else if (composeField == 2) {
drawSoftkeyBar("Send", "Send", "Cancel");
} else {
drawSoftkeyBar("Send", "Draft", "Cancel");
}
} else if (mode == ViewMode::PickContact) {
+48 -12
View File
@@ -81,7 +81,7 @@ static const struct gc2395_reg gc2395_init_regs[] = {
{ 0xf4, 0x03 }, { 0xf7, 0x01 }, { 0xf8, 0x28 }, { 0xf9, 0x02 },
{ 0xfa, 0x08 }, { 0xfc, 0x8e }, { 0xe7, 0xcc }, { 0x88, 0x03 },
{ 0x03, 0x04 }, { 0x04, 0x80 }, { 0x05, 0x02 }, { 0x06, 0x86 },
{ 0x07, 0x00 }, { 0x08, 0x20 }, { 0x09, 0x00 }, { 0x0a, 0x04 },
{ 0x07, 0x02 }, { 0x08, 0x00 }, { 0x09, 0x00 }, { 0x0a, 0x04 },
{ 0x0b, 0x00 }, { 0x0c, 0x02 }, { 0x17, 0xd7 }, { 0x18, 0x02 },
{ 0x19, 0x17 }, { 0x1c, 0x18 }, { 0x20, 0x73 }, { 0x22, 0xa2 },
{ 0x21, 0x38 }, { 0x29, 0x20 }, { 0x2f, 0x14 }, { 0x3f, 0x40 },
@@ -314,14 +314,35 @@ static void gc2395_write_reg(struct msm8905_cam_dev *cam, u8 reg, u8 val)
cam_i2c_stop(cam);
}
static void msm8905_cam_enable_clocks(struct msm8905_cam_dev *cam)
{
size_t i;
if (cam_r32(cam->gcc_base, 0x58034U) & 1U) {
cam_w32(cam->gcc_base, 0x58034U, cam_r32(cam->gcc_base, 0x58034U) & ~1U);
usleep_range(1000, 2000);
}
if ((cam_r32(cam->gcc_base, 0x4500cU) & 0x3202U) != 0x3202U) {
cam_w32(cam->gcc_base, 0x4500cU, cam_r32(cam->gcc_base, 0x4500cU) | 0x3202U);
usleep_range(1000, 2000);
}
for (i = 0; i < ARRAY_SIZE(camss_cbcr_offsets); i++) {
if ((cam_r32(cam->gcc_base, camss_cbcr_offsets[i]) & 1U) == 0U ||
(cam_r32(cam->gcc_base, camss_cbcr_offsets[i]) & 0x80000000U) != 0U)
cam_enable_cbcr(cam, camss_cbcr_offsets[i]);
}
}
static int msm8905_cam_hw_init(struct msm8905_cam_dev *cam)
{
size_t i;
u16 chip_id;
u32 r;
if (cam->hw_initialized)
if (cam->hw_initialized) {
msm8905_cam_enable_clocks(cam);
return 0;
}
/* 1. Ensure PM8909 LDO6 (1.8V) and LDO17 (2.85V) are enabled */
if (cam->usid1_regmap) {
@@ -498,11 +519,16 @@ static int msm8905_cam_capture_rgb(struct msm8905_cam_dev *cam, u8 *dst_rgb)
ret = msm8905_cam_hw_init(cam);
if (ret)
return ret;
} else {
msm8905_cam_enable_clocks(cam);
}
/* Ensure GC2395 stream and VFE0 WM0/RDI0 are idle before resetting ISPIF */
/* Ensure GC2395 stream and ISPIF/VFE0 are idle before arming next frame */
cam_w32(cam->camss_base, ISPIF_BASE + 0x248U, 0xaaaaaaaaU);
wmb();
gc2395_write_reg(cam, 0xfeU, 0x00U);
gc2395_write_reg(cam, 0xedU, 0x00U);
usleep_range(600, 900);
cam_w32(cam->camss_base, VFE0_BASE + 0x04cU, 0x00000000U);
cam_w32(cam->camss_base, VFE0_BASE + 0x6fcU, 0x00000000U);
wmb();
@@ -538,7 +564,7 @@ static int msm8905_cam_capture_rgb(struct msm8905_cam_dev *cam, u8 *dst_rgb)
cam_w32(cam->camss_base, VFE0_BASE + 0x018U, 0x00000001U);
cam_w32(cam->camss_base, VFE0_BASE + 0x260U, 0x00000002U);
/* Enable ISPIF RDI0 CID0 on frame boundary and start GC2395 MIPI stream */
/* Enable ISPIF RDI0 on frame boundary and start GC2395 MIPI stream */
cam_w32(cam->camss_base, ISPIF_BASE + 0x248U, 0xfffffdffU);
wmb();
@@ -546,30 +572,40 @@ static int msm8905_cam_capture_rgb(struct msm8905_cam_dev *cam, u8 *dst_rgb)
gc2395_write_reg(cam, 0xedU, 0x90U);
gc2395_write_reg(cam, 0xfeU, 0x00U);
/* Wait for WM0 PING_PONG_IRQ (bit 6 = 0x40) */
/*
* Poll for WM0 PING_PONG_IRQ (bit 6 = 0x40) with sub-millisecond sleep so we
* catch EOF right inside the 14 ms vertical blanking window before Frame 2.
*/
irq0 = 0;
for (poll_cnt = 0; poll_cnt < 150; poll_cnt++) {
for (poll_cnt = 0; poll_cnt < 400; poll_cnt++) {
irq0 = cam_r32(cam->camss_base, VFE0_BASE + 0x02cU);
if (irq0 & 0x00000040U)
break;
usleep_range(2000, 3000);
usleep_range(400, 600);
}
/* Stop GC2395 stream, WM0, and RDI0 cleanly */
/*
* 1. Gate ISPIF at frame boundary FIRST so VFE0 never receives a partial frame.
* 2. Stop GC2395 MIPI stream during VBLANK (LP-11 state).
* 3. Wait for VFE0 WM0 / VBIF AXI write bursts to drain completely before
* clearing WM0_CFG and RDI0_CFG.
*/
cam_w32(cam->camss_base, ISPIF_BASE + 0x248U, 0xaaaaaaaaU);
wmb();
gc2395_write_reg(cam, 0xfeU, 0x00U);
gc2395_write_reg(cam, 0xedU, 0x00U);
usleep_range(800, 1200);
cam_w32(cam->camss_base, VFE0_BASE + 0x04cU, 0x00000000U);
cam_w32(cam->camss_base, VFE0_BASE + 0x6fcU, 0x00000000U);
cam_w32(cam->camss_base, VFE0_BASE + 0x024U, 0xffffffffU);
cam_w32(cam->camss_base, VFE0_BASE + 0x028U, 0xffffffffU);
cam_w32(cam->camss_base, VFE0_BASE + 0x018U, 0x00000001U);
cam_w32(cam->camss_base, ISPIF_BASE + 0x008U, 0x00001ff9U);
usleep_range(500, 1000);
cam_w32(cam->camss_base, ISPIF_BASE + 0x008U, 0x00000000U);
wmb();
if (!(irq0 & 0x00000040U))
if (!(irq0 & 0x00000040U)) {
cam->hw_initialized = false;
return -ETIMEDOUT;
}
msm8905_cam_demosaic(cam->raw_dma_buf, dst_rgb);
cam->sequence++;
+37 -5
View File
@@ -1537,8 +1537,15 @@ static long long
read_softkey_suppress(void)
{
char buf[32];
long long now = dwm_now_ms();
if (softkey_suppress_until_ms > now + 5000LL)
softkey_suppress_until_ms = 0;
read_sysfs_str("/tmp/sxmo_softkey_suppress", buf, sizeof(buf));
long long v = atoll(buf);
if (v > now + 5000LL) {
unlink("/tmp/sxmo_softkey_suppress");
v = 0;
}
if (v > softkey_suppress_until_ms)
softkey_suppress_until_ms = v;
return softkey_suppress_until_ms;
@@ -1610,13 +1617,30 @@ host_spawn_command(const char *const *argv)
static int
is_plugin_daemon_alive(const char *plugin_name)
{
char pidpath[128], buf[32];
char pidpath[128], buf[256];
snprintf(pidpath, sizeof(pidpath), "/tmp/dwm_plugin_%s.pid", plugin_name);
read_sysfs_str(pidpath, buf, sizeof(buf));
int pid = atoi(buf);
return (pid > 0 && kill(pid, 0) == 0);
if (pid <= 0 || kill(pid, 0) != 0)
return 0;
snprintf(pidpath, sizeof(pidpath), "/proc/%d/cmdline", pid);
int fd = open(pidpath, O_RDONLY | O_CLOEXEC);
if (fd < 0)
return 0;
ssize_t n = read(fd, buf, sizeof(buf) - 1);
close(fd);
if (n <= 0)
return 0;
for (ssize_t i = 0; i < n; i++) {
if (buf[i] == '\0')
buf[i] = ' ';
}
buf[n] = '\0';
return (strstr(buf, "dwm-plugin") != NULL && strstr(buf, plugin_name) != NULL);
}
static int preload_stagger_idx = 0;
static void
host_spawn_plugin(const char *plugin_name, const char *arg)
{
@@ -1625,9 +1649,15 @@ host_spawn_plugin(const char *plugin_name, const char *arg)
if (arg && strcmp(arg, "--preload") == 0) {
if (is_plugin_daemon_alive(plugin_name))
return;
const char *cmd[4] = { "dwm-plugin", plugin_name, "--preload", NULL };
Arg a = { .v = cmd };
spawn(&a);
int stagger_ms = 600 + (preload_stagger_idx++ * 220);
if (fork() == 0) {
if (dpy)
close(ConnectionNumber(dpy));
setsid();
usleep((useconds_t)stagger_ms * 1000U);
execlp("dwm-plugin", "dwm-plugin", plugin_name, "--preload", (char *)NULL);
_exit(EXIT_SUCCESS);
}
return;
}
XUngrabKeyboard(dpy, CurrentTime);
@@ -2677,6 +2707,8 @@ setup(void)
lidfd = open("/dev/input/by-path/platform-gpio-keys-event", O_RDONLY | O_NONBLOCK | O_CLOEXEC);
if (lidfd < 0)
lidfd = open("/dev/input/event0", O_RDONLY | O_NONBLOCK | O_CLOEXEC);
unlink("/tmp/sxmo_softkey_suppress");
unlink("/tmp/sxmo_softkey_state");
load_plugins();
grabkeys();
focus(NULL);
+20
View File
@@ -450,8 +450,28 @@ static int xdrawer_run_main(int argc, char** argv) {
std::string pidPath = getRuntimeFile("xdrawer.pid");
int existingDaemon = readIntFile(daemonPidPath, -1);
bool daemonAlive = false;
if (existingDaemon > 0 && existingDaemon != static_cast<int>(::getpid()) &&
::kill(existingDaemon, 0) == 0) {
char cmdPath[64];
std::snprintf(cmdPath, sizeof(cmdPath), "/proc/%d/cmdline", existingDaemon);
int cfd = ::open(cmdPath, O_RDONLY | O_CLOEXEC);
if (cfd >= 0) {
char cbuf[256];
ssize_t cn = ::read(cfd, cbuf, sizeof(cbuf) - 1);
::close(cfd);
if (cn > 0) {
for (ssize_t i = 0; i < cn; ++i) {
if (cbuf[i] == '\0') cbuf[i] = ' ';
}
cbuf[cn] = '\0';
if (std::strstr(cbuf, "xdrawer") != nullptr) {
daemonAlive = true;
}
}
}
}
if (daemonAlive) {
if (!isPreload) {
int ffd = ::open(fifoPath.c_str(), O_WRONLY | O_NONBLOCK | O_CLOEXEC);
if (ffd >= 0) {