1 /* Hey EMACS -*- linux-c -*- */
2 /* $Id: link_nul.c 1059 2005-05-14 09:45:42Z roms $ */
3 
4 /*  libticalcs2 - hand-helds support library, a part of the TiLP project
5  *  Copyright (C) 1999-2005  Romain Liévin
6  *  Copyright (C) 2006  Kevin Kofler
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software Foundation,
20  *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 /*
24 	TI89/TI92+/V200/TI89T/TI92 support.
25 */
26 
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <time.h>
35 
36 #include "ticalcs.h"
37 #include "gettext.h"
38 #include "internal.h"
39 #include "logging.h"
40 #include "error.h"
41 
42 #include "cmd68k.h"
43 #include "rom89.h"
44 #include "rom92f2.h"
45 #include "romdump.h"
46 #include "keys89.h"
47 #include "keys92p.h"
48 
49 #define SEND_RDY(handle) (handle->model != CALC_TI92 ? ti89_send_RDY(handle) : ti92_send_RDY(handle))
50 #define SEND_KEY(handle, scancode) (handle->model != CALC_TI92 ? ti89_send_KEY(handle, scancode) : ti92_send_KEY(handle, scancode))
51 #define SEND_SCR(handle) (handle->model != CALC_TI92 ? ti89_send_SCR(handle) : ti92_send_SCR(handle))
52 #define SEND_ACK(handle) (handle->model != CALC_TI92 ? ti89_send_ACK(handle) : ti92_send_ACK(handle))
53 #define SEND_VAR(handle, varsize, vartype, varname) (handle->model != CALC_TI92 ? ti89_send_VAR(handle, varsize, vartype, varname) : ti92_send_VAR(handle, varsize, vartype, varname))
54 #define SEND_XDP(handle, length, data) (handle->model != CALC_TI92 ? ti89_send_XDP(handle, length, data) : ti92_send_XDP(handle, length, data))
55 #define SEND_REQ(handle, varsize, vartype, varname) (handle->model != CALC_TI92 ? ti89_send_REQ(handle, varsize, vartype, varname) : ti92_send_REQ(handle, varsize, vartype, varname))
56 #define SEND_RTS(handle, varsize, vartype, varname) (handle->model != CALC_TI92 ? ti89_send_RTS(handle, varsize, vartype, varname) : ti92_send_RTS(handle, varsize, vartype, varname))
57 #define SEND_RTS2 ti89_send_RTS2
58 #define SEND_CTS(handle) (handle->model != CALC_TI92 ? ti89_send_CTS(handle) : ti92_send_CTS(handle))
59 #define SEND_CNT(handle) (handle->model != CALC_TI92 ? ti89_send_CNT(handle) : ti92_send_CNT(handle))
60 #define SEND_DEL ti89_send_DEL
61 #define SEND_VER ti89_send_VER
62 #define SEND_EOT(handle) (handle->model != CALC_TI92 ? ti89_send_EOT(handle) : ti92_send_EOT(handle))
63 
64 #define RECV_ACK(handle, status) (handle->model != CALC_TI92 ? ti89_recv_ACK(handle, status) : ti92_recv_ACK(handle, status))
65 #define RECV_VAR(handle, varsize, vartype, varname) (handle->model != CALC_TI92 ? ti89_recv_VAR(handle, varsize, vartype, varname) : ti92_recv_VAR(handle, varsize, vartype, varname))
66 #define RECV_XDP(handle, length, data) (handle->model != CALC_TI92 ? ti89_recv_XDP(handle, length, data) : ti92_recv_XDP(handle, length, data))
67 #define RECV_CTS(handle) (handle->model != CALC_TI92 ? ti89_recv_CTS(handle) : ti92_recv_CTS(handle))
68 #define RECV_SKP(handle, rej_code) (handle->model != CALC_TI92 ? ti89_recv_SKP(handle, rej_code) : ti92_recv_SKP(handle, rej_code))
69 #define RECV_CNT(handle) (handle->model != CALC_TI92 ? ti89_recv_CNT(handle) : ti92_recv_CNT(handle))
70 #define RECV_EOT(handle) (handle->model != CALC_TI92 ? ti89_recv_EOT(handle) : ti92_recv_EOT(handle))
71 
72 // Screen coordinates of the TI-89 / TI-92+
73 #define TI89_ROWS          128
74 #define TI89_COLS          240
75 #define TI89_ROWS_VISIBLE  100
76 #define TI89_COLS_VISIBLE  160
77 
78 #define TI92_ROWS  128
79 #define TI92_COLS  240
80 
is_ready(CalcHandle * handle)81 static int		is_ready	(CalcHandle* handle)
82 {
83 	int ret;
84 	uint16_t status;
85 
86 	ret = SEND_RDY(handle);
87 	if (!ret)
88 	{
89 		ret = RECV_ACK(handle, &status);
90 		if (!ret)
91 		{
92 			ret = (MSB(status) & 0x01) ? ERR_NOT_READY : 0;
93 		}
94 	}
95 
96 	return ret;
97 }
98 
send_key(CalcHandle * handle,uint32_t key)99 static int		send_key	(CalcHandle* handle, uint32_t key)
100 {
101 	int ret;
102 	uint16_t status;
103 
104 	ret = SEND_KEY(handle, (uint16_t)key);
105 	if (!ret)
106 	{
107 		ret = RECV_ACK(handle, &status);
108 
109 		PAUSE(50);
110 	}
111 
112 	return ret;
113 }
114 
go_to_homescreen(CalcHandle * handle)115 static int go_to_homescreen(CalcHandle * handle)
116 {
117 	int ret;
118 
119 	PAUSE(200);
120 	if (handle->model == CALC_TI89 || handle->model == CALC_TI89T)
121 	{
122 		ret = send_key(handle, KEY89_HOME);
123 		if (!ret)
124 		{
125 			ret = send_key(handle, KEY89_CLEAR);
126 			if (!ret)
127 			{
128 				ret = send_key(handle, KEY89_CLEAR);
129 			}
130 		}
131 	}
132 	else if (handle->model == CALC_TI92 || handle->model == CALC_TI92P || handle->model == CALC_V200)
133 	{
134 		ret = send_key(handle, KEY92P_CTRL + KEY92P_Q);
135 		if (!ret)
136 		{
137 			ret = send_key(handle, KEY92P_CLEAR);
138 			if (!ret)
139 			{
140 				ret = send_key(handle, KEY92P_CLEAR);
141 			}
142 		}
143 	}
144 	else
145 	{
146 		ret = ERR_VOID_FUNCTION;
147 	}
148 
149 	return ret;
150 }
151 
execute(CalcHandle * handle,VarEntry * ve,const char * args)152 static int		execute		(CalcHandle* handle, VarEntry *ve, const char* args)
153 {
154 	int ret = 0;
155 
156 	if (ve->type == TI89_APPL)
157 	{
158 		return ERR_VOID_FUNCTION;
159 	}
160 
161 	ret = go_to_homescreen(handle);
162 
163 	if (!ret)
164 	{
165 		unsigned int i;
166 		// Launch program by remote control
167 		for (i = 0; !ret && i < strlen(ve->folder); i++)
168 		{
169 			ret = send_key(handle, (uint32_t)(uint8_t)((ve->folder)[i]));
170 		}
171 
172 		if (!ret && strcmp(ve->folder, ""))
173 		{
174 			ret = send_key(handle, (uint32_t)'\\');
175 		}
176 
177 		for (i = 0; !ret && i < strlen(ve->name); i++)
178 		{
179 			ret = send_key(handle, (uint32_t)(uint8_t)((ve->name)[i]));
180 		}
181 
182 		if (!ret)
183 		{
184 			ret = send_key(handle, KEY89_LP);
185 			if (!ret)
186 			{
187 				if (args)
188 				{
189 					for (i = 0; !ret && i < strlen(args); i++)
190 					{
191 						ret = send_key(handle, (uint32_t)(uint8_t)(args[i]));
192 					}
193 				}
194 				if (!ret)
195 				{
196 					ret = send_key(handle, KEY89_RP);
197 					if (!ret)
198 					{
199 						ret = send_key(handle, KEY89_ENTER);
200 
201 						PAUSE(200);
202 					}
203 				}
204 			}
205 		}
206 	}
207 
208 	return ret;
209 }
210 
recv_screen(CalcHandle * handle,CalcScreenCoord * sc,uint8_t ** bitmap)211 static int		recv_screen	(CalcHandle* handle, CalcScreenCoord* sc, uint8_t** bitmap)
212 {
213 	int ret;
214 
215 	*bitmap = (uint8_t *)ticalcs_alloc_screen(65537U);
216 	if (*bitmap == NULL)
217 	{
218 		return ERR_MALLOC;
219 	}
220 
221 	sc->width = TI89_COLS;
222 	sc->height = TI89_ROWS;
223 	if (handle->model == CALC_TI89 || handle->model == CALC_TI89T)
224 	{
225 		sc->clipped_width = TI89_COLS_VISIBLE;
226 		sc->clipped_height = TI89_ROWS_VISIBLE;
227 	}
228 	else
229 	{
230 		sc->clipped_width = TI89_COLS;
231 		sc->clipped_height = TI89_ROWS;
232 	}
233 	sc->pixel_format = CALC_PIXFMT_MONO;
234 
235 	ret = SEND_SCR(handle);
236 	if (!ret)
237 	{
238 		ret = RECV_ACK(handle, NULL);
239 		if (!ret)
240 		{
241 			uint16_t max_cnt;
242 			ret = RECV_XDP(handle, &max_cnt, *bitmap);
243 			if (!ret || ret == ERR_CHECKSUM) // problem with checksum
244 			{
245 				// Clip the unused part of the screen (nevertheless usable with asm programs)
246 				if (   ((handle->model == CALC_TI89) || (handle->model == CALC_TI89T))
247 				    && (sc->format == SCREEN_CLIPPED))
248 				{
249 					int i, j, k;
250 
251 					for (i = 0, j = 0; j < TI89_ROWS_VISIBLE; j++)
252 					{
253 						for (k = 0; k < (TI89_COLS_VISIBLE >> 3); k++)
254 						{
255 							(*bitmap)[i++] = (*bitmap)[j * (TI89_COLS >> 3) + k];
256 						}
257 					}
258 				}
259 
260 				*bitmap = ticalcs_realloc_screen(*bitmap, TI89_COLS * TI89_ROWS / 8);
261 				ret = SEND_ACK(handle);
262 			}
263 		}
264 	}
265 
266 	if (ret)
267 	{
268 		ticalcs_free_screen(*bitmap);
269 		*bitmap = NULL;
270 	}
271 
272 	return ret;
273 }
274 
get_dirlist(CalcHandle * handle,GNode ** vars,GNode ** apps)275 static int		get_dirlist	(CalcHandle* handle, GNode** vars, GNode** apps)
276 {
277 	VarEntry info;
278 	uint16_t block_size;
279 	uint8_t * buffer = handle->buffer2;
280 	int ret;
281 	int i, j;
282 	uint8_t extra = (handle->model == CALC_V200) ? 8 : 0;
283 	GNode *root, *node = NULL;
284 
285 	ret = dirlist_init_trees(handle, vars, apps);
286 	if (ret)
287 	{
288 		return ret;
289 	}
290 
291 	root = dirlist_create_append_node(NULL, apps);
292 	if (!root)
293 	{
294 		return ERR_MALLOC;
295 	}
296 
297 	ret = SEND_REQ(handle, ((uint32_t)TI89_FDIR) << 24, TI89_RDIR, "\0\0\0\0\0\0\0");
298 	if (!ret)
299 	{
300 		ret = RECV_ACK(handle, NULL);
301 		if (!ret)
302 		{
303 			ret = RECV_VAR(handle, &info.size, &info.type, info.name);
304 			if (!ret)
305 			{
306 				ret = SEND_ACK(handle);
307 				if (!ret)
308 				{
309 					ret = SEND_CTS(handle);
310 					if (!ret)
311 					{
312 						ret = RECV_ACK(handle, NULL);
313 						if (!ret)
314 						{
315 							ret = RECV_XDP(handle, &block_size, buffer);
316 							if (!ret)
317 							{
318 								ret = SEND_ACK(handle);
319 								if (!ret)
320 								{
321 									ret = RECV_EOT(handle);
322 									if (!ret)
323 									{
324 										ret = SEND_ACK(handle);
325 									}
326 								}
327 							}
328 						}
329 					}
330 				}
331 			}
332 		}
333 	}
334 	if (ret)
335 	{
336 		return ret;
337 	}
338 
339 	for (j = 4; j < (int)block_size;)
340 	{
341 		VarEntry *fe = tifiles_ve_create();
342 
343 		memcpy(fe->name, buffer + j, 8);
344 		fe->name[8] = '\0';
345 		fe->type = buffer[j + 8];
346 		fe->attr = buffer[j + 9];
347 		fe->size = (  (((uint32_t)buffer[j + 10])      )
348 		            | (((uint32_t)buffer[j + 11]) <<  8)
349 		            | (((uint32_t)buffer[j + 12]) << 16)); // | (((uint32_t)buffer[j + 13]) << 24);
350 		j += 14 + extra;
351 		fe->folder[0] = 0;
352 
353 		ticalcs_info(_("Name: %8s | Type: %8s | Attr: %i  | Size: %08X"),
354 			fe->name,
355 			tifiles_vartype2string(handle->model, fe->type),
356 			fe->attr,
357 			fe->size);
358 
359 		if (fe->type == TI89_DIR)
360 		{
361 			node = dirlist_create_append_node(fe, vars);
362 			if (!node)
363 			{
364 				break;
365 			}
366 		}
367 		else if (fe->type == TI89_APPL)
368 		{
369 			// AMS<2.08 returns FLASH apps
370 			continue;
371 		}
372 	}
373 
374 	if (!node)
375 	{
376 		return ERR_MALLOC;
377 	}
378 
379 	// get list of variables into each folder
380 	for (i = 0; i < (int)g_node_n_children(*vars); i++)
381 	{
382 		GNode *folder = g_node_nth_child(*vars, i);
383 		char *folder_name = ((VarEntry *) (folder->data))->name;
384 		char *u1, *u2;
385 
386 		ticalcs_info(_("Directory listing in %8s..."), folder_name);
387 
388 		ret = SEND_REQ(handle, ((uint32_t)TI89_LDIR) << 24, TI89_RDIR, folder_name);
389 		if (!ret)
390 		{
391 			ret = RECV_ACK(handle, NULL);
392 			if (!ret)
393 			{
394 				ret = RECV_VAR(handle, &info.size, &info.type, info.name);
395 				if (!ret)
396 				{
397 					ret = SEND_ACK(handle);
398 					if (!ret)
399 					{
400 						ret = SEND_CTS(handle);
401 						if (!ret)
402 						{
403 							ret = RECV_ACK(handle, NULL);
404 							if (!ret)
405 							{
406 								ret = RECV_XDP(handle, &block_size, buffer);
407 								if (!ret)
408 								{
409 									ret = SEND_ACK(handle);
410 									if (!ret)
411 									{
412 										ret = RECV_EOT(handle);
413 										if (!ret)
414 										{
415 											ret = SEND_ACK(handle);
416 										}
417 									}
418 								}
419 							}
420 						}
421 					}
422 				}
423 			}
424 		}
425 		if (!ret)
426 		{
427 			for (j = 4 + 14 + extra; j < (int)block_size;)
428 			{
429 				VarEntry *ve = tifiles_ve_create();
430 
431 				memcpy(ve->name, buffer + j, 8);
432 				ve->name[8] = '\0';
433 				ve->type = buffer[j + 8];
434 				ve->attr = buffer[j + 9];
435 				ve->size = (  (((uint32_t)buffer[j + 10])      )
436 					    | (((uint32_t)buffer[j + 11]) <<  8)
437 					    | (((uint32_t)buffer[j + 12]) << 16)); // | (((uint32_t)buffer[j + 13]) << 24);
438 				j += 14 + extra;
439 				ticalcs_strlcpy(ve->folder, folder_name, sizeof(ve->folder));
440 
441 				ticalcs_info(_("Name: %8s | Type: %8s | Attr: %i  | Size: %08X"),
442 				ve->name,
443 				tifiles_vartype2string(handle->model, ve->type),
444 				ve->attr,
445 				ve->size);
446 
447 				u1 = ticonv_varname_to_utf8(handle->model, ((VarEntry *) (folder->data))->name, -1);
448 				u2 = ticonv_varname_to_utf8(handle->model, ve->name, ve->type);
449 				ticalcs_slprintf(update_->text, sizeof(update_->text), _("Parsing %s/%s"), u1, u2);
450 				ticonv_utf8_free(u2);
451 				ticonv_utf8_free(u1);
452 				update_label();
453 
454 				if (ve->type == TI89_APPL)
455 				{
456 					VarEntry arg;
457 
458 					memset(&arg, 0, sizeof(arg));
459 					ticalcs_strlcpy(arg.name, ve->name, sizeof(arg.name));
460 					if (!ticalcs_dirlist_ve_exist(*apps, &arg))
461 					{
462 						ve->folder[0] = 0;
463 						node = dirlist_create_append_node(ve, &root);
464 						if (!node)
465 						{
466 							return ERR_MALLOC;
467 						}
468 					}
469 				}
470 				else
471 				{
472 					if (!strcmp(ve->folder, "main") && (!strcmp(ve->name, "regcoef") || !strcmp(ve->name, "regeq")))
473 					{
474 						tifiles_ve_delete(ve);
475 					}
476 					else
477 					{
478 						node = dirlist_create_append_node(ve, &folder);
479 						if (!node)
480 						{
481 							return ERR_MALLOC;
482 						}
483 					}
484 				}
485 			}
486 
487 			ticalcs_info(" ");
488 		}
489 	}
490 
491 	return ret;
492 }
493 
get_dirlist_92(CalcHandle * handle,GNode ** vars,GNode ** apps)494 static int		get_dirlist_92	(CalcHandle* handle, GNode** vars, GNode** apps)
495 {
496 	VarEntry info;
497 	int ret;
498 
499 	ret = dirlist_init_trees(handle, vars, apps);
500 	if (!ret)
501 	{
502 		ret = SEND_REQ(handle, 0, TI92_RDIR, "\0\0\0\0\0\0\0");
503 		if (!ret)
504 		{
505 			ret = RECV_ACK(handle, NULL);
506 			if (!ret)
507 			{
508 				ret = RECV_VAR(handle, &info.size, &info.type, info.name);
509 			}
510 		}
511 	}
512 	if (ret)
513 	{
514 		return ret;
515 	}
516 
517 	for (;;)
518 	{
519 		VarEntry *ve;
520 		GNode *folder = NULL;
521 		char folder_name[9];
522 		char *utf8;
523 		uint8_t * buffer = handle->buffer2;
524 		uint16_t unused;
525 
526 		folder_name[8] = 0;
527 
528 		ret = SEND_ACK(handle);
529 		if (!ret)
530 		{
531 			ret = SEND_CTS(handle);
532 			if (!ret)
533 			{
534 				ret = RECV_ACK(handle, NULL);
535 				if (!ret)
536 				{
537 					ret = RECV_XDP(handle, &unused, buffer);
538 				}
539 			}
540 		}
541 		if (ret)
542 		{
543 			break;
544 		}
545 
546 		ve = tifiles_ve_create();
547 		memcpy(ve->name, buffer + 4, 8);	// skip 4 extra 00s
548 		ve->name[8] = '\0';
549 		ve->type = buffer[12];
550 		ve->attr = buffer[13];
551 		ve->size = buffer[14] | (((uint32_t)buffer[15]) << 8) | (((uint32_t)buffer[16]) << 16) | (((uint32_t)buffer[17]) << 24);
552 		ve->folder[0] = 0;
553 
554 		if (ve->type == TI92_DIR)
555 		{
556 			ticalcs_strlcpy(folder_name, ve->name, sizeof(folder_name));
557 			folder = dirlist_create_append_node(ve, vars);
558 		}
559 		else
560 		{
561 			ticalcs_strlcpy(ve->folder, folder_name, sizeof(ve->folder));
562 
563 			if (!strcmp(ve->folder, "main") && (!strcmp(ve->name, "regcoef") || !strcmp(ve->name, "regeq")))
564 			{
565 				tifiles_ve_delete(ve);
566 				ve = NULL;
567 			}
568 			else
569 			{
570 				GNode *node = dirlist_create_append_node(ve, &folder);
571 				if (node == NULL)
572 				{
573 					return ERR_MALLOC;
574 				}
575 			}
576 		}
577 
578 		if (ve != NULL)
579 		{
580 			ticalcs_info(_("Name: %8s | Type: %8s | Attr: %i  | Size: %08X"),
581 				ve->name,
582 				tifiles_vartype2string(handle->model, ve->type),
583 				ve->attr,
584 				ve->size);
585 		}
586 
587 		ret = SEND_ACK(handle);
588 		if (!ret)
589 		{
590 			ret = RECV_CNT(handle);
591 			if (ret)
592 			{
593 				if (ret == ERR_EOT)
594 				{
595 					ret = SEND_ACK(handle);
596 				}
597 				break;
598 			}
599 		}
600 
601 		if (ve != NULL && folder != NULL)
602 		{
603 			utf8 = ticonv_varname_to_utf8(handle->model, ve->name, ve->type);
604 			ticalcs_slprintf(update_->text, sizeof(update_->text), _("Parsing %s/%s"), ((VarEntry *) (folder->data))->name, utf8);
605 			ticonv_utf8_free(utf8);
606 			update_->label();
607 		}
608 	}
609 
610 	return ret;
611 }
612 
get_memfree(CalcHandle * handle,uint32_t * ram,uint32_t * flash)613 static int		get_memfree	(CalcHandle* handle, uint32_t* ram, uint32_t *flash)
614 {
615 	(void)handle;
616 	*ram = *flash = -1;
617 	return 0;
618 }
619 
send_backup(CalcHandle * handle,BackupContent * content)620 static int		send_backup	(CalcHandle* handle, BackupContent* content)
621 {
622 	int ret;
623 	unsigned int i;
624 	unsigned int nblocks;
625 
626 	ret = SEND_VAR(handle, content->data_length, TI92_BKUP, content->rom_version);
627 	if (!ret)
628 	{
629 		ret = RECV_ACK(handle, NULL);
630 		if (!ret)
631 		{
632 			update_->cnt2 = 0;
633 			nblocks = content->data_length / 1024;
634 			handle->updat->max2 = nblocks;
635 
636 			for (i = 0; !ret && i <= nblocks; i++)
637 			{
638 				uint32_t length = (i != nblocks) ? 1024 : content->data_length % 1024;
639 
640 				ret = SEND_VAR(handle, length, TI92_BKUP, content->rom_version);
641 				if (!ret)
642 				{
643 					ret = RECV_ACK(handle, NULL);
644 					if (!ret)
645 					{
646 						ret = RECV_CTS(handle);
647 						if (!ret)
648 						{
649 							ret = SEND_ACK(handle);
650 							if (!ret)
651 							{
652 								ret = SEND_XDP(handle, length, content->data_part + 1024 * i);
653 								if (!ret)
654 								{
655 									ret = RECV_ACK(handle, NULL);
656 								}
657 							}
658 						}
659 					}
660 				}
661 
662 				handle->updat->cnt2 = i;
663 				update_pbar();
664 			}
665 
666 			if (!ret)
667 			{
668 				ret = SEND_EOT(handle);
669 			}
670 		}
671 	}
672 
673 	return ret;
674 }
675 
recv_backup(CalcHandle * handle,BackupContent * content)676 static int		recv_backup	(CalcHandle* handle, BackupContent* content)
677 {
678 	uint32_t block_size;
679 	int block, ret = 0;
680 	uint16_t unused;
681 	uint8_t *ptr;
682 
683 	ret = SEND_REQ(handle, 0, TI92_BKUP, "main\\backup");
684 	if (!ret)
685 	{
686 		ret = RECV_ACK(handle, &unused);
687 		if (!ret)
688 		{
689 			content->model = CALC_TI92;
690 			ticalcs_strlcpy(content->comment, tifiles_comment_set_backup(), sizeof(content->comment));
691 			content->data_part = tifiles_ve_alloc_data(128 * 1024);
692 			content->type = TI92_BKUP;
693 			content->data_length = 0;
694 
695 			for (block = 0; !ret; block++)
696 			{
697 				int ret2;
698 
699 				ticalcs_slprintf(update_->text, sizeof(update_->text), _("Block #%2i"), block);
700 				update_label();
701 
702 				ret = RECV_VAR(handle, &block_size, &content->type, content->rom_version);
703 				ret2 = SEND_ACK(handle);
704 
705 				if (ret)
706 				{
707 					if (ret == ERR_EOT)
708 					{
709 						ret = 0;
710 					}
711 					break;
712 				}
713 				if (ret2)
714 				{
715 					ret = ret2;
716 					break;
717 				}
718 
719 				ret = SEND_CTS(handle);
720 				if (!ret)
721 				{
722 					ret = RECV_ACK(handle, NULL);
723 					if (!ret)
724 					{
725 						ptr = content->data_part + content->data_length;
726 						ret = RECV_XDP(handle, &unused, ptr);
727 						if (!ret)
728 						{
729 							memmove(ptr, ptr + 4, block_size);
730 							ret = SEND_ACK(handle);
731 							if (!ret)
732 							{
733 								content->data_length += block_size;
734 							}
735 						}
736 					}
737 				}
738 			}
739 		}
740 	}
741 
742 	return ret;
743 }
744 
send_var(CalcHandle * handle,CalcMode mode,FileContent * content)745 static int		send_var	(CalcHandle* handle, CalcMode mode, FileContent* content)
746 {
747 	int ret = 0;
748 	unsigned int i;
749 	uint16_t status;
750 
751 	update_->cnt2 = 0;
752 	update_->max2 = content->num_entries;
753 
754 	for (i = 0; !ret && i < content->num_entries; i++)
755 	{
756 		VarEntry *entry;
757 		uint8_t * buffer = handle->buffer2;
758 		uint8_t vartype;
759 		char varname[18];
760 		uint32_t size;
761 
762 		entry = content->entries[i];
763 		if (!ticalcs_validate_varentry(entry))
764 		{
765 			ticalcs_critical("%s: skipping invalid content entry #%u", __FUNCTION__, i);
766 			continue;
767 		}
768 
769 		vartype = entry->type;
770 
771 		if (entry->action == ACT_SKIP)
772 		{
773 			continue;
774 		}
775 
776 		if ((mode & MODE_LOCAL_PATH) && !(mode & MODE_BACKUP))
777 		{
778 			// local & not backup
779 			ticalcs_strlcpy(varname, entry->name, sizeof(varname));
780 		}
781 		else
782 		{
783 			// full or backup
784 			tifiles_build_fullname(handle->model, varname, entry->folder, entry->name);
785 		}
786 
787 		ticonv_varname_to_utf8_sn(handle->model, varname, update_->text, sizeof(update_->text), vartype);
788 		update_label();
789 
790 		switch (entry->attr)
791 		{
792 		//case ATTRB_NONE:     vartype = TI89_BKUP; break;
793 		case ATTRB_LOCKED:   vartype = 0x26; break;
794 		case ATTRB_PROTECTED:
795 		case ATTRB_ARCHIVED: vartype = 0x27; break;
796 		}
797 
798 		size = entry->size;
799 		if (size >= 65536U)
800 		{
801 			ticalcs_critical("%s: oversized variable has size %u, clamping to 65535", __FUNCTION__, size);
802 			size = 65535;
803 		}
804 
805 		ret = SEND_RTS(handle, size, vartype, varname);
806 		if (!ret)
807 		{
808 			ret = RECV_ACK(handle, NULL);
809 			if (!ret)
810 			{
811 				ret = RECV_CTS(handle);
812 				if (!ret)
813 				{
814 					ret = SEND_ACK(handle);
815 					if (!ret)
816 					{
817 						buffer[0] = 0;
818 						buffer[1] = 0;
819 						buffer[2] = 0;
820 						buffer[3] = 0;
821 						memcpy(buffer + 4, entry->data, size);
822 						ret = SEND_XDP(handle, size + 4, buffer);
823 						if (!ret)
824 						{
825 							ret = RECV_ACK(handle, &status);
826 							if (!ret)
827 							{
828 								ret = SEND_EOT(handle);
829 								if (!ret)
830 								{
831 									ret = RECV_ACK(handle, NULL);
832 									if (!ret)
833 									{
834 										ticalcs_info("Sent variable #%u", i);
835 										update_->cnt2 = i+1;
836 										update_->max2 = content->num_entries;
837 										update_->pbar();
838 									}
839 								}
840 							}
841 						}
842 					}
843 				}
844 			}
845 		}
846 	}
847 
848 	return ret;
849 }
850 
recv_var(CalcHandle * handle,CalcMode mode,FileContent * content,VarRequest * vr)851 static int		recv_var	(CalcHandle* handle, CalcMode mode, FileContent* content, VarRequest* vr)
852 {
853 	int ret = 0;
854 	uint16_t status;
855 	VarEntry *ve;
856 	uint16_t unused;
857 	char varname[20];
858 
859 	content->model = handle->model;
860 	ve = tifiles_ve_create();
861 	memcpy(ve, vr, sizeof(VarEntry));
862 
863 	tifiles_build_fullname(handle->model, varname, vr->folder, vr->name);
864 	ticonv_varname_to_utf8_sn(handle->model, varname, update_->text, sizeof(update_->text), vr->type);
865 	update_label();
866 
867 	ret = SEND_REQ(handle, 0, vr->type, varname);
868 	if (!ret)
869 	{
870 		ret = RECV_ACK(handle, &status);
871 		if (!ret)
872 		{
873 			if (status != 0)
874 			{
875 				return ERR_MISSING_VAR;
876 			}
877 
878 			ret = RECV_VAR(handle, &ve->size, &ve->type, ve->name);
879 			if (!ret)
880 			{
881 				ret = SEND_ACK(handle);
882 				if (!ret)
883 				{
884 					ret = SEND_CTS(handle);
885 					if (!ret)
886 					{
887 						ret = RECV_ACK(handle, NULL);
888 						if (!ret)
889 						{
890 							ve->data = tifiles_ve_alloc_data(ve->size + 4);
891 							ret = RECV_XDP(handle, &unused, ve->data);
892 							if (!ret)
893 							{
894 								memmove(ve->data, ve->data + 4, ve->size);
895 								ret = SEND_ACK(handle);
896 								if (!ret)
897 								{
898 									ret = RECV_EOT(handle);
899 									if (!ret)
900 									{
901 										ret = SEND_ACK(handle);
902 										if (!ret)
903 										{
904 											PAUSE(250);
905 											tifiles_content_add_entry(content, ve);
906 										}
907 									}
908 								}
909 							}
910 						}
911 					}
912 				}
913 			}
914 		}
915 	}
916 
917 	return ret;
918 }
919 
send_all_vars_backup(CalcHandle * handle,FileContent * content)920 static int		send_all_vars_backup	(CalcHandle* handle, FileContent* content)
921 {
922 	int ret;
923 
924 	// erase memory
925 	ret = SEND_VAR(handle, 0, TI89_BKUP, "main");
926 	if (!ret)
927 	{
928 		ret = RECV_ACK(handle, NULL);
929 		if (!ret)
930 		{
931 			ret = RECV_CTS(handle);
932 			if (!ret)
933 			{
934 				ret = SEND_ACK(handle);
935 				if (!ret)
936 				{
937 					ret = SEND_EOT(handle);
938 					if (!ret)
939 					{
940 						ret = RECV_ACK(handle, NULL);
941 						if (!ret)
942 						{
943 							// next, send var(s)
944 							ret = send_var(handle, MODE_BACKUP, content);
945 						}
946 					}
947 				}
948 			}
949 		}
950 	}
951 
952 	return ret;
953 }
954 
send_var_ns(CalcHandle * handle,CalcMode mode,FileContent * content)955 static int		send_var_ns	(CalcHandle* handle, CalcMode mode, FileContent* content)
956 {
957 	int ret = 0;
958 	unsigned int i;
959 	uint16_t status;
960 
961 	update_->cnt2 = 0;
962 	update_->max2 = content->num_entries;
963 
964 	for (i = 0; !ret && i < content->num_entries; i++)
965 	{
966 		VarEntry *entry;
967 		uint8_t * buffer = handle->buffer2;
968 		uint8_t vartype;
969 		char varname[18];
970 		uint32_t size;
971 
972 		entry = content->entries[i];
973 		if (!ticalcs_validate_varentry(entry))
974 		{
975 			ticalcs_critical("%s: skipping invalid content entry #%u", __FUNCTION__, i);
976 			continue;
977 		}
978 
979 		vartype = entry->type;
980 
981 		if (entry->action == ACT_SKIP)
982 		{
983 			ticalcs_info("%s: skipping variable #%u because requested", __FUNCTION__, i);
984 			continue;
985 		}
986 
987 		if ((mode & MODE_LOCAL_PATH) && ((handle->model == CALC_TI92) || !(mode & MODE_BACKUP)))
988 		{
989 			// local & not backup
990 			ticalcs_strlcpy(varname, entry->name, sizeof(varname));
991 		}
992 		else
993 		{
994 			// full or backup
995 			tifiles_build_fullname(handle->model, varname, entry->folder, entry->name);
996 		}
997 
998 		ticonv_varname_to_utf8_sn(handle->model, varname, update_->text, sizeof(update_->text), vartype);
999 		update_label();
1000 
1001 		size = entry->size;
1002 		if (size >= 65536U)
1003 		{
1004 			ticalcs_critical("%s: oversized variable has size %u, clamping to 65535", __FUNCTION__, size);
1005 			size = 65535;
1006 		}
1007 
1008 		ret = SEND_VAR(handle, size, vartype, varname);
1009 		if (!ret)
1010 		{
1011 			ret = RECV_ACK(handle, NULL);
1012 			if (!ret)
1013 			{
1014 				ret = RECV_CTS(handle);
1015 				if (!ret)
1016 				{
1017 					ret = SEND_ACK(handle);
1018 					if (!ret)
1019 					{
1020 						buffer[0] = 0;
1021 						buffer[1] = 0;
1022 						buffer[2] = 0;
1023 						buffer[3] = 0;
1024 						memcpy(buffer + 4, entry->data, size);
1025 						ret = SEND_XDP(handle, size + 4, buffer);
1026 						if (!ret)
1027 						{
1028 							ret = RECV_ACK(handle, &status);
1029 							if (!ret)
1030 							{
1031 								ret = SEND_EOT(handle);
1032 								if (!ret)
1033 								{
1034 									ret = RECV_ACK(handle, NULL);
1035 									if (!ret)
1036 									{
1037 										ticalcs_info("Sent variable #%u", i);
1038 
1039 										if (mode & MODE_BACKUP || handle->model == CALC_TI92)
1040 										{
1041 											update_->cnt2 = i+1;
1042 											update_->max2 = content->num_entries;
1043 											update_->pbar();
1044 										}
1045 									}
1046 								}
1047 							}
1048 						}
1049 					}
1050 				}
1051 			}
1052 		}
1053 	}
1054 
1055 	return ret;
1056 }
1057 
recv_var_ns(CalcHandle * handle,CalcMode mode,FileContent * content,VarEntry ** vr)1058 static int		recv_var_ns	(CalcHandle* handle, CalcMode mode, FileContent* content, VarEntry** vr)
1059 {
1060 	uint16_t unused;
1061 	int nvar, ret = 0;
1062 	char tipath[18];
1063 	char *tiname;
1064 
1065 	content->model = handle->model;
1066 	content->num_entries = 0;
1067 
1068 	// receive packets
1069 	for (nvar = 0;; nvar++)
1070 	{
1071 		VarEntry *ve = tifiles_ve_create();
1072 		int ret2;
1073 
1074 		ticalcs_strlcpy(ve->folder, "main", sizeof(ve->folder));
1075 
1076 		ret = RECV_VAR(handle, &ve->size, &ve->type, tipath);
1077 		ret2 = SEND_ACK(handle);
1078 
1079 		if (ret)
1080 		{
1081 			if (ret == ERR_EOT)	// end of transmission
1082 			{
1083 				ret = 0;
1084 			}
1085 			goto error;
1086 		}
1087 		if (ret2)
1088 		{
1089 			ret = ret2;
1090 			goto error;
1091 		}
1092 
1093 		// from Christian (calculator can send varname or fldname/varname)
1094 		if ((tiname = strchr(tipath, '\\')) != NULL)
1095 		{
1096 			*tiname = '\0';
1097 			ticalcs_strlcpy(ve->folder, tipath, sizeof(ve->folder));
1098 			ticalcs_strlcpy(ve->name, tiname + 1, sizeof(ve->name));
1099 		}
1100 		else
1101 		{
1102 			ticalcs_strlcpy(ve->folder, "main", sizeof(ve->folder));
1103 			ticalcs_strlcpy(ve->name, tipath, sizeof(ve->name));
1104 		}
1105 
1106 		ticonv_varname_to_utf8_sn(handle->model, ve->name, update_->text, sizeof(update_->text), ve->type);
1107 		update_label();
1108 
1109 		ret = SEND_CTS(handle);
1110 		if (!ret)
1111 		{
1112 			ret = RECV_ACK(handle, NULL);
1113 			if (!ret)
1114 			{
1115 				ve->data = tifiles_ve_alloc_data(ve->size + 4);
1116 				ret = RECV_XDP(handle, &unused, ve->data);
1117 				if (!ret)
1118 				{
1119 					memmove(ve->data, ve->data + 4, ve->size);
1120 					ret = SEND_ACK(handle);
1121 				}
1122 			}
1123 		}
1124 
1125 		if (!ret)
1126 		{
1127 			tifiles_content_add_entry(content, ve);
1128 		}
1129 		else
1130 		{
1131 error:
1132 			tifiles_ve_delete(ve);
1133 			break;
1134 		}
1135 	}
1136 
1137 	if (nvar > 1)
1138 	{
1139 		*vr = NULL;
1140 	}
1141 	else
1142 	{
1143 		*vr = tifiles_ve_dup(content->entries[0]);
1144 	}
1145 
1146 	return ret;
1147 }
1148 
send_flash(CalcHandle * handle,FlashContent * content)1149 static int		send_flash	(CalcHandle* handle, FlashContent* content)
1150 {
1151 	int ret = 0;
1152 	FlashContent *ptr;
1153 	int i, nblocks;
1154 
1155 	// send all headers except license
1156 	for (ptr = content; !ret && ptr != NULL; ptr = ptr->next)
1157 	{
1158 		if (ptr->data_type == TI89_LICENSE)
1159 		{
1160 			continue;
1161 		}
1162 
1163 		ticalcs_info(_("FLASH name: \"%s\""), ptr->name);
1164 		ticalcs_info(_("FLASH size: %i bytes."), ptr->data_length);
1165 
1166 		ticonv_varname_to_utf8_sn(handle->model, ptr->name, update_->text, sizeof(update_->text), ptr->data_type);
1167 		update_label();
1168 
1169 		if (ptr->data_type == TI89_AMS)
1170 		{
1171 			if (handle->model == CALC_TI89T || handle->model == CALC_V200)
1172 			{
1173 				ret = SEND_RTS2(handle, ptr->data_length, ptr->data_type, ptr->hw_id);
1174 			}
1175 			else
1176 			{
1177 				ret = SEND_RTS(handle, ptr->data_length, ptr->data_type, "\0\0\0\0\0\0\0");
1178 			}
1179 		}
1180 		else
1181 		{
1182 			ret = SEND_RTS(handle, ptr->data_length, ptr->data_type, ptr->name);
1183 		}
1184 
1185 		if (!ret)
1186 		{
1187 			nblocks = ptr->data_length / 65536;
1188 			update_->max2 = nblocks+1;
1189 
1190 			for (i = 0; !ret && i <= nblocks; i++)
1191 			{
1192 				uint32_t length = (i != nblocks) ? 65536 : ptr->data_length % 65536;
1193 
1194 				ret = RECV_ACK(handle, NULL);
1195 				if (!ret)
1196 				{
1197 					ret = RECV_CTS(handle);
1198 					if (!ret)
1199 					{
1200 						ret = SEND_ACK(handle);
1201 						if (!ret)
1202 						{
1203 							ret = SEND_XDP(handle, length, (ptr->data_part) + 65536 * i);
1204 							if (!ret)
1205 							{
1206 								ret = RECV_ACK(handle, NULL);
1207 								if (!ret)
1208 								{
1209 									if (i != nblocks)
1210 									{
1211 										ret = SEND_CNT(handle);
1212 									}
1213 									else
1214 									{
1215 										ret = SEND_EOT(handle);
1216 									}
1217 
1218 									update_->cnt2 = i;
1219 									update_->pbar();
1220 								}
1221 							}
1222 						}
1223 					}
1224 				}
1225 			}
1226 
1227 			if (!ret)
1228 			{
1229 				ret = RECV_ACK(handle, NULL);
1230 				ticalcs_info(_("Header sent completely."));
1231 			}
1232 		}
1233 	}
1234 
1235 	return ret;
1236 }
1237 
recv_flash(CalcHandle * handle,FlashContent * content,VarRequest * vr)1238 static int		recv_flash	(CalcHandle* handle, FlashContent* content, VarRequest* vr)
1239 {
1240 	int ret;
1241 	int i;
1242 	ticonv_varname_to_utf8_sn(handle->model, vr->name, update_->text, sizeof(update_->text), vr->type);
1243 	update_label();
1244 
1245 	content->model = handle->model;
1246 	content->data_part = (uint8_t *)tifiles_ve_alloc_data(4 * 1024 * 1024);	// 4MB max
1247 	content->data_type = vr->type;
1248 	switch(handle->model)
1249 	{
1250 	case CALC_TI89:
1251 	case CALC_TI89T: content->device_type = DEVICE_TYPE_89; break;
1252 	case CALC_TI92P:
1253 	case CALC_V200:  content->device_type = DEVICE_TYPE_92P; break;
1254 	default: return ERR_FATAL_ERROR;
1255 	}
1256 
1257 	ret = SEND_REQ(handle, 0x00, vr->type, vr->name);
1258 	if (!ret)
1259 	{
1260 		ret = RECV_ACK(handle, NULL);
1261 		if (!ret)
1262 		{
1263 			ret = RECV_VAR(handle, &content->data_length, &content->data_type, content->name);
1264 			if (!ret)
1265 			{
1266 
1267 				update_->cnt2 = 0;
1268 				update_->max2 = vr->size;
1269 
1270 				for (i = 0, content->data_length = 0; !ret; i++)
1271 				{
1272 					uint16_t block_size;
1273 
1274 					ret = SEND_ACK(handle);
1275 					if (!ret)
1276 					{
1277 						ret = SEND_CTS(handle);
1278 						if (!ret)
1279 						{
1280 							ret = RECV_ACK(handle, NULL);
1281 							if (!ret)
1282 							{
1283 								ret = RECV_XDP(handle, &block_size, content->data_part + content->data_length);
1284 								if (!ret)
1285 								{
1286 									ret = SEND_ACK(handle);
1287 									if (!ret)
1288 									{
1289 										content->data_length += block_size;
1290 
1291 										ret  = RECV_CNT(handle);
1292 										if (ret)
1293 										{
1294 											if (ret  == ERR_EOT)
1295 											{
1296 												ret = 0;
1297 											}
1298 											break;
1299 										}
1300 
1301 										update_->cnt2 += block_size;
1302 										update_->pbar();
1303 									}
1304 								}
1305 							}
1306 						}
1307 					}
1308 				}
1309 
1310 				if (!ret)
1311 				{
1312 					ret = SEND_ACK(handle);
1313 				}
1314 			}
1315 		}
1316 	}
1317 
1318 	return ret;
1319 }
1320 
recv_idlist(CalcHandle * handle,uint8_t * idlist)1321 static int		recv_idlist	(CalcHandle* handle, uint8_t* idlist)
1322 {
1323 	int ret;
1324 	uint32_t varsize;
1325 	uint16_t pktsize;
1326 	uint8_t vartype;
1327 	char varname[9];
1328 
1329 	ticalcs_strlcpy(update_->text, "ID-LIST", sizeof(update_->text));
1330 	update_label();
1331 
1332 	ret = SEND_REQ(handle, 0x0000, TI89_IDLIST, "\0\0\0\0\0\0\0");
1333 	if (!ret)
1334 	{
1335 		ret = RECV_ACK(handle, NULL);
1336 		if (!ret)
1337 		{
1338 			ret = RECV_VAR(handle, &varsize, &vartype, varname);
1339 			if (!ret)
1340 			{
1341 				ret = SEND_ACK(handle);
1342 				if (!ret)
1343 				{
1344 					ret = SEND_CTS(handle);
1345 					if (!ret)
1346 					{
1347 						ret = RECV_ACK(handle, NULL);
1348 						if (!ret)
1349 						{
1350 							ret = RECV_XDP(handle, &pktsize, idlist);
1351 							if (!ret)
1352 							{
1353 								memmove(idlist, idlist + 8, pktsize - 8);
1354 								idlist[pktsize - 8] = '\0';
1355 								ret = SEND_ACK(handle);
1356 								if (!ret)
1357 								{
1358 									ret = RECV_EOT(handle);
1359 									if (!ret)
1360 									{
1361 										ret = SEND_ACK(handle);
1362 									}
1363 								}
1364 							}
1365 						}
1366 					}
1367 				}
1368 			}
1369 		}
1370 	}
1371 
1372 	return ret;
1373 }
1374 
dump_rom_1(CalcHandle * handle)1375 static int		dump_rom_1	(CalcHandle* handle)
1376 {
1377 	int ret = 0;
1378 
1379 	ret = go_to_homescreen(handle);
1380 	PAUSE(200);
1381 
1382 	if (!ret)
1383 	{
1384 		// Send dumping program
1385 		if (handle->model != CALC_TI92)
1386 		{
1387 			ret = rd_send(handle, "romdump.89z", romDumpSize89, romDump89);
1388 		}
1389 		else
1390 		{
1391 			ret = rd_send(handle, "romdump.92p", romDumpSize92, romDump92);
1392 		}
1393 		PAUSE(1000);
1394 	}
1395 
1396 	return ret;
1397 }
1398 
dump_rom_2(CalcHandle * handle,CalcDumpSize size,const char * filename)1399 static int		dump_rom_2	(CalcHandle* handle, CalcDumpSize size, const char *filename)
1400 {
1401 	int ret = 0;
1402 	unsigned int i;
1403 	static const uint16_t keys[] = {
1404 		'm', 'a', 'i', 'n', '\\',
1405 		'r', 'o', 'm', 'd', 'u', 'm', 'p',
1406 		KEY89_LP, KEY89_RP, KEY89_ENTER
1407 	};
1408 
1409 	// Launch program by remote control
1410 	for (i = 0; !ret && i < sizeof(keys) / sizeof(keys[0]); i++)
1411 	{
1412 		ret = send_key(handle, (uint32_t)(keys[i]));
1413 	}
1414 	PAUSE(200);
1415 
1416 	// Get dump
1417 	if (!ret)
1418 	{
1419 		ret = rd_dump(handle, filename);
1420 	}
1421 
1422 	return ret;
1423 }
1424 
set_clock(CalcHandle * handle,CalcClock * _clock)1425 static int		set_clock	(CalcHandle* handle, CalcClock* _clock)
1426 {
1427 	int ret;
1428 	uint8_t buffer[16];
1429 	uint16_t status;
1430 
1431 	buffer[0] = 0;
1432 	buffer[1] = 0;
1433 	buffer[2] = 0;
1434 	buffer[3] = 0;
1435 	buffer[4] = 0;
1436 	buffer[5] = 0;
1437 	buffer[6] = _clock->year >> 8;
1438 	buffer[7] = _clock->year & 0x00ff;
1439 	buffer[8] = _clock->month;
1440 	buffer[9] = _clock->day;
1441 	buffer[10] = _clock->hours;
1442 	buffer[11] = _clock->minutes;
1443 	buffer[12] = _clock->seconds;
1444 	buffer[13] = _clock->date_format;
1445 	buffer[14] = _clock->time_format;
1446 	buffer[15] = 0xff;
1447 
1448 	ticalcs_strlcpy(update_->text, _("Setting clock..."), sizeof(update_->text));
1449 	update_label();
1450 
1451 	ret = SEND_RTS(handle, 0x10, TI89_CLK, "Clock");
1452 	if (!ret)
1453 	{
1454 		ret = RECV_ACK(handle, NULL);
1455 		if (!ret)
1456 		{
1457 			ret = RECV_CTS(handle);
1458 			if (!ret)
1459 			{
1460 				ret = SEND_ACK(handle);
1461 				if (!ret)
1462 				{
1463 					ret = SEND_XDP(handle, 0x10, buffer);
1464 					if (!ret)
1465 					{
1466 						ret = RECV_ACK(handle, NULL);
1467 						if (!ret)
1468 						{
1469 							ret = SEND_EOT(handle);
1470 							if (!ret)
1471 							{
1472 								ret = RECV_ACK(handle, &status);
1473 							}
1474 						}
1475 					}
1476 				}
1477 			}
1478 		}
1479 	}
1480 
1481 	return ret;
1482 }
1483 
get_clock(CalcHandle * handle,CalcClock * _clock)1484 static int		get_clock	(CalcHandle* handle, CalcClock* _clock)
1485 {
1486 	int ret;
1487 	uint32_t varsize;
1488 	uint16_t pktsize;
1489 	uint8_t vartype;
1490 	char varname[9];
1491 
1492 	ticalcs_strlcpy(update_->text, _("Getting clock..."), sizeof(update_->text));
1493 	update_label();
1494 
1495 	ret = SEND_REQ(handle, 0x0000, TI89_CLK, "Clock");
1496 	if (!ret)
1497 	{
1498 		ret = RECV_ACK(handle, NULL);
1499 		if (!ret)
1500 		{
1501 			ret = RECV_VAR(handle, &varsize, &vartype, varname);
1502 			if (!ret)
1503 			{
1504 				ret = SEND_ACK(handle);
1505 				if (!ret)
1506 				{
1507 					ret = SEND_CTS(handle);
1508 					if (!ret)
1509 					{
1510 						ret = RECV_ACK(handle, NULL);
1511 						if (!ret)
1512 						{
1513 							uint8_t * buffer = (uint8_t *)(handle->buffer2);
1514 							ret = RECV_XDP(handle, &pktsize, buffer);
1515 							if (!ret)
1516 							{
1517 								ret = SEND_ACK(handle);
1518 								if (!ret)
1519 								{
1520 									ret = RECV_EOT(handle);
1521 									if (!ret)
1522 									{
1523 										ret = SEND_ACK(handle);
1524 										if (!ret)
1525 										{
1526 											_clock->year = (((uint16_t)buffer[6]) << 8) | buffer[7];
1527 											_clock->month = buffer[8];
1528 											_clock->day = buffer[9];
1529 											_clock->hours = buffer[10];
1530 											_clock->minutes = buffer[11];
1531 											_clock->seconds = buffer[12];
1532 											_clock->date_format = buffer[13];
1533 											_clock->time_format = buffer[14];
1534 										}
1535 									}
1536 								}
1537 							}
1538 						}
1539 					}
1540 				}
1541 			}
1542 		}
1543 	}
1544 
1545 	return ret;
1546 }
1547 
del_var(CalcHandle * handle,VarRequest * vr)1548 static int		del_var		(CalcHandle* handle, VarRequest* vr)
1549 {
1550 	int ret;
1551 	char varname[18];
1552 	char *utf8;
1553 
1554 	tifiles_build_fullname(handle->model, varname, vr->folder, vr->name);
1555 	utf8 = ticonv_varname_to_utf8(handle->model, varname, vr->type);
1556 	ticalcs_slprintf(update_->text, sizeof(update_->text), _("Deleting %s..."), utf8);
1557 	ticonv_utf8_free(utf8);
1558 	update_label();
1559 
1560 	ret = SEND_DEL(handle, vr->size, vr->type, varname);
1561 	if (!ret)
1562 	{
1563 		ret = RECV_ACK(handle, NULL);
1564 		if (!ret)
1565 		{
1566 			ret = RECV_ACK(handle, NULL);
1567 		}
1568 	}
1569 
1570 	return ret;
1571 }
1572 
del_var_92(CalcHandle * handle,VarRequest * vr)1573 static int		del_var_92		(CalcHandle* handle, VarRequest* vr)
1574 {
1575 	int ret = 0;
1576 	unsigned int i;
1577 	static const uint16_t keys[] = {
1578 		KEY92P_ON, KEY92P_ESC, KEY92P_ESC, KEY92P_ESC,
1579 		KEY92P_2ND + KEY92P_ESC, KEY92P_2ND + KEY92P_ESC, KEY92P_CTRL + KEY92P_Q, KEY92P_CLEAR, KEY92P_CLEAR,
1580 		'd', 'e', 'l', 'v', 'a', 'r',
1581 		KEY92P_SPACE
1582 	};
1583 	char varname[18];
1584 	char *utf8;
1585 
1586 	tifiles_build_fullname(handle->model, varname, vr->folder, vr->name);
1587 	utf8 = ticonv_varname_to_utf8(handle->model, varname, vr->type);
1588 	ticalcs_slprintf(update_->text, sizeof(update_->text), _("Deleting %s..."), utf8);
1589 	ticonv_utf8_free(utf8);
1590 	update_label();
1591 
1592 	for (i = 0; !ret && i < sizeof(keys) / sizeof(keys[0]); i++)
1593 	{
1594 		ret = send_key(handle, (uint32_t)(keys[i]));
1595 	}
1596 	for (i = 0; !ret && i < strlen(varname); i++)
1597 	{
1598 		ret = send_key(handle, (uint32_t)(uint8_t)(varname[i]));
1599 	}
1600 
1601 	if (!ret)
1602 	{
1603 		ret = send_key(handle, KEY92P_ENTER);
1604 	}
1605 
1606 	return ret;
1607 }
1608 
new_folder(CalcHandle * handle,VarRequest * vr)1609 static int		new_folder  (CalcHandle* handle, VarRequest* vr)
1610 {
1611 	int ret;
1612 	uint8_t data[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23 };
1613 	char varname[18];
1614 	char *utf8;
1615 
1616 	tifiles_build_fullname(handle->model, varname, vr->folder, "a1234567");
1617 	utf8 = ticonv_varname_to_utf8(handle->model, vr->folder, -1);
1618 	ticalcs_slprintf(update_->text, sizeof(update_->text), _("Creating %s..."), utf8);
1619 	ticonv_utf8_free(utf8);
1620 	update_label();
1621 
1622 	// send empty expression
1623 	ret = SEND_RTS(handle, 0x10, 0x00, varname);
1624 	if (!ret)
1625 	{
1626 		ret = RECV_ACK(handle, NULL);
1627 		if (!ret)
1628 		{
1629 			ret = RECV_CTS(handle);
1630 			if (!ret)
1631 			{
1632 				ret = SEND_ACK(handle);
1633 				if (!ret)
1634 				{
1635 					ret = SEND_XDP(handle, 0x10, data);
1636 					if (!ret)
1637 					{
1638 						ret = RECV_ACK(handle, NULL);
1639 						if (!ret)
1640 						{
1641 							ret = SEND_EOT(handle);
1642 							if (!ret)
1643 							{
1644 								ret = RECV_ACK(handle, NULL);
1645 								if (!ret)
1646 								{
1647 									PAUSE(250);
1648 									// delete 'a1234567' variable
1649 									ticalcs_strlcpy(vr->name, "a1234567", sizeof(vr->name));
1650 									ret = ((handle->model != CALC_TI92) ? del_var : del_var_92)(handle, vr);
1651 								}
1652 							}
1653 						}
1654 					}
1655 				}
1656 			}
1657 		}
1658 	}
1659 
1660 	return ret;
1661 }
1662 
get_version(CalcHandle * handle,CalcInfos * infos)1663 static int		get_version	(CalcHandle* handle, CalcInfos* infos)
1664 {
1665 	int ret;
1666 	uint16_t length;
1667 	uint8_t buf[32];
1668 
1669 	ret = SEND_VER(handle);
1670 	if (!ret)
1671 	{
1672 		ret = RECV_ACK(handle, NULL);
1673 		if (!ret)
1674 		{
1675 			ret = SEND_CTS(handle);
1676 			if (!ret)
1677 			{
1678 				ret = RECV_ACK(handle, NULL);
1679 				if (!ret)
1680 				{
1681 					ret = RECV_XDP(handle, &length, buf);
1682 					if (!ret)
1683 					{
1684 						ret = SEND_ACK(handle);
1685 					}
1686 				}
1687 			}
1688 		}
1689 	}
1690 	if (!ret)
1691 	{
1692 		memset(infos, 0, sizeof(CalcInfos));
1693 		ticalcs_slprintf(infos->os_version, sizeof(infos->os_version), "%1d.%02d", buf[0], buf[1]);
1694 		ticalcs_slprintf(infos->boot_version, sizeof(infos->boot_version), "%1d.%02d", buf[2], buf[3]);
1695 		infos->battery = buf[4] == 1 ? 0 : 1;
1696 		switch(buf[13])
1697 		{
1698 		case 1:
1699 		case 3: infos->hw_version = buf[5] + 1; break;
1700 		case 8: infos->hw_version = buf[5]; break;
1701 		case 9: infos->hw_version = buf[5] + 1; break;
1702 		}
1703 		switch(buf[13])
1704 		{
1705 		case 1: infos->model = CALC_TI92P; break;
1706 		case 3: infos->model = CALC_TI89; break;
1707 		case 8: infos->model = CALC_V200; break;
1708 		case 9: infos->model = CALC_TI89T; break;
1709 		}
1710 		infos->language_id = buf[6];
1711 		infos->sub_lang_id = buf[7];
1712 		infos->mask = INFOS_BOOT_VERSION | INFOS_OS_VERSION | INFOS_BATTERY | INFOS_HW_VERSION | INFOS_CALC_MODEL | INFOS_LANG_ID | INFOS_SUB_LANG_ID;
1713 
1714 		tifiles_hexdump(buf, length);
1715 		ticalcs_info(_("  OS: %s"), infos->os_version);
1716 		ticalcs_info(_("  BIOS: %s"), infos->boot_version);
1717 		ticalcs_info(_("  Battery: %s"), infos->battery ? "good" : "low");
1718 	}
1719 
1720 	return ret;
1721 }
1722 
get_version_92(CalcHandle * handle,CalcInfos * infos)1723 static int		get_version_92	(CalcHandle* handle, CalcInfos* infos)
1724 {
1725 	int ret;
1726 	uint32_t size;
1727 	uint8_t type;
1728 	char name[32];
1729 
1730 	ret = SEND_REQ(handle, 0, TI92_BKUP, "main\\version");
1731 	if (!ret)
1732 	{
1733 		ret = RECV_ACK(handle, NULL);
1734 		if (!ret)
1735 		{
1736 			ret = RECV_VAR(handle, &size, &type, name);
1737 			if (!ret)
1738 			{
1739 				ret = SEND_EOT(handle);
1740 				if (!ret)
1741 				{
1742 					memset(infos, 0, sizeof(CalcInfos));
1743 					strncpy(infos->os_version, name, 4);
1744 					infos->os_version[4] = 0;
1745 					infos->hw_version = 1;
1746 					infos->mask = INFOS_OS_VERSION | INFOS_HW_VERSION;
1747 
1748 					ticalcs_info(_("  OS: %s"), infos->os_version);
1749 					ticalcs_info(_("  Battery: %s"), infos->battery ? "good" : "low");
1750 				}
1751 			}
1752 		}
1753 	}
1754 
1755 	return ret;
1756 }
1757 
send_cert(CalcHandle * handle,FlashContent * content)1758 static int		send_cert	(CalcHandle* handle, FlashContent* content)
1759 {
1760 	return send_flash(handle, content);
1761 }
1762 
recv_cert(CalcHandle * handle,FlashContent * content)1763 static int		recv_cert	(CalcHandle* handle, FlashContent* content)
1764 {
1765 	VarEntry ve;
1766 	int ret = 0;
1767 
1768 	memset(&ve, 0, sizeof(VarEntry));
1769 	ve.type = TI89_GETCERT;
1770 	ve.name[0] = 0;
1771 
1772 	ret = recv_flash(handle, content, &ve);
1773 	if (!ret)
1774 	{
1775 		// fix up for certificate
1776 		memmove(content->data_part, content->data_part + 4, content->data_length - 4);
1777 		content->data_type = TI89_CERTIF;
1778 		switch(handle->model)
1779 		{
1780 		case CALC_TI89:  content->device_type = DEVICE_TYPE_89; break;
1781 		case CALC_TI89T: content->device_type = DEVICE_TYPE_89; break;
1782 		case CALC_TI92P: content->device_type = DEVICE_TYPE_92P; break;
1783 		case CALC_V200:  content->device_type = DEVICE_TYPE_92P; break;
1784 		default: content->device_type = DEVICE_TYPE_89; break;
1785 		}
1786 		content->name[0] = 0;
1787 	}
1788 
1789 	return ret;
1790 }
1791 
1792 const CalcFncts calc_89 =
1793 {
1794 	CALC_TI89,
1795 	"TI89",
1796 	"TI-89",
1797 	"TI-89",
1798 	OPS_ISREADY | OPS_KEYS | OPS_SCREEN | OPS_DIRLIST | OPS_BACKUP | OPS_VARS |
1799 	OPS_FLASH | OPS_IDLIST | OPS_CLOCK | OPS_ROMDUMP |
1800 	OPS_DELVAR | OPS_NEWFLD | OPS_VERSION |
1801 	FTS_SILENT | FTS_FOLDER | FTS_FLASH | FTS_CERT | FTS_NONSILENT,
1802 	PRODUCT_ID_TI89,
1803 	{"",     /* is_ready */
1804 	 "",     /* send_key */
1805 	 "",     /* execute */
1806 	 "1P",   /* recv_screen */
1807 	 "1L",   /* get_dirlist */
1808 	 "",     /* get_memfree */
1809 	 "",     /* send_backup */
1810 	 "",     /* recv_backup */
1811 	 "2P1L", /* send_var */
1812 	 "1P1L", /* recv_var */
1813 	 "2P1L", /* send_var_ns */
1814 	 "1P1L", /* recv_var_ns */
1815 	 "2P1L", /* send_app */
1816 	 "2P1L", /* recv_app */
1817 	 "2P",   /* send_os */
1818 	 "1L",   /* recv_idlist */
1819 	 "2P",   /* dump_rom_1 */
1820 	 "2P",   /* dump_rom_2 */
1821 	 "",     /* set_clock */
1822 	 "",     /* get_clock */
1823 	 "1L",   /* del_var */
1824 	 "1L",   /* new_folder */
1825 	 "",     /* get_version */
1826 	 "1L",   /* send_cert */
1827 	 "1L",   /* recv_cert */
1828 	 "",     /* rename */
1829 	 "",     /* chattr */
1830 	 "2P1L", /* send_all_vars_backup */
1831 	 "2P1L"  /* recv_all_vars_backup */ },
1832 	&is_ready,
1833 	&send_key,
1834 	&execute,
1835 	&recv_screen,
1836 	&get_dirlist,
1837 	&get_memfree,
1838 	&noop_send_backup,
1839 	&noop_recv_backup,
1840 	&send_var,
1841 	&recv_var,
1842 	&send_var_ns,
1843 	&recv_var_ns,
1844 	&send_flash,
1845 	&recv_flash,
1846 	&send_flash,
1847 	&recv_idlist,
1848 	&dump_rom_1,
1849 	&dump_rom_2,
1850 	&set_clock,
1851 	&get_clock,
1852 	&del_var,
1853 	&new_folder,
1854 	&get_version,
1855 	&send_cert,
1856 	&recv_cert,
1857 	&noop_rename_var,
1858 	&noop_change_attr,
1859 	&send_all_vars_backup,
1860 	&tixx_recv_all_vars_backup,
1861 };
1862 
1863 const CalcFncts calc_92p =
1864 {
1865 	CALC_TI92P,
1866 	"TI92+",
1867 	"TI-92 Plus",
1868 	"TI-92 Plus",
1869 	OPS_ISREADY | OPS_KEYS | OPS_SCREEN | OPS_DIRLIST | OPS_BACKUP | OPS_VARS |
1870 	OPS_FLASH | OPS_IDLIST | OPS_CLOCK | OPS_ROMDUMP |
1871 	OPS_DELVAR | OPS_NEWFLD | OPS_VERSION | OPS_OS |
1872 	FTS_SILENT | FTS_FOLDER | FTS_FLASH | FTS_CERT | FTS_NONSILENT,
1873 	PRODUCT_ID_TI92P,
1874 	{"",     /* is_ready */
1875 	 "",     /* send_key */
1876 	 "",     /* execute */
1877 	 "1P",   /* recv_screen */
1878 	 "1L",   /* get_dirlist */
1879 	 "",     /* get_memfree */
1880 	 "",     /* send_backup */
1881 	 "",     /* recv_backup */
1882 	 "2P1L", /* send_var */
1883 	 "1P1L", /* recv_var */
1884 	 "2P1L", /* send_var_ns */
1885 	 "1P1L", /* recv_var_ns */
1886 	 "2P1L", /* send_app */
1887 	 "2P1L", /* recv_app */
1888 	 "2P",   /* send_os */
1889 	 "1L",   /* recv_idlist */
1890 	 "2P",   /* dump_rom_1 */
1891 	 "2P",   /* dump_rom_2 */
1892 	 "",     /* set_clock */
1893 	 "",     /* get_clock */
1894 	 "1L",   /* del_var */
1895 	 "1L",   /* new_folder */
1896 	 "",     /* get_version */
1897 	 "1L",   /* send_cert */
1898 	 "1L",   /* recv_cert */
1899 	 "",     /* rename */
1900 	 "",     /* chattr */
1901 	 "2P1L", /* send_all_vars_backup */
1902 	 "2P1L"  /* recv_all_vars_backup */ },
1903 	&is_ready,
1904 	&send_key,
1905 	&execute,
1906 	&recv_screen,
1907 	&get_dirlist,
1908 	&get_memfree,
1909 	&noop_send_backup,
1910 	&noop_recv_backup,
1911 	&send_var,
1912 	&recv_var,
1913 	&send_var_ns,
1914 	&recv_var_ns,
1915 	&send_flash,
1916 	&recv_flash,
1917 	&send_flash,
1918 	&recv_idlist,
1919 	&dump_rom_1,
1920 	&dump_rom_2,
1921 	&set_clock,
1922 	&get_clock,
1923 	&del_var,
1924 	&new_folder,
1925 	&get_version,
1926 	&send_cert,
1927 	&recv_cert,
1928 	&noop_rename_var,
1929 	&noop_change_attr,
1930 	&send_all_vars_backup,
1931 	&tixx_recv_all_vars_backup,
1932 };
1933 
1934 const CalcFncts calc_89t =
1935 {
1936 	CALC_TI89T,
1937 	"Titanium",
1938 	"TI-89 Titanium",
1939 	"TI-89 Titanium",
1940 	OPS_ISREADY | OPS_KEYS | OPS_SCREEN | OPS_DIRLIST | OPS_BACKUP | OPS_VARS |
1941 	OPS_FLASH | OPS_IDLIST | OPS_CLOCK | OPS_ROMDUMP |
1942 	OPS_DELVAR | OPS_NEWFLD | OPS_VERSION | OPS_OS |
1943 	FTS_SILENT | FTS_FOLDER | FTS_FLASH | FTS_CERT | FTS_NONSILENT,
1944 	PRODUCT_ID_TI89T,
1945 	{"",     /* is_ready */
1946 	 "",     /* send_key */
1947 	 "",     /* execute */
1948 	 "1P",   /* recv_screen */
1949 	 "1L",   /* get_dirlist */
1950 	 "",     /* get_memfree */
1951 	 "",     /* send_backup */
1952 	 "",     /* recv_backup */
1953 	 "2P1L", /* send_var */
1954 	 "1P1L", /* recv_var */
1955 	 "2P1L", /* send_var_ns */
1956 	 "1P1L", /* recv_var_ns */
1957 	 "2P1L", /* send_app */
1958 	 "2P1L", /* recv_app */
1959 	 "2P",   /* send_os */
1960 	 "1L",   /* recv_idlist */
1961 	 "2P",   /* dump_rom_1 */
1962 	 "2P",   /* dump_rom_2 */
1963 	 "",     /* set_clock */
1964 	 "",     /* get_clock */
1965 	 "1L",   /* del_var */
1966 	 "1L",   /* new_folder */
1967 	 "",     /* get_version */
1968 	 "1L",   /* send_cert */
1969 	 "1L",   /* recv_cert */
1970 	 "",     /* rename */
1971 	 "",     /* chattr */
1972 	 "2P1L", /* send_all_vars_backup */
1973 	 "2P1L"  /* recv_all_vars_backup */ },
1974 	&is_ready,
1975 	&send_key,
1976 	&execute,
1977 	&recv_screen,
1978 	&get_dirlist,
1979 	&get_memfree,
1980 	&noop_send_backup,
1981 	&noop_recv_backup,
1982 	&send_var,
1983 	&recv_var,
1984 	&send_var_ns,
1985 	&recv_var_ns,
1986 	&send_flash,
1987 	&recv_flash,
1988 	&send_flash,
1989 	&recv_idlist,
1990 	&dump_rom_1,
1991 	&dump_rom_2,
1992 	&set_clock,
1993 	&get_clock,
1994 	&del_var,
1995 	&new_folder,
1996 	&get_version,
1997 	&send_cert,
1998 	&recv_cert,
1999 	&noop_rename_var,
2000 	&noop_change_attr,
2001 	&send_all_vars_backup,
2002 	&tixx_recv_all_vars_backup,
2003 };
2004 
2005 const CalcFncts calc_v2 =
2006 {
2007 	CALC_V200,
2008 	"V200",
2009 	"V200PLT",
2010 	N_("V200 Personal Learning Tool"),
2011 	OPS_ISREADY | OPS_KEYS | OPS_SCREEN | OPS_DIRLIST | OPS_BACKUP | OPS_VARS |
2012 	OPS_FLASH | OPS_IDLIST | OPS_CLOCK | OPS_ROMDUMP |
2013 	OPS_DELVAR | OPS_NEWFLD | OPS_VERSION | OPS_OS |
2014 	FTS_SILENT | FTS_FOLDER | FTS_FLASH | FTS_CERT | FTS_NONSILENT,
2015 	PRODUCT_ID_TIV200,
2016 	{"",     /* is_ready */
2017 	 "",     /* send_key */
2018 	 "",     /* execute */
2019 	 "1P",   /* recv_screen */
2020 	 "1L",   /* get_dirlist */
2021 	 "",     /* get_memfree */
2022 	 "",     /* send_backup */
2023 	 "",     /* recv_backup */
2024 	 "2P1L", /* send_var */
2025 	 "1P1L", /* recv_var */
2026 	 "2P1L", /* send_var_ns */
2027 	 "1P1L", /* recv_var_ns */
2028 	 "2P1L", /* send_app */
2029 	 "2P1L", /* recv_app */
2030 	 "2P",   /* send_os */
2031 	 "1L",   /* recv_idlist */
2032 	 "2P",   /* dump_rom_1 */
2033 	 "2P",   /* dump_rom_2 */
2034 	 "",     /* set_clock */
2035 	 "",     /* get_clock */
2036 	 "1L",   /* del_var */
2037 	 "1L",   /* new_folder */
2038 	 "",     /* get_version */
2039 	 "1L",   /* send_cert */
2040 	 "1L",   /* recv_cert */
2041 	 "",     /* rename */
2042 	 "",     /* chattr */
2043 	 "2P1L", /* send_all_vars_backup */
2044 	 "2P1L"  /* recv_all_vars_backup */ },
2045 	&is_ready,
2046 	&send_key,
2047 	&execute,
2048 	&recv_screen,
2049 	&get_dirlist,
2050 	&get_memfree,
2051 	&noop_send_backup,
2052 	&noop_recv_backup,
2053 	&send_var,
2054 	&recv_var,
2055 	&send_var_ns,
2056 	&recv_var_ns,
2057 	&send_flash,
2058 	&recv_flash,
2059 	&send_flash,
2060 	&recv_idlist,
2061 	&dump_rom_1,
2062 	&dump_rom_2,
2063 	&set_clock,
2064 	&get_clock,
2065 	&del_var,
2066 	&new_folder,
2067 	&get_version,
2068 	&send_cert,
2069 	&recv_cert,
2070 	&noop_rename_var,
2071 	&noop_change_attr,
2072 	&send_all_vars_backup,
2073 	&tixx_recv_all_vars_backup,
2074 };
2075 
2076 const CalcFncts calc_92 =
2077 {
2078 	CALC_TI92,
2079 	"TI92",
2080 	"TI-92",
2081 	"TI-92",
2082 	OPS_ISREADY | OPS_KEYS | OPS_SCREEN | OPS_DIRLIST | OPS_BACKUP | OPS_VARS | OPS_ROMDUMP |
2083 	OPS_DELVAR | OPS_NEWFLD | OPS_VERSION |
2084 	FTS_SILENT | FTS_FOLDER | FTS_BACKUP | FTS_NONSILENT,
2085 	PRODUCT_ID_NONE,
2086 	{"",     /* is_ready */
2087 	 "",     /* send_key */
2088 	 "",     /* execute */
2089 	 "1P",   /* recv_screen */
2090 	 "1L",   /* get_dirlist */
2091 	 "",     /* get_memfree */
2092 	 "2P",   /* send_backup */
2093 	 "1P1L", /* recv_backup */
2094 	 "2P1L", /* send_var */
2095 	 "1P1L", /* recv_var */
2096 	 "2P1L", /* send_var_ns */
2097 	 "1P1L", /* recv_var_ns */
2098 	 "",     /* send_app */
2099 	 "",     /* recv_app */
2100 	 "",     /* send_os */
2101 	 "",     /* recv_idlist */
2102 	 "2P",   /* dump_rom_1 */
2103 	 "2P",   /* dump_rom_2 */
2104 	 "",     /* set_clock */
2105 	 "",     /* get_clock */
2106 	 "1L",   /* del_var */
2107 	 "1L",   /* new_folder */
2108 	 "",     /* get_version */
2109 	 "",     /* send_cert */
2110 	 "",     /* recv_cert */
2111 	 "",     /* rename */
2112 	 "",     /* chattr */
2113 	 "",     /* send_all_vars_backup */
2114 	 ""      /* recv_all_vars_backup */ },
2115 	&is_ready,
2116 	&send_key,
2117 	&execute,
2118 	&recv_screen,
2119 	&get_dirlist_92,
2120 	&get_memfree,
2121 	&send_backup,
2122 	&recv_backup,
2123 	&send_var_ns,
2124 	&recv_var,
2125 	&send_var_ns,
2126 	&recv_var_ns,
2127 	&noop_send_flash,
2128 	&noop_recv_flash,
2129 	&noop_send_os,
2130 	&noop_recv_idlist,
2131 	&dump_rom_1,
2132 	&dump_rom_2,
2133 	&noop_set_clock,
2134 	&noop_get_clock,
2135 	&del_var_92,
2136 	&new_folder,
2137 	&get_version_92,
2138 	&noop_send_cert,
2139 	&noop_recv_cert,
2140 	&noop_rename_var,
2141 	&noop_change_attr,
2142 	&noop_send_all_vars_backup,
2143 	&noop_recv_all_vars_backup,
2144 };
2145