1
/* Hey EMACS -*- linux-c -*- */
2
/* $Id: cmd84p.c 2077 2006-03-31 21:16:19Z roms $ */
4
/* libticalcs - Ti Calculator library, a part of the TiLP project
5
* Copyright (C) 1999-2005 Romain Li�vin
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.
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.
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
19
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
This unit handles virtual packet types (commands) thru DirectLink.
26
// Some functions should be renamed or re-organized...
37
#include "dusb_vpkt.h"
42
GList *cpca_list = NULL;
44
CalcParam* cp_new(uint16_t id, uint16_t size)
46
CalcParam* cp = g_malloc0(sizeof(CalcParam));
50
cp->data = g_malloc0(size);
52
cpca_list = g_list_append(cpca_list, cp);
56
void cp_del(CalcParam* cp)
58
cpca_list = g_list_remove(cpca_list, cp);
64
CalcParam** cp_new_array(int size)
66
CalcParam** array = g_malloc0((size+1) * sizeof(CalcParam *));
70
void cp_del_array(int size, CalcParam **params)
74
for(i = 0; i < size && params[i]; i++)
79
/////////////----------------
81
CalcAttr* ca_new(uint16_t id, uint16_t size)
83
CalcAttr* cp = g_malloc0(sizeof(CalcAttr));
87
cp->data = g_malloc0(size);
89
cpca_list = g_list_append(cpca_list, cp);
93
void ca_del(CalcAttr* cp)
95
cpca_list = g_list_remove(cpca_list, cp);
101
CalcAttr** ca_new_array(int size)
103
CalcAttr** array = g_malloc0((size+1) * sizeof(CalcParam *));
107
void ca_del_array(int size, CalcAttr **attrs)
111
for(i = 0; i < size && attrs[i]; i++)
116
void cpca_purge(void)
118
//printf("cpca_purge: %p %i\n", cpca_list, g_list_length(cpca_list));
119
g_list_foreach(cpca_list, (GFunc)ca_del, NULL);
120
g_list_free(cpca_list);
124
/////////////----------------
126
static void byteswap(uint8_t *data, uint32_t len)
151
/////////////----------------
153
static uint16_t usb_errors[] = {
154
0x0004, 0x0006, 0x0008, 0x0009, 0x000c, 0x000d, 0x000e,
155
0x0011, 0x0012, 0x001c, 0x001d, 0x0022, 0x0029, 0x002b,
158
static int err_code(VirtualPacket *pkt)
161
int code = (pkt->data[0] << 8) | pkt->data[1];
163
for(i = 0; i < sizeof(usb_errors) / sizeof(uint16_t); i++)
164
if(usb_errors[i] == code)
167
ticalcs_warning("USB error code not found in list. Please report it at <tilp-devel@lists.sf.net>.");
172
/////////////----------------
174
extern const VtlPktName vpkt_types[];
176
#define CATCH_DELAY() \
177
if(pkt->type == VPKT_DELAY_ACK) \
179
uint32_t delay = (pkt->data[0] << 24) | (pkt->data[1] << 16) | (pkt->data[2] << 8) | (pkt->data[3] << 0); \
180
ticalcs_info(" delay = %u\n", delay); \
184
dusb_vtl_pkt_del(pkt); \
185
pkt = dusb_vtl_pkt_new(0, 0); \
186
TRYF(dusb_recv_data(h, pkt)); \
189
// 0x0001: set mode or ping
190
int cmd_s_mode_set(CalcHandle *h, ModeSet mode)
194
TRYF(dusb_send_buf_size_request(h, DUSB_DFL_BUF_SIZE));
195
TRYF(dusb_recv_buf_size_alloc(h, NULL));
197
pkt = dusb_vtl_pkt_new(sizeof(mode), VPKT_PING);
198
pkt->data[0] = MSB(mode.arg1);
199
pkt->data[1] = LSB(mode.arg1);
200
pkt->data[2] = MSB(mode.arg2);
201
pkt->data[3] = LSB(mode.arg2);
202
pkt->data[4] = MSB(mode.arg3);
203
pkt->data[5] = LSB(mode.arg3);
204
pkt->data[6] = MSB(mode.arg4);
205
pkt->data[7] = LSB(mode.arg4);
206
pkt->data[8] = MSB(mode.arg5);
207
pkt->data[9] = LSB(mode.arg5);
208
TRYF(dusb_send_data(h, pkt));
210
dusb_vtl_pkt_del(pkt);
211
ticalcs_info(" %04x %04x %04x %04x %04x", mode.arg1, mode.arg2, mode.arg3, mode.arg4, mode.arg5);
216
// 0x0002: begin OS transfer
217
int cmd_s_os_begin(CalcHandle *h, uint32_t size)
221
pkt = dusb_vtl_pkt_new(11, VPKT_OS_BEGIN);
222
pkt->data[7] = MSB(MSW(size));
223
pkt->data[8] = LSB(MSW(size));
224
pkt->data[9] = MSB(LSW(size));
225
pkt->data[10]= LSB(LSW(size));
226
TRYF(dusb_send_data(h, pkt));
228
dusb_vtl_pkt_del(pkt);
229
ticalcs_info(" size = %08x (%i)", size, size);
234
// 0x0003: acknowledgement of OS transfer
235
int cmd_r_os_ack(CalcHandle *h, uint32_t *size)
239
pkt = dusb_vtl_pkt_new(0, 0);
240
TRYF(dusb_recv_data(h, pkt));
244
if(pkt->type == VPKT_ERROR)
245
return ERR_CALC_ERROR2 + err_code(pkt);
246
else if(pkt->type != VPKT_OS_ACK)
247
return ERR_INVALID_PACKET;
249
*size = (pkt->data[0] << 24) | (pkt->data[1] << 16) | (pkt->data[2] << 8) | (pkt->data[3] << 0);
251
dusb_vtl_pkt_del(pkt);
252
ticalcs_info(" size = %08x (%i)", *size, *size);
257
static int s_os(uint8_t type, CalcHandle *h, uint16_t addr, uint8_t page, uint8_t flag, uint32_t size, uint8_t *data)
261
pkt = dusb_vtl_pkt_new(4 + size, type);
263
pkt->data[0] = MSB(addr);
264
pkt->data[1] = LSB(addr);
267
memcpy(pkt->data+4, data, size);
268
TRYF(dusb_send_data(h, pkt));
270
dusb_vtl_pkt_del(pkt);
271
ticalcs_info(" addr=%04x, page=%02x, flag=%02x, size=%04x", addr, page, flag, size);
277
int cmd_s_os_header(CalcHandle *h, uint16_t addr, uint8_t page, uint8_t flag, uint32_t size, uint8_t *data)
279
return s_os(VPKT_OS_HEADER, h, addr, page, flag, size, data);
283
int cmd_s_os_data(CalcHandle *h, uint16_t addr, uint8_t page, uint8_t flag, uint32_t size, uint8_t *data)
285
return s_os(VPKT_OS_DATA, h, addr, page, flag, size, data);
289
int cmd_s_os_header_89(CalcHandle *h, uint32_t size, uint8_t *data)
293
pkt = dusb_vtl_pkt_new(size, VPKT_OS_HEADER);
294
memcpy(pkt->data, data, size);
295
TRYF(dusb_send_data(h, pkt));
297
dusb_vtl_pkt_del(pkt);
298
ticalcs_info(" size = %08x (%i)", size, size);
304
int cmd_s_os_data_89(CalcHandle *h, uint32_t size, uint8_t *data)
308
pkt = dusb_vtl_pkt_new(size, VPKT_OS_DATA);
309
memcpy(pkt->data, data, size);
310
TRYF(dusb_send_data(h, pkt));
312
dusb_vtl_pkt_del(pkt);
313
ticalcs_info(" size = %08x (%i)", size, size);
318
// 0x0006: acknowledgement of EOT
319
int cmd_r_eot_ack(CalcHandle *h)
323
pkt = dusb_vtl_pkt_new(0, 0);
324
TRYF(dusb_recv_data(h, pkt));
328
if(pkt->type == VPKT_ERROR)
329
return ERR_CALC_ERROR2 + err_code(pkt);
330
else if(pkt->type != VPKT_EOT_ACK)
331
return ERR_INVALID_PACKET;
333
dusb_vtl_pkt_del(pkt);
338
// 0x0007: parameter request
339
int cmd_s_param_request(CalcHandle *h, int npids, uint16_t *pids)
344
pkt = dusb_vtl_pkt_new((npids + 1) * sizeof(uint16_t), VPKT_PARM_REQ);
346
pkt->data[0] = MSB(npids);
347
pkt->data[1] = LSB(npids);
349
for(i = 0; i < npids; i++)
351
pkt->data[2*(i+1) + 0] = MSB(pids[i]);
352
pkt->data[2*(i+1) + 1] = LSB(pids[i]);
355
TRYF(dusb_send_data(h, pkt));
357
dusb_vtl_pkt_del(pkt);
358
ticalcs_info(" npids=%i", npids);
363
// 0x0008: parameter data
364
int cmd_r_param_data(CalcHandle *h, int nparams, CalcParam **params)
369
pkt = dusb_vtl_pkt_new(0, 0);
370
TRYF(dusb_recv_data(h, pkt));
374
if(pkt->type == VPKT_ERROR)
375
return ERR_CALC_ERROR2 + err_code(pkt);
376
else if(pkt->type != VPKT_PARM_DATA)
377
return ERR_INVALID_PACKET;
379
if(((pkt->data[j=0] << 8) | pkt->data[j=1]) != nparams)
380
return ERR_INVALID_PACKET;
382
for(i = 0, j = 2; i < nparams; i++)
384
CalcParam *s = params[i] = cp_new(0, 0);
386
s->id = pkt->data[j++] << 8; s->id |= pkt->data[j++];
387
s->ok = !pkt->data[j++];
390
s->size = pkt->data[j++] << 8; s->size |= pkt->data[j++];
391
s->data = (uint8_t *)g_malloc0(s->size);
392
memcpy(s->data, &pkt->data[j], s->size);
397
dusb_vtl_pkt_del(pkt);
398
ticalcs_info(" nparams=%i", nparams);
403
// 0x0009: request directory listing
404
int cmd_s_dirlist_request(CalcHandle *h, int naids, uint16_t *aids)
410
pkt = dusb_vtl_pkt_new(4 + 2*naids + 7, VPKT_DIR_REQ);
412
pkt->data[j++] = MSB(MSW(naids));
413
pkt->data[j++] = LSB(MSW(naids));
414
pkt->data[j++] = MSB(LSW(naids));
415
pkt->data[j++] = LSB(LSW(naids));
417
for(i = 0; i < naids; i++)
419
pkt->data[j++] = MSB(aids[i]);
420
pkt->data[j++] = LSB(aids[i]);
423
pkt->data[j++] = 0x00; pkt->data[j++] = 0x01;
424
pkt->data[j++] = 0x00; pkt->data[j++] = 0x01;
425
pkt->data[j++] = 0x00; pkt->data[j++] = 0x01;
426
pkt->data[j++] = 0x01;
428
TRYF(dusb_send_data(h, pkt));
430
dusb_vtl_pkt_del(pkt);
431
ticalcs_info(" naids=%i", naids);
436
// 0x000A: variable header (name is utf-8)
437
// beware: attr array contents is allocated by function
438
int cmd_r_var_header(CalcHandle *h, char *folder, char *name, CalcAttr **attr)
446
pkt = dusb_vtl_pkt_new(0, 0);
447
TRYF(dusb_recv_data(h, pkt));
451
if(pkt->type == VPKT_EOT)
453
dusb_vtl_pkt_del(pkt);
456
else if(pkt->type == VPKT_ERROR)
457
return ERR_CALC_ERROR2 + err_code(pkt);
458
else if(pkt->type != VPKT_VAR_HDR)
459
return ERR_INVALID_PACKET;
462
fld_len = pkt->data[j++];
466
memcpy(folder, &pkt->data[j], fld_len+1);
469
var_len = pkt->data[j++];
473
memcpy(name, &pkt->data[j], var_len+1);
477
nattr = (pkt->data[j+0] << 8) | pkt->data[j+1];
480
for(i = 0; i < nattr; i++)
482
CalcAttr *s = attr[i] = ca_new(0, 0);
484
s->id = pkt->data[j++] << 8; s->id |= pkt->data[j++];
485
s->ok = !pkt->data[j++];
488
s->size = pkt->data[j++] << 8; s->size |= pkt->data[j++];
489
s->data = (uint8_t *)g_malloc0(s->size);
490
memcpy(s->data, &pkt->data[j], s->size);
495
dusb_vtl_pkt_del(pkt);
496
ticalcs_info(" folder=%s, name=%s", folder, name);
501
// 0x000B: request to send
502
int cmd_s_rts(CalcHandle *h, const char *folder, const char *name, uint32_t size, int nattrs, const CalcAttr **attrs)
509
pks = 2 + strlen(name)+1 + 5 + 2;
511
pks += strlen(folder)+1;
512
for(i = 0; i < nattrs; i++) pks += 4 + attrs[i]->size;
513
pkt = dusb_vtl_pkt_new(pks, VPKT_RTS);
517
pkt->data[j++] = strlen(folder);
518
memcpy(pkt->data + j, folder, strlen(folder)+1);
519
j += strlen(folder)+1;
524
pkt->data[j++] = strlen(name);
525
memcpy(pkt->data + j, name, strlen(name)+1);
528
pkt->data[j++] = MSB(MSW(size));
529
pkt->data[j++] = LSB(MSW(size));
530
pkt->data[j++] = MSB(LSW(size));
531
pkt->data[j++] = LSB(LSW(size));
532
pkt->data[j++] = 0x01;
534
pkt->data[j++] = MSB(nattrs);
535
pkt->data[j++] = LSB(nattrs);
536
for(i = 0; i < nattrs; i++)
538
pkt->data[j++] = MSB(attrs[i]->id);
539
pkt->data[j++] = LSB(attrs[i]->id);
540
pkt->data[j++] = MSB(attrs[i]->size);
541
pkt->data[j++] = LSB(attrs[i]->size);
542
memcpy(pkt->data + j, attrs[i]->data, attrs[i]->size);
543
byteswap(pkt->data + j, attrs[i]->size);
547
TRYF(dusb_send_data(h, pkt));
549
dusb_vtl_pkt_del(pkt);
550
ticalcs_info(" folder=%s, name=%s, size=%i, nattrs=%i", folder, name, size, nattrs);
555
// 0x000C: variable request
556
int cmd_s_var_request(CalcHandle *h, const char *folder, const char *name,
557
int naids, uint16_t *aids,
558
int nattrs, const CalcAttr **attrs)
565
pks = 2 + strlen(name)+1 + 5 + 2 + 2*naids + 2;
566
if(strlen(folder)) pks += strlen(folder)+1;
567
for(i = 0; i < nattrs; i++) pks += 4 + attrs[i]->size;
569
pkt = dusb_vtl_pkt_new(pks, VPKT_VAR_REQ);
573
pkt->data[j++] = strlen(folder);
574
memcpy(pkt->data + j, folder, strlen(folder)+1);
575
j += strlen(folder)+1;
580
pkt->data[j++] = strlen(name);
581
memcpy(pkt->data + j, name, strlen(name)+1);
584
pkt->data[j++] = 0x01;
585
pkt->data[j++] = 0xFF; pkt->data[j++] = 0xFF;
586
pkt->data[j++] = 0xFF; pkt->data[j++] = 0xFF;
588
pkt->data[j++] = MSB(naids);
589
pkt->data[j++] = LSB(naids);
590
for(i = 0; i < naids; i++)
592
pkt->data[j++] = MSB(aids[i]);
593
pkt->data[j++] = LSB(aids[i]);
596
pkt->data[j++] = MSB(nattrs);
597
pkt->data[j++] = LSB(nattrs);
598
for(i = 0; i < nattrs; i++)
600
pkt->data[j++] = MSB(attrs[i]->id);
601
pkt->data[j++] = LSB(attrs[i]->id);
602
pkt->data[j++] = MSB(attrs[i]->size);
603
pkt->data[j++] = LSB(attrs[i]->size);
604
memcpy(pkt->data + j, attrs[i]->data, attrs[i]->size);
605
byteswap(pkt->data + j, attrs[i]->size);
608
pkt->data[j++] = 0x00; pkt->data[j++] = 0x00;
610
TRYF(dusb_send_data(h, pkt));
612
dusb_vtl_pkt_del(pkt);
613
ticalcs_info(" folder=%s, name=%s, naids=%i, nattrs=%i", folder, name, naids, nattrs);
618
// 0x000D: variable contents (recv)
619
int cmd_r_var_content(CalcHandle *h, uint32_t *size, uint8_t **data)
623
pkt = dusb_vtl_pkt_new(0, 0);
624
TRYF(dusb_recv_data(h, pkt));
628
if(pkt->type == VPKT_ERROR)
629
return ERR_CALC_ERROR2 + err_code(pkt);
630
else if(pkt->type != VPKT_VAR_CNTS)
631
return ERR_INVALID_PACKET;
636
*data = g_malloc0(pkt->size);
637
memcpy(*data, pkt->data, pkt->size);
639
dusb_vtl_pkt_del(pkt);
640
ticalcs_info(" size=%i", size);
645
// 0x000D: variable contents (send)
646
int cmd_s_var_content(CalcHandle *h, uint32_t size, uint8_t *data)
650
pkt = dusb_vtl_pkt_new(size, VPKT_VAR_CNTS);
652
memcpy(pkt->data, data, size);
653
TRYF(dusb_send_data(h, pkt));
655
dusb_vtl_pkt_del(pkt);
656
ticalcs_info(" size=%i", size);
661
// 0x000E: parameter set
662
int cmd_s_param_set(CalcHandle *h, const CalcParam *param)
666
pkt = dusb_vtl_pkt_new(2 + 2 + param->size, VPKT_PARM_SET);
668
pkt->data[0] = MSB(param->id);
669
pkt->data[1] = LSB(param->id);
670
pkt->data[2] = MSB(param->size);
671
pkt->data[3] = LSB(param->size);
672
memcpy(pkt->data + 4, param->data, param->size);
674
TRYF(dusb_send_data(h, pkt));
676
dusb_vtl_pkt_del(pkt);
677
ticalcs_info(" pid=%04x, size=%04x", param->id, param->size);
682
// 0x0010: variable delete
683
int cmd_s_var_delete(CalcHandle *h, const char *folder, const char *name, int nattrs, const CalcAttr **attrs)
690
pks = 2 + strlen(name)+1 + 2;
692
pks += strlen(folder)+1;
693
for(i = 0; i < nattrs; i++) pks += 4 + attrs[i]->size;
695
pkt = dusb_vtl_pkt_new(pks, VPKT_DEL_VAR);
699
pkt->data[j++] = strlen(folder);
700
memcpy(pkt->data + j, folder, strlen(folder)+1);
701
j += strlen(folder)+1;
706
pkt->data[j++] = strlen(name);
707
memcpy(pkt->data + j, name, strlen(name)+1);
710
pkt->data[j++] = MSB(nattrs);
711
pkt->data[j++] = LSB(nattrs);
712
for(i = 0; i < nattrs; i++)
714
pkt->data[j++] = MSB(attrs[i]->id);
715
pkt->data[j++] = LSB(attrs[i]->id);
716
pkt->data[j++] = MSB(attrs[i]->size);
717
pkt->data[j++] = LSB(attrs[i]->size);
718
memcpy(pkt->data + j, attrs[i]->data, attrs[i]->size);
719
byteswap(pkt->data + j, attrs[i]->size);
723
pkt->data[j++] = 0x01; pkt->data[j++] = 0x00;
724
pkt->data[j++] = 0x00; pkt->data[j++] = 0x00;
725
pkt->data[j++] = 0x00;
727
TRYF(dusb_send_data(h, pkt));
729
dusb_vtl_pkt_del(pkt);
730
ticalcs_info(" folder=%s, name=%s, nattrs=%i", folder, name, nattrs);
735
// 0x0011: remote control
736
int cmd_s_execute(CalcHandle *h, const char *folder, const char *name,
737
uint8_t action, const char *args, uint16_t code)
744
if(args) pks += strlen(args); else pks += 2;
745
if(strlen(folder)) pks += strlen(folder)+1;
746
if(strlen(name)) pks += strlen(name)+1;
747
pkt = dusb_vtl_pkt_new(pks, VPKT_EXECUTE);
749
pkt->data[j++] = strlen(folder);
752
memcpy(pkt->data + j, folder, strlen(folder)+1);
753
j += strlen(folder)+1;
756
pkt->data[j++] = strlen(name);
759
memcpy(pkt->data + j, name, strlen(name)+1);
763
pkt->data[j++] = action;
765
if(action != EID_KEY && args != NULL)
766
memcpy(pkt->data + j, args, strlen(args));
767
else if(action == EID_KEY || args == NULL)
769
if(h->model == CALC_TI89T_USB)
771
pkt->data[j++] = MSB(code);
772
pkt->data[j++] = LSB(code);
774
else if(h->model == CALC_TI84P_USB)
776
pkt->data[j++] = LSB(code);
777
pkt->data[j++] = MSB(code);
781
TRYF(dusb_send_data(h, pkt));
783
dusb_vtl_pkt_del(pkt);
785
ticalcs_info(" action=%i, folder=%s, name=%s, args=%s", action, folder, name, args);
787
ticalcs_info(" action=%i, keycode=%04x", action, code);
792
// 0x0012: acknowledgement of mode setting
793
int cmd_r_mode_ack(CalcHandle *h)
797
pkt = dusb_vtl_pkt_new(0, 0);
798
TRYF(dusb_recv_data(h, pkt));
802
if(pkt->type == VPKT_ERROR)
803
return ERR_CALC_ERROR2 + err_code(pkt);
804
else if(pkt->type != VPKT_MODE_SET)
805
return ERR_INVALID_PACKET;
807
dusb_vtl_pkt_del(pkt);
812
// 0xAA00: acknowledgement of data
813
int cmd_r_data_ack(CalcHandle *h)
817
pkt = dusb_vtl_pkt_new(0, 0);
818
TRYF(dusb_recv_data(h, pkt));
822
if(pkt->type == VPKT_ERROR)
823
return ERR_CALC_ERROR2 + err_code(pkt);
824
else if(pkt->type != VPKT_DATA_ACK)
825
return ERR_INVALID_PACKET;
827
dusb_vtl_pkt_del(pkt);
832
// 0xBB00: delay acknowledgement
833
int cmd_r_delay_ack(CalcHandle *h)
837
pkt = dusb_vtl_pkt_new(0, 0);
838
TRYF(dusb_recv_data(h, pkt));
840
if(pkt->type == VPKT_ERROR)
841
return ERR_CALC_ERROR2 + err_code(pkt);
842
else if(pkt->type != VPKT_DELAY_ACK)
843
return ERR_INVALID_PACKET;
847
dusb_vtl_pkt_del(pkt);
852
// 0xDD00: end of transmission (send)
853
int cmd_s_eot(CalcHandle *h)
857
pkt = dusb_vtl_pkt_new(0, VPKT_EOT);
858
TRYF(dusb_send_data(h, pkt));
860
dusb_vtl_pkt_del(pkt);
865
// 0xDD00: end of transmission (recv)
866
int cmd_r_eot(CalcHandle *h)
870
pkt = dusb_vtl_pkt_new(0, 0);
871
TRYF(dusb_recv_data(h, pkt));
875
if(pkt->type == VPKT_ERROR)
876
return ERR_CALC_ERROR2 + err_code(pkt);
877
else if(pkt->type != VPKT_EOT)
878
return ERR_INVALID_PACKET;
880
dusb_vtl_pkt_del(pkt);
886
int cmd_s_error(CalcHandle *h, uint16_t code)
890
pkt = dusb_vtl_pkt_new(2, VPKT_ERROR);
892
pkt->data[0] = MSB(code);
893
pkt->data[1] = LSB(code);
894
TRYF(dusb_send_data(h, pkt));
896
dusb_vtl_pkt_del(pkt);
897
ticalcs_info(" code = %04x", code);
1
/* Hey EMACS -*- linux-c -*- */
2
/* $Id: cmd84p.c 2077 2006-03-31 21:16:19Z roms $ */
4
/* libticalcs - Ti Calculator library, a part of the TiLP project
5
* Copyright (C) 1999-2005 Romain Li�vin
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.
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.
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
23
This unit handles virtual packet types (commands) thru DirectLink.
26
// Some functions should be renamed or re-organized...
37
#include "dusb_vpkt.h"
42
GList *cpca_list = NULL;
44
TIEXPORT3 DUSBCalcParam* TICALL dusb_cp_new(uint16_t id, uint16_t size)
46
DUSBCalcParam* cp = g_malloc0(sizeof(DUSBCalcParam)); // aborts the program if it fails.
50
cp->data = g_malloc0(size); // aborts the program if it fails.
52
cpca_list = g_list_append(cpca_list, cp);
57
TIEXPORT3 void TICALL dusb_cp_del(DUSBCalcParam* cp)
61
cpca_list = g_list_remove(cpca_list, cp);
68
ticalcs_critical("%s: cp is NULL", __FUNCTION__);
72
TIEXPORT3 DUSBCalcParam** TICALL dusb_cp_new_array(int size)
74
DUSBCalcParam** array = g_malloc0((size+1) * sizeof(DUSBCalcParam *)); // aborts the program if it fails.
78
TIEXPORT3 void TICALL dusb_cp_del_array(int size, DUSBCalcParam **params)
84
for(i = 0; i < size && params[i]; i++)
86
dusb_cp_del(params[i]);
92
ticalcs_critical("%s: params is NULL", __FUNCTION__);
97
/////////////----------------
99
TIEXPORT3 DUSBCalcAttr* TICALL dusb_ca_new(uint16_t id, uint16_t size)
101
DUSBCalcAttr* cp = g_malloc0(sizeof(DUSBCalcAttr)); // aborts the program if it fails.
105
cp->data = g_malloc0(size); // aborts the program if it fails.
107
cpca_list = g_list_append(cpca_list, cp);
112
TIEXPORT3 void TICALL dusb_ca_del(DUSBCalcAttr* cp)
116
cpca_list = g_list_remove(cpca_list, cp);
123
ticalcs_critical("%s: cp is NULL", __FUNCTION__);
127
TIEXPORT3 DUSBCalcAttr** TICALL dusb_ca_new_array(int size)
129
DUSBCalcAttr** array = g_malloc0((size+1) * sizeof(DUSBCalcAttr *)); // aborts the program if it fails.
133
TIEXPORT3 void TICALL dusb_ca_del_array(int size, DUSBCalcAttr **attrs)
139
for(i = 0; i < size && attrs[i]; i++)
141
dusb_ca_del(attrs[i]);
147
ticalcs_critical("%s: attrs is NULL", __FUNCTION__);
151
void dusb_cpca_purge(void)
153
//printf("cpca_purge: %p %i\n", cpca_list, g_list_length(cpca_list));
154
g_list_foreach(cpca_list, (GFunc)dusb_ca_del, NULL);
155
g_list_free(cpca_list);
159
/////////////----------------
161
static void byteswap(uint8_t *data, uint32_t len)
186
/////////////----------------
188
static const uint16_t usb_errors[] = {
189
0x0004, 0x0006, 0x0008, 0x0009, 0x000c, 0x000d, 0x000e,
190
0x0011, 0x0012, 0x001c, 0x001d, 0x0022, 0x0027, 0x0029,
191
0x002b, 0x002e, 0x0034 };
193
static int err_code(DUSBVirtualPacket *pkt)
196
int code = (pkt->data[0] << 8) | pkt->data[1];
198
for(i = 0; i < (int)(sizeof(usb_errors) / sizeof(usb_errors[0])); i++)
199
if(usb_errors[i] == code)
202
ticalcs_warning("USB error code 0x%02x not found in list. Please report it at <tilp-devel@lists.sf.net>.", code);
207
/////////////----------------
209
extern const DUSBVtlPktName vpkt_types[];
211
#define CATCH_DELAY() \
212
if (pkt->type == DUSB_VPKT_DELAY_ACK) \
214
uint32_t delay = (pkt->data[0] << 24) | (pkt->data[1] << 16) | (pkt->data[2] << 8) | (pkt->data[3] << 0); \
215
ticalcs_info(" delay = %u", delay); \
216
if (delay > 400000) \
219
ticalcs_info(" (absurdly high delay, clamping to a more reasonable value)"); \
224
dusb_vtl_pkt_del(pkt); \
225
pkt = dusb_vtl_pkt_new(0, 0); \
227
retval = dusb_recv_data(h, pkt); \
234
// 0x0001: set mode or ping
235
TIEXPORT3 int TICALL dusb_cmd_s_mode_set(CalcHandle *h, DUSBModeSet mode)
237
DUSBVirtualPacket* pkt;
242
ticalcs_critical("%s: h is NULL", __FUNCTION__);
243
return ERR_INVALID_HANDLE;
246
TRYF(dusb_send_buf_size_request(h, DUSB_DFL_BUF_SIZE));
247
TRYF(dusb_recv_buf_size_alloc(h, NULL));
249
pkt = dusb_vtl_pkt_new(sizeof(mode), DUSB_VPKT_PING);
251
pkt->data[0] = MSB(mode.arg1);
252
pkt->data[1] = LSB(mode.arg1);
253
pkt->data[2] = MSB(mode.arg2);
254
pkt->data[3] = LSB(mode.arg2);
255
pkt->data[4] = MSB(mode.arg3);
256
pkt->data[5] = LSB(mode.arg3);
257
pkt->data[6] = MSB(mode.arg4);
258
pkt->data[7] = LSB(mode.arg4);
259
pkt->data[8] = MSB(mode.arg5);
260
pkt->data[9] = LSB(mode.arg5);
261
retval = dusb_send_data(h, pkt);
263
dusb_vtl_pkt_del(pkt);
265
ticalcs_info(" %04x %04x %04x %04x %04x", mode.arg1, mode.arg2, mode.arg3, mode.arg4, mode.arg5);
270
// 0x0002: begin OS transfer
271
TIEXPORT3 int TICALL dusb_cmd_s_os_begin(CalcHandle *h, uint32_t size)
273
DUSBVirtualPacket* pkt;
278
ticalcs_critical("%s: h is NULL", __FUNCTION__);
279
return ERR_INVALID_HANDLE;
282
pkt = dusb_vtl_pkt_new(11, DUSB_VPKT_OS_BEGIN);
284
pkt->data[7] = MSB(MSW(size));
285
pkt->data[8] = LSB(MSW(size));
286
pkt->data[9] = MSB(LSW(size));
287
pkt->data[10]= LSB(LSW(size));
288
retval = dusb_send_data(h, pkt);
290
dusb_vtl_pkt_del(pkt);
292
ticalcs_info(" size = %08x (%i)", size, size);
297
// 0x0003: acknowledgement of OS transfer
298
TIEXPORT3 int TICALL dusb_cmd_r_os_ack(CalcHandle *h, uint32_t *size)
300
DUSBVirtualPacket* pkt;
305
ticalcs_critical("%s: h is NULL", __FUNCTION__);
306
return ERR_INVALID_HANDLE;
309
pkt = dusb_vtl_pkt_new(0, 0);
311
retval = dusb_recv_data(h, pkt);
317
if(pkt->type == DUSB_VPKT_ERROR)
319
retval = ERR_CALC_ERROR2 + err_code(pkt);
322
else if(pkt->type != DUSB_VPKT_OS_ACK)
324
retval = ERR_INVALID_PACKET;
330
*size = (pkt->data[0] << 24) | (pkt->data[1] << 16) | (pkt->data[2] << 8) | (pkt->data[3] << 0);
331
ticalcs_info(" size = %08x (%i)", *size, *size);
336
dusb_vtl_pkt_del(pkt);
341
static int s_os(uint8_t type, CalcHandle *h, uint16_t addr, uint8_t page, uint8_t flag, uint32_t size, uint8_t *data)
343
DUSBVirtualPacket* pkt;
348
ticalcs_critical("%s: h is NULL", __FUNCTION__);
349
return ERR_INVALID_HANDLE;
353
ticalcs_critical("%s: data is NULL", __FUNCTION__);
354
return ERR_INVALID_PARAMETER;
357
pkt = dusb_vtl_pkt_new(4 + size, type);
359
pkt->data[0] = MSB(addr);
360
pkt->data[1] = LSB(addr);
363
memcpy(pkt->data+4, data, size);
364
retval = dusb_send_data(h, pkt);
366
dusb_vtl_pkt_del(pkt);
367
ticalcs_info(" addr=%04x, page=%02x, flag=%02x, size=%04x", addr, page, flag, size);
373
TIEXPORT3 int TICALL dusb_cmd_s_os_header(CalcHandle *h, uint16_t addr, uint8_t page, uint8_t flag, uint32_t size, uint8_t *data)
375
return s_os(DUSB_VPKT_OS_HEADER, h, addr, page, flag, size, data);
379
TIEXPORT3 int TICALL dusb_cmd_s_os_data(CalcHandle *h, uint16_t addr, uint8_t page, uint8_t flag, uint32_t size, uint8_t *data)
381
return s_os(DUSB_VPKT_OS_DATA, h, addr, page, flag, size, data);
385
TIEXPORT3 int TICALL dusb_cmd_s_os_header_89(CalcHandle *h, uint32_t size, uint8_t *data)
387
DUSBVirtualPacket* pkt;
392
ticalcs_critical("%s: h is NULL", __FUNCTION__);
393
return ERR_INVALID_HANDLE;
397
ticalcs_critical("%s: data is NULL", __FUNCTION__);
398
return ERR_INVALID_PARAMETER;
401
pkt = dusb_vtl_pkt_new(size, DUSB_VPKT_OS_HEADER);
403
memcpy(pkt->data, data, size);
404
retval = dusb_send_data(h, pkt);
406
dusb_vtl_pkt_del(pkt);
407
ticalcs_info(" size = %08x (%i)", size, size);
413
TIEXPORT3 int TICALL dusb_cmd_s_os_data_89(CalcHandle *h, uint32_t size, uint8_t *data)
415
DUSBVirtualPacket* pkt;
420
ticalcs_critical("%s: h is NULL", __FUNCTION__);
421
return ERR_INVALID_HANDLE;
425
ticalcs_critical("%s: data is NULL", __FUNCTION__);
426
return ERR_INVALID_PARAMETER;
429
pkt = dusb_vtl_pkt_new(size, DUSB_VPKT_OS_DATA);
431
memcpy(pkt->data, data, size);
432
retval = dusb_send_data(h, pkt);
434
dusb_vtl_pkt_del(pkt);
435
ticalcs_info(" size = %08x (%i)", size, size);
440
// 0x0006: acknowledgement of EOT
441
TIEXPORT3 int TICALL dusb_cmd_r_eot_ack(CalcHandle *h)
443
DUSBVirtualPacket* pkt;
448
ticalcs_critical("%s: h is NULL", __FUNCTION__);
449
return ERR_INVALID_HANDLE;
452
pkt = dusb_vtl_pkt_new(0, 0);
454
retval = dusb_recv_data(h, pkt);
460
if(pkt->type == DUSB_VPKT_ERROR)
462
retval = ERR_CALC_ERROR2 + err_code(pkt);
464
else if(pkt->type != DUSB_VPKT_EOT_ACK)
466
retval = ERR_INVALID_PACKET;
471
dusb_vtl_pkt_del(pkt);
476
// 0x0007: parameter request
477
TIEXPORT3 int TICALL dusb_cmd_s_param_request(CalcHandle *h, int npids, uint16_t *pids)
479
DUSBVirtualPacket* pkt;
485
ticalcs_critical("%s: h is NULL", __FUNCTION__);
486
return ERR_INVALID_HANDLE;
488
if (npids != 0 && pids == NULL)
490
ticalcs_critical("%s: pids is NULL", __FUNCTION__);
491
return ERR_INVALID_PARAMETER;
494
pkt = dusb_vtl_pkt_new(2 + npids * sizeof(uint16_t), DUSB_VPKT_PARM_REQ);
496
pkt->data[0] = MSB(npids);
497
pkt->data[1] = LSB(npids);
499
for(i = 0; i < npids; i++)
501
pkt->data[2*(i+1) + 0] = MSB(pids[i]);
502
pkt->data[2*(i+1) + 1] = LSB(pids[i]);
505
retval = dusb_send_data(h, pkt);
507
dusb_vtl_pkt_del(pkt);
508
ticalcs_info(" npids=%i", npids);
513
// 0x0008: parameter data
514
TIEXPORT3 int TICALL dusb_cmd_r_param_data(CalcHandle *h, int nparams, DUSBCalcParam **params)
516
DUSBVirtualPacket* pkt;
522
ticalcs_critical("%s: h is NULL", __FUNCTION__);
523
return ERR_INVALID_HANDLE;
527
ticalcs_critical("%s: params is NULL", __FUNCTION__);
528
return ERR_INVALID_PARAMETER;
531
pkt = dusb_vtl_pkt_new(0, 0);
533
retval = dusb_recv_data(h, pkt);
539
if(pkt->type == DUSB_VPKT_ERROR)
541
retval = ERR_CALC_ERROR2 + err_code(pkt);
544
else if(pkt->type != DUSB_VPKT_PARM_DATA)
546
retval = ERR_INVALID_PACKET;
550
if(((pkt->data[0] << 8) | pkt->data[1]) != nparams)
552
retval = ERR_INVALID_PACKET;
556
for(i = 0, j = 2; i < nparams; i++)
558
DUSBCalcParam *s = params[i] = dusb_cp_new(0, 0);
560
s->id = pkt->data[j++] << 8; s->id |= pkt->data[j++];
561
s->ok = !pkt->data[j++];
564
s->size = pkt->data[j++] << 8; s->size |= pkt->data[j++];
565
s->data = (uint8_t *)g_malloc0(s->size);
566
memcpy(s->data, &pkt->data[j], s->size);
573
dusb_vtl_pkt_del(pkt);
574
ticalcs_info(" nparams=%i", nparams);
579
// 0x0009: request directory listing
580
TIEXPORT3 int TICALL dusb_cmd_s_dirlist_request(CalcHandle *h, int naids, uint16_t *aids)
582
DUSBVirtualPacket* pkt;
589
ticalcs_critical("%s: h is NULL", __FUNCTION__);
590
return ERR_INVALID_HANDLE;
592
if (naids != 0 && aids == NULL)
594
ticalcs_critical("%s: aids is NULL", __FUNCTION__);
595
return ERR_INVALID_PARAMETER;
598
pkt = dusb_vtl_pkt_new(4 + 2*naids + 7, DUSB_VPKT_DIR_REQ);
600
pkt->data[j++] = MSB(MSW(naids));
601
pkt->data[j++] = LSB(MSW(naids));
602
pkt->data[j++] = MSB(LSW(naids));
603
pkt->data[j++] = LSB(LSW(naids));
605
for(i = 0; i < naids; i++)
607
pkt->data[j++] = MSB(aids[i]);
608
pkt->data[j++] = LSB(aids[i]);
611
pkt->data[j++] = 0x00; pkt->data[j++] = 0x01;
612
pkt->data[j++] = 0x00; pkt->data[j++] = 0x01;
613
pkt->data[j++] = 0x00; pkt->data[j++] = 0x01;
614
pkt->data[j++] = 0x01;
616
retval = dusb_send_data(h, pkt);
618
dusb_vtl_pkt_del(pkt);
619
ticalcs_info(" naids=%i", naids);
624
// 0x000A: variable header (name is utf-8)
625
// beware: attr array contents is allocated by function
626
TIEXPORT3 int TICALL dusb_cmd_r_var_header(CalcHandle *h, char *folder, char *name, DUSBCalcAttr **attr)
628
DUSBVirtualPacket* pkt;
637
ticalcs_critical("%s: h is NULL", __FUNCTION__);
638
return ERR_INVALID_HANDLE;
640
if (folder == NULL || name == NULL || attr == NULL)
642
ticalcs_critical("%s: an argument is NULL", __FUNCTION__);
643
return ERR_INVALID_PARAMETER;
646
pkt = dusb_vtl_pkt_new(0, 0);
648
retval = dusb_recv_data(h, pkt);
654
if(pkt->type == DUSB_VPKT_EOT)
659
else if(pkt->type == DUSB_VPKT_ERROR)
661
retval = ERR_CALC_ERROR2 + err_code(pkt);
664
else if(pkt->type != DUSB_VPKT_VAR_HDR)
666
retval = ERR_INVALID_PACKET;
671
fld_len = pkt->data[j++];
675
memcpy(folder, &pkt->data[j], fld_len+1);
678
var_len = pkt->data[j++];
682
memcpy(name, &pkt->data[j], var_len+1);
686
nattr = (pkt->data[j+0] << 8) | pkt->data[j+1];
689
for(i = 0; i < nattr; i++)
691
DUSBCalcAttr *s = attr[i] = dusb_ca_new(0, 0);
693
s->id = pkt->data[j++] << 8; s->id |= pkt->data[j++];
694
s->ok = !pkt->data[j++];
697
s->size = pkt->data[j++] << 8; s->size |= pkt->data[j++];
698
s->data = (uint8_t *)g_malloc0(s->size);
699
memcpy(s->data, &pkt->data[j], s->size);
706
dusb_vtl_pkt_del(pkt);
707
ticalcs_info(" folder=%s, name=%s", folder, name);
712
// 0x000B: request to send
713
TIEXPORT3 int TICALL dusb_cmd_s_rts(CalcHandle *h, const char *folder, const char *name, uint32_t size, int nattrs, const DUSBCalcAttr **attrs)
715
DUSBVirtualPacket* pkt;
723
ticalcs_critical("%s: h is NULL", __FUNCTION__);
724
return ERR_INVALID_HANDLE;
726
if (folder == NULL || name == NULL || (nattrs != 0 && attrs == NULL))
728
ticalcs_critical("%s: an argument is NULL", __FUNCTION__);
729
return ERR_INVALID_PARAMETER;
732
pks = 2 + strlen(name)+1 + 5 + 2;
734
pks += strlen(folder)+1;
735
for(i = 0; i < nattrs; i++) pks += 4 + attrs[i]->size;
737
pkt = dusb_vtl_pkt_new(pks, DUSB_VPKT_RTS);
741
pkt->data[j++] = strlen(folder);
742
memcpy(pkt->data + j, folder, strlen(folder)+1);
743
j += strlen(folder)+1;
750
pkt->data[j++] = strlen(name);
751
memcpy(pkt->data + j, name, strlen(name)+1);
754
pkt->data[j++] = MSB(MSW(size));
755
pkt->data[j++] = LSB(MSW(size));
756
pkt->data[j++] = MSB(LSW(size));
757
pkt->data[j++] = LSB(LSW(size));
758
pkt->data[j++] = 0x01;
760
pkt->data[j++] = MSB(nattrs);
761
pkt->data[j++] = LSB(nattrs);
762
for(i = 0; i < nattrs; i++)
764
pkt->data[j++] = MSB(attrs[i]->id);
765
pkt->data[j++] = LSB(attrs[i]->id);
766
pkt->data[j++] = MSB(attrs[i]->size);
767
pkt->data[j++] = LSB(attrs[i]->size);
768
memcpy(pkt->data + j, attrs[i]->data, attrs[i]->size);
769
byteswap(pkt->data + j, attrs[i]->size);
773
retval = dusb_send_data(h, pkt);
775
dusb_vtl_pkt_del(pkt);
776
ticalcs_info(" folder=%s, name=%s, size=%i, nattrs=%i", folder, name, size, nattrs);
781
// 0x000C: variable request
782
TIEXPORT3 int TICALL dusb_cmd_s_var_request(CalcHandle *h, const char *folder, const char *name, int naids, uint16_t *aids, int nattrs, const DUSBCalcAttr **attrs)
784
DUSBVirtualPacket* pkt;
792
ticalcs_critical("%s: h is NULL", __FUNCTION__);
793
return ERR_INVALID_HANDLE;
795
if (folder == NULL || name == NULL || (naids != 0 && aids == NULL) || (nattrs != 0 && attrs == NULL))
797
ticalcs_critical("%s: an argument is NULL", __FUNCTION__);
798
return ERR_INVALID_PARAMETER;
801
pks = 2 + strlen(name)+1 + 5 + 2 + 2*naids + 2;
802
if(strlen(folder)) pks += strlen(folder)+1;
803
for(i = 0; i < nattrs; i++) pks += 4 + attrs[i]->size;
806
pkt = dusb_vtl_pkt_new(pks, DUSB_VPKT_VAR_REQ);
810
pkt->data[j++] = strlen(folder);
811
memcpy(pkt->data + j, folder, strlen(folder)+1);
812
j += strlen(folder)+1;
817
pkt->data[j++] = strlen(name);
818
memcpy(pkt->data + j, name, strlen(name)+1);
821
pkt->data[j++] = 0x01;
822
pkt->data[j++] = 0xFF; pkt->data[j++] = 0xFF;
823
pkt->data[j++] = 0xFF; pkt->data[j++] = 0xFF;
825
pkt->data[j++] = MSB(naids);
826
pkt->data[j++] = LSB(naids);
827
for(i = 0; i < naids; i++)
829
pkt->data[j++] = MSB(aids[i]);
830
pkt->data[j++] = LSB(aids[i]);
833
pkt->data[j++] = MSB(nattrs);
834
pkt->data[j++] = LSB(nattrs);
835
for(i = 0; i < nattrs; i++)
837
pkt->data[j++] = MSB(attrs[i]->id);
838
pkt->data[j++] = LSB(attrs[i]->id);
839
pkt->data[j++] = MSB(attrs[i]->size);
840
pkt->data[j++] = LSB(attrs[i]->size);
841
memcpy(pkt->data + j, attrs[i]->data, attrs[i]->size);
842
byteswap(pkt->data + j, attrs[i]->size);
845
pkt->data[j++] = 0x00; pkt->data[j++] = 0x00;
847
retval = dusb_send_data(h, pkt);
849
dusb_vtl_pkt_del(pkt);
850
ticalcs_info(" folder=%s, name=%s, naids=%i, nattrs=%i", folder, name, naids, nattrs);
855
// 0x000D: variable contents (recv)
856
TIEXPORT3 int TICALL dusb_cmd_r_var_content(CalcHandle *h, uint32_t *size, uint8_t **data)
858
DUSBVirtualPacket* pkt;
863
ticalcs_critical("%s: h is NULL", __FUNCTION__);
864
return ERR_INVALID_HANDLE;
868
ticalcs_critical("%s: data is NULL", __FUNCTION__);
869
return ERR_INVALID_PARAMETER;
872
pkt = dusb_vtl_pkt_new(0, 0);
874
retval = dusb_recv_data(h, pkt);
880
if(pkt->type == DUSB_VPKT_ERROR)
882
retval = ERR_CALC_ERROR2 + err_code(pkt);
885
else if(pkt->type != DUSB_VPKT_VAR_CNTS)
887
retval = ERR_INVALID_PACKET;
896
*data = g_malloc0(pkt->size);
899
memcpy(*data, pkt->data, pkt->size);
905
ticalcs_info(" size=%i", pkt->size);
909
dusb_vtl_pkt_del(pkt);
914
// 0x000D: variable contents (send)
915
TIEXPORT3 int TICALL dusb_cmd_s_var_content(CalcHandle *h, uint32_t size, uint8_t *data)
917
DUSBVirtualPacket* pkt;
922
ticalcs_critical("%s: h is NULL", __FUNCTION__);
923
return ERR_INVALID_HANDLE;
927
ticalcs_critical("%s: data is NULL", __FUNCTION__);
928
return ERR_INVALID_PARAMETER;
931
pkt = dusb_vtl_pkt_new(size, DUSB_VPKT_VAR_CNTS);
933
memcpy(pkt->data, data, size);
934
retval = dusb_send_data(h, pkt);
936
dusb_vtl_pkt_del(pkt);
937
ticalcs_info(" size=%i", size);
942
// 0x000E: parameter set
943
TIEXPORT3 int TICALL dusb_cmd_s_param_set(CalcHandle *h, const DUSBCalcParam *param)
945
DUSBVirtualPacket* pkt;
950
ticalcs_critical("%s: h is NULL", __FUNCTION__);
951
return ERR_INVALID_HANDLE;
955
ticalcs_critical("%s: param is NULL", __FUNCTION__);
956
return ERR_INVALID_PARAMETER;
959
pkt = dusb_vtl_pkt_new(2 + 2 + param->size, DUSB_VPKT_PARM_SET);
961
pkt->data[0] = MSB(param->id);
962
pkt->data[1] = LSB(param->id);
963
pkt->data[2] = MSB(param->size);
964
pkt->data[3] = LSB(param->size);
965
memcpy(pkt->data + 4, param->data, param->size);
967
retval = dusb_send_data(h, pkt);
969
dusb_vtl_pkt_del(pkt);
970
ticalcs_info(" pid=%04x, size=%04x", param->id, param->size);
975
// 0x0010: modify/rename/delete variable
976
TIEXPORT3 int TICALL dusb_cmd_s_var_modify(CalcHandle *h,
977
const char *src_folder, const char *src_name,
978
int n_src_attrs, const DUSBCalcAttr **src_attrs,
979
const char *dst_folder, const char *dst_name,
980
int n_dst_attrs, const DUSBCalcAttr **dst_attrs)
982
DUSBVirtualPacket* pkt;
990
ticalcs_critical("%s: h is NULL", __FUNCTION__);
991
return ERR_INVALID_HANDLE;
993
if (src_folder == NULL || src_name == NULL || src_attrs == NULL || dst_folder == NULL || dst_name == NULL || (n_dst_attrs != 0 && dst_attrs == NULL))
995
ticalcs_critical("%s: an argument is NULL", __FUNCTION__);
996
return ERR_INVALID_PARAMETER;
999
pks = 2 + strlen(src_name)+1 + 2;
1000
if(strlen(src_folder))
1001
pks += strlen(src_folder)+1;
1002
for(i = 0; i < n_src_attrs; i++)
1003
pks += 4 + src_attrs[i]->size;
1007
if(strlen(dst_folder))
1008
pks += strlen(dst_folder)+1;
1009
if(strlen(dst_name))
1010
pks += strlen(dst_name)+1;
1011
for (i = 0; i < n_dst_attrs; i++)
1012
pks += 4 + dst_attrs[i]->size;
1014
pkt = dusb_vtl_pkt_new(pks, DUSB_VPKT_DEL_VAR);
1016
if(strlen(src_folder))
1018
pkt->data[j++] = strlen(src_folder);
1019
memcpy(pkt->data + j, src_folder, strlen(src_folder)+1);
1020
j += strlen(src_folder)+1;
1027
pkt->data[j++] = strlen(src_name);
1028
memcpy(pkt->data + j, src_name, strlen(src_name)+1);
1029
j += strlen(src_name)+1;
1031
pkt->data[j++] = MSB(n_src_attrs);
1032
pkt->data[j++] = LSB(n_src_attrs);
1033
for(i = 0; i < n_src_attrs; i++)
1035
pkt->data[j++] = MSB(src_attrs[i]->id);
1036
pkt->data[j++] = LSB(src_attrs[i]->id);
1037
pkt->data[j++] = MSB(src_attrs[i]->size);
1038
pkt->data[j++] = LSB(src_attrs[i]->size);
1039
memcpy(pkt->data + j, src_attrs[i]->data, src_attrs[i]->size);
1040
j += src_attrs[i]->size;
1043
pkt->data[j++] = 0x01; /* ??? */
1045
if(strlen(dst_folder))
1047
pkt->data[j++] = strlen(dst_folder);
1048
memcpy(pkt->data + j, dst_folder, strlen(dst_folder)+1);
1049
j += strlen(dst_folder)+1;
1054
if(strlen(dst_name))
1056
pkt->data[j++] = strlen(dst_name);
1057
memcpy(pkt->data + j, dst_name, strlen(dst_name)+1);
1058
j += strlen(dst_name)+1;
1063
pkt->data[j++] = MSB(n_dst_attrs);
1064
pkt->data[j++] = LSB(n_dst_attrs);
1065
for(i = 0; i < n_dst_attrs; i++)
1067
pkt->data[j++] = MSB(dst_attrs[i]->id);
1068
pkt->data[j++] = LSB(dst_attrs[i]->id);
1069
pkt->data[j++] = MSB(dst_attrs[i]->size);
1070
pkt->data[j++] = LSB(dst_attrs[i]->size);
1071
memcpy(pkt->data + j, dst_attrs[i]->data, dst_attrs[i]->size);
1072
j += dst_attrs[i]->size;
1077
retval = dusb_send_data(h, pkt);
1079
ticalcs_info(" src_folder=%s, name=%s, nattrs=%i", src_folder, src_name, n_src_attrs);
1080
ticalcs_info(" dst_folder=%s, name=%s, nattrs=%i", dst_folder, dst_name, n_dst_attrs);
1082
dusb_vtl_pkt_del(pkt);
1086
TIEXPORT3 int TICALL dusb_cmd_s_var_delete(CalcHandle *h, const char *folder, const char *name, int nattrs, const DUSBCalcAttr **attrs)
1088
const DUSBCalcAttr * dummy;
1089
return dusb_cmd_s_var_modify(h, folder, name, nattrs, attrs, "", "", 0, &dummy);
1092
// 0x0011: remote control
1093
TIEXPORT3 int TICALL dusb_cmd_s_execute(CalcHandle *h, const char *folder, const char *name, uint8_t action, const char *args, uint16_t code)
1095
DUSBVirtualPacket* pkt = NULL;
1102
ticalcs_critical("%s: h is NULL", __FUNCTION__);
1103
return ERR_INVALID_HANDLE;
1105
if (folder == NULL || name == NULL)
1107
ticalcs_critical("%s: an argument is NULL", __FUNCTION__);
1108
return ERR_INVALID_PARAMETER;
1111
if(h->model == CALC_TI89T_USB)
1114
if(args) pks += strlen(args); else pks += 2;
1115
if(strlen(folder)) pks += strlen(folder)+1;
1116
if(strlen(name)) pks += strlen(name)+1;
1117
pkt = dusb_vtl_pkt_new(pks, DUSB_VPKT_EXECUTE);
1119
pkt->data[j++] = strlen(folder);
1122
memcpy(pkt->data + j, folder, strlen(folder)+1);
1123
j += strlen(folder)+1;
1126
pkt->data[j++] = strlen(name);
1129
memcpy(pkt->data + j, name, strlen(name)+1);
1130
j += strlen(name)+1;
1133
pkt->data[j++] = action;
1135
if(action != EID_KEY && args != NULL)
1137
memcpy(pkt->data + j, args, strlen(args));
1139
else if(action == EID_KEY || args == NULL)
1141
pkt->data[j++] = MSB(code);
1142
pkt->data[j++] = LSB(code);
1145
else if(h->model == CALC_TI84P_USB)
1148
if(args) pks += strlen(args); else pks += 2;
1149
if(strlen(name)) pks += strlen(name);
1150
pkt = dusb_vtl_pkt_new(pks, DUSB_VPKT_EXECUTE);
1152
// MSB first (like other commands anyway).
1153
// Otherwise, a "EE 00 00 0D" packet is returned.
1154
pkt->data[j++] = MSB(strlen(name));
1155
pkt->data[j++] = LSB(strlen(name));
1158
memcpy(pkt->data + j, name, strlen(name));
1162
pkt->data[j++] = action;
1164
if(action != EID_KEY && args != NULL)
1166
memcpy(pkt->data + j, args, strlen(args));
1168
else if(action == EID_KEY || args == NULL)
1170
pkt->data[j++] = LSB(code);
1171
pkt->data[j++] = MSB(code);
1175
retval = dusb_send_data(h, pkt);
1177
dusb_vtl_pkt_del(pkt);
1178
if (action == EID_KEY)
1180
ticalcs_info(" action=%i, keycode=%04x", action, code);
1184
ticalcs_info(" action=%i, folder=%s, name=%s, args=%s", action, folder ? folder : "NULL", name ? name : "NULL", args ? args : "NULL");
1190
// 0x0012: acknowledgement of mode setting
1191
TIEXPORT3 int TICALL dusb_cmd_r_mode_ack(CalcHandle *h)
1193
DUSBVirtualPacket* pkt;
1198
ticalcs_critical("%s: h is NULL", __FUNCTION__);
1199
return ERR_INVALID_HANDLE;
1202
pkt = dusb_vtl_pkt_new(0, 0);
1204
retval = dusb_recv_data(h, pkt);
1210
if(pkt->type == DUSB_VPKT_ERROR)
1212
retval = ERR_CALC_ERROR2 + err_code(pkt);
1214
else if(pkt->type != DUSB_VPKT_MODE_SET)
1216
retval = ERR_INVALID_PACKET;
1221
dusb_vtl_pkt_del(pkt);
1226
// 0xAA00: acknowledgement of data
1227
TIEXPORT3 int TICALL dusb_cmd_r_data_ack(CalcHandle *h)
1229
DUSBVirtualPacket* pkt;
1234
ticalcs_critical("%s: h is NULL", __FUNCTION__);
1235
return ERR_INVALID_HANDLE;
1238
pkt = dusb_vtl_pkt_new(0, 0);
1240
retval = dusb_recv_data(h, pkt);
1246
if(pkt->type == DUSB_VPKT_ERROR)
1248
retval = ERR_CALC_ERROR2 + err_code(pkt);
1250
else if(pkt->type != DUSB_VPKT_DATA_ACK)
1252
ticalcs_info("cmd_r_data_ack: expected type 0x%4X, received type 0x%4X", DUSB_VPKT_DATA_ACK, pkt->type);
1253
retval = ERR_INVALID_PACKET;
1258
dusb_vtl_pkt_del(pkt);
1263
// 0xBB00: delay acknowledgement
1264
TIEXPORT3 int TICALL dusb_cmd_r_delay_ack(CalcHandle *h)
1266
DUSBVirtualPacket* pkt;
1271
ticalcs_critical("%s: h is NULL", __FUNCTION__);
1272
return ERR_INVALID_HANDLE;
1275
pkt = dusb_vtl_pkt_new(0, 0);
1277
retval = dusb_recv_data(h, pkt);
1281
if(pkt->type == DUSB_VPKT_ERROR)
1283
retval = ERR_CALC_ERROR2 + err_code(pkt);
1285
else if(pkt->type != DUSB_VPKT_DELAY_ACK)
1287
ticalcs_info("cmd_r_data_ack: expected type 0x%4X, received type 0x%4X", DUSB_VPKT_DELAY_ACK, pkt->type);
1288
retval = ERR_INVALID_PACKET;
1294
dusb_vtl_pkt_del(pkt);
1299
// 0xDD00: end of transmission (send)
1300
TIEXPORT3 int TICALL dusb_cmd_s_eot(CalcHandle *h)
1302
DUSBVirtualPacket* pkt;
1307
ticalcs_critical("%s: h is NULL", __FUNCTION__);
1308
return ERR_INVALID_HANDLE;
1311
pkt = dusb_vtl_pkt_new(0, DUSB_VPKT_EOT);
1313
retval = dusb_send_data(h, pkt);
1315
dusb_vtl_pkt_del(pkt);
1320
// 0xDD00: end of transmission (recv)
1321
TIEXPORT3 int TICALL dusb_cmd_r_eot(CalcHandle *h)
1323
DUSBVirtualPacket* pkt;
1328
ticalcs_critical("%s: h is NULL", __FUNCTION__);
1329
return ERR_INVALID_HANDLE;
1332
pkt = dusb_vtl_pkt_new(0, 0);
1334
retval = dusb_recv_data(h, pkt);
1340
if(pkt->type == DUSB_VPKT_ERROR)
1342
retval = ERR_CALC_ERROR2 + err_code(pkt);
1345
else if(pkt->type != DUSB_VPKT_EOT)
1347
retval = ERR_INVALID_PACKET;
1353
dusb_vtl_pkt_del(pkt);
1359
TIEXPORT3 int TICALL dusb_cmd_s_error(CalcHandle *h, uint16_t code)
1361
DUSBVirtualPacket* pkt;
1366
ticalcs_critical("%s: h is NULL", __FUNCTION__);
1367
return ERR_INVALID_HANDLE;
1370
pkt = dusb_vtl_pkt_new(2, DUSB_VPKT_ERROR);
1372
pkt->data[0] = MSB(code);
1373
pkt->data[1] = LSB(code);
1374
retval = dusb_send_data(h, pkt);
1376
dusb_vtl_pkt_del(pkt);
1377
ticalcs_info(" code = %04x", code);