From 3b0f2014e31a2ee16cddb39157e7050d6aa00724 Mon Sep 17 00:00:00 2001
From: yellows8 <yellows8@users.noreply.github.com>
Date: Sat, 20 Apr 2019 16:11:05 -0400
Subject: [PATCH] Added appletGetCurrentIlluminance,
 appletGetCurrentIlluminanceEx, and appletIsIlluminanceAvailable.

---
 nx/include/switch/services/applet.h |  22 +++++
 nx/source/services/applet.c         | 122 ++++++++++++++++++++++++++++
 2 files changed, 144 insertions(+)

diff --git a/nx/include/switch/services/applet.h b/nx/include/switch/services/applet.h
index 4d24ad67..43b2aff4 100644
--- a/nx/include/switch/services/applet.h
+++ b/nx/include/switch/services/applet.h
@@ -253,6 +253,28 @@ Result appletSetScreenShotPermission(s32 val);
 
 Result appletSetScreenShotImageOrientation(s32 val);
 
+/**
+ * @brief Gets the current Illuminance from the light sensor.
+ * @note Only available with [3.0.0+].
+ * @param fLux Output fLux
+ */
+Result appletGetCurrentIlluminance(float *fLux);
+
+/**
+ * @brief Gets the current Illuminance from the light sensor. Same as \ref appletGetCurrentIlluminance except for the additional param.
+ * @note Only available with [5.0.0+].
+ * @param bOverLimit Output bOverLimit
+ * @param fLux Output fLux
+ */
+Result appletGetCurrentIlluminanceEx(bool *bOverLimit, float *fLux);
+
+/**
+ * @brief Gets whether Illuminance is available.
+ * @note Only available with [3.0.0+].
+ * @param out Output flag
+ */
+Result appletIsIlluminanceAvailable(bool *out);
+
 /**
  * @brief Stops forwarding the input to the foreground app, works only in the Overlay applet context.
  * @note You have to call this to receive inputs through the hid service when running as the overlay applet.
diff --git a/nx/source/services/applet.c b/nx/source/services/applet.c
index 0fe77985..6cd4b3f7 100644
--- a/nx/source/services/applet.c
+++ b/nx/source/services/applet.c
@@ -709,6 +709,43 @@ static Result _appletCmdNoInOut32(Service* srv, u32 *out, u64 cmd_id) {
     return rc;
 }
 
+static Result _appletCmdNoInOutBool(Service* srv, bool *out, u64 cmd_id) {
+    IpcCommand c;
+    ipcInitialize(&c);
+
+    struct {
+        u64 magic;
+        u64 cmd_id;
+    } *raw;
+
+    raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
+
+    raw->magic = SFCI_MAGIC;
+    raw->cmd_id = cmd_id;
+
+    Result rc = serviceIpcDispatch(srv);
+
+    if (R_SUCCEEDED(rc)) {
+        IpcParsedCommand r;
+        struct {
+            u64 magic;
+            u64 result;
+            u8 out;
+        } *resp;
+
+        serviceIpcParse(srv, &r, sizeof(*resp));
+        resp = r.Raw;
+
+        rc = resp->result;
+
+        if (R_SUCCEEDED(rc) && out) {
+            *out = resp->out!=0;
+        }
+    }
+
+    return rc;
+}
+
 static Result _appletCmdInU8(Service* srv, u8 inval, u64 cmd_id) {
     IpcCommand c;
     ipcInitialize(&c);
@@ -1890,6 +1927,91 @@ Result appletCreateManagedDisplayLayer(u64 *out) {
     return _appletCmdNoInOut64(&g_appletISelfController, out, 40);
 }
 
+Result appletGetCurrentIlluminance(float *fLux) {
+    if (hosversionBefore(3,0,0))
+        return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
+
+    IpcCommand c;
+    ipcInitialize(&c);
+
+    struct {
+        u64 magic;
+        u64 cmd_id;
+    } *raw;
+
+    raw = serviceIpcPrepareHeader(&g_appletISelfController, &c, sizeof(*raw));
+
+    raw->magic = SFCI_MAGIC;
+    raw->cmd_id = 66;
+
+    Result rc = serviceIpcDispatch(&g_appletISelfController);
+
+    if (R_SUCCEEDED(rc)) {
+        IpcParsedCommand r;
+        struct {
+            u64 magic;
+            u64 result;
+            float fLux;
+        } *resp;
+
+        serviceIpcParse(&g_appletISelfController, &r, sizeof(*resp));
+        resp = r.Raw;
+
+        rc = resp->result;
+
+        if (R_SUCCEEDED(rc) && fLux) *fLux = resp->fLux;
+    }
+
+    return rc;
+}
+
+Result appletIsIlluminanceAvailable(bool *out) {
+    if (hosversionBefore(3,0,0))
+        return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
+
+    return _appletCmdNoInOutBool(&g_appletISelfController, out, 67);
+}
+
+Result appletGetCurrentIlluminanceEx(bool *bOverLimit, float *fLux) {
+    if (hosversionBefore(5,0,0))
+        return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
+
+    IpcCommand c;
+    ipcInitialize(&c);
+
+    struct {
+        u64 magic;
+        u64 cmd_id;
+    } *raw;
+
+    raw = serviceIpcPrepareHeader(&g_appletISelfController, &c, sizeof(*raw));
+
+    raw->magic = SFCI_MAGIC;
+    raw->cmd_id = 71;
+
+    Result rc = serviceIpcDispatch(&g_appletISelfController);
+
+    if (R_SUCCEEDED(rc)) {
+        IpcParsedCommand r;
+        struct {
+            u64 magic;
+            u64 result;
+            u8 bOverLimit;
+            float fLux;
+        } *resp;
+
+        serviceIpcParse(&g_appletISelfController, &r, sizeof(*resp));
+        resp = r.Raw;
+
+        rc = resp->result;
+
+        if (R_SUCCEEDED(rc) && bOverLimit) *bOverLimit = resp->bOverLimit!=0;
+        if (R_SUCCEEDED(rc) && fLux) *fLux = resp->fLux;
+    }
+
+    return rc;
+}
+
 // ILibraryAppletSelfAccessor
 
 static Result _appletExitProcessAndReturn(void) {