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