Hi all:

I created a firmware extractor for these chips. Hope it is useful.

Some notes:

  * Sometimes it fails in the first launch, but launching again with
exactly the same parameters works fine.
  * Try to unload the touch module before running it, to avoid
interferences between both codes.
  * Try first with a chunk size of 4 bytes, and change only to 2 or 1 if
it fails.

-- 
Nos leemos
                         RASTER    (Linux user #228804)
[email protected]              http://www.rastersoft.com

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
/*
 * Copyright 2015 Raster Software Vigo
 *
 *
 * extract 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.
 *
 * extract is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "extract.h"

#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <linux/i2c-dev.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <linux/input.h>
#include <linux/uinput.h>
#include <math.h>

#ifdef USE_FB
#include "linux/fb.h"
#endif

struct i2c_client {
	int adapter;
};

static __inline__ void fw2buf(u8 *buf, const u32 *fw) {
	u32 *u32_buf = (u32 *)buf;
	*u32_buf = *fw;
}


static int gsl_ts_write(struct i2c_client *client, u8 addr, u8 *pdata, int datalen) {

	int ret = 0;
	u8 tmp_buf[128];
	unsigned int bytelen;

	if (client==NULL) {
		return datalen+1;
	}

	if (datalen > 125) {
		printf("%s too big datalen = %d!\n", __func__, datalen);
		return -1;
	}
	
	tmp_buf[0] = addr;
	bytelen=1;
	
	if (datalen != 0 && pdata != NULL) {
		memcpy(tmp_buf+1, pdata, datalen);
		bytelen += datalen;
	}
	
	ret = write(client->adapter, tmp_buf, bytelen);

	return ret;
}

static int gsl_ts_read(struct i2c_client *client, u8 addr, u8 *pdata, unsigned int datalen) {
	int ret = 0;

	if (datalen > 126) {
		printf("%s too big datalen = %d!\n", __func__, datalen);
		return -1;
	}

	ret = write(client->adapter, &addr, 1);
	if (ret < 0) {
		printf("%s set data address fail!\n", __func__);
		return ret;
	}
	
	return read(client->adapter, pdata, datalen);
}

static void reset_chip(struct i2c_client *client) {

	u8 buf[1];
	
	buf[0]=0x88;
	gsl_ts_write(client, GSL_STATUS_REG, buf, 1);
	usleep(10000);

	buf[0]=0x04;
	gsl_ts_write(client, 0xe4, buf, 1);
	usleep(10000);

	buf[0]=0x00;
	gsl_ts_write(client, 0xbc, buf, 1);
	usleep(10000);
	buf[0]=0x00;
	gsl_ts_write(client, 0xbd, buf, 1);
	usleep(10000);
	buf[0]=0x00;
	gsl_ts_write(client, 0xbe, buf, 1);
	usleep(10000);
	buf[0]=0x00;
	gsl_ts_write(client, 0xbf, buf, 1);
	usleep(10000);

}

static void startup_chip(struct i2c_client *client) {
	u8 tmp = 0x00;
	gsl_ts_write(client, GSL_STATUS_REG, &tmp, 1);
	usleep(10000);	
}

int main(int argc, char **argv) {

	struct i2c_client cliente;
	int retval;

	if (argc<4) {
		printf("Version 1\n");
		printf("Format: extract DEVICE FW_FILE BLOCK_SIZE\n\n");
		printf("DEVICE: path to the I2C device where the GSLx680 chip is connected\n");
		printf("FW_FILE: path to the file where to store the current firmware\n");
		printf("BLOCK_SIZE: size in bytes to read in one chunk. It can be 1, 2 or 4. Try the values until there aren't read errors.\n");
		printf("\nWARNING: sometimes, the first execution fails, but launching the program again, with the same parameters, works.");
		return 0;
	}

	char *adapter=NULL;
	char *firmware=NULL;
	int block_size=-1;
	char *option;

	int loop=1;
	while(loop<argc) {
		option=argv[loop];
		loop++;
		if (adapter==NULL) {
			adapter=strdup(option);
			continue;
		}
		if (firmware==NULL) {
			firmware=strdup(option);
			continue;
		}
		if (block_size == -1) {
			block_size=atoi(option);
			continue;
		}
		printf("Too many parameters\n");
		return -1;
	}

	printf("Connecting to device %s, storing at %s\n",adapter,firmware);
	
	cliente.adapter=open(adapter,O_RDWR);
	if (cliente.adapter<0) {
		printf("Can't open device %s\n",adapter);
		return -1;
	}

	if (ioctl(cliente.adapter, I2C_SLAVE, GSLX680_I2C_ADDR) < 0) {
		printf("Error selecting device %d\n",GSLX680_I2C_ADDR);
		return -2;
	}

	//reset_chip(&cliente);

	FILE *firmware_file = fopen(firmware,"wb");
	if (firmware_file == NULL) {
		printf("Can't open the file %s for writting the firmware. Aborting\n",firmware);
		return -3;
	}

	int memory_page;
	int word_to_read;
	u8 address = 0;
	u8 page = 0;
	u8 data[4];
	u32 tmp;
	u32 *data_bin;

	for(memory_page = 0; memory_page < 256; memory_page++) {
		printf("Accesing page %02X of 255\n",memory_page);
		fflush(NULL);
		tmp = (u32) memory_page;
		fw2buf(data, &tmp);
		retval = gsl_ts_write(&cliente,GSL_PAGE_REG,data,4); // choose memory page
		if (retval != 5) {
			printf("Error while writing to the PAGE register. Aborting.\n",retval);
			exit(-1);
		}
		fprintf(firmware_file,"{0x%02x,0x%x},\n",GSL_PAGE_REG,memory_page);
		for (address = 0; address < 128; address += 4) {
			data[0]=0;
			data[1]=0;
			data[2]=0;
			data[3]=0;
			if (block_size == 1) {
				retval = gsl_ts_read(&cliente,address,data,1);
				if (retval < 0) {
					printf("\nError while reading data from memory. Aborting. (Please, try again).\n");
					exit(-1);
				}
				retval = gsl_ts_read(&cliente,address+1,data+1,1);
				if (retval < 0) {
					printf("\nError while reading data from memory. Aborting. (Please, try again).\n");
					exit(-1);
				}
				retval = gsl_ts_read(&cliente,address+2,data+2,1);
				if (retval < 0) {
					printf("\nError while reading data from memory. Aborting. (Please, try again).\n");
					exit(-1);
				}
				retval = gsl_ts_read(&cliente,address+3,data+3,1);
				if (retval < 0) {
					printf("\nError while reading data from memory. Aborting. (Please, try again).\n");
					exit(-1);
				}
			} else if (block_size == 2) {
				retval = gsl_ts_read(&cliente,address,data,2);
				if (retval < 0) {
					printf("\nError while reading data from memory. Aborting. (Please, try again).\n");
					exit(-1);
				}
				retval = gsl_ts_read(&cliente,address+2,data+2,2);
				if (retval < 0) {
					printf("\nError while reading data from memory. Aborting. (Please, try again).\n");
					exit(-1);
				}
			} else if (block_size == 4){
				retval = gsl_ts_read(&cliente,address,data,4);
				if (retval < 0) {
					printf("\nError while reading data from memory. Aborting. (Please, try again).\n");
					exit(-1);
				}
			} else {
				printf("Chunk size incorrent. Aborting.\n");
				exit(-1);
			}
			data_bin = (u32 *) data;
			fprintf(firmware_file,"{0x%02x,0x%08x},\n",address,*data_bin);
		}
	}
	fclose(firmware_file);
	printf("\n");
	return 0;
}

/*
 * Copyright 2015 Raster Software Vigo
 *
 *
 * extract 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.
 *
 * extract is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef _GSLX680_EXTRACT_H_
#define _GSLX680_EXTRACT_H_

#include <unistd.h>

#define GSLX680_I2C_ADDR 	0x40

#define GSL_DATA_REG		0x80
#define GSL_STATUS_REG		0xE0
#define GSL_PAGE_REG		0xF0

typedef unsigned int u32;
typedef unsigned short int u16;
typedef unsigned char u8;
typedef unsigned int  bool;

#define true 1
#define false 0

#endif

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to