|  | 
 
 
| 我有个acer笔记本电池锁了,其实没有循环几次,多年来一直插着电源用,莫名其妙就锁了,拆了折腾过,保险熔断,电芯焊下测试有电,电压一致性也挺好,看不出来异常,焊过几次,就成了伊拉克成色: 
 
 电芯是LG的,保护板主控BQ20Z955,
 
 
 
 
 看到数码之家里有人解锁成功了,过程很复杂不太懂,自己也试试,春节刚过买了个cp2112小板,连了一次电池,初次可以识别,后来莫名其妙软件(Be2works)不认小板了,但是cp2112厂商的demo软件还是可以认的,研究了一番发现是PID、VID被改写后otp写死了,把Be2works网上能找到的那个版本反编译后看到destroy的字样,怀疑是软件破坏了。尝试用silicon lab自己的demo软件读电池信息试试:找出电池接口的针脚定义,
 
 这个是通信小板,与type-c的otg插头对比,很小巧,
 
 
 按针脚定义连线,用软件读一下,确实可以读到内容
 
 
 其中目标地址相当于smbus命令地址,20、21分别表示电芯制造商、型号,根据返回的内容,对照asc2表,21地址返回值翻译过来就是AS10D81 , 20地址翻译过来是LGC,好像是那么回事儿?
 
 网上还有大神写了个基于cp2112与电池通信的代码,我下载回来编译完无法认小板,后来在源码里修改了pid vid为我的小板现在的数值,再编译后可以读一些信息了,
 这是我连接几个电池读到的部分信息:
 
 
 
 
 源代码里作者没有写解锁部分,我想在这儿蹲个现成的,有大神帮忙吗?  网上下载的那个源码是这样的我直接贴在这儿,侵删
 
 
 复制代码#include <stdio.h>
#include <stdlib.h>
#include "smbus.h"
/*
NOTE: As command response lengths may differ between gas gauges, ensure
sbsCommandResponseLength contains the correct lengths for your
particular device (check datasheet).
For example, some typical variations:
Manufacturer Name [0x20] = 20+1 bytes / 11+1 bytes
Device Name [0x21] = 20+1 bytes / 7+1 bytes
*/
const WORD sbsCommandResponseLength[] = {
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2,   // 0x00 - 0x09
    2, 2, 1, 1, 1, 2, 2, 2, 2, 2,   // 0x0A - 0x13
    2, 2, 2, 2, 2, 2, 2, 2, 2, 0,   // 0x14 - 0x1D
    0, 0, 21, 21, 5, 15             // 0x1E - 0x23
};
enum sbsCommands {
    MANUFACTURER_ACCESS,        // 0x00
    REMAINING_CAPACITY_ALARM,   // 0x01
    REMAINING_TIME_ALARM,       // 0x02
    BATTERY_MODE,               // 0x03
    AT_RATE,                    // 0x04
    AT_RATE_TIME_TO_FULL,       // 0x05
    AT_RATE_TIME_TO_EMPTY,      // 0x06
    AT_RATE_OK,                 // 0x07
    TEMPERATURE,                // 0x08
    VOLTAGE,                    // 0x09
    CURRENT,                    // 0x0A
    AVERAGE_CURRENT,            // 0x0B
    MAX_ERROR,                  // 0x0C
    RELATIVE_STATE_OF_CHARGE,   // 0x0D
    ABSOLUTE_STATE_OF_CHARGE,   // 0x0E
    REMAINING_CAPACITY,         // 0x0F
    FULL_CHARGE_CAPACITY,       // 0x10
    RUN_TIME_TO_EMPTY,          // 0x11
    AVERAGE_TIME_TO_EMPTY,      // 0x12
    AVERAGE_TIME_TO_FULL,       // 0x13
    CHARGING_CURRENT,           // 0x14
    CHARGING_VOLTAGE,           // 0x15
    BATTERY_STATUS,             // 0x16
    CYCLE_COUNT,                // 0x17
    DESIGN_CAPACITY,            // 0x18
    DESIGN_VOLTAGE,             // 0x19
    SPECIFICATION_INFO,         // 0x1A
    MANUFACTURER_DATE,          // 0x1B
    SERIAL_NUMBER,              // 0x1C
    RESERVED1,                  // 0x1D
    RESERVED2,                  // 0x1E
    RESERVED3,                  // 0x1F
    MANUFACTURER_NAME,          // 0x20
    DEVICE_NAME,                // 0x21
    DEVICE_CHEMISTRY,           // 0x22
    MANUFACTURER_DATA           // 0x23
};
#define BITRATE_HZ                  25000
#define ACK_ADDRESS                 0x02
#define AUTO_RESPOND                FALSE
#define WRITE_TIMEOUT_MS            1000
#define READ_TIMEOUT_MS             1000
#define TRANSFER_RETRIES            0
#define SCL_LOW_TIMEOUT             TRUE
#define RESPONSE_TIMEOUT_MS         1000
#define CHARGER_SLAVE_ADDRESS_W     0x12
#define BATTERY_SLAVE_ADDRESS_W     0x16
int main(int argc, char* argv[])
{
    HID_SMBUS_DEVICE    m_hidSmbus;
    BYTE                buffer[HID_SMBUS_MAX_READ_RESPONSE_SIZE];
    BYTE                targetAddress[16];
    // Open device
    if(SMBus_Open(&m_hidSmbus) != 0)
    {
        fprintf(stderr,"ERROR: Could not open device.\r\n");
        SMBus_Close(m_hidSmbus);
        return -1;
    }
    fprintf(stderr,"Device successfully opened.\r\n");
    // Configure device
    if(SMBus_Configure(m_hidSmbus, BITRATE_HZ, ACK_ADDRESS, AUTO_RESPOND, WRITE_TIMEOUT_MS, READ_TIMEOUT_MS, SCL_LOW_TIMEOUT, TRANSFER_RETRIES, RESPONSE_TIMEOUT_MS) != 0)
    {
        fprintf(stderr,"ERROR: Could not configure device.\r\n");
        SMBus_Close(m_hidSmbus);
        return -1;
    }
    fprintf(stderr,"Device successfully configured.\r\n");
    // Voltage [0x09]
    targetAddress[0] = VOLTAGE;
    if (SMBus_Read(m_hidSmbus, buffer, BATTERY_SLAVE_ADDRESS_W, sbsCommandResponseLength[VOLTAGE], 1, targetAddress) != sbsCommandResponseLength[VOLTAGE])
    {
        fprintf(stderr,"ERROR: Could not perform SMBus read.\r\n");
        SMBus_Close(m_hidSmbus);
        return -1;
    }
    UINT16 voltage_mV = (buffer[1] << 8) | buffer[0];
    fprintf(stderr, "Voltage = %d mV\r\n", voltage_mV);
    // Current [0x0A]
    targetAddress[0] = CURRENT;
    if (SMBus_Read(m_hidSmbus, buffer, BATTERY_SLAVE_ADDRESS_W, sbsCommandResponseLength[CURRENT], 1, targetAddress) != sbsCommandResponseLength[CURRENT])
    {
        fprintf(stderr,"ERROR: Could not perform SMBus read.\r\n");
        SMBus_Close(m_hidSmbus);
        return -1;
    }
    INT16 current_mA = (buffer[1] << 8) | buffer[0];
    fprintf(stderr, "Current = %d mA\r\n", current_mA);
    // Relative State of Charge [0x0D]
    targetAddress[0] = RELATIVE_STATE_OF_CHARGE;
    if (SMBus_Read(m_hidSmbus, buffer, BATTERY_SLAVE_ADDRESS_W, sbsCommandResponseLength[RELATIVE_STATE_OF_CHARGE], 1, targetAddress) != sbsCommandResponseLength[RELATIVE_STATE_OF_CHARGE])
    {
        fprintf(stderr,"ERROR: Could not perform SMBus read.\r\n");
        SMBus_Close(m_hidSmbus);
        return -1;
    }
    BYTE rsoc = buffer[0];
    fprintf(stderr, "RSOC = %d %%\r\n", rsoc);
    // Remaining Capacity [0x0F]
    targetAddress[0] = REMAINING_CAPACITY;
    if (SMBus_Read(m_hidSmbus, buffer, BATTERY_SLAVE_ADDRESS_W, sbsCommandResponseLength[REMAINING_CAPACITY], 1, targetAddress) != sbsCommandResponseLength[REMAINING_CAPACITY])
    {
        fprintf(stderr,"ERROR: Could not perform SMBus read.\r\n");
        SMBus_Close(m_hidSmbus);
        return -1;
    }
    UINT16 remCap = (buffer[1] << 8) | buffer[0];
    fprintf(stderr, "Remaining Capacity = %d mAh\r\n", remCap);
    // Average Time to Empty [0x12]
    targetAddress[0] = AVERAGE_TIME_TO_EMPTY;
    if (SMBus_Read(m_hidSmbus, buffer, BATTERY_SLAVE_ADDRESS_W, sbsCommandResponseLength[AVERAGE_TIME_TO_EMPTY], 1, targetAddress) != sbsCommandResponseLength[AVERAGE_TIME_TO_EMPTY])
    {
        fprintf(stderr,"ERROR: Could not perform SMBus read.\r\n");
        SMBus_Close(m_hidSmbus);
        return -1;
    }
    UINT16 avgTimeToEmpty = (buffer[1] << 8) | buffer[0];
    fprintf(stderr, "Average Time to Empty = %d min(s)\r\n", avgTimeToEmpty);
    // Manufacturer Name [0x20]
    targetAddress[0] = MANUFACTURER_NAME;
    if (SMBus_Read(m_hidSmbus, buffer, BATTERY_SLAVE_ADDRESS_W, sbsCommandResponseLength[MANUFACTURER_NAME], 1, targetAddress) < 1)
    {
        fprintf(stderr,"ERROR: Could not perform SMBus read.\r\n");
        SMBus_Close(m_hidSmbus);
        return -1;
    }
    fprintf(stderr, "Manufacturer Name = ");
    // NOTE: Length of string is stored in first received byte
    for(int i = 1; i < buffer[0] + 1; i++)
    {
        fprintf(stderr, "%c", buffer[i]);
    }
    fprintf(stderr, "\r\n");
    // Check if charger is present
    // Charger Status [0x13]
    targetAddress[0] = 0x13;
    if (SMBus_Read(m_hidSmbus, buffer, CHARGER_SLAVE_ADDRESS_W, 2, 1, targetAddress) != 2)
    {
        fprintf(stderr, "ERROR: Could not perform SMBus read.\r\n");
        SMBus_Close(m_hidSmbus);
        return -1;
    }
    UINT16 chargerStatus = (buffer[1] << 8) | buffer[0];
    if (chargerStatus & 0x8000)
    {
        fprintf(stderr, "Charger connected.\r\n");
    }
    else
    {
        fprintf(stderr, "Charger NOT connected.\r\n");
    }
    // Success
    fprintf(stderr, "Done! Exiting...\r\n");
    SMBus_Close(m_hidSmbus);
    return 0;
}
 知识到用的时候才恨少,感觉到被有知识的大佬降维打击
 
 
 
 
 
 
 BQ20Z955,艰难的笔记本电池解锁,终于解决:https://www.mydigit.cn/forum.php?mod=viewthread&tid=265242
 
 尝试低成本解锁ThinkPad笔记本电池:https://www.mydigit.cn/forum.php?mod=viewthread&tid=256068
 
 | 
 
x本帖子中包含更多资源您需要 登录 才可以下载或查看,没有账号?立即注册 
    打赏
查看全部打赏
 |