<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://maemo.octonezd.me/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=118.208.239.196</id>
	<title>Maemo Wiki Mirror - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://maemo.octonezd.me/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=118.208.239.196"/>
	<link rel="alternate" type="text/html" href="https://maemo.octonezd.me/index.php/Special:Contributions/118.208.239.196"/>
	<updated>2026-04-22T00:52:08Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://maemo.octonezd.me/index.php?title=Mer/Documentation/BME_Protocol&amp;diff=23709</id>
		<title>Mer/Documentation/BME Protocol</title>
		<link rel="alternate" type="text/html" href="https://maemo.octonezd.me/index.php?title=Mer/Documentation/BME_Protocol&amp;diff=23709"/>
		<updated>2009-06-23T11:24:59Z</updated>

		<summary type="html">&lt;p&gt;118.208.239.196: /* Some BULK0 message (0x42, 0x00) */ Add info on n-bars, time-per-bar fields.  -- pjrm&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This documentation is entirely for the purpose of implementing software gathering battery information on Nokia Internet Tablets, not alteration of battery management state. &lt;br /&gt;
&lt;br /&gt;
Existing code:&lt;br /&gt;
* Dummy server: https://garage.maemo.org/plugins/scmsvn/viewcvs.php/dsme/trunk/adhoc/dummy_bme.c?revision=155&amp;amp;root=dsm&amp;amp;view=markup , released as LGPL 2.1.  (Bug: The server shouldn&#039;t send a status word before sending the response struct.)&lt;br /&gt;
* Simple command-line client written based on this web page: http://bowman.infotech.monash.edu.au/~pmoulder/bme-client.c .  (GPLv2+, assuming that the text on this web page is compatible with that license.)&lt;br /&gt;
&lt;br /&gt;
General protocol:&lt;br /&gt;
&lt;br /&gt;
* UNIX socket connection to /tmp/.bmesrv&lt;br /&gt;
* Client: send(&#039;BMentity&#039;)&lt;br /&gt;
* Server: send(&#039;\n&#039;)&lt;br /&gt;
&lt;br /&gt;
After handshake:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint16      type, subtype;&lt;br /&gt;
} BMEHeader;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
types so far (NAME, (type, subtype)):&lt;br /&gt;
&lt;br /&gt;
== EM_BATTERY_INFO_REQ (0x06, 0x00) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    BMEHeader header;&lt;br /&gt;
    u_int32_t flags;   // Set to 0xFFFFFFFF to get all data&lt;br /&gt;
} BME_EM_BATTERY_INFO_Req;&lt;br /&gt;
&lt;br /&gt;
struct emsg_battery_info_reply {&lt;br /&gt;
    uint32      a;&lt;br /&gt;
    uint32      flags;&lt;br /&gt;
    uint16      c;&lt;br /&gt;
    uint16      d;&lt;br /&gt;
    uint16      temp;   // Battery temperature measured in Kelvin &lt;br /&gt;
    uint16      f;&lt;br /&gt;
    uint16      g;&lt;br /&gt;
    uint16      h;&lt;br /&gt;
    uint16      i;&lt;br /&gt;
    uint16      j;&lt;br /&gt;
    uint16      k;&lt;br /&gt;
    uint16      l;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Some BULK0 message (0x42, 0x00) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    BMEHeader header;&lt;br /&gt;
    u_int32_t flags;   // Set to 0xFFFFFFFF to get all data&lt;br /&gt;
} BME_EM_BULK_Req;&lt;br /&gt;
&lt;br /&gt;
struct emsg_bme_bulk_reply {&lt;br /&gt;
   uint32     unknown1;&lt;br /&gt;
   uint32     unknown2;&lt;br /&gt;
   uint32     unknown3;&lt;br /&gt;
   uint16     sw_status; // Battery monitor SW status&lt;br /&gt;
   uint16     instaneous_battery_voltage; // Instantaneous battery voltage (mV)&lt;br /&gt;
   uint16      // Remaining standby time to battery low (mins)&lt;br /&gt;
   uint16     unknown4;&lt;br /&gt;
   uint16     unknown5;&lt;br /&gt;
   uint16     unknown6;&lt;br /&gt;
   uint16     // Battery monitor check voltage (mV)&lt;br /&gt;
   uint16     // Battery low warning interval counter&lt;br /&gt;
   uint16     // Double median filtered battery voltage&lt;br /&gt;
   uint16     // Initial battery monitor voltage (mV)&lt;br /&gt;
   uint16     // Time per battery bar (mins)&lt;br /&gt;
   uint16     // DMF voltage sampled at first battery low (mV)&lt;br /&gt;
   uint32     // Average phone current (uA)&lt;br /&gt;
   uint16     // Most recent battery charge condition (mAh)&lt;br /&gt;
   uint16     // Lowest TX-Off voltage (mV)&lt;br /&gt;
   uint16     // Lowest TX-On voltage (mV)&lt;br /&gt;
   uint16     // Largest TX-Off/On voltage difference (mV)&lt;br /&gt;
   uint8      // Battery bar level log mask&lt;br /&gt;
   uint8      // Previous battery bar level&lt;br /&gt;
   uint8      // Battery low reason&lt;br /&gt;
   uint8      // CS state information &lt;br /&gt;
   uint16     // Number of battery bars&lt;br /&gt;
   uint16     // Battery type&lt;br /&gt;
   uint16     // Temperature, in kelvin&lt;br /&gt;
   uint16     // Battery capacity &lt;br /&gt;
   uint16     // Battery impedance (mOhm)&lt;br /&gt;
   uint16     // Present value of v_bat_full_level&lt;br /&gt;
   uint16     // Present value of v_bat_low_ths_mv&lt;br /&gt;
   uint16     unknown7;&lt;br /&gt;
   uint16     unknown8;&lt;br /&gt;
   uint16     unknown9;&lt;br /&gt;
   uint16     // Load current estimated by Batmon4 (uA)&lt;br /&gt;
   uint16     unknown10;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;“Instantaneous battery voltage (mV)”&#039;&#039;&#039; field’s observed values have a certain regular spacing indicating a linear function of some integer value with a smaller range, presumably retu adc register #8.  If it is indeed from that register, then note there is a non-zero offset involved: one function that gives values consistent with the set of values observed and that somewhat matches one set of observations of both fields (which unfortunately had a non-negligible delay between sampling the two) is mV = 2252.362 + 2.81361 * adc#8 (where the multiplier is fairly accurate, but the constant could be out by some multiple of 2.81361).  -- pjrm.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;“Battery monitor check voltage (mV)”&#039;&#039;&#039; field has similar values to the “Instantaneous battery voltage (mV)” field, but without obvious regular spacing.  I don&#039;t know how it&#039;s calculated.  -- pjrm.&lt;br /&gt;
&lt;br /&gt;
Voltage levels depend not just on amount of charge remaining in the battery, but also recent electrical load: the voltage level goes down markedly while the CPU is being heavily used, for example.&lt;br /&gt;
&lt;br /&gt;
There is some weak evidence that the voltage level goes down by about 1mV for each 3 units of backlight level (so 40–50mV for full brightness compared to screen off).  The main weakness of this evidence is that there&#039;s no serious correction for the effect of CPU usage on voltage, and one would assume CPU usage to correlate with backlight.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;“Time per battery bar”&#039;&#039;&#039; seems to be a constant 2520; edit this page if you&#039;ve seen a different value.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;“Average phone current”&#039;&#039;&#039; field has some strangeness in that if there is a long period of high CPU activity then it takes 3-7 seconds before this field&#039;s value increases (even though the voltage field drops straight away, suggesting that the true current does drop straight away); but the field is much quicker to go down once the CPU activity stops, so it&#039;s not just a matter of always lagging by a few seconds (such as because of using a simple averaging/smoothing method).  One might suggest that this could be because some thread that updates the average is at low priority and doesn&#039;t get scheduled for a while, but the &amp;quot;CPU activity&amp;quot; in the experiment consisted of alternating ~100ms of full CPU followed by a usleep of 100ms, so this effect presumably isn&#039;t just because of standard kernel scheduling decisions and niceness.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;“Number of battery bars”&#039;&#039;&#039; is something like min(4, ceil(standby-time-remaining / time-per-bar)), but with a bit of lag: sometimes time-per-bar * n-bars can exceed standby-time-remaining by 2522 or so.  (Where of course standby-time-remaining means the value of the “Remaining standby time to battery low (mins)” field, time-per-bar means the “Time per battery bar” field, and n-bars means the “Number of battery bars” field.)  Note the ‘min(4,’ part: standby-time-remaining can be over 4000mins more than the product of those two fields would suggest.&lt;br /&gt;
&lt;br /&gt;
== Some BULK1 message (0x43, 0x00) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    BMEHeader header;&lt;br /&gt;
    u_int32_t flags;   // Set to 0xFFFFFFFF to get all data&lt;br /&gt;
} BME_EM_BULK1_Req;&lt;br /&gt;
&lt;br /&gt;
struct emsg_bme_bulk1_reply {&lt;br /&gt;
   uint32     unknown1;&lt;br /&gt;
   uint32     unknown2;&lt;br /&gt;
   uint32     unknown3;&lt;br /&gt;
   uint16     // Elapsed model time (min)&lt;br /&gt;
   uint16     // Tx-Off battery voltage (mV)&lt;br /&gt;
   uint16     // Tx-On battery voltage (mV)&lt;br /&gt;
   uint8      // Battery power state&lt;br /&gt;
   uint8      //  Batmon4 internal flags2&lt;br /&gt;
   uint8      // Batmon4 internal flags3&lt;br /&gt;
   uint8      // Charging method&lt;br /&gt;
   uint16     // Present Phi value (mV)&lt;br /&gt;
   uint16     // Present Delta Phi value (mV)&lt;br /&gt;
   uint8      // Charging mode &lt;br /&gt;
   uint8      // Previous charging mode &lt;br /&gt;
   uint8      // Charger type&lt;br /&gt;
   uint8      // Previous charger type&lt;br /&gt;
   uint16     // Instantaneous battery voltage (mV)&lt;br /&gt;
   uint8      // Number of charger checks (0-9) ?&lt;br /&gt;
   uint8      // Charger recognition state&lt;br /&gt;
   uint16     unknown4;&lt;br /&gt;
   uint16     // Instantaneous charger current (mA)&lt;br /&gt;
   uint16     unknown5;&lt;br /&gt;
   uint16     // Charging time (min)&lt;br /&gt;
   uint16     // Average Vchar (mV)&lt;br /&gt;
   uint16     // Equivalent DC charger current (mA) &lt;br /&gt;
   uint8      // Battery full flag (0 or 1)&lt;br /&gt;
   uint8      // HW Cha PWM value L ??&lt;br /&gt;
   uint8      // Cha PWM value L ??&lt;br /&gt;
   uint8      unknown6;&lt;br /&gt;
   uint16     // Open switch battery voltage (mV)&lt;br /&gt;
   uint16     // Closed switch battery voltage (mV)&lt;br /&gt;
   uint16     unknown7;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Some BULK2 message (0x44, 0x00) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
    BMEHeader header;&lt;br /&gt;
    u_int32_t flags;   // Set to 0xFFFFFFFF to get all data&lt;br /&gt;
} BME_EM_BULK2_Req;&lt;br /&gt;
&lt;br /&gt;
struct emsg_bme_bulk2_reply {&lt;br /&gt;
   uint32     unknown1;&lt;br /&gt;
   uint32     unknown2;&lt;br /&gt;
   uint32     unknown3;&lt;br /&gt;
   uint16     // Conf. battery footprint&lt;br /&gt;
   uint16     // Conf. minimum standby current (mA)&lt;br /&gt;
   uint16     // Conf. Batmon battery low voltage (Safety level) &lt;br /&gt;
   uint16     // Conf. Batmon battery low voltage (Empty)&lt;br /&gt;
   uint16     // Configured number of battery bars&lt;br /&gt;
   uint16     unknown4;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Other information about battery life =&lt;br /&gt;
&lt;br /&gt;
Some battery-related information is also available from retu adc registers (which in turn are available via ioctl&#039;s on /dev/rutu: see retu-adc source).&lt;br /&gt;
&lt;br /&gt;
It&#039;s said that register 3 shows whether charging is occurring: with value 0 meaning &amp;quot;not being charged&amp;quot;, while &amp;quot;values 0xff and above&amp;quot; are an indication of the voltage being applied for charging.  Matan adds (http://talk.maemo.org/showpost.php?p=259465&amp;amp;postcount=43) that values around 0x100 indicate charging, while values around 0x170 indicate that the power source is connected but we aren&#039;t charging.&lt;br /&gt;
&lt;br /&gt;
Register 8 apparently indicates battery voltage.  See the note above about “instantaneous battery voltage (mV)” for how it might correspond to one measure of voltage.&lt;br /&gt;
&lt;br /&gt;
Note that this value can fluctuate a lot when the device is in use, but when idle it gets a good fit to the curve adc#8 = 438.3 + exp(p0 + p1*t) - exp(n0 + n1*t) where t is time (or more generally charge used or remaining), and p0,p1,n0,n1 are constants.  (I forget the values I found for them, but in any case it would be good to fit for them again once more data is on hand.)&lt;br /&gt;
&lt;br /&gt;
To invert this function to find idle time remaining (on assumption that the device was idle when the register was read), first see whether the adc#8 value is above or below 438.3, which tells you which exponential is dominant, and approximate the other exponential with a constant 3 (or a straight line if you like); can iterate and update this approximation for the neighbourhood of the solution found by the previous iteration.  -- pjrm&lt;/div&gt;</summary>
		<author><name>118.208.239.196</name></author>
	</entry>
</feed>