File indexing completed on 2024-05-12 05:36:20

0001 /*
0002  * SPDX-FileCopyrightText: 2020 Han Young <hanyoung@protonmail.com>
0003  * SPDX-FileCopyrightText: 2022 by Devin Lin <devin@kde.org>
0004  *
0005  * SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 #include "flashlightutil.h"
0009 
0010 #include <cstring>
0011 #include <fcntl.h>
0012 #include <libudev.h>
0013 #include <unistd.h>
0014 
0015 #include <QDebug>
0016 #include <QFileInfo>
0017 
0018 #define TORCH_SUBSYSTEM "leds"
0019 
0020 FlashlightUtil::FlashlightUtil(QObject *parent)
0021     : QObject{parent}
0022     , m_device{nullptr}
0023     , m_isAvailable{false}
0024 {
0025     findTorchDevice();
0026 }
0027 
0028 FlashlightUtil::~FlashlightUtil()
0029 {
0030     if (m_device != nullptr) {
0031         udev_device_unref(m_device);
0032     }
0033 }
0034 
0035 void FlashlightUtil::toggleTorch()
0036 {
0037     if (!isAvailable()) {
0038         qWarning() << "Flashlight not available";
0039         return;
0040     }
0041 
0042     int ret = udev_device_set_sysattr_value(m_device, "brightness", const_cast<char *>(m_torchEnabled ? "0" : m_maxBrightness));
0043     if (ret < 0) {
0044         qWarning() << "Flashlight can't be toggled";
0045         return;
0046     }
0047 
0048     m_torchEnabled = !m_torchEnabled;
0049     Q_EMIT torchChanged(m_torchEnabled);
0050 }
0051 
0052 bool FlashlightUtil::torchEnabled() const
0053 {
0054     return m_torchEnabled;
0055 }
0056 
0057 bool FlashlightUtil::isAvailable() const
0058 {
0059     return m_isAvailable;
0060 }
0061 
0062 void FlashlightUtil::findTorchDevice()
0063 {
0064     if (m_device != nullptr) {
0065         udev_device_unref(m_device);
0066     }
0067     m_device = nullptr;
0068     m_isAvailable = false;
0069 
0070     struct udev *udev = udev_new();
0071     struct udev_enumerate *enumerate = udev_enumerate_new(udev);
0072 
0073     udev_enumerate_add_match_subsystem(enumerate, TORCH_SUBSYSTEM);
0074     udev_enumerate_add_match_sysname(enumerate, "*:torch");
0075     udev_enumerate_add_match_sysname(enumerate, "*:flash");
0076     udev_enumerate_scan_devices(enumerate);
0077 
0078     struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
0079     struct udev_list_entry *entry = nullptr;
0080 
0081     struct udev_device *device = nullptr;
0082 
0083     udev_list_entry_foreach(entry, devices)
0084     {
0085         const char *path = udev_list_entry_get_name(entry);
0086 
0087         if (path == nullptr) {
0088             continue;
0089         }
0090 
0091         if (device != nullptr) {
0092             udev_device_unref(device); // Use to free memory from previous loop iteration
0093         }
0094 
0095         device = udev_device_new_from_syspath(udev, path);
0096 
0097         if (device == nullptr) {
0098             continue;
0099         }
0100 
0101         qInfo() << "Found flashlight device : " << path;
0102 
0103         const char *color = udev_device_get_sysattr_value(device, "color");
0104 
0105         if (color == nullptr) {
0106             continue;
0107         }
0108 
0109         qInfo() << "Flash color : " << color;
0110 
0111         if (std::strcmp(color, "white") == 0) {
0112             break;
0113         }
0114     }
0115 
0116     if (device == nullptr) {
0117         qWarning() << "No flashlight device found";
0118         return;
0119     }
0120 
0121     const char *maxBrightness = udev_device_get_sysattr_value(device, "max_brightness");
0122 
0123     if (maxBrightness == nullptr) {
0124         qWarning() << "Failed to read max_brightness from udev device";
0125         return;
0126     }
0127 
0128     qInfo() << "Flash maxBrightness : " << maxBrightness;
0129 
0130     const char *brightness = udev_device_get_sysattr_value(device, "brightness");
0131 
0132     if (brightness == nullptr) {
0133         qWarning() << "Failed to read brightness from udev device";
0134         return;
0135     }
0136 
0137     qInfo() << "Flash brightness : " << brightness;
0138 
0139     m_maxBrightness = maxBrightness;
0140     m_device = device;
0141     m_isAvailable = true;
0142     m_torchEnabled = std::strcmp(brightness, "0") != 0;
0143 
0144     udev_enumerate_unref(enumerate);
0145     udev_unref(udev);
0146 }