示例#1
0
static int send_pkt(CalcHandle* handle, uint16_t cmd, uint16_t len, uint8_t* data)
{
	uint16_t sum;

	// command
	buf[0] = LSB(cmd);
	buf[1] = MSB(cmd);

	// length
	buf[2] = LSB(len);
	buf[3] = MSB(len);

	// data
	if(data)
		memcpy(buf+4, data, len);

	// checksum
	sum = tifiles_checksum(buf, 4 + len);
	buf[len+4+0] = LSB(sum);
	buf[len+4+1] = MSB(sum);

	TRYF(ticables_cable_send(handle->cable, buf, len+6));

	return 0;
}
示例#2
0
/**
 * tifiles_ungroup_content:
 * @src_content: a pointer on the structure to unpack.
 * @dst_contents: the address of your pointer. This pointers will point on a 
 * dynamically allocated array of structures. The array is terminated by NULL.
 *
 * Ungroup a TI file by exploding the structure into an array of structures.
 *
 * Array must be freed when no longer needed as well as the content of each #FileContent 
 * structure (use #tifiles_content_delete_regular as usual).
 *
 * Return value: an error code if unsuccessful, 0 otherwise.
 **/
TIEXPORT2 int TICALL tifiles_ungroup_content(FileContent *src, FileContent ***dest)
{
	int i;
	FileContent **dst;

	if (src == NULL || dest == NULL)
	{
		tifiles_critical("%s: an argument is NULL", __FUNCTION__);
		return ERR_INVALID_FILE;
	}

	if(src->model == CALC_NSPIRE)
		return ERR_BAD_CALC;

	// allocate an array of FileContent structures (NULL terminated)
	dst = *dest = (FileContent **)g_malloc0((src->num_entries + 1) * sizeof(FileContent *));
	if (dst == NULL)
		return ERR_MALLOC;

	// parse each entry and duplicate it into a single content
	for (i = 0; i < src->num_entries; i++)
	{
		VarEntry *dst_entry = NULL;

		// allocate and duplicate content
		dst[i] = (FileContent *)g_malloc0(sizeof(FileContent));
		if (dst[i] == NULL)
			return ERR_MALLOC;
		memcpy(dst[i], src, sizeof(FileContent));

		// allocate and duplicate entry
		dst[i]->entries = g_malloc0((1+1) * sizeof(VarEntry*));
		dst_entry = dst[i]->entries[0] = tifiles_ve_dup(src->entries[i]);

		// update some fields
		dst[i]->num_entries = 1;
		dst[i]->checksum += tifiles_checksum((uint8_t *) dst_entry, 15);
		dst[i]->checksum += tifiles_checksum(dst_entry->data, dst_entry->size);
	}
	dst[i] = NULL;

	return 0;
}
示例#3
0
文件: files9x.c 项目: TC01/tilibs
/**
 * ti9x_file_write_backup:
 * @filename: name of backup file where to write.
 * @content: the file content to write.
 *
 * Write content to a backup file.
 *
 * Return value: an error code, 0 otherwise.
 **/
int ti9x_file_write_backup(const char *filename, Ti9xBackup *content)
{
	FILE *f;

	if (filename == NULL || content == NULL)
	{
		tifiles_critical("%s: an argument is NULL", __FUNCTION__);
		return ERR_INVALID_FILE;
	}

	f = g_fopen(filename, "wb");
	if (f == NULL) 
	{
		tifiles_info("Unable to open this file: %s", filename);
		return ERR_FILE_OPEN;
	}

	if (fwrite_8_chars(f, tifiles_calctype2signature(content->model)) < 0) goto tfwb;
	if (fwrite(fsignature, 1, 2, f) < 2) goto tfwb;
	if (fwrite_8_chars(f, "") < 0) goto tfwb;
	if (fwrite_n_bytes(f, 40, (uint8_t *)content->comment) < 0) goto tfwb;
	if (fwrite_word(f, 1) < 0) goto tfwb;
	if (fwrite_long(f, 0x52) < 0) goto tfwb;
	if (fwrite_8_chars(f, content->rom_version) < 0) goto tfwb;
	if (fwrite_word(f, content->type) < 0) goto tfwb;
	if (fwrite_word(f, 0) < 0) goto tfwb;
	if (fwrite_long(f, content->data_length + 0x52 + 2) < 0) goto tfwb;
	if (fwrite_word(f, 0x5aa5) < 0) goto tfwb;
	if (fwrite(content->data_part, 1, content->data_length, f) < content->data_length) goto tfwb;

	content->checksum = tifiles_checksum(content->data_part, content->data_length);
	if (fwrite_word(f, content->checksum) < 0) goto tfwb;

	fclose(f);
	return 0;

tfwb:	// release on exit
	tifiles_critical("%s: error writing file %s", __FUNCTION__, filename);
	fclose(f);
	return ERR_FILE_IO;
}
示例#4
0
文件: files9x.c 项目: TC01/tilibs
/**
 * ti9x_file_read_regular:
 * @filename: name of single/group file to open.
 * @content: where to store the file content.
 *
 * Load the single/group file into a Ti9xRegular structure.
 *
 * Structure content must be freed with #tifiles_content_delete_regular when
 * no longer used. If error occurs, the structure content is released for you.
 *
 * Return value: an error code, 0 otherwise.
 **/
int ti9x_file_read_regular(const char *filename, Ti9xRegular *content)
{
	FILE *f;
	long cur_pos;
	char default_folder[FLDNAME_MAX];
	char current_folder[FLDNAME_MAX];
	uint32_t curr_offset = 0;
	uint32_t next_offset = 0;
	uint32_t file_size;
	uint16_t tmp;
	unsigned int i, j;
	char signature[9];
	char varname[VARNAME_MAX];
	int ret = ERR_FILE_IO;

	if (content == NULL)
	{
		tifiles_critical("%s: an argument is NULL", __FUNCTION__);
		return ERR_INVALID_FILE;
	}

	if (!tifiles_file_is_regular(filename))
	{
		ret = ERR_INVALID_FILE;
		goto tfrr2;
	}

	f = g_fopen(filename, "rb");
	if (f == NULL) 
	{
		ret = ERR_FILE_OPEN;
		goto tfrr2;
	}

	// Get file size, then rewind.
	if (fseek(f, 0, SEEK_END) < 0) goto tfrr;
	cur_pos = ftell(f);
	if (cur_pos < 0) goto tfrr;
	if (fseek(f, 0, SEEK_SET) < 0) goto tfrr;

	// The TI-68k series' members have at best 4 MB of Flash (TODO: modify this code if this no longer holds).
	// Regular / group files larger than that size are highly dubious, files larger than twice that size are insane.
	if (cur_pos >= (8L << 20))
	{
		ret = ERR_INVALID_FILE;
		goto tfrr;
	}
	file_size = (uint32_t)cur_pos;

	if (fread_8_chars(f, signature) < 0) goto tfrr; // Offset 0
	content->model = tifiles_signature2calctype(signature);
	if (content->model == CALC_NONE)
	{
		ret = ERR_INVALID_FILE;
		goto tfrr;
	}
	if (content->model_dst == CALC_NONE)
	{
		content->model_dst = content->model;
	}

	if (fread_word(f, NULL) < 0) goto tfrr; // Offset 0x8
	if (fread_8_chars(f, default_folder) < 0) goto tfrr; // Offset 0xA
	ticonv_varname_from_tifile_sn(content->model_dst, default_folder, content->default_folder, sizeof(content->default_folder), -1);
	strncpy(current_folder, content->default_folder, sizeof(current_folder) - 1);
	current_folder[sizeof(current_folder) - 1] = 0;
	if (fread_n_chars(f, 40, content->comment) < 0) goto tfrr; // Offset 0x12
	if (fread_word(f, &tmp) < 0) goto tfrr; // Offset 0x3A
	content->num_entries = tmp;

	content->entries = g_malloc0((content->num_entries + 1) * sizeof(VarEntry*));
	if (content->entries == NULL) 
	{
		ret = ERR_MALLOC;
		goto tfrr;
	}

	for (i = 0, j = 0; i < content->num_entries; i++) 
	{
		VarEntry *entry = content->entries[j] = g_malloc0(sizeof(VarEntry));

		if (fread_long(f, &curr_offset) < 0) goto tfrr; // Offset N, 0x3C for the first entry
		if (curr_offset > file_size)
		{
			ret = ERR_INVALID_FILE;
			goto tfrr;
		}
		if (fread_8_chars(f, varname) < 0)  goto tfrr; // Offset N+4, 0x40 for the first entry
		ticonv_varname_from_tifile_sn(content->model_dst, varname, entry->name, sizeof(entry->name), entry->type);
		if (fread_byte(f, &(entry->type)) < 0) goto tfrr; // Offset N+12, 0x48 for the first entry
		if (fread_byte(f, &(entry->attr)) < 0) goto tfrr; // Offset N+13, 0x49 for the first entry
		entry->attr = (entry->attr == 2 || entry->attr == 3) ? ATTRB_ARCHIVED : entry->attr;
		if (fread_word(f, NULL) < 0) goto tfrr; // Offset N+14, 0x4A for the first entry

		if (entry->type == TI92_DIR) // same as TI89_DIR, TI89t_DIR, ...
		{
			strncpy(current_folder, entry->name,sizeof(current_folder) - 1);
			current_folder[sizeof(current_folder) - 1] = 0;
			g_free(entry);
			continue;			// folder: skip entry
		}
		else 
		{
			uint16_t checksum, sum = 0;

			j++;
			strncpy(entry->folder, current_folder, sizeof(entry->folder) - 1);
			current_folder[sizeof(entry->folder) - 1] = 0;
			cur_pos = ftell(f);
			if (cur_pos < 0) goto tfrr;
			if (fread_long(f, &next_offset) < 0) goto tfrr; // Offset N+16, 0x4C for the first entry
			if (next_offset > file_size)
			{
				ret = ERR_INVALID_FILE;
				goto tfrr;
			}
			entry->size = next_offset - curr_offset - 4 - 2;
			if (entry->size > file_size)
			{
				ret = ERR_INVALID_FILE;
				goto tfrr;
			}
			entry->data = (uint8_t *)g_malloc0(entry->size);
			if (entry->data == NULL) 
			{
				ret = ERR_MALLOC;
				goto tfrr;
			}

			if (fseek(f, curr_offset, SEEK_SET)) goto tfrr;
			if (fread_long(f, NULL) < 0) goto tfrr;	// Normally: offset N+22, 0x52 for the first entry
			if (fread(entry->data, 1, entry->size, f) < entry->size) goto tfrr; // Normally: offset N+26, 0x56 for the first entry

			if (fread_word(f, &checksum) < 0) goto tfrr;
			if (fseek(f, cur_pos, SEEK_SET)) goto tfrr;

			sum = tifiles_checksum(entry->data, entry->size);
			if (sum != checksum)
			{
				ret = ERR_FILE_CHECKSUM;
				goto tfrr;
			}
			content->checksum += sum;	// sum of all checksums but unused
		}
	}
	content->num_entries = j;
	content->entries = g_realloc(content->entries, content->num_entries * sizeof(VarEntry*));
	//fread_long(f, &next_offset);
	//fseek(f, next_offset - 2, SEEK_SET);
	//fread_word(f, &(content->checksum));

	fclose(f);
	return 0;

tfrr:	// release on exit
	tifiles_critical("%s: error reading / understanding file %s", __FUNCTION__, filename);
	fclose(f);
tfrr2:
	tifiles_content_delete_regular(content);
	return ret;
}
示例#5
0
文件: files9x.c 项目: TC01/tilibs
/**
 * ti9x_file_write_regular:
 * @filename: name of single/group file where to write or NULL.
 * @content: the file content to write.
 * @real_filename: pointer address or NULL. Must be freed if needed when no longer needed.
 *
 * Write one (or several) variable(s) into a single (group) file. If filename is set to NULL,
 * the function build a filename from varname and allocates resulting filename in %real_fname.
 * %filename and %real_filename can be NULL but not both !
 *
 * %real_filename must be freed when no longer used.
 *
 * Return value: an error code, 0 otherwise.
 **/
int ti9x_file_write_regular(const char *fname, Ti9xRegular *content, char **real_fname)
{
	FILE *f;
	unsigned int i;
	char *filename = NULL;
	uint32_t offset = 0x52;
	int **table;
	unsigned int num_folders;
	char default_folder[FLDNAME_MAX];
	char fldname[FLDNAME_MAX], varname[VARNAME_MAX];

	if (content->entries == NULL)
	{
		tifiles_warning("%s: skipping content with NULL content->entries", __FUNCTION__);
		return 0;
	}

	if (fname != NULL)
	{
		filename = g_strdup(fname);
		if (filename == NULL)
		{
			return ERR_MALLOC;
		}
	} 
	else 
	{
		if (content->entries[0])
		{
			filename = tifiles_build_filename(content->model_dst, content->entries[0]);
		}
		else
		{
			tifiles_warning("%s: asked to build a filename from null content->entries[0], bailing out", __FUNCTION__);
			if (real_fname != NULL)
			{
				*real_fname = NULL;
			}
			return 0;
		}
		if (real_fname != NULL)
		{
			*real_fname = g_strdup(filename);
		}
	}

	// build the table of folder & variable entries
	table = tifiles_create_table_of_entries((FileContent *)content, &num_folders);
	if (table == NULL)
	{
		g_free(filename);
		return ERR_MALLOC;
	}

	f = g_fopen(filename, "wb");
	if (f == NULL) 
	{
		tifiles_info( "Unable to open this file: %s", filename);
		tifiles_free_table_of_entries(table);
		g_free(filename);
		return ERR_FILE_OPEN;
	}

	// write header
	if (fwrite_8_chars(f, tifiles_calctype2signature(content->model)) < 0) goto tfwr;
	if (fwrite(fsignature, 1, 2, f) < 2) goto tfwr;
	if (content->num_entries == 1)	// folder entry for single var is placed here
	{
		strncpy(content->default_folder, content->entries[0]->folder, sizeof(content->default_folder) - 1);
		content->default_folder[sizeof(content->default_folder) - 1] = 0;
	}
	ticonv_varname_to_tifile_sn(content->model, content->default_folder, default_folder, sizeof(default_folder), -1);
	if (fwrite_8_chars(f, default_folder) < 0) goto tfwr;
	if (fwrite_n_bytes(f, 40, (uint8_t *)content->comment) < 0) goto tfwr;
	if (content->num_entries > 1) 
	{
		if (fwrite_word(f, (uint16_t) (content->num_entries + num_folders)) < 0) goto tfwr;
		offset += 16 * (content->num_entries + num_folders - 1);
	} 
	else
	{
		if (fwrite_word(f, 1) < 0) goto tfwr;
	}

	// write table of entries
	for (i = 0; table[i] != NULL; i++) 
	{
		VarEntry *fentry;
		int j, idx = table[i][0];
		fentry = content->entries[idx];

		if (fentry == NULL)
		{
			tifiles_warning("%s: skipping null content entry %d", __FUNCTION__, i);
			continue;
		}

		if (content->num_entries > 1)	// single var does not have folder entry
		{
			if (fwrite_long(f, offset) < 0) goto tfwr;
			ticonv_varname_to_tifile_sn(content->model, fentry->folder, fldname, sizeof(fldname), -1);
			if (fwrite_8_chars(f, fldname) < 0) goto tfwr;
			if (fwrite_byte(f, (uint8_t)tifiles_folder_type(content->model)) < 0) goto tfwr;
			if (fwrite_byte(f, 0x00) < 0) goto tfwr;
			for (j = 0; table[i][j] != -1; j++);
			if (fwrite_word(f, (uint16_t) j) < 0) goto tfwr;
		}

		for (j = 0; table[i][j] != -1; j++) 
		{
			int idx2 = table[i][j];
			VarEntry *entry = content->entries[idx2];
			uint8_t attr = ATTRB_NONE;

			if (fwrite_long(f, offset) < 0) goto tfwr;
			ticonv_varname_to_tifile_sn(content->model, entry->name, varname, sizeof(varname), entry->type);
			if (fwrite_8_chars(f, varname) < 0) goto tfwr;
			if (fwrite_byte(f, entry->type) < 0) goto tfwr;
			attr = (entry->attr == ATTRB_ARCHIVED) ? 3 : entry->attr;
			if (fwrite_byte(f, attr) < 0) goto tfwr;
			if (fwrite_word(f, 0) < 0) goto tfwr;

			offset += entry->size + 4 + 2;
		}
	}

	if (fwrite_long(f, offset) < 0) goto tfwr;
	if (fwrite_word(f, 0x5aa5) < 0) goto tfwr;

	// write data
	for (i = 0; table[i] != NULL; i++) 
	{
		int j;

		for (j = 0; table[i][j] != -1; j++) 
		{
			int idx = table[i][j];
			VarEntry *entry = content->entries[idx];
			uint16_t sum;

			if (fwrite_long(f, 0) < 0) goto tfwr;
			if (fwrite(entry->data, 1, entry->size, f) < entry->size) goto tfwr;
			sum = tifiles_checksum(entry->data, entry->size);
			if (fwrite_word(f, sum) < 0) goto tfwr;
		}
	}

	tifiles_free_table_of_entries(table);
	g_free(filename);
	fclose(f);
	return 0;

tfwr:	// release on exit
	tifiles_critical("%s: error writing file %s", __FUNCTION__, filename);
	tifiles_free_table_of_entries(table);
	g_free(filename);
	fclose(f);
	return ERR_FILE_IO;
}
示例#6
0
文件: files9x.c 项目: TC01/tilibs
/**
 * ti9x_file_read_backup:
 * @filename: name of backup file to open.
 * @content: where to store the file content.
 *
 * Load the backup file into a Ti9xBackup structure.
 *
 * Structure content must be freed with #tifiles_content_delete_backup when
 * no longer used. If error occurs, the structure content is released for you.
 *
 * Return value: an error code, 0 otherwise.
 **/
int ti9x_file_read_backup(const char *filename, Ti9xBackup *content)
{
	FILE *f;
	long cur_pos = 0;
	uint32_t file_size;
	char signature[9];
	uint16_t sum;
	int ret = ERR_FILE_IO;

	if (content == NULL)
	{
		tifiles_critical("%s: an argument is NULL", __FUNCTION__);
		return ERR_INVALID_FILE;
	}

	if (!tifiles_file_is_backup(filename))
	{
		ret = ERR_INVALID_FILE;
		goto tfrb2;
	}

	f = g_fopen(filename, "rb");
	if (f == NULL) 
	{
		tifiles_info( "Unable to open this file: %s", filename);
		ret = ERR_FILE_OPEN;
		goto tfrb2;
	}

	// Get file size, then rewind.
	if (fseek(f, 0, SEEK_END) < 0) goto tfrb;
	cur_pos = ftell(f);
	if (cur_pos < 0) goto tfrb;
	if (fseek(f, 0, SEEK_SET) < 0) goto tfrb;

	// The TI-68k series' members have at best 4 MB of Flash (TODO: modify this code if this no longer holds).
	// Backup files larger than that size are highly dubious, files larger than twice that size are insane.
	if (cur_pos >= (8L << 20))
	{
		ret = ERR_INVALID_FILE;
		goto tfrb;
	}

	if (fread_8_chars(f, signature) < 0) goto tfrb;
	content->model = tifiles_signature2calctype(signature);
	if (content->model == CALC_NONE)
	{
		ret = ERR_INVALID_FILE;
	}

	if (fread_word(f, NULL) < 0) goto tfrb;
	if (fread_8_chars(f, NULL) < 0) goto tfrb;
	if (fread_n_chars(f, 40, content->comment) < 0) goto tfrb;
	if (fread_word(f, NULL) < 0) goto tfrb;
	if (fread_long(f, NULL) < 0) goto tfrb;
	if (fread_8_chars(f, content->rom_version) < 0) goto tfrb;
	if (fread_byte(f, &(content->type)) < 0) goto tfrb;
	if (fread_byte(f, NULL) < 0) goto tfrb;
	if (fread_word(f, NULL) < 0) goto tfrb;
	if (fread_long(f, &file_size) < 0) goto tfrb;
	if (file_size > (uint32_t)cur_pos)
	{
		ret = ERR_INVALID_FILE;
		goto tfrb;
	}
	content->data_length = file_size - 0x52 - 2;
	if (fread_word(f, NULL) < 0) goto tfrb;

	content->data_part = (uint8_t *)g_malloc0(content->data_length);
	if (content->data_part == NULL) 
	{
		ret = ERR_MALLOC;
		goto tfrb;
	}

	if (fread(content->data_part, 1, content->data_length, f) < content->data_length) goto tfrb;
	if (fread_word(f, &(content->checksum)) < 0) goto tfrb;

	sum = tifiles_checksum(content->data_part, content->data_length);
#if defined(CHECKSUM_ENABLED)
	if (sum != content->checksum)
	{
		ret = ERR_FILE_CHECKSUM;
		goto tfrb;
	}
#endif

	fclose(f);
	return 0;

tfrb:	// release on exit
	tifiles_critical("%s: error reading / understanding file %s", __FUNCTION__, filename);
	fclose(f);
tfrb2:
	tifiles_content_delete_backup(content);
	return ret;
}
示例#7
0
/*
    Send a packet from PC (host) to TI (target):
    - target [in] : a machine ID uint8_t
    - cmd [in]    : a command ID uint8_t
    - length [in] : length of buffer
    - data [in]   : data to send (or 0x00 if NULL)
    - int [out]   : an error code
*/
TIEXPORT3 int TICALL dbus_send(CalcHandle* handle, uint8_t target, uint8_t cmd, uint16_t len, uint8_t* data)
{
	int i;
	uint16_t sum;
	uint32_t length = (len == 0x0000) ? 65536 : len;   // wrap around
	uint8_t *buf;
	int r, q;
	static int ref = 0;

	if (handle == NULL)
	{
		ticalcs_critical("%s: handle is NULL", __FUNCTION__);
		return ERR_INVALID_HANDLE;
	}
	buf = (uint8_t *)handle->priv2;                    //[65536+6];
	if (buf == NULL)
	{
		ticalcs_critical("%s: handle->priv2 is NULL", __FUNCTION__);
		return ERR_INVALID_HANDLE;
	}

	ticables_progress_reset(handle->cable);

	if(data == NULL)
	{
		// short packet (no data)
		buf[0] = target;
		buf[1] = cmd;
		buf[2] = 0x00;
		buf[3] = 0x00;

		// TI80 does not use length
		if(target == PC_TI80)
		{
			TRYF(ticables_cable_send(handle->cable, buf, 2));
		}
		else
		{
			TRYF(ticables_cable_send(handle->cable, buf, 4));
		}
	}
	else 
	{
		// std packet (data + checksum)
		buf[0] = target;
		buf[1] = cmd;
		buf[2] = LSB(length);
		buf[3] = MSB(length);

		// copy data
		memcpy(buf+4, data, length);

		// add checksum of packet
		sum = tifiles_checksum(data, length);
		buf[length+4+0] = LSB(sum);
		buf[length+4+1] = MSB(sum);

		// compute chunks
		MIN_SIZE = (handle->cable->model == CABLE_GRY) ? 512 : 2048;
		BLK_SIZE = (length + 6) / 20;		// 5%
		if(BLK_SIZE == 0) BLK_SIZE = length + 6;
		if(BLK_SIZE < 32) BLK_SIZE = 128;	// SilverLink doesn't like small block (< 32)

		q = (length + 6) / BLK_SIZE;
		r = (length + 6) % BLK_SIZE;

		handle->updat->max1 = length + 6;
		handle->updat->cnt1 = 0;

		// send full chunks
		for(i = 0; i < q; i++)
		{
			TRYF(ticables_cable_send(handle->cable, &buf[i*BLK_SIZE], BLK_SIZE));
			ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate);

			handle->updat->cnt1 += BLK_SIZE;
			if(length > MIN_SIZE)
				handle->updat->pbar();

			if (handle->updat->cancel)
				return ERR_ABORT;
		}

		// send last chunk
		{
			TRYF(ticables_cable_send(handle->cable, &buf[i*BLK_SIZE], (uint16_t)r));
			ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate);

			handle->updat->cnt1 += 1;
			if(length > MIN_SIZE)
				handle->updat->pbar();

			if (handle->updat->cancel)
				return ERR_ABORT;
		}
	}

	// force periodic refresh
	if(!(ref++ % 4))
		handle->updat->refresh();

	return 0;
}
示例#8
0
static int recv_pkt(CalcHandle* handle, uint16_t* cmd, uint16_t* len, uint8_t* data)
{
	int i, r, q;
	uint16_t sum, chksum;

	// Any packet has always at least 4 bytes (cmd, len)
	TRYF(ticables_cable_recv(handle->cable, buf, 4));

	*cmd = (buf[1] << 8) | buf[0];
	*len = (buf[3] << 8) | buf[2];

	if(!cmd_is_valid(*cmd))
		return ERR_INVALID_CMD;

	if(*cmd == CMD_ERROR)
		return ERR_ROM_ERROR;

	// compute chunks
	BLK_SIZE = *len / 20;
	if(BLK_SIZE == 0) BLK_SIZE = 1;

	q = *len / BLK_SIZE;
	r = *len % BLK_SIZE;
	handle->updat->max1 = *len;
	handle->updat->cnt1 = 0;

	// recv full chunks
	for(i = 0; i < q; i++)
	{
		TRYF(ticables_cable_recv(handle->cable, &buf[i*BLK_SIZE + 4], BLK_SIZE));
		ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate);
		handle->updat->cnt1 += BLK_SIZE;
		if(*len > MIN_SIZE)
			handle->updat->pbar();
		//if (handle->updat->cancel) 
		//	return ERR_ABORT;
	}

	// recv last chunk
	{
		TRYF(ticables_cable_recv(handle->cable, &buf[i*BLK_SIZE + 4], (uint16_t)(r+2)));
		ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate);
		handle->updat->cnt1 += 1;
		if(*len > MIN_SIZE)
			handle->updat->pbar();
		if (handle->updat->cancel)
			return ERR_ABORT;
	}

	// verify checksum
	chksum = (buf[*len+4 + 1] << 8) | buf[*len+4 + 0];
	sum = tifiles_checksum(buf, *len + 4);
	//printf("<%04x %04x>\n", sum, chksum);

	if (chksum != sum)
		return ERR_CHECKSUM;

	if(data)
		memcpy(data, buf+4, *len);

	return 0;
}
示例#9
0
static int dbus_recv_(CalcHandle* handle, uint8_t* host, uint8_t* cmd, uint16_t* length, uint8_t* data, int host_check)
{
	int i;
	uint16_t chksum;
	uint8_t buf[4];
	int r, q;
	static int ref = 0;

	if (handle == NULL)
	{
		ticalcs_critical("%s: handle is NULL", __FUNCTION__);
		return ERR_INVALID_HANDLE;
	}
	if (host == NULL || cmd == NULL || length == NULL)
	{
		ticalcs_critical("%s: an argument is NULL", __FUNCTION__);
		return ERR_INVALID_PACKET;
	}

	// Any packet has always at least 2 bytes (MID, CID)
	TRYF(ticables_cable_recv(handle->cable, buf, 2));

	*host = buf[0];
	*cmd = buf[1];

	// Any non-TI80 packet has a length; TI80 data packets also have a length
	if(*host != TI80_PC || *cmd == CMD_XDP)
	{
		TRYF(ticables_cable_recv(handle->cable, buf, 2));

		*length = buf[0] | (buf[1] << 8);
	}
	else *length = 0;

	//removed for probing (pb here !)
	//if(host_check && (*host != host_ids(handle))) 
	//	return ERR_INVALID_HOST;

	if(*cmd == CMD_ERR || *cmd == CMD_ERR2)
		return ERR_CHECKSUM;

	switch (*cmd) 
	{
	case CMD_VAR:	// std packet ( data + checksum)
	case CMD_XDP:
	case CMD_SKP:
	case CMD_SID:
	case CMD_REQ:
	case CMD_IND:
	case CMD_RTS:
		if (data == NULL)
		{
			ticalcs_critical("%s: data is NULL", __FUNCTION__);
			return ERR_INVALID_CMD;
		}

		// compute chunks*
		MIN_SIZE = (handle->cable->model == CABLE_GRY) ? 512 : 2048;
		BLK_SIZE = *length / 20;
		if(BLK_SIZE == 0) BLK_SIZE = 1;

		q = *length / BLK_SIZE;
		r = *length % BLK_SIZE;
		handle->updat->max1 = *length;
		handle->updat->cnt1 = 0;

		// recv full chunks
		for(i = 0; i < q; i++)
		{
			TRYF(ticables_cable_recv(handle->cable, &data[i*BLK_SIZE], BLK_SIZE));
			ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate);

			handle->updat->cnt1 += BLK_SIZE;
			if(*length > MIN_SIZE) 
				handle->updat->pbar();

			if (handle->updat->cancel)
				return ERR_ABORT;
		}

		// recv last chunk
		{
			TRYF(ticables_cable_recv(handle->cable, 
						 &data[i*BLK_SIZE], 
						 (uint16_t)r));
			ticables_progress_get(handle->cable, NULL, NULL, 
					      &handle->updat->rate);
			TRYF(ticables_cable_recv(handle->cable, buf, 2));

			handle->updat->cnt1 += 1;
			if(*length > MIN_SIZE) 
				handle->updat->pbar();

			if (handle->updat->cancel)
				return ERR_ABORT;
		}

		// verify checksum
		chksum = buf[0] | (buf[1] << 8);
		if (chksum != tifiles_checksum(data, *length))
			return ERR_CHECKSUM;

		break;
	case CMD_CTS:	// short packet (no data)
	case CMD_ACK:
	case CMD_ERR:
	case CMD_ERR2:
	case CMD_RDY:
	case CMD_SCR:
	case CMD_RID:
	case CMD_KEY:
	case CMD_EOT:
	case CMD_CNT:
		break;
	default:
		return ERR_INVALID_CMD;
	}

	// force periodic refresh
	if(!(ref++ % 4))
		handle->updat->refresh();

	return 0;
}
示例#10
0
文件: dbus_pkt.c 项目: TC01/tilibs
/*
    Send a packet from PC (host) to TI (target):
    - target [in] : a machine ID uint8_t
    - cmd [in]    : a command ID uint8_t
    - length [in] : length of buffer
    - data [in]   : data to send (or 0x00 if NULL)
    - int [out]   : an error code
*/
TIEXPORT3 int TICALL dbus_send(CalcHandle* handle, uint8_t target, uint8_t cmd, uint16_t len, const uint8_t* data)
{
	int i;
	uint16_t sum;
	uint32_t length = (len == 0x0000) ? 65536 : len;   // wrap around
	uint8_t *buf;
	int r, q;
	static int ref = 0;
	int ret;

	VALIDATE_HANDLE(handle);

	buf = (uint8_t *)handle->buffer;                    //[65536+6];
	if (buf == NULL)
	{
		ticalcs_critical("%s: handle->buffer is NULL", __FUNCTION__);
		return ERR_INVALID_HANDLE;
	}

	ticables_progress_reset(handle->cable);

	if (data == NULL)
	{
		// short packet (no data)
		buf[0] = target;
		buf[1] = cmd;
		buf[2] = 0x00;
		buf[3] = 0x00;

		// The TI-80 does not use length
		ret = ticables_cable_send(handle->cable, buf, (target == DBUS_MID_PC_TI80) ? 2 : 4);
	}
	else 
	{
		// std packet (data + checksum)
		buf[0] = target;
		buf[1] = cmd;
		buf[2] = LSB(length);
		buf[3] = MSB(length);

		// copy data
		memcpy(buf+4, data, length);

		// add checksum of packet
		sum = tifiles_checksum(data, length);
		buf[length+4+0] = LSB(sum);
		buf[length+4+1] = MSB(sum);

		// compute chunks
		handle->priv.progress_min_size = (handle->cable->model == CABLE_GRY) ? 512 : 2048;
		handle->priv.progress_blk_size = (length + 6) / 20;		// 5%
		if (handle->priv.progress_blk_size == 0)
		{
			handle->priv.progress_blk_size = length + 6;
		}
		if (handle->priv.progress_blk_size < 32)
		{
			handle->priv.progress_blk_size = 128;	// SilverLink doesn't like small block (< 32)
		}

		q = (length + 6) / handle->priv.progress_blk_size;
		r = (length + 6) % handle->priv.progress_blk_size;

		handle->updat->max1 = length + 6;
		handle->updat->cnt1 = 0;

		ret = 0;

		// send full chunks
		for (i = 0; i < q; i++)
		{
			ret = ticables_cable_send(handle->cable, &buf[i*handle->priv.progress_blk_size], handle->priv.progress_blk_size);
			if (ret)
			{
				break;
			}
			ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate);

			handle->updat->cnt1 += handle->priv.progress_blk_size;
			if (length > handle->priv.progress_min_size)
			{
				handle->updat->pbar();
			}

			if (handle->updat->cancel)
			{
				ret = ERR_ABORT;
				break;
			}
		}

		// send last chunk
		if (!ret)
		{
			ret = ticables_cable_send(handle->cable, &buf[i*handle->priv.progress_blk_size], (uint16_t)r);
			if (!ret)
			{
				ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate);

				handle->updat->cnt1 += 1;
				if (length > handle->priv.progress_min_size)
				{
					handle->updat->pbar();
				}

				if (handle->updat->cancel)
				{
					ret = ERR_ABORT;
				}
			}
		}
	}

	// force periodic refresh
	if (!ret && !(ref++ % 4))
	{
		handle->updat->refresh();
	}

	return ret;
}
示例#11
0
文件: dbus_pkt.c 项目: TC01/tilibs
TIEXPORT3 int TICALL dbus_recv_data(CalcHandle *handle, uint16_t* length, uint8_t* data)
{
	int ret;
	int i;
	uint16_t chksum;
	uint8_t buf[4];
	int r, q;

	VALIDATE_HANDLE(handle);
	VALIDATE_NONNULL(length);
	VALIDATE_NONNULL(data);

	// compute chunks
	handle->priv.progress_min_size = (handle->cable->model == CABLE_GRY) ? 512 : 2048;
	handle->priv.progress_blk_size = *length / 20;
	if (handle->priv.progress_blk_size == 0)
	{
		handle->priv.progress_blk_size = 1;
	}

	q = *length / handle->priv.progress_blk_size;
	r = *length % handle->priv.progress_blk_size;
	handle->updat->max1 = *length;
	handle->updat->cnt1 = 0;

	ret = 0;
	// recv full chunks
	for (i = 0; i < q; i++)
	{
		ret = ticables_cable_recv(handle->cable, &data[i*handle->priv.progress_blk_size], handle->priv.progress_blk_size);
		if (ret)
		{
			break;
		}
		ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate);

		handle->updat->cnt1 += handle->priv.progress_blk_size;
		if (*length > handle->priv.progress_min_size)
		{
			handle->updat->pbar();
		}

		if (handle->updat->cancel)
		{
			ret = ERR_ABORT;
			break;
		}
	}

	// recv last chunk
	if (!ret)
	{
		ret = ticables_cable_recv(handle->cable, &data[i*handle->priv.progress_blk_size], (uint16_t)r);
		if (!ret)
		{
			ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate);
			ret = ticables_cable_recv(handle->cable, buf, 2);
			if (!ret)
			{
				handle->updat->cnt1++;
				if (*length > handle->priv.progress_min_size)
				{
					handle->updat->pbar();
				}

				if (handle->updat->cancel)
				{
					ret = ERR_ABORT;
				}
			}
		}
	}

	if (!ret)
	{
		// verify checksum
		chksum = buf[0] | ((uint16_t)buf[1] << 8);
		if (chksum != tifiles_checksum(data, *length))
		{
			ret = ERR_CHECKSUM;
		}
	}

	return ret;
}
示例#12
0
/**
 * ti9x_file_read_regular:
 * @filename: name of single/group file to open.
 * @content: where to store the file content.
 *
 * Load the single/group file into a Ti9xRegular structure.
 *
 * Structure content must be freed with #tifiles_content_delete_regular when
 * no longer used. If error occurs, the structure content is released for you.
 *
 * Return value: an error code, 0 otherwise.
 **/
int ti9x_file_read_regular(const char *filename, Ti9xRegular *content)
{
	FILE *f;
	long cur_pos = 0;
	char default_folder[FLDNAME_MAX];
	char current_folder[FLDNAME_MAX];
	uint32_t curr_offset = 0;
	uint32_t next_offset = 0;
	uint16_t tmp;
	int i, j;
	char signature[9];
	char varname[VARNAME_MAX];

	if (!tifiles_file_is_regular(filename))
	{
		return ERR_INVALID_FILE;
	}

	if (content == NULL)
	{
		tifiles_critical("%s: an argument is NULL", __FUNCTION__);
		return ERR_INVALID_FILE;
	}

	f = g_fopen(filename, "rb");
	if (f == NULL) 
	{
		tifiles_info( "Unable to open this file: %s", filename);
		return ERR_FILE_OPEN;
	}

	if(fread_8_chars(f, signature) < 0) goto tffr;
	content->model = tifiles_signature2calctype(signature);
	if (content->model == CALC_NONE)
	{
		return ERR_INVALID_FILE;
	}
	if(content->model_dst == CALC_NONE)
	{
		content->model_dst = content->model;
	}

	if(fread_word(f, NULL) < 0) goto tffr;
	if(fread_8_chars(f, default_folder) < 0) goto tffr;
	ticonv_varname_from_tifile_s(content->model_dst, default_folder, content->default_folder, -1);
	strcpy(current_folder, content->default_folder);
	if(fread_n_chars(f, 40, content->comment) < 0) goto tffr;
	if(fread_word(f, &tmp) < 0) goto tffr;
	content->num_entries = tmp;

	content->entries = g_malloc0((content->num_entries + 1) * sizeof(VarEntry*));
	if (content->entries == NULL) 
	{
		fclose(f);
		return ERR_MALLOC;
	}

	for (i = 0, j = 0; i < content->num_entries; i++) 
	{
		VarEntry *entry = content->entries[j] = g_malloc0(sizeof(VarEntry));

		if(fread_long(f, &curr_offset) < 0) goto tffr;
		if(fread_8_chars(f, varname) < 0)  goto tffr;
		ticonv_varname_from_tifile_s(content->model_dst, varname, entry->name, entry->type);
		if(fread_byte(f, &(entry->type)) < 0) goto tffr;
		if(fread_byte(f, &(entry->attr)) < 0) goto tffr;
		entry->attr = (entry->attr == 2 || entry->attr == 3) ? ATTRB_ARCHIVED : entry->attr;
		if(fread_word(f, NULL) < 0) goto tffr;

		if (entry->type == TI92_DIR) // same as TI89_DIR, TI89t_DIR, ...
		{
			strcpy(current_folder, entry->name);
			g_free(entry);
			continue;			// folder: skip entry
		}
		else 
		{
			uint16_t checksum, sum = 0;

			j++;
			strcpy(entry->folder, current_folder);
			cur_pos = ftell(f);
			if(cur_pos == -1L) goto tffr;
			if(fread_long(f, &next_offset) < 0) goto tffr;
			entry->size = next_offset - curr_offset - 4 - 2;
			entry->data = (uint8_t *)g_malloc0(entry->size);
			if (entry->data == NULL) 
			{
				fclose(f);
				tifiles_content_delete_regular(content);
				return ERR_MALLOC;
			}

			if(fseek(f, curr_offset, SEEK_SET)) goto tffr;
			if(fread_long(f, NULL) < 0) goto tffr;	// 4 bytes (NULL)
			if(fread(entry->data, 1, entry->size, f) < entry->size) goto tffr;

			if(fread_word(f, &checksum) < 0) goto tffr;
			if(fseek(f, cur_pos, SEEK_SET)) goto tffr;

			sum = tifiles_checksum(entry->data, entry->size);
			if(sum != checksum)
			{
				fclose(f);
				tifiles_content_delete_regular(content);
				return ERR_FILE_CHECKSUM;
			}
			content->checksum += sum;	// sum of all checksums but unused
		}
	}
	content->num_entries = j;
	content->entries = g_realloc(content->entries, content->num_entries * sizeof(VarEntry*));
	//fread_long(f, &next_offset);
	//fseek(f, next_offset - 2, SEEK_SET);
	//fread_word(f, &(content->checksum));

	fclose(f);
	return 0;

tffr:	// release on exit
	tifiles_critical("%s: error reading / understanding file %s", __FUNCTION__, filename);
	fclose(f);
	tifiles_content_delete_regular(content);
	return ERR_FILE_IO;
}
示例#13
0
/**
 * ti9x_file_read_backup:
 * @filename: name of backup file to open.
 * @content: where to store the file content.
 *
 * Load the backup file into a Ti9xBackup structure.
 *
 * Structure content must be freed with #tifiles_content_delete_backup when
 * no longer used. If error occurs, the structure content is released for you.
 *
 * Return value: an error code, 0 otherwise.
 **/
int ti9x_file_read_backup(const char *filename, Ti9xBackup *content)
{
	FILE *f;
	uint32_t file_size;
	char signature[9];
	uint16_t sum;

	if (!tifiles_file_is_backup(filename))
	{
		return ERR_INVALID_FILE;
	}

	f = g_fopen(filename, "rb");
	if (f == NULL) 
	{
		tifiles_info( "Unable to open this file: %s", filename);
		return ERR_FILE_OPEN;
	}

	if (content == NULL)
	{
		tifiles_critical("%s: an argument is NULL", __FUNCTION__);
		return ERR_INVALID_FILE;
	}

	if(fread_8_chars(f, signature) < 0) goto tfrb;
	content->model = tifiles_signature2calctype(signature);
	if (content->model == CALC_NONE)
	{
		return ERR_INVALID_FILE;
	}

	if(fread_word(f, NULL) < 0) goto tfrb;
	if(fread_8_chars(f, NULL) < 0) goto tfrb;
	if(fread_n_chars(f, 40, content->comment) < 0) goto tfrb;
	if(fread_word(f, NULL) < 0) goto tfrb;
	if(fread_long(f, NULL) < 0) goto tfrb;
	if(fread_8_chars(f, content->rom_version) < 0) goto tfrb;
	if(fread_byte(f, &(content->type)) < 0) goto tfrb;
	if(fread_byte(f, NULL) < 0) goto tfrb;
	if(fread_word(f, NULL) < 0) goto tfrb;
	if(fread_long(f, &file_size) < 0) goto tfrb;
	content->data_length = file_size - 0x52 - 2;
	if(fread_word(f, NULL) < 0) goto tfrb;

	content->data_part = (uint8_t *)g_malloc0(content->data_length);
	if (content->data_part == NULL) 
	{
		fclose(f);
		tifiles_content_delete_backup(content);
		return ERR_MALLOC;
	}

	if(fread(content->data_part, 1, content->data_length, f) < content->data_length) goto tfrb;
	if(fread_word(f, &(content->checksum)) < 0) goto tfrb;

	sum = tifiles_checksum(content->data_part, content->data_length);
#if defined(CHECKSUM_ENABLED)
	if(sum != content->checksum)
	{
		fclose(f);
		tifiles_content_delete_backup(content);
		return ERR_FILE_CHECKSUM;
	}
#endif

	fclose(f);
	return 0;

tfrb:	// release on exit
	tifiles_critical("%s: error reading / understanding file %s", __FUNCTION__, filename);
	fclose(f);
	tifiles_content_delete_backup(content);
	return ERR_FILE_IO;
}