edid 解析

转自项目:deepin-devicemanager
EDIDParser.cpp

// 项目自身文件
#include "EDIDParser.h"

// Qt库文件
#include<QDebug>
#include<QDate>

// 其它头文件
#include<qmath.h>

EDIDParser::EDIDParser()
    : m_Vendor()
    , m_ReleaseDate()
    , m_ScreenSize()
    , m_LittleEndianMode(true)
    , m_Width(0)
    , m_Height(0)
{
    m_MapCh.insert("00001", "A");
    m_MapCh.insert("00010", "B");
    m_MapCh.insert("00011", "C");
    m_MapCh.insert("00100", "D");
    m_MapCh.insert("00101", "E");
    m_MapCh.insert("00110", "F");
    m_MapCh.insert("00111", "G");
    m_MapCh.insert("01000", "H");
    m_MapCh.insert("01001", "I");
    m_MapCh.insert("01010", "J");
    m_MapCh.insert("01011", "K");
    m_MapCh.insert("01100", "L");
    m_MapCh.insert("01101", "M");
    m_MapCh.insert("01110", "N");
    m_MapCh.insert("01111", "O");
    m_MapCh.insert("10000", "P");
    m_MapCh.insert("10001", "Q");
    m_MapCh.insert("10010", "R");
    m_MapCh.insert("10011", "S");
    m_MapCh.insert("10100", "T");
    m_MapCh.insert("10101", "U");
    m_MapCh.insert("10110", "V");
    m_MapCh.insert("10111", "W");
    m_MapCh.insert("11000", "X");
    m_MapCh.insert("11001", "Y");
    m_MapCh.insert("11010", "Z");
}

bool EDIDParser::setEdid(const QString &edid, QString &errorMsg, const QString &ch, bool littleEndianMode)
{
    m_LittleEndianMode = littleEndianMode;
    // 判断是否是合理的edid
    if (m_LittleEndianMode) {
        if (!edid.startsWith("00ffffffffffff00")) {
            errorMsg = "Error edid info";
            return false;
        }
    } else {
        if (!edid.startsWith("ff00ffffffff00ff")) {
            errorMsg = "Error edid info";
            return false;
        }
    }

    QStringList lines = edid.split(ch);
    foreach (const QString &line, lines) {
        if (line == "")
            continue;

        m_ListEdid.append(line);
    }

    // 解析厂商信息
    parserVendor();
    // 解析发布日期
    parseReleaseDate();
    // 解析屏幕尺寸
    parseScreenSize();


    return true;
}

const QString &EDIDParser::vendor()const
{
    return m_Vendor;
}

const QString &EDIDParser::releaseDate()const
{
    return m_ReleaseDate;
}

const QString &EDIDParser::screenSize()const
{
    return m_ScreenSize;
}

int EDIDParser::width()
{
    return m_Width;
}

int EDIDParser::height()
{
    return m_Height;
}

void EDIDParser::parserVendor()
{
    // 获取制造商信息,edid中的 08h 和 09h 是厂商信息
    // 08表示 第0行  第9个字节
    QString vendorStr;
    QString h08 = getBytes(0, 8);
    QString h09 = getBytes(0, 9);
    if (m_LittleEndianMode)
        vendorStr = h08 + h09;
    else
        vendorStr = h09 + h08;

    // 将16进制的厂商信息转换成二进制的厂商信息
    QString binStr = hexToBin(vendorStr);

    // 转换后的二进制厂商信息格式为(6,5,5),如:010110 10011 00011
    // 分别表示三个字符,就是厂商的缩写
    QString bin1 = binStr.mid(1, 5);
    QString bin2 = binStr.mid(6, 5);
    QString bin3 = binStr.mid(11, 5);

    // 获取厂商信息
    m_Vendor = m_MapCh[bin1] +  m_MapCh[bin2] + m_MapCh[bin3];
}

void EDIDParser::parseReleaseDate()
{
    // edid中的  10H和11H就是发布日期信息
    QString hWeek = getBytes(1, m_LittleEndianMode ? 0 : 1);
    QString hYear = getBytes(1, m_LittleEndianMode ? 1 : 0);

    int week = hexToDec(hWeek).toInt();
    int year = hexToDec(hYear).toInt() + 1990;

    QDate date(year, 1, 1);
    date = date.addDays(week * 7 - 1);
    m_ReleaseDate = date.toString("yyyy-MM");
}

void EDIDParser::parseScreenSize()
{
    // edid中的  15H和16H就是屏幕大小
    m_Width = hexToDec(getBytes(1, m_LittleEndianMode ? 5 : 4)).toInt();
    m_Height = hexToDec(getBytes(1, m_LittleEndianMode ? 6 : 7)).toInt();
    double inch = sqrt((m_Width / 2.54) * (m_Width / 2.54) + (m_Height / 2.54) * (m_Height / 2.54));
    m_ScreenSize = QString("%1 %2(%3mm X %4mm)").arg(QString::number(inch, 'f', 1)).arg(QObject::tr("inch")).arg(m_Width).arg(m_Height);
}

QString EDIDParser::binToDec(QString strBin)   //二进制转十进制
{
    // 二进制转十进制
    QString decimal;
    int nDec = 0, nLen;
    int i, j, k;
    nLen = strBin.length();

    for (i = 0; i < nLen; i++) {
        if (strBin[nLen - i - 1] == "0")
            continue;
        else {
            k = 1;
            for (j = 0; j < i; j++)
                k = k * 2;
            nDec += k;
        }
    }

    decimal = QString::number(nDec);
    return decimal;
}

QString EDIDParser::decTobin(QString strDec)   //十进制转二进制
{
    int nDec = strDec.toInt();
    int nYushu = 0;
    int nShang = 0;
    QString strBin, strTemp;

    bool bContinue = true;
    while (bContinue) {
        nYushu = nDec % 2;
        nShang = nDec / 2;
        strBin = QString::number(nYushu) + strBin; //qInfo()<<strBin;
        strTemp = strBin;
        //strBin.Format("%s%s", buf, strTemp);
        nDec = nShang;
        if (nShang == 0)
            bContinue = false;
    }
    int nTemp = strBin.length() % 4;
    switch (nTemp) {
    case 1:
        //strTemp.Format(_T("000%s"), strBin);
        strTemp = "000" + strBin;
        strBin = strTemp;
        break;
    case 2:
        //strTemp.Format(_T("00%s"), strBin);
        strTemp = "00" + strBin;
        strBin = strTemp;
        break;
    case 3:
        //strTemp.Format(_T("0%s"), strBin);
        strTemp = "0" + strBin;
        strBin = strTemp;
        break;
    default:
        break;
    }
    return strBin;
}

QString EDIDParser::decToHex(QString strDec)   //十进制转十六进制
{
    int hex = strDec.toInt();
    QString hex1 = QString("%1").arg(hex, 8, 16, QLatin1Char('0'));
    return hex1;
}

int EDIDParser::hex2(unsigned char ch)           //十六进制转换工具
{
    if ((ch >= '0') && (ch <= '9'))
        return ch - 0x30;
    else if ((ch >= 'A') && (ch <= 'F'))
        return ch - 'A' + 10;
    else if ((ch >= 'a') && (ch <= 'f'))
        return ch - 'a' + 10;
    return 0;
}

QString EDIDParser::hexToDec(QString strHex)   //十六进制转十进制
{
    int i;
    int v = 0;
    for (i = 0; i < strHex.length(); i++) {
        v *= 16;
        v += hex2(strHex[i].toLatin1());
    }
    return QString::number(v);
}

QString EDIDParser::hexToBin(QString strHex)
{
    // 十六进制转二进制
    QString dec = hexToDec(strHex);
    return decTobin(dec);
}

QString EDIDParser::getBytes(int l, int n)
{
    // 获取指定字节
    int index = n * 2;
    if (m_ListEdid.size() < l + 1)
        return "";

    QString line = m_ListEdid[l];
    if (line.length() < n + 1)
        return "";

    return line.mid(index, 2);
}

EDIDParser.h

/*
* Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd.
*
* Author:     Jun.Liu <liujuna@uniontech.com>
*
* Maintainer: XiaoMei.Ji <jixiaomei@uniontech.com>
* Maintainer: Jun.Liu <liujuna@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef EDIDPARSER_H
#define EDIDPARSER_H
#include<QString>
#include<QStringList>
#include<QMap>

/**
 * @brief The EDIDParser class
 * 用于解析edid的类
 */

class EDIDParser
{
public:
    EDIDParser();
    /**
     * @brief setEdid:设置edid原始数据
     * @param edid:edid信息
     * @param errorMsg:错误提示信息
     * @param ch:分隔符
     * @param littleEndianMode:大端、小端
     * @return 布尔值:true-设置成功;false-设置失败
     */
    bool setEdid(const QString &edid, QString &errorMsg, const QString &ch = "\n", bool littleEndianMode = true);

    /**
     * @brief vendor:获取厂商信息
     * @return 厂商信息
     */
    const QString &vendor()const;

    /**
     * @brief releaseDate:获取生产日期
     * @return 生产日期
     */
    const QString &releaseDate()const;

    /**
     * @brief screenSize:获取屏幕大小
     * @return 屏幕大小
     */
    const QString &screenSize()const;

    /**
     * @brief width : get screen width
     * @return
     */
    int width();

    /**
     * @brief height : get screen height
     * @return
     */
    int height();

private:

    /**
     * @brief parserVendor:从edid中获取厂商信息
     */
    void parserVendor();

    /**
     * @brief parseReleaseDate:从edid中获取发布日期
     */
    void parseReleaseDate();

    /**
     * @brief parseScreenSize:从edid中获取屏幕大小
     */
    void parseScreenSize();

    /**
     * @brief binToDec:将二进制转换成十进制
     * @param strBin:二进制字符串
     * @return 十进制字符串
     */
    QString binToDec(QString strBin);

    /**
     * @brief decTobin:将十进制转换成二进制
     * @param strDec::十进制字符串
     * @return 二进制字符串
     */
    QString decTobin(QString strDec);

    /**
     * @brief decToHex:将十进制转换成十六进制
     * @param strDec:十进制字符串
     * @return 十六进制字符串
     */
    QString decToHex(QString strDec);

    /**
     * @brief hex2:符号转换
     * @param ch:字符
     * @return 整数
     */
    int hex2(unsigned char ch);

    /**
     * @brief hexToDec:将十六进制转换成十进制
     * @param strHex:十六进制字符串
     * @return 十进制字符串
     */
    QString hexToDec(QString strHex);

    /**
     * @brief hexToBin:十六进制转换成二进制
     * @param strHex:十六进制字符串
     * @return 二进制字符串
     */
    QString hexToBin(QString strHex);

    /**@brief:获取第几个字节的值*/

    /**
     * @brief getBytes:获取第几个字节的值
     * @param l:行数
     * @param n:字节数
     * @return l行第n个字节字符串
     */
    QString getBytes(int l, int n);


private:
    /**@brief:机器的存储模式不同,会导致计算结果不同,所以在解析的时候需要考虑大小端模式*/
    QString                m_Vendor;                           // 显示屏的厂商信息
    QString                m_ReleaseDate;                      // 显示屏的生产日期
    QString                m_ScreenSize;                       // 屏幕大小
    bool                   m_LittleEndianMode;                 // 小端模式
    int                    m_Width;                            // width
    int                    m_Height;                           // heigth
    QStringList            m_ListEdid;                         // edid数据
    QMap<QString, QString> m_MapCh;                            //


};

#endif // EDIDPARSER_H

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
分析 EDID 的小工具 生成如下形式的说明文档: Adr Value Remark Description 00h 00h 01h FFh 02h FFh 03h FFh 04h FFh 05h FFh 06h FFh 07h 00h 08h 34h MAG EISA Manufacturer ID (high) 09h 27h EISA Manufacturer ID (low) 0Ah 17h 0717h EISA Product ID(low) 0Bh 07h EISA Product ID(high) 0Ch 02h 2 Serial Number 0Dh 00h Serial Number 0Eh 00h Serial Number 0Fh 00h Serial Number 10h 0Dh 13 Week of Manufacture 11h 0Eh 2004 Year of Manufacture 12h 01h 1 EDID Version 13h 03h 3 EDID Revision 14h 08h Video Input Definition Bit 7 : 0 = Analog signal Bit 6,5: 00 = 0.700,0.300(1.000Vpp) Bit 4 : 0 = No blank-to-black setup Bit 3 : 1 = Separate sync supported Bit 2 : 0 = No composite sync supported Bit 1 : 0 = No sync on green supported Bit 0 : 0 = No serration of the Vsync required 15h 22h 34 Max. Horizontal Image Size 16h 1Bh 27 Max. Vertical Image Size 17h 96h 2.5 Display Transfer Characteristic (Gamma) 18h 28h Feature Support (DPMS) Bit 7 : 0 = No stand-by mode Bit 6 : 0 = No suspend mode Bit 5 : 1 = Active off Bit 4,3: 01 = R/G/B color display Bit 2 : 0 = No standard default color space Bit 1 : 0 = No preferred timing mode Bit 0 : 0 = No GTF supported 19h 67h Red / Green Low Bits 1Ah 55h Blue/ White Low Bits 1Bh A5h 0.646 Red X 1Ch 5Bh 0.357 Red X 1Dh 47h 0.278 Green X 1Eh 9Ch 0.612 Green Y 1Fh 25h 0.146 Blue X 20h 1Eh 0.118 Blue Y 21h 4Fh 0.31 White X 22h 54h 0.329 White Y 23h BFh Established Timings 1 Bit 7 : 1 = 720 x 400 : 70 Hz Bit 6 : 0 Bit 5 : 1 = 640 x 480 : 60 Hz Bit 4 : 1 = 640 x 480 : 67 Hz Bit 3 : 1 = 640 x 480 : 72 Hz Bit 2 : 1 = 640 x 480 : 75 Hz Bit 1 : 1 = 800 x 600 : 56 Hz Bit 0 : 1 = 800 x 600 : 60 Hz 24h EFh Established Timings 2 Bit 7 : 1 = 800 x 600 : 72 Hz Bit 6 : 1 = 800 x 600 : 75 Hz Bit 5 : 1 = 832 x 624 : 75 Hz Bit 4 : 0 Bit 3 : 1 = 1024 x 768 : 60 Hz Bit 2 : 1 = 1024 x 768 : 70 Hz Bit 1 : 1 = 1024 x 768 : 75 Hz Bit 0 : 1 = 1280 x1024 : 75 Hz 25h 00h Manufacturers Timings 26h 31h 640 x 480 27h 40h 60 Hz 28h 45h 800 x 600 29h 40h 60 Hz 2Ah 61h 1024 x 768 2Bh 40h 60 Hz 2Ch 81h 1280 x 1024 2Dh 80h 60 Hz 2Eh 31h 640 x 480 2Fh 4Fh 75 Hz 30h 45h 800 x 600 31h 4Fh 75 Hz 32h 61h 1024 x 768 33h 4Fh 75 Hz 34h 81h 1280 x 1024 35h 8Fh 75 Hz 36h 30h 108Mhz Pixel Clock (low) 37h 2Ah Pixel Clock (high) 38h 00h 1280 Horizontal Active (low) 39h 98h 408 Horizontal Blank (low) 3Ah 51h H.Active/H.Blank (high) 3Bh 00h 1024 Vertikal Active (low) 3Ch 2Ah 42 Vertikal Blank (low) 3Dh 40h V.Active/V.Blank (high) 3Eh 30h 48 H.Front Porch (low) 3Fh 70h 112 H.Sync Pulse Width (low) 40h 13h 1/3 V.Front Porch/V.Sync PW (low) 41h 00h H/V Sync (high) 42h 51h 337 H.Image Size (low) 43h 0Eh 270 V.Image Size (low) 44h 11h H/V Smage Size (high) 45h 00h 0 H.Border 46h 00h 0 H.Border 47h 1Eh Flags 48h 00h Flag = 0000h 49h 00h 4Ah 00h Reserved = 00h 4Bh FFh Tag=Monitor S/N String 4Ch 00h Flag = 00h 4Dh 31h '1' 4Eh 0Ah 4Fh 20h 50h 20h 51h 20h 52h 20h 53h 20h 54h 20h 55h 20h 56h 20h 57h 20h 58h 20h 59h 20h 5Ah 00h Flag = 0000h 5Bh 00h 5Ch 00h Reserved = 00h 5Dh FCh Monitor Name 5Eh 00h Flag = 00h 5Fh 50h 'P' 60h 53h 'S' 61h 2Dh '-' 62h 37h '7' 63h 37h '7' 64h 36h '6' 65h 49h 'I' 66h 0Ah 67h 20h 68h 20h 69h 20h 6Ah 20h 6Bh 20h 6Ch 00h Flag = 0000h 6Dh 00h 6Eh 00h Reserved = 00h 6Fh FDh Tag=Monitor Range Limits 70h 00h Flag = 00h 71h 3Ch 60 Min. vert. Frequency [Hz] 72h 4Bh 75 Max. vert. Frequency [Hz] 73h 1Eh 30 Min. hor. Frequency [kHz] 74h 50h 80 Max. hor. Frequency [kHz] 75h 0Eh 140 Max. Pixel Frequency [MHz/10] 76h 00h Reserved for VESA GTF (=00) 77h 0Ah Set to 0Ah 78h 20h 79h 20h 7Ah 20h 7Bh 20h 7Ch 20h 7Dh 20h 7Eh 00h EDID Ext. Flag 7Fh 15h Checksum

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值