1 /* Hey EMACS -*- linux-c -*- */
2 /* $Id$ */
3
4 /* libticalcs2 - hand-helds support library, a part of the TiLP project
5 * Copyright (C) 1999-2005 Romain Liévin
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #ifdef HAVE_CONFIG_H
23 # include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <errno.h>
30 #if defined(__WIN32__)
31 #include <windows.h>
32 #endif
33 #include <locale.h>
34
35 #include "gettext.h"
36 #include "ticalcs.h"
37 #include "internal.h"
38 #include "logging.h"
39 #include "error.h"
40 #include "calc_xx.h"
41
42 /*****************/
43 /* Internal data */
44 /*****************/
45
46 extern const CalcUpdate default_update;
47
48 static CalcFncts const *const calcs[] =
49 {
50 &calc_00,
51 #ifndef NO_TI73
52 &calc_73,
53 #endif
54 #ifndef NO_TI82
55 &calc_82,
56 #endif
57 #ifndef NO_TI83
58 &calc_83,
59 #endif
60 #ifndef NO_TI83P
61 &calc_83p,
62 #endif
63 #ifndef NO_TI84P
64 &calc_84p,
65 #endif
66 #ifndef NO_TI85
67 &calc_85,
68 #endif
69 #ifndef NO_TI86
70 &calc_86,
71 #endif
72 #ifndef NO_TI89
73 &calc_89,
74 #endif
75 #ifndef NO_TI89T
76 &calc_89t,
77 #endif
78 #ifndef NO_TI92
79 &calc_92,
80 #endif
81 #ifndef NO_TI92P
82 &calc_92p,
83 #endif
84 #ifndef NO_V200
85 &calc_v2,
86 #endif
87 #ifndef NO_TI84P_USB
88 &calc_84p_usb,
89 #endif
90 #ifndef NO_TI89T_USB
91 &calc_89t_usb,
92 #endif
93 #ifndef NO_NSPIRE
94 &calc_nsp,
95 #endif
96 #ifndef NO_TI80
97 &calc_80,
98 #endif
99 #ifndef NO_TI84PC
100 &calc_84pcse,
101 #endif
102 #ifndef NO_TI84PC_USB
103 &calc_84pcse_usb,
104 #endif
105 #ifndef NO_TI83PCE_USB
106 &calc_83pce_usb,
107 #endif
108 #ifndef NO_TI84PCE_USB
109 &calc_84pce_usb,
110 #endif
111 #ifndef NO_TI82A_USB
112 &calc_82a_usb,
113 #endif
114 #ifndef NO_TI84PT_USB
115 &calc_84pt_usb,
116 #endif
117 NULL
118 };
119
120 static const uint32_t supported_calcs =
121 (1U << CALC_NONE)
122 #ifndef NO_TI73
123 | (1U << CALC_TI73)
124 #endif
125 #ifndef NO_TI82
126 | (1U << CALC_TI82)
127 #endif
128 #ifndef NO_TI83
129 | (1U << CALC_TI83)
130 #endif
131 #ifndef NO_TI83P
132 | (1U << CALC_TI83P)
133 #endif
134 #ifndef NO_TI84P
135 | (1U << CALC_TI84P)
136 #endif
137 #ifndef NO_TI85
138 | (1U << CALC_TI85)
139 #endif
140 #ifndef NO_TI86
141 | (1U << CALC_TI86)
142 #endif
143 #ifndef NO_TI89
144 | (1U << CALC_TI89)
145 #endif
146 #ifndef NO_TI89T
147 | (1U << CALC_TI89T)
148 #endif
149 #ifndef NO_TI92
150 | (1U << CALC_TI92)
151 #endif
152 #ifndef NO_TI92P
153 | (1U << CALC_TI92P)
154 #endif
155 #ifndef NO_V200
156 | (1U << CALC_V200)
157 #endif
158 #ifndef NO_TI84P_USB
159 | (1U << CALC_TI84P_USB)
160 #endif
161 #ifndef NO_TI89T_USB
162 | (1U << CALC_TI89T_USB)
163 #endif
164 #ifndef NO_NSPIRE
165 | (1U << CALC_NSPIRE)
166 #endif
167 #ifndef NO_TI80
168 | (1U << CALC_TI80)
169 #endif
170 #ifndef NO_TI84PC
171 | (1U << CALC_TI84PC)
172 #endif
173 #ifndef NO_TI84PC_USB
174 | (1U << CALC_TI84PC_USB)
175 #endif
176 #ifndef NO_TI83PCE_USB
177 | (1U << CALC_TI83PCE_USB)
178 #endif
179 #ifndef NO_TI84PCE_USB
180 | (1U << CALC_TI84PCE_USB)
181 #endif
182 #ifndef NO_TI82A_USB
183 | (1U << CALC_TI82A_USB)
184 #endif
185 #ifndef NO_TI84PT_USB
186 | (1U << CALC_TI84PT_USB)
187 #endif
188 ;
189
190 /****************/
191 /* Entry points */
192 /****************/
193
194 // not static, must be shared between instances
195 int ticalcs_instance = 0; // counts # of instances
196
197 /**
198 * ticalcs_library_init:
199 *
200 * This function must be the first one to call. It inits library internals.
201 *
202 * Return value: the instance count.
203 **/
ticalcs_library_init(void)204 TIEXPORT3 int TICALL ticalcs_library_init(void)
205 {
206 char locale_dir[65536 + 20];
207
208 #ifdef __WIN32__
209 HANDLE hDll;
210 int i;
211
212 hDll = GetModuleHandle("libticalcs2-12.dll");
213 GetModuleFileName(hDll, locale_dir, sizeof(locale_dir) - 21);
214
215 for (i = strlen(locale_dir); i >= 0; i--)
216 {
217 if (locale_dir[i] == '\\')
218 {
219 break;
220 }
221 }
222 locale_dir[i] = '\0';
223
224 #ifdef __MINGW32__
225 strcat(locale_dir, "\\..\\share\\locale");
226 #else
227 strcat(locale_dir, "\\locale");
228 #endif
229 #else
230 strncpy(locale_dir, LOCALEDIR, sizeof(locale_dir) - 21);
231 locale_dir[sizeof(locale_dir) - 21] = 0;
232 #endif
233
234 if (ticalcs_instance)
235 {
236 return (++ticalcs_instance);
237 }
238 ticalcs_info(_("ticalcs library version %s"), LIBCALCS_VERSION);
239 errno = 0;
240
241 #if defined(ENABLE_NLS)
242 ticalcs_info("setlocale: %s", setlocale(LC_ALL, ""));
243 ticalcs_info("bindtextdomain: %s", bindtextdomain(PACKAGE, locale_dir));
244 bind_textdomain_codeset(PACKAGE, "UTF-8"/*"ISO-8859-15"*/);
245 ticalcs_info("textdomain: %s", textdomain(NULL));
246 #endif
247
248 return (++ticalcs_instance);
249 }
250
251
252 /**
253 * ticalcs_library_exit:
254 *
255 * This function must be the last one to call. Used to release internal resources.
256 *
257 * Return value: the instance count.
258 **/
ticalcs_library_exit(void)259 TIEXPORT3 int TICALL ticalcs_library_exit(void)
260 {
261 return (--ticalcs_instance);
262 }
263
264 /***********/
265 /* Methods */
266 /***********/
267
268 /**
269 * ticalcs_version_get:
270 *
271 * This function returns the library version like "X.Y.Z".
272 *
273 * Return value: a string.
274 **/
ticalcs_version_get(void)275 TIEXPORT3 const char *TICALL ticalcs_version_get(void)
276 {
277 return LIBCALCS_VERSION;
278 }
279
280 /**
281 * ticalcs_supported_calcs:
282 *
283 * This function returns the calcs built into the current binary.
284 *
285 * Return value: an integer containing a binary OR of (1 << CALC_*) values,
286 * where CALC_* values are defined in enum CalcModel.
287 **/
ticalcs_supported_calcs(void)288 TIEXPORT3 uint32_t TICALL ticalcs_supported_calcs (void)
289 {
290 return supported_calcs;
291 }
292
293 /**
294 * ticalcs_handle_new:
295 * @model: a hand-held model
296 *
297 * Create a new handle associated with the given cable on the given port.
298 * Must be freed with ticables_handle_del when no longer needed.
299 * Note: the handle is a pointer on an opaque structure and should not be modified.
300 *
301 * Return value: NULL if error, an handle otherwise.
302 **/
ticalcs_handle_new(CalcModel model)303 TIEXPORT3 CalcHandle* TICALL ticalcs_handle_new(CalcModel model)
304 {
305 CalcHandle *handle = NULL;
306 CalcFncts * calc = NULL;
307 unsigned int i;
308
309 for (i = 0; i < sizeof(calcs) / sizeof(calcs[0]) - 1; i++) // - 1 for the terminating NULL.
310 {
311 if (calcs[i]->model == (int const)model)
312 {
313 calc = (CalcFncts *)calcs[i];
314 break;
315 }
316 }
317
318 if (calc != NULL)
319 {
320 handle = (CalcHandle *)g_malloc0(sizeof(CalcHandle));
321 if (handle != NULL)
322 {
323 handle->model = model;
324 handle->calc = calc;
325 handle->updat = (CalcUpdate *)&default_update;
326
327 handle->priv.nsp_src_port = 0x8001;
328 handle->priv.nsp_dst_port = 0x4003; // NSP_PORT_ADDR_REQUEST
329
330 handle->buffer = (uint8_t *)g_malloc(65536 + 6);
331 if (handle->buffer == NULL)
332 {
333 g_free(handle);
334 handle = NULL;
335 }
336 handle->buffer2 = (uint8_t *)g_malloc(65536 + 6);
337 if (handle->buffer2 == NULL)
338 {
339 g_free(handle->buffer);
340 g_free(handle);
341 handle = NULL;
342 }
343 }
344 }
345
346 return handle;
347 }
348
349 /**
350 * ticalcs_handle_del:
351 * @handle: the handle
352 *
353 * Release the cable and free the associated resources.
354 * If cable has not been detached with #ticalcs_cable_detach,
355 * it will be detached.
356 *
357 * Return value: always 0.
358 **/
ticalcs_handle_del(CalcHandle * handle)359 TIEXPORT3 int TICALL ticalcs_handle_del(CalcHandle* handle)
360 {
361 VALIDATE_HANDLE(handle);
362
363 if (handle->attached)
364 {
365 ticalcs_cable_detach(handle);
366 }
367
368 if (handle->buffer2)
369 {
370 g_free(handle->buffer2);
371 }
372
373 if (handle->buffer)
374 {
375 g_free(handle->buffer);
376 }
377
378 memset((void *)handle, 0, sizeof(*handle));
379 g_free(handle);
380
381 return 0;
382 }
383
384 /**
385 * ticalcs_handle_show:
386 * @handle: the handle
387 *
388 * Show information stored in the handle.
389 *
390 * Return value: always 0.
391 **/
ticalcs_handle_show(CalcHandle * handle)392 TIEXPORT3 int TICALL ticalcs_handle_show(CalcHandle* handle)
393 {
394 VALIDATE_HANDLE(handle);
395
396 ticalcs_info(_("Link calc handle details:"));
397 ticalcs_info(_(" model : %s"), ticalcs_model_to_string(handle->model));
398
399 return 0;
400 }
401
402 /**
403 * ticalcs_cable_attach:
404 * @handle: the handle
405 * @cable: a cable to use
406 *
407 * Attach and open the given cable for use with the hand-held.
408 *
409 * Return value: 0 if successful, an error code otherwise.
410 **/
ticalcs_cable_attach(CalcHandle * handle,CableHandle * cable)411 TIEXPORT3 int TICALL ticalcs_cable_attach(CalcHandle* handle, CableHandle* cable)
412 {
413 int ret;
414
415 VALIDATE_HANDLE(handle);
416
417 handle->cable = cable;
418 handle->attached = !0;
419
420 ret = ticables_cable_open(cable);
421 if (!ret)
422 {
423 handle->open = !0;
424 }
425
426 return ret;
427 }
428
429 /**
430 * ticalcs_cable_detach:
431 * @handle: the handle
432 * @cable: a cable to use
433 *
434 * Close and detach the cable associated with the hand-held.
435 *
436 * Return value: 0 if successful, an error code otherwise.
437 **/
ticalcs_cable_detach(CalcHandle * handle)438 TIEXPORT3 int TICALL ticalcs_cable_detach(CalcHandle* handle)
439 {
440 int ret;
441
442 VALIDATE_HANDLE(handle);
443
444 ret = ticables_cable_close(handle->cable);
445 if (!ret)
446 {
447 handle->open = 0;
448
449 handle->attached = 0;
450 handle->cable = NULL;
451 }
452
453 return ret;
454 }
455
456 /**
457 * ticalcs_update_set:
458 * @handle: the handle
459 * @update: the callbacks to use
460 *
461 * Set the callbacks to use for the given handle.
462 *
463 * Return value: 0 if successful, an error code otherwise.
464 **/
ticalcs_update_set(CalcHandle * handle,CalcUpdate * upd)465 TIEXPORT3 int TICALL ticalcs_update_set(CalcHandle* handle, CalcUpdate* upd)
466 {
467 VALIDATE_HANDLE(handle);
468
469 handle->updat = upd;
470 return 0;
471
472 }
473
474 /**
475 * ticalcs_model_supports_dbus:
476 * @model: a calculator model taken in #CalcModel.
477 *
478 * Returns whether the given calculator model supports the protocol dubbed DBUS by libticalcs.
479 * That is, the standard protocol used by TI-Z80 and TI-68k calculators over the legacy I/O.
480 *
481 * Return value: nonzero if the calculator supports the DBUS protocol, zero if it doesn't.
482 */
ticalcs_model_supports_dbus(CalcModel model)483 TIEXPORT3 int TICALL ticalcs_model_supports_dbus(CalcModel model)
484 {
485 return ( /*model < CALC_MAX
486 &&*/ ( model == CALC_TI73
487 || model == CALC_TI82
488 || model == CALC_TI83
489 || model == CALC_TI83P
490 || model == CALC_TI84P
491 || model == CALC_TI85
492 || model == CALC_TI86
493 || model == CALC_TI89
494 || model == CALC_TI89T
495 || model == CALC_TI92
496 || model == CALC_TI92P
497 || model == CALC_V200
498 || model == CALC_TI80
499 || model == CALC_TI84PC));
500 }
501
502 /**
503 * ticalcs_model_supports_dusb:
504 * @model: a calculator model taken in #CalcModel.
505 *
506 * Returns whether the given calculator model supports the protocol dubbed DUSB by libticalcs.
507 * That is, the standard protocol used by TI-Z80, TI-eZ80 and TI-68k calculators over the USB port.
508 *
509 * Return value: nonzero if the calculator supports the DUSB protocol, zero if it doesn't.
510 */
ticalcs_model_supports_dusb(CalcModel model)511 TIEXPORT3 int TICALL ticalcs_model_supports_dusb(CalcModel model)
512 {
513 return ( /*model < CALC_MAX
514 &&*/ ( model == CALC_TI84P_USB
515 || model == CALC_TI89T_USB
516 || model == CALC_TI84PC_USB
517 || model == CALC_TI83PCE_USB
518 || model == CALC_TI84PCE_USB
519 || model == CALC_TI82A_USB
520 || model == CALC_TI84PT_USB));
521 }
522
523 /**
524 * ticalcs_model_supports_nsp:
525 * @model: a calculator model taken in #CalcModel.
526 *
527 * Returns whether the given calculator model supports the protocol dubbed NSP by libticalcs.
528 * That is, the standard protocol used by TI-Nspire calculators over the USB port.
529 *
530 * Return value: nonzero if the calculator supports the NSP protocol, zero if it doesn't.
531 */
ticalcs_model_supports_nsp(CalcModel model)532 TIEXPORT3 int TICALL ticalcs_model_supports_nsp(CalcModel model)
533 {
534 return ( /*model < CALC_MAX
535 &&*/ ( model == CALC_NSPIRE));
536 }
537