SanDisk Sansa Connect
History/Background
The Sansa Connect is designed by
Zing System Inc. (part of Dell), who showed off a WIFI device for listening to streaming radio stations, without any onboard storage. A prototype device was announced, but never put into production. Screenshots of the time show a similar UI design to the current Sansa Connect.
The Sansa Connect has 4Gb of onboard flash storage, as well as a Micro-SD slot, capable of using SDHC cards in the newer firmware versions.
Rockbox Status
There is a Sansa Connect Rockbox port in progress. Bootloader can boot both OF (by holding PREV button) and Rockbox. Bootloader can be flashed in Recovery Mode using
zsitool exploit mode. Rockbox bootloader looks for the files on Micro-SD card.
Device |
Status |
Comments |
LCD driver |
100% |
|
Backlight |
100% |
|
Storage (SD) driver |
90% |
|
Button driver |
90% |
Keymap should be updated |
USB handler |
80% |
TNETV105 driver ported from Linux |
RTC driver |
10% |
RTC doesn't seem to be accessible by I2C. Rockbox uses HID_MONOTIME together with offset file stored in rockbox directory |
Power handling |
50% |
|
Audio DAC driver |
80% |
|
WiFi driver |
5% |
Firmware loading works |
(Software) I2C driver |
90% |
|
Additional work to be done:
- SD driver can use interrupts
- WiFi driver needs to be written (network subsystem needs to be added to Rockbox)
- Frequency scaling for clocks other than CPU
- Perform actual DSP operations on DSP, currently it is just "pcm forwarder"
Hardware
AnythingButiPod performed a basic disassembly.
Further to this: the EMI shield is a frame and clip-on top shield - only the frame is soldered to the main PCB. The frame visually obscures some of the chips.
- DSP/CPU: TexasInstrumentsTMS320. This is a multicore device consisting of a ARM926EJ-S CPU core and TMS320vc5409 DSP.
- Secondary CPU: ATMEL MEGA165PV. The Atmel AVR line has great support of open source developement tools (GCC et all). It's referred internally as "HID", and it's used as an interface to external devices - handles display sleep & wakeup, for example. Interfaced via SPI.
- Power Management: TI TPS 65021. Interfaced via I2C.
- LCD: 2.2 inch - CT022TND4 V.6 M1-B
- SDRAM: Samsung K4M51323LC-DN75
- USB 2.0: TNETV105. Not to be confused with TI's TNETV105 (DSP/CPU bundle), this handles USB for the device. The TMS320 has an internal USB controller but it is disabled on boot. Interfaced via VLYNQ.
- Codec: Ti AC3106I. DAC and stereo power amplifier, with programmable filters. Most likely interfaced via I2C.
- EEPROM: Atmel AT88SC6416C - 64kbit fused, cryptographically secure. Holds individual device information such as USB deviceid, MAC address and device certificate. Interfaced via I2C.
- Flash: Sandisk SDINB1-4096. 4GB iNAND flash module. Holds filesystem.
Visually obscured chips:
- Flash: Samsung K8D3216UBC (located just under DSP/CPU) - NOR Flash 32MBIT. Holds bootloader, linux kernel, persistent variables, platform.
- WIFI: Murata (chip has the MAC address engraved on it - vendor digits are 00:13:E0) - possible model numbers start KK6T6... or LBWA-.... Interfaced via SPI. Actually, after desoldering the chip, it turned out to be tiny PCB - the chipset is labelled MARVELL W8686B12 717AEUP: http://www.arm9board.net/download/FL6410/datasheet/mavell_88w8686.pdf
- RTC: ST M41T62 - interfacing method unknown
- TPS61042 Led driver (package marking BHS)
Battery PCB:
- Battery Gas Gauge: TI BQ27000. Interfaced via AVR.
Clock speeds
These are obtained from the initialization code on the linux kernel patch for the Connect:
- TMS320 ARM core: 120 MHz
- SDRAM: 72 MHz
- TMS320 DSP core: 72 MHz
- DMA coprocessor: 144 MHz
TMS320 general purpose I/O pins mapping
This is the detail for the known GPIO pins in the Connect:
Pin |
Device |
Name |
Comments |
Direction |
GIO0 |
TMS320 |
STANDBY |
Buttons state changed IRQ |
In |
GIO2 |
Headphones |
PRESENT |
Headphones inserted |
In |
GIO5 |
iNAND |
SELECT |
Selects iNAND when low |
Out |
GIO6 |
SD Card |
SELECT |
Selects SD slot when low |
Out |
GIO7 |
USB |
RESET |
TNETV105PAP reset (active low) |
Out |
GIO8 |
I2C |
INTR |
Data available on dock I2C to UART connector (rising edge) |
In |
GIO9 |
USB |
DETECT |
low when USB cable connected |
In |
GIO11 |
I2C |
DTCT |
Available at dock connector, low if I2C to UART is not connected |
In |
GIO12 |
I2C |
SCL |
Available at dock connector (pin 22) |
In/Out |
GIO13 |
I2C |
SDA |
Available at dock connector (pin 21) |
In/Out |
GIO14 |
SD Card |
CARD_DETECT |
Low when card inserted |
In |
GIO16 |
AIC3X |
MCLK |
Audio interface master clock |
Out |
GIO29 |
SIF1 |
ENABLE |
AVR's SS (active low) |
Out |
GIO30 |
SIF1 |
Clock |
|
Out |
GIO31 |
SIF1 |
Data In |
|
In |
GIO32 |
SIF1 |
Data Out |
|
Out |
GIO33 |
USB |
CLK |
USB clock (source from M48XI) |
Out |
GIO34 |
Backlight |
PWM |
Backlight PWM (active high) |
Out |
GIO35 |
I2C |
SDA |
I2C data line |
In/Out |
GIO36 |
I2C |
SCL |
I2C clock |
In/Out |
GIO37 |
SD Card |
CARD_POWER |
Powers SD slot when low |
Out |
GIO38 |
iNAND |
iNAND_POWER |
Powers iNAND when low |
Out |
GIO39 |
LCD |
VENC |
FIELD_VENC |
Out |
Contents of the /proc/gio:
GIO# |
User ID |
Function |
Dir |
Invert |
Level |
IRQ |
IRQ Edge |
Debounce |
0 |
|
GIO |
in |
normal |
asserted |
21 |
falling |
normal |
1 |
spi0-wifi-irq |
GIO |
in |
normal |
asserted |
22 |
falling |
normal |
2 |
|
GIO |
in |
inverted |
deasserted |
23 |
any |
normal |
3 |
wifi-reset |
GIO |
out |
normal |
asserted |
GIO |
-- |
normal |
4 |
spi0-wifi-cs |
GIO |
out |
normal |
asserted |
GIO |
-- |
normal |
5 |
|
GIO |
out |
normal |
asserted |
GIO |
-- |
normal |
6 |
|
GIO |
out |
normal |
asserted |
GIO |
-- |
normal |
7 |
TNETV USB nreset |
GIO |
out |
normal |
asserted |
GIO |
-- |
normal |
8 |
|
GIO |
in |
normal |
deasserted |
GIO |
-- |
normal |
9 |
|
GIO |
in |
normal |
deasserted |
30 |
any |
normal |
10 |
|
GIO |
in |
normal |
deasserted |
GIO |
-- |
normal |
11 |
|
GIO |
in |
normal |
asserted |
32 |
any |
normal |
12 |
GIO I2C SCL |
GIO |
in |
normal |
asserted |
GIO |
-- |
normal |
13 |
GIO I2C SDA |
GIO |
in |
normal |
asserted |
GIO |
-- |
normal |
14 |
|
GIO |
in |
normal |
asserted |
35 |
any |
normal |
15 |
|
GIO |
in |
normal |
asserted |
GIO |
-- |
normal |
16 |
|
CLKOUT0 |
|
|
|
|
|
|
17 |
|
VLYNQ RXD0 |
|
|
|
|
|
|
18 |
|
VLYNQ RXD1 |
|
|
|
|
|
|
19 |
|
VLYNQ RXD2 |
|
|
|
|
|
|
20 |
|
VLYNQ RXD3 |
|
|
|
|
|
|
21 |
|
VLYNQ_TXD0 |
|
|
|
|
|
|
22 |
|
VLYNQ TXD1 |
|
|
|
|
|
|
23 |
|
VLYNQ TXD2 |
|
|
|
|
|
|
24 |
|
VLYNQ TXD3 |
|
|
|
|
|
|
25 |
|
VLYNQ SCRU |
|
|
|
|
|
|
26 |
|
VLYNQ CLK |
|
|
|
|
|
|
27 |
|
GIO |
in |
normal |
asserted |
GIO |
-- |
normal |
28 |
|
GIO |
out |
normal |
deasserted |
GIO |
-- |
normal |
29 |
SPI-nSS |
GIO |
out |
normal |
asserted |
GIO |
-- |
normal |
30 |
|
SPI SCLK1 |
|
|
|
|
|
|
31 |
|
SPI SDI1 |
|
|
|
|
|
|
32 |
|
SPI SDO1 |
|
|
|
|
|
|
33 |
|
CLKOUT1B |
|
|
|
|
|
|
34 |
|
PWM1 |
|
|
|
|
|
|
35 |
GIO I2C SDA |
GIO |
in |
normal |
asserted |
GIO |
-- |
normal |
36 |
GIO I2C SCL |
GIO |
in |
normal |
asserted |
GIO |
-- |
normal |
37 |
|
GIO |
out |
normal |
asserted |
GIO |
-- |
normal |
38 |
|
GIO |
out |
normal |
deasserted |
GIO |
-- |
normal |
39 |
|
FIELD VENC |
|
|
|
|
|
|
40 |
|
GIO |
out |
normal |
deasserted |
GIO |
-- |
normal |
Addresses available on I2c bus:
- 0x18 - Codec AIC3X
- 0x48 - Power Management TPS65021
- 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f - AT88SC6416C responding at address 0xB
- 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f - AT88SC6416C responding at address 0xF
TMS320 memory maps
Physical memory:
Region name |
Description |
Start |
End |
Size |
Comments |
DM320_RESET_VECTOR_PADDR |
CPU reset vector |
0x00000000 |
0x00000003 |
4 bytes |
Should point to bootloader |
DM320_IRAM_PADDR |
CPU internal RAM |
0x00000004 |
0x00003FFF |
Approx. 16Kb |
|
DM320_PERIPHERALS_PADDR |
ARM peripherials registers |
0x00030000 |
0x0003FFFF |
4Kb |
|
DM320_DSP_ONCHIP_RAM_PADDR |
DSP internal RAM |
0x00040000 |
0x0005FFFF |
128Kb |
|
DM320_AHB_PADDR |
TMS320 internal AHB bus |
0x00060000 |
0x00063FFF |
4Kb |
|
DM320_COPRO_SUB_PADDR |
DMA coprocessor interface |
0x00080000 |
0x0009FFFF |
128Kb |
|
DM320_EXT_MEM_PADDR |
External memory |
0x00100000 |
0x010FFFFF |
16Mb |
Maps to Flash exclusively (cached) Bootloader and kernel are stored here |
DM320_CFI_PADDR |
CFI Flash interface |
0x40000000 |
0x40FFFFFF |
16Mb |
|
DM320_SSFDC_PADDR |
SmartMedia interface |
0x48000000 |
0x48FFFFFF |
16Mb |
|
DM320_CE1_PADDR |
Control enable 1 (???) |
0x50000000 |
0x50FFFFFF |
16Mb |
Related to Comm. port 1 (external interface) |
DM320_CE2_PADDR |
Control enable 1 (???) |
0x60000000 |
0x60FFFFFF |
16Mb |
Related to Comm. port 2 (external interface) |
DM320_VLYNQ_PADDR |
VLYNQ interface |
0x70000000 |
0x73FFFFFF |
64MB |
More details in http://en.wikipedia.org/wiki/VLYNQ |
DM320_USBOTG_PADDR |
USB On-The-Go inteface |
0x80000000 |
0x800003FF |
1Kb |
More details in http://en.wikipedia.org/wiki/USB_On-The-Go |
Virtual memory:
(..more to come..)
Flash:
Flash starts at 0x00100000. Start and End values in table are absolute addresses.
Region name |
Description |
zsi_fw address |
Start |
End |
Size |
Comments |
BOOT |
rrload bootloader |
N/A |
0x00100000 |
0x0010FFFF |
64 Kb |
Hardware write-protected |
ENVIRO |
Persistent variables |
N/A |
0x00110000 |
0x0011FFFF |
64 Kb |
Bootloader variables (recoverzap, usbautoboot, etc.) and graphics |
KERNEL |
vmlinux kernel image |
0x01008000 |
0x00120000 |
0x0031FFFF |
2 Mb |
Stock kernel image is about 1,6 Mb big |
INITRD |
initrd compressed ROM image |
0x04400020 |
0x00320000 |
0x004FFFFF |
1.875 Mb |
At least 1,6 Mb big |
Power managment
After loading the Linux kernel, the TPS 65021 is programmed via
I2C (/usr/share/lua/5.1/pwrfix.lua) - devices'
I2C address is 0x48.
- Device is set to PWM mode (register 0x04 = 10110010b).
- Core voltage set to 1.5V (register 0x06 = 00011100b).
- Codec and USB power line (LD02) to 1.8V, LCD display module (LD01) to 2.85V (register 0x08 = 00110110b).
HID (ATMEL MEGA165PV microcontroller)
The HID handles external devices - it is interfaced to the CPU via its built SPI interfase, clocked at 200 KHz.
This device is initialized on boot - the firmware loaded on it is located on /lib/clicky165.bin. The Fuse high byte register is set to 0xd1 (OCD and JTAG enabled, watchdog always on, uses reset vector), while the fuse low byte is set to 0xC2 (divide clock by 8, enable clock output, use clock source 1).
Once programmed, it accepts commands (via SPI) which are defined in /usr/include/hidif.lu. These are used to control & query external devices:
Name |
Command |
Description |
CMD_SYNC |
0xAA |
Sync with device to send/receive Marks the beginning of a command |
CMD_CLOSE |
0xCC |
Close sync Marks the end of a command |
CMD_VER |
0xBC |
|
CMD_FILL |
0xFF |
Filler - seems to be used to signal HID that it can send data back |
CMD_CODEC_RESET |
0xD7 |
Reset codec |
CMD_ADC_START |
0xD8 |
Initalize ADC |
CMD_ADC_RESULT |
0xD9, 0xFFFF |
|
CMD_SYS_CTRL |
0xDA |
Sends command SYS_CTRL_xxx |
SYS_CTRL_POWEROFF |
0x00 |
Powers off the Connect |
SYS_CTRL_RESET |
0x01 |
Reset the Connect |
SYS_CTRL_SLEEP |
0x02 |
Sleeps the Connect |
SYS_CTRL_DIS_WD |
0x03 |
|
SYS_CTRL_KICK_WD |
0x4 |
|
SYS_CTRL_EN_HDQ_THERM |
0x5 |
|
SYS_CTRL_EN_TS_THERM |
0x6 |
|
SYS_CTRL_FRESET |
0x80 |
|
CMD_SET_INTCHRG |
0xD1 |
|
CMD_GET_INTCHRG |
0xD2, 0xFF |
|
CMD_SET_EXTCHRG |
0xC6 |
|
CMD_GET_EXTCHRG |
0xC7, 0xFF |
|
CMD_GPIOD_SET_BANK |
0xDB |
|
CMD_GPIOD_SET_PORT |
0xDC |
|
CMD_GPIOD_GET_PIN |
0xDF, 0xFF |
|
CMD_GPIOD_SET_DDR |
0xE0 |
|
CMD_HDQ_READ |
0xC0 |
Read HDQ (battery) data |
CMD_HDQ_WRITE |
0xC1 |
Write HDQ (battery) data |
CMD_HDQ_STATUS |
0xC2, 0xFFFF |
OK = 0, not ready = 1, timeout = 2 |
CMD_STATE |
0xBB, 0xFFFFFFFFFFFFFFFF |
|
CMD_PGMWAKE |
0xBF |
|
CMD_LCM_POWER |
0xC9 |
Sends command LCM_xxx to LCD driver |
LCM_POWER_OFF |
0x00 |
LCD power off |
LCM_POWER_ON |
0x01 |
LCD power on |
LCM_POWER_SLEEP |
0x02 |
LCD sleep |
LCM_POWER_WAKE |
0x03 |
LCD wakeup |
LCM_REPOWER_ON |
0x04 |
|
CMD_WHEEL_EN |
0xD0 |
|
CMD_MONOTIME |
0xBD, 0xFFFFFFFF |
|
CMD_MONORSTCNT |
0xE4, 0xFFFF |
|
CMD_SET_USBCHRG |
0xE2 |
|
CMD_GET_USBCHRG |
0xE3, 0xFF |
|
CMD_GET_DOCK_STATE |
0xE5, 0xFF |
|
CMD_READ_DOCK_STATE |
0xE6 |
|
Sync sequence is CMD_SYNC -> CMD_VER -> CMD_FILL -> CMD_CLOSE, while command sequence is CMD_SYNC ->
command -> CMD_CLOSE -> CMD_FILL Communication to this device is handled by /usr/bin/hidtool, which is a binary file.
Device also seems to work as a watchdog.
Atmel AT88SC EEPROM and USB.
This device is read by the /bin/setupenv script - it retrieves both deviceid and MAC address and loads them into the $deviceid and $mac environment variables, respectively. Other environment variables (/etc/setupenv) are:
- Manufacturer:"SanDisk"
- Product name: "Sansa Connect"
- Vendor ID: 0x0781
- Product ID: 0x7480 (MTP more), 0x0F02 (Ethernet-over-USB mode), or 0x7482 (recovery mode)
- Product revision: 0x0101
Recovery Mode
Recovery Mode can be reached by completely powering down the device (by holding off for 10 seconds). Holding the volume-up and right keys while powering the device back on switch it to recovery mode. In recovery mode the device uses different USB IDs (0781:7481 and 0781:7482, vs 0781:7480 in normal operation) - if installed under Windows the Sansa Connect Device Recovery software will automatically launch when a Connect in recovery mode is connected.
USB ID 0781:7481 is used for writing .SRR files to Flash, while 0781:7482 acceses the "Zaprecover" service (complete with a kernel module!!!), which handles dumping files to the filesystem.
Once linux is loaded, recovery mode is signaled by a persistent variable ("recoverzap") stored in flash. This flag is only removed after a sucessful recovery operation, so there's no way to exit recovery mode once entered without running the recovery operation (and therefore wiping the unit) with the stock initrd file. It is possible to boot the already flashed firmware even if the "recoverzap" variable is set by entering console and waiting for timeout. To enter console press UP or DOWN (on the wheel) when powering on the device.
Recovery sequence
- Turn off the device completely (hold power key for 10 seconds)
- Turn the device on while holding volume-up and the right button (above the wheel)
- The device will boot showing a "recovery needed" indicator. On this mode the device exposes the USB ID 0781:7481, which zsi_fw.exe communicates to. This is NOT handled by linux - so it's either the linux bootloader or maybe even a previous instance of software. This mode is persistent after reboot.
- Once the USB cable is connected the indicator is changed to "recovery in progress".
- After a suceessful firmware load with zsi_fw.exe, the device will attempt to boot the vmlinux image (after a small delay). If the device reboots to recovery mode something went wrong with the firmware load. otherwise Linux will boot correctly and go to recovery mode, exposing the USB ID 0781:748 (Zaprecover service) and displaying a "starting recovery" message (with a yellow clock on top). How the device determines it has to go into recovery mode after boot is unclear - most likely it's because the flash filesystem is wiped after a firwmare write.
- Once a platform load is started with zaprecover.exe the message changes to_"receiving software"_.
- Once finished, the message now changes to "verifying software" (signature check), then "installing software" (a message reading _"can't find image_" might flash briefly). The device proceeds now to extract the platform into the filesystem.
- After a small delay, if everything went ok the device should now reboot to the familiar Sansa loading screen (with the five color balls).
ZAP recovery service
Once linux is loaded, on recovery mode the device loads a kernel module called "zaprecover" (/bin/usb_switch_zaprecover), listening on 0781:7482. The driver is interfaced with /usr/bin/zsi_zap, which tells the module how many files to expect and where to store them. On recovery mode, it waits for both the platform file and signature to be sent, in that order (/etc/rc.recover):
/usr/bin/zsi_zap -f /disk/zap/ZAP.tar.gz -f /disk/zap/ZAP.tar.gz.sig
The device won't leave recovery mode unless both files are downloaded correctly and the signature is checked. The host side of zaprecover service protocol is implemented in zsitool.
Software
Original Software information can be found on
SansaConnectOriginalFirmware.
Software/Hardware hacking
It is possible to replace the internal iNAND with microSD card - which allows to change the platform to for example start telnet.
Tips:
after connecting via wireless, stop
WiFiThread to prevent disconnection due to inactivity, this can be achieved by checking the thread pid cat /var/tmp/native_thread_map, and then sending SIGSTOP to it(kill -s SIGSTOP pid).
JTAG
There is JTAG on the PCB. Hirose Electric
FH19SC-16S-0.5SH(05) connector matches the footprint.
Connector pinout:
Volume up button
1 GND
2 RTCK (B1)
3 TDO (A13)
4 GND
5 TRST (F12)
6 TMS (A14)
7 TDI (B14)
8 TCK (C13)
9 GND
10 ? UNKNOWN
11 RXD0 (C2)
12 TXD0 (E5)
13 VDDIO (Vref for JTAG)
14 VDDIO (Vref for JTAG)
15 EMU0 (A2)
16 EMU1 (C3)
Volume down button
Vref is 3.3V. Bootloader configures UART0 to baud rate 115200, character format is 8N1, no flow control.
Free Software
The PDF that ships on the Sansa Connect CD includes a section called "Open Source Licences" and includes:
busybox
curl
Ezxml
Freetype
GPG
Linux
mDNSresponder
Mono
libpng
openssl
SSLeay
resample
Uclibc
wpa_supplicant
zlib
There are broken links in the PDF to the Sansa site to download modified source versions of the GPL licensed software. Instead these downloads are available from the Zing site, substituting zing.net for sandisk.com in the links:
busybox,
GPG,
Linux,
Mono,
resample and
Uclibc. Also attached is a
diff created against the vanilla 2.6.4 kernel release.
Copyright © by the contributing authors.