From 208998c13aa8dcd20f78ed7e1ab59d23189b00f5 Mon Sep 17 00:00:00 2001 From: 916BGAI <916772719@qq.com> Date: Tue, 9 Jun 2026 18:00:32 +0800 Subject: [PATCH] support lt6911d --- kvmapp/system/init.d/S03usbdev | 22 +- kvmapp/system/init.d/S15kvmhwd | 41 ++-- .../sg2002/additional/kvm/src/kvm_vision.cpp | 190 +++++++++++---- .../main/lib/system_init/system_init.cpp | 8 +- tools/nanokvm_update_edid/nanokvm_update_edid | Bin 24240 -> 28464 bytes .../nanokvm_update_edid/nanokvm_update_edid.c | 217 ++++++++++++++++-- .../nanokvm_update_edid/nanokvm_update_edid.h | 6 +- 7 files changed, 382 insertions(+), 102 deletions(-) diff --git a/kvmapp/system/init.d/S03usbdev b/kvmapp/system/init.d/S03usbdev index df5e248..e4a2c83 100755 --- a/kvmapp/system/init.d/S03usbdev +++ b/kvmapp/system/init.d/S03usbdev @@ -1,5 +1,5 @@ #!/bin/sh -# kvmhwd Rev2.1 +# kvmhwd Rev2.2 start_usb_dev(){ . /etc/profile @@ -23,6 +23,11 @@ start_usb_dev(){ else echo 0x1009 > idProduct fi + + echo 0xEF > bDeviceClass + echo 0x02 > bDeviceSubClass + echo 0x01 > bDeviceProtocol + mkdir strings/0x409 echo '0123456789ABCDEF' > strings/0x409/serialnumber echo 'sipeed' > strings/0x409/manufacturer @@ -37,15 +42,30 @@ start_usb_dev(){ if [ -e /boot/usb.ncm ] then mkdir functions/ncm.usb0 + echo WINNCM > functions/ncm.usb0/os_desc/interface.ncm/compatible_id ln -s functions/ncm.usb0 configs/c.1/ else if [ -e /boot/usb.rndis0 ] then mkdir functions/rndis.usb0 + echo e0 > functions/rndis.usb0/class + echo 01 > functions/rndis.usb0/subclass + echo 03 > functions/rndis.usb0/protocol + echo RNDIS > functions/rndis.usb0/os_desc/interface.rndis/compatible_id + echo 5162001 > functions/rndis.usb0/os_desc/interface.rndis/sub_compatible_id ln -s functions/rndis.usb0 configs/c.1/ fi fi + if [ -e /boot/usb.ncm ] || [ -e /boot/usb.rndis0 ] + then + # Microsoft OS 2.0 Descriptor + echo 1 > os_desc/use + echo 0xCD > os_desc/b_vendor_code + echo MSFT100 > os_desc/qw_sign + ln -s configs/c.1 os_desc + fi + if [ ! -e /boot/disable_hid ] then # keyboard diff --git a/kvmapp/system/init.d/S15kvmhwd b/kvmapp/system/init.d/S15kvmhwd index e2e2575..6cbafef 100755 --- a/kvmapp/system/init.d/S15kvmhwd +++ b/kvmapp/system/init.d/S15kvmhwd @@ -1,5 +1,5 @@ #!/bin/sh -# kvmhwd Rev2.4 +# kvmhwd Rev2.5 Alpha_OLED_RST_Pin=371 Beta_OLED_RST_Pin=502 @@ -25,7 +25,7 @@ init_alpha_hw(){ devmem 0x03001060 32 0x3 # GPIOA24 devmem 0x03001054 32 0x3 # GPIOA25 devmem 0x03001058 32 0x3 # GPIOA27 - + devmem 0x03001068 32 0x6 # GPIOA 18 UART1 RX devmem 0x03001064 32 0x6 # GPIOA 19 UART1 TX devmem 0x03001070 32 0x2 # GPIOA 28 UART2 TX @@ -146,19 +146,7 @@ kvm_hw_detect(){ insmod /mnt/system/ko/i2c-algo-bit.ko insmod /mnt/system/ko/i2c-gpio.ko - kvm_tmp=$(i2cdetect -ry 4 0x2c 0x2c | grep 2c) - if [ -n "$kvm_tmp" ] - then - echo "c" > /etc/kvm/hdmi_version - else - kvm_tmp1=$(i2cdetect -ry 4 0x2b 0x2b | grep 2b) - if [ -n "$kvm_tmp1" ] - then - echo "ux" > /etc/kvm/hdmi_version - else - echo "ue" > /etc/kvm/hdmi_version - fi - fi + kvm_hdmi_version_detect kvm_tmp=$(i2cdetect -ry 5 0x3c 0x3c | grep 3c) if [ -n "$kvm_tmp" ] @@ -199,20 +187,19 @@ kvm_hw_init(){ fi } -kvm_hdmi_version_detect(){ - hdmi_tmp=$(i2cdetect -ry 4 0x2c 0x2c | grep 2c) - if [ -n "$hdmi_tmp" ] - then - echo "c" > /etc/kvm/hdmi_version - else - hdmi_tmp1=$(i2cdetect -ry 4 0x2b 0x2b | grep 2b) - if [ -n "$hdmi_tmp1" ] - then - echo "ux" > /etc/kvm/hdmi_version +kvm_hdmi_version_detect() +{ + if i2cdetect -ry 4 0x2c 0x2c | grep -qw "2c"; then + echo "c" > /etc/kvm/hdmi_version + elif i2cdetect -ry 4 0x2b 0x2b | grep -qw "2b"; then + if i2cdetect -ry 4 0x44 0x44 | grep -qw "44"; then + echo "ux" > /etc/kvm/hdmi_version + else + echo "d" > /etc/kvm/hdmi_version + fi else - echo "ue" > /etc/kvm/hdmi_version + echo "ue" > /etc/kvm/hdmi_version fi - fi } case "$1" in diff --git a/support/sg2002/additional/kvm/src/kvm_vision.cpp b/support/sg2002/additional/kvm/src/kvm_vision.cpp index 2e67ce4..8e260f3 100644 --- a/support/sg2002/additional/kvm/src/kvm_vision.cpp +++ b/support/sg2002/additional/kvm/src/kvm_vision.cpp @@ -222,7 +222,7 @@ uint8_t get_vi_state() uint8_t VIWHGTLSCnt[4]; FILE* fp = popen( cmd, "r" ); uint8_t ret = 0; - + if (fgets(VI_State, sizeof(VI_State), fp) != NULL){ FPS[0] = atoi(VI_State); // debug("VIDevFPS = %d\n", FPS[0]); @@ -318,7 +318,7 @@ uint8_t watchdog_sf_is_open(void) else return 0; } -int vision_update_watchdog() +int vision_update_watchdog() { FILE *file; @@ -344,7 +344,7 @@ int get_manual_resolution(void) if(access("/kvmapp/kvm/width", F_OK) == 0){ fp = fopen("/kvmapp/kvm/width", "r"); fseek(fp, 0, SEEK_END); - file_size = ftell(fp); + file_size = ftell(fp); fseek(fp, 0, SEEK_SET); fread(RW_Data, sizeof(char), file_size, fp); fclose(fp); @@ -356,7 +356,7 @@ int get_manual_resolution(void) if(access("/kvmapp/kvm/height", F_OK) == 0){ fp = fopen("/kvmapp/kvm/height", "r"); fseek(fp, 0, SEEK_END); - file_size = ftell(fp); + file_size = ftell(fp); fseek(fp, 0, SEEK_SET); fread(RW_Data, sizeof(char), file_size, fp); fclose(fp); @@ -495,15 +495,20 @@ uint8_t chack_ion() void lt6911_enable() { uint8_t buf[2]; + + if(kvmv_cfg.hdmi_version == 3){ + return; + } + buf[0] = 0xff; buf[1] = 0x80; LT6911_i2c.writeto(LT6911_ADDR, buf, 2); - + buf[0] = 0xee; buf[1] = 0x01; LT6911_i2c.writeto(LT6911_ADDR, buf, 2); - if(kvmv_cfg.hdmi_version != 0){ + if(kvmv_cfg.hdmi_version == 1){ // disable watchdog buf[0] = 0x10; buf[1] = 0x00; @@ -514,10 +519,15 @@ void lt6911_enable() void lt6911_disable() { uint8_t buf[2]; + + if(kvmv_cfg.hdmi_version == 3){ + return; + } + buf[0] = 0xff; buf[1] = 0x80; LT6911_i2c.writeto(LT6911_ADDR, buf, 2); - + buf[0] = 0xee; buf[1] = 0x00; LT6911_i2c.writeto(LT6911_ADDR, buf, 2); @@ -629,6 +639,38 @@ uint8_t lt6911_get_hdmi_res() if(revbuf[0] == 0x55) return 1; else if(revbuf[0] == 0x88) return 0; else return 0; + } else if (kvmv_cfg.hdmi_version == 3){ + // LT6911D + buf[0] = 0xff; + buf[1] = 0xe0; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); + + // Hactive + buf[0] = 0x8c; + LT6911_i2c.writeto(LT6911_ADDR, buf, 1); + maix::Bytes *dat0 = LT6911_i2c.readfrom(LT6911_ADDR, 2); + + // Vactive + buf[0] = 0x8e; + LT6911_i2c.writeto(LT6911_ADDR, buf, 1); + maix::Bytes *dat1 = LT6911_i2c.readfrom(LT6911_ADDR, 2); + + revbuf[0] = (uint8_t)dat0->data[0]; + revbuf[1] = (uint8_t)dat0->data[1]; + revbuf[2] = (uint8_t)dat1->data[0]; + revbuf[3] = (uint8_t)dat1->data[1]; + + Hactive = ((revbuf[0] << 8)|revbuf[1]) * 2; + Vactive = (revbuf[2] << 8)|revbuf[3]; + + debug("[hdmi]HDMI-D res modification event\n"); + debug("[hdmi]new res: %d * %d\n", Hactive, Vactive); + + delete dat0; + delete dat1; + + if(Hactive != 0 || Vactive != 0) return 1; + else return 0; } else { return 0; } @@ -686,7 +728,7 @@ uint8_t lt6911_get_csi_res(uint16_t *p_width, uint16_t *p_height) uint16_t Hactive; if(kvmv_cfg.hdmi_version == 0){ - // LT6911C + // LT6911C buf[0] = 0xff; buf[1] = 0xc2; LT6911_i2c.writeto(LT6911_ADDR, buf, 2); @@ -705,7 +747,7 @@ uint8_t lt6911_get_csi_res(uint16_t *p_width, uint16_t *p_height) revbuf[1] = (uint8_t)dat0->data[1]; revbuf[2] = (uint8_t)dat1->data[0]; revbuf[3] = (uint8_t)dat1->data[1]; - + delete dat0; delete dat1; @@ -738,6 +780,33 @@ uint8_t lt6911_get_csi_res(uint16_t *p_width, uint16_t *p_height) Vactive = (revbuf[0] << 8)|revbuf[1]; Hactive = (revbuf[2] << 8)|revbuf[3]; + } else if(kvmv_cfg.hdmi_version == 3) { + // LT6911D + debug("[hdmi]D get csi res\n"); + buf[0] = 0xff; + buf[1] = 0xe0; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); + + // Vactive + buf[0] = 0x8e; + LT6911_i2c.writeto(LT6911_ADDR, buf, 1); + maix::Bytes *dat0 = LT6911_i2c.readfrom(LT6911_ADDR, 2); + + // Hactive + buf[0] = 0x8c; + LT6911_i2c.writeto(LT6911_ADDR, buf, 1); + maix::Bytes *dat1 = LT6911_i2c.readfrom(LT6911_ADDR, 2); + + revbuf[0] = (uint8_t)dat0->data[0]; + revbuf[1] = (uint8_t)dat0->data[1]; + revbuf[2] = (uint8_t)dat1->data[0]; + revbuf[3] = (uint8_t)dat1->data[1]; + + delete dat0; + delete dat1; + + Vactive = (revbuf[0] << 8)|revbuf[1]; + Hactive = ((revbuf[2] << 8)|revbuf[3]) * 2; } else { return UNKNOWN_RES; } @@ -790,7 +859,7 @@ void lt6911_read_reg(uint8_t reg) buf[0] = reg; LT6911_i2c.writeto(LT6911_ADDR, buf, 1); - maix::Bytes *dat = LT6911_i2c.readfrom(LT6911_ADDR, 16); + maix::Bytes *dat = LT6911_i2c.readfrom(LT6911_ADDR, 16); for(int i = 0; i < 16; i++){ buf[i] = (uint8_t)dat->data[i]; @@ -809,7 +878,7 @@ uint8_t lt6911_read_one_reg(uint8_t reg) ret = reg; LT6911_i2c.writeto(LT6911_ADDR, &ret, 1); - maix::Bytes *dat = LT6911_i2c.readfrom(LT6911_ADDR, 1); + maix::Bytes *dat = LT6911_i2c.readfrom(LT6911_ADDR, 1); ret = (uint8_t)dat->data[0]; @@ -846,7 +915,7 @@ void lt6911_write_edid(void) lt6911_write_reg(0x5E, 0xEF); lt6911_write_reg(0x5A, 0xA2); lt6911_write_reg(0x5A, 0x82); - + lt6911_write_reg(0x58, 0x01); if(i < 8) { @@ -1048,6 +1117,10 @@ void get_hdmi_version() kvmv_cfg.hdmi_version = 1; debug("[hdmi]Incomplete version number, set to 'ux'\n"); } + } else if(RW_Data[0] == 'd'){ + // 6911d + kvmv_cfg.hdmi_version = 3; + debug("[hdmi]HDMI-D exist!\n"); } else { // 6911c kvmv_cfg.hdmi_version = 0; @@ -1085,7 +1158,7 @@ void* vi_subsystem_detection(void * arg) { if(kvmv_cfg.try_exit_thread == 1) break; - + uint8_t get_new_hdmi_mode = get_hdmi_mode(); uint8_t try_res; uint8_t err_code; @@ -1109,7 +1182,7 @@ void* vi_subsystem_detection(void * arg) fp = fopen(hdmi_state_path, "r+"); if(fp != NULL){ // fseek(fp, 0, SEEK_END); - // file_size = ftell(fp); + // file_size = ftell(fp); // fseek(fp, 0, SEEK_SET); fread(RW_Data, sizeof(char), 2, fp); tmp8 = atoi((char*)RW_Data); @@ -1134,7 +1207,7 @@ void* vi_subsystem_detection(void * arg) kvmv_cfg.hdmi_res_type = lt6911_get_csi_res(&kvmv_cfg.vi_width, &kvmv_cfg.vi_height); if (kvmv_cfg.hdmi_res_type == NEW_RES) kvmv_cfg.reopen_cam_flag = 1; else if (kvmv_cfg.hdmi_res_type == UNKNOWN_RES){ - /* Move HDMI resolution modification directly + /* Move HDMI resolution modification directly to mode1 to solve deadlock problem */ auto_change_mode = 1; set_hdmi_mode(1); @@ -1159,7 +1232,7 @@ void* vi_subsystem_detection(void * arg) kvmv_cfg.hdmi_res_type = lt6911_get_csi_res(&kvmv_cfg.vi_width, &kvmv_cfg.vi_height); if (kvmv_cfg.hdmi_res_type == NEW_RES) kvmv_cfg.reopen_cam_flag = 1; else if (kvmv_cfg.hdmi_res_type == UNKNOWN_RES){ - /* Move HDMI resolution modification directly + /* Move HDMI resolution modification directly to mode1 to solve deadlock problem */ auto_change_mode = 1; set_hdmi_mode(1); @@ -1171,6 +1244,31 @@ void* vi_subsystem_detection(void * arg) } lt6911_disable(); } + } else if (kvmv_cfg.hdmi_version == 3){ + // LT6911D + debug("[hdmi] D int\n"); + if(falling_times != 0){ + debug("[hdmi] D int && \n"); + lt6911_enable(); + if(lt6911_get_hdmi_res()){ + // hdmi get res + debug("[hdmi] D HDMI cable insertion!\n"); + kvmv_cfg.hdmi_cable_state = 1; + kvmv_cfg.hdmi_res_type = lt6911_get_csi_res(&kvmv_cfg.vi_width, &kvmv_cfg.vi_height); + if (kvmv_cfg.hdmi_res_type == NEW_RES) kvmv_cfg.reopen_cam_flag = 1; + else if (kvmv_cfg.hdmi_res_type == UNKNOWN_RES){ + /* Move HDMI resolution modification directly + to mode1 to solve deadlock problem */ + auto_change_mode = 1; + set_hdmi_mode(1); + } + } else { + // HDMI res = 0*0/x*0 + debug("[hdmi] D HDMI cable unplugged!\n"); + kvmv_cfg.hdmi_cable_state = 0; + } + lt6911_disable(); + } } else { debug("[hdmi] Chip not supported for reading \n"); } @@ -1180,15 +1278,15 @@ void* vi_subsystem_detection(void * arg) fclose(fp); } break; - /* Mode 1 & 2 will disable API access to the image during detection, + /* Mode 1 & 2 will disable API access to the image during detection, and will output -4: Modifying image resolution, please wait.*/ case 1: // Automatically trying common resolutions - /* kvmv_cfg.vi_detect_state : + /* kvmv_cfg.vi_detect_state : * 0: HDMI standard mode, detection program does not interfere with the camera * 1: Preparing / Testing in progress * 2: Test completed: Suitable resolution found, */ - + if(get_new_hdmi_mode == 1){ kvmv_cfg.vi_detect_state = 1; } @@ -1199,9 +1297,9 @@ void* vi_subsystem_detection(void * arg) kvmv_cfg.hdmi_try_rounds = 0; kvmv_cfg.vi_detect_state = 2; } else if (try_res == 0) { - /* There may be a situation where the correct resolution cannot be recognized - after one round of detection. By default, Try_rounds_HDMI_err_res rounds will be detected, - and if it cannot be detected, jump to the next mode */ + /* There may be a situation where the correct resolution cannot be recognized + after one round of detection. By default, Try_rounds_HDMI_err_res rounds will be detected, + and if it cannot be detected, jump to the next mode */ kvmv_cfg.hdmi_res_err = ERROR_RES; kvmv_cfg.hdmi_try_rounds++; if(kvmv_cfg.hdmi_try_rounds >= Try_rounds_HDMI_err_res){ @@ -1226,7 +1324,7 @@ void* vi_subsystem_detection(void * arg) if (err_code != 1) { kvmv_cfg.vi_detect_state = 1; } - time::sleep_ms(1000); + time::sleep_ms(1000); } else { kvmv_cfg.vi_detect_state = 1; } @@ -1280,7 +1378,7 @@ void* vi_subsystem_detection(void * arg) } } break; - + default: debug("Non-existent hdmi state = %d\n", kvmv_cfg.hdmi_mode); break; @@ -1308,7 +1406,7 @@ int sync_vi_res() } else { fp = fopen(vi_width_path, "r"); fseek(fp, 0, SEEK_END); - file_size = ftell(fp); + file_size = ftell(fp); fseek(fp, 0, SEEK_SET); fread(RW_Data, sizeof(char), file_size, fp); fclose(fp); @@ -1328,7 +1426,7 @@ int sync_vi_res() } else { fp = fopen(vi_height_path, "r"); fseek(fp, 0, SEEK_END); - file_size = ftell(fp); + file_size = ftell(fp); fseek(fp, 0, SEEK_SET); fread(RW_Data, sizeof(char), file_size, fp); fclose(fp); @@ -1465,15 +1563,15 @@ int8_t raw_to_h264(image::Image *raw, kvmv_data_t* ret_stream, uint16_t _qlty) // log::info("getimg: %d \r\n", (int)(time::time_ms())); mmf_stream_t _stream = {0}; if(kvm_venc.enc_h264_init != 1 || raw->width() != kvm_venc.kvm_venc_cfg.w || raw->height() != kvm_venc.kvm_venc_cfg.h || _qlty != kvm_venc.kvm_venc_cfg.bitrate){ - debug("[kvmv]init_venc_h264 enc_h264_init = %d; raw->width() = %d | %d raw->height() = %d | %d \n", - kvm_venc.enc_h264_init, - raw->width(), kvm_venc.kvm_venc_cfg.w, + debug("[kvmv]init_venc_h264 enc_h264_init = %d; raw->width() = %d | %d raw->height() = %d | %d \n", + kvm_venc.enc_h264_init, + raw->width(), kvm_venc.kvm_venc_cfg.w, raw->height(), kvm_venc.kvm_venc_cfg.h); - init_venc_h264(raw->width(), raw->height(), _qlty); - debug("[kvmv]init_venc_h264 finish enc_h264_init = %d; raw->width() = %d | %d raw->height() = %d | %d \n", - kvm_venc.enc_h264_init, - raw->width(), kvm_venc.kvm_venc_cfg.w, + init_venc_h264(raw->width(), raw->height(), _qlty); + debug("[kvmv]init_venc_h264 finish enc_h264_init = %d; raw->width() = %d | %d raw->height() = %d | %d \n", + kvm_venc.enc_h264_init, + raw->width(), kvm_venc.kvm_venc_cfg.w, raw->height(), kvm_venc.kvm_venc_cfg.h); // if(kvm_venc.enc_h264_init == 1){ // init_venc_h264(raw->width(), raw->height(), _qlty); @@ -1489,8 +1587,8 @@ int8_t raw_to_h264(image::Image *raw, kvmv_data_t* ret_stream, uint16_t _qlty) debug("[kvmv]mmf venc push failed!\n"); // err::check_raise(err::ERR_RUNTIME, "mmf venc push failed!\r\n"); return -1; - } - // log::info("push(): %d \r\n", (int)(time::time_ms() - start_time)); + } + // log::info("push(): %d \r\n", (int)(time::time_ms() - start_time)); if (mmf_venc_pop(kvm_venc.mmf_venc_chn, &_stream)) { // log::error("mmf_venc_pop failed\n"); mmf_venc_free(kvm_venc.mmf_venc_chn); @@ -1500,10 +1598,10 @@ int8_t raw_to_h264(image::Image *raw, kvmv_data_t* ret_stream, uint16_t _qlty) // rtmp->unlock(); return -1; } - // log::info("pop(): %d \r\n", (int)(time::time_ms() - start_time)); + // log::info("pop(): %d \r\n", (int)(time::time_ms() - start_time)); ret = h264_stream_dump(ret_stream, &_stream); mmf_venc_free(kvm_venc.mmf_venc_chn); - // log::info("dump(): %d \r\n", (int)(time::time_ms() - start_time)); + // log::info("dump(): %d \r\n", (int)(time::time_ms() - start_time)); // debug("[kvmv]_stream.data[0][4] = %d;\n", _stream.data[0][4]); debug("[kvmv]Frame size = %d;\n", ret_stream->img_data_size); @@ -1539,7 +1637,7 @@ void kvmv_init(uint8_t _debug_info_en) kvmv_cfg.try_exit_thread = 0; // debug("[kvmv]kvmv_init - 2\r\n"); - + if(kvmv_cfg.thread_is_running == 1){ debug("[kvmv]thread is running!\r\n"); } else { @@ -1656,14 +1754,14 @@ int kvmv_read_img(uint16_t _width, uint16_t _height, uint8_t _type, uint16_t _ql // Set the output kvmv_cfg.vpss_width = _width; kvmv_cfg.vpss_height = _height; - + cam->set_resolution(kvmv_cfg.vpss_width, kvmv_cfg.vpss_height); kvmv_cfg.reinit_flag = 1; } } // - if (kvmv_cfg.reinit_flag == 1) { + if (kvmv_cfg.reinit_flag == 1) { cam->hmirror(1); cam->vflip(1); kvmv_cfg.reinit_flag = 0; @@ -1671,7 +1769,7 @@ int kvmv_read_img(uint16_t _width, uint16_t _height, uint8_t _type, uint16_t _ql // debug("[kvmv]befor read img: %d \r\n", (int)(time::time_ms() - start_time)); image::Image *img = cam->read(); // debug("[kvmv]read img: %d \r\n", (int)(time::time_ms() - start_time)); - + if(img != NULL){ // frame detect if(_type == VENC_MJPEG && kvmv_cfg.frame_detact != 0){ @@ -1680,10 +1778,10 @@ int kvmv_read_img(uint16_t _width, uint16_t _height, uint8_t _type, uint16_t _ql } else { frame_undetact_count = kvmv_cfg.frame_detact; } - + if(frame_undetact_count == kvmv_cfg.frame_detact){ frame_undetact_count = 0; - + if(frame_changed(img) == 0){ debug("[kvmv]frame not changed...\n"); kvmv_cfg.stream_stop = 1; @@ -1694,7 +1792,7 @@ int kvmv_read_img(uint16_t _width, uint16_t _height, uint8_t _type, uint16_t _ql kvmv_cfg.stream_stop = 0; } } - } + } if(kvmv_cfg.cam_state == 0) { kvmv_cfg.cam_state = 1; kvmv_cfg.hdmi_cable_state = 1; @@ -1741,7 +1839,7 @@ int kvmv_read_img(uint16_t _width, uint16_t _height, uint8_t _type, uint16_t _ql *_pp_kvm_data = NULL; pthread_mutex_unlock(&vi_mutex); return IMG_BUFFER_FULL; - } + } jpg_dump(p_kvmv_data, jpg); delete jpg; delete img; @@ -1758,7 +1856,7 @@ int kvmv_read_img(uint16_t _width, uint16_t _height, uint8_t _type, uint16_t _ql *_pp_kvm_data = NULL; pthread_mutex_unlock(&vi_mutex); return IMG_BUFFER_FULL; - } + } // debug("[kvmv]get_save_buffer: %d \r\n", (int)(time::time_ms() - start_time)); ret = raw_to_h264(img, p_kvmv_data, maxmin_data(10000, 500, (int)_qlty)); // debug("[kvmv]venc raw_to_h264: %d \r\n", (int)(time::time_ms() - start_time)); diff --git a/support/sg2002/kvm_system/main/lib/system_init/system_init.cpp b/support/sg2002/kvm_system/main/lib/system_init/system_init.cpp index f858193..950dee7 100644 --- a/support/sg2002/kvm_system/main/lib/system_init/system_init.cpp +++ b/support/sg2002/kvm_system/main/lib/system_init/system_init.cpp @@ -17,7 +17,7 @@ uint8_t get_hdmi_version() fread(RW_Data, sizeof(char), 2, fp); fclose(fp); if(RW_Data[0] == 'u'){ - // 6911uxc + // 6911uxc / 6911uxe if(RW_Data[1] == 'e'){ return 2; } else if(RW_Data[1] == 'x') { @@ -25,6 +25,9 @@ uint8_t get_hdmi_version() } else { return 1; } + } else if(RW_Data[0] == 'd'){ + // 6911d + return 3; } else { // 6911c return 0; @@ -139,6 +142,7 @@ void new_app_init(void) fclose(fp); if(RW_Data[0] == 'c') hdmi_ver = 1; else if(RW_Data[0] == 'u') hdmi_ver = 2; + else if(RW_Data[0] == 'd') hdmi_ver = 2; } // system("/etc/init.d/S03usbdev stop_start"); @@ -195,4 +199,4 @@ void new_img_init(void) { build_complete_resolv(); system("rm /kvmapp/kvm_new_img"); -} \ No newline at end of file +} diff --git a/tools/nanokvm_update_edid/nanokvm_update_edid b/tools/nanokvm_update_edid/nanokvm_update_edid index 8b2489ed51c72931ed65bfee671abce24b44a39c..2ee62cc05e9a99017151696039b1efbc29c87e42 100755 GIT binary patch delta 8288 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 delta 5441 zcmai24OCQB9=~q}crhX~%%~%p!ioWE0hS+#3Yg)T)c~cA-!OsUM*(&`>z+Ni0}hX; z>@tYgjq=oy^^mf&rr4C3n=WRXX0_VxTDI%j_|=DB4>vbM9o+xD@73!wnoB zu@Zy^92 z9j~K(3v_%P?VGRT>uBFR9Uo{9@6hMc3Fv6wTpeFW`{wBQI@&i|$Ddu{>6NkXDV>0h z_C2ZN>u6uGj<2JAMLK@bxZZ%Tus0nardx^;!nH!DNopy;adD&XzqrT!w!Hu$TlCT? zEe>GHUr#Qp-+?g9oaV#puVU3WXEu_Jhq`8Njn zLwwpi!61H&2Uw@TL&9vXm9* z-+?OwM;Zsw3W59_hW|(DQrdB4^8NR^(0lenI7PhC!-S?Wqh|t@iAOb~y`15hLv#A@ zg*Oi^?*k5)?(K|(HkO4D44fYJf+3trBs9DtS+fpKxnTAtHwgIDm=T^0jdz! z@vIW`;E-$5t_^f@$mf9G?3Z)plwD_i-W`XU%Dxa0onq&e;PFt%b#f;`Z804N9Gz92 zD=ERMZogc1Mw7Y-^lc(RIA1o0T%Wdi)84;Y>q%==ysoyZ2PNb9sH;j>mCrAK_z?@o z7E{e;%C`_eL)buL$W=@Y43$MBIm(9LH1JlM?)c?BMxTtGbj8bf3jX9^jwt(c4d7I_|X<)JL8jeO5K)aOB zd#6#u(zvDs%{|Pvr#9qqt@RTFkvw=aNk@C^2Av=or z!vv^A(|JgwM@p-OzXQL8_Ohleje_d!zM^tdQg8H-9!VIBUFP%u{Q4I25?+Bnfc&MD zk<<&_yS!<2Jvb)n?%o#f5m~8C%dJ=a=A?jQ^J&8VDaV-?@vk#~;Rz~Vhg`#2sVi6t zPz6@YTaeN@R;Q+mwT@irjcV)aIqr2eLPE@y5#Jz-UnXJG>3&BE7Jfo|2!i~W_KXk% z?TI2x^N&b+kUo8D<2ulDGm40c{XpPD+B3ttIZAsr2te)Gp^8T+HdF~JACR6r92}~> zWN`Rb0i7#-xIFqNgKIiWwMK&edt4y+<*a_oC?^#-ozw>eTi6+~_rR){Ya=cpE0r1z zksKuFhIoNYnw)xVW(PC>?3dNUMSKAC->r2tw%b60o-7$TWH>&;abuH=LFFBsF*d_Q zU1dVrZ{cUgrV1Nyp`%xKV?eW9XPf^FDq;=*kafrAwLB5`HSROyB#9A zZJbaSf>;b>?H&K4U;h1hropy#aRSJ{OAo~0?!A)Z)m>^|d5gwKym}-t8_Mv;&$&JR zw&b{P7r5=_-BxYm-L7SO@FWQ6P1RN5Zpk5RSNl!7pggxD`2cSmH)x3Z z3(7k&>YG=}w7sW@7HmE495>V$G&kZi2e%U*(k?PqZ6d<=t?O ze7j#Fv)J73mz$5XIN2#AyCCo1NseOJvf$U-dE%S1HXp2=*a|zT8ZMmT18$;nF!r8z zZh1FMp>N6JpHNR-beXTiScF|f_C9$bEWUcl5#8F`5V$_TYP0oqvLk+9J$H2?Y&r-9 zJ{!NufcItp3-6!g3}oeWMg=T+StgwBbi-x5!I=cD-`OM-1#${^3ve^PRP>^lSTlyd zKC0InBkG4vpf7%Zl+`C5kFxv3&4_(E;4V?2e=OSKtZbDOjCVjXhFP) z&jR;VYB?5d(eiy$a~Z%1rFO%911Yf3iKms?6HjSDY}5r2#H&i}?rXp$1!7;JSb_eh zIhbuz-REl#j5I9x)SZnr%)NAm@Fl-TfQ z_kiff0ZGPg!6vleLvDNG(^MiBtv0JsvNEg+Tz6j;0@uqP780IW^ZfGFOHs+va`$RC zyeb0~OOFVFtcqkq{}+&TwAlpIv6XoO$UmDW zOvAHi+d$i6&_0Y!&*cfz@hsXlK>G+j2JH-Ns?3XmYdpexj5b_aIqDulz>|%eD<{Tw U!u6j#HTcuYiH7_+*i@DJe-D<7>i_@% diff --git a/tools/nanokvm_update_edid/nanokvm_update_edid.c b/tools/nanokvm_update_edid/nanokvm_update_edid.c index 4a829ee..9435402 100644 --- a/tools/nanokvm_update_edid/nanokvm_update_edid.c +++ b/tools/nanokvm_update_edid/nanokvm_update_edid.c @@ -47,9 +47,9 @@ int check_edid(uint8_t *edid_data, uint16_t edid_size) } // Check EDID header - if (edid_data[0] != 0x00 || edid_data[1] != 0xFF || - edid_data[2] != 0xFF || edid_data[3] != 0xFF || - edid_data[4] != 0xFF || edid_data[5] != 0xFF || + if (edid_data[0] != 0x00 || edid_data[1] != 0xFF || + edid_data[2] != 0xFF || edid_data[3] != 0xFF || + edid_data[4] != 0xFF || edid_data[5] != 0xFF || edid_data[6] != 0xFF || edid_data[7] != 0x00) { fprintf(stderr, "EDID header is invalid\n"); return -1; // EDID header is invalid @@ -64,7 +64,7 @@ int check_edid(uint8_t *edid_data, uint16_t edid_size) if (checksum1 != edid_data[127]) { // Checksum for first 128 bytes is incorrect fprintf(stderr, "Checksum for first 128 bytes is incorrect\n"); - return -1; + return -1; } // Second 128 Bytes checksum @@ -95,7 +95,7 @@ void NanoKVM_PCIe_HDMI_Reset(void) // ======================================================================================================= // I2C write function -int i2c_write_byte(uint8_t offset, uint8_t reg, uint8_t data) +int i2c_write_byte(uint8_t offset, uint8_t reg, uint8_t data) { // reg buffer uint8_t reg_buf[2] = {0}; @@ -121,7 +121,7 @@ int i2c_write_byte(uint8_t offset, uint8_t reg, uint8_t data) return 0; } -int i2c_write_bytes(uint8_t offset, uint8_t reg, const uint8_t *data, size_t len) +int i2c_write_bytes(uint8_t offset, uint8_t reg, const uint8_t *data, size_t len) { // check len if (len == 0) { @@ -159,7 +159,7 @@ int i2c_write_bytes(uint8_t offset, uint8_t reg, const uint8_t *data, size_t len } // I2C read function -int i2c_read_byte(uint8_t offset, uint8_t reg, uint8_t *data) +int i2c_read_byte(uint8_t offset, uint8_t reg, uint8_t *data) { // reg buffer uint8_t reg_buf[2] = {0}; @@ -191,7 +191,7 @@ int i2c_read_byte(uint8_t offset, uint8_t reg, uint8_t *data) return 0; } -int i2c_read_bytes(uint8_t offset, uint8_t reg, uint8_t *data, size_t len) +int i2c_read_bytes(uint8_t offset, uint8_t reg, uint8_t *data, size_t len) { // 检查数据长度 if (len == 0) { @@ -259,7 +259,7 @@ int lt6911uxc_edid_write(uint8_t *edid_data, uint16_t edid_size) uint8_t version_str[32] = {0}; fprintf(stdout, "Writing EDID....\n"); - + // Start if (i2c_write_byte(LT6911_SYS_OFFSET, 0xFF, 0x80) != 0) return -1; lt6911_enable(); @@ -286,7 +286,7 @@ int lt6911uxc_edid_write(uint8_t *edid_data, uint16_t edid_size) if (chip_data[0] != 0xEE) { fprintf(stderr, "Unsupported chip version\n"); return -1; - } + } if (i2c_write_byte(LT6911_SYS3_OFFSET, 0x08, 0xAE) != 0) return -1; if (i2c_write_byte(LT6911_SYS3_OFFSET, 0x08, 0xEE) != 0) return -1; // Write @@ -373,7 +373,7 @@ int lt6911c_edid_write(uint8_t *edid_data, uint16_t edid_size) uint8_t version_str[32] = {0}; fprintf(stdout, "Writing EDID....\n"); - + // Start lt6911_enable(); if (i2c_read_bytes(LT6911_SYS4_OFFSET, 0x00, chip_data, 2) != 0) return -1; @@ -487,9 +487,161 @@ int lt6911c_edid_read(uint8_t *edid_data, uint16_t edid_size) return 0; } +int lt6911d_str_read(uint8_t *str) +{ + fprintf(stdout, "Reading LT6911D version data...\n"); + + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0xEE, 0x01) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5E, 0xDF) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x59, 0x50) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x10) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x21) != 0) return -1; + if (i2c_write_byte(LT6911D_DATA_OFFSET, 0x03, 0xBF) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_DATA_OFFSET, 0x03, 0xFF) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x04) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5E, 0x5F) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x20) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5B, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5C, 0x81) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5D, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x10) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1; + if (i2c_read_bytes(LT6911D_MANAGE_OFFSET, 0x5F, str, LT6911D_WR_SIZE) != 0) return -1; + usleep(10000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x08) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x00) != 0) return -1; + + return 0; +} + +int lt6911d_edid_write(uint8_t *edid_data, uint16_t edid_size) +{ + uint8_t i; + uint8_t wr_count = edid_size / LT6911D_WR_SIZE + 1; + uint8_t version_str[LT6911D_WR_SIZE] = {0}; + + if (lt6911d_str_read(version_str) != 0) { + fprintf(stderr, "Failed to read LT6911D version data\n"); + return -1; + } + + fprintf(stdout, "Writing EDID....\n"); + + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0xEE, 0x01) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5E, 0xDF) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x59, 0x50) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x10) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x21) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x04) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5B, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5C, 0x80) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5D, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x01) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1; + usleep(600000); + + for (i = 0; i < wr_count; i++) { + if (i2c_write_byte(LT6911D_DATA_OFFSET, 0x03, 0xBF) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_DATA_OFFSET, 0x03, 0xFF) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x04) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5E, 0xDF) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x20) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x21) != 0) return -1; + if (i != wr_count - 1) { + if (i2c_write_bytes(LT6911D_MANAGE_OFFSET, 0x59, edid_data + (LT6911D_WR_SIZE * i), LT6911D_WR_SIZE) != 0) return -1; + } else { + if (i2c_write_bytes(LT6911D_MANAGE_OFFSET, 0x59, version_str, LT6911D_WR_SIZE) != 0) return -1; + } + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5B, 0x00) != 0) return -1; + if (i != wr_count - 1) { + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5C, 0x80) != 0) return -1; + } else { + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5C, 0x81) != 0) return -1; + } + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5D, 0x00 + (LT6911D_WR_SIZE * i)) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x10) != 0) return -1; + usleep(5000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1; + usleep(10000); + } + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x08) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x00) != 0) return -1; + + fprintf(stdout, "EDID write completed\n"); + + return 0; +} + +int lt6911d_edid_read(uint8_t *edid_data, uint16_t edid_size) +{ + uint8_t i; + uint8_t wr_count = edid_size / LT6911D_WR_SIZE; + + fprintf(stdout, "Reading EDID...\n"); + + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0xEE, 0x01) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5E, 0xDF) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x59, 0x50) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x10) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x21) != 0) return -1; + for (i = 0; i < wr_count; i++) { + if (i2c_write_byte(LT6911D_DATA_OFFSET, 0x03, 0xBF) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_DATA_OFFSET, 0x03, 0xFF) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x04) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5E, 0x5F) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x20) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5B, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5C, 0x80) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5D, 0x00 + (LT6911D_WR_SIZE * i)) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x10) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1; + if (i2c_read_bytes(LT6911D_MANAGE_OFFSET, 0x5F, edid_data + (LT6911D_WR_SIZE * i), LT6911D_WR_SIZE) != 0) return -1; + usleep(10000); + } + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x08) != 0) return -1; + usleep(1000); + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1; + if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x00) != 0) return -1; + + return 0; +} + // ======================================================================================================= -int lt6911_edid_config(chip_version_t chip_version, uint8_t *edid_data, uint16_t edid_size) +int lt6911_edid_config(chip_version_t chip_version, uint8_t *edid_data, uint16_t edid_size) { if (chip_version == CHIP_UNKNOWN) { @@ -523,6 +675,12 @@ int lt6911_edid_config(chip_version_t chip_version, uint8_t *edid_data, uint16_t close(client); return -1; } + } else if (chip_version == CHIP_LT6911D) { + if (lt6911d_edid_write(edid_data, edid_size) != 0) { + fprintf(stderr, "Failed to write EDID data to LT6911D\n"); + close(client); + return -1; + } } else { fprintf(stderr, "Unknown chip version\n"); close(client); @@ -545,6 +703,12 @@ int lt6911_edid_config(chip_version_t chip_version, uint8_t *edid_data, uint16_t close(client); return -1; } + } else if (chip_version == CHIP_LT6911D) { + if (lt6911d_edid_read(edid_read_data, EDID_BUFFER_SIZE) != 0) { + fprintf(stderr, "Failed to read EDID data from LT6911D\n"); + close(client); + return -1; + } } else { fprintf(stderr, "Unknown chip version\n"); close(client); @@ -596,7 +760,7 @@ void print_warning(product_version_t product_version) { printf("Please ensure you can physically disconnect its power,\n"); printf("NOT just remotely reboot it!!\n"); printf("==========================================================\n\n"); - } + } } void print_success(product_version_t product_version) { @@ -604,31 +768,31 @@ void print_success(product_version_t product_version) { printf("✅ EDID update successful!\n"); if (product_version == PRODUCT_CUBE_A || product_version == PRODUCT_CUBE_B) { printf("Please manually power cycle the device to apply changes.\n"); - } + } printf("=========================================================\n\n"); } int get_user_confirmation() { char input[256]; printf("Do you want to continue? (Y/N): \n"); - + while (1) { - + if (fgets(input, sizeof(input), stdin) == NULL) { printf("\nInput error. Exiting.\n"); return 0; } - + // 去除换行符 input[strcspn(input, "\n")] = '\0'; - + if (strlen(input) == 0) { continue; // 空输入,重新提示 } - + // 转换为小写方便比较 char choice = tolower(input[0]); - + if (choice == 'y') { return 1; } else if (choice == 'n') { @@ -656,7 +820,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Please upgrade to the latest system\n"); return 1; } - + if (fgets(chip_version_str, sizeof(chip_version_str), file) == NULL) { fprintf(stderr, "Failed to read chip version\n"); fclose(file); @@ -669,23 +833,26 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Please upgrade to the latest system\n"); return 1; } - + if (fgets(product_version_str, sizeof(product_version_str), file) == NULL) { fprintf(stderr, "Failed to read product version\n"); fclose(file); return 1; } fclose(file); - + chip_version_str[strcspn(chip_version_str, "\n")] = '\0'; product_version_str[strcspn(product_version_str, "\n")] = '\0'; - + if (strcmp(chip_version_str, "c") == 0) { fprintf(stdout, "Chip Version: LT6911C\n"); chip_version = CHIP_LT6911C; } else if (strcmp(chip_version_str, "ux") == 0) { fprintf(stdout, "Chip Version: LT6911UXC\n"); chip_version = CHIP_LT6911UXC; + } else if (strcmp(chip_version_str, "d") == 0) { + fprintf(stdout, "Chip Version: LT6911D\n"); + chip_version = CHIP_LT6911D; } else if (strcmp(chip_version_str, "ue") == 0) { fprintf(stderr, "Chip Version Error: UE version's edid can't be updated\n"); return 1; @@ -693,7 +860,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Chip Version Error: Unknown version\n"); return 1; } - + if (strcmp(product_version_str, "alpha") == 0) { fprintf(stdout, "Product Version: CUBE_A\n"); product_version = PRODUCT_CUBE_A; diff --git a/tools/nanokvm_update_edid/nanokvm_update_edid.h b/tools/nanokvm_update_edid/nanokvm_update_edid.h index ed743fb..214c970 100644 --- a/tools/nanokvm_update_edid/nanokvm_update_edid.h +++ b/tools/nanokvm_update_edid/nanokvm_update_edid.h @@ -17,10 +17,13 @@ #define LT6911C_HDMI_INFO_OFFSET 0xD2 // LT6911C HDMI信息寄存器偏移地址 #define LT6911C_AUDIO_INFO_OFFSET 0xD1 // LT6911C 音频信息寄存器偏移地址 #define LT6911C_CSI_INFO_OFFSET 0xC2 // LT6911C CSI信息寄存器偏移地址 +#define LT6911D_MANAGE_OFFSET 0xE0 // LT6911D 管理寄存器偏移地址 +#define LT6911D_DATA_OFFSET 0xE1 // LT6911D 数据寄存器偏移地址 #define EDID_BUFFER_SIZE 256 // 最大支持的字节数 #define LT6911UXC_WR_SIZE 32 // LT6911UXC单次读写最大字节数 #define LT6911C_WR_SIZE 16 // LT6911C单次读写最大字节数 +#define LT6911D_WR_SIZE 32 // LT6911D单次读写最大字节数 #define VERSION_PATH "/etc/kvm/hdmi_version" #define PRODUCT_PATH "/etc/kvm/hw" @@ -28,6 +31,7 @@ typedef enum { CHIP_LT6911UXC = 0, CHIP_LT6911C, + CHIP_LT6911D, CHIP_UNKNOWN } chip_version_t; @@ -38,4 +42,4 @@ typedef enum { PRODUCT_UNKNOWN, } product_version_t; -#endif // NANOKVM_UPDATE_EDID_H \ No newline at end of file +#endif // NANOKVM_UPDATE_EDID_H