/** * ticalcs_probe: * @c_model: link cable model * @c_port: link cable port * @model: hand-held model detected/found [out] * @all: which hand-helds to detect (FLASH only or all) * * This function attempts to detect the calculator model plugged onto a * given link cable model/port. It works in a heuristic fashion. * This function handles device opening/closing for you. * * Return value: 0 if successful, an error code otherwise. **/ TIEXPORT3 int TICALL ticalcs_probe(CableModel c_model, CablePort c_port, CalcModel* model, int all) { CableHandle *handle; int err = 0; CalcHandle calc; if (model == NULL) { ticalcs_critical("ticalcs_probe_calc: model is NULL"); return -1; } // get handle handle = ticables_handle_new(c_model, c_port); ticables_options_set_timeout(handle, 10); // hack: we construct the structure here because we don't really need it. // I want to use ticalcs functions with a non-fixed calculator memset(&calc, 0, sizeof(CalcHandle)); calc.model = *model = CALC_NONE; calc.updat = (CalcUpdate *)&default_update; calc.priv2 = (uint8_t *)g_malloc(65536 + 4); calc.cable = handle; calc.open = !0; // open cable err = ticables_cable_open(handle); if(err) { ticables_handle_del(handle); return err; } // probe if(c_model == CABLE_USB) err = ticalcs_probe_usb_calc(handle, model); else { if(all) err = ticalcs_probe_calc(handle, model); else err = ticalcs_probe_calc_1(&calc, model); } if(err) { ticables_cable_close(handle); ticables_handle_del(handle); return err; } // close ticables_cable_close(handle); ticables_handle_del(handle); return err; }
static int is_ready (CalcHandle* handle) { // If re-enabled, these ones should be moved to handle->priv. //static int rom_11 = 0; //static int rom_14 = 0; int ret; // 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) do { static const char echostr[] = "ready"; int old; uint32_t size; uint8_t *data; // XXX debrouxl moving those two calls 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. ret = nsp_addr_request(handle); if (ret) { break; } ret = nsp_addr_assign(handle, NSP_DEV_ADDR); if (ret) { break; } // XXX when commenting this OS version detection code, sending many Status or Dirlist // requests in quick succession often triggers memory corruption (hangs, reboots, // a variable amount of black pixels on the screen) on (at least) Nspire (CAS) OS 1.7... 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 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; ret = nsp_addr_request(handle); if (ret) { break; } ret = nsp_addr_assign(handle, NSP_DEV_ADDR); if (ret) { break; } } 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; // Now use ECHO packet as ready check ret = nsp_session_open(handle, NSP_SID_ECHO); if (!ret) { ret = nsp_cmd_s_echo(handle, sizeof(echostr), (uint8_t *)echostr); if (!ret) { ret = nsp_cmd_r_echo(handle, &size, &data); if (!ret) { g_free(data); } } } } while (0); return ret; }
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; }
/** * ticables_probing_do: * @result: address of an array of integers to put the result. * @timeout: timeout to set during probing * @method: defines which link cables you want to search for. * * Returns cables which have been detected. All cables should be closed before ! * The array is like a matrix which contains 5 columns (PORT_0 to PORT_4) and * 7 lines (CABLE_GRY to CABLE_USB). * The array must be freed by #ticables_probing_finish when no longer used. * * Return value: 0 if successful, ERR_NO_CABLE if no cables found. **/ TIEXPORT1 int TICALL ticables_probing_do(int ***result, int timeout, ProbingMethod method) { CablePort port; CableModel model; int **array; int found = 0; if (result == NULL) { ticables_critical("%s: result is NULL", __FUNCTION__); return ERR_PROBE_FAILED; } ticables_info(_("Link cable probing:")); array = (int **)calloc(CABLE_MAX + 1, sizeof(int *)); for(model = CABLE_NUL; model <= CABLE_MAX; model++) array[model] = (int *)calloc(5, sizeof(int)); // look for USB devices (faster) if(method & PROBE_USB) { int *list, n, i; ticables_get_usb_devices(&list, &n); for(i = 0; i < n; i++) { port = i+1; if(list[i] == PID_TIGLUSB) array[CABLE_SLV][port] = !0; if(list[i]) array[CABLE_USB][port] = !0; if(list[i]) found = !0; } } if((method & PROBE_FIRST) && found) { *result = array; return found ? 0 : ERR_NO_CABLE; } // look for DBUS devices (slower) if(method & PROBE_DBUS) { for(model = CABLE_GRY; model <= CABLE_PAR; model++) { for(port = PORT_1; port <= PORT_4; port++) { CableHandle* handle; int err, ret; handle = ticables_handle_new(model, port); if(handle) { ticables_options_set_timeout(handle, timeout); err = ticables_cable_probe(handle, &ret); array[model][port] = (ret && !err) ? 1: 0; if(array[model][port]) found = !0; if(found && (method & PROBE_FIRST)) { ticables_handle_del(handle); break; } } ticables_handle_del(handle); } } } *result = array; return found ? 0 : ERR_NO_CABLE; }