A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 182 lines 4.6 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Telechips firmware checksum support for scramble 11 * 12 * Copyright (C) 2007 Dave Chapman 13 * 14 * Thanks to Hein-Pieter van Braam for his work in identifying the 15 * CRC algorithm used. 16 * 17 * This program is free software; you can redistribute it and/or 18 * modify it under the terms of the GNU General Public License 19 * as published by the Free Software Foundation; either version 2 20 * of the License, or (at your option) any later version. 21 * 22 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 23 * KIND, either express or implied. 24 * 25 ****************************************************************************/ 26 27#include <stdio.h> 28#include <unistd.h> 29#include <sys/types.h> 30#include <sys/stat.h> 31#include <fcntl.h> 32#include <stdint.h> 33#include <stdlib.h> 34#include <string.h> 35 36static uint32_t crctable[256]; 37 38/* Simple implementation of a function to reverse the bottom n bits in x */ 39static uint32_t bitreverse(uint32_t x,int n) 40{ 41 int i; 42 uint32_t mask = 1<<(n-1); 43 uint32_t res = 0; 44 45 for (i=0; i<n; i++) 46 { 47 if (x & 1) 48 res |= mask; 49 50 x >>= 1; 51 mask >>= 1; 52 } 53 return res; 54} 55 56/* Generate a lookup table for a reverse CRC32 */ 57static void gentable(uint32_t poly) 58{ 59 int i; 60 uint32_t r; 61 uint32_t idx; 62 63 for (idx = 0; idx < 256; idx++) 64 { 65 r = bitreverse(idx,8) << 24; 66 for (i=0; i<8; i++) 67 { 68 if (r & (1 << 31)) 69 r = (r << 1) ^ poly; 70 else 71 r<<=1; 72 } 73 crctable[idx] = bitreverse(r,32); 74 } 75} 76 77/* Perform a reverse CRC32 */ 78static uint32_t calc_crc(unsigned char *message, int size) 79{ 80 uint32_t crc = 0; 81 int i; 82 83 for (i=0; i < size; i++){ 84 if ((i < 0x10) || (i >= 0x18)) { 85 crc = crctable[((crc ^ (message[i])) & 0xff)] ^ (crc >> 8); 86 } 87 } 88 89 return crc; 90} 91 92/* Endian-safe functions to read/write a 32-bit little-endian integer */ 93 94static uint32_t get_uint32le(unsigned char* p) 95{ 96 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); 97} 98 99static void put_uint32le(unsigned char* p, uint32_t x) 100{ 101 p[0] = x & 0xff; 102 p[1] = (x >> 8) & 0xff; 103 p[2] = (x >> 16) & 0xff; 104 p[3] = (x >> 24) & 0xff; 105} 106 107/* A simple checksum - seems to be used by the TCC76x firmwares */ 108void telechips_encode_sum(unsigned char* buf, int length) 109{ 110 uint32_t sum; 111 int i; 112 113 /* Set checksum field to 0 */ 114 put_uint32le(buf + 0x10, 0); 115 116 /* Perform a simple sum, treating the file as a series of 32-bit 117 little-endian integers */ 118 sum = 0; 119 for (i=0; i < length; i+=4) { 120 sum += get_uint32le(buf + i); 121 } 122 /* Negate the sum - this means that the sum of the whole file 123 (including this value) will be equal to zero */ 124 sum = -sum; 125 126 /* Set the checksum field */ 127 put_uint32le(buf + 0x10, sum); 128} 129 130 131/* Two reverse CRC32 checksums - seems to be used by the TCC77x firmwares */ 132void telechips_encode_crc(unsigned char* buf, int length) 133{ 134 uint32_t crc1,crc2; 135 136 /* Generate the CRC table */ 137 gentable(0x8001801BL); 138 139 /* Clear the existing CRC values */ 140 put_uint32le(buf+0x10, 0); 141 put_uint32le(buf+0x18, 0); 142 143 /* Write the length */ 144 put_uint32le(buf+0x1c, length); 145 146 /* Calculate the first CRC - over the entire file */ 147 crc1 = calc_crc(buf, length); 148 149 /* What happens next depends on the filesize */ 150 if (length >= 128*1024) 151 { 152 put_uint32le(buf+0x18, crc1); 153 154 crc2 = calc_crc(buf, 128*1024); 155 put_uint32le(buf+0x10, crc2); 156 } else { 157 put_uint32le(buf+0x10, crc1); 158 } 159} 160 161int telechips_test_crc(unsigned char* buf, int length) 162{ 163 uint32_t crc1, crc2, test_crc1, test_crc2; 164 unsigned char *test_buf; 165 166 crc1 = get_uint32le(buf + 0x10); 167 crc2 = get_uint32le(buf + 0x18); 168 169 test_buf = malloc(length); 170 if (!test_buf) 171 return 1; 172 173 memcpy(test_buf, buf, length); 174 telechips_encode_crc(test_buf, length); 175 176 test_crc1 = get_uint32le(test_buf + 0x10); 177 test_crc2 = get_uint32le(test_buf + 0x18); 178 179 free(test_buf); 180 181 return (crc1 == test_crc1 && crc2 == test_crc2) ? 0 : 2; 182}