// Work around TI's OS behaviour: extra bulk write of 0 size required after the last raw packet in a transfer, // when some conditions are met. static void workaround_send(CalcHandle *h, DUSBRawPacket *raw, DUSBVirtualPacket *vtl) { uint8_t buf[64]; ticalcs_info("workaround_send: vtl->size=%d\traw->size=%d", vtl->size, raw->size); if (h->model == CALC_TI89T_USB) { // A 1076-byte (string) variable doesn't require this workaround, but bigger (string) variables do. if (vtl->size > 1076 && ((raw->size + 5) % 64) == 0) { ticalcs_info("XXX triggering an extra bulk write\n\tvtl->size=%d\traw->size=%d", vtl->size, raw->size); ticables_cable_send(h->cable, buf, 0); } } else // if (h->model == CALC_TI84P_USB) { // A 244-byte (program) variable doesn't require this workaround, but bigger (program) variables do. if (raw->type == DUSB_RPKT_VIRT_DATA_LAST && vtl->size > 244 && (vtl->size % 250) == 244) { ticalcs_info("XXX triggering an extra bulk write\n\tvtl->size=%d\traw->size=%d", vtl->size, raw->size); ticables_cable_send(h->cable, buf, 0); } } }
static int send_pkt(CalcHandle* handle, uint16_t cmd, uint16_t len, uint8_t* data) { uint16_t sum; // command buf[0] = LSB(cmd); buf[1] = MSB(cmd); // length buf[2] = LSB(len); buf[3] = MSB(len); // data if(data) memcpy(buf+4, data, len); // checksum sum = tifiles_checksum(buf, 4 + len); buf[len+4+0] = LSB(sum); buf[len+4+1] = MSB(sum); TRYF(ticables_cable_send(handle->cable, buf, len+6)); return 0; }
TIEXPORT3 int TICALL ti68k_send_KEY(CalcHandle* handle, uint16_t scancode, uint8_t target) { uint8_t buf[4] = { target, DBUS_CMD_KEY, LSB(scancode), MSB(scancode) }; VALIDATE_HANDLE(handle); ticalcs_info(" PC->TI: KEY"); return ticables_cable_send(handle->cable, buf, 4); }
TIEXPORT3 int TICALL ti73_send_KEY(CalcHandle* handle, uint16_t scancode) { uint8_t buf[5]; buf[0] = PC_TI7383; buf[1] = CMD_KEY; buf[2] = LSB(scancode); buf[3] = MSB(scancode); ticalcs_info(" PC->TI: KEY"); return ticables_cable_send(handle->cable, buf, 4); }
int ti83_send_KEY_h(CalcHandle* handle, uint16_t scancode) { uint8_t buf[5]; buf[0] = PC_TI83; buf[1] = CMD_KEY; buf[2] = LSB(scancode); buf[3] = MSB(scancode); ticalcs_info(" PC->TI: KEY"); TRYF(ticables_cable_send(handle->cable, buf, 4)); return 0; }
TIEXPORT3 int TICALL dusb_send(CalcHandle* handle, DUSBRawPacket* pkt) { uint8_t buf[sizeof(pkt->data) + 5]; uint32_t size; int ret; VALIDATE_HANDLE(handle); VALIDATE_NONNULL(pkt); memset(buf, 0, sizeof(buf)); size = pkt->size; if (size > sizeof(pkt->data)) { size = sizeof(pkt->data); } buf[0] = MSB(MSW(size)); buf[1] = LSB(MSW(size)); buf[2] = MSB(LSW(size)); buf[3] = LSB(LSW(size)); buf[4] = pkt->type; memcpy(buf + 5, pkt->data, size); //printf("dusb_send: pkt->size=%d\n", pkt->size); ticables_progress_reset(handle->cable); ret = ticables_cable_send(handle->cable, buf, size + 5); if (!ret) { if (size >= 128) { ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate); } if (handle->updat->cancel) { ret = ERR_ABORT; } } return ret; }
int dusb_send(CalcHandle* handle, RawPacket* pkt) { uint8_t buf[1023 + 5]= { 0 }; uint32_t size = pkt->size + 5; buf[0] = MSB(MSW(pkt->size)); buf[1] = LSB(MSW(pkt->size)); buf[2] = MSB(LSW(pkt->size)); buf[3] = LSB(LSW(pkt->size)); buf[4] = pkt->type; memcpy(buf+5, pkt->data, pkt->size); //printf("dusb_send: pkt->size=%d\n", pkt->size); ticables_progress_reset(handle->cable); TRYF(ticables_cable_send(handle->cable, buf, size)); if(size >= 128) ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate); if (handle->updat->cancel) return ERR_ABORT; return 0; }
TIEXPORT3 int TICALL dusb_send(CalcHandle* handle, DUSBRawPacket* pkt) { uint8_t buf[1023 + 5]= { 0 }; uint32_t size; if (handle == NULL) { ticalcs_critical("%s: handle is NULL", __FUNCTION__); return ERR_INVALID_HANDLE; } if (pkt == NULL) { ticalcs_critical("%s: pkt is NULL", __FUNCTION__); return ERR_INVALID_PACKET; } size = pkt->size + 5; buf[0] = MSB(MSW(pkt->size)); buf[1] = LSB(MSW(pkt->size)); buf[2] = MSB(LSW(pkt->size)); buf[3] = LSB(LSW(pkt->size)); buf[4] = pkt->type; memcpy(buf+5, pkt->data, pkt->size); //printf("dusb_send: pkt->size=%d\n", pkt->size); ticables_progress_reset(handle->cable); TRYF(ticables_cable_send(handle->cable, buf, size)); if(size >= 128) ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate); if (handle->updat->cancel) return ERR_ABORT; return 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; }
/* Send a packet from PC (host) to TI (target): - target [in] : a machine ID uint8_t - cmd [in] : a command ID uint8_t - length [in] : length of buffer - data [in] : data to send (or 0x00 if NULL) - int [out] : an error code */ TIEXPORT3 int TICALL dbus_send(CalcHandle* handle, uint8_t target, uint8_t cmd, uint16_t len, uint8_t* data) { int i; uint16_t sum; uint32_t length = (len == 0x0000) ? 65536 : len; // wrap around uint8_t *buf; int r, q; static int ref = 0; if (handle == NULL) { ticalcs_critical("%s: handle is NULL", __FUNCTION__); return ERR_INVALID_HANDLE; } buf = (uint8_t *)handle->priv2; //[65536+6]; if (buf == NULL) { ticalcs_critical("%s: handle->priv2 is NULL", __FUNCTION__); return ERR_INVALID_HANDLE; } ticables_progress_reset(handle->cable); if(data == NULL) { // short packet (no data) buf[0] = target; buf[1] = cmd; buf[2] = 0x00; buf[3] = 0x00; // TI80 does not use length if(target == PC_TI80) { TRYF(ticables_cable_send(handle->cable, buf, 2)); } else { TRYF(ticables_cable_send(handle->cable, buf, 4)); } } else { // std packet (data + checksum) buf[0] = target; buf[1] = cmd; buf[2] = LSB(length); buf[3] = MSB(length); // copy data memcpy(buf+4, data, length); // add checksum of packet sum = tifiles_checksum(data, length); buf[length+4+0] = LSB(sum); buf[length+4+1] = MSB(sum); // compute chunks MIN_SIZE = (handle->cable->model == CABLE_GRY) ? 512 : 2048; BLK_SIZE = (length + 6) / 20; // 5% if(BLK_SIZE == 0) BLK_SIZE = length + 6; if(BLK_SIZE < 32) BLK_SIZE = 128; // SilverLink doesn't like small block (< 32) q = (length + 6) / BLK_SIZE; r = (length + 6) % BLK_SIZE; handle->updat->max1 = length + 6; handle->updat->cnt1 = 0; // send full chunks for(i = 0; i < q; i++) { TRYF(ticables_cable_send(handle->cable, &buf[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; } // send last chunk { TRYF(ticables_cable_send(handle->cable, &buf[i*BLK_SIZE], (uint16_t)r)); ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate); handle->updat->cnt1 += 1; if(length > MIN_SIZE) handle->updat->pbar(); if (handle->updat->cancel) return ERR_ABORT; } } // force periodic refresh if(!(ref++ % 4)) handle->updat->refresh(); return 0; }
/* Send a packet from PC (host) to TI (target): - target [in] : a machine ID uint8_t - cmd [in] : a command ID uint8_t - length [in] : length of buffer - data [in] : data to send (or 0x00 if NULL) - int [out] : an error code */ TIEXPORT3 int TICALL dbus_send(CalcHandle* handle, uint8_t target, uint8_t cmd, uint16_t len, const uint8_t* data) { int i; uint16_t sum; uint32_t length = (len == 0x0000) ? 65536 : len; // wrap around uint8_t *buf; int r, q; static int ref = 0; int ret; VALIDATE_HANDLE(handle); buf = (uint8_t *)handle->buffer; //[65536+6]; if (buf == NULL) { ticalcs_critical("%s: handle->buffer is NULL", __FUNCTION__); return ERR_INVALID_HANDLE; } ticables_progress_reset(handle->cable); if (data == NULL) { // short packet (no data) buf[0] = target; buf[1] = cmd; buf[2] = 0x00; buf[3] = 0x00; // The TI-80 does not use length ret = ticables_cable_send(handle->cable, buf, (target == DBUS_MID_PC_TI80) ? 2 : 4); } else { // std packet (data + checksum) buf[0] = target; buf[1] = cmd; buf[2] = LSB(length); buf[3] = MSB(length); // copy data memcpy(buf+4, data, length); // add checksum of packet sum = tifiles_checksum(data, length); buf[length+4+0] = LSB(sum); buf[length+4+1] = MSB(sum); // compute chunks handle->priv.progress_min_size = (handle->cable->model == CABLE_GRY) ? 512 : 2048; handle->priv.progress_blk_size = (length + 6) / 20; // 5% if (handle->priv.progress_blk_size == 0) { handle->priv.progress_blk_size = length + 6; } if (handle->priv.progress_blk_size < 32) { handle->priv.progress_blk_size = 128; // SilverLink doesn't like small block (< 32) } q = (length + 6) / handle->priv.progress_blk_size; r = (length + 6) % handle->priv.progress_blk_size; handle->updat->max1 = length + 6; handle->updat->cnt1 = 0; ret = 0; // send full chunks for (i = 0; i < q; i++) { ret = ticables_cable_send(handle->cable, &buf[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; } } // send last chunk if (!ret) { ret = ticables_cable_send(handle->cable, &buf[i*handle->priv.progress_blk_size], (uint16_t)r); if (!ret) { ticables_progress_get(handle->cable, NULL, NULL, &handle->updat->rate); handle->updat->cnt1 += 1; if (length > handle->priv.progress_min_size) { handle->updat->pbar(); } if (handle->updat->cancel) { ret = ERR_ABORT; } } } } // force periodic refresh if (!ret && !(ref++ % 4)) { handle->updat->refresh(); } return ret; }