/** * ticalcs_calc_send_tigroup: * @handle: a previously allocated handle * @filename: name of file * @mode: which vars/apps to send * * Send a TiGroup file. * * Return value: 0 if ready else ERR_NOT_READY. **/ TIEXPORT3 int TICALL ticalcs_calc_send_tigroup(CalcHandle* handle, TigContent* content, TigMode mode) { TigEntry **ptr; GNode *vars, *apps; int nvars = 0; int napps = 0; if(handle == NULL) return ERR_INVALID_HANDLE; if (content == NULL) { ticalcs_critical("ticalcs_calc_send_tigroup: content is NULL"); return -1; } TRYF(handle->calc->get_dirlist(handle, &vars, &apps)); if((mode & TIG_RAM) || (mode & TIG_ARCHIVE)) nvars = content->n_vars; if(mode & TIG_FLASH) napps = content->n_apps; update_->cnt3 = 0; update_->max3 = nvars + napps; update_->pbar(); if((handle->model == CALC_TI89 || handle->model == CALC_TI92P || handle->model == CALC_TI89T || handle->model == CALC_V200) && (mode & TIG_BACKUP)) { // erase memory TRYF(ti89_send_VAR(0, TI89_BKUP, "main")); TRYF(ti89_recv_ACK(NULL)); TRYF(ti89_recv_CTS()); TRYF(ti89_send_ACK()); TRYF(ti89_send_EOT()); TRYF(ti89_recv_ACK(NULL)); } // Send vars if((mode & TIG_RAM) || (mode & TIG_ARCHIVE)) { for(ptr = content->var_entries; *ptr; ptr++) { TigEntry *te = *ptr; update_->cnt3++; update_->pbar(); if((te->content.regular->entries[0]->attr == ATTRB_ARCHIVED) && !(mode & TIG_ARCHIVE)) continue; if((te->content.regular->entries[0]->attr != ATTRB_ARCHIVED) && !(mode & TIG_RAM)) continue; TRYF(handle->calc->send_var(handle, MODE_BACKUP, te->content.regular)); } } TRYF(handle->calc->is_ready(handle)); // Send apps if(mode & TIG_FLASH) { for(ptr = content->app_entries; *ptr; ptr++) { TigEntry *te = *ptr; VarEntry ve; update_->cnt3++; update_->pbar(); // can't overwrite apps so check before sending app memset(&ve, 0, sizeof(VarEntry)); strcpy(ve.name, te->content.flash->name); if(!ticalcs_dirlist_ve_exist(apps, &ve)) TRYF(handle->calc->send_app(handle, te->content.flash)); } } ticalcs_dirlist_destroy(&vars); ticalcs_dirlist_destroy(&apps); return 0; }
/** * ticalcs_calc_recv_tigroup: * @handle: a previously allocated handle * @filename: name of file * @mode: which vars/apps to receive * * Receive a TiGroup file. * * Return value: 0 if ready else ERR_NOT_READY. **/ TIEXPORT3 int TICALL ticalcs_calc_recv_tigroup(CalcHandle* handle, TigContent* content, TigMode mode) { int i, j; int i_max, j_max; GNode *vars, *apps; int nvars = 0; int napps = 0; int b = 0; if(handle == NULL) return ERR_INVALID_HANDLE; if (content == NULL) { ticalcs_critical("ticalcs_calc_send_tigroup: content is NULL"); return -1; } update_->cnt3 = 0; update_->pbar(); // Do a directory list and check for something to backup TRYF(handle->calc->get_dirlist(handle, &vars, &apps)); if((mode & TIG_RAM) || (mode & TIG_ARCHIVE)) nvars = ticalcs_dirlist_ve_count(vars); if(mode & TIG_FLASH) napps = ticalcs_dirlist_ve_count(apps); update_->cnt3 = 0; update_->max3 = nvars + napps; update_->pbar(); if(!nvars && !napps) return ERR_NO_VARS; // Check whether the last folder is empty b = g_node_n_children(g_node_nth_child(vars, g_node_n_children(vars) - 1)); PAUSE(100); // needed by TI84+/USB // Receive all vars i_max = g_node_n_children(vars); if((mode & TIG_RAM) || (mode & TIG_ARCHIVE)) for(i = 0; i < i_max; i++) { GNode *parent = g_node_nth_child(vars, i); j_max = g_node_n_children(parent); for(j = 0; j < j_max; j++) { GNode *node = g_node_nth_child(parent, j); VarEntry *ve = (VarEntry *) (node->data); TigEntry *te; char *filename; char *varname; char *fldname; PAUSE(100); TRYF(handle->calc->is_ready(handle)); PAUSE(100); update_->cnt3++; update_->pbar(); if(((mode & TIG_ARCHIVE) && (ve->attr == ATTRB_ARCHIVED)) || ((mode & TIG_RAM) && ve->attr != ATTRB_ARCHIVED)) { fldname = ticonv_varname_to_filename(handle->model, ve->folder, -1); varname = ticonv_varname_to_filename(handle->model, ve->name, ve->type); if(handle->calc->features & FTS_FOLDER) filename = g_strconcat(fldname, ".", varname, ".", tifiles_vartype2fext(handle->model, ve->type), NULL); else filename = g_strconcat(varname, ".", tifiles_vartype2fext(handle->model, ve->type), NULL); g_free(fldname); g_free(varname); te = tifiles_te_create(filename, TIFILE_SINGLE, handle->model); g_free(filename); TRYF(handle->calc->recv_var(handle, 0, te->content.regular, ve)); tifiles_content_add_te(content, te); } } } ticalcs_dirlist_destroy(&vars); // Receive all apps i_max = g_node_n_children(apps); if(mode & TIG_FLASH) for(i = 0; i < i_max; i++) { GNode *parent = g_node_nth_child(apps, i); j_max = g_node_n_children(parent); for(j = 0; j < j_max; j++) { GNode *node = g_node_nth_child(parent, j); VarEntry *ve = (VarEntry *) (node->data); TigEntry *te; char *filename; char *basename; TRYF(handle->calc->is_ready(handle)); update_->cnt3++; update_->pbar(); basename = ticonv_varname_to_filename(handle->model, ve->name, ve->type); filename = g_strconcat(basename, ".", tifiles_vartype2fext(handle->model, ve->type), NULL); g_free(basename); te = tifiles_te_create(filename, TIFILE_FLASH, handle->model); g_free(filename); TRYF(handle->calc->recv_app(handle, te->content.flash, ve)); tifiles_content_add_te(content, te); } } ticalcs_dirlist_destroy(&apps); return 0; }
static int set_clock (CalcHandle* handle, CalcClock* _clock) { CalcParam *param; uint32_t calc_time; struct tm ref, cur; time_t r, c, now; time(&now); memcpy(&ref, localtime(&now), sizeof(struct tm)); ref.tm_year = 1997 - 1900; ref.tm_mon = 0; ref.tm_yday = 0; ref.tm_mday = 1; ref.tm_wday = 3; ref.tm_hour = 0; ref.tm_min = 0; ref.tm_sec = 0; //ref.tm_isdst = 1; r = mktime(&ref); cur.tm_year = _clock->year - 1900; cur.tm_mon = _clock->month - 1; cur.tm_mday = _clock->day; cur.tm_hour = _clock->hours; cur.tm_min = _clock->minutes; cur.tm_sec = _clock->seconds; cur.tm_isdst = 1; c = mktime(&cur); calc_time = (uint32_t)difftime(c, r); g_snprintf(update_->text, sizeof(update_->text), _("Setting clock...")); update_label(); param = cp_new(PID_CLK_SEC, 4); param->data[0] = MSB(MSW(calc_time)); param->data[1] = LSB(MSW(calc_time)); param->data[2] = MSB(LSW(calc_time)); param->data[3] = LSB(LSW(calc_time)); TRYF(cmd_s_param_set(handle, param)); TRYF(cmd_r_data_ack(handle)); cp_del(param); param = cp_new(PID_CLK_DATE_FMT, 1); param->data[0] = _clock->date_format == 3 ? 0 : _clock->date_format; TRYF(cmd_s_param_set(handle, param)); TRYF(cmd_r_data_ack(handle)); cp_del(param); param = cp_new(PID_CLK_TIME_FMT, 1); param->data[0] = _clock->time_format == 24 ? 1 : 0; TRYF(cmd_s_param_set(handle, param)); TRYF(cmd_r_data_ack(handle)); cp_del(param); param = cp_new(PID_CLK_ON, 1); param->data[0] = _clock->state; TRYF(cmd_s_param_set(handle, param)); TRYF(cmd_r_data_ack(handle)); cp_del(param); return 0; }
static int get_version (CalcHandle* handle, CalcInfos* infos) { uint16_t pids[] = { PID_PRODUCT_NAME, PID_MAIN_PART_ID, PID_HW_VERSION, PID_LANGUAGE_ID, PID_SUBLANG_ID, PID_DEVICE_TYPE, PID_BOOT_VERSION, PID_OS_VERSION, PID_PHYS_RAM, PID_USER_RAM, PID_FREE_RAM, PID_PHYS_FLASH, PID_USER_FLASH, PID_FREE_FLASH, PID_LCD_WIDTH, PID_LCD_HEIGHT, PID_BATTERY, PID_OS_MODE, }; const int size = sizeof(pids) / sizeof(uint16_t); CalcParam **params; int i = 0; g_snprintf(update_->text, sizeof(update_->text), _("Getting version...")); update_label(); memset(infos, 0, sizeof(CalcInfos)); params = cp_new_array(size); TRYF(cmd_s_param_request(handle, size, pids)); TRYF(cmd_r_param_data(handle, size, params)); strncpy(infos->product_name, (char*)params[i]->data, params[i]->size); infos->mask |= INFOS_PRODUCT_NAME; i++; g_snprintf(infos->main_calc_id, 10, "%02X%02X%02X%02X%02X", params[i]->data[0], params[i]->data[1], params[i]->data[2], params[i]->data[3], params[i]->data[4]); infos->mask |= INFOS_MAIN_CALC_ID; strcpy(infos->product_id, infos->main_calc_id); infos->mask |= INFOS_PRODUCT_ID; i++; infos->hw_version = (params[i]->data[0] << 8) | params[i]->data[1]; infos->mask |= INFOS_HW_VERSION; // hw version or model ? i++; infos->language_id = params[i]->data[0]; infos->mask |= INFOS_LANG_ID; i++; infos->sub_lang_id = params[i]->data[0]; infos->mask |= INFOS_SUB_LANG_ID; i++; infos->device_type = params[i]->data[1]; infos->mask |= INFOS_DEVICE_TYPE; i++; g_snprintf(infos->boot_version, 5, "%1i.%02i", params[i]->data[1], params[i]->data[2]); infos->mask |= INFOS_BOOT_VERSION; i++; g_snprintf(infos->os_version, 5, "%1i.%02i", params[i]->data[1], params[i]->data[2]); infos->mask |= INFOS_OS_VERSION; i++; infos->ram_phys = GINT64_FROM_BE(*((uint64_t *)(params[i]->data))); infos->mask |= INFOS_RAM_PHYS; i++; infos->ram_user = GINT64_FROM_BE(*((uint64_t *)(params[i]->data))); infos->mask |= INFOS_RAM_USER; i++; infos->ram_free = GINT64_FROM_BE(*((uint64_t *)(params[i]->data))); infos->mask |= INFOS_RAM_FREE; i++; infos->flash_phys = GINT64_FROM_BE(*((uint64_t *)(params[i]->data))); infos->mask |= INFOS_FLASH_PHYS; i++; infos->flash_user = GINT64_FROM_BE(*((uint64_t *)(params[i]->data))); infos->mask |= INFOS_FLASH_USER; i++; infos->flash_free = GINT64_FROM_BE(*((uint64_t *)(params[i]->data))); infos->mask |= INFOS_FLASH_FREE; i++; infos->lcd_width = GINT16_FROM_BE(*((uint16_t *)(params[i]->data))); infos->mask |= INFOS_LCD_WIDTH; i++; infos->lcd_height = GINT16_FROM_BE(*((uint16_t *)(params[i]->data))); infos->mask |= INFOS_LCD_HEIGHT; i++; infos->bits_per_pixel = 1; infos->mask |= INFOS_BPP; infos->battery = params[i]->data[0]; infos->mask |= INFOS_BATTERY; i++; infos->run_level = params[i]->data[0]; infos->mask |= INFOS_RUN_LEVEL; i++; switch(infos->hw_version) { case 0: infos->model = CALC_TI83P; break; case 1: infos->model = CALC_TI83P; break; case 2: infos->model = CALC_TI84P; break; case 3: infos->model = CALC_TI84P; break; } infos->mask |= INFOS_CALC_MODEL; cp_del_array(size, params); return 0; }
static int send_os (CalcHandle* handle, FlashContent* content) { ModeSet mode = { 2, 1, 0, 0, 0x0fa0 }; //MODE_BASIC; uint32_t pkt_size = 266; uint32_t os_size = 0; FlashContent *ptr; int i, j; int boot = 0; // search for data header for (ptr = content; ptr != NULL; ptr = ptr->next) if(ptr->data_type == TI83p_AMS || ptr->data_type == TI83p_APPL) break; if(ptr == NULL) return -1; if(ptr->data_type != TI83p_AMS) return -1; #if 0 printf("#pages: %i\n", ptr->num_pages); printf("type: %02x\n", ptr->data_type); for (i = 0; i < ptr->num_pages; i++) { FlashPage *fp = ptr->pages[i]; printf("page #%i: %04x %02x %02x %04x\n", i, fp->addr, fp->page, fp->flag, fp->size); //tifiles_hexdump(fp->data, 16); } printf("data length = %08x %i\n", ptr->data_length, ptr->data_length); #endif for(i = 0; i < ptr->num_pages; i++) { FlashPage *fp = ptr->pages[i]; if(fp->size < 256) os_size += 4; else os_size += 4*(fp->size / 260); } printf("os_size overhead = %i\n", os_size); os_size += ptr->data_length; printf("os_size new = %i\n", os_size); // switch to BASIC mode TRYF(cmd_s_mode_set(handle, mode)); TRYF(cmd_r_mode_ack(handle)); // test for boot mode { uint16_t pids[] = { PID_OS_MODE }; const int size = sizeof(pids) / sizeof(uint16_t); CalcParam **params; params = cp_new_array(size); TRYF(cmd_s_param_request(handle, size, pids)); TRYF(cmd_r_param_data(handle, size, params)); boot = !params[0]->data[0]; } // start OS transfer TRYF(cmd_s_os_begin(handle, os_size)); if(!boot) { TRYF(dusb_recv_buf_size_request(handle, &pkt_size)); TRYF(dusb_send_buf_size_alloc(handle, pkt_size)); } TRYF(cmd_r_os_ack(handle, &pkt_size)); // this pkt_size is important // send OS header/signature TRYF(cmd_s_os_header(handle, 0x4000, 0x7A, 0x80, pkt_size-4, ptr->pages[0]->data)); TRYF(cmd_r_os_ack(handle, &pkt_size)); // send OS data update_->cnt2 = 0; update_->max2 = ptr->num_pages; for(i = 0; i < ptr->num_pages; i++) { FlashPage *fp = ptr->pages[i]; fp->addr = 0x4000; if(i == 0) // need relocation { TRYF(cmd_s_os_data(handle, 0x4000, 0x7A, 0x80, pkt_size-4, fp->data)); TRYF(cmd_r_data_ack(handle)); } else if(i == ptr->num_pages-1) // idem { TRYF(cmd_s_os_data(handle, 0x4100, 0x7A, 0x80, pkt_size-4, fp->data)); TRYF(cmd_r_data_ack(handle)); } else { for(j = 0; j < fp->size; j += 256/*(pkt_size-4)*/) { TRYF(cmd_s_os_data(handle, (uint16_t)(fp->addr + j), (uint8_t)fp->page, fp->flag, pkt_size-4, fp->data + j)); TRYF(cmd_r_data_ack(handle)); } } update_->cnt2 = i; update_->pbar(); } TRYF(cmd_s_eot(handle)); PAUSE(500); TRYF(cmd_r_eot_ack(handle)); return 0; }
static int dump_rom_1 (CalcHandle* handle) { TRYF(rd_send(handle, "romdump.8Xp", romDumpSize84p, romDump84p)); return 0; }
static int send_flash (CalcHandle* handle, FlashContent* content) { FlashContent *ptr; int i; char *utf8; CalcAttr **attrs; const int nattrs = 2; uint8_t *data; uint32_t size; // search for data header for (ptr = content; ptr != NULL; ptr = ptr->next) if(ptr->data_type == TI83p_AMS || ptr->data_type == TI83p_APPL) break; if(ptr == NULL) return -1; if(ptr->data_type != TI83p_APPL) return -1; #if 0 printf("#pages: %i\n", ptr->num_pages); printf("type: %02x\n", ptr->data_type); for (i = 0; i < ptr->num_pages; i++) { FlashPage *fp = ptr->pages[i]; printf("page #%i: %04x %02x %02x %04x\n", i, fp->addr, fp->page, fp->flag, fp->size); } printf("data length: %08x\n", ptr->data_length); return 0; #endif size = ptr->num_pages * FLASH_PAGE_SIZE; data = tifiles_fp_alloc_data(size); // must be rounded-up update_->cnt2 = 0; update_->max2 = ptr->num_pages; for (i = 0; i < ptr->num_pages; i++) { FlashPage *fp = ptr->pages[i]; memcpy(data + i*FLASH_PAGE_SIZE, fp->data, FLASH_PAGE_SIZE); update_->cnt2 = i; update_->pbar(); } { FlashPage *fp = ptr->pages[--i]; memset(data + i*FLASH_PAGE_SIZE + fp->size, 0x00, FLASH_PAGE_SIZE - fp->size); update_->cnt2 = i; update_->pbar(); } // send utf8 = ticonv_varname_to_utf8(handle->model, ptr->name, ptr->data_type); g_snprintf(update_->text, sizeof(update_->text), "%s", utf8); g_free(utf8); update_label(); attrs = ca_new_array(nattrs); attrs[0] = ca_new(AID_VAR_TYPE, 4); attrs[0]->data[0] = 0xF0; attrs[0]->data[1] = 0x07; attrs[0]->data[2] = 0x00; attrs[0]->data[3] = ptr->data_type; attrs[1] = ca_new(AID_ARCHIVED, 1); attrs[1]->data[0] = 0; TRYF(cmd_s_rts(handle, "", ptr->name, size, nattrs, CA(attrs))); TRYF(cmd_r_data_ack(handle)); TRYF(cmd_s_var_content(handle, size, data)); TRYF(cmd_r_data_ack(handle)); TRYF(cmd_s_eot(handle)); return 0; }
static int recv_var_ns (CalcHandle* handle, CalcMode mode, FileContent* content, VarEntry** vr) { int nvar = 0; int err = 0; char *utf8; uint16_t ve_size; g_snprintf(update_->text, sizeof(update_->text), _("Waiting for var(s)...")); update_label(); content->model = CALC_TI85; for (nvar = 0;; nvar++) { VarEntry *ve; content->entries = tifiles_ve_resize_array(content->entries, nvar+1); ve = content->entries[nvar] = tifiles_ve_create();; do { update_refresh(); if (update_->cancel) return ERR_ABORT; err = ti85_recv_VAR(&ve_size, &(ve->type), ve->name); ve->size = ve_size; } while (err == ERROR_READ_TIMEOUT); TRYF(ti85_send_ACK()); if (err == ERR_EOT) goto exit; TRYF(err); TRYF(ti85_send_CTS()); TRYF(ti85_recv_ACK(NULL)); utf8 = ticonv_varname_to_utf8(handle->model, ve->name, ve->type); g_snprintf(update_->text, sizeof(update_->text), "%s", utf8); g_free(utf8); update_label(); ve->data = tifiles_ve_alloc_data(ve->size); TRYF(ti85_recv_XDP(&ve_size, ve->data)); ve->size = ve_size; TRYF(ti85_send_ACK()); } exit: content->num_entries = nvar; if(nvar == 1) { strcpy(content->comment, tifiles_comment_set_single()); *vr = tifiles_ve_dup(content->entries[0]); } else { strcpy(content->comment, tifiles_comment_set_group()); *vr = NULL; } return 0; }
static int get_dirlist (CalcHandle* handle, GNode** vars, GNode** apps) { uint16_t aids[] = { AID_VAR_SIZE, AID_VAR_TYPE, AID_ARCHIVED, }; const int size = sizeof(aids) / sizeof(uint16_t); TreeInfo *ti; int err; CalcAttr **attr; GNode *folder, *root; char fldname[40], varname[40]; char *utf8; (*apps) = g_node_new(NULL); ti = (TreeInfo *)g_malloc(sizeof(TreeInfo)); ti->model = handle->model; ti->type = APP_NODE_NAME; (*apps)->data = ti; (*vars) = g_node_new(NULL); ti = (TreeInfo *)g_malloc(sizeof(TreeInfo)); ti->model = handle->model; ti->type = VAR_NODE_NAME; (*vars)->data = ti; folder = g_node_new(NULL); g_node_append(*vars, folder); root = g_node_new(NULL); g_node_append(*apps, root); // Add permanent variables (Window, RclWindow, TblSet aka WINDW, ZSTO, TABLE) { GNode *node; VarEntry *ve; ve = tifiles_ve_create(); strcpy(ve->name, "Window"); ve->type = TI84p_WINDW; node = g_node_new(ve); g_node_append(folder, node); ve = tifiles_ve_create(); strcpy(ve->name, "RclWin"); ve->type = TI84p_ZSTO; node = g_node_new(ve); g_node_append(folder, node); ve = tifiles_ve_create(); strcpy(ve->name, "TblSet"); ve->type = TI84p_TABLE; node = g_node_new(ve); g_node_append(folder, node); } TRYF(cmd_s_dirlist_request(handle, size, aids)); do { VarEntry *ve = tifiles_ve_create(); GNode *node; attr = ca_new_array(size); err = cmd_r_var_header(handle, fldname, varname, attr); if (err == ERR_EOT) break; else if (err != 0) return err; strcpy(ve->name, varname); ve->size = GINT32_FROM_BE(*((uint32_t *)(attr[0]->data))); ve->type = GINT32_FROM_BE(*((uint32_t *)(attr[1]->data))) & 0xff; ve->attr = attr[2]->data[0] ? ATTRB_ARCHIVED : ATTRB_NONE; ca_del_array(size, attr); node = g_node_new(ve); if (ve->type != TI73_APPL) g_node_append(folder, node); else g_node_append(root, node); utf8 = ticonv_varname_to_utf8(handle->model, ve->name, ve->type); g_snprintf(update_->text, sizeof(update_->text), _("Parsing %s"), utf8); g_free(utf8); update_label(); } while(1); return 0; }
static int send_backup (CalcHandle* handle, BackupContent* content) { TRYF(send_var(handle, MODE_BACKUP, (FileContent *)content)); return 0; }
static int get_version (CalcHandle* handle, CalcInfos* infos) { uint32_t size; uint8_t cmd, *data; //int i; TRYF(nsp_session_open(handle, SID_DEV_INFOS)); TRYF(nsp_cmd_s_dev_infos(handle, CMD_DI_MODEL)); TRYF(nsp_cmd_r_dev_infos(handle, &cmd, &size, &data)); strcpy(infos->product_name, (char*)data); infos->mask |= INFOS_PRODUCT_NAME; TRYF(nsp_cmd_s_dev_infos(handle, CMD_DI_VERSION)); TRYF(nsp_cmd_r_dev_infos(handle, &cmd, &size, &data)); infos->model = CALC_NSPIRE; //i = 0; //infos->flash_free = GUINT64_FROM_BE(*((uint64_t *)(data + i))); infos->flash_free = ( (((uint64_t)data[ 0]) << 56) | (((uint64_t)data[ 1]) << 48) | (((uint64_t)data[ 2]) << 40) | (((uint64_t)data[ 3]) << 32) | (((uint64_t)data[ 4]) << 24) | (((uint64_t)data[ 5]) << 16) | (((uint64_t)data[ 6]) << 8) | (((uint64_t)data[ 7]) )); infos->mask |= INFOS_FLASH_FREE; //i = 8; //infos->flash_phys = GUINT64_FROM_BE(*((uint64_t *)(data + i))); infos->flash_phys = ( (((uint64_t)data[ 8]) << 56) | (((uint64_t)data[ 9]) << 48) | (((uint64_t)data[10]) << 40) | (((uint64_t)data[11]) << 32) | (((uint64_t)data[12]) << 24) | (((uint64_t)data[13]) << 16) | (((uint64_t)data[14]) << 8) | (((uint64_t)data[15]) )); infos->mask |= INFOS_FLASH_PHYS; //i = 16; //infos->ram_free = GUINT64_FROM_BE(*((uint64_t *)(data + i))); infos->ram_free = ( (((uint64_t)data[16]) << 56) | (((uint64_t)data[17]) << 48) | (((uint64_t)data[18]) << 40) | (((uint64_t)data[19]) << 32) | (((uint64_t)data[20]) << 24) | (((uint64_t)data[21]) << 16) | (((uint64_t)data[22]) << 8) | (((uint64_t)data[23]) )); infos->mask |= INFOS_RAM_FREE; //i = 24; //infos->ram_phys = GUINT64_FROM_BE(*((uint64_t *)(data + i))); infos->ram_phys = ( (((uint64_t)data[24]) << 56) | (((uint64_t)data[25]) << 48) | (((uint64_t)data[26]) << 40) | (((uint64_t)data[27]) << 32) | (((uint64_t)data[28]) << 24) | (((uint64_t)data[29]) << 16) | (((uint64_t)data[30]) << 8) | (((uint64_t)data[31]) )); infos->mask |= INFOS_RAM_PHYS; //i = 32; infos->battery = (data[32] == 0x01) ? 0 : 1; infos->mask |= INFOS_BATTERY; //i = 35; infos->clock_speed = data[35]; infos->mask |= INFOS_CLOCK_SPEED; //i = 36; g_snprintf(infos->os_version, sizeof(infos->os_version), "%1i.%1i.%04i", data[36], data[37], (data[38] << 8) | data[39]); infos->mask |= INFOS_OS_VERSION; //i = 40; g_snprintf(infos->boot_version, sizeof(infos->boot_version), "%1i.%1i.%04i", data[40], data[41], (data[42] << 8) | data[43]); infos->mask |= INFOS_BOOT_VERSION; //i = 44; g_snprintf(infos->boot2_version, sizeof(infos->boot2_version), "%1i.%1i.%04i", data[44], data[45], (data[46] << 8) | data[47]); infos->mask |= INFOS_BOOT2_VERSION; //i = 48; //infos->hw_version = GUINT32_FROM_BE(*((uint32_t *)(data + i))); infos->hw_version = ( (((uint32_t)data[48]) << 24) | (((uint32_t)data[49]) << 16) | (((uint32_t)data[50]) << 8) | (((uint32_t)data[51]) )); infos->mask |= INFOS_HW_VERSION; //i = 52; //infos->run_level = (uint8_t)GUINT16_FROM_BE(*((uint16_t *)(data + i))); infos->run_level = data[53]; infos->mask |= INFOS_RUN_LEVEL; //i = 58; //infos->lcd_width = GUINT16_FROM_BE(*((uint16_t *)(data + i))); infos->lcd_width = ( (((uint16_t)data[58]) << 8) | (((uint16_t)data[59]) )); infos->mask |= INFOS_LCD_WIDTH; //i = 60; //infos->lcd_height = GUINT16_FROM_BE(*((uint16_t *)(data + i))); infos->lcd_height = ( (((uint16_t)data[60]) << 8) | (((uint16_t)data[61]) )); infos->mask |= INFOS_LCD_HEIGHT; //i = 62; infos->bits_per_pixel = data[62]; infos->mask |= INFOS_BPP; //i = 64; infos->device_type = data[64]; infos->mask |= INFOS_DEVICE_TYPE; memset(infos->main_calc_id, 0, sizeof(infos->main_calc_id)); strncpy(infos->main_calc_id, (char*)(data + 82), 28); infos->mask |= INFOS_MAIN_CALC_ID; memset(infos->product_id, 0, sizeof(infos->product_id)); strncpy(infos->product_id, (char*)(data + 82), 28); infos->mask |= INFOS_PRODUCT_ID; g_free(data); TRYF(nsp_session_close(handle)); return 0; }
static int is_ready (CalcHandle* handle) { static int rom_11 = 0; static int rom_14 = 0; // XXX debrouxl forcing a full sequence makes all operations a LOT slower (especially on // older OS), but fixes the 100% reproducible loss of connection after a few "Status" // operations or a single "List" operation, on my S-0907A non-CAS Nspire. // Tested with OS 1.1.9253, 1.2.2398, 1.3.2407, 1.4.11653, 1.6.4379, 1.7.2471, 1.7.1.50. // // A better fix is needed in the mid- and long-term. // checking for OS version and LOGIN packet //if(!nsp_reset) { // XXX debrouxl moving those two lines above the 'if(!nsp_reset)' test fixes connection // loss, but linking with at least 1.7.1.50 does not work properly after that: at least // directory listing and screenshot don't do anything beyond the "Status" probe. TRYF(nsp_addr_request(handle)); TRYF(nsp_addr_assign(handle, NSP_DEV_ADDR)); // XXX after commenting the following block of code, sending many Status or Dirlist // requests in short succession often triggers memory corruption (hangs, reboots, // a variable amount of black pixels on the screen) on (at least) Nspire (CAS) OS 1.7... { int old; int ret; ticalcs_info(" waiting for LOGIN request (OS >= 1.2 check)..."); old = ticables_options_set_timeout(handle->cable, 40); // 3s mini ret = nsp_cmd_r_login(handle); // no call to TRYF(nsp_send_nack(handle)) because nack is managed in nsp_recv_data() ticables_options_set_timeout(handle->cable, old); if(ret) { ticalcs_info("OS = 1.1"); rom_11 = !0; TRYF(nsp_addr_request(handle)); TRYF(nsp_addr_assign(handle, NSP_DEV_ADDR)); } else { ret = nsp_recv_disconnect(handle); if(ret) { ticalcs_info("OS = 1.2 or 1.3"); rom_14 = 0; } else { ticalcs_info("OS = 1.4 or later"); rom_14 = !0; } } } //nsp_reset = !0; } // Use ECHO packet as ready check { char str[] = "ready"; uint32_t size; uint8_t *data; TRYF(nsp_session_open(handle, SID_ECHO)); TRYF(nsp_cmd_s_echo(handle, strlen(str)+1, (uint8_t *)str)); TRYF(nsp_cmd_r_echo(handle, &size, &data)); g_free(data); TRYF(nsp_session_close(handle)); } return 0; }
static int get_dirlist (CalcHandle* handle, GNode** vars, GNode** apps) { TreeInfo *ti; int err; GNode *root, *folder = NULL; char varname[VARNAME_MAX]; uint32_t varsize; uint8_t vartype; int i; (*apps) = g_node_new(NULL); ti = (TreeInfo *)g_malloc(sizeof(TreeInfo)); ti->model = handle->model; ti->type = APP_NODE_NAME; (*apps)->data = ti; (*vars) = g_node_new(NULL); ti = (TreeInfo *)g_malloc(sizeof(TreeInfo)); ti->model = handle->model; ti->type = VAR_NODE_NAME; (*vars)->data = ti; root = g_node_new(NULL); g_node_append(*apps, root); TRYF(nsp_session_open(handle, SID_FILE_MGMT)); TRYF(nsp_cmd_s_dir_attributes(handle, "/")); TRYF(nsp_cmd_r_dir_attributes(handle, NULL, NULL, NULL)); TRYF(nsp_session_close(handle)); TRYF(nsp_session_open(handle, SID_FILE_MGMT)); TRYF(nsp_cmd_s_dir_enum_init(handle, "/")); TRYF(nsp_cmd_r_dir_enum_init(handle)); for(;;) { VarEntry *fe; GNode *node; TRYF(nsp_cmd_s_dir_enum_next(handle)); err = nsp_cmd_r_dir_enum_next(handle, varname, &varsize, &vartype); if (err == ERR_EOT) break; else if (err != 0) return err; fe = tifiles_ve_create(); strcpy(fe->folder, varname); strcpy(fe->name, varname); fe->size = varsize; fe->type = vartype; fe->attr = ATTRB_NONE; node = g_node_new(fe); folder = g_node_append(*vars, node); ticalcs_info(_("Name: %s | Type: %8s | Attr: %i | Size: %08X"), fe->name, tifiles_vartype2string(handle->model, fe->type), fe->attr, fe->size); } TRYF(nsp_cmd_s_dir_enum_done(handle)); TRYF(nsp_cmd_r_dir_enum_done(handle)); for(i = 0; i < (int)g_node_n_children(*vars); i++) { char *folder_name; char *u1, *u2; folder = g_node_nth_child(*vars, i); folder_name = ((VarEntry *) (folder->data))->name; vartype = ((VarEntry *) (folder->data))->type; // Skip entries whose type is 0 (TNS), for example themes.csv on OS 3.0+. if (vartype == 0) { ticalcs_info(_("Not enumerating documents in %s because it's not a folder"), folder_name); continue; } ticalcs_info(_("Directory listing in <%s>..."), folder_name); TRYF(nsp_cmd_s_dir_enum_init(handle, folder_name)); TRYF(nsp_cmd_r_dir_enum_init(handle)); for(;;) { VarEntry *ve = tifiles_ve_create(); GNode *node; char *ext; TRYF(nsp_cmd_s_dir_enum_next(handle)); err = nsp_cmd_r_dir_enum_next(handle, varname, &varsize, &vartype); if (err == ERR_EOT) break; else if (err != 0) return err; ext = tifiles_fext_get(varname); strcpy(ve->folder, folder_name); ve->size = varsize; ve->type = tifiles_fext2vartype(handle->model, ext); ve->attr = ATTRB_NONE; // Just a sanity check if (ext) { // Did the file name have any non-empty extension ? if (*ext) { // Do we know about this file type ? if (ve->type < NSP_MAXTYPES) { // Then we can remove the exension. *(ext-1) = '\0'; } // else don't remove the extension. } // else there is no extension to remove. } strcpy(ve->name, varname); node = g_node_new(ve); g_node_append(folder, node); ticalcs_info(_("Name: %8s | Type: %8s | Attr: %i | Size: %08X"), ve->name, tifiles_vartype2string(handle->model, ve->type), ve->attr, ve->size); u1 = ticonv_varname_to_utf8(handle->model, ((VarEntry *) (folder->data))->name, -1); u2 = ticonv_varname_to_utf8(handle->model, ve->name, ve->type); g_snprintf(update_->text, sizeof(update_->text), _("Parsing %s/%s"), u1, u2); g_free(u1); g_free(u2); update_label(); } TRYF(nsp_cmd_s_dir_enum_done(handle)); TRYF(nsp_cmd_r_dir_enum_done(handle)); } TRYF(nsp_session_close(handle)); return 0; }
int tixx_recv_backup(CalcHandle* handle, BackupContent* content) { int i, j, k; int i_max, j_max; GNode *vars, *apps; int nvars, ivars = 0; int b = 0; FileContent **group; FileContent *single; if(handle == NULL) return ERR_INVALID_HANDLE; if (content == NULL) { ticalcs_critical("tixx_recv_backup: content is NULL"); return -1; } // Do a directory list and check for something to backup TRYF(handle->calc->get_dirlist(handle, &vars, &apps)); nvars = ticalcs_dirlist_ve_count(vars); if(!nvars) return ERR_NO_VARS; update_->cnt2 = update_->cnt3 = 0; update_->max2 = update_->max3 = nvars; update_->pbar(); // Check whether the last folder is empty b = g_node_n_children(g_node_nth_child(vars, g_node_n_children(vars) - 1)); PAUSE(100); // needed by TI84+/USB // Create a group file k = 0; group = tifiles_content_create_group(nvars); // Receive all vars except for FLASH apps i_max = g_node_n_children(vars); for(i = 0; i < i_max; i++) { GNode *parent = g_node_nth_child(vars, i); j_max = g_node_n_children(parent); for(j = 0; j < j_max; j++) { GNode *node = g_node_nth_child(parent, j); VarEntry *ve = (VarEntry *) (node->data); update_->cnt2 = update_->cnt3 = ++ivars; update_->pbar(); // we need to group files ! TRYF(handle->calc->is_ready(handle)); group[k] = tifiles_content_create_regular(handle->model); TRYF(handle->calc->recv_var(handle, 0, group[k++], ve)); } } ticalcs_dirlist_destroy(&vars); ticalcs_dirlist_destroy(&apps); tifiles_group_contents(group, &single); tifiles_content_delete_group(group); // Swap content and single because we have a pointer on an allocated content { FileContent* cnt = (FileContent *)content; memcpy(content, single, sizeof(FileContent)); cnt->entries = single->entries; strcpy(cnt->comment, tifiles_comment_set_group()); } return 0; }
static int recv_flash (CalcHandle* handle, FlashContent* content, VarRequest* vr) { uint16_t aids[] = { AID_ARCHIVED, AID_VAR_VERSION }; const int naids = sizeof(aids) / sizeof(uint16_t); CalcAttr **attrs; const int nattrs = 1; char fldname[40], varname[40]; uint8_t *data; char *utf8; int page; uint16_t data_addr = 0x4000; uint16_t data_page = 0; int r, q; utf8 = ticonv_varname_to_utf8(handle->model, vr->name, vr->type); g_snprintf(update_->text, sizeof(update_->text), "%s", utf8); g_free(utf8); update_label(); attrs = ca_new_array(nattrs); attrs[0] = ca_new(AID_VAR_TYPE2, 4); attrs[0]->data[0] = 0xF0; attrs[0]->data[1] = 0x07; attrs[0]->data[2] = 0x00; attrs[0]->data[3] = vr->type; TRYF(cmd_s_var_request(handle, "", vr->name, naids, aids, nattrs, CA(attrs))); ca_del_array(nattrs, attrs); attrs = ca_new_array(naids); TRYF(cmd_r_var_header(handle, fldname, varname, attrs)); TRYF(cmd_r_var_content(handle, NULL, &data)); content->model = handle->model; strcpy(content->name, vr->name); content->data_type = vr->type; content->device_type = DEVICE_TYPE_83P; content->num_pages = 2048; // TI83+ has 512 KB of FLASH max content->pages = tifiles_fp_create_array(content->num_pages); q = vr->size / FLASH_PAGE_SIZE; r = vr->size % FLASH_PAGE_SIZE; update_->cnt2 = 0; update_->max2 = q; for(page = 0; page < q; page++) { FlashPage *fp = content->pages[page] = tifiles_fp_create(); fp->addr = data_addr; fp->page = data_page++; fp->flag = 0x80; fp->size = FLASH_PAGE_SIZE; fp->data = tifiles_fp_alloc_data(FLASH_PAGE_SIZE); memcpy(fp->data, data + FLASH_PAGE_SIZE*page, FLASH_PAGE_SIZE); update_->cnt2 = page; update_->pbar(); } { FlashPage *fp = content->pages[page] = tifiles_fp_create(); fp->addr = data_addr; fp->page = data_page++; fp->flag = 0x80; fp->size = r; fp->data = tifiles_fp_alloc_data(FLASH_PAGE_SIZE); memcpy(fp->data, data + FLASH_PAGE_SIZE*page, r); update_->cnt2 = page; update_->pbar(); } content->num_pages = page+1; g_free(data); ca_del_array(naids, attrs); return 0; }
static int send_backup (CalcHandle* handle, BackupContent* content) { int err = 0; uint16_t length; char varname[9]; uint8_t rej_code; uint16_t status; g_snprintf(update_->text, sizeof(update_->text), _("Waiting for user's action...")); update_label(); length = content->data_length1; varname[0] = LSB(content->data_length2); varname[1] = MSB(content->data_length2); varname[2] = LSB(content->data_length3); varname[3] = MSB(content->data_length3); varname[4] = LSB(content->mem_address); varname[5] = MSB(content->mem_address); TRYF(ti85_send_VAR(content->data_length1, TI85_BKUP, varname)); TRYF(ti85_recv_ACK(&status)); do { // wait user's action update_refresh(); if (update_->cancel) return ERR_ABORT; err = ti85_recv_SKP(&rej_code); } while (err == ERROR_READ_TIMEOUT); TRYF(ti85_send_ACK()); switch (rej_code) { case REJ_EXIT: case REJ_SKIP: return ERR_ABORT; case REJ_MEMORY: return ERR_OUT_OF_MEMORY; default: // RTS break; } strcpy(update_->text, ""); update_label(); update_->cnt2 = 0; update_->max2 = 3; update_->pbar(); TRYF(ti85_send_XDP(content->data_length1, content->data_part1)); TRYF(ti85_recv_ACK(&status)); update_->cnt2++; update_->pbar(); TRYF(ti85_send_XDP(content->data_length2, content->data_part2)); TRYF(ti85_recv_ACK(&status)); update_->cnt2++; update_->pbar(); TRYF(ti85_send_XDP(content->data_length3, content->data_part3)); TRYF(ti85_recv_ACK(&status)); update_->cnt2++; update_->pbar(); TRYF(ti85_send_EOT()); return 0; }
static int send_var_ns (CalcHandle* handle, CalcMode mode, FileContent* content) { int i; int err; uint8_t rej_code; uint16_t status; char *utf8; update_->cnt2 = 0; update_->max2 = content->num_entries; for (i = 0; i < content->num_entries; i++) { VarEntry *entry = content->entries[i]; TRYF(ti85_send_VAR((uint16_t)entry->size, entry->type, entry->name)); TRYF(ti85_recv_ACK(&status)); g_snprintf(update_->text, sizeof(update_->text), _("Waiting for user's action...")); update_label(); do { // wait user's action update_refresh(); if (update_->cancel) return ERR_ABORT; err = ti85_recv_SKP(&rej_code); } while (err == ERROR_READ_TIMEOUT); TRYF(ti85_send_ACK()); switch (rej_code) { case REJ_EXIT: return ERR_ABORT; case REJ_SKIP: continue; case REJ_MEMORY: return ERR_OUT_OF_MEMORY; default: // RTS break; } utf8 = ticonv_varname_to_utf8(handle->model, entry->name, entry->type); g_snprintf(update_->text, sizeof(update_->text), "%s", utf8); g_free(utf8); update_label(); TRYF(ti85_send_XDP(entry->size, entry->data)); TRYF(ti85_recv_ACK(&status)); update_->cnt2 = i+1; update_->max2 = content->num_entries; update_->pbar(); } if ((mode & MODE_SEND_ONE_VAR) || (mode & MODE_SEND_LAST_VAR)) { TRYF(ti85_send_EOT()); TRYF(ti85_recv_ACK(NULL)); } return 0; }