Reverse engineered by Diego Elio Pettenò.
The communication protocol as described in this document applies to the following models:
Not to be confused with the the previous generation of OneTouch Verio meters, the 2015 edition comes with a microUSB-A connector, rather than a TRS (stereo-jack.)
|Device||Vendor ID||Product ID|
|OneTouch Verio 2015||2766||0000|
The device is identified by operating systems as a standard USB Mass Storage device of disk type. No custom drivers are required.
The original software does not use any knocking sequence, no extra device or interface is available.
The registers are accessed through SCSI commands WRITE(10) and READ(10). Raw commands seem to be required, as the device rejects any CDB (Command Block) with non-default flags set.
There does not appear to be any specific requirement of timing between the WRITE(10) command the subsequent READ(10). The response for a given request is read from the same register it has been written to. Message are specific to one register and will not work if written to a different register.
No knock sequence is needed to initiate communication.
Since the device communicates by what would otherwise be a destructive change to its storage, it is important that the commands are not issued to a non-compatible device, as they might damage the partition table of an external storage device.
It is possible to identify the device by inspecting either the USB Device descriptor, or issuing a SCSI INQUIRY command.
In the USB descriptor, the device will report an Interface descriptor as such:
bInterfaceClass 8 Mass Storage bInterfaceSubClass 6 SCSI bInterfaceProtocol 80 Bulk-Only iInterface 7 LifeScan MSC
LifeScan MSC string identifies the mass-storage controller
protocol as being non-standard.
iSerial are also matching the information
reported by the LifeScan communication protocol.
At the SCSI level, the device will report a Vendor identification
Vendor identification: LifeScan Product identification: Product revision level: Unit serial number:
Note that while the USB protocol information (product, serial number) match the device’s information, only the vendor identification is visible in response to the INQUIRY command.
Message, both sent and received, in any of the registers follow the same structure:
message = STX length message ETX checksum STX = %x02 length = 2OCTET ; 16-bit little-endian value message = [length - 6]OCTET ETX = %x03 checksum = 2OCTET ; 16-bit little-endian value
The messages are variable length, with the length provided by the
16-bit word following the
STX constant. The value of length includes
the STX/ETX constants, the length itself and the checksum, leaving the
body of the message 6 bytes short.
While no command has been recorded using more than 255 bytes, the length is assumed to be 16-bit to match out of band information in the original software’s debug logs. The size of the register also makes the maximum lenght of the command 512 bytes (0x200).
ETX constants to mark start and end of the message
match the constants used in the OneTouch Ultra Easy serial protocol,
and are thus named the same way as in its specs.
checksum is a variant of CRC-16-CCITT, seeded at
stored little-endian, again the same as used in the OneTouch Ultra
If the checksum is not valid, the device will not process the message, and the next READ request to the LBA will return the content as written.
Messages are binary, and only some are related to each other in any obvious way.
The commands have been named after their function, in the style of SCSI commands:
A single message with a byte specification provides information on the
hardware device. The request is sent through, and the response read
QUERY-request = STX %x0a %x00 ; message length = 10 bytes %x04 %xE6 %x02 query-selector ETX checksum query-selector = query-selector-serial / query-selector-model / query-selector-software / query-selector-unknown / query-selector-date-format / query-selector-time-format / query-selector-url / query-selector-languages query-selector-serial = %x00 query-selector-model = %x01 query-selector-software = %x02 query-selector-unknown = %x03 query-selector-date-format = %x04 query-selector-time-format = %x05 query-selector-url = %x07 ; http://www.lifescan.co.uk query-selector-languages = %x09
The reply starts with what appears an arbitrary pair of bytes, and
then follows with what appears to be a UTF-16-LE string, NULL
terminated (except for the
QUERY-response = STX length %x04 %x06 *WCHAR-LE %x00 %x00 ETX checksum
Devices sold on multilingual markets allow the selection of the
language to use through settings. The QUERY selector
appears to provide the list of supported languages in the device.
WALPHA-UPPER = %x41-5A %x00 WALPHA-LOWER = %x61-7a %x00 WDIGIT = %x30-39 %x00 WIDESP = SP %x00 WSEMICOLON = ";" %x00 WDOT = "." %x00 LANGUAGES = language *(WSEMICOLON WIDESP language) language = language-code country-specifier WIDESP language-version language-code = 2WALPHA-UPPER country-specifier = WALPHA-LOWER language-version = 2WDIGIT WDOT 2WDIGIT WDOT 2WDIGIT
The languages are given as a list of wide-char (little endian)
specifications of languages. Each language specification includes a
main language code (which appears to match ISO language codes) and
some country specification:
ENu for English (US) and
The device appears to provide some information on the date and time format to use for displaying date and time, although this does not match the actual format displayed on the device.
The format appears to be similar to
strftime, but it is not
compatible with the POSIX interface for it.
|%I||Hour as decimal number, 24-hour clock|
|%h||Hour as decimal number, 12-hour clock|
|%T||Minute as decimal number|
|%p||Either “AM” or “PM”|
|%D||Day of the month as decimal number|
|%n||Abbreviated month name|
|%y||Year as decimal number|
The meter repors a number of parameters in a similar fashion to the
QUERY command. The request is sent through, and the response read
READ-PARAMETER-request = STX %x09 %x00 ; message length = 9 bytes %x04 parameter-selector OCTET ETX checksum parameter-selector = parameter-selector-timefmt / parameter-selector-datefmt / parameter-selector-unit parameter-selector-timefmt = %x00 parameter-selector-datefmt = %x02 parameter-selector-unit = %x04
OCTET following the selector appears to be completely ignored.
The response is provided in different formats, depending on the parameter requested.
READ-PARAMETER-response = STX length %x03 %x06 parameter-response ETX checksum parameter-response = parameter-response-timefmt / parameter-response-datefmt / parameter-response-unit parameter-response-timefmt = *WCHAR-LE %x00 %x00 parameter-response-datefmt = *WCHAR-LE %x00 %x00 parameter-response-unit = parameter-unit-mgdl / parameter-unit-mmol parameter-unit-mgdl = %x00 %x00 %x00 %x00 parameter-unit-mmoll = %x01 %x00 %x00 %x00
Time and date formats match those returned by the QUERY command.
The request to query the device time is fairly simple, and is
READ RTC-request = STX %x09 %x00 ; message length = 9 bytes %x04 %x20 %x02 ETX checksum READ RTC-response = STX %x0c %x00 ; message length = 12 bytes %x04 %x06 timestamp ETX checksum timestamp = 4OCTET ; 32-bit little-endian value
Timestamp, both for the device’s clock and for the reading records, is defined as a little-endian 32-bit number, representing the number of seconds since 2000-01-01 00:00:00.
It should not be mistaken for a UNIX timestamp, although the format is
compatible. To convert to UNIX timestamp, you should add
to the value (the UNIX timestamp of the device’s own epoch.)
The WRITE RTC command is also communicated through
WRITE RTC-request = STX %x0d %x00 ; message length = 13 bytes %x04 %x20 %x01 timestamp ETX checksum WRITE RTC-response = STX %x08 %x00 ; message length = 8 bytes %x04 %x06 ETX checksum
The following messages correspond to request and response for the
number of records in memory. The messages are transmitted over
READ-RECORD-COUNT-request = STX %x09 %x00 ; message length = 9 bytes %x04 %x27 %x00 ETX checksum READ-RECORD-COUNT-response = STX %x0a %x00 ; message length = 10 bytes %x04 %x06 message-count ETX checksum message-count = 2OCTET ; 16-bit little-endian value
The records are then accessed through indexes between 0 and
message-count (excluded) as reported by READ RECORD COUNT.
READ-RECORD-request = STX %x0c %x00 ; message length = 12 bytes %x04 %x31 %x02 record-number %x00 ETX checksum record-number = 2OCTET ; 16-bit little-endian value
The record number is assumed to be a 16-bit little endian value, as the Verio 2015 is reported to store up to 500 results. It is also consistent with the UltraEasy protocol.
Records are stored in descending time order, which means record
the latest reading.
READ-RECORD-response = STX %x18 %x00 ; message length = 24 bytes %x04 %x06 inverse-record-number %x00 lifetime-counter timestamp glucose-value flags %x0b %x00 ETX checksum inverse-record-number = 2OCTET ; 16-bit little-endian value liftime-counter = 2OCTET ; 16-bit little-endian value glucose-value = 4OCTET ; 32-bit little-endian value flags = OCTET
The inverse record number seem to provide a sequence of readings, it would be interesting to compare its value for a reader that exceeded its storage memory.
A lifetime counter is also present, that will keep increasing even though the device’s memory is cleared with the ERASE MEMORY command. The original offset of the meter is likely related to the factory calibration.
The glucose value is represented as a 32-bit little endian value, to continue the similarities with the UltraEasy device. It represent the blood sugar in mg/dL. As most other meters, the eventual conversion to mmol/L happens only at display time.
The flags are not currently well understood; the device allows setting comments on the readings, but these responses are not visible from the interface of the device itself; a “speech bubble” appears, steady or blinking, on some of the readings instead. The original software does not seem to expose the data correctly either.
At least two information are likely to be found in these flags, or in
the following constant
0x0b byte: the type of measurement (plasma v
whole blood) and the measurement site (fingertip), as those are
visible in the original software’s UI. Meal information might also be
present. OneTouch Ultra2 provided a simple mapping of meal and comment
The memory erase command deletes all the records in the device’s
memory. It is communicated over
MEMORY-ERASE-request = STX %x08 %x00 ; message length = 8 bytes %x04 %x1a ETX checksum MEMORY-ERASE-response = STX %x08 %x00 ; message length = 8 bytes %x04 %x06 ETX checksum
Remember that this action is irreversible.