Hacking E-ink Price Tag

I got an E-ink price tag from a friend and wanted to mess around with it. My goal was to redraw the contents of the display.
My first step was to disassemble the device and take note of all serial numbers outside or inside. Disassembling was rather easy, the device is luckily not glued together. The disassembly is done by prying open the front frame.
Pasted image 20231213165636.png
Pasted image 20231213165801.png
Pasted image 20231213165646.png
I found that the device model is VUSION 2.6 BWR GU140 by SES-imagotag. The main controller chip is Texas Instruments CC2510 with 32kB flash. The display is 2.66" 3-color panel by Pervasive Displays. It was a bit harder to find --- the model number written on the display is SE2266JS0C2 but the manufacturer leaves out the leading S- in their manuals and so the actual model number is E2266JS0C2.
Interestingly, searching for SE2266JS0C2 (with the S) on Google yields no results but searching for the same query on DuckDuckGo or even Bing leads correctly to the Pervasive Displays website.
Pasted image 20231212165603.png
Pasted image 20231212162911.png

Looking around the internet I found several works on reusing the E-ink price tags:

  • Aaron Christophel hacked many different price tags and even wrote a custom firmware OpenEPaperLink for ZBS243-based tags. In the Driving an 4.4" Black White Red E-Paper Pricetag with an ESP32 and Arduino video he reuses a similar 4.4" Imagotag price tag by removing the original CC2510 controller and replacing it with ESP32.
  • Andrei Tatar seems to have re-flashed the CC2510 using a debugging interface the Texas Instruments chip provides. The repository contains pinout of the chip, photos of the connections to his flashing tool and the code for his firmware. Sadly, the repository is not documented so it would take time to understand what is going on there exactly.
  • Jasper Devreker published a brilliant blog post about circumventing the debug lock on the CC2510 in a similar E-ink price tag. Using a voltage glitching attack he was able to dump the original firmware from the device.

Three options

From this point, I saw three possible routes, inspired by the related work:

  1. dump the firmware of CC2510, reverse engineer it and either try to find vulnerability that would allow redrawing the screen or modify the firmware to allow that.
  2. re-flash the CC2510 with a custom firmware
  3. replace the CC2510 with my controller

The first option seems quite difficult and the result is uncertain although it is the most interesting option. For the second option, I would need a CC-debugger from TI or I would need to build it. I have ordered the debugger from Aliexpress for ~6 EUR. But I didn't want to wait and so I proceeded with the third option.

I found that Pervasive Displays offers development kits for their displays and distributes examples for many platforms including Arduino and Raspberry Pico. Because I had some Picos (Waveshare RP2040 Zero) laying around, I figured I would use them as the controller chip.

I have compared the driving circuit schema from the E2266JS0C2 reference manual with what I saw on the price tag PCB and confirmed that it matches closely. Using GIMP I overlaid the top and bottom photo of the PCB and traced the connections to the CC2510.

Schema PCB
Pasted image 20231213115356.png Pasted image 20231213121158.png

Replacing the MCU

It was time to unsolder the controller chip, solder wires to the traced pins and prepare a socket for my Raspberry Pico.
To unsolder the chip, I used my cheap and trusty hotair station from Aliexpress. I covered the plastic connector with kapton tape to make sure I don't melt it. The PCB is thin and unsoldering the chip was very quick so the kapton tape was probably an overkill. Still, better safe than sorry.
I also removed the battery legs because I figured the chip will not be powered from batteries anymore.
After that I cut up a 0.1mm enameled coil wire and removed the insulation on the ends by heating my solder station to ~400°C and putting each wire end into a hot blob of solder.
I soldered the wires under a microscope.
Pasted image 20231213122505.png
I soldered the other ends onto a socket, following the pin ordering from the display FPC cable.
For VCC I soldered the socket directly to the pin at the bottom of the PCB. For ground I scraped off a bit of the PCB insulation layer so that I could solder the other end of the socket directly to the ground plane of the PCB. This way, the socket is nicely secured to the board.

Preparing Raspberry Pi Pico

Now the only thing that remains is to flash the RP2040-Zero and connect it to our E-ink board. To flash the board, I followed the guide linked from Pervasive Displaysand used the Common_Fonts arduino sketch example from the PDLS_EXT3_Basic_Global library.
The only adjustments were to change the screen definition to eScreen_EPD_EXT3_266_BWR:

Screen_EPD_EXT3 myScreen(eScreen_EPD_EXT3_266_BWR, boardRaspberryPiPico_RP2040);

and in case of my RP2040-Zero, I needed to change the SPI pins to ones that are exposed on the small board:

void setup()

To connect the Raspberry with the screen, I followed the pin definitions in the boardRaspberryPiPico_RP2040 struct in PDLS_EXT3_Basic_Global/src/hV_List_Boards.h:

const pins_t boardRaspberryPiPico_RP2040 =
    ///< EXT3 and EXT3-1 pin 1 Black -> +3.3V
    ///< EXT3 and EXT3-1 pin 2 Brown -> SPI SCK GP18
    .panelBusy = 13, ///< EXT3 and EXT3-1 pin 3 Red -> GP13
    .panelDC = 12, ///< EXT3 and EXT3-1 pin 4 Orange -> GP12
    .panelReset = 11, ///< EXT3 and EXT3-1 pin 5 Yellow -> GP11
    ///< EXT3 and EXT3-1 pin 6 Green -> SPI MISO GP16
    ///< EXT3 and EXT3-1 pin 7 Blue -> SPI MOSI GP19
    .flashCS = 10, ///< EXT3 and EXT3-1 pin 8 Violet -> GP10
    .panelCS = 17, ///< EXT3 and EXT3-1 pin 9 Grey -> GP17
    .panelCSS = 14, ///< EXT3 and EXT3-1 pin 12 Grey2 -> GP14
    .flashCSS = 15, ///< EXT3 pin 20 or EXT3-1 pin 11 Black2 -> GP15
    ///< EXT3 and EXT3-1 pin 10 White -> GROUND

And I compared it with the Development Kit schema:
Pasted image 20231212233405.png
Of course, the SPI pins are different because I redefine them manually in the setup() procedure.

The first time I ran the sketch, the display didn't do anything but that was because I connected the SPI pins wrong. After I fixed the SPI pins to be on GP1-GP4 as I explained before and reconnected the Raspberry, the screen started to blink and update!!
Sadly, while I was working on this project, I accidentally dropped the display and it broke, so the new screen content is not legible. But the stated goal was to redraw the contents and so I was happy with this result :-)