/**********************************************************/ /* TI-89 Transfer Program */ /* A TI-89 (and possibly a TI-92) file uploader for linux */ /* based heavily on TIcomm-1.0, but with the 8 char file */ /* bug fixed.... it can also do multiple files at a time. */ /* Make sure you have tidev-1.0.2 installed properly. */ /* compile this with 'gcc -o ti89 ti89.c' If you have any */ /* questions, feel free to e-mail me. */ /* Written by Kenneth Sanislo -- sanislo@wolfenet.com */ /**********************************************************/ /* Change this line to equal 0x89 for a TI-92, or 0x98 for a TI-89 */ #define TI_HEXID 0x98 #undef DEBUG #include #include #include #include #include #include #include #include #define COM_VAR 0x06 #define COM_WAIT 0x09 #define COM_DATA 0x15 #define COM_OK 0x56 #define COM_CHKERR 0x5a #define COM_TEST92 0x68 #define COM_SCRDUMP 0x6d #define COM_CONTINUE 0x78 #define COM_DIRECT 0x87 #define COM_EOT 0x92 #define COM_REQ 0xa2 #define COM_SEND 0xc9 #define mkpkt(a, y, z) { \ a.device = (TI_HEXID & 0x0f); \ a.command = y; \ a.length = z; \ } void *load_var (char *filename, int *len, char *varname, char *folder); static int calcfd; static char filetypes_92[] = "e---l-m---ctsda-i-pfx---h----b-g-z---------------r"; typedef struct _TI_Packet { unsigned char device; unsigned char command; unsigned short length; } TI_Packet; typedef struct _TI_Varhead92 { unsigned short length; unsigned char junk1; unsigned char junk2; unsigned char type; unsigned char namelen; } TI_Varhead92; typedef struct _TI_File92 { unsigned char magic[8]; unsigned char sep1[2]; unsigned char folder[8]; unsigned char ident[40]; unsigned char sep2[6]; unsigned char name[8]; unsigned char sep3[4]; unsigned char length[4]; unsigned char sep4[6]; } TI_File92; typedef struct _TI_Varjunk92 { unsigned char junk[4]; unsigned char size[2]; } TI_Varjunk92; #define do_size(x) (x[1] << 8 | x[0]) #define rev_size(x) (x[0] << 8 | x[1]) short calc_sum (void *data, int len) { unsigned char *bleh = (unsigned char *) data; int i; int ret = 0; for (i = 0; i < len; i++) ret += bleh[i]; ret &= 0xFFFF; return (unsigned short) ret; } void calc_xmit_pack (TI_Packet * pack) { if (ti_write (pack, sizeof (TI_Packet)) < sizeof (TI_Packet)) { printf ("Packet could not be transmitted, driver or device fault\n"); exit (1); } return; } void calc_recv_pack (TI_Packet * pack) { int c; if ((c = ti_read (pack, sizeof (TI_Packet))) < sizeof (TI_Packet)) { printf ("Incomplete packet recieved from calculator, terminating\n"); printf ("(%d bytes, expected %d)\n", c, sizeof (TI_Packet)); exit (1); } } int is_ti_ok (void) { TI_Packet pack; mkpkt (pack, COM_TEST92, 0); calc_xmit_pack (&pack); calc_recv_pack (&pack); printf ("Link Established\n"); } int ti_write (void *buf, size_t size) { int ret; #ifdef DEBUG int i = 0; unsigned char *bleh = (unsigned char *) buf; while (i < size) { printf ("%x ", bleh[i]); i++; } printf ("(of %d)\n", size); #endif return write (calcfd, buf, size); } int ti_read (void *buf, size_t size) { int r; int j = 0; #ifdef DEBUG unsigned char *bleh = (unsigned char *) buf; int i = 0; #endif while ((r = read (calcfd, buf, size)) == 0) { if (j > 10) return 0; j++; } #ifdef DEBUG while (i < r) { printf ("%x ", bleh[i]); i++; } printf ("(of %d)\n", size); #endif return r; } main (int argc, char **argv) { char varname[16], folder[16], filename[255], fullname[17]; int len = 0, i = 0, x = 2, datatype = 0; void *data; unsigned short chksum; TI_Packet packet; TI_Varhead92 head; TI_Varjunk92 junk; if (argc <= 1) { printf ("usage: %s ... \n", argv[0]); exit (-1); } init_comm (); while (x <= argc) { bzero (varname, sizeof (varname)); bzero (folder, sizeof (folder)); strncpy (filename, argv[x - 1], 255); data = load_var (filename, &len, varname, folder); for (i = 0; i < strlen (filetypes_92); i++) if (filetypes_92[i] == tolower (filename[strlen (filename) - 1])) datatype = i; head.namelen = sprintf (fullname, "%s\\%s", folder, varname); head.junk1 = 0; head.junk2 = 0; head.length = len + 2; head.type = datatype; #ifdef DEBUG printf ("File path and name: %s\n", fullname, strlen (fullname), datatype); #endif mkpkt (packet, COM_SEND, sizeof (TI_Varhead92) + head.namelen + 1); calc_xmit_pack (&packet); ti_write (&head, sizeof (TI_Varhead92)); ti_write (fullname, head.namelen + 1); chksum = calc_sum (&head, sizeof (TI_Varhead92)) + calc_sum (fullname, head.namelen); ti_write (&chksum, 2); calc_recv_pack (&packet); calc_recv_pack (&packet); mkpkt (packet, COM_OK, 0); calc_xmit_pack (&packet); mkpkt (packet, COM_DATA, len + sizeof (TI_Varjunk92)); calc_xmit_pack (&packet); memset (&junk, 0, sizeof (TI_Varjunk92)); junk.size[0] = (len & 0xff00) >> 8; junk.size[1] = len & 0x00ff; ti_write (&junk, sizeof (TI_Varjunk92)); ti_write (data, len); chksum = calc_sum (&junk, sizeof (TI_Varjunk92)) + calc_sum (data, len); ti_write (&chksum, 2); /* ti should say ok */ calc_recv_pack (&packet); mkpkt (packet, COM_EOT, 0); calc_xmit_pack (&packet); calc_recv_pack (&packet); free (data); printf ("%d of %d complete.\n", x - 1, argc - 1); x++; } printf ("done.\n"); } int init_comm () { TI_Packet packet; if ((calcfd = open ("/dev/ti", O_RDWR)) == -1) { perror ("open /dev/ti"); exit (1); } is_ti_ok (); } void * load_var (char *filename, int *len, char *varname, char *folder) { TI_File92 head; int fd; int type; unsigned short size; unsigned char rsize[2]; void *ret; if ((fd = open (filename, O_RDONLY)) == -1) { printf ("Unable to open %s\n", filename); return NULL; } type = filename[strlen (filename) - 1]; /* first is some header data */ read (fd, &head, sizeof (TI_File92)); /* now the actual size of the variable, byte reversed */ read (fd, rsize, 2); size = rev_size (rsize); /* extract foldername and varname */ strncpy (folder, head.folder, 8); strncpy (varname, head.name, 8); printf ("%s: %s\\%s is %d bytes in size.\n", filename, folder, varname, size); ret = malloc (size); read (fd, ret, size); /* all file types have superfluous data now, but, we really couldn't care less about it */ close (fd); (*len) = size; return ret; }