int dusb_recv(CalcHandle* handle, RawPacket* pkt) { uint8_t buf[5]; // Any packet has always an header of 5 bytes (size & type) ticables_progress_reset(handle->cable); TRYF(ticables_cable_recv(handle->cable, buf, 5)); pkt->size = buf[3] | (buf[2] << 8) | (buf[1] << 16) | (buf[0] << 24); pkt->type = buf[4]; if(handle->model == CALC_TI84P_USB && pkt->size > 250) return ERR_INVALID_PACKET; if(handle->model == CALC_TI89T_USB && pkt->size > 1023) return ERR_INVALID_PACKET; //printf("dusb_send: pkt->size=%d\n", pkt->size); // Next, follows data TRYF(ticables_cable_recv(handle->cable, pkt->data, pkt->size)); if(pkt->size >= 128) ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate); if (handle->updat->cancel) return ERR_ABORT; return 0; }
// Work around TI's OS behaviour: extra bulk read of 0 size required after the last raw packet in a transfer, // when some conditions are met. static void workaround_recv(CalcHandle *handle, DUSBRawPacket * raw, DUSBVirtualPacket * vtl) { uint8_t buf[64]; ticalcs_info("workaround_recv: vtl->size=%d\traw->size=%d", vtl->size, raw->size); if (handle->model == CALC_TI89T_USB) { if ((raw->size % 64) == 0) { ticalcs_info("XXX triggering an extra bulk read\n\tvtl->size=%d\traw->size=%d", vtl->size, raw->size); ticables_cable_recv(handle->cable, buf, 0); } } else if (handle->model == CALC_TI84P_USB || handle->model == CALC_TI84PC_USB || handle->model == CALC_TI82A_USB || handle->model == CALC_TI84PT_USB) { if (((raw->size + 5) % 64) == 0) { ticalcs_info("XXX triggering an extra bulk read\n\tvtl->size=%d\traw->size=%d", vtl->size, raw->size); ticables_cable_recv(handle->cable, buf, 0); } } else if (handle->model == CALC_TI83PCE_USB || handle->model == CALC_TI84PCE_USB) { // These models don't seem to need receive workarounds. } else { ticalcs_warning("XXX unhandled model in workaround_recv"); } }
TIEXPORT3 int TICALL dbus_recv_header(CalcHandle *handle, uint8_t* host, uint8_t* cmd, uint16_t* length) { int ret; uint8_t buf[4]; VALIDATE_HANDLE(handle); VALIDATE_NONNULL(host); VALIDATE_NONNULL(cmd); VALIDATE_NONNULL(length); // Any packet has always at least 2 bytes (MID, CID) ret = ticables_cable_recv(handle->cable, buf, 2); if (!ret) { *host = buf[0]; *cmd = buf[1]; // Any non-TI-80 packet has a length; TI-80 data packets also have a length if (*host != DBUS_MID_TI80_PC || *cmd == DBUS_CMD_XDP) { ret = ticables_cable_recv(handle->cable, buf, 2); if (!ret) { *length = buf[0] | ((uint16_t)buf[1] << 8); } } else { *length = 0; } } return ret; }
TIEXPORT3 int TICALL dusb_recv(CalcHandle* handle, DUSBRawPacket* pkt) { uint8_t buf[5]; int ret; VALIDATE_HANDLE(handle); VALIDATE_NONNULL(pkt); // Any packet has always an header of 5 bytes (size & type) ticables_progress_reset(handle->cable); ret = ticables_cable_recv(handle->cable, buf, 5); while (!ret) { pkt->size = buf[3] | (((uint32_t)buf[2]) << 8) | (((uint32_t)buf[1]) << 16) | (((uint32_t)buf[0]) << 24); pkt->type = buf[4]; if ( (handle->model == CALC_TI84P_USB || handle->model == CALC_TI84PC_USB || handle->model == CALC_TI82A_USB || handle->model == CALC_TI84PT_USB) && pkt->size > 250) { ticalcs_warning("Raw packet is unexpectedly large: %u bytes", pkt->size); } else if ( (handle->model == CALC_TI83PCE_USB || handle->model == CALC_TI84PCE_USB) && pkt->size > 1018) { ticalcs_warning("Raw packet is unexpectedly large: %u bytes", pkt->size); } else if (handle->model == CALC_TI89T_USB) { // Fall through. } // else do nothing for now. if (pkt->size > sizeof(pkt->data)) { ticalcs_critical("Raw packet is too large: %u bytes", pkt->size); ret = ERR_INVALID_PACKET; break; } //printf("dusb_send: pkt->size=%d\n", pkt->size); // Next, follows data ret = ticables_cable_recv(handle->cable, pkt->data, pkt->size); if (!ret) { if (pkt->size >= 128) { ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate); } if (handle->updat->cancel) { ret = ERR_ABORT; } } break; } return ret; }
static int recv_cert (CalcHandle* handle, FlashContent* content) { int ret; int i; uint8_t buf[256]; ticalcs_strlcpy(handle->updat->text, _("Receiving certificate"), sizeof(handle->updat->text)); ticalcs_update_label(handle); content->model = handle->model; content->name[0] = 0; content->data_type = TI83p_CERT; content->device_type = 0x73; content->num_pages = 0; content->data_part = (uint8_t *)tifiles_ve_alloc_data(2 * 1024 * 1024); // 2MB max ret = SEND_REQ2(handle, 0x00, TI83p_GETCERT, "\0\0\0\0\0\0\0", 0x00); if (!ret) { ret = RECV_ACK(handle, NULL); if (!ret) { ret = ticables_cable_recv(handle->cable, buf, 4); //VAR w/ no header if (!ret) { ticalcs_info(" TI->PC: VAR"); ret = SEND_ACK(handle); for (i = 0, content->data_length = 0; !ret; i++) { uint16_t block_size; ret = SEND_CTS(handle); if (!ret) { ret = RECV_ACK(handle, NULL); if (!ret) { ret = RECV_XDP(handle, &block_size, content->data_part); if (!ret) { ret = SEND_ACK(handle); if (!ret) { content->data_length += block_size; handle->updat->cnt2 += block_size; ticalcs_update_pbar(handle); } } } } } } } } return ret; }
// Work around TI's OS behaviour: extra bulk read of 0 size required after the last raw packet in a transfer, // when some conditions are met. static void workaround_recv(CalcHandle *h, DUSBRawPacket * raw, DUSBVirtualPacket * vtl) { uint8_t buf[64]; ticalcs_info("workaround_recv: vtl->size=%d\traw->size=%d", vtl->size, raw->size); if (h->model == CALC_TI89T_USB) { if ((raw->size % 64) == 0) { ticalcs_info("XXX triggering an extra bulk read\n\tvtl->size=%d\traw->size=%d", vtl->size, raw->size); ticables_cable_recv(h->cable, buf, 0); } } else // if (h->model == CALC_TI84P_USB) { if (((raw->size + 5) % 64) == 0) { ticalcs_info("XXX triggering an extra bulk read\n\tvtl->size=%d\traw->size=%d", vtl->size, raw->size); ticables_cable_recv(h->cable, buf, 0); } } }
int main(int argc, char **argv) { CableHandle *handle; int err; // int i, j; // uint8_t buf[65536], data; // int status, result; // uint8_t scr[3840 + 6]; // int **probing = NULL; #if 0 tiTIME ref, end; unsigned long k; to_START(ref); for(k = 0; k < 1000000; k++) printf(" "); to_START(end); printf("%lu %lu\n", ref, end); printf("%lu\n", to_CURRENT(ref)); printf("%i\n", to_ELAPSED(ref, 60)); return 0; #endif printf("USB support: %i\n", ticables_is_usb_enabled()); // init lib ticables_library_init(); print_lc_error(1); #if 0 ticables_probing_do(&probing, 5, PROBE_ALL); for(i = 1; i <= 7; i++) printf("%i: %i %i %i %i\n", i, probing[i][1], probing[i][2], probing[i][3], probing[i][4]); ticables_probing_finish(&probing); #endif #if 0 { int *list = NULL; int i, n; int *p; ticables_get_usb_devices(&list, &n); printf("List of devices:\n"); for(i = 0; i < n; i++) printf("%i: %04x\n", i, list[i]); } #endif // set cable handle = ticables_handle_new(CABLE_PAR, PORT_1); if(handle == NULL) return -1; ticables_options_set_timeout(handle, 15); ticables_options_set_delay(handle, 10); ticables_handle_show(handle); // open cable err = ticables_cable_open(handle); if(err) print_lc_error(err); if(err) return -1; #if 0 // simple test with DirectLink hand-helds (buf size req/neg) buf[0]=0x00; buf[1]=0x00; buf[2]=0x00; buf[3]=0x04; buf[4]=0x01; buf[5]=0x00; buf[6]=0x00; buf[7]=0x04; buf[8]=0x00; err = ticables_cable_send(handle, buf, 9); if(err) print_lc_error(err); // display answer memset(buf, 0, sizeof(buf)); err = ticables_cable_recv(handle, buf, 9); if(err) print_lc_error(err); for(i = 0; i < 9; i++) printf("%02x ", buf[i]); printf("\n"); #endif #if 0 // mode set i = 0; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x10; buf[i++]=0x04; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x0a; buf[i++]=0x00; buf[i++]=0x01; buf[i++]=0x00; buf[i++]=0x03; buf[i++]=0x00; buf[i++]=0x01; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x07; buf[i++]=0xd0; err = ticables_cable_send(handle, buf, i); if(err) print_lc_error(err); err = ticables_cable_recv(handle, buf, 7); if(err) print_lc_error(err); for(i = 0; i < 7; i++) printf("%02x ", buf[i]); printf("\n"); // mode ack err = ticables_cable_recv(handle, buf, 15); if(err) print_lc_error(err); for(i = 0; i < 15; i++) printf("%02x ", buf[i]); printf("\n"); i = 0; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x02; buf[i++]=0x05; buf[i++]=0xe0; buf[i++]=0x00; err = ticables_cable_send(handle, buf, i); if(err) print_lc_error(err); PAUSE(500); #endif #if 0 // param req (TI84+ only) i = 0; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0xa; buf[i++]=0x04; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x04; buf[i++]=0x00; buf[i++]=0x07; buf[i++]=0x00; buf[i++]=0x01; buf[i++]=0x00; buf[i++]=0x22; err = ticables_cable_send(handle, buf, i); if(err) print_lc_error(err); err = ticables_cable_recv(handle, buf, 7); if(err) print_lc_error(err); for(i = 0; i < 7; i++) printf("%02x ", buf[i]); printf("\n"); // delay ack err = ticables_cable_recv(handle, buf, 15); if(err) print_lc_error(err); for(i = 0; i < 15; i++) printf("%02x ", buf[i]); printf("\n"); i = 0; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x02; buf[i++]=0x05; buf[i++]=0xe0; buf[i++]=0x00; err = ticables_cable_send(handle, buf, i); if(err) print_lc_error(err); // param data for(j = 0; j < 3; j++) { err = ticables_cable_recv(handle, buf, 255); if(err) print_lc_error(err); for(i = 0; i < 16; i++) printf("%02x ", buf[i]); printf("\n"); i = 0; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x02; buf[i++]=0x05; buf[i++]=0xe0; buf[i++]=0x00; err = ticables_cable_send(handle, buf, i); if(err) print_lc_error(err); } { err = ticables_cable_recv(handle, buf, 36); if(err) print_lc_error(err); for(i = 0; i < 16; i++) printf("%02x ", buf[i]); printf("\n"); i = 0; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x00; buf[i++]=0x02; buf[i++]=0x05; buf[i++]=0xe0; buf[i++]=0x00; err = ticables_cable_send(handle, buf, i); if(err) print_lc_error(err); } PAUSE(500); #endif #if 0 // do a simple test with a TI89/92+ calculator buf[0] = 0x08; buf[1] = 0x68; buf[2] = 0x00; buf[3] = 0x00; // RDY err = ticables_cable_send(handle, buf, 4); if(err) print_lc_error(err); // display answer memset(buf, 0xff, 4); err = ticables_cable_recv(handle, buf, 4); if(err) print_lc_error(err); for(i = 0; i < 4; i++) printf("%02x ", buf[i]); printf("\n"); #endif #if 0 // do a screendump buf[0] = 0x08; buf[1] = 0x6D; buf[2] = 0x00; buf[3] = 0x00; // SCR err = ticables_cable_send(handle, buf, 4); if(err) print_lc_error(err); memset(buf, 0xff, 4); err = ticables_cable_recv(handle, buf, 4); // ACK if(err) print_lc_error(err); err = ticables_cable_recv(handle, scr, 0x0f00 + 6); // XDP if(err) print_lc_error(err); printf("%02x %02x\n", scr[2], scr[3]); buf[0] = 0x08; buf[1] = 0x56; buf[2] = 0x00; buf[3] = 0x00; // ACK err = ticables_cable_send(handle, buf, 4); if(err) print_lc_error(err); #endif #if 0 // simple test for data arrival detection buf[0] = 0x08; buf[1] = 0x87; buf[2] = 'A'; buf[3] = 0x00; // KEY err = ticables_cable_send(handle, buf, 4); if(err) print_lc_error(err); for(status = 0; !status;) { err = ticables_cable_check(handle, &status); if(err) print_lc_error(err); } // display answer memset(buf, 0xff, 4); err = ticables_cable_recv(handle, buf, 4); if(err) print_lc_error(err); for(i = 0; i < 4; i++) printf("%02x ", buf[i]); printf("\n"); #endif #if 0 for(status = 0; !status;) { //fprintf(stdout, "$\n"); //fflush(stdout); err = ticables_cable_check(handle, &status); if(err) print_lc_error(err); } // display answer memset(buf, 0xff, 4); err = ticables_cable_recv(handle, buf, 4); if(err) print_lc_error(err); for(i = 0; i < 4; i++) printf("%02x ", buf[i]); printf("\n"); #endif // close cable ticables_cable_close(handle); // release handle ticables_handle_del(handle); // exit lib ticables_library_exit(); #ifdef __WIN32__ while(!kbhit()); #endif return 0; }
static int recv_pkt(CalcHandle* handle, uint16_t* cmd, uint16_t* len, uint8_t* data) { int i, r, q; uint16_t sum, chksum; // Any packet has always at least 4 bytes (cmd, len) TRYF(ticables_cable_recv(handle->cable, buf, 4)); *cmd = (buf[1] << 8) | buf[0]; *len = (buf[3] << 8) | buf[2]; if(!cmd_is_valid(*cmd)) return ERR_INVALID_CMD; if(*cmd == CMD_ERROR) return ERR_ROM_ERROR; // compute chunks BLK_SIZE = *len / 20; if(BLK_SIZE == 0) BLK_SIZE = 1; q = *len / BLK_SIZE; r = *len % BLK_SIZE; handle->updat->max1 = *len; handle->updat->cnt1 = 0; // recv full chunks for(i = 0; i < q; i++) { TRYF(ticables_cable_recv(handle->cable, &buf[i*BLK_SIZE + 4], BLK_SIZE)); ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate); handle->updat->cnt1 += BLK_SIZE; if(*len > MIN_SIZE) handle->updat->pbar(); //if (handle->updat->cancel) // return ERR_ABORT; } // recv last chunk { TRYF(ticables_cable_recv(handle->cable, &buf[i*BLK_SIZE + 4], (uint16_t)(r+2))); ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate); handle->updat->cnt1 += 1; if(*len > MIN_SIZE) handle->updat->pbar(); if (handle->updat->cancel) return ERR_ABORT; } // verify checksum chksum = (buf[*len+4 + 1] << 8) | buf[*len+4 + 0]; sum = tifiles_checksum(buf, *len + 4); //printf("<%04x %04x>\n", sum, chksum); if (chksum != sum) return ERR_CHECKSUM; if(data) memcpy(data, buf+4, *len); return 0; }
static int dbus_recv_(CalcHandle* handle, uint8_t* host, uint8_t* cmd, uint16_t* length, uint8_t* data, int host_check) { int i; uint16_t chksum; uint8_t buf[4]; int r, q; static int ref = 0; if (handle == NULL) { ticalcs_critical("%s: handle is NULL", __FUNCTION__); return ERR_INVALID_HANDLE; } if (host == NULL || cmd == NULL || length == NULL) { ticalcs_critical("%s: an argument is NULL", __FUNCTION__); return ERR_INVALID_PACKET; } // Any packet has always at least 2 bytes (MID, CID) TRYF(ticables_cable_recv(handle->cable, buf, 2)); *host = buf[0]; *cmd = buf[1]; // Any non-TI80 packet has a length; TI80 data packets also have a length if(*host != TI80_PC || *cmd == CMD_XDP) { TRYF(ticables_cable_recv(handle->cable, buf, 2)); *length = buf[0] | (buf[1] << 8); } else *length = 0; //removed for probing (pb here !) //if(host_check && (*host != host_ids(handle))) // return ERR_INVALID_HOST; if(*cmd == CMD_ERR || *cmd == CMD_ERR2) return ERR_CHECKSUM; switch (*cmd) { case CMD_VAR: // std packet ( data + checksum) case CMD_XDP: case CMD_SKP: case CMD_SID: case CMD_REQ: case CMD_IND: case CMD_RTS: if (data == NULL) { ticalcs_critical("%s: data is NULL", __FUNCTION__); return ERR_INVALID_CMD; } // compute chunks* MIN_SIZE = (handle->cable->model == CABLE_GRY) ? 512 : 2048; BLK_SIZE = *length / 20; if(BLK_SIZE == 0) BLK_SIZE = 1; q = *length / BLK_SIZE; r = *length % BLK_SIZE; handle->updat->max1 = *length; handle->updat->cnt1 = 0; // recv full chunks for(i = 0; i < q; i++) { TRYF(ticables_cable_recv(handle->cable, &data[i*BLK_SIZE], BLK_SIZE)); ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate); handle->updat->cnt1 += BLK_SIZE; if(*length > MIN_SIZE) handle->updat->pbar(); if (handle->updat->cancel) return ERR_ABORT; } // recv last chunk { TRYF(ticables_cable_recv(handle->cable, &data[i*BLK_SIZE], (uint16_t)r)); ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate); TRYF(ticables_cable_recv(handle->cable, buf, 2)); handle->updat->cnt1 += 1; if(*length > MIN_SIZE) handle->updat->pbar(); if (handle->updat->cancel) return ERR_ABORT; } // verify checksum chksum = buf[0] | (buf[1] << 8); if (chksum != tifiles_checksum(data, *length)) return ERR_CHECKSUM; break; case CMD_CTS: // short packet (no data) case CMD_ACK: case CMD_ERR: case CMD_ERR2: case CMD_RDY: case CMD_SCR: case CMD_RID: case CMD_KEY: case CMD_EOT: case CMD_CNT: break; default: return ERR_INVALID_CMD; } // force periodic refresh if(!(ref++ % 4)) handle->updat->refresh(); return 0; }
TIEXPORT3 int TICALL dbus_recv_data(CalcHandle *handle, uint16_t* length, uint8_t* data) { int ret; int i; uint16_t chksum; uint8_t buf[4]; int r, q; VALIDATE_HANDLE(handle); VALIDATE_NONNULL(length); VALIDATE_NONNULL(data); // compute chunks handle->priv.progress_min_size = (handle->cable->model == CABLE_GRY) ? 512 : 2048; handle->priv.progress_blk_size = *length / 20; if (handle->priv.progress_blk_size == 0) { handle->priv.progress_blk_size = 1; } q = *length / handle->priv.progress_blk_size; r = *length % handle->priv.progress_blk_size; handle->updat->max1 = *length; handle->updat->cnt1 = 0; ret = 0; // recv full chunks for (i = 0; i < q; i++) { ret = ticables_cable_recv(handle->cable, &data[i*handle->priv.progress_blk_size], handle->priv.progress_blk_size); if (ret) { break; } ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate); handle->updat->cnt1 += handle->priv.progress_blk_size; if (*length > handle->priv.progress_min_size) { handle->updat->pbar(); } if (handle->updat->cancel) { ret = ERR_ABORT; break; } } // recv last chunk if (!ret) { ret = ticables_cable_recv(handle->cable, &data[i*handle->priv.progress_blk_size], (uint16_t)r); if (!ret) { ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate); ret = ticables_cable_recv(handle->cable, buf, 2); if (!ret) { handle->updat->cnt1++; if (*length > handle->priv.progress_min_size) { handle->updat->pbar(); } if (handle->updat->cancel) { ret = ERR_ABORT; } } } } if (!ret) { // verify checksum chksum = buf[0] | ((uint16_t)buf[1] << 8); if (chksum != tifiles_checksum(data, *length)) { ret = ERR_CHECKSUM; } } return ret; }