# sitronix usb keychain

## gnac

So my wife got a Royal USB keychain as a gift that displays images on the keychain.

In typical fashion with crappy devices like these, linux is not supported, and it doesn't appear to behave as a typical usb storage device.  When I plug in it, dmesg gives me the following:

```
usb 3-2: new full speed USB device using ohci_hcd and address 8

usb 3-2: configuration #1 chosen from 1 choice

scsi5 : SCSI emulation for USB Mass Storage devices

usb-storage: device found at 8

usb-storage: waiting for device to settle before scanning

  Vendor: SITRONIX  Model: MULTIMEDIA        Rev: 0.09

  Type:   Direct-Access                      ANSI SCSI revision: 00

SCSI device sda: 4096 512-byte hdwr sectors (2 MB)

sda: Write Protect is off

sda: Mode Sense: 0b 00 00 08

sda: assuming drive cache: write through

SCSI device sda: 4096 512-byte hdwr sectors (2 MB)

sda: Write Protect is off

sda: Mode Sense: 0b 00 00 08

sda: assuming drive cache: write through

 sda: unknown partition table

sd 5:0:0:0: Attached scsi removable disk sda

usb-storage: device scan complete

```

lsusb gives

```
Bus 001 Device 001: ID 0000:0000

Bus 003 Device 008: ID 1403:0001

Bus 003 Device 002: ID 045e:00db Microsoft Corp.

Bus 003 Device 001: ID 0000:0000

Bus 002 Device 001: ID 0000:0000

```

So Device 8/1403 appears to be the usb key chain.  There are no devices under /dev/sda (eg /dev/sda8).  I even tried to mount /dev/sda but that didnt work either.  Any thoughts on how to get this working?  

I installed the supplied windows software under wine, but it didn't work, the software couldn't find the device.

----------

## xpd259

ditto here. any joy yet with it under linux or windows?

I've got 2 of the paper weights the missus got them as xmas gifts

----------

## GroovBird

I bought one in a toy shop while on a shopping spree for the holidays. I'm not exactly a Gentoo user, but I wanted to reply to this thread because I found it while googling on the subject.

I got it to work under Windows, and it actually works like a charm. I think the use of the USB Mass Storage class was pretty clever, as it doesn't require you to install a driver on any modern end-user OS.

I did however found that it sets up a "drive" under Windows, which is a bit dangerous because when I tried to open that Windows asked if I wanted to format it. Which I didn't, of course...

Then I used Hexviewer to take a look at all the blocks on the drive, because my second guess was that it would just expose the whole Flash memory as a single big block with a propietary format easier to read from the cheap-o flip-chip microcontroller on the board. But every sector read exactly the same.

So then I used Sysinternals' Process Monitor to see what kind of interaction takes place between the Photoviewer.exe app and the drive, and it seems that it uses the block device as a two-way communication with the microcontroller.

The application writes 512 bytes to offset 25088 on the device, and it then reads 64KB from 45056. It does this several times on startup. I don't have a tool handy to find out the bytes that are sent and those that are read, so I'm not going further into that right now. When synchronizing, it writes as follows:

* 512 bytes to offset 25088

* 32758 bytes to offset 26112

* 512 bytes to 25088

* reads 512 bytes from 45056

and does so for every picture added.

From the screen it looks like a 32x32 graphical screen, and while it's possible there's a 32-bit image in each block of 32KB, I think 32KB (32x32x32) seems a bit much for one image. Maybe not all of that space is used to write the picture.

You'd have to get really digging to find out how the whole process works.

Just my .02

Dave

----------

## xpd259

after geting rather annoyed i took mine apart and disconected the battery

and re connected it and that seem to do the trick the photo app program seems to work again :-/

very odd

still no joy with linux but hey 1 beter then none

----------

## grizzlybear

I also have 2 similar devices, what can I do to help supporting these devices?

I downloaded Snoopy USB debugger, so I can sniff messages. I will start analyzing what is happening when syncing, so maybe we can reverse engineer what's happening.

----------

## WingGnDm

I got most of the data that i need to reverse engineer it.  Just need a good way to do random read/write to a block device.

something like this

/*

the device is 4096 * 512byte sectors = 2mb

sector 49 is for commands

reading images starts at sector 88

writing images starts at sector 51

the device also has a 64K section which stores things line the names of the images

and probably a map of which image slots are taken up

the device reserves sectors 256-4095 for images

enough for 60 images

0-255 are for the command sector and buffer

-------------map of first 256 sectors-----------------

0-48 are probably read only so you can't format

49 is the command block

50 is useless or read only

we write starting from 51 to 114

we read starting from 88 to 151

152-255 most likely is used for the 64K map which holds the names of the files

and which image slots are used up

*/

char image[32768];         /*each picture is a 128x128 x 16bit image, 32K*/

char map[65536];            /*the map that contains the image names and other info*/

char command_buf[512]; /*sector 49 on the device is for commands*/

write_cmd(block_dev[49],command_buf); /*write out command to device*/

read_32(block_dev[88],image);                /*read in a 32K image*/

read_64(block_dev[88],map);                  /*read in 64K internal map*/

write_32(block_dev[51],image);               /*write out a 32K image*/

write_64(block_dev[51],map);                  /*write out the new 64K map*/

if some one can give me a good way to do this type of random access read/write to the block device, i might be able to do it

----------

## gnac

Do we have any idea of what the commands are (for sector 49)?

My experience in the past tells me that we need to follow a sequence like:

write_cmd(GET_READY_FOR_IMAGE);

write_32(*ptr_to_image);

write_cmd(IMAGE_READY);

At which point the device will copy the image buffer into its own internal storage, if there is in fact no direct access to the storage.

----------

## WingGnDm

Yea i have dumps of the commands needs, and i believe i figured out which bits are used for the image index.

I will post them up later.  The sequence is just like this

startup

command

read_map

get image 1 by 1

command

read_image

command

read_image

....

i believe they just redirect the read requests to what ever is set in the command.

I also started to write up the basic functions needed.  Its just going to be a pain to put the commands into the source files since they are 512bytes each.

Good thing that there are only 4 commands needed.

----------

## WingGnDm

this is the 512bytes sent to sector 49

http://filebin.ca/gejkhw/getimage

http://filebin.ca/tozxam/1image

this is one of the images in the device, if someone can figure out its format and make it usable it would help out a lot.

As far as i can tell, it should be 16bit rgb, 128x128.

PS is the get_image command, later i will post the

get_map command and a dump of the 64K map

when viewed with the hex editor, it shows the names

of the images.

----------

## WingGnDm

Here is the command sent to get the map,

http://filebin.ca/aezozc/getmap

and here is what is the map that is retrieved

http://filebin.ca/fnhvar/map

the map is 64K, looks like it saves the name of the file in multiple places and the index of the image.

----------

## crybaby

i think that a lot of the data in those dumps is junk data to pad out the commands. where the filename is repeated looks to me like repeating whatever is in the buffer until reach a certain sector number. 

the get image cmd i think is : 4.L 2.L and i reckon rest is junk bytes.

and the get map i think is: 4.L 1.L

----------

## crybaby

also, i believe that the device has 70 slots (0-69) that is the number of entries i get in a dd of the filesystem.

----------

## crybaby

WingGnDm are the getmap and getimage commands identical for each image? did you do md5sum of each to see if they are exactly the same?

----------

## WingGnDm

The command is almost the same for each one.  There is 1 byte that is always different for each image.  It seems that there is some init code that i am still missing.  With out it, most of the area that the program uses, is not readable and writable.  As for the dd dump.  Don't trust it.  Its a repeating pattern.  When the program first starts up.  It read the first byte of the device, i think its to verify that it is the device it wants.  Use  something like ghextedit and search for "SITRONIX CORP".  You will see that it just repeats several times.  This leads me to believe that what we see is just an interface and not the actual memory that is in the device.  I read some where that the device actually has 8MB of internal ram, so we might be able to add in more pictures that the program allows us to right now. I have a dump of all bytes sent to and from the device when the program starts.  I decided that for now, i will save each command sent to the device at startup into files, read them in and send them to the device to see if it gives me access.  I will probably report the result back tonight or tomorrow.

----------

## gerard

On http://gkall.hobby.nl/dpf018.html i collected some data about this device, also placed a usb command file (collected with a usb analyser). for the dpf018 (96x64 display)

Seems there are different devices, difference 128x128 and 96x64 besides display ?

----------

## WingGnDm

I still can't seem to read when i set the offset to 45056.

        fseek(blockdev, 25088, SEEK_SET);

        fwrite(get_map2, 512, 1, blockdev);

this is written to the device

http://filebin.ca/hfdnwc/getmap-2

get_map2 is a 512byte block that is written to the device

this should have been the one that gives me access the

rest of the device.

        fseek(blockdev, 45056, SEEK_SET);

        fread(get_map1, 512, 1, blockdev);

http://filebin.ca/zwshg/getmap-1

what should have been read but it blocks waiting for it to be returned.  I have to unplug the device to make the program quit.

this is what photo viewer does in windows when it starts up and loads the images, the write is when you write out the files, you will see a jump in the time stamp.

http://filebin.ca/ukugjx/photo_viewer_access.tar.gz

the problem might have to be with buffering.  The program requests no buffering, synchronous access.  How would i get the equivalent type of access in linux? any one have an idea?

----------

## WingGnDm

Ok i'm getting some where now.  I had to use open to set O_DIRECT and O_SYNC then use fdopen.  I wrote the getmap2 command and when i read offset  45056, i got getmap1 which is what i expected.  I then wrote the getmap command, but all i get when reading offset 45056 is all 0s.  I will do another dump of transfers later.  I might have missed something or got the wrong command.

Correction:

 What i got when i read was something very close to what i got from the dump.  I compared it to the getmap and it seems that it uses what is returned from getmap1 to create the getmap command.

PS the order goes like this if your confused about the naming

write getmap2

read getmap1

write getmap

read map

the reason is that i already created get map but found out i needed 2 things before it.

----------

## WingGnDm

Good news, i made good progress.  I am now able to get the map which holds the names of the files.  once i clean up the init code i will post it up as well as the code to read the map.  Next will be retrieving the images.  This shouldn't be hard since i already have the commands for them.  The hard part was getting the device to actually accept the commands.

----------

## crybaby

that is great news WingGnDm. can't wait to try out your code. btw are you using libusb or kernel driver?

----------

## dracohack

I found this thread while looking for other people hacking the keychain i bought.  Glad to see there is so much progress being made!

My device is a Coby DP-151, which is a 128x128 pixel model.

I disassembled mine to see what I could learn from the guts.  The only chip i was able to learn anything about was the A29L800ATV-70F inside, which is a 1 megabyte boot sector flash chip.  I wonder if the code for the microcontroller lives in there?  This has a lot of hack potential, I think!

----------

## crybaby

the one inside mine is an integrated chip. it has 3 product codes on the same chip, i guess flash memory ram and processor are on the same die?

----------

## WingGnDm

Would any one be willing to make a udev rule for this device?  I need the device to show up as something like

/dev/sitronix

with read/write access under a reasonable group like image.

I don't want this program to be used as root on any other block device.

It would be a disaster if some one by accident runs it on /dev/sda or anything like that.

I adding a check_dev function which reads the 1st block of the dev, which constains the string SITRONIX_MULTIMEDIA in it.  I can check for that string to make sure it doesn't mess up people's system.

Oh yea, it seems i was wrong on the images.  I now believe that each 32K block holds 2 images and not just 1.  Figuring out the images will probably be the hardest part.

Bellow is a link of what i have so far.  Tomorrow I'll add the promised get_image command.  I ran into some problems with the 4k boundary that comes with fwrite and fread which i was using before.

http://filebin.ca/kmmkec/coby.tar.gz

you first need to make the symlink /dev/sitronix to the device

and use it as root.  MAKE SURE THAT YOU KNOW WHICH DEVICE IT IS.

it will write out the tmp_out.bin which if you read with a hexeditor should show you the names of the files you have in the keychain.  :Smile: 

----------

## crybaby

hey WingGnDm, 

i recommend

s/@/_at_/

s/./_dot_/

in keychain.c before you get indexed by google  :Smile: 

btw, why do you use posix_memalign fn?

----------

## WingGnDm

When using O_DIRECT, the buffer that you use has to be aligned, or read and write will return invalid argument.  You have to use O_DIRECT because the contents of the device can change after you write a command.  Also, if you don't use it, reads will block for ever more than likely.

I am going to email the kernel devs later about these devices because they report themselves as  usb mass-storage devices when they really aren't.  This is what was recommended by the libusb guys.  It also will probably mean that i will have to use libusb instead of standard read and write.

----------

## WingGnDm

Ok updated, with get_image, it takes in the file descriptor, an buffer to write the image to, and which image block you want to retrieve.   Also clean up the code for get_map,  it turns out i don't need all of the 512byte for commands, its just the first 6, which makes sense.  Does any one know if there is a version of memalign which returns the space already initialized to 0s?  I'll now be checking which way to get the number of images in the device.  I think the raw number is in the first few bytes of the map, or we can just check how many names there are in the map manually.

http://filebin.ca/vusvrk/coby.tar.gz

----------

## gerard

If the choice is, using a userspace program, maybe using gtkam with libgphoto (camlib) can be a good choice, some time ago i wrote to the gphoto mailinglist about this device. Some reaction was, its usb-storage so not for libgphoto.

I don't have a list with the correct reasons why usb-storage is not usable.

Reason for me to choice for libgphoto is that is included in many or all distrbutions so people can use it.

WingGnDm, if its OK with you i like to place your files on my homepage?

----------

## WingGnDm

That would be a good idea.  I just read the email.

"No I don't think. The device is apparently a mass storage device. 

Hub"

He is under the impression that these devices are actually mass storage device, but they aren't.  The device that show up as a mass storage device doesn't even have a file system.  It is just an interface for the device.

If you want, check out the libusb mailing list.  You will see the discussion on these devices.  The best thing to do is black list them as mass storage devices, and mark them as generic scsi devices, then use udev to create the standard /dev entry.  Or we can go the even longer way and pretty much use libusb to access the device, but then we would basically be duplicating code thats already in the kernel.

The hardest part will be figuring out the format of the images.  As of right now you can dump the images using the get_image function.

I believe i figured out how the device determines the number of pictures in the device.  There is a bitmap in the map.   On every line with the names of the files, there is a byte that is eigther 0 or 1, if its 1, then the image is valid, if its 0, it has been delete.  The best way to handle this is run down the list of names, until you hit a null string.  then use the bitmap to show which ones are valid and which have been delete.  This could also allow us to recover deleted images.  The images are marked invalid when you use the delete function in the device.  The list is rewritten by the program.

gerard, it's fine by me if you post them on your site.

If anyone is able to figure out the image format, please post it here.

----------

## dracohack

I'm not aware of a function to allocate and zero an aligned area, but you could do the posix_memalign() and replace your for() loop with: memset(&get_map, 0, 512);

I'm at work right now and my keychain's at home, but if you can post a binary of a retrieved image i'd take a look at it and see what we can do to make it viewable.

edit: corrected my memset arguments

----------

## greytortoise

If you pull an image off of the keychain using the Mac PhotoViewer.app application, it saves the image in TIFF format.  While it's possible that the image needs to be specifically formatted for the particular LCD display and is being reformatted by the app before saving it as a .tiff file, it is also quite possible that the device itself uses TIFF.  TIFF is defined by Adobe in the spec:   http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf, and is described as a format that describes and stores raster image data  *Quote:*   

> that typically comes from scanners, frame grabbers, 
> 
> and paint- and photo-retouching programs

 .  Given the type of device, I'd be surprised if the image data wasn't either TIFF or something very close.

----------

## blooflame

I think TIFF requires too much processing for a small MCU.

Note, I'm not a Linux person yet, but I am trying to understand the tools for hacking this device (mine came from Digital Foci, seems that they sold this design to many).

I am currently using XP and USB Snoopy, trying to determine which device in Snoopy corresponds to the device...Someone above said something about 8/1403?

On Windows, the Photo Viewer uses JPG.

One thing I am going to try (when I get Snoopy figured out):  create images of 128x128 in the following:  pure red, pure blue, pure green, half red half blue (top bottom), and half red half blue (left right), then move them to the device and see what the data looks like.

----------

## aiah

```
[quote="WingGnDm"]this is the 512bytes sent to sector 49

http://filebin.ca/gejkhw/getimage

http://filebin.ca/tozxam/1image

this is one of the images in the device, if someone can figure out its format and make it usable it would help out a lot.

As far as i can tell, it should be 16bit rgb, 128x128.

[/quote]

The first 16bytes is a soort of header

F5 00 80 00 80 01 00 02 04 01 30 00 00 00 00 00

F5              posably some magic number to verify start of image

 00 80       128 possably x resolution

 00 80       128 possably y resolution

 01 00 02 01

30 00         length of image data

It seems the image data consists of blocks (subframe) of data each block starts with 2f (3f of 37)

Each block (subframe) is 8x8 pixels and arranges like

[01][17][32]....[96][112]

[02][18].

[03]

.....

[16][32]..............[][128]

2f block is 48bytes

3f block is 64 bytes

37 block is 56 bytes

Verify:

* to check this, randomly change some data achter the 2F and upload the memory image to the device, is will show a change in an area 8x8pix (subframe) 

* analize the imagedatafile and you wil see the 2f/3f/37 repeating at the given offsets (according to blocksize)

Block data:

(a) 2f d5 4c 31 d2 c2 7e d4   

(b) ed f7 fd e2 cc f4 fd f9        

(c) 78 86 76 76 79 77 77 76  

     88 67 87 77 86 57 87 87  

     a8 77 88 77 76 68 88 77 

     87 77 77 77 86 77 79 77  

32

This is where it realy gets weird, the data doesn't seem to be related to rgb values in any way.

I think its using an color lookup table.

* if you check the windows software viewer, it has a file called decodertable (the data contents of this file is also found in the device itself somewhere near address 0x8000 of the memory

Changing one byte in part (a) changes the whoile block (i assume it's some offset into the color/conversion table)

Changing one byte in part (b) changes the whole line of 8pix (i assume it's an offset into the color/conversions

Changing one byte in part (c) changes 2pixex on a line (4bits/pixel) this also fits whith the 32 bytes in part (c)    8x8 * (4bit/pix) = 256bit = 32 bytes

But so far  i'm still unable te produce anything representing an image :( 

Other options:

Maby there is some 65c02 expert who can disaaemble the firmware (with notes) tp see how the image data is transfered to the LCD. (My 65c02 knowledge is to close to nonexistend to even try)

Or can start debuging the windows software to see what it does in detail.  (long ago in the windows98 days,  still had access to softice debugger)

```

----------

## iibm

there is some answer here : http://picframe.spritesserver.nl/wiki/index.php/ImageEncoding

----------

## ericm

I had a go at writing a set image.  From looking at a usb snoop I think the image gets loaded 

via a sequence like:

send to block 0x31  -- 512 bytes

03 00 00 00 XX 00 00 ....

send to block 0x33 -- 0x8000 bytes  32728

the image data

send to block 0x31  -- 512 bytes

02 00 00 00 XX 00 00 ....

read from block 0x58 -- 512 bytes

I tried reading an image then writing it back with some changed bytes.

This ran okay but locked up the display and I have been unable to get it working again.

I guess this helps people in what not to do!

----------

## NGE

Hello every one,

I have bought a keyChain, but  like some1 told on the beginning of this thread this keychain have a "trap" my wife connected to the pc, and tryed to open on the Windows Usb devices and it asked to format the unit and she pressed "YES" !!!! but it have gived an error telling that cannot format the unit, but now when i insert pictures on the device using Picture Viwer, and then i try to see the pictures on the KeyChain nothing appens... Black Screen.. Any guess how to fix this problem ?

( Maybe she have deleted any page on the "formating process " ) ? I cant enter on the "memory stick" it ask me all the time to format it..

Thanks in advance.

----------

## Jsines

Sorry guys. I've read all the theads but I'm really not smart enough to understand enough to even ask a question about what you wrote.  The basic question is, how can a real layman that just knows how to point and click get this stupid thing to work. i.e. accept pictures from the computer and show them back. I need something easy.  Or is this item destined to be filed in the circular file on tthe floor?

----------

## herberto07

 *Jsines wrote:*   

> Sorry guys. I've read all the theads but I'm really not smart enough to understand enough to even ask a question about what you wrote.  The basic question is, how can a real layman that just knows how to point and click get this stupid thing to work. i.e. accept pictures from the computer and show them back. I need something easy.  Or is this item destined to be filed in the circular file on tthe floor?

 

   Same here, any easy methods to get pix on this thing ???  Thanks all!

----------

