/*
 * camera_config.c — 热成像摄像头参数配置接口实现
 *
 * 参考官方示例 ThermalDevice.cpp 封装的全部红外配置项。
 * 配置操作统一走 USB 通道 1(官方约定),码流通道 2 只用于视频流。
 * 图像增强使用 V20→V1 自动回退;其余均使用 V1 命令。
 */

#include "camera_config.h"
#include <stdio.h>
#include <string.h>

/* ======================================================================== *
 *  内部辅助函数                                                              *
 * ======================================================================== */

/*
 * 通用 GET:通过 USB_GetDeviceConfig 读取设备参数。
 * 通道固定为 1(控制通道),与流数据通道(2)分离。
 */
static int get_config(LONG uid, DWORD cmd, void *out, DWORD out_size)
{
    USB_COMMON_COND         cond = {0};
    USB_CONFIG_INPUT_INFO   ii   = {0};
    USB_CONFIG_OUTPUT_INFO  oo   = {0};

    cond.dwSize = sizeof(cond);
    cond.byChannelID = 1;
    ii.lpCondBuffer     = &cond;
    ii.dwCondBufferSize = sizeof(cond);
    ii.lpInBuffer       = out;
    ii.dwInBufferSize   = out_size;
    oo.lpOutBuffer      = out;
    oo.dwOutBufferSize  = out_size;

    if (!USB_GetDeviceConfig(uid, cmd, &ii, &oo)) {
        printf("[camera_config] GET fail cmd=0x%lx (%lu)\n",
               (unsigned long)cmd, (unsigned long)cmd);
        return 0;
    }
    return 1;
}

/*
 * 通用 SET:通过 USB_SetDeviceConfig 写入设备参数。
 */
static int set_config(LONG uid, DWORD cmd, void *in, DWORD in_size)
{
    USB_COMMON_COND         cond = {0};
    USB_CONFIG_INPUT_INFO   ii   = {0};
    USB_CONFIG_OUTPUT_INFO  oo   = {0};

    cond.dwSize = sizeof(cond);
    cond.byChannelID = 1;
    ii.lpCondBuffer     = &cond;
    ii.dwCondBufferSize = sizeof(cond);
    ii.lpInBuffer       = in;
    ii.dwInBufferSize   = in_size;

    if (!USB_SetDeviceConfig(uid, cmd, &ii, &oo)) {
        printf("[camera_config] SET fail cmd=0x%lx (%lu)\n",
               (unsigned long)cmd, (unsigned long)cmd);
        return 0;
    }
    return 1;
}

/*
 * 通用 CONTROL:通过 USB_Control 发送无数据/简单参数的控制命令。
 */
static int control_cmd(LONG uid, DWORD cmd)
{
    USB_COMMON_COND         cond = {0};
    USB_CONTROL_INPUT_INFO  ci   = {0};

    cond.dwSize = sizeof(cond);
    cond.byChannelID = 1;
    ci.lpCondBuffer     = &cond;
    ci.dwCondBufferSize = sizeof(cond);

    if (!USB_Control(uid, cmd, &ci)) {
        printf("[camera_config] CTRL fail cmd=0x%lx (%lu)\n",
               (unsigned long)cmd, (unsigned long)cmd);
        return 0;
    }
    return 1;
}

/* ======================================================================== *
 *  1.  系统管理                                                             *
 * ======================================================================== */

int camera_get_device_info(LONG uid, USB_SYSTEM_DEVICE_INFO *info)
{
    memset(info, 0, sizeof(*info));
    info->dwSize = sizeof(*info);
    return get_config(uid, USB_GET_SYSTEM_DEVICE_INFO, info, sizeof(*info));
}

int camera_set_reboot(LONG uid)
{
    return control_cmd(uid, USB_SET_SYSTEM_REBOOT);
}

int camera_set_factory_reset(LONG uid)
{
    return control_cmd(uid, USB_SET_SYSTEM_RESET);
}

int camera_set_background_correct(LONG uid)
{
    return control_cmd(uid, USB_SET_IMAGE_BACKGROUND_CORRECT);
}

int camera_set_manual_correct(LONG uid)
{
    return control_cmd(uid, USB_SET_IMAGE_MANUAL_CORRECT);
}

int camera_get_hardware_server(LONG uid, USB_SYSTEM_HARDWARE_SERVER *hs)
{
    memset(hs, 0, sizeof(*hs));
    hs->dwSize = sizeof(*hs);
    return get_config(uid, USB_GET_SYSTEM_HARDWARE_SERVER, hs, sizeof(*hs));
}

int camera_set_hardware_server(LONG uid, const USB_SYSTEM_HARDWARE_SERVER *hs)
{
    return set_config(uid, USB_SET_SYSTEM_HARDWARE_SERVER,
                      (void *)hs, sizeof(*hs));
}

int camera_get_local_time(LONG uid, USB_SYSTEM_LOCALTIME *lt)
{
    memset(lt, 0, sizeof(*lt));
    lt->dwSize = sizeof(*lt);
    return get_config(uid, USB_GET_SYSTEM_LOCALTIME, lt, sizeof(*lt));
}

int camera_set_local_time(LONG uid, const USB_SYSTEM_LOCALTIME *lt)
{
    return set_config(uid, USB_SET_SYSTEM_LOCALTIME, (void *)lt, sizeof(*lt));
}

/* ======================================================================== *
 *  2.  图像增强 Enhancement(V20 → V1 自动回退)                             *
 * ======================================================================== */

int camera_get_enhancement(LONG uid, USB_IMAGE_ENHANCEMENT *enh)
{
    USB_COMMON_COND         cond = {0};
    USB_CONFIG_INPUT_INFO   ii   = {0};
    USB_CONFIG_OUTPUT_INFO  oo   = {0};

    cond.dwSize = sizeof(cond);
    cond.byChannelID = 1;
    enh->dwSize = sizeof(*enh);

    ii.lpCondBuffer     = &cond;
    ii.dwCondBufferSize = sizeof(cond);
    ii.lpInBuffer       = enh;
    ii.dwInBufferSize   = sizeof(*enh);
    oo.lpOutBuffer      = enh;
    oo.dwOutBufferSize  = sizeof(*enh);

    /* 先试 V20 */
    if (USB_GetDeviceConfig(uid, USB_GET_IMAGE_ENHANCEMENT_V20, &ii, &oo))
        return 1;

    /* 回退 V1 */
    memset(&ii, 0, sizeof(ii));
    memset(&oo, 0, sizeof(oo));
    ii.lpCondBuffer     = &cond;
    ii.dwCondBufferSize = sizeof(cond);
    ii.lpInBuffer       = enh;
    ii.dwInBufferSize   = sizeof(*enh);
    oo.lpOutBuffer      = enh;
    oo.dwOutBufferSize  = sizeof(*enh);

    if (!USB_GetDeviceConfig(uid, USB_GET_IMAGE_ENHANCEMENT, &ii, &oo)) {
        printf("[camera_config] get_enhancement: V20 和 V1 都失败\n");
        return 0;
    }
    return 1;
}

int camera_set_enhancement(LONG uid, const USB_IMAGE_ENHANCEMENT *enh)
{
    USB_COMMON_COND         cond = {0};
    USB_CONFIG_INPUT_INFO   ii   = {0};
    USB_CONFIG_OUTPUT_INFO  oo   = {0};

    cond.dwSize = sizeof(cond);
    cond.byChannelID = 1;
    ii.lpCondBuffer     = &cond;
    ii.dwCondBufferSize = sizeof(cond);
    ii.lpInBuffer       = (void *)enh;
    ii.dwInBufferSize   = sizeof(*enh);

    /* 先试 V20 */
    if (USB_SetDeviceConfig(uid, USB_SET_IMAGE_ENHANCEMENT_V20, &ii, &oo))
        return 1;

    /* 回退 V1 */
    memset(&ii, 0, sizeof(ii));
    memset(&oo, 0, sizeof(oo));
    ii.lpCondBuffer     = &cond;
    ii.dwCondBufferSize = sizeof(cond);
    ii.lpInBuffer       = (void *)enh;
    ii.dwInBufferSize   = sizeof(*enh);

    if (!USB_SetDeviceConfig(uid, USB_SET_IMAGE_ENHANCEMENT, &ii, &oo)) {
        printf("[camera_config] set_enhancement: V20 和 V1 都失败\n");
        return 0;
    }
    return 1;
}

/* ---- 2a. 伪彩色 ---- */

int camera_get_palette(LONG uid, int *mode)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    *mode = enh.byPaletteMode;
    return 1;
}

int camera_set_palette(LONG uid, int mode)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    enh.byPaletteMode = (BYTE)mode;
    return camera_set_enhancement(uid, &enh);
}

/* ---- 2b. AGC 模式 ---- */

int camera_get_agc_mode(LONG uid, int *mode)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    *mode = enh.byIspAgcMode;
    return 1;
}

int camera_set_agc_mode(LONG uid, int mode)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    enh.byIspAgcMode = (BYTE)mode;
    return camera_set_enhancement(uid, &enh);
}

/* ---- 2c. DDE ---- */

int camera_get_dde_enabled(LONG uid, int *enabled)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    *enabled = enh.byLSEDetailEnabled;
    return 1;
}

int camera_set_dde_enabled(LONG uid, int enabled)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    enh.byLSEDetailEnabled = enabled ? 1 : 0;
    return camera_set_enhancement(uid, &enh);
}

int camera_get_dde_level(LONG uid, DWORD *level)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    *level = enh.dwLSEDetailLevel;
    return 1;
}

int camera_set_dde_level(LONG uid, DWORD level)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    enh.dwLSEDetailLevel = level;
    return camera_set_enhancement(uid, &enh);
}

/* ---- 2d. 降噪 ---- */

int camera_get_noise_reduce_mode(LONG uid, int *mode)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    *mode = enh.byNoiseReduceMode;
    return 1;
}

int camera_set_noise_reduce_mode(LONG uid, int mode)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    enh.byNoiseReduceMode = (BYTE)mode;
    return camera_set_enhancement(uid, &enh);
}

int camera_get_general_denoise(LONG uid, DWORD *level)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    *level = enh.dwGeneralLevel;
    return 1;
}

int camera_set_general_denoise(LONG uid, DWORD level)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    enh.byNoiseReduceMode = 1;
    enh.dwGeneralLevel = level;
    return camera_set_enhancement(uid, &enh);
}

int camera_get_spatial_denoise(LONG uid, DWORD *level)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    *level = enh.dwFrameNoiseReduceLevel;
    return 1;
}

int camera_set_spatial_denoise(LONG uid, DWORD level)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    enh.byNoiseReduceMode = 2;
    enh.dwFrameNoiseReduceLevel = level;
    return camera_set_enhancement(uid, &enh);
}

int camera_get_temporal_denoise(LONG uid, DWORD *level)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    *level = enh.dwInterFrameNoiseReduceLevel;
    return 1;
}

int camera_set_temporal_denoise(LONG uid, DWORD level)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    enh.byNoiseReduceMode = 2;
    enh.dwInterFrameNoiseReduceLevel = level;
    return camera_set_enhancement(uid, &enh);
}

/* ---- 2e. 勾边 ---- */

int camera_get_hook_edge(LONG uid, int *enabled, int *level)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    *enabled = enh.byHookEdgeMode;
    *level   = enh.byHookEdgeLevel;
    return 1;
}

int camera_set_hook_edge(LONG uid, int enabled, int level)
{
    USB_IMAGE_ENHANCEMENT enh = {0};
    if (!camera_get_enhancement(uid, &enh)) return 0;
    enh.byHookEdgeMode  = enabled ? 1 : 0;
    enh.byHookEdgeLevel = (BYTE)level;
    return camera_set_enhancement(uid, &enh);
}

/* ======================================================================== *
 *  3.  视频调整                                                             *
 * ======================================================================== */

int camera_get_video_adjust(LONG uid, USB_IMAGE_VIDEO_ADJUST *va)
{
    memset(va, 0, sizeof(*va));
    va->dwSize = sizeof(*va);
    return get_config(uid, USB_GET_IMAGE_VIDEO_ADJUST_CAMERA, va, sizeof(*va));
}

int camera_set_video_adjust(LONG uid, const USB_IMAGE_VIDEO_ADJUST *va)
{
    return set_config(uid, USB_SET_IMAGE_VIDEO_ADJUST_CAMERA,
                      (void *)va, sizeof(*va));
}

int camera_get_mirror_mode(LONG uid, int *mode)
{
    USB_IMAGE_VIDEO_ADJUST va;
    if (!camera_get_video_adjust(uid, &va)) return 0;
    *mode = va.byImageFlipStyle;
    return 1;
}

int camera_set_mirror_mode(LONG uid, int mode)
{
    USB_IMAGE_VIDEO_ADJUST va;
    if (!camera_get_video_adjust(uid, &va)) return 0;
    va.byImageFlipStyle = (BYTE)mode;
    return camera_set_video_adjust(uid, &va);
}

int camera_get_digital_zoom(LONG uid, int *zoom)
{
    USB_IMAGE_VIDEO_ADJUST va;
    if (!camera_get_video_adjust(uid, &va)) return 0;
    *zoom = va.byDigitalZoom;
    return 1;
}

int camera_set_digital_zoom(LONG uid, int zoom)
{
    USB_IMAGE_VIDEO_ADJUST va;
    if (!camera_get_video_adjust(uid, &va)) return 0;
    va.byDigitalZoom = (BYTE)zoom;
    return camera_set_video_adjust(uid, &va);
}

/* ======================================================================== *
 *  4.  亮度 / 对比度                                                        *
 * ======================================================================== */

int camera_get_brightness(LONG uid, DWORD *value)
{
    USB_IMAGE_BRIGHTNESS b = {0};
    b.dwSize = sizeof(b);
    if (!get_config(uid, USB_GET_IMAGE_BRIGHTNESS, &b, sizeof(b)))
        return 0;
    *value = b.dwBrightness;
    return 1;
}

int camera_set_brightness(LONG uid, DWORD value)
{
    USB_IMAGE_BRIGHTNESS b = {0};
    b.dwSize = sizeof(b);
    b.dwBrightness = value;
    return set_config(uid, USB_SET_IMAGE_BRIGHTNESS, &b, sizeof(b));
}

int camera_get_contrast(LONG uid, DWORD *value)
{
    USB_IMAGE_CONTRAST c = {0};
    c.dwSize = sizeof(c);
    if (!get_config(uid, USB_GET_IMAGE_CONTRAST, &c, sizeof(c)))
        return 0;
    *value = c.dwContrast;
    return 1;
}

int camera_set_contrast(LONG uid, DWORD value)
{
    USB_IMAGE_CONTRAST c = {0};
    c.dwSize = sizeof(c);
    c.dwContrast = value;
    return set_config(uid, USB_SET_IMAGE_CONTRAST, &c, sizeof(c));
}

/* ======================================================================== *
 *  5.  测温基本参数                                                          *
 * ======================================================================== */

int camera_get_thermometry(LONG uid, USB_THERMOMETRY_BASIC_PARAM *tp)
{
    memset(tp, 0, sizeof(*tp));
    tp->dwSize = sizeof(*tp);
    return get_config(uid, USB_GET_THERMOMETRY_BASIC_PARAM, tp, sizeof(*tp));
}

int camera_set_thermometry(LONG uid, const USB_THERMOMETRY_BASIC_PARAM *tp)
{
    return set_config(uid, USB_SET_THERMOMETRY_BASIC_PARAM,
                      (void *)tp, sizeof(*tp));
}

/* ---- 5a. 发射率 ---- */

int camera_get_emissivity(LONG uid, DWORD *value_x100)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *value_x100 = tp.dwEmissivity;
    return 1;
}

int camera_set_emissivity(LONG uid, DWORD value_x100)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.dwEmissivity = value_x100;
    return camera_set_thermometry(uid, &tp);
}

/* ---- 5b. 测温距离 ---- */

int camera_get_distance(LONG uid, DWORD *distance_cm)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *distance_cm = tp.dwDistance;
    return 1;
}

int camera_set_distance(LONG uid, DWORD distance_cm)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.dwDistance = distance_cm;
    return camera_set_thermometry(uid, &tp);
}

int camera_get_distance_unit(LONG uid, int *unit)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *unit = tp.byDistanceUnit;
    return 1;
}

int camera_set_distance_unit(LONG uid, int unit)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.byDistanceUnit = (BYTE)unit;
    return camera_set_thermometry(uid, &tp);
}

/* ---- 5c. 温度单位 ---- */

int camera_get_temp_unit(LONG uid, int *unit)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *unit = tp.byTemperatureUnit;
    return 1;
}

int camera_set_temp_unit(LONG uid, int unit)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.byTemperatureUnit = (BYTE)unit;
    return camera_set_thermometry(uid, &tp);
}

/* ---- 5d. 测温范围 ---- */

int camera_get_temp_range(LONG uid, int *range)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *range = tp.byTemperatureRange;
    return 1;
}

int camera_set_temp_range(LONG uid, int range)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.byTemperatureRange = (BYTE)range;
    return camera_set_thermometry(uid, &tp);
}

int camera_get_temp_range_auto_enabled(LONG uid, int *enabled)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *enabled = tp.byTemperatureRangeAutoChangedEnabled;
    return 1;
}

int camera_set_temp_range_auto_enabled(LONG uid, int enabled)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.byTemperatureRangeAutoChangedEnabled = enabled ? 1 : 0;
    return camera_set_thermometry(uid, &tp);
}

/* ---- 5e. 标定系数 ---- */

int camera_get_calibration_coeff(LONG uid, DWORD *value_x100)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *value_x100 = tp.dwCalibrationCoefficient;
    return 1;
}

int camera_set_calibration_coeff(LONG uid, DWORD value_x100)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.dwCalibrationCoefficient = value_x100;
    return camera_set_thermometry(uid, &tp);
}

int camera_get_calibration_coeff_enabled(LONG uid, int *enabled)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *enabled = tp.byCalibrationCoefficientEnabled;
    return 1;
}

int camera_set_calibration_coeff_enabled(LONG uid, int enabled)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.byCalibrationCoefficientEnabled = enabled ? 1 : 0;
    return camera_set_thermometry(uid, &tp);
}

/* ---- 5f. 反射温度 ---- */

int camera_get_reflective_temp(LONG uid, DWORD *temp_x10)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *temp_x10 = tp.dwReflectiveTemperature;
    return 1;
}

int camera_set_reflective_temp(LONG uid, DWORD temp_x10)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.dwReflectiveTemperature = temp_x10;
    return camera_set_thermometry(uid, &tp);
}

int camera_get_reflective_enabled(LONG uid, int *enabled)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *enabled = tp.byReflectiveEnable;
    return 1;
}

int camera_set_reflective_enabled(LONG uid, int enabled)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.byReflectiveEnable = enabled ? 1 : 0;
    return camera_set_thermometry(uid, &tp);
}

/* ---- 5g. 环境温度 ---- */

int camera_get_env_temp(LONG uid, int *enabled, DWORD *temp)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *enabled = tp.byEnviromentTemperatureEnable;
    *temp    = tp.dwEnviromentTemperature;
    return 1;
}

int camera_set_env_temp(LONG uid, int enabled, DWORD temp)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.byEnviromentTemperatureEnable = (BYTE)enabled;
    tp.dwEnviromentTemperature       = temp;
    return camera_set_thermometry(uid, &tp);
}

/* ---- 5h. 报警温度 ---- */

int camera_get_alert_temp(LONG uid, DWORD *temp_x100)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *temp_x100 = tp.dwAlert;
    return 1;
}

int camera_set_alert_temp(LONG uid, DWORD temp_x100)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.dwAlert = temp_x100;
    return camera_set_thermometry(uid, &tp);
}

int camera_get_alarm_temp(LONG uid, DWORD *temp_x100)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *temp_x100 = tp.dwAlarm;
    return 1;
}

int camera_set_alarm_temp(LONG uid, DWORD temp_x100)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.dwAlarm = temp_x100;
    return camera_set_thermometry(uid, &tp);
}

/* ---- 5i. 显示元素 ---- */

int camera_get_display_flags(LONG uid, int *max_en, int *min_en,
                             int *avg_en, int *cen_en)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *max_en = tp.byDisplayMaxTemperatureEnabled;
    *min_en = tp.byDisplayMinTemperatureEnabled;
    *avg_en = tp.byDisplayAverageTemperatureEnabled;
    *cen_en = tp.byDisplayCenTempEnabled;
    return 1;
}

int camera_set_display_flags(LONG uid, int max_en, int min_en,
                             int avg_en, int cen_en)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.byDisplayMaxTemperatureEnabled     = max_en ? 1 : 0;
    tp.byDisplayMinTemperatureEnabled     = min_en ? 1 : 0;
    tp.byDisplayAverageTemperatureEnabled = avg_en ? 1 : 0;
    tp.byDisplayCenTempEnabled            = cen_en ? 1 : 0;
    return camera_set_thermometry(uid, &tp);
}

/* ---- 5j. 全局开关 / 叠加 ---- */

int camera_get_thermometry_enabled(LONG uid, int *enabled)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *enabled = tp.byEnabled;
    return 1;
}

int camera_set_thermometry_enabled(LONG uid, int enabled)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.byEnabled = enabled ? 1 : 0;
    return camera_set_thermometry(uid, &tp);
}

int camera_get_thermometry_overlay(LONG uid, int *enabled)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *enabled = tp.byThermometryStreamOverlay;
    return 1;
}

int camera_set_thermometry_overlay(LONG uid, int enabled)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.byThermometryStreamOverlay = enabled ? 1 : 0;
    return camera_set_thermometry(uid, &tp);
}

/* ---- 5k. 外部光学 ---- */

int camera_get_external_optics_correction(LONG uid, DWORD *temp)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *temp = tp.dwExternalOpticsWindowCorrection;
    return 1;
}

int camera_set_external_optics_correction(LONG uid, DWORD temp)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.dwExternalOpticsWindowCorrection = temp;
    return camera_set_thermometry(uid, &tp);
}

int camera_get_atmospheric_humidity(LONG uid, DWORD *humidity)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    *humidity = tp.dwAtmosphericHumidity;
    return 1;
}

int camera_set_atmospheric_humidity(LONG uid, DWORD humidity)
{
    USB_THERMOMETRY_BASIC_PARAM tp;
    if (!camera_get_thermometry(uid, &tp)) return 0;
    tp.dwAtmosphericHumidity = humidity;
    return camera_set_thermometry(uid, &tp);
}

/* ======================================================================== *
 *  6.  测温模式                                                             *
 * ======================================================================== */

int camera_get_thermometry_mode(LONG uid, USB_THERMOMETRY_MODE *mode)
{
    memset(mode, 0, sizeof(*mode));
    mode->dwSize = sizeof(*mode);
    return get_config(uid, USB_GET_THERMOMETRY_MODE, mode, sizeof(*mode));
}

int camera_set_thermometry_mode(LONG uid, const USB_THERMOMETRY_MODE *mode)
{
    return set_config(uid, USB_SET_THERMOMETRY_MODE,
                      (void *)mode, sizeof(*mode));
}

/* ======================================================================== *
 *  7.  测温规则区域                                                          *
 * ======================================================================== */

int camera_get_thermometry_regions(LONG uid, USB_THERMOMETRY_REGIONS *regs)
{
    memset(regs, 0, sizeof(*regs));
    regs->dwSize = sizeof(*regs);
    return get_config(uid, USB_GET_THERMOMETRY_REGIONS, regs, sizeof(*regs));
}

int camera_set_thermometry_regions(LONG uid,
                                   const USB_THERMOMETRY_REGIONS *regs)
{
    return set_config(uid, USB_SET_THERMOMETRY_REGIONS,
                      (void *)regs, sizeof(*regs));
}

/* ======================================================================== *
 *  8.  测温修正                                                             *
 * ======================================================================== */

int camera_get_temperature_correct(LONG uid, USB_TEMPERATURE_CORRECT *tc)
{
    memset(tc, 0, sizeof(*tc));
    tc->dwSize = sizeof(*tc);
    return get_config(uid, USB_GET_TEMPERATURE_CORRECT, tc, sizeof(*tc));
}

int camera_set_temperature_correct(LONG uid,
                                   const USB_TEMPERATURE_CORRECT *tc)
{
    return set_config(uid, USB_SET_TEMPERATURE_CORRECT,
                      (void *)tc, sizeof(*tc));
}

/* ======================================================================== *
 *  9.  黑体参数                                                             *
 * ======================================================================== */

int camera_get_black_body(LONG uid, USB_BLACK_BODY *bb)
{
    memset(bb, 0, sizeof(*bb));
    bb->dwSize = sizeof(*bb);
    return get_config(uid, USB_GET_BLACK_BODY, bb, sizeof(*bb));
}

int camera_set_black_body(LONG uid, const USB_BLACK_BODY *bb)
{
    return set_config(uid, USB_SET_BLACK_BODY, (void *)bb, sizeof(*bb));
}

/* ======================================================================== *
 *  10. 体温补偿                                                             *
 * ======================================================================== */

int camera_get_bodytemp_compensation(LONG uid,
                                     USB_BODYTEMP_COMPENSATION *bc)
{
    memset(bc, 0, sizeof(*bc));
    bc->dwSize = sizeof(*bc);
    return get_config(uid, USB_GET_BODYTEMP_COMPENSATION,
                      bc, sizeof(*bc));
}

int camera_set_bodytemp_compensation(LONG uid,
                                     const USB_BODYTEMP_COMPENSATION *bc)
{
    return set_config(uid, USB_SET_BODYTEMP_COMPENSATION,
                      (void *)bc, sizeof(*bc));
}

/* ======================================================================== *
 *  11. 全屏测温参数                                                         *
 * ======================================================================== */

int camera_get_p2p_param(LONG uid, USB_P2P_PARAM *p2p)
{
    memset(p2p, 0, sizeof(*p2p));
    p2p->dwSize = sizeof(*p2p);
    return get_config(uid, USB_GET_P2P_PARAM, p2p, sizeof(*p2p));
}

int camera_set_p2p_param(LONG uid, const USB_P2P_PARAM *p2p)
{
    return set_config(uid, USB_SET_P2P_PARAM, (void *)p2p, sizeof(*p2p));
}

/* ======================================================================== *
 *  12. 热成像码流参数                                                       *
 * ======================================================================== */

int camera_get_thermal_stream_param(LONG uid, USB_THERMAL_STREAM_PARAM *sp)
{
    memset(sp, 0, sizeof(*sp));
    sp->dwSize = sizeof(*sp);
    return get_config(uid, USB_GET_THERMAL_STREAM_PARAM, sp, sizeof(*sp));
}

/* ======================================================================== *
 *  13. 算法版本                                                             *
 * ======================================================================== */

int camera_get_thermal_alg_version(LONG uid, USB_THERMAL_ALG_VERSION *ver)
{
    memset(ver, 0, sizeof(*ver));
    ver->dwSize = sizeof(*ver);
    return get_config(uid, USB_GET_THERMAL_ALG_VERSION, ver, sizeof(*ver));
}

/* ======================================================================== *
 *  14. 诊断信息导出                                                         *
 * ======================================================================== */

int camera_get_system_diagnosed_data(LONG uid,
                                     USB_SYSTEM_DIAGNOSED_DATA *dd)
{
    dd->dwSize = sizeof(*dd);
    return get_config(uid, USB_GET_SYSTEM_DIAGNOSED_DATA, dd, sizeof(*dd));
}

/* ======================================================================== *
 *  15. ROI 最高温搜索                                                       *
 * ======================================================================== */

int camera_get_roi_max_temperature_search(
        LONG uid,
        USB_ROI_MAX_TEMPERATURE_SEARCH *in,
        USB_ROI_MAX_TEMPERATURE_SEARCH_RESULT *out)
{
    USB_COMMON_COND         cond = {0};
    USB_CONFIG_INPUT_INFO   ii   = {0};
    USB_CONFIG_OUTPUT_INFO  oo   = {0};

    cond.dwSize = sizeof(cond);
    cond.byChannelID = 1;
    in->dwSize = sizeof(*in);

    ii.lpCondBuffer     = &cond;
    ii.dwCondBufferSize = sizeof(cond);
    ii.lpInBuffer       = in;
    ii.dwInBufferSize   = sizeof(*in);
    oo.lpOutBuffer      = out;
    oo.dwOutBufferSize  = sizeof(*out);

    if (!USB_GetDeviceConfig(uid, USB_GET_ROI_MAX_TEMPERATURE_SEARCH,
                             &ii, &oo)) {
        printf("[camera_config] get_roi_max_temperature_search 失败\n");
        return 0;
    }
    return 1;
}

/* ======================================================================== *
 *  16. 双光校准                                                             *
 * ======================================================================== */

int camera_post_double_lights_correct(
        LONG uid,
        const USB_DOUBLE_LIGHTS_CORRECT *in,
        USB_DOUBLE_LIGHTS_CORRECT_RESULT *out)
{
    USB_COMMON_COND         cond = {0};
    USB_CONFIG_INPUT_INFO   ii   = {0};
    USB_CONFIG_OUTPUT_INFO  oo   = {0};

    cond.dwSize = sizeof(cond);
    cond.byChannelID = 1;

    ii.lpCondBuffer     = &cond;
    ii.dwCondBufferSize = sizeof(cond);
    ii.lpInBuffer       = (void *)in;
    ii.dwInBufferSize   = sizeof(*in);
    oo.lpOutBuffer      = out;
    oo.dwOutBufferSize  = sizeof(*out);

    if (!USB_GetDeviceConfig(uid, USB_POST_DOUBLE_LIGHTS_CORRECT,
                             &ii, &oo)) {
        printf("[camera_config] post_double_lights_correct 失败\n");
        return 0;
    }
    return 1;
}

int camera_get_double_lights_correct_points_ctrl(
        LONG uid, USB_DOUBLE_LIGHTS_CORRECT_POINTS_CTRL *ctrl)
{
    memset(ctrl, 0, sizeof(*ctrl));
    ctrl->dwSize = sizeof(*ctrl);
    return get_config(uid, USB_GET_DOUBLE_LIGHTS_CORRECT_POINTS_CTRL,
                      ctrl, sizeof(*ctrl));
}

int camera_set_double_lights_correct_points_ctrl(
        LONG uid, const USB_DOUBLE_LIGHTS_CORRECT_POINTS_CTRL *ctrl)
{
    return set_config(uid, USB_SET_DOUBLE_LIGHTS_CORRECT_POINTS_CTRL,
                      (void *)ctrl, sizeof(*ctrl));
}

/* ======================================================================== *
 *  17. 测温标定文件                                                         *
 * ======================================================================== */

int camera_get_thermometry_calibration_file(
        LONG uid, USB_THERMOMETRY_CALIBRATION_FILE *cf)
{
    cf->dwSize = sizeof(*cf);
    return get_config(uid, USB_GET_THERMOMETRY_CALIBRATION_FILE,
                      cf, sizeof(*cf));
}

int camera_set_thermometry_calibration_file(
        LONG uid, const USB_THERMOMETRY_CALIBRATION_FILE *cf)
{
    return set_config(uid, USB_SET_THERMOMETRY_CALIBRATION_FILE,
                      (void *)cf, sizeof(*cf));
}

/* ======================================================================== *
 *  18. 命令状态                                                             *
 * ======================================================================== */

int camera_get_command_state(LONG uid, USB_COMMAND_STATE *state)
{
    memset(state, 0, sizeof(*state));
    state->dwSize = sizeof(*state);
    if (!USB_GetCommandState(uid, state)) {
        printf("[camera_config] get_command_state 失败\n");
        return 0;
    }
    return 1;
}