1 /* Hey EMACS -*- linux-c -*- */
2 /* $Id$ */
3
4 /* libticalcs2 - hand-helds support library, a part of the TiLP project
5 * Copyright (c) 1999-2005 Romain Liévin
6 * Copyright (c) 2005 Benjamin Moody (ROM dumper)
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 TI84+ support thru DirectUsb link.
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 "dusb_vpkt.h"
43 #include "dusb_cmd.h"
44 #include "rom84p.h"
45 #include "rom84pcu.h"
46 #include "rom834pceu.h"
47 #include "romdump.h"
48 #include "keys83p.h"
49
50 // Screen coordinates of the TI83+
51 #define TI84P_ROWS 64
52 #define TI84P_COLS 96
53 #define TI84PC_ROWS 240
54 #define TI84PC_COLS 320
55
is_ready(CalcHandle * handle)56 static int is_ready (CalcHandle* handle)
57 {
58 int ret;
59 static const DUSBModeSet mode = DUSB_MODE_NORMAL;
60
61 ret = dusb_cmd_s_mode_set(handle, mode);
62 if (!ret)
63 {
64 // use PID_HOMESCREEN to return status ?
65 ret = dusb_cmd_r_mode_ack(handle);
66 }
67
68 return ret;
69 }
70
send_key_noack(CalcHandle * handle,uint32_t key)71 static int send_key_noack (CalcHandle* handle, uint32_t key)
72 {
73 int ret;
74
75 ret = dusb_cmd_s_execute(handle, "", "", DUSB_EID_KEY, "", (uint16_t)key);
76 if (!ret)
77 {
78 ret = dusb_cmd_r_delay_ack(handle);
79 }
80
81 return ret;
82 }
83
send_key(CalcHandle * handle,uint32_t key)84 static int send_key (CalcHandle* handle, uint32_t key)
85 {
86 int ret;
87
88 ret = send_key_noack(handle, key);
89 if (!ret)
90 {
91 ret = dusb_cmd_r_data_ack(handle);
92 }
93
94 return ret;
95 }
96
execute(CalcHandle * handle,VarEntry * ve,const char * args)97 static int execute (CalcHandle* handle, VarEntry *ve, const char *args)
98 {
99 uint8_t action;
100 int ret;
101
102 switch (ve->type)
103 {
104 case TI84p_ASM: action = DUSB_EID_ASM; break;
105 case TI84p_APPL: action = DUSB_EID_APP; break;
106 default: action = DUSB_EID_PRGM; break;
107 }
108
109 ret = dusb_cmd_s_execute(handle, ve->folder, ve->name, action, args, 0);
110 if (!ret)
111 {
112 ret = dusb_cmd_r_data_ack(handle);
113 }
114
115 return ret;
116 }
117
recv_screen(CalcHandle * handle,CalcScreenCoord * sc,uint8_t ** bitmap)118 static int recv_screen (CalcHandle* handle, CalcScreenCoord* sc, uint8_t** bitmap)
119 {
120 static const uint16_t pid[] = { DUSB_PID_SCREENSHOT };
121 uint32_t size;
122 uint8_t *data;
123 int ret;
124
125 ret = dusb_cmd_s_param_request(handle, 1, pid);
126 if (!ret)
127 {
128 ret = dusb_cmd_r_screenshot(handle, &size, &data);
129 if (!ret)
130 {
131 switch (handle->model)
132 {
133 case CALC_TI84P_USB:
134 case CALC_TI82A_USB:
135 {
136 if (size == TI84P_ROWS * TI84P_COLS / 8)
137 {
138 *bitmap = data;
139 sc->width = TI84P_COLS;
140 sc->height = TI84P_ROWS;
141 sc->clipped_width = TI84P_COLS;
142 sc->clipped_height = TI84P_ROWS;
143 sc->pixel_format = CALC_PIXFMT_MONO;
144 }
145 else
146 {
147 g_free(data);
148 *bitmap = NULL;
149 ret = ERR_INVALID_SCREENSHOT;
150 }
151 break;
152 }
153 case CALC_TI84PC_USB:
154 {
155 size -= 4;
156 *bitmap = ticalcs_alloc_screen(TI84PC_ROWS * TI84PC_COLS * 2);
157 ret = ticalcs_screen_84pcse_rle_uncompress(data, size, *bitmap, TI84PC_ROWS * TI84PC_COLS * 2);
158 g_free(data);
159 if (ret)
160 {
161 ticalcs_free_screen(*bitmap);
162 *bitmap = NULL;
163 ret = ERR_INVALID_SCREENSHOT;
164 }
165 else
166 {
167 sc->width = TI84PC_COLS;
168 sc->height = TI84PC_ROWS;
169 sc->clipped_width = TI84PC_COLS;
170 sc->clipped_height = TI84PC_ROWS;
171 sc->pixel_format = CALC_PIXFMT_RGB_565_LE;
172 }
173 break;
174 }
175 case CALC_TI83PCE_USB:
176 case CALC_TI84PCE_USB:
177 {
178 if (size == TI84PC_ROWS * TI84PC_COLS * 2)
179 {
180 // 83PCE, 84PCE
181 *bitmap = data;
182 sc->width = TI84PC_COLS;
183 sc->height = TI84PC_ROWS;
184 sc->clipped_width = TI84PC_COLS;
185 sc->clipped_height = TI84PC_ROWS;
186 sc->pixel_format = CALC_PIXFMT_RGB_565_LE;
187 break;
188 }
189 // else fall through.
190 }
191 default:
192 {
193 g_free(data);
194 *bitmap = NULL;
195 ret = ERR_INVALID_SCREENSHOT;
196 break;
197 }
198 }
199 }
200 }
201
202 return ret;
203 }
204
get_dirlist(CalcHandle * handle,GNode ** vars,GNode ** apps)205 static int get_dirlist (CalcHandle* handle, GNode** vars, GNode** apps)
206 {
207 static const uint16_t aids[] = { DUSB_AID_VAR_SIZE, DUSB_AID_VAR_TYPE, DUSB_AID_ARCHIVED };
208 const int size = sizeof(aids) / sizeof(uint16_t);
209 int ret;
210 DUSBCalcAttr **attr;
211 GNode *folder, *root, *node;
212 char fldname[40], varname[40];
213 char *utf8;
214
215 ret = dirlist_init_trees(handle, vars, apps);
216 if (ret)
217 {
218 return ret;
219 }
220
221 folder = dirlist_create_append_node(NULL, vars);
222 if (!folder)
223 {
224 return ERR_MALLOC;
225 }
226 root = dirlist_create_append_node(NULL, apps);
227 if (!root)
228 {
229 return ERR_MALLOC;
230 }
231
232 // Add permanent variables (Window, RclWin / RclWindw, TblSet aka WINDW, ZSTO, TABLE)
233 {
234 VarEntry *ve;
235
236 ve = tifiles_ve_create();
237 ticalcs_strlcpy(ve->name, "Window", sizeof(ve->name));
238 ve->type = TI84p_WINDW;
239 node = dirlist_create_append_node(ve, &folder);
240 if (node != NULL)
241 {
242 ve = tifiles_ve_create();
243 // Actually, "RclWindw" works even on an old 84+ running OS 2.43, but libticalcs
244 // has been using "RclWin" successfully on TI-Z80 DUSB models since the beginning...
245 ticalcs_strlcpy(ve->name, (handle->model == CALC_TI84PC_USB || handle->model == CALC_TI83PCE_USB || handle->model == CALC_TI84PCE_USB) ? "RclWindw" : "RclWin", sizeof(ve->name));
246 ve->type = TI84p_ZSTO;
247 node = dirlist_create_append_node(ve, &folder);
248 if (node != NULL)
249 {
250 ve = tifiles_ve_create();
251 ticalcs_strlcpy(ve->name, "TblSet", sizeof(ve->name));
252 ve->type = TI84p_TABLE;
253 node = dirlist_create_append_node(ve, &folder);
254 }
255 }
256 }
257
258 if (!node)
259 {
260 return ERR_MALLOC;
261 }
262
263 ret = dusb_cmd_s_dirlist_request(handle, size, aids);
264 if (!ret)
265 {
266 for (;;)
267 {
268 VarEntry *ve;
269
270 attr = dusb_ca_new_array(handle, size);
271 ret = dusb_cmd_r_var_header(handle, fldname, varname, attr);
272 if (ret)
273 {
274 // Not a real error.
275 if (ret == ERR_EOT)
276 {
277 ret = 0;
278 }
279 dusb_ca_del_array(handle, size, attr);
280 break;
281 }
282
283 ve = tifiles_ve_create();
284 ticalcs_strlcpy(ve->name, varname, sizeof(ve->name));
285 ve->size = ( (((uint32_t)(attr[0]->data[0])) << 24)
286 | (((uint32_t)(attr[0]->data[1])) << 16)
287 | (((uint32_t)(attr[0]->data[2])) << 8)
288 | (((uint32_t)(attr[0]->data[3])) ));
289 ve->type = (uint32_t)(attr[1]->data[3]);
290 ve->attr = attr[2]->data[0] ? ATTRB_ARCHIVED : ATTRB_NONE;
291 dusb_ca_del_array(handle, size, attr);
292
293 node = dirlist_create_append_node(ve, (ve->type != TI73_APPL) ? &folder : &root);
294 if (!node)
295 {
296 ret = ERR_MALLOC;
297 break;
298 }
299
300 utf8 = ticonv_varname_to_utf8(handle->model, ve->name, ve->type);
301 ticalcs_slprintf(update_->text, sizeof(update_->text), _("Parsing %s"), utf8);
302 ticonv_utf8_free(utf8);
303 update_label();
304 }
305 }
306
307 return ret;
308 }
309
get_memfree(CalcHandle * handle,uint32_t * ram,uint32_t * flash)310 static int get_memfree (CalcHandle* handle, uint32_t* ram, uint32_t* flash)
311 {
312 static const uint16_t pids[] = { DUSB_PID_FREE_RAM, DUSB_PID_FREE_FLASH };
313 const int size = sizeof(pids) / sizeof(uint16_t);
314 DUSBCalcParam **params;
315 int ret;
316
317 params = dusb_cp_new_array(handle, size);
318 ret = dusb_cmd_s_param_request(handle, size, pids);
319 if (!ret)
320 {
321 ret = dusb_cmd_r_param_data(handle, size, params);
322 if (!ret)
323 {
324 *ram = ( (((uint32_t)(params[0]->data[4])) << 24)
325 | (((uint32_t)(params[0]->data[5])) << 16)
326 | (((uint32_t)(params[0]->data[6])) << 8)
327 | (((uint32_t)(params[0]->data[7])) ));
328 *flash = ( (((uint32_t)(params[1]->data[4])) << 24)
329 | (((uint32_t)(params[1]->data[5])) << 16)
330 | (((uint32_t)(params[1]->data[6])) << 8)
331 | (((uint32_t)(params[1]->data[7])) ));
332 }
333 }
334 dusb_cp_del_array(handle, size, params);
335
336 return ret;
337 }
338
send_backup(CalcHandle * handle,BackupContent * content)339 static int send_backup (CalcHandle* handle, BackupContent* content)
340 {
341 DUSBCalcAttr **attrs;
342 const int nattrs = 3;
343 uint32_t length;
344 uint8_t *data, *p;
345 int ret = 0;
346 static const uint16_t keys[] = {
347 KEY83P_Quit, KEY83P_LinkIO, KEY83P_Right, KEY83P_1
348 };
349 unsigned int i;
350
351 attrs = dusb_ca_new_array(handle, nattrs);
352 attrs[0] = dusb_ca_new(handle, DUSB_AID_VAR_TYPE, 4);
353 attrs[0]->data[0] = 0xF0; attrs[0]->data[1] = 0x07;
354 attrs[0]->data[2] = 0x00; attrs[0]->data[3] = TI84p_BKUP;
355
356 attrs[1] = dusb_ca_new(handle, DUSB_AID_VAR_VERSION, 4);
357 attrs[1]->data[0] = 0x00; attrs[1]->data[1] = 0x00;
358 attrs[1]->data[2] = 0x00; attrs[1]->data[3] = content->version;
359
360 attrs[2] = dusb_ca_new(handle, DUSB_AID_BACKUP_HEADER, 8);
361 attrs[2]->data[0] = MSB(content->data_length1);
362 attrs[2]->data[1] = LSB(content->data_length1);
363 attrs[2]->data[2] = MSB(content->data_length2);
364 attrs[2]->data[3] = LSB(content->data_length2);
365 attrs[2]->data[4] = MSB(content->data_length3);
366 attrs[2]->data[5] = LSB(content->data_length3);
367 attrs[2]->data[6] = MSB(content->mem_address);
368 attrs[2]->data[7] = LSB(content->mem_address);
369
370 length = content->data_length1 + content->data_length2 + content->data_length3;
371 data = p = g_malloc(length);
372 memcpy(p, content->data_part1, content->data_length1);
373 p += content->data_length1;
374 memcpy(p, content->data_part2, content->data_length2);
375 p += content->data_length2;
376 memcpy(p, content->data_part3, content->data_length3);
377
378 // enter manual link mode
379 for (i = 0; i < sizeof(keys) / sizeof(keys[0]) - 1; i++)
380 {
381 ret = send_key(handle, (uint32_t)(keys[i]));
382 if (ret)
383 {
384 goto end;
385 }
386 }
387 ret = send_key_noack(handle, (uint32_t)(keys[i]));
388 if (ret)
389 {
390 goto end;
391 }
392
393 // send backup header
394 ret = dusb_cmd_s_rts_ns(handle, "", "!", length, 3, CA(attrs));
395 if (ret)
396 {
397 goto end;
398 }
399 ret = dusb_cmd_r_delay_ack(handle);
400 if (ret)
401 {
402 goto end;
403 }
404
405 // press key to accept the backup
406 ret = send_key_noack(handle, KEY83P_1);
407 if (ret)
408 {
409 goto end;
410 }
411
412 // acknowledgement of RTS
413 ret = dusb_cmd_r_data_ack(handle);
414 if (ret)
415 {
416 goto end;
417 }
418
419 // send backup contents
420 ret = dusb_cmd_s_var_content(handle, length, data);
421 if (ret)
422 {
423 goto end;
424 }
425 ret = dusb_cmd_r_data_ack(handle);
426 if (ret)
427 {
428 goto end;
429 }
430 ret = dusb_cmd_s_eot(handle);
431
432 end:
433 dusb_ca_del_array(handle, nattrs, attrs);
434 g_free(data);
435
436 return ret;
437 }
438
send_var(CalcHandle * handle,CalcMode mode,FileContent * content)439 static int send_var (CalcHandle* handle, CalcMode mode, FileContent* content)
440 {
441 unsigned int i;
442 int ret = 0;
443
444 for (i = 0; i < content->num_entries; i++)
445 {
446 DUSBCalcAttr **attrs;
447 const int nattrs = 3;
448 VarEntry *entry = content->entries[i];
449 uint32_t size;
450
451 if (!ticalcs_validate_varentry(entry))
452 {
453 ticalcs_critical("%s: skipping invalid content entry #%u", __FUNCTION__, i);
454 continue;
455 }
456
457 if (entry->action == ACT_SKIP)
458 {
459 ticalcs_info("%s: skipping variable #%u because requested", __FUNCTION__, i);
460 continue;
461 }
462
463 ticonv_varname_to_utf8_sn(handle->model, entry->name, update_->text, sizeof(update_->text), entry->type);
464 update_label();
465
466 attrs = dusb_ca_new_array(handle, nattrs);
467 attrs[0] = dusb_ca_new(handle, DUSB_AID_VAR_TYPE, 4);
468 attrs[0]->data[0] = 0xF0; attrs[0]->data[1] = 0x07;
469 attrs[0]->data[2] = 0x00; attrs[0]->data[3] = entry->type;
470 attrs[1] = dusb_ca_new(handle, DUSB_AID_ARCHIVED, 1);
471 attrs[1]->data[0] = entry->attr == ATTRB_ARCHIVED ? 1 : 0;
472 attrs[2] = dusb_ca_new(handle, DUSB_AID_VAR_VERSION, 4);
473 attrs[2]->data[3] = entry->version;
474
475 size = entry->size;
476 if (entry->size >= 65536U)
477 {
478 ticalcs_critical("%s: variable size %u is suspiciously large", __FUNCTION__, size);
479 }
480
481 ret = dusb_cmd_s_rts(handle, "", entry->name, size, nattrs, CA(attrs));
482 dusb_ca_del_array(handle, nattrs, attrs);
483 if (ret)
484 {
485 break;
486 }
487 ret = dusb_cmd_r_data_ack(handle);
488 if (ret)
489 {
490 break;
491 }
492 ret = dusb_cmd_s_var_content(handle, size, entry->data);
493 if (ret)
494 {
495 break;
496 }
497 ret = dusb_cmd_r_data_ack(handle);
498 if (ret)
499 {
500 break;
501 }
502 ret = dusb_cmd_s_eot(handle);
503 if (ret)
504 {
505 break;
506 }
507
508 update_->cnt2 = i + 1;
509 update_->max2 = content->num_entries;
510 update_->pbar();
511
512 PAUSE(50); // needed
513 }
514
515 return ret;
516 }
517
recv_var(CalcHandle * handle,CalcMode mode,FileContent * content,VarRequest * vr)518 static int recv_var (CalcHandle* handle, CalcMode mode, FileContent* content, VarRequest* vr)
519 {
520 static const uint16_t aids[] = { DUSB_AID_ARCHIVED, DUSB_AID_VAR_VERSION, DUSB_AID_VAR_SIZE };
521 const int naids = sizeof(aids) / sizeof(uint16_t);
522 DUSBCalcAttr **attrs;
523 const int nattrs = 1;
524 char fldname[40], varname[40];
525 uint8_t *data;
526 VarEntry *ve;
527 int ret;
528
529 ticonv_varname_to_utf8_sn(handle->model, vr->name, update_->text, sizeof(update_->text), vr->type);
530 update_label();
531
532 attrs = dusb_ca_new_array(handle, nattrs);
533 attrs[0] = dusb_ca_new(handle, DUSB_AID_VAR_TYPE2, 4);
534 attrs[0]->data[0] = 0xF0; attrs[0]->data[1] = 0x07;
535 attrs[0]->data[2] = 0x00; attrs[0]->data[3] = vr->type;
536
537 ret = dusb_cmd_s_var_request(handle, "", vr->name, naids, aids, nattrs, CA(attrs));
538 dusb_ca_del_array(handle, nattrs, attrs);
539 if (!ret)
540 {
541 attrs = dusb_ca_new_array(handle, naids);
542 ret = dusb_cmd_r_var_header(handle, fldname, varname, attrs);
543 if (!ret)
544 {
545 ret = dusb_cmd_r_var_content(handle, NULL, &data);
546 if (!ret)
547 {
548 content->model = handle->model;
549 ticalcs_strlcpy(content->comment, tifiles_comment_set_single(), sizeof(content->comment));
550 content->num_entries = 1;
551
552 content->entries = tifiles_ve_create_array(1);
553 ve = content->entries[0] = tifiles_ve_create();
554 memcpy(ve, vr, sizeof(VarEntry));
555
556 ve->size = ( (((uint32_t)(attrs[2]->data[0])) << 24)
557 | (((uint32_t)(attrs[2]->data[1])) << 16)
558 | (((uint32_t)(attrs[2]->data[2])) << 8)
559 | (((uint32_t)(attrs[2]->data[3])) ));
560
561 if (attrs[0]->size == 1)
562 {
563 ve->attr = (attrs[0]->data[0] ? ATTRB_ARCHIVED : 0);
564 }
565 if (attrs[1]->size == 4)
566 {
567 ve->version = attrs[1]->data[3];
568 }
569
570 if (ve->type == TI83p_PIC)
571 {
572 if (ve->version >= 0xa)
573 {
574 content->model = CALC_TI84PC_USB;
575 }
576 else
577 {
578 content->model = CALC_TI84P_USB;
579 }
580 }
581
582 ve->data = tifiles_ve_alloc_data(ve->size);
583 memcpy(ve->data, data, ve->size);
584
585 g_free(data);
586 }
587 }
588 dusb_ca_del_array(handle, naids, attrs);
589 }
590
591 return ret;
592 }
593
send_all_vars_backup(CalcHandle * handle,FileContent * content)594 static int send_all_vars_backup (CalcHandle* handle, FileContent* content)
595 {
596 return send_var(handle, MODE_BACKUP, content);
597 }
598
send_flash(CalcHandle * handle,FlashContent * content)599 static int send_flash (CalcHandle* handle, FlashContent* content)
600 {
601 FlashContent *ptr;
602 unsigned int i;
603 DUSBCalcAttr **attrs;
604 const int nattrs = 2;
605 int ret = 0;
606
607 uint8_t *data;
608 uint32_t size;
609
610 // search for data header
611 for (ptr = content; ptr != NULL; ptr = ptr->next)
612 {
613 if (ptr->data_type == TI83p_AMS || ptr->data_type == TI83p_APPL)
614 {
615 break;
616 }
617 }
618 if ( ptr == NULL
619 || ptr->data_type != TI83p_APPL
620 || ptr->pages == NULL)
621 {
622 return ERR_INVALID_PARAMETER;
623 }
624
625 #if 0
626 ticalcs_debug("#pages: %i", ptr->num_pages);
627 ticalcs_debug("type: %02x", ptr->data_type);
628 for (i = 0; i < ptr->num_pages; i++)
629 {
630 FlashPage *fp = ptr->pages[i];
631
632 ticalcs_debug("page #%i: %04x %02x %02x %04x", i, fp->addr, fp->page, fp->flag, fp->size);
633 }
634 ticalcs_debug("data length: %08x", ptr->data_length);
635 #endif
636
637 size = ptr->num_pages * FLASH_PAGE_SIZE;
638 data = tifiles_fp_alloc_data(size); // must be rounded-up
639 if (data == NULL)
640 {
641 return ERR_MALLOC;
642 }
643
644 update_->cnt2 = 0;
645 update_->max2 = ptr->num_pages;
646
647 for (i = 0; i < ptr->num_pages; i++)
648 {
649 FlashPage *fp = ptr->pages[i];
650 memcpy(data + i*FLASH_PAGE_SIZE, fp->data, FLASH_PAGE_SIZE);
651
652 update_->cnt2 = i;
653 update_->pbar();
654 }
655 {
656 FlashPage *fp = ptr->pages[--i];
657 memset(data + i*FLASH_PAGE_SIZE + fp->size, 0x00, FLASH_PAGE_SIZE - fp->size);
658
659 update_->cnt2 = i;
660 update_->pbar();
661 }
662
663 // send
664 ticonv_varname_to_utf8_sn(handle->model, ptr->name, update_->text, sizeof(update_->text), ptr->data_type);
665 update_label();
666
667 attrs = dusb_ca_new_array(handle, nattrs);
668 attrs[0] = dusb_ca_new(handle, DUSB_AID_VAR_TYPE, 4);
669 attrs[0]->data[0] = 0xF0; attrs[0]->data[1] = 0x07;
670 attrs[0]->data[2] = 0x00; attrs[0]->data[3] = ptr->data_type;
671 attrs[1] = dusb_ca_new(handle, DUSB_AID_ARCHIVED, 1);
672 attrs[1]->data[0] = 0;
673
674 ret = dusb_cmd_s_rts(handle, "", ptr->name, size, nattrs, CA(attrs));
675 dusb_ca_del_array(handle, nattrs, attrs);
676 if (!ret)
677 {
678 ret = dusb_cmd_r_data_ack(handle);
679 if (!ret)
680 {
681 ret = dusb_cmd_s_var_content(handle, size, data);
682 if (!ret)
683 {
684 ret = dusb_cmd_r_data_ack(handle);
685 if (!ret)
686 {
687 ret = dusb_cmd_s_eot(handle);
688 }
689 }
690 }
691 }
692
693 g_free(data);
694
695 return ret;
696 }
697
send_flash_834pce(CalcHandle * handle,FlashContent * content)698 static int send_flash_834pce (CalcHandle* handle, FlashContent* content)
699 {
700 FlashContent *ptr;
701 DUSBCalcAttr **attrs;
702 const int nattrs = 2;
703 int ret = 0;
704
705 uint8_t *data;
706 uint32_t size;
707
708 // search for data header
709 for (ptr = content; ptr != NULL; ptr = ptr->next)
710 {
711 if (ptr->data_type == TI83p_AMS || ptr->data_type == TI83p_APPL)
712 {
713 break;
714 }
715 }
716 if ( ptr == NULL
717 || ptr->data_type != TI83p_APPL
718 || ptr->data_part == NULL)
719 {
720 return ERR_INVALID_PARAMETER;
721 }
722
723 size = ptr->data_length;
724 data = ptr->data_part;
725
726 update_->cnt2 = 0;
727 update_->max2 = 0;
728
729 // send
730 ticonv_varname_to_utf8_sn(handle->model, ptr->name, update_->text, sizeof(update_->text), ptr->data_type);
731 update_label();
732
733 attrs = dusb_ca_new_array(handle, nattrs);
734 attrs[0] = dusb_ca_new(handle, DUSB_AID_VAR_TYPE, 4);
735 attrs[0]->data[0] = 0xF0; attrs[0]->data[1] = 0x0F;
736 attrs[0]->data[2] = 0x00; attrs[0]->data[3] = ptr->data_type;
737 attrs[1] = dusb_ca_new(handle, DUSB_AID_ARCHIVED, 1);
738 attrs[1]->data[0] = 1;
739
740 ret = dusb_cmd_s_rts(handle, "", ptr->name, size, nattrs, CA(attrs));
741 dusb_ca_del_array(handle, nattrs, attrs);
742 if (!ret)
743 {
744 ret = dusb_cmd_r_data_ack(handle);
745 if (!ret)
746 {
747 ret = dusb_cmd_s_var_content(handle, size, data);
748 if (!ret)
749 {
750 ret = dusb_cmd_r_data_ack(handle);
751 if (!ret)
752 {
753 ret = dusb_cmd_s_eot(handle);
754 }
755 }
756 }
757 }
758
759 return ret;
760 }
761
recv_flash(CalcHandle * handle,FlashContent * content,VarRequest * vr)762 static int recv_flash (CalcHandle* handle, FlashContent* content, VarRequest* vr)
763 {
764 static const uint16_t aids[] = { DUSB_AID_ARCHIVED, DUSB_AID_VAR_VERSION };
765 const int naids = sizeof(aids) / sizeof(uint16_t);
766 DUSBCalcAttr **attrs;
767 const int nattrs = 1;
768 char fldname[40], varname[40];
769 uint8_t *data;
770 uint32_t data_length;
771 int page;
772 uint16_t data_addr = 0x4000;
773 uint16_t data_page = 0;
774 int r, q;
775 int ret;
776
777 ticonv_varname_to_utf8_sn(handle->model, vr->name, update_->text, sizeof(update_->text), vr->type);
778 update_label();
779
780 attrs = dusb_ca_new_array(handle, nattrs);
781 attrs[0] = dusb_ca_new(handle, DUSB_AID_VAR_TYPE2, 4);
782 attrs[0]->data[0] = 0xF0; attrs[0]->data[1] = 0x07;
783 attrs[0]->data[2] = 0x00; attrs[0]->data[3] = vr->type;
784
785 ret = dusb_cmd_s_var_request(handle, "", vr->name, naids, aids, nattrs, CA(attrs));
786 dusb_ca_del_array(handle, nattrs, attrs);
787 if (!ret)
788 {
789 attrs = dusb_ca_new_array(handle, naids);
790 ret = dusb_cmd_r_var_header(handle, fldname, varname, attrs);
791 if (!ret)
792 {
793 ret = dusb_cmd_r_var_content(handle, &data_length, &data);
794 if (!ret)
795 {
796
797 content->model = handle->model;
798 ticalcs_strlcpy(content->name, vr->name, sizeof(content->name));
799 content->data_type = vr->type;
800 content->device_type = DEVICE_TYPE_83P;
801
802 q = data_length / FLASH_PAGE_SIZE;
803 r = data_length % FLASH_PAGE_SIZE;
804 content->num_pages = q + 1;
805 content->pages = tifiles_fp_create_array(content->num_pages);
806
807 update_->cnt2 = 0;
808 update_->max2 = q;
809
810 for (page = 0; page < q; page++)
811 {
812 FlashPage *fp = content->pages[page] = tifiles_fp_create();
813
814 fp->addr = data_addr;
815 fp->page = data_page++;
816 fp->flag = 0x80;
817 fp->size = FLASH_PAGE_SIZE;
818 fp->data = tifiles_fp_alloc_data(FLASH_PAGE_SIZE);
819 memcpy(fp->data, data + FLASH_PAGE_SIZE*page, FLASH_PAGE_SIZE);
820
821 update_->cnt2 = page;
822 update_->pbar();
823 }
824 {
825 FlashPage *fp = content->pages[page] = tifiles_fp_create();
826
827 fp->addr = data_addr;
828 fp->page = data_page++;
829 fp->flag = 0x80;
830 fp->size = r;
831 fp->data = tifiles_fp_alloc_data(FLASH_PAGE_SIZE);
832 memcpy(fp->data, data + FLASH_PAGE_SIZE*page, r);
833
834 update_->cnt2 = page;
835 update_->pbar();
836 }
837 content->num_pages = page+1;
838
839 g_free(data);
840 }
841 }
842 dusb_ca_del_array(handle, naids, attrs);
843 }
844
845 return ret;
846 }
847
recv_flash_834pce(CalcHandle * handle,FlashContent * content,VarRequest * vr)848 static int recv_flash_834pce (CalcHandle* handle, FlashContent* content, VarRequest* vr)
849 {
850 static const uint16_t aids[] = { DUSB_AID_ARCHIVED, DUSB_AID_VAR_VERSION };
851 const int naids = sizeof(aids) / sizeof(uint16_t);
852 DUSBCalcAttr **attrs;
853 const int nattrs = 1;
854 char fldname[40], varname[40];
855 uint8_t *data;
856 uint32_t data_length;
857 int ret;
858
859 ticonv_varname_to_utf8_sn(handle->model, vr->name, update_->text, sizeof(update_->text), vr->type);
860 update_label();
861
862 attrs = dusb_ca_new_array(handle, nattrs);
863 attrs[0] = dusb_ca_new(handle, DUSB_AID_VAR_TYPE2, 4);
864 attrs[0]->data[0] = 0xF0; attrs[0]->data[1] = 0x0F;
865 attrs[0]->data[2] = 0x00; attrs[0]->data[3] = vr->type;
866
867 ret = dusb_cmd_s_var_request(handle, "", vr->name, naids, aids, nattrs, CA(attrs));
868 dusb_ca_del_array(handle, nattrs, attrs);
869 if (!ret)
870 {
871 attrs = dusb_ca_new_array(handle, naids);
872 ret = dusb_cmd_r_var_header(handle, fldname, varname, attrs);
873 if (!ret)
874 {
875 ret = dusb_cmd_r_var_content(handle, &data_length, &data);
876 if (!ret)
877 {
878
879 content->model = handle->model;
880 ticalcs_strlcpy(content->name, vr->name, sizeof(content->name));
881 content->data_type = vr->type;
882 content->device_type = DEVICE_TYPE_83P;
883 content->data_length = data_length;
884 content->data_part = data; // Borrow this memory block.
885 content->hw_id = handle->calc->product_id;
886
887 // Do NOT g_free(data);
888 }
889 }
890 dusb_ca_del_array(handle, naids, attrs);
891 }
892
893 return ret;
894 }
895
send_os(CalcHandle * handle,FlashContent * content)896 static int send_os (CalcHandle* handle, FlashContent* content)
897 {
898 DUSBModeSet mode = { 2, 1, 0, 0, 0x0fa0 }; //MODE_BASIC;
899 uint32_t pkt_size = 266;
900 uint32_t os_size = 0;
901 FlashContent *ptr;
902 unsigned int i, j;
903 int boot = 0;
904 int ret;
905
906 // search for data header
907 for (ptr = content; ptr != NULL; ptr = ptr->next)
908 {
909 if (ptr->data_type == TI83p_AMS || ptr->data_type == TI83p_APPL)
910 {
911 break;
912 }
913 }
914 if (ptr == NULL)
915 {
916 return ERR_INVALID_PARAMETER;
917 }
918 if (ptr->data_type != TI83p_AMS)
919 {
920 return ERR_INVALID_PARAMETER;
921 }
922 if (ptr->pages == NULL)
923 {
924 return ERR_INVALID_PARAMETER;
925 }
926
927 #if 0
928 ticalcs_debug("#pages: %i", ptr->num_pages);
929 ticalcs_debug("type: %02x", ptr->data_type);
930 for (i = 0; i < ptr->num_pages; i++)
931 {
932 FlashPage *fp = ptr->pages[i];
933
934 ticalcs_debug("page #%i: %04x %02x %02x %04x", i,
935 fp->addr, fp->page, fp->flag, fp->size);
936 //tifiles_hexdump(fp->data, 16);
937 }
938 ticalcs_debug("data length = %08x %i", ptr->data_length, ptr->data_length);
939 #endif
940
941 for (i = 0; i < ptr->num_pages; i++)
942 {
943 FlashPage *fp = ptr->pages[i];
944
945 if (fp->size < 256)
946 {
947 os_size += 4;
948 }
949 else
950 {
951 os_size += 4*(fp->size / 260);
952 }
953 }
954 ticalcs_debug("os_size overhead = %i", os_size);
955 os_size += ptr->data_length;
956 ticalcs_debug("os_size new = %i", os_size);
957
958 do
959 {
960 static const uint16_t pids[] = { DUSB_PID_OS_MODE };
961 const int size = sizeof(pids) / sizeof(uint16_t);
962 DUSBCalcParam **params;
963
964 // switch to BASIC mode
965 ret = dusb_cmd_s_mode_set(handle, mode);
966 if (ret)
967 {
968 break;
969 }
970 ret = dusb_cmd_r_mode_ack(handle);
971 if (ret)
972 {
973 break;
974 }
975
976 // test for boot mode
977 ret = dusb_cmd_s_param_request(handle, size, pids);
978 if (ret)
979 {
980 break;
981 }
982 params = dusb_cp_new_array(handle, size);
983 ret = dusb_cmd_r_param_data(handle, size, params);
984 if (ret)
985 {
986 dusb_cp_del_array(handle, size, params);
987 break;
988 }
989 boot = !params[0]->data[0];
990 dusb_cp_del_array(handle, size, params);
991
992 // start OS transfer
993 ret = dusb_cmd_s_os_begin(handle, os_size);
994 if (ret)
995 {
996 break;
997 }
998 if (!boot)
999 {
1000 ret = dusb_recv_buf_size_request(handle, &pkt_size);
1001 if (ret)
1002 {
1003 break;
1004 }
1005 ret = dusb_send_buf_size_alloc(handle, pkt_size);
1006 if (ret)
1007 {
1008 break;
1009 }
1010 }
1011 ret = dusb_cmd_r_os_ack(handle, &pkt_size); // this pkt_size is important
1012 if (ret)
1013 {
1014 break;
1015 }
1016
1017 // send OS header/signature
1018 ret = dusb_cmd_s_os_header(handle, 0x4000, 0x7A, 0x80, pkt_size-4, ptr->pages[0]->data);
1019 if (ret)
1020 {
1021 break;
1022 }
1023 ret = dusb_cmd_r_os_ack(handle, &pkt_size);
1024 if (ret)
1025 {
1026 break;
1027 }
1028
1029 // send OS data
1030 update_->cnt2 = 0;
1031 update_->max2 = ptr->num_pages;
1032
1033 for (i = 0; i < ptr->num_pages; i++)
1034 {
1035 FlashPage *fp = ptr->pages[i];
1036
1037 fp->addr = 0x4000;
1038
1039 if (i == 0) // need relocation
1040 {
1041 ret = dusb_cmd_s_os_data(handle, 0x4000, 0x7A, 0x80, pkt_size-4, fp->data);
1042 if (ret)
1043 {
1044 goto end;
1045 }
1046 ret = dusb_cmd_r_data_ack(handle);
1047 if (ret)
1048 {
1049 goto end;
1050 }
1051 }
1052 else if (i == ptr->num_pages-1) // idem
1053 {
1054 ret = dusb_cmd_s_os_data(handle, 0x4100, 0x7A, 0x80, pkt_size-4, fp->data);
1055 if (ret)
1056 {
1057 goto end;
1058 }
1059 ret = dusb_cmd_r_data_ack(handle);
1060 if (ret)
1061 {
1062 goto end;
1063 }
1064 }
1065 else
1066 {
1067 for (j = 0; j < fp->size; j += 256)
1068 {
1069 ret = dusb_cmd_s_os_data(handle,
1070 (uint16_t)(fp->addr + j), (uint8_t)fp->page, fp->flag,
1071 pkt_size-4, fp->data + j);
1072 if (ret)
1073 {
1074 goto end;
1075 }
1076 ret = dusb_cmd_r_data_ack(handle);
1077 if (ret)
1078 {
1079 goto end;
1080 }
1081 }
1082 }
1083
1084 update_->cnt2 = i;
1085 update_->pbar();
1086 }
1087
1088 ret = dusb_cmd_s_eot(handle);
1089 if (ret)
1090 {
1091 break;
1092 }
1093 PAUSE(500);
1094 ret = dusb_cmd_r_eot_ack(handle);
1095 } while (0);
1096 end:
1097
1098 return ret;
1099 }
1100
send_os_834pce(CalcHandle * handle,FlashContent * content)1101 static int send_os_834pce (CalcHandle* handle, FlashContent* content)
1102 {
1103 DUSBModeSet mode = { 2, 1, 0, 0, 0x0fa0 }; //MODE_BASIC;
1104 uint32_t pkt_size = 0x3ff;
1105 uint32_t hdr_size = 0;
1106 uint32_t hdr_offset = 0;
1107 const uint32_t memory_offset = 0x30000U;
1108 FlashContent *ptr;
1109 uint8_t *d;
1110 int i, r, q;
1111 int ret;
1112
1113 // search for data header
1114 for (ptr = content; ptr != NULL; ptr = ptr->next)
1115 {
1116 if (ptr->data_type == TI83p_AMS || ptr->data_type == TI83p_APPL)
1117 {
1118 break;
1119 }
1120 }
1121 if (ptr == NULL)
1122 {
1123 return ERR_INVALID_PARAMETER;
1124 }
1125 if (ptr->data_type != TI83p_AMS)
1126 {
1127 return ERR_INVALID_PARAMETER;
1128 }
1129 if (ptr->data_part == NULL)
1130 {
1131 return ERR_INVALID_PARAMETER;
1132 }
1133
1134 // search for OS header (offset & size)
1135 hdr_offset = 0;
1136 for (i = 0, d = ptr->data_part; (d[i] != 0xFF) || (d[i+1] != 0xFF) || (d[i+2] != 0xFF) || (d[i+3] != 0xFF); i++);
1137 hdr_size = i - hdr_offset;
1138
1139 do
1140 {
1141 // switch to BASIC mode
1142 ret = dusb_cmd_s_mode_set(handle, mode);
1143 if (ret)
1144 {
1145 break;
1146 }
1147 ret = dusb_cmd_r_mode_ack(handle);
1148 if (ret)
1149 {
1150 break;
1151 }
1152
1153 // start OS transfer
1154 ret = dusb_cmd_s_os_begin(handle, ptr->data_length);
1155 if (ret)
1156 {
1157 break;
1158 }
1159 ret = dusb_cmd_r_os_ack(handle, &pkt_size);
1160 if (ret)
1161 {
1162 break;
1163 }
1164
1165 // send OS header/signature
1166 ret = dusb_cmd_s_os_header_89(handle, hdr_size, ptr->data_part + hdr_offset);
1167 if (ret)
1168 {
1169 break;
1170 }
1171 ret = dusb_cmd_r_os_ack(handle, &pkt_size);
1172 if (ret)
1173 {
1174 break;
1175 }
1176
1177 // send OS data
1178 q = ptr->data_length / (pkt_size - 4);
1179 r = ptr->data_length % (pkt_size - 4);
1180
1181 update_->cnt2 = 0;
1182 update_->max2 = q;
1183
1184 for (i = 0; i < q; i++)
1185 {
1186 ret = dusb_cmd_s_os_data_834pce(handle, memory_offset + i*(pkt_size - 4), (pkt_size - 4), ptr->data_part + i*(pkt_size - 4));
1187 if (ret)
1188 {
1189 goto end;
1190 }
1191 ret = dusb_cmd_r_data_ack(handle);
1192 if (ret)
1193 {
1194 goto end;
1195 }
1196
1197 update_->cnt2 = i;
1198 update_->pbar();
1199 }
1200
1201 ret = dusb_cmd_s_os_data_834pce(handle, memory_offset + q*(pkt_size - 4), r, ptr->data_part + i*(pkt_size - 4));
1202 if (ret)
1203 {
1204 break;
1205 }
1206 ret = dusb_cmd_r_data_ack(handle);
1207 if (ret)
1208 {
1209 break;
1210 }
1211
1212 update_->cnt2 = i;
1213 update_->pbar();
1214
1215 ret = dusb_cmd_s_eot(handle);
1216 if (ret)
1217 {
1218 break;
1219 }
1220 PAUSE(500);
1221 ret = dusb_cmd_r_eot_ack(handle);
1222 } while (0);
1223 end:
1224
1225 return ret;
1226 }
1227
recv_idlist(CalcHandle * handle,uint8_t * id)1228 static int recv_idlist (CalcHandle* handle, uint8_t* id)
1229 {
1230 static const uint16_t aids[] = { DUSB_AID_ARCHIVED, DUSB_AID_VAR_VERSION };
1231 const int naids = sizeof(aids) / sizeof(uint16_t);
1232 DUSBCalcAttr **attrs;
1233 const int nattrs = 1;
1234 char folder[40], name[40];
1235 uint8_t *data;
1236 uint32_t i, varsize;
1237 int ret;
1238
1239 ticalcs_strlcpy(update_->text, "ID-LIST", sizeof(update_->text));
1240 update_label();
1241
1242 attrs = dusb_ca_new_array(handle, nattrs);
1243 attrs[0] = dusb_ca_new(handle, DUSB_AID_VAR_TYPE2, 4);
1244 attrs[0]->data[0] = 0xF0; attrs[0]->data[1] = 0x07;
1245 attrs[0]->data[2] = 0x00; attrs[0]->data[3] = TI83p_IDLIST;
1246
1247 ret = dusb_cmd_s_var_request(handle, "", "IDList", naids, aids, nattrs, CA(attrs));
1248 dusb_ca_del_array(handle, nattrs, attrs);
1249 if (!ret)
1250 {
1251 attrs = dusb_ca_new_array(handle, naids);
1252 ret = dusb_cmd_r_var_header(handle, folder, name, attrs);
1253 if (!ret)
1254 {
1255 ret = dusb_cmd_r_var_content(handle, &varsize, &data);
1256 if (!ret)
1257 {
1258 i = data[9];
1259 data[9] = data[10];
1260 data[10] = i;
1261
1262 for (i = 4; i < varsize && i < 16; i++)
1263 {
1264 sprintf((char *)&id[2 * (i-4)], "%02x", data[i]);
1265 }
1266 id[7*2] = '\0';
1267
1268 g_free(data);
1269 }
1270 }
1271 dusb_ca_del_array(handle, naids, attrs);
1272 }
1273
1274 return ret;
1275 }
1276
1277 static int get_version (CalcHandle* handle, CalcInfos* infos);
1278
dump_rom_1(CalcHandle * handle)1279 static int dump_rom_1 (CalcHandle* handle)
1280 {
1281 CalcInfos infos;
1282 int ret;
1283
1284 ret = get_version(handle, &infos);
1285 if (!ret)
1286 {
1287 PAUSE(100);
1288 if (infos.model == CALC_TI84P_USB)
1289 {
1290 ret = rd_send(handle, "romdump.8Xp", romDumpSize84p, romDump84p);
1291 }
1292 else if (infos.model == CALC_TI84PC_USB)
1293 {
1294 ret = rd_send(handle, "romdump.8Xp", romDumpSize84pcu, romDump84pcu);
1295 }
1296 else if (infos.model == CALC_TI84PCE_USB || infos.model == CALC_TI83PCE_USB)
1297 {
1298 ret = rd_send(handle, "romdump.8Xp", romDumpSize834pceu, romDump834pceu);
1299 }
1300 else
1301 {
1302 ret = 0;
1303 }
1304 }
1305
1306 return ret;
1307 }
1308
dump_rom_2(CalcHandle * handle,CalcDumpSize size,const char * filename)1309 static int dump_rom_2 (CalcHandle* handle, CalcDumpSize size, const char *filename)
1310 {
1311 CalcInfos infos;
1312 int ret;
1313
1314 ret = get_version(handle, &infos);
1315 if (!ret)
1316 {
1317 PAUSE(100);
1318 if (infos.model == CALC_TI84PCE_USB || infos.model == CALC_TI83PCE_USB)
1319 {
1320 // The TI-eZ80 series does no longer provide direct remote program launch...
1321 // Therefore, use a less sophisticated and more complicated way to queue keypresses.
1322 unsigned int i;
1323 unsigned int iterations;
1324 static const uint16_t keys[] = {
1325 0x40, 0x09, 0x09, 0xFC9C, /* Quit, Clear, Clear, Asm( */
1326 0xDA, 0xAB, 0xA8, 0xA6, /* prgm, R, O, M */
1327 0x9D, 0xAE, 0xA6, 0xA9, /* D, U, M, P */
1328 0x86 /* ) */
1329 };
1330 FILE *f;
1331
1332 f = fopen(filename, "wb");
1333 if (f == NULL)
1334 {
1335 return ERR_OPEN_FILE;
1336 }
1337
1338 // Launch program by remote control
1339 PAUSE(200);
1340 for (i = 0; i < sizeof(keys) / sizeof(keys[0]); i++)
1341 {
1342 ret = send_key(handle, (uint32_t)(keys[i]));
1343 if (ret)
1344 {
1345 goto end;
1346 }
1347 PAUSE(100);
1348 }
1349
1350 // Keep synchronized with the ROM dumper's source code, here and below. For now, it dumps 16 KB at a time.
1351 iterations = (uint32_t)(infos.flash_phys / 0x4000);
1352
1353 for (i = 0; !ret && i < iterations; i++)
1354 {
1355 ret = dusb_cmd_s_execute(handle, "", "", DUSB_EID_KEY, "", 0x05);
1356 if (!ret)
1357 {
1358 FileContent *content;
1359 VarEntry ve;
1360
1361 ret = dusb_cmd_r_delay_ack(handle);
1362 PAUSE(400);
1363 ticables_cable_reset(handle->cable);
1364
1365 memset(&ve, 0, sizeof(VarEntry));
1366 ticalcs_strlcpy(ve.name, "ROMDATA", sizeof(ve.name));
1367 ve.type = 0x06; // PPRGM / ASM.
1368
1369 content = tifiles_content_create_regular(handle->model);
1370 if (content == NULL)
1371 {
1372 ret = ERR_MALLOC;
1373 break;
1374 }
1375
1376 ret = is_ready(handle);
1377 if (!ret)
1378 {
1379 ret = recv_var(handle, 0 /* MODE_NORMAL */, content, &ve);
1380 PAUSE(200);
1381 if (!ret)
1382 {
1383 if (content->num_entries == 1 && content->entries && content->entries[0] && content->entries[0]->size == 16386)
1384 {
1385 // Skip the two leading bytes.
1386 if (fwrite(content->entries[0]->data + 2, content->entries[0]->size - 2, 1, f) < 1)
1387 {
1388 ret = ERR_SAVE_FILE;
1389 }
1390 }
1391 else
1392 {
1393 ret = ERR_INVALID_PACKET;
1394 }
1395 }
1396 }
1397 }
1398 }
1399 end:
1400 fclose(f);
1401
1402 }
1403 else
1404 {
1405 ret = dusb_cmd_s_execute(handle, "", "ROMDUMP", DUSB_EID_PRGM, "", 0);
1406 if (!ret)
1407 {
1408 ret = dusb_cmd_r_data_ack(handle);
1409 if (!ret)
1410 {
1411 PAUSE(3000);
1412
1413 // Get dump
1414 ret = rd_dump(handle, filename);
1415 }
1416 }
1417 }
1418 }
1419
1420 return ret;
1421 }
1422
set_clock(CalcHandle * handle,CalcClock * _clock)1423 static int set_clock (CalcHandle* handle, CalcClock* _clock)
1424 {
1425 static const uint16_t pids[2] = { DUSB_PID_CLASSIC_CLK_SUPPORT, DUSB_PID_NEW_CLK_SUPPORT };
1426 const int size = sizeof(pids) / sizeof(uint16_t);
1427 DUSBCalcParam **params;
1428 int ret;
1429
1430 // get raw clock
1431 ticalcs_strlcpy(update_->text, _("Getting clock..."), sizeof(update_->text));
1432 update_label();
1433
1434 params = dusb_cp_new_array(handle, size);
1435 ret = dusb_cmd_s_param_request(handle, size, pids);
1436 if (!ret)
1437 {
1438 ret = dusb_cmd_r_param_data(handle, size, params);
1439 if (!ret)
1440 {
1441 int classic_clock = !!params[0]->ok && !!!params[1]->ok;
1442 int new_clock = !!!params[0]->ok && !!params[1]->ok;
1443 if (!classic_clock && !new_clock)
1444 {
1445 ticalcs_warning(_("Could not determine clock type: %u %u"), params[0]->ok, params[1]->ok);
1446 }
1447 else if (classic_clock)
1448 {
1449 uint32_t calc_time;
1450 struct tm ref, cur;
1451 time_t r, c, now;
1452 uint8_t data[4];
1453
1454 ticalcs_info(_("Will set classic clock"));
1455
1456 time(&now);
1457 memcpy(&ref, localtime(&now), sizeof(struct tm));
1458
1459 ref.tm_year = 1997 - 1900;
1460 ref.tm_mon = 0;
1461 ref.tm_yday = 0;
1462 ref.tm_mday = 1;
1463 ref.tm_wday = 3;
1464 ref.tm_hour = 0;
1465 ref.tm_min = 0;
1466 ref.tm_sec = 0;
1467 //ref.tm_isdst = 1;
1468 r = mktime(&ref);
1469
1470 cur.tm_year = _clock->year - 1900;
1471 cur.tm_mon = _clock->month - 1;
1472 cur.tm_mday = _clock->day;
1473 cur.tm_hour = _clock->hours;
1474 cur.tm_min = _clock->minutes;
1475 cur.tm_sec = _clock->seconds;
1476 cur.tm_isdst = 1;
1477 c = mktime(&cur);
1478
1479 calc_time = (uint32_t)difftime(c, r);
1480
1481 ticalcs_strlcpy(update_->text, _("Setting clock..."), sizeof(update_->text));
1482 update_label();
1483
1484 data[0] = MSB(MSW(calc_time));
1485 data[1] = LSB(MSW(calc_time));
1486 data[2] = MSB(LSW(calc_time));
1487 data[3] = LSB(LSW(calc_time));
1488 ret = dusb_cmd_s_param_set_r_data_ack(handle, DUSB_PID_CLK_SEC_SINCE_1997, 4, data);
1489 if (!ret)
1490 {
1491 data[0] = _clock->date_format == 3 ? 0 : _clock->date_format;
1492 ret = dusb_cmd_s_param_set_r_data_ack(handle, DUSB_PID_CLK_DATE_FMT, 1, data);
1493 if (!ret)
1494 {
1495 data[0] = _clock->time_format == 24 ? 1 : 0;
1496 ret = dusb_cmd_s_param_set_r_data_ack(handle, DUSB_PID_CLK_TIME_FMT, 1, data);
1497 if (!ret)
1498 {
1499 data[0] = _clock->state;
1500 ret = dusb_cmd_s_param_set_r_data_ack(handle, DUSB_PID_CLK_ON, 1, data);
1501 }
1502 }
1503 }
1504 }
1505 else if (new_clock)
1506 {
1507 uint8_t data[4];
1508
1509 ticalcs_info(_("Will set new clock"));
1510
1511 ticalcs_strlcpy(update_->text, _("Setting clock..."), sizeof(update_->text));
1512 update_label();
1513
1514 data[0] = _clock->date_format == 3 ? 0 : _clock->date_format;
1515 ret = dusb_cmd_s_param_set_r_data_ack(handle, DUSB_PID_CLK_DATE_FMT, 1, data);
1516 if (!ret)
1517 {
1518 data[0] = _clock->time_format == 24 ? 0x81 : 0x80;
1519 ret = dusb_cmd_s_param_set_r_data_ack(handle, DUSB_PID_CLK_TIME_FMT, 1, data);
1520 if (!ret)
1521 {
1522 data[0] = (uint8_t)(_clock->year >> 8);
1523 data[1] = _clock->year & 0xFF;
1524 ret = dusb_cmd_s_param_set_r_data_ack(handle, DUSB_PID_CLK_YEAR, 2, data);
1525 if (!ret)
1526 {
1527 data[0] = _clock->month;
1528 ret = dusb_cmd_s_param_set_r_data_ack(handle, DUSB_PID_CLK_MONTH, 1, data);
1529 if (!ret)
1530 {
1531 data[0] = _clock->day;
1532 ret = dusb_cmd_s_param_set_r_data_ack(handle, DUSB_PID_CLK_DAY, 1, data);
1533 if (!ret)
1534 {
1535 data[0] = _clock->hours;
1536 ret = dusb_cmd_s_param_set_r_data_ack(handle, DUSB_PID_CLK_HOURS, 1, data);
1537 if (!ret)
1538 {
1539 data[0] = _clock->minutes;
1540 ret = dusb_cmd_s_param_set_r_data_ack(handle, DUSB_PID_CLK_MINUTES, 1, data);
1541 if (!ret)
1542 {
1543 data[0] = _clock->seconds;
1544 ret = dusb_cmd_s_param_set_r_data_ack(handle, DUSB_PID_CLK_SECONDS, 1, data);
1545 if (!ret)
1546 {
1547 data[0] = _clock->state;
1548 ret = dusb_cmd_s_param_set_r_data_ack(handle, DUSB_PID_CLK_ON, 1, data);
1549 }
1550 }
1551 }
1552 }
1553 }
1554 }
1555 }
1556 }
1557 }
1558 else
1559 {
1560 ret = ERR_INVALID_PACKET;
1561 }
1562 }
1563 }
1564 dusb_cp_del_array(handle, size, params);
1565
1566 return ret;
1567 }
1568
get_clock(CalcHandle * handle,CalcClock * _clock)1569 static int get_clock (CalcHandle* handle, CalcClock* _clock)
1570 {
1571 static const uint16_t pids[12] = {
1572 DUSB_PID_CLASSIC_CLK_SUPPORT, DUSB_PID_NEW_CLK_SUPPORT,
1573 DUSB_PID_CLK_ON, DUSB_PID_CLK_SEC_SINCE_1997, DUSB_PID_CLK_DATE_FMT, DUSB_PID_CLK_TIME_FMT,
1574 DUSB_PID_CLK_SECONDS, DUSB_PID_CLK_MINUTES, DUSB_PID_CLK_HOURS, DUSB_PID_CLK_DAY, DUSB_PID_CLK_MONTH, DUSB_PID_CLK_YEAR
1575 };
1576 const int size = sizeof(pids) / sizeof(uint16_t);
1577 DUSBCalcParam **params;
1578 int ret;
1579
1580 // get raw clock
1581 ticalcs_strlcpy(update_->text, _("Getting clock..."), sizeof(update_->text));
1582 update_label();
1583
1584 params = dusb_cp_new_array(handle, size);
1585 ret = dusb_cmd_s_param_request(handle, size, pids);
1586 if (!ret)
1587 {
1588 ret = dusb_cmd_r_param_data(handle, size, params);
1589 if (!ret)
1590 {
1591 int classic_clock = !!params[0]->ok && !!!params[1]->ok;
1592 int new_clock = !!!params[0]->ok && !!params[1]->ok;
1593 if (!classic_clock && !new_clock)
1594 {
1595 ticalcs_warning(_("Could not determine clock type: %u %u"), params[0]->ok, params[1]->ok);
1596 }
1597 else if (classic_clock)
1598 {
1599 if (params[2]->ok && params[3]->ok && params[4]->ok && params[5]->ok)
1600 {
1601 struct tm ref, *cur;
1602 time_t r, c, now;
1603 uint8_t * data = params[3]->data;
1604 uint32_t calc_time = (((uint32_t)data[0]) << 24) | (((uint32_t)data[1]) << 16) | (((uint32_t)data[2]) << 8) | (data[3] << 0);
1605
1606 ticalcs_info(_("Found valid classic clock"));
1607
1608 time(&now); // retrieve current DST setting
1609 memcpy(&ref, localtime(&now), sizeof(struct tm));
1610 ref.tm_year = 1997 - 1900;
1611 ref.tm_mon = 0;
1612 ref.tm_yday = 0;
1613 ref.tm_mday = 1;
1614 ref.tm_wday = 3;
1615 ref.tm_hour = 0;
1616 ref.tm_min = 0;
1617 ref.tm_sec = 0;
1618 //ref.tm_isdst = 1;
1619 r = mktime(&ref);
1620
1621 c = r + calc_time;
1622 cur = localtime(&c);
1623
1624 _clock->year = cur->tm_year + 1900;
1625 _clock->month = cur->tm_mon + 1;
1626 _clock->day = cur->tm_mday;
1627 _clock->hours = cur->tm_hour;
1628 _clock->minutes = cur->tm_min;
1629 _clock->seconds = cur->tm_sec;
1630
1631 _clock->date_format = params[4]->data[0] == 0 ? 3 : params[4]->data[0];
1632 _clock->time_format = params[5]->data[0] ? 24 : 12;
1633 _clock->state = params[2]->data[0];
1634 }
1635 else
1636 {
1637 ticalcs_warning(_("Found classic clock but failed to retrieve its parameters: %u %u %u %u"),
1638 params[2]->ok, params[3]->ok, params[4]->ok, params[5]->ok);
1639 }
1640 }
1641 else if (new_clock)
1642 {
1643 if (params[6]->ok && params[7]->ok && params[8]->ok && params[9]->ok && params[10]->ok && params[11]->ok)
1644 {
1645 uint8_t * data = params[11]->data;
1646
1647 ticalcs_info(_("Found valid new clock"));
1648
1649 _clock->year = (((uint16_t)data[0]) << 8) | (data[1] << 0);
1650 _clock->month = params[10]->data[0];
1651 _clock->day = params[9]->data[0];
1652 _clock->hours = params[8]->data[0];
1653 _clock->minutes = params[7]->data[0];
1654 _clock->seconds = params[6]->data[0];
1655
1656 _clock->date_format = params[4]->data[0] == 0 ? 3 : params[4]->data[0];
1657 _clock->time_format = params[5]->data[0] == 0x80 ? 12 : 24;
1658 _clock->state = params[2]->data[0];
1659 }
1660 else
1661 {
1662 ticalcs_warning(_("Found new clock but failed to retrieve its parameters: %u %u %u %u %u %u"),
1663 params[6]->ok, params[7]->ok, params[8]->ok, params[9]->ok, params[10]->ok, params[11]->ok);
1664 }
1665 }
1666 else
1667 {
1668 ret = ERR_INVALID_PACKET;
1669 }
1670 }
1671 }
1672 dusb_cp_del_array(handle, size, params);
1673
1674 return ret;
1675 }
1676
del_var(CalcHandle * handle,VarRequest * vr)1677 static int del_var (CalcHandle* handle, VarRequest* vr)
1678 {
1679 DUSBCalcAttr **attr;
1680 const int size = 1;
1681 char *utf8;
1682 int ret;
1683
1684 utf8 = ticonv_varname_to_utf8(handle->model, vr->name, vr->type);
1685 ticalcs_slprintf(update_->text, sizeof(update_->text), _("Deleting %s..."), utf8);
1686 ticonv_utf8_free(utf8);
1687 update_label();
1688
1689 attr = dusb_ca_new_array(handle, size);
1690 attr[0] = dusb_ca_new(handle, 0x0011, 4);
1691 attr[0]->data[0] = 0xF0; attr[0]->data[1] = 0x0B;
1692 attr[0]->data[2] = 0x00; attr[0]->data[3] = vr->type;
1693
1694 ret = dusb_cmd_s_var_delete(handle, "", vr->name, size, CA(attr));
1695 dusb_ca_del_array(handle, size, attr);
1696 if (!ret)
1697 {
1698 ret = dusb_cmd_r_data_ack(handle);
1699 }
1700
1701 return ret;
1702 }
1703
rename_var(CalcHandle * handle,VarRequest * oldname,VarRequest * newname)1704 static int rename_var (CalcHandle* handle, VarRequest* oldname, VarRequest* newname)
1705 {
1706 DUSBCalcAttr **attrs;
1707 const int size = 1;
1708 int ret;
1709
1710 attrs = dusb_ca_new_array(handle, size);
1711 attrs[0] = dusb_ca_new(handle, DUSB_AID_VAR_TYPE2, 4);
1712 attrs[0]->data[0] = 0xF0; attrs[0]->data[1] = 0x07;
1713 attrs[0]->data[2] = 0x00; attrs[0]->data[3] = oldname->type;
1714
1715 ret = dusb_cmd_s_var_modify(handle, "", oldname->name, 1, CA(attrs), "", newname->name, 0, NULL);
1716 dusb_ca_del_array(handle, size, attrs);
1717 if (!ret)
1718 {
1719 ret = dusb_cmd_r_data_ack(handle);
1720 }
1721
1722 return ret;
1723 }
1724
change_attr(CalcHandle * handle,VarRequest * vr,FileAttr attr)1725 static int change_attr (CalcHandle* handle, VarRequest* vr, FileAttr attr)
1726 {
1727 DUSBCalcAttr **srcattrs;
1728 DUSBCalcAttr **dstattrs;
1729 int ret;
1730
1731 srcattrs = dusb_ca_new_array(handle, 1);
1732 srcattrs[0] = dusb_ca_new(handle, DUSB_AID_VAR_TYPE2, 4);
1733 srcattrs[0]->data[0] = 0xF0; srcattrs[0]->data[1] = 0x07;
1734 srcattrs[0]->data[2] = 0x00; srcattrs[0]->data[3] = vr->type;
1735
1736 dstattrs = dusb_ca_new_array(handle, 1);
1737 dstattrs[0] = dusb_ca_new(handle, DUSB_AID_ARCHIVED, 1);
1738 /* use 0xff here rather than 0x01 to work around an OS bug */
1739 dstattrs[0]->data[0] = (attr == ATTRB_ARCHIVED ? 0xff : 0x00);
1740
1741 ret = dusb_cmd_s_var_modify(handle, "", vr->name, 1, CA(srcattrs), "", vr->name, 1, CA(dstattrs));
1742 dusb_ca_del_array(handle, 1, dstattrs);
1743 dusb_ca_del_array(handle, 1, srcattrs);
1744 if (!ret)
1745 {
1746 ret = dusb_cmd_r_data_ack(handle);
1747 }
1748
1749 return ret;
1750 }
1751
get_version(CalcHandle * handle,CalcInfos * infos)1752 static int get_version (CalcHandle* handle, CalcInfos* infos)
1753 {
1754 static const uint16_t pids[] = {
1755 DUSB_PID_OS_MODE, DUSB_PID_DEVICE_TYPE, DUSB_PID_PRODUCT_NAME, DUSB_PID_MAIN_PART_ID,
1756 DUSB_PID_HW_VERSION, DUSB_PID_LANGUAGE_ID, DUSB_PID_SUBLANG_ID,
1757 DUSB_PID_BOOT_BUILD_NUMBER, DUSB_PID_BOOT_VERSION, DUSB_PID_OS_BUILD_NUMBER, DUSB_PID_OS_VERSION,
1758 DUSB_PID_PHYS_RAM, DUSB_PID_USER_RAM, DUSB_PID_FREE_RAM,
1759 DUSB_PID_PHYS_FLASH, DUSB_PID_USER_FLASH, DUSB_PID_FREE_FLASH,
1760 DUSB_PID_LCD_WIDTH, DUSB_PID_LCD_HEIGHT, DUSB_PID_BITS_PER_PIXEL, DUSB_PID_COLOR_AVAILABLE,
1761 DUSB_PID_BATTERY, DUSB_PID_EXACT_MATH, DUSB_PID_CLASSIC_CLK_SUPPORT
1762 };
1763 const int size = sizeof(pids) / sizeof(uint16_t);
1764 DUSBCalcParam **params;
1765 int i = 0;
1766 int ret;
1767
1768 ticalcs_strlcpy(update_->text, _("Getting version..."), sizeof(update_->text));
1769 update_label();
1770
1771 memset(infos, 0, sizeof(CalcInfos));
1772 params = dusb_cp_new_array(handle, size);
1773
1774 // TODO rewrite this function to ask for parameters in multiple phases, starting with 0x000A, then
1775 // model-dependent sets of parameters. That's how TI-Connect CE 5.x does.
1776 ret = dusb_cmd_s_param_request(handle, size, pids);
1777 if (!ret)
1778 {
1779 ret = dusb_cmd_r_param_data(handle, size, params);
1780 if (!ret)
1781 {
1782 uint8_t product_id = 0;
1783 uint8_t has_boot_build_number = 0;
1784 uint8_t has_os_build_number = 0;
1785
1786 if (params[i]->ok && params[i]->size == 1)
1787 {
1788 infos->run_level = params[i]->data[0];
1789 infos->mask |= INFOS_RUN_LEVEL;
1790 }
1791 i++;
1792
1793 if (params[i]->ok && params[i]->size == 2)
1794 {
1795 infos->device_type = params[i]->data[1];
1796 infos->mask |= INFOS_DEVICE_TYPE;
1797 }
1798 i++;
1799
1800 if (params[i]->ok)
1801 {
1802 ticalcs_strlcpy(infos->product_name, (char *)params[i]->data, sizeof(infos->product_name));
1803 infos->mask |= INFOS_PRODUCT_NAME;
1804 }
1805 i++;
1806
1807 if (params[i]->ok && params[i]->size == 5)
1808 {
1809 product_id = params[i]->data[0];
1810 ticalcs_slprintf(infos->main_calc_id, sizeof(infos->main_calc_id), "%02X%02X%02X%02X%02X",
1811 product_id, params[i]->data[1], params[i]->data[2], params[i]->data[3], params[i]->data[4]);
1812 infos->mask |= INFOS_MAIN_CALC_ID;
1813 ticalcs_strlcpy(infos->product_id, infos->main_calc_id, sizeof(infos->product_id));
1814 infos->mask |= INFOS_PRODUCT_ID;
1815 }
1816 i++;
1817
1818 if (params[i]->ok && params[i]->size == 2)
1819 {
1820 infos->hw_version = (((uint16_t)params[i]->data[0]) << 8) | params[i]->data[1];
1821 infos->mask |= INFOS_HW_VERSION;
1822 }
1823 i++;
1824
1825 if (params[i]->ok && params[i]->size == 1)
1826 {
1827 infos->language_id = params[i]->data[0];
1828 infos->mask |= INFOS_LANG_ID;
1829 }
1830 i++;
1831
1832 if (params[i]->ok && params[i]->size == 1)
1833 {
1834 infos->sub_lang_id = params[i]->data[0];
1835 infos->mask |= INFOS_SUB_LANG_ID;
1836 }
1837 i++;
1838
1839 if (params[i]->ok && params[i]->size == 2)
1840 {
1841 has_boot_build_number = 1;
1842 }
1843 i++;
1844
1845 if (params[i]->ok && params[i]->size >= 3)
1846 {
1847 if (!has_boot_build_number)
1848 {
1849 ticalcs_slprintf(infos->boot_version, sizeof(infos->boot_version), "%1u.%02u", params[i]->data[1], params[i]->data[2]);
1850 infos->mask |= INFOS_BOOT_VERSION;
1851 }
1852 else if (params[i]->size == 4)
1853 {
1854 ticalcs_slprintf(infos->boot_version, sizeof(infos->boot_version), "%1u.%1u.%1u.%04u",
1855 params[i]->data[1], params[i]->data[2], params[i]->data[3],
1856 (((uint16_t)(params[i - 1]->data[0])) << 8) | params[i - 1]->data[1]);
1857 infos->mask |= INFOS_BOOT_VERSION;
1858 }
1859 // else do nothing.
1860 }
1861 i++;
1862
1863 if (params[i]->ok && params[i]->size == 2)
1864 {
1865 has_os_build_number = 1;
1866 }
1867 i++;
1868
1869 if (params[i]->ok && params[i]->size >= 3)
1870 {
1871 if (!has_os_build_number)
1872 {
1873 ticalcs_slprintf(infos->os_version, sizeof(infos->os_version), "%1u.%02u", params[i]->data[1], params[i]->data[2]);
1874 infos->mask |= INFOS_OS_VERSION;
1875 }
1876 else if (params[i]->size == 4)
1877 {
1878 ticalcs_slprintf(infos->os_version, sizeof(infos->os_version), "%1u.%1u.%1u.%04u",
1879 params[i]->data[1], params[i]->data[2], params[i]->data[3],
1880 (((uint16_t)(params[i - 1]->data[0])) << 8) | params[i - 1]->data[1]);
1881 infos->mask |= INFOS_OS_VERSION;
1882 }
1883 // else do nothing.
1884 }
1885 i++;
1886
1887 if (params[i]->ok && params[i]->size == 8)
1888 {
1889 infos->ram_phys = ( (((uint64_t)(params[i]->data[0])) << 56)
1890 | (((uint64_t)(params[i]->data[1])) << 48)
1891 | (((uint64_t)(params[i]->data[2])) << 40)
1892 | (((uint64_t)(params[i]->data[3])) << 32)
1893 | (((uint64_t)(params[i]->data[4])) << 24)
1894 | (((uint64_t)(params[i]->data[5])) << 16)
1895 | (((uint64_t)(params[i]->data[6])) << 8)
1896 | (((uint64_t)(params[i]->data[7])) ));
1897 infos->mask |= INFOS_RAM_PHYS;
1898 }
1899 i++;
1900 if (params[i]->ok && params[i]->size == 8)
1901 {
1902 infos->ram_user = ( (((uint64_t)(params[i]->data[0])) << 56)
1903 | (((uint64_t)(params[i]->data[1])) << 48)
1904 | (((uint64_t)(params[i]->data[2])) << 40)
1905 | (((uint64_t)(params[i]->data[3])) << 32)
1906 | (((uint64_t)(params[i]->data[4])) << 24)
1907 | (((uint64_t)(params[i]->data[5])) << 16)
1908 | (((uint64_t)(params[i]->data[6])) << 8)
1909 | (((uint64_t)(params[i]->data[7])) ));
1910 infos->mask |= INFOS_RAM_USER;
1911 }
1912 i++;
1913 if (params[i]->ok && params[i]->size == 8)
1914 {
1915 infos->ram_free = ( (((uint64_t)(params[i]->data[0])) << 56)
1916 | (((uint64_t)(params[i]->data[1])) << 48)
1917 | (((uint64_t)(params[i]->data[2])) << 40)
1918 | (((uint64_t)(params[i]->data[3])) << 32)
1919 | (((uint64_t)(params[i]->data[4])) << 24)
1920 | (((uint64_t)(params[i]->data[5])) << 16)
1921 | (((uint64_t)(params[i]->data[6])) << 8)
1922 | (((uint64_t)(params[i]->data[7])) ));
1923 infos->mask |= INFOS_RAM_FREE;
1924 }
1925 i++;
1926
1927 if (params[i]->ok && params[i]->size == 8)
1928 {
1929 infos->flash_phys = ( (((uint64_t)(params[i]->data[0])) << 56)
1930 | (((uint64_t)(params[i]->data[1])) << 48)
1931 | (((uint64_t)(params[i]->data[2])) << 40)
1932 | (((uint64_t)(params[i]->data[3])) << 32)
1933 | (((uint64_t)(params[i]->data[4])) << 24)
1934 | (((uint64_t)(params[i]->data[5])) << 16)
1935 | (((uint64_t)(params[i]->data[6])) << 8)
1936 | (((uint64_t)(params[i]->data[7])) ));
1937 infos->mask |= INFOS_FLASH_PHYS;
1938 }
1939 i++;
1940 if (params[i]->ok && params[i]->size == 8)
1941 {
1942 infos->flash_user = ( (((uint64_t)(params[i]->data[0])) << 56)
1943 | (((uint64_t)(params[i]->data[1])) << 48)
1944 | (((uint64_t)(params[i]->data[2])) << 40)
1945 | (((uint64_t)(params[i]->data[3])) << 32)
1946 | (((uint64_t)(params[i]->data[4])) << 24)
1947 | (((uint64_t)(params[i]->data[5])) << 16)
1948 | (((uint64_t)(params[i]->data[6])) << 8)
1949 | (((uint64_t)(params[i]->data[7])) ));
1950 infos->mask |= INFOS_FLASH_USER;
1951 }
1952 i++;
1953 if (params[i]->ok && params[i]->size == 8)
1954 {
1955 infos->flash_free = ( (((uint64_t)(params[i]->data[0])) << 56)
1956 | (((uint64_t)(params[i]->data[1])) << 48)
1957 | (((uint64_t)(params[i]->data[2])) << 40)
1958 | (((uint64_t)(params[i]->data[3])) << 32)
1959 | (((uint64_t)(params[i]->data[4])) << 24)
1960 | (((uint64_t)(params[i]->data[5])) << 16)
1961 | (((uint64_t)(params[i]->data[6])) << 8)
1962 | (((uint64_t)(params[i]->data[7])) ));
1963 infos->mask |= INFOS_FLASH_FREE;
1964 }
1965 i++;
1966
1967 if (params[i]->ok && params[i]->size == 2)
1968 {
1969 infos->lcd_width = ( (((uint16_t)(params[i]->data[ 0])) << 8)
1970 | (((uint16_t)(params[i]->data[ 1])) ));
1971 infos->mask |= INFOS_LCD_WIDTH;
1972 }
1973 i++;
1974 if (params[i]->ok && params[i]->size == 2)
1975 {
1976 infos->lcd_height = ( (((uint16_t)(params[i]->data[ 0])) << 8)
1977 | (((uint16_t)(params[i]->data[ 1])) ));
1978 infos->mask |= INFOS_LCD_HEIGHT;
1979 }
1980 i++;
1981
1982 if (params[i]->ok && params[i]->size == 1)
1983 {
1984 infos->bits_per_pixel = params[i]->data[0];
1985 infos->mask |= INFOS_BPP;
1986 }
1987 i++;
1988
1989 if (params[i]->ok && params[i]->size == 1)
1990 {
1991 infos->color_screen = params[i]->data[0];
1992 infos->mask |= INFOS_COLOR_SCREEN;
1993 }
1994 i++;
1995
1996 if (params[i]->ok && params[i]->size == 1)
1997 {
1998 infos->battery = params[i]->data[0];
1999 infos->mask |= INFOS_BATTERY;
2000 }
2001 i++;
2002
2003 if (params[i]->ok && params[i]->size == 1)
2004 {
2005 infos->exact_math = params[i]->data[0];
2006 infos->mask |= INFOS_EXACT_MATH;
2007 }
2008 i++;
2009
2010 switch (product_id)
2011 {
2012 case PRODUCT_ID_TI84P:
2013 {
2014 infos->model = CALC_TI84P_USB;
2015 if (infos->hw_version >= 4)
2016 {
2017 ticalcs_warning(_("Unhandled 84+ family member with product_id=%d hw_version=%d"), product_id, infos->hw_version);
2018 }
2019 break;
2020 }
2021 case PRODUCT_ID_TI82A:
2022 {
2023 infos->model = CALC_TI82A_USB;
2024 if (infos->hw_version >= 4)
2025 {
2026 ticalcs_warning(_("Unhandled 84+ family member with product_id=%d hw_version=%d"), product_id, infos->hw_version);
2027 }
2028 break;
2029 }
2030 case PRODUCT_ID_TI84PCSE:
2031 {
2032 infos->model = CALC_TI84PC_USB;
2033 if (infos->hw_version < 4)
2034 {
2035 ticalcs_warning(_("Unhandled 84+ family member with product_id=%d hw_version=%d"), product_id, infos->hw_version);
2036 }
2037 break;
2038 }
2039 case PRODUCT_ID_TI83PCE: // and case PRODUCT_ID_TI84PCE:
2040 {
2041 if (infos->exact_math)
2042 {
2043 infos->model = CALC_TI83PCE_USB;
2044 }
2045 else
2046 {
2047 infos->model = CALC_TI84PCE_USB;
2048 }
2049 if (infos->hw_version < 6)
2050 {
2051 ticalcs_warning(_("Unhandled 84+ family member with product_id=%d hw_version=%d"), product_id, infos->hw_version);
2052 }
2053 break;
2054 }
2055 default:
2056 {
2057 // Default to generic 84+(SE).
2058 infos->model = CALC_TI84P_USB;
2059 ticalcs_warning(_("Unhandled 84+ family member with product_id=%d hw_version=%d"), product_id, infos->hw_version);
2060 break;
2061 }
2062 }
2063 infos->mask |= INFOS_CALC_MODEL;
2064 }
2065 }
2066 dusb_cp_del_array(handle, size, params);
2067
2068 return ret;
2069 }
2070
2071 const CalcFncts calc_84p_usb =
2072 {
2073 CALC_TI84P_USB,
2074 "TI84+",
2075 "TI-84 Plus",
2076 N_("TI-84 Plus thru DirectLink"),
2077 OPS_ISREADY | OPS_SCREEN | OPS_DIRLIST | OPS_VARS | OPS_FLASH | OPS_OS |
2078 OPS_IDLIST | OPS_ROMDUMP | OPS_CLOCK | OPS_DELVAR | OPS_VERSION | OPS_BACKUP | OPS_KEYS |
2079 OPS_RENAME | OPS_CHATTR |
2080 FTS_SILENT | FTS_MEMFREE | FTS_FLASH,
2081 PRODUCT_ID_TI84P,
2082 {"", /* is_ready */
2083 "", /* send_key */
2084 "", /* execute */
2085 "1P", /* recv_screen */
2086 "1L", /* get_dirlist */
2087 "", /* get_memfree */
2088 "1P", /* send_backup */
2089 "", /* recv_backup */
2090 "2P1L", /* send_var */
2091 "1P1L", /* recv_var */
2092 "", /* send_var_ns */
2093 "", /* recv_var_ns */
2094 "2P1L", /* send_app */
2095 "2P1L", /* recv_app */
2096 "2P", /* send_os */
2097 "1L", /* recv_idlist */
2098 "2P", /* dump_rom_1 */
2099 "2P", /* dump_rom_2 */
2100 "", /* set_clock */
2101 "", /* get_clock */
2102 "1L", /* del_var */
2103 "1L", /* new_folder */
2104 "", /* get_version */
2105 "1L", /* send_cert */
2106 "1L", /* recv_cert */
2107 "", /* rename */
2108 "", /* chattr */
2109 "2P", /* send_all_vars_backup */
2110 "2P", /* recv_all_vars_backup */ },
2111 &is_ready,
2112 &send_key,
2113 &execute,
2114 &recv_screen,
2115 &get_dirlist,
2116 &get_memfree,
2117 &send_backup,
2118 &noop_recv_backup,
2119 &send_var,
2120 &recv_var,
2121 &noop_send_var_ns,
2122 &noop_recv_var_ns,
2123 &send_flash,
2124 &recv_flash,
2125 &send_os,
2126 &recv_idlist,
2127 &dump_rom_1,
2128 &dump_rom_2,
2129 &set_clock,
2130 &get_clock,
2131 &del_var,
2132 &noop_new_folder,
2133 &get_version,
2134 &noop_send_cert,
2135 &noop_recv_cert,
2136 &rename_var,
2137 &change_attr,
2138 &send_all_vars_backup,
2139 &tixx_recv_all_vars_backup
2140 };
2141
2142 const CalcFncts calc_84pcse_usb =
2143 {
2144 CALC_TI84PC_USB,
2145 "TI84+CSE",
2146 "TI-84 Plus C Silver Edition",
2147 N_("TI-84 Plus C Silver Edition thru DirectLink"),
2148 OPS_ISREADY | OPS_SCREEN | OPS_DIRLIST | OPS_VARS | OPS_FLASH | OPS_OS |
2149 OPS_IDLIST | OPS_ROMDUMP | OPS_CLOCK | OPS_DELVAR | OPS_VERSION | OPS_BACKUP | OPS_KEYS |
2150 OPS_RENAME | OPS_CHATTR |
2151 FTS_SILENT | FTS_MEMFREE | FTS_FLASH,
2152 PRODUCT_ID_TI84PCSE,
2153 {"", /* is_ready */
2154 "", /* send_key */
2155 "", /* execute */
2156 "1P", /* recv_screen */
2157 "1L", /* get_dirlist */
2158 "", /* get_memfree */
2159 "1P", /* send_backup */
2160 "", /* recv_backup */
2161 "2P1L", /* send_var */
2162 "1P1L", /* recv_var */
2163 "", /* send_var_ns */
2164 "", /* recv_var_ns */
2165 "2P1L", /* send_app */
2166 "2P1L", /* recv_app */
2167 "2P", /* send_os */
2168 "1L", /* recv_idlist */
2169 "2P", /* dump_rom_1 */
2170 "2P", /* dump_rom_2 */
2171 "", /* set_clock */
2172 "", /* get_clock */
2173 "1L", /* del_var */
2174 "1L", /* new_folder */
2175 "", /* get_version */
2176 "1L", /* send_cert */
2177 "1L", /* recv_cert */
2178 "", /* rename */
2179 "", /* chattr */
2180 "2P", /* send_all_vars_backup */
2181 "2P", /* recv_all_vars_backup */ },
2182 &is_ready,
2183 &send_key,
2184 &execute,
2185 &recv_screen,
2186 &get_dirlist,
2187 &get_memfree,
2188 &send_backup,
2189 &noop_recv_backup,
2190 &send_var,
2191 &recv_var,
2192 &noop_send_var_ns,
2193 &noop_recv_var_ns,
2194 &send_flash,
2195 &recv_flash,
2196 &send_os,
2197 &recv_idlist,
2198 &dump_rom_1,
2199 &dump_rom_2,
2200 &set_clock,
2201 &get_clock,
2202 &del_var,
2203 &noop_new_folder,
2204 &get_version,
2205 &noop_send_cert,
2206 &noop_recv_cert,
2207 &rename_var,
2208 &change_attr,
2209 &send_all_vars_backup,
2210 &tixx_recv_all_vars_backup
2211 };
2212
2213 const CalcFncts calc_83pce_usb =
2214 {
2215 CALC_TI83PCE_USB,
2216 "TI83PCE",
2217 "TI-83 Premium CE",
2218 N_("TI-83 Premium CE thru DirectLink"),
2219 OPS_ISREADY | OPS_SCREEN | OPS_DIRLIST | OPS_VARS | OPS_FLASH | OPS_OS |
2220 /*OPS_IDLIST |*/ OPS_ROMDUMP | OPS_CLOCK | OPS_DELVAR | OPS_VERSION | OPS_BACKUP | OPS_KEYS |
2221 OPS_RENAME | OPS_CHATTR |
2222 FTS_SILENT | FTS_MEMFREE | FTS_FLASH,
2223 PRODUCT_ID_TI83PCE,
2224 {"", /* is_ready */
2225 "", /* send_key */
2226 "", /* execute */
2227 "1P", /* recv_screen */
2228 "1L", /* get_dirlist */
2229 "", /* get_memfree */
2230 "", /* send_backup */
2231 "", /* recv_backup */
2232 "2P1L", /* send_var */
2233 "1P1L", /* recv_var */
2234 "", /* send_var_ns */
2235 "", /* recv_var_ns */
2236 "2P1L", /* send_app */
2237 "2P1L", /* recv_app */
2238 "2P", /* send_os */
2239 "1L", /* recv_idlist */
2240 "2P", /* dump_rom_1 */
2241 "2P", /* dump_rom_2 */
2242 "", /* set_clock */
2243 "", /* get_clock */
2244 "1L", /* del_var */
2245 "1L", /* new_folder */
2246 "", /* get_version */
2247 "1L", /* send_cert */
2248 "1L", /* recv_cert */
2249 "", /* rename */
2250 "", /* chattr */
2251 "2P", /* send_all_vars_backup */
2252 "2P", /* recv_all_vars_backup */ },
2253 &is_ready,
2254 &send_key,
2255 &execute,
2256 &recv_screen,
2257 &get_dirlist,
2258 &get_memfree,
2259 &noop_send_backup,
2260 &noop_recv_backup,
2261 &send_var,
2262 &recv_var,
2263 &noop_send_var_ns,
2264 &noop_recv_var_ns,
2265 &send_flash_834pce,
2266 &recv_flash_834pce,
2267 &send_os_834pce,
2268 &recv_idlist,
2269 &dump_rom_1,
2270 &dump_rom_2,
2271 &set_clock,
2272 &get_clock,
2273 &del_var,
2274 &noop_new_folder,
2275 &get_version,
2276 &noop_send_cert,
2277 &noop_recv_cert,
2278 &rename_var,
2279 &change_attr,
2280 &send_all_vars_backup,
2281 &tixx_recv_all_vars_backup
2282 };
2283
2284 const CalcFncts calc_84pce_usb =
2285 {
2286 CALC_TI84PCE_USB,
2287 "TI84+CE",
2288 "TI-84 Plus CE",
2289 N_("TI-84 Plus CE thru DirectLink"),
2290 OPS_ISREADY | OPS_SCREEN | OPS_DIRLIST | OPS_VARS | OPS_FLASH | OPS_OS |
2291 /*OPS_IDLIST |*/ OPS_ROMDUMP | OPS_CLOCK | OPS_DELVAR | OPS_VERSION | OPS_BACKUP | OPS_KEYS |
2292 OPS_RENAME | OPS_CHATTR |
2293 FTS_SILENT | FTS_MEMFREE | FTS_FLASH,
2294 PRODUCT_ID_TI84PCE,
2295 {"", /* is_ready */
2296 "", /* send_key */
2297 "", /* execute */
2298 "1P", /* recv_screen */
2299 "1L", /* get_dirlist */
2300 "", /* get_memfree */
2301 "", /* send_backup */
2302 "", /* recv_backup */
2303 "2P1L", /* send_var */
2304 "1P1L", /* recv_var */
2305 "", /* send_var_ns */
2306 "", /* recv_var_ns */
2307 "2P1L", /* send_app */
2308 "2P1L", /* recv_app */
2309 "2P", /* send_os */
2310 "1L", /* recv_idlist */
2311 "2P", /* dump_rom_1 */
2312 "2P", /* dump_rom_2 */
2313 "", /* set_clock */
2314 "", /* get_clock */
2315 "1L", /* del_var */
2316 "1L", /* new_folder */
2317 "", /* get_version */
2318 "1L", /* send_cert */
2319 "1L", /* recv_cert */
2320 "", /* rename */
2321 "", /* chattr */
2322 "2P", /* send_all_vars_backup */
2323 "2P", /* recv_all_vars_backup */ },
2324 &is_ready,
2325 &send_key,
2326 &execute,
2327 &recv_screen,
2328 &get_dirlist,
2329 &get_memfree,
2330 &noop_send_backup,
2331 &noop_recv_backup,
2332 &send_var,
2333 &recv_var,
2334 &noop_send_var_ns,
2335 &noop_recv_var_ns,
2336 &send_flash_834pce,
2337 &recv_flash_834pce,
2338 &send_os_834pce,
2339 &recv_idlist,
2340 &dump_rom_1,
2341 &dump_rom_2,
2342 &set_clock,
2343 &get_clock,
2344 &del_var,
2345 &noop_new_folder,
2346 &get_version,
2347 &noop_send_cert,
2348 &noop_recv_cert,
2349 &rename_var,
2350 &change_attr,
2351 &send_all_vars_backup,
2352 &tixx_recv_all_vars_backup
2353 };
2354
2355 const CalcFncts calc_82a_usb =
2356 {
2357 CALC_TI82A_USB,
2358 "TI82A",
2359 "TI-82 Advanced",
2360 N_("TI-82 Advanced thru DirectLink"),
2361 OPS_ISREADY | OPS_SCREEN | OPS_DIRLIST | OPS_VARS | /*OPS_FLASH |*/ OPS_OS |
2362 OPS_IDLIST | /*OPS_ROMDUMP |*/ OPS_CLOCK | OPS_DELVAR | OPS_VERSION | OPS_BACKUP | OPS_KEYS |
2363 OPS_RENAME | OPS_CHATTR |
2364 FTS_SILENT | FTS_MEMFREE | FTS_FLASH,
2365 PRODUCT_ID_TI82A,
2366 {"", /* is_ready */
2367 "", /* send_key */
2368 "", /* execute */
2369 "1P", /* recv_screen */
2370 "1L", /* get_dirlist */
2371 "", /* get_memfree */
2372 "1P", /* send_backup */
2373 "", /* recv_backup */
2374 "2P1L", /* send_var */
2375 "1P1L", /* recv_var */
2376 "", /* send_var_ns */
2377 "", /* recv_var_ns */
2378 "2P1L", /* send_app */
2379 "2P1L", /* recv_app */
2380 "2P", /* send_os */
2381 "1L", /* recv_idlist */
2382 "2P", /* dump_rom_1 */
2383 "2P", /* dump_rom_2 */
2384 "", /* set_clock */
2385 "", /* get_clock */
2386 "1L", /* del_var */
2387 "1L", /* new_folder */
2388 "", /* get_version */
2389 "1L", /* send_cert */
2390 "1L", /* recv_cert */
2391 "", /* rename */
2392 "", /* chattr */
2393 "2P", /* send_all_vars_backup */
2394 "2P", /* recv_all_vars_backup */ },
2395 &is_ready,
2396 &send_key,
2397 &execute,
2398 &recv_screen,
2399 &get_dirlist,
2400 &get_memfree,
2401 &send_backup,
2402 &noop_recv_backup,
2403 &send_var,
2404 &recv_var,
2405 &noop_send_var_ns,
2406 &noop_recv_var_ns,
2407 &send_flash,
2408 &recv_flash,
2409 &send_os,
2410 &recv_idlist,
2411 &dump_rom_1,
2412 &dump_rom_2,
2413 &set_clock,
2414 &get_clock,
2415 &del_var,
2416 &noop_new_folder,
2417 &get_version,
2418 &noop_send_cert,
2419 &noop_recv_cert,
2420 &rename_var,
2421 &change_attr,
2422 &send_all_vars_backup,
2423 &tixx_recv_all_vars_backup
2424 };
2425
2426 const CalcFncts calc_84pt_usb =
2427 {
2428 CALC_TI84PT_USB,
2429 "TI84PT",
2430 "TI-84 Plus T",
2431 N_("TI-84 Plus T thru DirectLink"),
2432 OPS_ISREADY | OPS_SCREEN | OPS_DIRLIST | OPS_VARS | /*OPS_FLASH |*/ OPS_OS |
2433 OPS_IDLIST | /*OPS_ROMDUMP |*/ OPS_CLOCK | OPS_DELVAR | OPS_VERSION | OPS_BACKUP | OPS_KEYS |
2434 OPS_RENAME | OPS_CHATTR |
2435 FTS_SILENT | FTS_MEMFREE | FTS_FLASH,
2436 PRODUCT_ID_TI84PT,
2437 {"", /* is_ready */
2438 "", /* send_key */
2439 "", /* execute */
2440 "1P", /* recv_screen */
2441 "1L", /* get_dirlist */
2442 "", /* get_memfree */
2443 "1P", /* send_backup */
2444 "", /* recv_backup */
2445 "2P1L", /* send_var */
2446 "1P1L", /* recv_var */
2447 "", /* send_var_ns */
2448 "", /* recv_var_ns */
2449 "2P1L", /* send_app */
2450 "2P1L", /* recv_app */
2451 "2P", /* send_os */
2452 "1L", /* recv_idlist */
2453 "2P", /* dump_rom_1 */
2454 "2P", /* dump_rom_2 */
2455 "", /* set_clock */
2456 "", /* get_clock */
2457 "1L", /* del_var */
2458 "1L", /* new_folder */
2459 "", /* get_version */
2460 "1L", /* send_cert */
2461 "1L", /* recv_cert */
2462 "", /* rename */
2463 "", /* chattr */
2464 "2P", /* send_all_vars_backup */
2465 "2P", /* recv_all_vars_backup */ },
2466 &is_ready,
2467 &send_key,
2468 &execute,
2469 &recv_screen,
2470 &get_dirlist,
2471 &get_memfree,
2472 &send_backup,
2473 &noop_recv_backup,
2474 &send_var,
2475 &recv_var,
2476 &noop_send_var_ns,
2477 &noop_recv_var_ns,
2478 &send_flash,
2479 &recv_flash,
2480 &send_os,
2481 &recv_idlist,
2482 &dump_rom_1,
2483 &dump_rom_2,
2484 &set_clock,
2485 &get_clock,
2486 &del_var,
2487 &noop_new_folder,
2488 &get_version,
2489 &noop_send_cert,
2490 &noop_recv_cert,
2491 &rename_var,
2492 &change_attr,
2493 &send_all_vars_backup,
2494 &tixx_recv_all_vars_backup
2495 };
2496