OneTouch Verio 2015

Reverse engineered by Diego Elio Pettenò.

The communication protocol as described in this document applies to the following models:

  • OneTouch Verio 2015 (microUSB connector)
  • OneTouch Select Plus
  • OneTouch Select Plus Flex (USB connection only)

Important device notes

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
OneTouch Select Plus 2766 1000
OneTouch Select Plus Flex 2766 1004


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.

Communication is apparently achieved through three 512-bytes registers, implemented as flash device sectors with LBA 3, 4 and 5. These will be referenced as lba3, lba4 and lba5 in this text.

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.

USB identification

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

The LifeScan MSC string identifies the mass-storage controller protocol as being non-standard.

The USB iProduct and iSerial are also matching the information reported by the LifeScan communication protocol.

SCSI identification

At the SCSI level, the device will report a Vendor identification string of LifeScan:

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.

Packet Structure

The registers are all 512 bytes in size (SCSI block size), and contain a padded packet as defined by the Shared Binary Protocol.

Within the packet, the link-control byte is unused and always left at 0x00.

The command-prefix byte may have one of accepted values as defined below, but for ease of implementation, 0x03 is suggested, as the READ PARAMETER command will not echo the chosen prefix, but always return 0x03.

packet                  ; see
link-control = %x00     ; not used by this device
command-prefix = %x03 / ; suggested
                 %x04 / %x05

Timestamp Format

Timestamps, both for the device's clock and for the reading records, are 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 946684800 to the value (the UNIX timestamp of the device's own epoch.)


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:

  • QUERY to retrieve information on the device (serial number, device model, etc.)
  • READ PARAMETER to retrieve parameters set for the device (time and date format, glucose unit used.)
  • READ RTC to retrieve current RTC time of the device.
  • WRITE RTC to change the RTC time fo the device.
  • READ RECORD COUNT to retrieve the number of records in the device's memory.
  • READ RECORD to retrieve the content of one record.
  • ERASE MEMORY to clear the meter altogether.


A single message with a byte specification provides information on the hardware device. The request is sent through, and the response read from, lba3.

QUERY-request = STX %x0a %x00 ; message length = 10 bytes
                %x03 %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-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  ;
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-selector-unknown response.)

QUERY-response = STX length
                 %x03 %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 0x09 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 ENe for English (UK).

Date and time format

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.

Specifier Meaning
%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 from, lba4.

READ-PARAMETER-request = STX %x09 %x00 ; message length = 9 bytes
                         %x03 parameter-selector OCTET
                         ETX checksum

parameter-selector = parameter-selector-timefmt /
                     parameter-selector-datefmt /

parameter-selector-timefmt = %x00
parameter-selector-datefmt = %x02
parameter-selector-unit = %x04

The 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-timefmt = *WCHAR-LE %x00 %x00
parameter-response-datefmt = *WCHAR-LE %x00 %x00

parameter-response-unit = parameter-unit-mgdl / parameter-unit-mmol
                          %x00 %x00 %x00
parameter-unit-mgdl = %x00
parameter-unit-mmoll = %x01

Time and date formats match those returned by the QUERY command.


The request to query the device time is fairly simple, and is communicated through lba3:

READ-RTC-request = STX %x09 %x00 ; message length = 9 bytes
                   %x03 %x20 %x02
                   ETX checksum

READ-RTC-response = STX %x0c %x00 ; message length = 12 bytes
                    %x03 %x06 timestamp
                    ETX checksum

timestamp = 4OCTET ; 32-bit little-endian value


The WRITE RTC command is also communicated through lba3.

WRITE-RTC-request = STX %x0d %x00 ; message length = 13 bytes
                    %x03 %x20 %x01 timestamp
                    ETX checksum

WRITE-RTC-response = STX %x08 %x00 ; message length = 8 bytes
                     %x03 %x06
                     ETX checksum


The following messages correspond to request and response for the number of records in memory. The messages are transmitted over lba3.

READ-RECORD-COUNT-request = STX %x09 %x00 ; message length = 9 bytes
                            %x03 %x27 %x00
                            ETX checksum

READ-RECORD-COUNT-response = STX %x0a %x00 ; message length = 10 bytes
                             %x03 %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
                      %x03 %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 OneTouch UltraEasy protocol.

Records are stored in descending time order, which means record 0 is the latest reading.

READ-RECORD-response = STX %x18 %x00 ; message length = 24 bytes
                       %x03 %x06 inverse-record-number
                       %x00 lifetime-counter
                       timestamp glucose-value flag-meal %x00
                       other-flags %x0b %x00
                       ETX checksum

inverse-record-number = 2OCTET ; 16-bit little-endian value
liftime-counter = 2OCTET       ; 16-bit little-endian value
glucose-value = 2OCTET         ; 16-bit little-endian value
other-flags = OCTET

flag-meal = meal-none / meal-before / meal-after
meal-none = %x00
meal-before = %x01
meal-after = %x02

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 16-bit little endian value. It represent the blood sugar in mg/dL. As most other meters, the eventual conversion to mmol/L happens only at display time.

The meal flag is a single byte, representing a tristate of no information, before meal reading, and after meal reading. This meal information cannot be set on the Verio meter, but can be set on the Select Plus.

The second set of flags are not currently well understood; Verio meters allow 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. These may be used by other models such as Select Plus.

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.

Caution: at least one byte in the record will likely represent a control solution test, rather than an actual blood glucose reading; which value is that is still unknown.


The memory erase command deletes all the records in the device's memory. It is communicated over lba3.

MEMORY-ERASE-request = STX %x08 %x00 ; message length = 8 bytes
                       %x03 %x1a
                       ETX checksum

MEMORY-ERASE-response = STX %x08 %x00 ; message length = 8 bytes
                        %x03 %x06
                        ETX checksum

Remember that this action is irreversible.