1 /* Hey EMACS -*- linux-c -*- */
2 
3 /*  libticalcs - Ti Calculator library, a part of the TiLP project
4  *  Copyright (C) 1999-2005  Romain Liévin
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software Foundation,
18  *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /*
22   This unit handles:
23   * TI-92 commands;
24   * TI-89/92+/V200/89T commands.
25 */
26 
27 #include <stdio.h>
28 #include <string.h>
29 
30 #include "ticalcs.h"
31 #include "internal.h"
32 #include "dbus_pkt.h"
33 #include "error.h"
34 #include "logging.h"
35 #include "cmd68k.h"
36 
37 #ifdef _MSC_VER
38 #pragma warning( disable : 4761 4244)
39 #endif
40 
ti68k_handle_to_dbus_mid(CalcHandle * handle)41 TIEXPORT3 uint8_t TICALL ti68k_handle_to_dbus_mid(CalcHandle * handle)
42 {
43 	if (ticalcs_validate_handle(handle))
44 	{
45 		switch (handle->model)
46 		{
47 		case CALC_TI89:
48 		case CALC_TI89T:
49 			return DBUS_MID_PC_TI89;
50 		case CALC_TI92:
51 			return DBUS_MID_PC_TI92;
52 		case CALC_TI92P:
53 			return DBUS_MID_PC_TI92p;
54 		case CALC_V200:
55 			return DBUS_MID_PC_V200;
56 		default:
57 			return DBUS_MID_PC_TIXX;
58 		}
59 	}
60 	return 0;
61 }
62 
ti68k_send_simple_cmd(CalcHandle * handle,uint8_t target,uint8_t cmd,const char * cmdname,uint16_t length,const uint8_t * data)63 static inline int ti68k_send_simple_cmd(CalcHandle * handle, uint8_t target, uint8_t cmd, const char * cmdname, uint16_t length, const uint8_t* data)
64 {
65 	VALIDATE_HANDLE(handle);
66 
67 	ticalcs_info(" PC->TI: %s", cmdname);
68 	return dbus_send(handle, target, cmd, length, data);
69 }
70 
71 static const uint8_t dbus_errors[] = { 0x03, 0x25, 0x1e, 0x21, 0x07, 0x24, 0x08 };
72 
err_code(uint8_t * data)73 static int err_code(uint8_t *data)
74 {
75 	int i;
76 	int code = data[2];
77 
78 	ticalcs_info(" TI->PC: SKP (%02x)", data[0]);
79 	for (i = 0; i < (int)(sizeof(dbus_errors) / sizeof(dbus_errors[0])); i++)
80 	{
81 		if(dbus_errors[i] == code)
82 		{
83 			return i+1;
84 		}
85 	}
86 
87 	ticalcs_warning("D-BUS error code not found in list. Please report it at <tilp-devel@lists.sf.net>.");
88 
89 	return 0;
90 }
91 
ti68k_send_VAR(CalcHandle * handle,uint32_t varsize,uint8_t vartype,const char * varname,uint8_t target)92 TIEXPORT3 int TICALL ti68k_send_VAR(CalcHandle* handle, uint32_t varsize, uint8_t vartype, const char *varname, uint8_t target)
93 {
94 	uint8_t buffer[32];
95 	char trans[127];
96 	uint8_t extra = (target == DBUS_MID_PC_TI92) ? 0 : ((vartype == TI89_BKUP) ? 0 : 1);
97 	uint16_t len;
98 
99 	VALIDATE_HANDLE(handle);
100 	VALIDATE_NONNULL(varname);
101 
102 	len = (uint16_t)strlen(varname);
103 	if (len > 17)
104 	{
105 		ticalcs_critical("Oversized variable name has length %i, clamping to 17", len);
106 		len = 17;
107 	}
108 
109 	ticonv_varname_to_utf8_sn(handle->model, varname, trans, sizeof(trans), vartype);
110 
111 	buffer[0] = LSB(LSW(varsize));
112 	buffer[1] = MSB(LSW(varsize));
113 	buffer[2] = LSB(MSW(varsize));
114 	buffer[3] = MSB(MSW(varsize));
115 	buffer[4] = vartype;
116 	buffer[5] = len;
117 	memcpy(buffer + 6, varname, len);
118 	buffer[6 + len] = 0x03;
119 
120 	ticalcs_info(" PC->TI: VAR (size=0x%08X=%i, id=%02X, name=%s)", varsize, varsize, vartype, trans);
121 	return dbus_send(handle, target, DBUS_CMD_VAR, 6 + len + extra, buffer);
122 }
123 
ti68k_send_CTS(CalcHandle * handle,uint8_t target)124 TIEXPORT3 int TICALL ti68k_send_CTS(CalcHandle* handle, uint8_t target)
125 {
126 	return ti68k_send_simple_cmd(handle, target, DBUS_CMD_CTS, "CTS", 2, NULL);
127 }
128 
ti68k_send_XDP(CalcHandle * handle,uint32_t length,const uint8_t * data,uint8_t target)129 TIEXPORT3 int TICALL ti68k_send_XDP(CalcHandle* handle, uint32_t length, const uint8_t * data, uint8_t target)
130 {
131 	VALIDATE_HANDLE(handle);
132 
133 	ticalcs_info(" PC->TI: XDP (0x%04X = %i bytes)", length, length);
134 	return dbus_send(handle, target, DBUS_CMD_XDP, length, data);
135 }
136 
ti89_send_SKP(CalcHandle * handle,uint8_t rej_code)137 TIEXPORT3 int TICALL ti89_send_SKP(CalcHandle* handle, uint8_t rej_code)
138 {
139 	uint8_t buffer[4] = { rej_code, 0, 0, 0 };
140 
141 	VALIDATE_HANDLE(handle);
142 
143 	ticalcs_info(" PC->TI: SKP (rejection code = %i)", rej_code);
144 	return dbus_send(handle, ti68k_handle_to_dbus_mid(handle), DBUS_CMD_SKP, 3, buffer);
145 }
146 
ti92_send_SKP(CalcHandle * handle,uint8_t rej_code)147 TIEXPORT3 int TICALL ti92_send_SKP(CalcHandle* handle, uint8_t rej_code)
148 {
149 	VALIDATE_HANDLE(handle);
150 
151 	ticalcs_info(" PC->TI: SKP (rejection code = %i)", rej_code);
152 	return dbus_send(handle, DBUS_MID_PC_TI92, DBUS_CMD_SKP, 1, &rej_code);
153 }
154 
ti68k_send_ACK(CalcHandle * handle,uint8_t target)155 TIEXPORT3 int TICALL ti68k_send_ACK(CalcHandle* handle, uint8_t target)
156 {
157 	return ti68k_send_simple_cmd(handle, target, DBUS_CMD_ACK, "ACK", 2, NULL);
158 }
159 
ti68k_send_ERR(CalcHandle * handle,uint8_t target)160 TIEXPORT3 int TICALL ti68k_send_ERR(CalcHandle* handle, uint8_t target)
161 {
162 	return ti68k_send_simple_cmd(handle, target, DBUS_CMD_ERR, "ERR", 2, NULL);
163 }
164 
ti68k_send_RDY(CalcHandle * handle,uint8_t target)165 TIEXPORT3 int TICALL ti68k_send_RDY(CalcHandle* handle, uint8_t target)
166 {
167 	return ti68k_send_simple_cmd(handle, target, DBUS_CMD_RDY, "RDY", 2, NULL);
168 }
169 
ti68k_send_SCR(CalcHandle * handle,uint8_t target)170 TIEXPORT3 int TICALL ti68k_send_SCR(CalcHandle* handle, uint8_t target)
171 {
172 	return ti68k_send_simple_cmd(handle, target, DBUS_CMD_SCR, "SCR", 2, NULL);
173 }
174 
ti68k_send_CNT(CalcHandle * handle,uint8_t target)175 TIEXPORT3 int TICALL ti68k_send_CNT(CalcHandle* handle, uint8_t target)
176 {
177 	return ti68k_send_simple_cmd(handle, target, DBUS_CMD_CNT, "CNT", 2, NULL);
178 }
179 
ti68k_send_KEY(CalcHandle * handle,uint16_t scancode,uint8_t target)180 TIEXPORT3 int TICALL ti68k_send_KEY(CalcHandle* handle, uint16_t scancode, uint8_t target)
181 {
182 	uint8_t buf[4] = { target, DBUS_CMD_KEY, LSB(scancode), MSB(scancode) };
183 
184 	VALIDATE_HANDLE(handle);
185 
186 	ticalcs_info(" PC->TI: KEY");
187 	return ticables_cable_send(handle->cable, buf, 4);
188 }
189 
ti68k_send_EOT(CalcHandle * handle,uint8_t target)190 TIEXPORT3 int TICALL ti68k_send_EOT(CalcHandle* handle, uint8_t target)
191 {
192 	return ti68k_send_simple_cmd(handle, target, DBUS_CMD_EOT, "EOT", 2, NULL);
193 }
194 
ti89_send_REQ(CalcHandle * handle,uint32_t varsize,uint8_t vartype,const char * varname)195 TIEXPORT3 int TICALL ti89_send_REQ(CalcHandle* handle, uint32_t varsize, uint8_t vartype, const char *varname)
196 {
197 	uint8_t buffer[32];
198 	uint16_t len;
199 
200 	VALIDATE_HANDLE(handle);
201 	VALIDATE_NONNULL(varname);
202 	len = (uint16_t)strlen(varname);
203 	if (len > 17)
204 	{
205 		ticalcs_critical("Oversized variable name has length %i, clamping to 17", len);
206 		len = 17;
207 	}
208 
209 	buffer[0] = LSB(LSW(varsize));
210 	buffer[1] = MSB(LSW(varsize));
211 	buffer[2] = LSB(MSW(varsize));
212 	buffer[3] = MSB(MSW(varsize));
213 	buffer[4] = vartype;
214 	buffer[5] = len;
215 	memcpy(buffer + 6, varname, len);
216 	buffer[6 + len] = 0x00;
217 
218 	len += 6 + 1;
219 	if (vartype != TI89_CLK) {
220 		len--;
221 	}
222 
223 	ticalcs_info(" PC->TI: REQ (size=0x%08X=%i, id=%02X, name=%s)", varsize, varsize, vartype, varname);
224 	return dbus_send(handle, ti68k_handle_to_dbus_mid(handle), DBUS_CMD_REQ, len, buffer);
225 }
226 
ti92_send_REQ(CalcHandle * handle,uint32_t varsize,uint8_t vartype,const char * varname)227 TIEXPORT3 int TICALL ti92_send_REQ(CalcHandle* handle, uint32_t varsize, uint8_t vartype, const char *varname)
228 {
229 	uint8_t buffer[32];
230 	uint16_t len;
231 
232 	VALIDATE_HANDLE(handle);
233 	VALIDATE_NONNULL(varname);
234 	len = (uint16_t)strlen(varname);
235 	if (len > 17)
236 	{
237 		ticalcs_critical("Oversized variable name has length %i, clamping to 17", len);
238 		len = 17;
239 	}
240 
241 	buffer[0] = 0;
242 	buffer[1] = 0;
243 	buffer[2] = 0;
244 	buffer[3] = 0;
245 	buffer[4] = vartype;
246 	buffer[5] = len;
247 	memcpy(buffer + 6, varname, len);
248 
249 	ticalcs_info(" PC->TI: REQ (size=0x%08X=%i, id=%02X, name=%s)", varsize, varsize, vartype, varname);
250 	return dbus_send(handle, DBUS_MID_PC_TI92, DBUS_CMD_REQ, 6 + len, buffer);
251 }
252 
ti89_send_RTS(CalcHandle * handle,uint32_t varsize,uint8_t vartype,const char * varname)253 TIEXPORT3 int TICALL ti89_send_RTS(CalcHandle* handle, uint32_t varsize, uint8_t vartype, const char *varname)
254 {
255 	uint8_t buffer[32];
256 	uint16_t len;
257 
258 	VALIDATE_HANDLE(handle);
259 	VALIDATE_NONNULL(varname);
260 	len = (uint16_t)strlen(varname);
261 	if (len > 17)
262 	{
263 		ticalcs_critical("Oversized variable name has length %i, clamping to 17", len);
264 		len = 17;
265 	}
266 
267 	buffer[0] = LSB(LSW(varsize));
268 	buffer[1] = MSB(LSW(varsize));
269 	buffer[2] = LSB(MSW(varsize));
270 	buffer[3] = MSB(MSW(varsize));
271 	buffer[4] = vartype;
272 	buffer[5] = len;
273 	memcpy(buffer + 6, varname, len);
274 	buffer[6 + len] = 0x00;
275 
276 	len += 6 + 1;
277 	// used by AMS <= 2.09 ?
278 	//if ((vartype == TI89_AMS) || (vartype == TI89_APPL)) len--;
279 
280 	ticalcs_info(" PC->TI: RTS (size=0x%08X=%i, id=%02X, name=%s)", varsize, varsize, vartype, varname);
281 	return dbus_send(handle, ti68k_handle_to_dbus_mid(handle), DBUS_CMD_RTS, len, buffer);
282 }
283 
ti92_send_RTS(CalcHandle * handle,uint32_t varsize,uint8_t vartype,const char * varname)284 TIEXPORT3 int TICALL ti92_send_RTS(CalcHandle* handle, uint32_t varsize, uint8_t vartype, const char *varname)
285 {
286 	uint8_t buffer[32];
287 	uint16_t len;
288 
289 	VALIDATE_HANDLE(handle);
290 	VALIDATE_NONNULL(varname);
291 	len = (uint16_t)strlen(varname);
292 	if (len > 17)
293 	{
294 		ticalcs_critical("Oversized variable name has length %i, clamping to 17", len);
295 		len = 17;
296 	}
297 
298 	buffer[0] = LSB(LSW(varsize));
299 	buffer[1] = MSB(LSW(varsize));
300 	buffer[2] = LSB(MSW(varsize));
301 	buffer[3] = MSB(MSW(varsize));
302 	buffer[4] = vartype;
303 	buffer[5] = len;
304 	memcpy(buffer + 6, varname, len);
305 
306 	ticalcs_info(" PC->TI: RTS (size=0x%08X=%i, id=%02X, name=%s)", varsize, varsize, vartype, varname);
307 	return dbus_send(handle, DBUS_MID_PC_TI92, DBUS_CMD_RTS, 6 + len, buffer);
308 }
309 
ti89_send_RTS2(CalcHandle * handle,uint32_t varsize,uint8_t vartype,uint8_t hw_id)310 TIEXPORT3 int TICALL ti89_send_RTS2(CalcHandle* handle, uint32_t varsize, uint8_t vartype, uint8_t hw_id)
311 {
312 	uint8_t buffer[9];
313 
314 	VALIDATE_HANDLE(handle);
315 
316 	buffer[0] = LSB(LSW(varsize));
317 	buffer[1] = MSB(LSW(varsize));
318 	buffer[2] = LSB(MSW(varsize));
319 	buffer[3] = MSB(MSW(varsize));
320 	buffer[4] = vartype;
321 	buffer[5] = 0x00;
322 	buffer[6] = 0x08;
323 	buffer[7] = 0x00;
324 	buffer[8] = hw_id;	// 0x08 -> V200, 0x09 -> Titanium (Hardware ID)
325 
326 	ticalcs_info(" PC->TI: RTS (size=0x%08X=%i, id=%02X, hw_id=%02x)", varsize, varsize, vartype, hw_id);
327 	return dbus_send(handle, ti68k_handle_to_dbus_mid(handle), DBUS_CMD_RTS, 9, buffer);
328 }
329 
ti89_send_VER(CalcHandle * handle)330 TIEXPORT3 int TICALL ti89_send_VER(CalcHandle* handle)
331 {
332 	return ti68k_send_simple_cmd(handle, ti68k_handle_to_dbus_mid(handle), DBUS_CMD_VER, "VER", 2, NULL);
333 }
334 
ti89_send_DEL(CalcHandle * handle,uint32_t varsize,uint8_t vartype,const char * varname)335 TIEXPORT3 int TICALL ti89_send_DEL(CalcHandle* handle, uint32_t varsize, uint8_t vartype, const char *varname)
336 {
337 	uint8_t buffer[32];
338 	uint16_t len;
339 
340 	VALIDATE_HANDLE(handle);
341 	VALIDATE_NONNULL(varname);
342 	len = (uint16_t)strlen(varname);
343 	if (len > 17)
344 	{
345 		ticalcs_critical("Oversized variable name has length %i, clamping to 17", len);
346 		len = 17;
347 	}
348 
349 	buffer[0] = 0;
350 	buffer[1] = 0;
351 	buffer[2] = 0;
352 	buffer[3] = 0;
353 	buffer[4] = 0;
354 	buffer[5] = len;
355 	memcpy(buffer + 6, varname, len);
356 
357 	ticalcs_info(" PC->TI: DEL (size=0x%08X=%i, id=%02X, name=%s)", varsize, varsize, vartype, varname);
358 	return dbus_send(handle, ti68k_handle_to_dbus_mid(handle), DBUS_CMD_DEL, 6 + len, buffer);
359 }
360 
ti89_recv_VAR(CalcHandle * handle,uint32_t * varsize,uint8_t * vartype,char * varname)361 TIEXPORT3 int TICALL ti89_recv_VAR(CalcHandle* handle, uint32_t * varsize, uint8_t * vartype, char *varname)
362 {
363 	uint8_t host, cmd;
364 	uint8_t *buffer;
365 	uint16_t length;
366 	uint8_t strl;
367 	uint8_t flag;
368 	char * varname_nofldname;
369 	int ret;
370 
371 	VALIDATE_HANDLE(handle);
372 	VALIDATE_NONNULL(varsize);
373 	VALIDATE_NONNULL(vartype);
374 	VALIDATE_NONNULL(varname);
375 
376 	buffer = (uint8_t *)handle->buffer;
377 	ret = dbus_recv(handle, &host, &cmd, &length, buffer);
378 	if (ret)
379 	{
380 		return ret;
381 	}
382 
383 	if (cmd == DBUS_CMD_EOT)
384 	{
385 		ticalcs_info(" TI->PC: EOT");
386 		return ERR_EOT;		// not really an error
387 	}
388 	if (cmd == DBUS_CMD_SKP)
389 	{
390 		return ERR_CALC_ERROR1 + err_code(buffer);
391 	}
392 	if (cmd != DBUS_CMD_VAR)
393 	{
394 		return ERR_INVALID_CMD;
395 	}
396 
397 	*varsize = buffer[0] | (((uint32_t)buffer[1]) << 8) | (((uint32_t)buffer[2]) << 16) | (((uint32_t)buffer[3]) << 24);
398 	*vartype = buffer[4];
399 	strl = buffer[5];
400 	memcpy(varname, buffer + 6, strl);
401 	varname[strl] = '\0';
402 	flag = buffer[6 + strl];
403 
404 	if ((length != (6 + strlen(varname))) && (length != (7 + strlen(varname))))
405 	{
406 		return ERR_INVALID_PACKET;
407 	}
408 
409 	ticalcs_info(" TI->PC: VAR (size=0x%08X=%i, id=%02X, name=%s, flag=%i)", *varsize, *varsize, *vartype, varname, flag);
410 	varname_nofldname = tifiles_get_varname(varname);
411 	if (varname_nofldname != varname)
412 	{
413 		// This variable name contains a folder name. Erase it.
414 		ticalcs_info(" TI->PC: VAR: the variable name contains a folder name, stripping it.");
415 		memmove(varname, varname_nofldname, strlen(varname_nofldname)+1);
416 	}
417 
418 	return 0;
419 }
420 
ti92_recv_VAR(CalcHandle * handle,uint32_t * varsize,uint8_t * vartype,char * varname)421 TIEXPORT3 int TICALL ti92_recv_VAR(CalcHandle* handle, uint32_t * varsize, uint8_t * vartype, char *varname)
422 {
423 	uint8_t host, cmd;
424 	uint8_t *buffer;
425 	uint16_t length;
426 	uint8_t strl;
427 	int ret;
428 
429 	VALIDATE_HANDLE(handle);
430 	VALIDATE_NONNULL(varsize);
431 	VALIDATE_NONNULL(vartype);
432 	VALIDATE_NONNULL(varname);
433 
434 	buffer = (uint8_t *)handle->buffer;
435 	ret = dbus_recv(handle, &host, &cmd, &length, buffer);
436 	if (ret)
437 	{
438 		return ret;
439 	}
440 
441 	if (cmd == DBUS_CMD_EOT)
442 	{
443 		ticalcs_info(" TI->PC: EOT");
444 		return ERR_EOT;		// not really an error
445 	}
446 	if (cmd == DBUS_CMD_SKP)
447 	{
448 		return ERR_VAR_REJECTED;
449 	}
450 	if (cmd != DBUS_CMD_VAR)
451 	{
452 		return ERR_INVALID_CMD;
453 	}
454 
455 	*varsize = buffer[0] | (((uint32_t)buffer[1]) << 8) | (((uint32_t)buffer[2]) << 16) | (((uint32_t)buffer[3]) << 24);
456 	*vartype = buffer[4];
457 	strl = buffer[5];
458 	memcpy(varname, buffer + 6, strl);
459 	varname[strl] = '\0';
460 
461 	if (length != (6 + strlen(varname)))
462 	{
463 		return ERR_INVALID_PACKET;
464 	}
465 
466 	ticalcs_info(" TI->PC: VAR (size=0x%08X=%i, id=%02X, name=%s)", *varsize, *varsize, *vartype, varname);
467 
468 	return 0;
469 }
470 
ti68k_recv_CTS(CalcHandle * handle,uint8_t is_92)471 static int ti68k_recv_CTS(CalcHandle* handle, uint8_t is_92)
472 {
473 	uint8_t host, cmd;
474 	uint16_t length;
475 	uint8_t *buffer;
476 	int ret;
477 
478 	VALIDATE_HANDLE(handle);
479 
480 	buffer = (uint8_t *)handle->buffer;
481 	ret = dbus_recv(handle, &host, &cmd, &length, buffer);
482 	if (ret)
483 	{
484 		return ret;
485 	}
486 
487 	if (cmd == DBUS_CMD_SKP)
488 	{
489 		return is_92 ? ERR_VAR_REJECTED : ERR_CALC_ERROR1 + err_code(buffer);
490 	}
491 	else if (cmd != DBUS_CMD_CTS)
492 	{
493 		return ERR_INVALID_CMD;
494 	}
495 	if (length != 0x0000)
496 	{
497 		return ERR_CTS_ERROR;
498 	}
499 
500 	ticalcs_info(" TI->PC: CTS");
501 
502 	return 0;
503 }
504 
ti89_recv_CTS(CalcHandle * handle)505 TIEXPORT3 int TICALL ti89_recv_CTS(CalcHandle* handle)
506 {
507 	return ti68k_recv_CTS(handle, 0);
508 }
509 
ti92_recv_CTS(CalcHandle * handle)510 TIEXPORT3 int TICALL ti92_recv_CTS(CalcHandle* handle)
511 {
512 	return ti68k_recv_CTS(handle, 1);
513 }
514 
ti68k_recv_SKP(CalcHandle * handle,uint8_t * rej_code)515 TIEXPORT3 int TICALL ti68k_recv_SKP(CalcHandle* handle, uint8_t * rej_code)
516 {
517 	uint8_t host, cmd;
518 	uint16_t length;
519 	uint8_t *buffer;
520 	int retval;
521 
522 	VALIDATE_HANDLE(handle);
523 	VALIDATE_NONNULL(rej_code);
524 
525 	buffer = (uint8_t *)handle->buffer;
526 	*rej_code = 0;
527 
528 	retval = dbus_recv(handle, &host, &cmd, &length, buffer);
529 	if (retval == 0)
530 	{
531 		if (cmd == DBUS_CMD_CTS)
532 		{
533 			ticalcs_info("CTS");
534 		}
535 		else
536 		{
537 			if (cmd != DBUS_CMD_SKP)
538 			{
539 				retval = ERR_INVALID_CMD;
540 			}
541 			else
542 			{
543 				ticalcs_info(" TI->PC: SKP (rejection code = %i)", buffer[0]);
544 				if (rej_code != NULL)
545 				{
546 					*rej_code = buffer[0];
547 				}
548 			}
549 		}
550 	}
551 
552 	return retval;
553 }
554 
ti68k_recv_XDP(CalcHandle * handle,uint16_t * length,uint8_t * data)555 TIEXPORT3 int TICALL ti68k_recv_XDP(CalcHandle* handle, uint16_t * length, uint8_t * data)
556 {
557 	uint8_t host, cmd;
558 	int err;
559 	uint16_t len;
560 
561 	VALIDATE_HANDLE(handle);
562 	VALIDATE_NONNULL(length);
563 
564 	err = dbus_recv(handle, &host, &cmd, &len, data);
565 	*length = len;
566 
567 	if (cmd != DBUS_CMD_XDP)
568 	{
569 		return ERR_INVALID_CMD;
570 	}
571 
572 	if (!err)
573 	{
574 		ticalcs_info(" TI->PC: XDP (%04X=%i bytes)", *length, *length);
575 	}
576 
577 	return err;
578 }
579 
580 /* ACK: receive acknowledge
581   - status [in/out]: if NULL is passed, the function checks that 00 00 has
582   been received. Otherwise, it put in status the received value.
583   - int [out]: an error code
584 */
ti68k_recv_ACK(CalcHandle * handle,uint16_t * status,uint8_t is_92)585 static int ti68k_recv_ACK(CalcHandle* handle, uint16_t * status, uint8_t is_92)
586 {
587 	uint8_t host, cmd;
588 	uint16_t length;
589 	uint8_t *buffer;
590 	int ret;
591 
592 	VALIDATE_HANDLE(handle);
593 
594 	buffer = (uint8_t *)handle->buffer;
595 	ret = dbus_recv(handle, &host, &cmd, &length, buffer);
596 	if (ret)
597 	{
598 		return ret;
599 	}
600 
601 	if (!is_92 && cmd == DBUS_CMD_SKP)
602 	{
603 		return ERR_CALC_ERROR1 + err_code(buffer);
604 	}
605 
606 	if (status != NULL)
607 	{
608 		*status = length;
609 	}
610 	else if (length != 0x0000)
611 	{
612 		return ERR_NACK;
613 	}
614 
615 	if (cmd != DBUS_CMD_ACK)
616 	{
617 		return ERR_INVALID_CMD;
618 	}
619 
620 	ticalcs_info(" TI->PC: ACK");
621 
622 	return 0;
623 }
624 
ti89_recv_ACK(CalcHandle * handle,uint16_t * status)625 TIEXPORT3 int TICALL ti89_recv_ACK(CalcHandle* handle, uint16_t * status)
626 {
627 	return ti68k_recv_ACK(handle, status, 0);
628 }
629 
ti92_recv_ACK(CalcHandle * handle,uint16_t * status)630 TIEXPORT3 int TICALL ti92_recv_ACK(CalcHandle* handle, uint16_t * status)
631 {
632 	return ti68k_recv_ACK(handle, status, 1);
633 }
634 
ti68k_recv_CNT(CalcHandle * handle)635 TIEXPORT3 int TICALL ti68k_recv_CNT(CalcHandle* handle)
636 {
637 	uint8_t host, cmd;
638 	uint16_t sts;
639 	int ret;
640 
641 	VALIDATE_HANDLE(handle);
642 
643 	ret = dbus_recv(handle, &host, &cmd, &sts, NULL);
644 	if (ret)
645 	{
646 		return ret;
647 	}
648 
649 	if (cmd == DBUS_CMD_EOT)
650 	{
651 		return ERR_EOT;		// not really an error
652 	}
653 
654 	if (cmd != DBUS_CMD_CNT)
655 	{
656 		return ERR_INVALID_CMD;
657 	}
658 
659 	ticalcs_info(" TI->PC: CNT");
660 
661 	return 0;
662 }
663 
ti68k_recv_EOT(CalcHandle * handle)664 TIEXPORT3 int TICALL ti68k_recv_EOT(CalcHandle* handle)
665 {
666 	uint8_t host, cmd;
667 	uint16_t length;
668 	int ret;
669 
670 	VALIDATE_HANDLE(handle);
671 
672 	ret = dbus_recv(handle, &host, &cmd, &length, NULL);
673 	if (ret)
674 	{
675 		return ret;
676 	}
677 
678 	if (cmd != DBUS_CMD_EOT)
679 	{
680 		return ERR_INVALID_CMD;
681 	}
682 
683 	ticalcs_info(" TI->PC: EOT");
684 
685 	return 0;
686 }
687 
ti68k_recv_RTS(CalcHandle * handle,uint32_t * varsize,uint8_t * vartype,char * varname,uint8_t is_92)688 static int ti68k_recv_RTS(CalcHandle* handle, uint32_t * varsize, uint8_t * vartype, char *varname, uint8_t is_92)
689 {
690 	uint8_t host, cmd;
691 	uint8_t *buffer;
692 	uint16_t length;
693 	uint8_t strl;
694 	int ret;
695 
696 	VALIDATE_HANDLE(handle);
697 	VALIDATE_NONNULL(varsize);
698 	VALIDATE_NONNULL(vartype);
699 	VALIDATE_NONNULL(varname);
700 
701 	buffer = (uint8_t *)handle->buffer;
702 	ret = dbus_recv(handle, &host, &cmd, &length, buffer);
703 	if (ret)
704 	{
705 		return ret;
706 	}
707 
708 	if (cmd == DBUS_CMD_EOT)
709 	{
710 		return ERR_EOT;		// not really an error
711 	}
712 	else if (cmd == DBUS_CMD_SKP)
713 	{
714 		return is_92 ? ERR_VAR_REJECTED : ERR_CALC_ERROR1 + err_code(buffer);
715 	}
716 	else if (cmd != DBUS_CMD_VAR)
717 	{
718 		return ERR_INVALID_CMD;
719 	}
720 
721 	*varsize = buffer[0] | (((uint32_t)buffer[1]) << 8) | (((uint32_t)buffer[2]) << 16) | (((uint32_t)buffer[3]) << 24);
722 	*vartype = buffer[4];
723 	strl = buffer[5];
724 	memcpy(varname, buffer + 6, strl);
725 	varname[strl] = '\0';
726 
727 	if (length != (6 + strlen(varname)))
728 	{
729 		return ERR_INVALID_PACKET;
730 	}
731 
732 	ticalcs_info(" TI->PC: RTS (size=0x%08X=%i, id=%02X, name=%s)", *varsize, *varsize, *vartype, varname);
733 
734 	return 0;
735 }
736 
ti89_recv_RTS(CalcHandle * handle,uint32_t * varsize,uint8_t * vartype,char * varname)737 TIEXPORT3 int TICALL ti89_recv_RTS(CalcHandle* handle, uint32_t * varsize, uint8_t * vartype, char *varname)
738 {
739 	return ti68k_recv_RTS(handle, varsize, vartype, varname, 0);
740 }
741 
ti92_recv_RTS(CalcHandle * handle,uint32_t * varsize,uint8_t * vartype,char * varname)742 TIEXPORT3 int TICALL ti92_recv_RTS(CalcHandle* handle, uint32_t * varsize, uint8_t * vartype, char *varname)
743 {
744 	return ti68k_recv_RTS(handle, varsize, vartype, varname, 1);
745 }
746