Friday, August 26, 2016

SMBusb - Hacking smart batteries

Having gone deep down the rabbit hole of researching smart laptop battery controllers I've ended up reverse engineering a couple of them used in ThinkPad batteries. Looking around there's very little software available out there for working with battery controllers in general and most of them cost hundreds or even thousands of dollars. Usually the chips' datasheets aren't even publicly available. (Aside from a few outtakes from chinese developer forums)

So why would you want to mess with a smart battery controller anyway?

Consider the case of one ThinkPad X100e I purchased a few months ago. Battery dead. Querying the controller reveals it's had 43 charge/discharge cycles so the cells are practically new! And yet the controller was in permanent lockout mode due to a single overdischarge condition getting logged. Trying to charge the battery in the laptop resulted in a rapidly flashing charge LED indicating charge failure.

Some people will say "Well that's by design, a single overdischarge turns Li-Ion cells into potential fire-bombs!"

If that was true there would've been a lot more cases of batteries setting houses on fire back in the early 2000s as "0V deep discharge recovery" used to be a feature in some laptop battery pack controllers back then.

It's not nearly as bad as some urban legends would have you believe. Take the battery pack I mentioned above for example. After recharging the cells externally while carefully monitoring their temperature and reprogramming the controller the pack was fine. It ended up with 100% the design capacity lasting 3.5 hours (it's a power hungry AMD system with an ATI GPU)

For the manufacturer, taking no chances from a legal standpoint is understandable but sometimes they can go a little overboard. A 3.5hr battery ending up in a landfill is not the best outcome.

Another reason would be for re-celling the pack. You have some options when the battery of your laptop dies: Replace the whole shebang because it's too slow anyway, replace the battery with a factory one for $100+, buy a chinese knockoff for $20-50 or re-cell with good brand cells for $20-50ish.

As demonstrated in my previous article about laptop batteries, keeping the original controller board has certain advantages such as temperature monitoring and an extra safety feature. It's also a good bet that brand cells will survive more cycles without capacity loss than ChangJiang ones. (I've actually recently tested a 6-cell LG pack at 540 cycles and it held a 1.5Amp load for 80 minutes.. a ChangJiang pack at 230 cycles petered out at 50 minutes. A sample size of two and the CJ pack was lower capacity to begin with (4.4AH vs 5.2) but still...)

Ok, so how do you talk to these controllers?

SMBus, which is I2C's impatient cousin with nasty hard timeouts and bulk transfer modes not standard in I2C along with a RESTART condition in addition to the START and STOP you normally deal with (... or just 1-Wire in more exotic hardware but let's not think about that).

How nasty are the timing constraints? You can implement I2C through a USB serial dongle's flow control pins. You can't implement SMBus because your code, the windows API, driver, USB stack and controller firmware response overhead added up is over the limit (especially if your serial thing uses only USB1.1). You can't keep the clock idle for over 35 milliseconds or the controller drops the conversation.

But don't go TOO fast because SMBus can't go over 100Khz (I2C can do 400). All that rushing and it can't keep up the pace in the long run, figures..

Unfortunately this makes it cumbersome to implement a dumb SMBus interface on a non real-time system like a PC alone.

Did I mention that different controllers seem to have slightly different timing requirements?

The most well supported interface for speaking with smart battery packs is the Texas Instruments EV-2300. It's a fairly expensive piece of kit but it has the advantage of being able to work with TI's own software which has a myriad of options for the publicly available TI battery controllers running the TI firmware but more on that later.


What's next?

Once reliable SMBus communication is established you will have access to a battery controller that talks the SBS Standard! It's a standard so we're basically done now. We just look at the standard documentation on how to clear any failure condition and reprogram the controller to our desired parameters, easy!

Ha! Yeah, no. The SBS standard only defines the very basic functionality for a smart battery controller. The controller will have something sometimes referred to as a "sealed" mode which is where it's only going to service the limited SBS standard requests. This will be the standard mode for the battery as that's all that laptops need. No touchy on any of the settings that really matter and certainly no clearing of any error conditions.

They'll sometimes have a command to "unseal" and enter full access mode where some or all settings are modifiable with a mixture of standard and unstandard commands. Most of the time this unseal command will be password protected or worse. Some TI controllers are like this while other controllers will only implement a sealed mode for SBS compliance and a completely proprietary bootloader mode to modify flash memory content directly (which may or may not also be entered in a similar way). It's really a mixed bag.

What's similar in all SBS microcontrollers is that getting into the Boot ROM where you can access and modify flash memory is hindered by the firmware that's already running on the device.


Texas Instruments is a BIG player in the smart battery world. They sell their battery management microcontrollers and analog frontends to pretty much everyone making battery packs. Some companies buy the whole package that is, the microcontrollers with TI-developed firmware. The security model mentioned above (sealed/unsealed/bootrom) is actually used mostly by the TI firmware. These pre-programmed micros under the "bq"-line usually have a letter in their model number such az the bq20z90. What's somewhat less known is that the bq20z90 is also sold WITHOUT the TI firmware as the bq8030(DBT). At the very least SONY and Sanyo have opted to buy the bq8030 with the accompanying (super-secret) SDK and develop their own firmware for their battery packs with it.

Did they not trust TI's expertise? Was the firmware too expensive to license? Did the TI firmware not do everything they wanted? Who knows! But the fact is production bq8030s are pretty much complete black boxes as they run a proprietary firmware and don't work at all with TI's own software. Other bq series are sold similarly as both pre-programmed and unprogrammed versions. The bq8050 would be another example though I don't know what the pre-programmed counterpart's model number is.

The EV-2300 will still talk to the chips running 3rd party firmware but the TI software will not work for anything other than simple SBS reporting.
The ONE thing the pre-programmed and unprogrammed chips will always have in common though is the TI Boot ROM. The challenge? Actually getting into it if there's already firmware on the chip. With the TI firmware the method for doing so is fully documented: You need to send two passwords to two SMBus commands. You can even find default passwords that will work in case the pack producer forgot (or didn't care) to change it, such as one particular series of Apple MacBook battery packs. (Charlie Miller did a LOT of work on this including making a cpu module (zip) for IDA to disassemble the proprietary Xemics CoolRISC core and modifying the TI firmware. Go check it out (pdf))

With a Sanyo or SONY or other 3rd-party firmware however, you're on your own! The procedure to access the Boot ROM is not public and neither are the passwords (if there even are passwords). The latter would also be true for most battery packs using the TI pre-programmed chips as pack manufacturers tend not to use the default passwords



So the obstacles to hacking smart batteries are numerous but let's take it one step at a time. First up.. the interface. Introducing SMBusb, a USB SMBus interface based on the Cypress FX2LP CY7C68013A(datasheet) USB Microcontroller or more specifically the dev-board that's available all across eBay for around $5 shipped.

This one here:

But all FX2LP based boards should work as long their firmware isn't pre-programmed into the EEPROM.

It's open source as far as firmware and software goes, comes with a library so you can easily use it in your own projects and includes a few tools to aid SMBus and smart battery hacking such as:

$ smbusb_scan -a
SMBusb Firmware Version: 1.0.0
Scanning for addresses..
Skipping: a0 a1
[0] ACK
[16] ACK
[17] ACK

Which allows scanning for available devices on the bus and analyzing the command set they expose:

$ smbusb_scan -w 0x16
  * snip *
[2f] ACK, Byte writable, Word writable, Block writable 
[30] ACK 
[31] ACK 
[32] ACK 
[33] ACK 
[35] ACK, Byte writable, Word writable 
[37] ACK 
[38] ACK 
[39] ACK, Byte writable, Word writable 
  * snip *


$ smbusb_sbsreport
SMBusb Firmware Version: 1.0.0
Manufacturer Name:          LGC
Device Name:                LNV-42T4911
Device Chemistry:           LION
Serial Number:              41291
Manufacture Date:           2010.01.25

Manufacturer Access:        6001
Remaining Capacity Alarm:   561 mAh(/10mWh)
Remaining Time Alarm:       10 min
Battery Mode:               e000
At Rate:                    0 mAh(/10mWh)
At Rate Time To Full:       65535 min
At Rate Time To Empty:      65535 min
At Rate OK:                 1
Temperature:                23.05 degC
Voltage:                    21 mV (*)
Current:                    0 mA
Average Current:            0 mA
Max Error:                  0 %
Relative State Of Charge    0 %
Absolute State Of Charge    0 %
Remaining Capacity:         0 mAh(/10mWh)
Full Charge Capacity:       5616 mAh(/10mWh)
Run Time To Empty:          65535 min
Average Time To Empty:      65535 min
Average Time To Full:       65535 min
Charging Current:           0 mA
Charging Voltage:           0 mV
Cycle Count:                529
Manufacturer Data:          fffffff7

(*):  This controller is just a bare board with no cells connected.

And also a couple of flashing tools for BQ8030 and R2J240 chips. (Note that there are NO passwords or methods included for entering the Boot ROM on already programmed chips. I may publish articles about how I got into these two at some point but be warned that it involves caveman methods and intentional flash corruption.)

Bonus: When you don't need the SMBusb (and you don't feel like learning fx2lib to do something interesting with the dev board) you can still use it as a 16 channel logic analyzer with sigrok. (You may need to compile sigrok from scratch with the VID/PID added in but it'll work)
And chances are you already have an FX2LP device laying around in your drawer in the form of an Altera ByteBlaster clone or one of the many USB logic analyzers that use it. You only need to access the hardware I2C pins for SMBusb to work and an easy point to get at those is the onboard EEPROM which is usually a nice big SO-8.

So where is this project?

Right here:

Sunday, May 1, 2016

Notes on the Gobi2000 in a Thinkpad X100e

The Qualcomm Gobi2000 is an internal Mini PCI Express 3G modem. It was used in a variety of machines including the Lenovo Thinkpad X100e.
It's a bit unintuitive to set up (to say the least) so I decided to write this post. Maybe it'll help someone else out there.

So right off the bat unless you're a Verizon customer do NOT just install the driver from Lenovo's site because it will default to loading Verizon's firmware. See:

If you already did you can uninstall and follow the instructions above or you can open the file: C:\ProgramData\QUALCOMM\QDLService2k\Options2k.txt and edit it.

The text file contains the path to 3 binary blobs which get loaded into the card's ram when the driver loads. Apps.mbn, AMMS.mbn and UQCN.mbn 
You just need to change which directory the images are loaded from. \1 is the Verizon firmware. For a full list see the support link above.
Note that to load the generic UMTS firmware you need to load Apps.mbn and AMMS.mbn from \UMTS and UQCN.mbn from \6 because consistency was not the developers' strong suit.

Also unless you're on a CDMA network that doesn't use a SIM card and requires an activation procedure instead do NOT install "Mobile Broadband Activation" either.

DO Install "Hotkey Features Integration" As far as I could tell it's the only way to enable the WWAN antenna. Fn+F5 brings up the radio power controls. It's also a separate executable so you can create a shortcut for it if you like. The naming is pretty straightforward, look through the installation folder in Program Files.

A note on all the abbreviations you can come across while setting up a 3G connection:
UMTS is the name of the whole 3G network technology, WCDMA is the name of the radio access layer used by UMTS networks. From a setup perspective they're pretty much interchangeable. HSDPA or HSUPA are high speed data services offered on a UMTS network. HSDPA offers faster download and HSUPA offers faster upload speeds. Together they are often referred to as HSPA. HSPA+ and Advanced HSPA+ are further iterations of this technology that offer even faster speeds.
And of course GPRS and EDGE are considerably slower data services running on a 2G GSM network.

Unlike Huawei or ZTE modems the Gobi2000 doesn't have a straightforward way to set which network and data service it should prefer. The automatic selection will be fine in most cases but sometimes you just want to force the setting. Like let's say the 3G network's signal is really weak and flaky but it's still faster than the 2G network that has good signal.
Apparently there is a method with the slow and clumsy Lenovo Access Connections tool but from what I can tell the setting doesn't persist.

I'm fairly certain the Lenovo tool just issues a manual network selection AT command. You can do that yourself (you can even add it as a pre-connection command to the Windows mobile broadband connection. It's there on one of the properties pages)
You can tell the modem to connect to a network by name but it's a better idea to use the network ID because carriers will sometimes name their 2g and 3g networks differently.

AT+COPS=1,2,"#####",0 (where ##### is the network id) will connect to the 2G network of the carrier

AT+COPS=1,2,"#####",2 will connect to the 3G network

To get the network ID you can issue AT+COPS=? to do a network scan (it will take a while) the 5 digit numbers in the list will be the network IDs

You can query the current operating mode with AT$QCSYSMODE?

On the 2G network I got simply GSM as the reply
On the 3G network WCDMA + HSDPA + HSUPA (which Windows listed as HSPA in the network list)
On another 3G network simply WCDMA (which Windows listed as UMTS)

You can also query the current network with AT+COPS?
You'll get something like +COPS: 1,0,"Network-Name",2

Note that the modem will return ERROR for most commands if it doesn't see a SIM card or if the radio is powered off.

Monday, April 18, 2016

[Random Teardowns] A couple of laptop batteries (aftermarket vs original)

Device: Original Lenovo 42T5225 (ThinkPad R61) and Chinese clone of 42T4788 (ThinkPad X100e)
Origin: Various
Reason for teardown: Broken
Impressions: I've recently opened up a few laptop batteries and decided to take some pictures. Keep reading if you've ever wondered just how different the Chinese aftermarket batteries are compared to the originals.

The original battery controller PCB is conformally coated while the clone is bare. Fair enough.

The original is based on the Mitsubishi/Renesas M37512 microcontroller (datasheet)

The clone on the other hand is based on the SINO WEALTH SH79F32 (datasheet)

Nothing terrible so far, right?

Well, if you take another look at the image with the original microcontroller there are two things worth mentioning on there. That component with the two long leads to the right of the micro is an externally triggerable fuse. It can blow during an overcurrent condition as any regular fuse OR the micro can trigger it in case of another hazard condition like say the cells overheating. Which brings us to the small flex cable temperature sensor stuck to the cell on the left side

Now let's see what the clone has in terms of overcurrent or overtemp protection.


Zero for two.

So the most the micro could do is (attempt) to shut the FETs off in case of an issue. (If it even noticed it before the cells set themselves ablaze.)

Lastly, let's take a look at the cells themselves.

The original has Japanese made Panasonic cells
The clone has Chinese made ChangJiang (CJ) cells
No surprises here. And it should be pointed out that these aren't necessarily bad or more hazardous than any of the high-end cells. If anything they're just unlikely to handle as many cycles before capacity loss renders them unusable. That said, a fuse and temperature monitoring still wouldn't hurt.

Thursday, October 29, 2015

[Random Teardowns] XL4005 5A step-down module with display

Device: XL4005 constant-current/constant-voltage buck converter with LED display
Origin: eBay / China
Reason for teardown: Project
Impressions: Ok so there isn't much to tear down on this given that it's just two PCBs screwed together with standoffs but oh well.

I got two of these for a project because they're just so cheap now. Supposedly they do 5amps and you get current limiting as well.

Already a bit modified

The modules themselves work reasonably well based on my limited testing. The display/monitor boards are pretty terrible though.

My gripes with them:
  • Horrible accuracy as-is and no calibration pot.  (FWIW you can hook up 10k trim pots to the two unpopulated resistor pads near the LM358 to fix this.)
  • Horrible resolution and pointless, wasted digits on the 7segment displays. (I'd take an extra digit over the lower-case u moonlighting as V ...)
  • Painfully slow update-rate
  • Serial feature poorly documented but also borderline worthless (see below)
All of these issues could be fixed in firmware. I'm almost tempted to get an ST-LINK dongle and reverse engineer the thing but it'd probably take about as much time as reimplementing the whole board using a microcontroller I'm actually familiar with and not bothering with the STM 8S003F3P6 it has which is to say: too long either way to be worth it. Anyone up for the challenge?

As for the worthless serial interface: the biggest issue is that the serial processing code takes too long to run and the micro isn't updating the screen while it's running so you get a really noticeable dip in brightness every time you send a query for voltage or current. And of course they're separate commands which compounds the problem.
If you're continuously polling the board with something you basically won't be able to see anything on the display.

If after all that you still want to use it, here's the info they give you:

Baud Rate : 9600 Bps
BB CC ADDR 00 XX XX CRC ( current return command )
BB CC ADDR 01 XX XX CRC ( voltage returns to the command )
BB CC for the header ( 2 bytes )
ADDR for the module address ( 1 byte )
00 to read the current command ( 1 byte )
01 is a read voltage command ( 1 byte )
XX XX arbitrary value ( 2 bytes )
CRC CRC checksum ( 1 byte )

Not bad. CRC is undocumented though and ADDR varies with board revision. (0 and 1 definitely exists)
Serial is standard 9600bps with no parity, 8 data and 1 stop-bits with no flow-control.
The revision with ADDR 0 may ignore CRC as long as it's not 0 because these have been reported to work with it:

Get current: BBCC00000000B4
Get voltage: BBCC00010000DF

It also doesn't return a CRC in it's replies and returns voltage and current in millivolts and milliamps (so a higher resolution than it displays) which is nice.

ADDR 1 on the other hand checks CRC and also returns it in replies. A brute-force loop later I got two replies with CRC and it was pretty obvious that it's just a simple addition you take the least significant byte of.

So the proper commands for ADDR 1 boards are:
Get current: BBCC0100000088 (  BB+CC+01+00+00+00 = 0188 so 0x88 )
Get voltage: BBCC0101000089 (  BB+CC+01+01+00+00 = 0189 so 0x89 )

Unfortunately this revision of the board returns values in 100 millivolts and 100 milliamps so for 4 volts you only get the value 40 .. FAIL!
And in case you're wondering if there's maybe an undocumented command you could use to get a higher resolution value or maybe a raw ADC value.. there isn't.

So in conclusion:
ADDR1 boards give you a low resolution value in exchange for a flickering or completely unreadable display.
ADDR0 boards give you a higher resolution value and I'm not sure if the flickering is present or not. Anyone know?