master ohmu/fastfetch-openbsd / src / detection / brightness / brightness.h
ohmu  ·  2026-10-15
 1#pragma once
 2
 3#include "fastfetch.h"
 4#include "modules/brightness/option.h"
 5
 6typedef struct FFBrightnessResult {
 7    FFstrbuf name;
 8    double min, max, current;
 9    bool builtin;
10} FFBrightnessResult;
11
12enum {
13    FF_DDC_EDID_ADDR = 0x50u,
14    FF_DDC_EDID_WRITE_ADDR = FF_DDC_EDID_ADDR << 1,
15    FF_DDC_CI_ADDR = 0x37u,
16    FF_DDC_CI_WRITE_ADDR = FF_DDC_CI_ADDR << 1,
17    FF_DDC_CI_READ_ADDR = FF_DDC_CI_WRITE_ADDR | 1,
18    FF_DDC_CI_VCP_COMMAND = 0x51u,
19    FF_DDC_CI_GET_VCP = 0x01u,
20    FF_DDC_CI_SET_VCP = 0x03u,
21    FF_DDC_CI_COMMAND_PACKET = 0x80u,
22    FF_DDC_CI_LUMINANCE_OPCODE = 0x10u,
23    FF_DDC_CI_VCP_RESPONSE_LENGTH = 8u,
24    FF_DDC_CI_VCP_RESPONSE_PACKET_SIZE = 11u,
25    FF_DDC_CI_VCP_RESPONSE_BUFFER_SIZE = 12u,
26    FF_DDC_CI_RESPONSE_CHECKSUM_ADDR = 0x50u,
27};
28#define FF_BRIGHTNESS_DDCCI_SLEEP_SKIP ((uint32_t) -1)
29#define FF_DDC_CI_MAKE_HEADER(len) (FF_DDC_CI_COMMAND_PACKET | ((len) & 0x7F))
30
31static inline uint8_t ffDdcCiChecksum(uint8_t address, const uint8_t* data, size_t length) {
32    uint8_t checksum = address;
33    for (size_t i = 0; i < length; ++i) {
34        checksum ^= data[i];
35    }
36    return checksum;
37}
38
39static inline void ffDdcCiBuildGetVcpRequest(uint8_t request[5]) {
40    request[0] = FF_DDC_CI_VCP_COMMAND;
41    request[1] = FF_DDC_CI_MAKE_HEADER(2);
42    request[2] = FF_DDC_CI_GET_VCP;
43    request[3] = FF_DDC_CI_LUMINANCE_OPCODE;
44    request[4] = ffDdcCiChecksum(FF_DDC_CI_WRITE_ADDR, request, 4);
45}
46
47static inline bool ffDdcCiValidateGetVcpResponse(const uint8_t response[FF_DDC_CI_VCP_RESPONSE_BUFFER_SIZE]) {
48    if (response[0] != FF_DDC_CI_WRITE_ADDR
49        || response[1] != FF_DDC_CI_MAKE_HEADER(FF_DDC_CI_VCP_RESPONSE_LENGTH)
50        || response[2] != 0x02u
51        || response[3] != 0x00u
52        || response[4] != FF_DDC_CI_LUMINANCE_OPCODE
53        || response[5] != 0x00u) {
54        return false;
55    }
56
57    return ffDdcCiChecksum(FF_DDC_CI_RESPONSE_CHECKSUM_ADDR, response, FF_DDC_CI_VCP_RESPONSE_PACKET_SIZE - 1u) == response[FF_DDC_CI_VCP_RESPONSE_PACKET_SIZE - 1u];
58}
59
60#define FF_I2C_DEVICE_CACHE_MAX 32
61
62typedef struct FFBrightnessDdcCache {
63    int devices[FF_I2C_DEVICE_CACHE_MAX];
64    size_t count;
65} FFBrightnessDdcCache;
66
67static inline FFstrbuf ffBrightnessDdcCachePath(void) {
68    FFstrbuf path = ffStrbufCreateCopy(&instance.state.platform.cacheDir);
69    ffStrbufEnsureEndsWithC(&path, '/');
70    ffStrbufAppendS(&path, "fastfetch/brightness/i2c_cache.txt");
71    return path;
72}
73
74const char* ffDetectBrightness(FFBrightnessOptions* options, FFlist* result); // list of FFBrightnessResult