From b4ecd612f7184cbf23d83ef78b0ccb5ed2c318e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Sat, 10 Jul 2021 08:56:32 +0200 Subject: [PATCH] Sansa Connect: Use deviceid in USB Serial Number Atmel AT88SC6416C CryptoMemory is almost I2C compatible. The device is connected to bitbanged I2C bus shared with compliant I2C devices. Change-Id: Iec54702db1bdfb93c01291eef18ec60391c63b16 --- firmware/SOURCES | 1 + firmware/drivers/generic_i2c.c | 34 ++++++++ firmware/export/generic_i2c.h | 10 +++ firmware/target/arm/tms320dm320/i2c-dm320.c | 8 ++ firmware/target/arm/tms320dm320/i2c-dm320.h | 3 + .../sansa-connect/cryptomem-sansaconnect.c | 80 +++++++++++++++++++ .../sansa-connect/cryptomem-sansaconnect.h | 27 +++++++ firmware/usbstack/usb_core.c | 20 +++++ 8 files changed, 183 insertions(+) create mode 100644 firmware/target/arm/tms320dm320/sansa-connect/cryptomem-sansaconnect.c create mode 100644 firmware/target/arm/tms320dm320/sansa-connect/cryptomem-sansaconnect.h diff --git a/firmware/SOURCES b/firmware/SOURCES index 109a40b161..b1024d97da 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -1274,6 +1274,7 @@ target/arm/tms320dm320/sansa-connect/tnetv105_cppi.c target/arm/tms320dm320/sansa-connect/tnetv105_usb_drv.c target/arm/tms320dm320/sansa-connect/usb-sansaconnect.c target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c +target/arm/tms320dm320/sansa-connect/cryptomem-sansaconnect.c target/arm/tms320dm320/sansa-connect/backlight-sansaconnect.c target/arm/tms320dm320/sansa-connect/pcm-sansaconnect.c target/arm/tms320dm320/sansa-connect/wifi-sansaconnect.c diff --git a/firmware/drivers/generic_i2c.c b/firmware/drivers/generic_i2c.c index effb5372b4..9fd90b5b2c 100644 --- a/firmware/drivers/generic_i2c.c +++ b/firmware/drivers/generic_i2c.c @@ -198,6 +198,40 @@ end: return ret; } +int i2c_write_read_data(int bus_index, int bus_address, + const unsigned char* buf_write, int count_write, + unsigned char* buf_read, int count_read) +{ + int i; + int ret = 0; + const struct i2c_interface *iface = i2c_if[bus_index]; + + i2c_start(iface); + if (!i2c_outb(iface, bus_address)) + { + ret = -2; + goto end; + } + + for(i = 0;i < count_write;i++) + { + if (!i2c_outb(iface, buf_write[i])) + { + ret = -3; + goto end; + } + } + + for(i = 0;i < count_read-1;i++) + buf_read[i] = i2c_inb(iface, true); + + buf_read[i] = i2c_inb(iface, false); + +end: + i2c_stop(iface); + return ret; +} + /* returns bus index which can be used as a handle, or <0 on error */ int i2c_add_node(const struct i2c_interface *iface) { diff --git a/firmware/export/generic_i2c.h b/firmware/export/generic_i2c.h index f71736acf0..9fdba26836 100644 --- a/firmware/export/generic_i2c.h +++ b/firmware/export/generic_i2c.h @@ -49,5 +49,15 @@ int i2c_write_data(int bus_index, int bus_address, int address, int i2c_read_data(int bus_index, int bus_address, int address, unsigned char* buf, int count); +/* Special function for devices that can appear on I2C bus but do not + * comply to I2C specification. Such devices include AT88SC6416C crypto + * memory. To read data from AT88SC6416C, a write I2C transaction starts, + * 3 bytes are written and then, in the middle of transaction, the device + * starts sending data. + */ +int i2c_write_read_data(int bus_index, int bus_address, + const unsigned char* buf_write, int count_write, + unsigned char* buf_read, int count_read); + #endif /* _GEN_I2C_ */ diff --git a/firmware/target/arm/tms320dm320/i2c-dm320.c b/firmware/target/arm/tms320dm320/i2c-dm320.c index 629dae394c..364d3b5c17 100644 --- a/firmware/target/arm/tms320dm320/i2c-dm320.c +++ b/firmware/target/arm/tms320dm320/i2c-dm320.c @@ -294,4 +294,12 @@ int i2c_read_bytes(unsigned short address, unsigned short reg, return i2c_read_data(dm320_i2c_bus, address, reg, buf, count); } +int i2c_write_read_bytes(unsigned short address, + const unsigned char* buf_write, int count_write, + unsigned char* buf_read, int count_read) +{ + return i2c_write_read_data(dm320_i2c_bus, address, buf_write, count_write, + buf_read, count_read); +} + #endif diff --git a/firmware/target/arm/tms320dm320/i2c-dm320.h b/firmware/target/arm/tms320dm320/i2c-dm320.h index 7dfc19f046..43271692eb 100644 --- a/firmware/target/arm/tms320dm320/i2c-dm320.h +++ b/firmware/target/arm/tms320dm320/i2c-dm320.h @@ -31,6 +31,9 @@ int i2c_read(unsigned short address, unsigned char* buf, int count); #ifdef HAVE_SOFTWARE_I2C int i2c_read_bytes(unsigned short address, unsigned short reg, unsigned char* buf, int count); +int i2c_write_read_bytes(unsigned short address, + const unsigned char* buf_write, int count_write, + unsigned char* buf_read, int count_read); #endif #endif diff --git a/firmware/target/arm/tms320dm320/sansa-connect/cryptomem-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/cryptomem-sansaconnect.c new file mode 100644 index 0000000000..ac01525500 --- /dev/null +++ b/firmware/target/arm/tms320dm320/sansa-connect/cryptomem-sansaconnect.c @@ -0,0 +1,80 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id: $ +* +* Copyright (C) 2021 by Tomasz Moń +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +* KIND, either express or implied. +* +****************************************************************************/ + +#include +#include "cryptomem-sansaconnect.h" +#include "i2c-dm320.h" + +/* Command values */ +#define WRITE_USER_ZONE 0xB0 +#define READ_USER_ZONE 0xB2 +#define SYSTEM_WRITE 0xB4 +#define SYSTEM_READ 0xB6 +#define VERIFY_CRYPTO 0xB8 +#define VERIFY_PASSWORD 0xBA + +/* SYSTEM_WRITE ADDR 1 values */ +#define WRITE_CONFIG 0x00 +#define WRITE_FUSES 0x01 +#define SEND_CHECKSUM 0x02 +#define SET_USER_ZONE 0x03 + +int cryptomem_read_deviceid(char deviceid[32]) +{ + int ret; + unsigned int i; + unsigned char cmd_data[3]; + + /* It is assumed that other I2C communication has already taken place + * (e.g. power_init()) before this function is called and thus we don't + * have to send atleast 5 dummy clock cycles here. + */ + + cmd_data[0] = SET_USER_ZONE; + cmd_data[1] = 0; + cmd_data[2] = 0; + ret = i2c_write(SYSTEM_WRITE, cmd_data, sizeof(cmd_data)); + if (ret < 0) + { + return ret; + } + + cmd_data[0] = 0; + cmd_data[1] = 0; + cmd_data[2] = 32; + ret = i2c_write_read_bytes(READ_USER_ZONE, cmd_data, sizeof(cmd_data), + deviceid, 32); + if (ret < 0) + { + return ret; + } + + /* Verify that deviceid contains only printable ASCII characters */ + for (i = 0; i < 32; i++) + { + if (!isprint(deviceid[i])) + { + return -1; + } + } + + return 0; +} diff --git a/firmware/target/arm/tms320dm320/sansa-connect/cryptomem-sansaconnect.h b/firmware/target/arm/tms320dm320/sansa-connect/cryptomem-sansaconnect.h new file mode 100644 index 0000000000..b6b52d3b2c --- /dev/null +++ b/firmware/target/arm/tms320dm320/sansa-connect/cryptomem-sansaconnect.h @@ -0,0 +1,27 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id: $ +* +* Copyright (C) 2021 by Tomasz Moń +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +* KIND, either express or implied. +* +****************************************************************************/ + +#ifndef _CRYPTOMEM_SANSACONNECT_H_ +#define _CRYPTOMEM_SANSACONNECT_H_ + +int cryptomem_read_deviceid(char deviceid[32]); + +#endif /* _CRYPTOMEM_SANSACONNECT_H_ */ diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c index 3d187c8cab..b291dc7655 100644 --- a/firmware/usbstack/usb_core.c +++ b/firmware/usbstack/usb_core.c @@ -62,6 +62,10 @@ #include "ocotp-imx233.h" #endif +#ifdef SANSA_CONNECT +#include "cryptomem-sansaconnect.h" +#endif + #ifndef USB_MAX_CURRENT #define USB_MAX_CURRENT 500 #endif @@ -327,6 +331,22 @@ static void set_serial_descriptor(void) } usb_string_iSerial.bLength = 2 + 2 * (1 + IMX233_NUM_OCOTP_OPS * 8); } +#elif defined(SANSA_CONNECT) +static void set_serial_descriptor(void) +{ + char deviceid[32]; + short* p = &usb_string_iSerial.wString[1]; + int i; + + if(!cryptomem_read_deviceid(deviceid)) { + for(i = 0; i < 32; i++) { + *p++ = deviceid[i]; + } + usb_string_iSerial.bLength = 2 + 2 * (1 + 32); + } else { + device_descriptor.iSerialNumber = 0; + } +} #elif (CONFIG_STORAGE & STORAGE_ATA) /* If we don't know the device serial number, use the one * from the disk */