~ubuntu-branches/ubuntu/trusty/libticalcs/trusty-proposed

« back to all changes in this revision

Viewing changes to src/nsp_vpkt.c

  • Committer: Package Import Robot
  • Author(s): Andreas B. Mundt
  • Date: 2013-08-27 19:58:21 UTC
  • mfrom: (2.1.2 sid)
  • Revision ID: package-import@ubuntu.com-20130827195821-biurlicyqb65gj3g
Tags: 1.1.8+dfsg2-2
* Provide original upstream source, but patch away pre-compiled
  binaries to be policy-compliant.
* Remove unnecessary dependency on 'autopoint', use autoreconf.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Hey EMACS -*- linux-c -*- */
2
 
/* $Id: cmd84p.c 2077 2006-03-31 21:16:19Z roms $ */
3
 
 
4
 
/*  libticalcs - Ti Calculator 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
19
 
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
 
 */
21
 
 
22
 
/*
23
 
        This unit manages virtual packets from/to NSPire (DirectLink).
24
 
        Virtual packets are fragmented into one or more raw packets.
25
 
 
26
 
        Please note this unit does not fully implement the NSpire protocol. It assumes
27
 
        there is one Nspire which is not exposing services. This assumption allows to 
28
 
        work in a linear fashion although we need sometimes some nasty hacks (LOGIN for
29
 
        instance).
30
 
 
31
 
        A better unit should implement a kind of daemon listening on all ports and launching
32
 
        a thread for each connection attempt. This way is fully parallelized but need a state
33
 
        machine and so more (complex) code. Maybe later...
34
 
*/
35
 
 
36
 
#include <stdlib.h>
37
 
#include <string.h>
38
 
 
39
 
#include "ticalcs.h"
40
 
#include "logging.h"
41
 
#include "error.h"
42
 
#include "macros.h"
43
 
 
44
 
#include "nsp_rpkt.h"
45
 
#include "nsp_vpkt.h"
46
 
 
47
 
// Type to string
48
 
 
49
 
static const ServiceName sid_types[] = 
50
 
{
51
 
        { 0x00FE, "Reception Acknowledgment" },
52
 
        { 0x00FF, "Reception Ack" },
53
 
        { 0x4001, "Null" },
54
 
        { 0x4002, "Echo" },
55
 
        { 0x4003, "Device Address Request/Assignment" },
56
 
        { 0x4020, "Device Information" },
57
 
        { 0x4021, "Screen Capture" },
58
 
        { 0x4024, "Screen Capture w/ RLE" },
59
 
        { 0x4050, "Login" },
60
 
        { 0x4060, "File Management" },
61
 
        { 0x4080, "OS Installation" },
62
 
        { 0x40DE, "Service Disconnect" },
63
 
        { -1, NULL},
64
 
};
65
 
 
66
 
const char* nsp_sid2name(uint16_t id)
67
 
{
68
 
        const ServiceName *p;
69
 
 
70
 
        for(p = sid_types; p->name != NULL; p++)
71
 
                if(p->id == id)
72
 
                        return p->name;
73
 
 
74
 
        return "unknown: not listed";
75
 
}
76
 
 
77
 
// Creation/Destruction/Garbage Collecting of packets
78
 
 
79
 
static GList *vtl_pkt_list = NULL;
80
 
 
81
 
VirtualPacket*  nsp_vtl_pkt_new_ex(uint32_t size, uint16_t src_addr, uint16_t src_port, uint16_t dst_addr, uint16_t dst_port)
82
 
{
83
 
        VirtualPacket* vtl = g_malloc0(sizeof(VirtualPacket));
84
 
 
85
 
        vtl->src_addr = src_addr;
86
 
        vtl->src_port = src_port;
87
 
        vtl->dst_addr = dst_addr;
88
 
        vtl->dst_port = dst_port;
89
 
        vtl->size = size;
90
 
        vtl->data = g_malloc0(size+1);
91
 
 
92
 
        vtl_pkt_list = g_list_append(vtl_pkt_list, vtl);
93
 
 
94
 
        return vtl;
95
 
}
96
 
 
97
 
VirtualPacket*  nsp_vtl_pkt_new(void)
98
 
{
99
 
        return nsp_vtl_pkt_new_ex(0, 0, 0, 0, 0);
100
 
}
101
 
 
102
 
void                    nsp_vtl_pkt_del(VirtualPacket* vtl)
103
 
{
104
 
        vtl_pkt_list = g_list_remove(vtl_pkt_list, vtl);
105
 
 
106
 
        g_free(vtl->data);
107
 
        g_free(vtl);
108
 
}
109
 
 
110
 
void                    nsp_vtl_pkt_purge(void)
111
 
{
112
 
        g_list_foreach(vtl_pkt_list, (GFunc)nsp_vtl_pkt_del, NULL);
113
 
        g_list_free(vtl_pkt_list);
114
 
        vtl_pkt_list = NULL;
115
 
}
116
 
 
117
 
// Session Management
118
 
 
119
 
uint16_t        nsp_src_port = 0x8001;
120
 
uint16_t        nsp_dst_port = PORT_ADDR_REQUEST;
121
 
 
122
 
int nsp_session_open(CalcHandle *h, uint16_t port)
123
 
{
124
 
        nsp_src_port++;
125
 
        nsp_dst_port = port;
126
 
 
127
 
        ticalcs_info("  opening session from port #%04x to port #%04x:", nsp_src_port, nsp_dst_port);
128
 
 
129
 
        return 0;
130
 
}
131
 
 
132
 
int nsp_session_close(CalcHandle *h)
133
 
{
134
 
        ticalcs_info("  closed session from port #%04x to port #%04x:", nsp_src_port, nsp_dst_port);
135
 
 
136
 
        TRYF(nsp_send_disconnect(h));
137
 
        TRYF(nsp_recv_ack(h));
138
 
 
139
 
        nsp_dst_port = PORT_ADDR_REQUEST;
140
 
 
141
 
        return 0;
142
 
}
143
 
 
144
 
// Address Request/Assignment
145
 
 
146
 
int nsp_addr_request(CalcHandle *h)
147
 
{
148
 
        extern uint8_t nsp_seq_pc;
149
 
        RawPacket pkt = {0};
150
 
 
151
 
        // Reset connection so that device send an address request packet
152
 
        // Warning: you need a modified libusb-win32 library (see ticables2/src/win32/usb/libusb-win32.html)
153
 
        TRYC(h->cable->cable->reset(h->cable));
154
 
        nsp_seq_pc = 1;
155
 
 
156
 
        ticalcs_info("  device address request:");
157
 
 
158
 
        TRYF(nsp_recv(h, &pkt));
159
 
        
160
 
        if(pkt.src_port != PORT_ADDR_ASSIGN)
161
 
                return ERR_INVALID_PACKET;
162
 
        if(pkt.dst_port != PORT_ADDR_REQUEST)
163
 
                return ERR_INVALID_PACKET;
164
 
 
165
 
        return 0;
166
 
}
167
 
 
168
 
int nsp_addr_assign(CalcHandle *h, uint16_t addr)
169
 
{
170
 
        RawPacket pkt = {0};
171
 
 
172
 
        ticalcs_info("  assigning address %04x:", addr);
173
 
 
174
 
        pkt.data_size = 4;
175
 
        pkt.src_addr = NSP_SRC_ADDR;
176
 
        pkt.src_port = PORT_ADDR_ASSIGN;
177
 
        pkt.dst_addr = NSP_DEV_ADDR;
178
 
        pkt.dst_port = PORT_ADDR_ASSIGN;
179
 
        pkt.data[0] = MSB(addr);
180
 
        pkt.data[1] = LSB(addr);
181
 
        pkt.data[2] = 0xFF;
182
 
        pkt.data[3] = 0x00;
183
 
        TRYF(nsp_send(h, &pkt));
184
 
 
185
 
        return 0;
186
 
}
187
 
 
188
 
// Acknowledgement
189
 
 
190
 
int nsp_send_ack(CalcHandle* h)
191
 
{
192
 
        RawPacket pkt = {0};
193
 
 
194
 
        ticalcs_info("  sending ack:");
195
 
 
196
 
        pkt.data_size = 2;
197
 
        pkt.src_addr = NSP_SRC_ADDR;
198
 
        pkt.src_port = PORT_PKT_ACK2;
199
 
        pkt.dst_addr = NSP_DEV_ADDR;
200
 
        pkt.dst_port = nsp_dst_port;
201
 
        pkt.data[0] = MSB(nsp_src_port);
202
 
        pkt.data[1] = LSB(nsp_src_port);
203
 
        TRYF(nsp_send(h, &pkt));
204
 
 
205
 
        return 0;
206
 
}
207
 
 
208
 
int nsp_send_nack(CalcHandle* h)
209
 
{
210
 
        RawPacket pkt = {0};
211
 
 
212
 
        ticalcs_info("  sending nAck:");
213
 
 
214
 
        pkt.data_size = 2;
215
 
        pkt.src_addr = NSP_SRC_ADDR;
216
 
        pkt.src_port = PORT_PKT_NACK;
217
 
        pkt.dst_addr = NSP_DEV_ADDR;
218
 
        pkt.dst_port = nsp_dst_port;
219
 
        pkt.data[0] = MSB(PORT_LOGIN);
220
 
        pkt.data[1] = LSB(PORT_LOGIN);
221
 
        TRYF(nsp_send(h, &pkt));
222
 
 
223
 
        return 0;
224
 
}
225
 
 
226
 
int nsp_send_nack_ex(CalcHandle* h, uint16_t port)
227
 
{
228
 
        RawPacket pkt = {0};
229
 
 
230
 
        ticalcs_info("  sending nAck:");
231
 
 
232
 
        pkt.data_size = 2;
233
 
        pkt.src_addr = NSP_SRC_ADDR;
234
 
        pkt.src_port = PORT_PKT_NACK;
235
 
        pkt.dst_addr = NSP_DEV_ADDR;
236
 
        pkt.dst_port = port;
237
 
        pkt.data[0] = MSB(PORT_LOGIN);
238
 
        pkt.data[1] = LSB(PORT_LOGIN);
239
 
        TRYF(nsp_send(h, &pkt));
240
 
 
241
 
        return 0;
242
 
}
243
 
 
244
 
int nsp_recv_ack(CalcHandle *h)
245
 
{
246
 
        RawPacket pkt = {0};
247
 
        uint16_t addr;
248
 
 
249
 
        ticalcs_info("  receiving ack:");
250
 
 
251
 
        TRYF(nsp_recv(h, &pkt));
252
 
        
253
 
        if(pkt.src_port != PORT_PKT_ACK2)
254
 
                return ERR_INVALID_PACKET;
255
 
        if(pkt.dst_port != nsp_src_port)
256
 
                return ERR_INVALID_PACKET;
257
 
 
258
 
        addr = (pkt.data[0] << 8) | pkt.data[1];
259
 
        if(addr != nsp_dst_port)
260
 
                return ERR_INVALID_PACKET;
261
 
 
262
 
        if(pkt.ack != 0x0A)
263
 
                return ERR_INVALID_PACKET;
264
 
 
265
 
        return 0;
266
 
}
267
 
 
268
 
// Service Disconnection
269
 
 
270
 
int nsp_send_disconnect(CalcHandle *h)
271
 
{
272
 
        RawPacket pkt = {0};
273
 
 
274
 
        ticalcs_info("  disconnecting from service #%04x:", nsp_dst_port);
275
 
 
276
 
        pkt.data_size = 2;
277
 
        pkt.src_addr = NSP_SRC_ADDR;
278
 
        pkt.src_port = PORT_DISCONNECT;
279
 
        pkt.dst_addr = NSP_DEV_ADDR;
280
 
        pkt.dst_port = nsp_dst_port;
281
 
        pkt.data[0] = MSB(nsp_src_port);
282
 
        pkt.data[1] = LSB(nsp_src_port);
283
 
        TRYF(nsp_send(h, &pkt));
284
 
 
285
 
        return 0;
286
 
}
287
 
 
288
 
int nsp_recv_disconnect(CalcHandle *h)
289
 
{
290
 
        RawPacket pkt = {0};
291
 
        uint16_t addr;
292
 
 
293
 
        ticalcs_info("  receiving disconnect:");
294
 
 
295
 
        TRYF(nsp_recv(h, &pkt));
296
 
 
297
 
        if(pkt.src_port != PORT_DISCONNECT)
298
 
                return ERR_INVALID_PACKET;
299
 
 
300
 
        // nasty hack
301
 
        nsp_dst_port = (pkt.data[0] << 8) | pkt.data[1];
302
 
        addr = pkt.dst_port;
303
 
 
304
 
        // nasty hack
305
 
        {
306
 
                RawPacket pkt = {0};
307
 
 
308
 
                ticalcs_info("  sending ack:");
309
 
                
310
 
                pkt.data_size = 2;
311
 
                pkt.src_addr = NSP_SRC_ADDR;
312
 
                pkt.src_port = PORT_PKT_ACK2;
313
 
                pkt.dst_addr = NSP_DEV_ADDR;
314
 
                pkt.dst_port = nsp_dst_port;
315
 
                pkt.data[0] = MSB(addr);
316
 
                pkt.data[1] = LSB(addr);
317
 
                TRYF(nsp_send(h, &pkt));
318
 
        }
319
 
 
320
 
        return 0;
321
 
}
322
 
 
323
 
// Fragmenting of packets
324
 
 
325
 
int nsp_send_data(CalcHandle *h, VirtualPacket *vtl)
326
 
{
327
 
        RawPacket raw = {0};
328
 
        int i, r, q;
329
 
        long offset = 0;
330
 
 
331
 
        raw.src_addr = vtl->src_addr;
332
 
        raw.src_port = vtl->src_port;
333
 
        raw.dst_addr = vtl->dst_addr;
334
 
        raw.dst_port = vtl->dst_port;
335
 
 
336
 
        q = (vtl->size - offset) / (DATA_SIZE-1);
337
 
        r = (vtl->size - offset) % (DATA_SIZE-1);
338
 
 
339
 
        for(i = 1; i <= q; i++)
340
 
        {
341
 
                raw.data_size = DATA_SIZE;
342
 
                raw.data[0] = vtl->cmd;
343
 
                memcpy(raw.data + 1, vtl->data + offset, DATA_SIZE-1);
344
 
                offset += DATA_SIZE-1;
345
 
 
346
 
                TRYF(nsp_send(h, &raw));
347
 
                
348
 
                if(raw.src_port != PORT_ADDR_ASSIGN && raw.dst_port != PORT_ADDR_REQUEST)
349
 
                        TRYF(nsp_recv_ack(h));
350
 
 
351
 
                h->updat->max1 = vtl->size;
352
 
                h->updat->cnt1 += DATA_SIZE;
353
 
                h->updat->pbar();
354
 
        }
355
 
 
356
 
        if(r || !vtl->size)
357
 
        {
358
 
                raw.data_size = r + 1;
359
 
                raw.data[0] = vtl->cmd;
360
 
                memcpy(raw.data + 1, vtl->data + offset, r);
361
 
                offset += r;
362
 
                
363
 
                TRYF(nsp_send(h, &raw));
364
 
 
365
 
                if(raw.src_port != PORT_ADDR_ASSIGN && raw.dst_port != PORT_ADDR_REQUEST)
366
 
                        TRYF(nsp_recv_ack(h));
367
 
        }       
368
 
 
369
 
        return 0;
370
 
}
371
 
 
372
 
// Note: data field may be re-allocated.
373
 
int nsp_recv_data(CalcHandle* h, VirtualPacket* vtl)
374
 
{
375
 
        RawPacket raw = {0};
376
 
        long offset = 0;
377
 
        uint32_t size = vtl->size;
378
 
 
379
 
        vtl->size = 0;
380
 
        vtl->data = malloc(DATA_SIZE);
381
 
 
382
 
        do
383
 
        {
384
 
                TRYF(nsp_recv(h, &raw));
385
 
                vtl->cmd = raw.data[0];
386
 
                vtl->size += raw.data_size-1;
387
 
 
388
 
                vtl->data = realloc(vtl->data, vtl->size);
389
 
                memcpy(vtl->data + offset, &(raw.data[1]), raw.data_size-1);
390
 
                offset += raw.data_size-1;
391
 
 
392
 
                h->updat->max1 = size ? size : vtl->size;
393
 
                h->updat->cnt1 += DATA_SIZE;
394
 
                h->updat->pbar();
395
 
 
396
 
                if(raw.dst_port == PORT_LOGIN)
397
 
                { TRYF(nsp_send_nack_ex(h, raw.src_port)); }
398
 
                else if(raw.src_port != PORT_ADDR_ASSIGN && raw.dst_port != PORT_ADDR_REQUEST)
399
 
                { TRYF(nsp_send_ack(h)); }
400
 
 
401
 
        } while(raw.data_size >= DATA_SIZE);
402
 
 
403
 
        vtl->src_addr = raw.src_addr;
404
 
        vtl->src_port = raw.src_port;
405
 
        vtl->dst_addr = raw.dst_addr;
406
 
        vtl->dst_port = raw.dst_port;
407
 
 
408
 
        return 0;
409
 
}
 
1
/* Hey EMACS -*- linux-c -*- */
 
2
/* $Id: cmd84p.c 2077 2006-03-31 21:16:19Z roms $ */
 
3
 
 
4
/*  libticalcs - Ti Calculator 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
/*
 
23
        This unit manages virtual packets from/to NSPire (DirectLink).
 
24
        Virtual packets are fragmented into one or more raw packets.
 
25
 
 
26
        Please note this unit does not fully implement the NSpire protocol. It assumes
 
27
        there is one Nspire which is not exposing services. This assumption allows to 
 
28
        work in a linear fashion although we need sometimes some nasty hacks (LOGIN for
 
29
        instance).
 
30
 
 
31
        A better unit should implement a kind of daemon listening on all ports and launching
 
32
        a thread for each connection attempt. This way is fully parallelized but need a state
 
33
        machine and so more (complex) code. Maybe later...
 
34
*/
 
35
 
 
36
#include <stdlib.h>
 
37
#include <string.h>
 
38
 
 
39
#include "ticalcs.h"
 
40
#include "logging.h"
 
41
#include "error.h"
 
42
#include "macros.h"
 
43
 
 
44
#include "nsp_vpkt.h"
 
45
 
 
46
// Type to string
 
47
 
 
48
static const NSPServiceName sid_types[] = 
 
49
{
 
50
        { 0x00FE, "Reception Acknowledgment" },
 
51
        { 0x00FF, "Reception Ack" },
 
52
        { 0x4001, "Null" },
 
53
        { 0x4002, "Echo" },
 
54
        { 0x4003, "Device Address Request/Assignment" },
 
55
        { 0x4020, "Device Information" },
 
56
        { 0x4021, "Screen Capture" },
 
57
        { 0x4024, "Screen Capture w/ RLE" },
 
58
        { 0x4042, "Keypresses" },
 
59
        { 0x4050, "Login" },
 
60
        { 0x4060, "File Management" },
 
61
        { 0x4080, "OS Installation" },
 
62
        { 0x40DE, "Service Disconnect" },
 
63
        { -1, NULL},
 
64
};
 
65
 
 
66
TIEXPORT3 const char* TICALL nsp_sid2name(uint16_t id)
 
67
{
 
68
        const NSPServiceName *p;
 
69
 
 
70
        for(p = sid_types; p->name != NULL; p++)
 
71
                if(p->id == id)
 
72
                        return p->name;
 
73
 
 
74
        return "unknown: not listed";
 
75
}
 
76
 
 
77
// Creation/Destruction/Garbage Collecting of packets
 
78
 
 
79
static GList *vtl_pkt_list = NULL;
 
80
 
 
81
TIEXPORT3 NSPVirtualPacket* TICALL nsp_vtl_pkt_new_ex(uint32_t size, uint16_t src_addr, uint16_t src_port, uint16_t dst_addr, uint16_t dst_port)
 
82
{
 
83
        NSPVirtualPacket* vtl = g_malloc0(sizeof(NSPVirtualPacket)); // aborts the program if it fails.
 
84
 
 
85
        vtl->src_addr = src_addr;
 
86
        vtl->src_port = src_port;
 
87
        vtl->dst_addr = dst_addr;
 
88
        vtl->dst_port = dst_port;
 
89
        vtl->size = size;
 
90
        vtl->data = g_malloc0(size+1); // aborts the program if it fails.
 
91
 
 
92
        vtl_pkt_list = g_list_append(vtl_pkt_list, vtl);
 
93
 
 
94
        return vtl;
 
95
}
 
96
 
 
97
TIEXPORT3 NSPVirtualPacket* TICALL nsp_vtl_pkt_new(void)
 
98
{
 
99
        return nsp_vtl_pkt_new_ex(0, 0, 0, 0, 0);
 
100
}
 
101
 
 
102
TIEXPORT3 void TICALL nsp_vtl_pkt_del(NSPVirtualPacket* vtl)
 
103
{
 
104
        if (vtl != NULL)
 
105
        {
 
106
                vtl_pkt_list = g_list_remove(vtl_pkt_list, vtl);
 
107
 
 
108
                g_free(vtl->data);
 
109
                g_free(vtl);
 
110
        }
 
111
        else
 
112
        {
 
113
                ticalcs_critical("%s: vtl is NULL", __FUNCTION__);
 
114
        }
 
115
}
 
116
 
 
117
void nsp_vtl_pkt_purge(void)
 
118
{
 
119
        g_list_foreach(vtl_pkt_list, (GFunc)nsp_vtl_pkt_del, NULL);
 
120
        g_list_free(vtl_pkt_list);
 
121
        vtl_pkt_list = NULL;
 
122
}
 
123
 
 
124
// Session Management
 
125
 
 
126
uint16_t        nsp_src_port = 0x8001;
 
127
uint16_t        nsp_dst_port = NSP_PORT_ADDR_REQUEST;
 
128
 
 
129
TIEXPORT3 int TICALL nsp_session_open(CalcHandle *h, uint16_t port)
 
130
{
 
131
        if (h == NULL)
 
132
        {
 
133
                ticalcs_critical("%s: h is NULL", __FUNCTION__);
 
134
                return ERR_INVALID_HANDLE;
 
135
        }
 
136
 
 
137
        nsp_src_port++;
 
138
        nsp_dst_port = port;
 
139
 
 
140
        ticalcs_info("  opening session from port #%04x to port #%04x:", nsp_src_port, nsp_dst_port);
 
141
 
 
142
        return 0;
 
143
}
 
144
 
 
145
TIEXPORT3 int TICALL nsp_session_close(CalcHandle *h)
 
146
{
 
147
        if (h == NULL)
 
148
        {
 
149
                ticalcs_critical("%s: h is NULL", __FUNCTION__);
 
150
                return ERR_INVALID_HANDLE;
 
151
        }
 
152
 
 
153
        ticalcs_info("  closed session from port #%04x to port #%04x:", nsp_src_port, nsp_dst_port);
 
154
 
 
155
        TRYF(nsp_send_disconnect(h));
 
156
        TRYF(nsp_recv_ack(h));
 
157
 
 
158
        nsp_dst_port = NSP_PORT_ADDR_REQUEST;
 
159
 
 
160
        return 0;
 
161
}
 
162
 
 
163
// Address Request/Assignment
 
164
 
 
165
TIEXPORT3 int TICALL nsp_addr_request(CalcHandle *h)
 
166
{
 
167
        extern uint8_t nsp_seq_pc;
 
168
        NSPRawPacket pkt;
 
169
 
 
170
        if (h == NULL)
 
171
        {
 
172
                ticalcs_critical("%s: h is NULL", __FUNCTION__);
 
173
                return ERR_INVALID_HANDLE;
 
174
        }
 
175
 
 
176
        memset(&pkt, 0, sizeof(pkt));
 
177
 
 
178
        // Reset connection so that device send an address request packet
 
179
        TRYC(h->cable->cable->reset(h->cable));
 
180
        nsp_seq_pc = 1;
 
181
 
 
182
        ticalcs_info("  device address request:");
 
183
 
 
184
        TRYF(nsp_recv(h, &pkt));
 
185
        
 
186
        if(pkt.src_port != NSP_PORT_ADDR_ASSIGN)
 
187
                return ERR_INVALID_PACKET;
 
188
        if(pkt.dst_port != NSP_PORT_ADDR_REQUEST)
 
189
                return ERR_INVALID_PACKET;
 
190
 
 
191
        return 0;
 
192
}
 
193
 
 
194
TIEXPORT3 int TICALL nsp_addr_assign(CalcHandle *h, uint16_t addr)
 
195
{
 
196
        NSPRawPacket pkt;
 
197
 
 
198
        if (h == NULL)
 
199
        {
 
200
                ticalcs_critical("%s: h is NULL", __FUNCTION__);
 
201
                return ERR_INVALID_HANDLE;
 
202
        }
 
203
 
 
204
        ticalcs_info("  assigning address %04x:", addr);
 
205
 
 
206
        memset(&pkt, 0, sizeof(pkt));
 
207
        pkt.data_size = 4;
 
208
        pkt.src_addr = NSP_SRC_ADDR;
 
209
        pkt.src_port = NSP_PORT_ADDR_ASSIGN;
 
210
        pkt.dst_addr = NSP_DEV_ADDR;
 
211
        pkt.dst_port = NSP_PORT_ADDR_ASSIGN;
 
212
        pkt.data[0] = MSB(addr);
 
213
        pkt.data[1] = LSB(addr);
 
214
        pkt.data[2] = 0xFF;
 
215
        pkt.data[3] = 0x00;
 
216
        TRYF(nsp_send(h, &pkt));
 
217
 
 
218
        return 0;
 
219
}
 
220
 
 
221
// Acknowledgement
 
222
 
 
223
TIEXPORT3 int TICALL nsp_send_ack(CalcHandle* h)
 
224
{
 
225
        NSPRawPacket pkt;
 
226
 
 
227
        if (h == NULL)
 
228
        {
 
229
                ticalcs_critical("%s: h is NULL", __FUNCTION__);
 
230
                return ERR_INVALID_HANDLE;
 
231
        }
 
232
 
 
233
        ticalcs_info("  sending ack:");
 
234
 
 
235
        memset(&pkt, 0, sizeof(pkt));
 
236
        pkt.data_size = 2;
 
237
        pkt.src_addr = NSP_SRC_ADDR;
 
238
        pkt.src_port = NSP_PORT_PKT_ACK2;
 
239
        pkt.dst_addr = NSP_DEV_ADDR;
 
240
        pkt.dst_port = nsp_dst_port;
 
241
        pkt.data[0] = MSB(nsp_src_port);
 
242
        pkt.data[1] = LSB(nsp_src_port);
 
243
        TRYF(nsp_send(h, &pkt));
 
244
 
 
245
        return 0;
 
246
}
 
247
 
 
248
TIEXPORT3 int TICALL nsp_send_nack(CalcHandle* h)
 
249
{
 
250
        NSPRawPacket pkt;
 
251
 
 
252
        if (h == NULL)
 
253
        {
 
254
                ticalcs_critical("%s: h is NULL", __FUNCTION__);
 
255
                return ERR_INVALID_HANDLE;
 
256
        }
 
257
 
 
258
        ticalcs_info("  sending nAck:");
 
259
 
 
260
        memset(&pkt, 0, sizeof(pkt));
 
261
        pkt.data_size = 2;
 
262
        pkt.src_addr = NSP_SRC_ADDR;
 
263
        pkt.src_port = NSP_PORT_PKT_NACK;
 
264
        pkt.dst_addr = NSP_DEV_ADDR;
 
265
        pkt.dst_port = nsp_dst_port;
 
266
        pkt.data[0] = MSB(NSP_PORT_LOGIN);
 
267
        pkt.data[1] = LSB(NSP_PORT_LOGIN);
 
268
        TRYF(nsp_send(h, &pkt));
 
269
 
 
270
        return 0;
 
271
}
 
272
 
 
273
TIEXPORT3 int TICALL nsp_send_nack_ex(CalcHandle* h, uint16_t port)
 
274
{
 
275
        NSPRawPacket pkt;
 
276
 
 
277
        if (h == NULL)
 
278
        {
 
279
                ticalcs_critical("%s: h is NULL", __FUNCTION__);
 
280
                return ERR_INVALID_HANDLE;
 
281
        }
 
282
 
 
283
        ticalcs_info("  sending nAck:");
 
284
 
 
285
        memset(&pkt, 0, sizeof(pkt));
 
286
        pkt.data_size = 2;
 
287
        pkt.src_addr = NSP_SRC_ADDR;
 
288
        pkt.src_port = NSP_PORT_PKT_NACK;
 
289
        pkt.dst_addr = NSP_DEV_ADDR;
 
290
        pkt.dst_port = port;
 
291
        pkt.data[0] = MSB(NSP_PORT_LOGIN);
 
292
        pkt.data[1] = LSB(NSP_PORT_LOGIN);
 
293
        TRYF(nsp_send(h, &pkt));
 
294
 
 
295
        return 0;
 
296
}
 
297
 
 
298
TIEXPORT3 int TICALL nsp_recv_ack(CalcHandle *h)
 
299
{
 
300
        NSPRawPacket pkt;
 
301
        uint16_t addr;
 
302
        int ret = 0;
 
303
 
 
304
        if (h == NULL)
 
305
        {
 
306
                ticalcs_critical("%s: h is NULL", __FUNCTION__);
 
307
                return ERR_INVALID_HANDLE;
 
308
        }
 
309
 
 
310
        ticalcs_info("  receiving ack:");
 
311
 
 
312
        memset(&pkt, 0, sizeof(pkt));
 
313
 
 
314
        TRYF(nsp_recv(h, &pkt));
 
315
 
 
316
        if(pkt.src_port != NSP_PORT_PKT_ACK2)
 
317
        {
 
318
                ticalcs_info("XXX weird src_port\n");
 
319
                ret = ERR_INVALID_PACKET;
 
320
        }
 
321
        if(pkt.dst_port != nsp_src_port)
 
322
        {
 
323
                ticalcs_info("XXX weird .dst_port\n");
 
324
                ret = ERR_INVALID_PACKET;
 
325
        }
 
326
 
 
327
        if (pkt.data_size >= 2)
 
328
        {
 
329
                addr = (pkt.data[0] << 8) | pkt.data[1];
 
330
                if(addr != nsp_dst_port)
 
331
                {
 
332
                        ticalcs_info("XXX weird addr\n");
 
333
                        ret = ERR_INVALID_PACKET;
 
334
                }
 
335
        }
 
336
        else
 
337
        {
 
338
                ticalcs_info("XXX weird addr\n");
 
339
                ret = ERR_INVALID_PACKET;
 
340
        }
 
341
 
 
342
        if(pkt.ack != 0x0A)
 
343
        {
 
344
                ticalcs_info("XXX weird .ack\n");
 
345
                ret = ERR_INVALID_PACKET;
 
346
        }
 
347
 
 
348
        return ret;
 
349
}
 
350
 
 
351
// Service Disconnection
 
352
 
 
353
TIEXPORT3 int TICALL nsp_send_disconnect(CalcHandle *h)
 
354
{
 
355
        NSPRawPacket pkt;
 
356
 
 
357
        if (h == NULL)
 
358
        {
 
359
                ticalcs_critical("%s: h is NULL", __FUNCTION__);
 
360
                return ERR_INVALID_HANDLE;
 
361
        }
 
362
 
 
363
        ticalcs_info("  disconnecting from service #%04x:", nsp_dst_port);
 
364
 
 
365
        memset(&pkt, 0, sizeof(pkt));
 
366
        pkt.data_size = 2;
 
367
        pkt.src_addr = NSP_SRC_ADDR;
 
368
        pkt.src_port = NSP_PORT_DISCONNECT;
 
369
        pkt.dst_addr = NSP_DEV_ADDR;
 
370
        pkt.dst_port = nsp_dst_port;
 
371
        pkt.data[0] = MSB(nsp_src_port);
 
372
        pkt.data[1] = LSB(nsp_src_port);
 
373
        TRYF(nsp_send(h, &pkt));
 
374
 
 
375
        return 0;
 
376
}
 
377
 
 
378
TIEXPORT3 int TICALL nsp_recv_disconnect(CalcHandle *h)
 
379
{
 
380
        NSPRawPacket pkt;
 
381
        uint16_t addr;
 
382
 
 
383
        if (h == NULL)
 
384
        {
 
385
                ticalcs_critical("%s: h is NULL", __FUNCTION__);
 
386
                return ERR_INVALID_HANDLE;
 
387
        }
 
388
 
 
389
        ticalcs_info("  receiving disconnect:");
 
390
 
 
391
        memset(&pkt, 0, sizeof(pkt));
 
392
 
 
393
        TRYF(nsp_recv(h, &pkt));
 
394
 
 
395
        if(pkt.src_port != NSP_PORT_DISCONNECT)
 
396
                return ERR_INVALID_PACKET;
 
397
 
 
398
        // nasty hack
 
399
        nsp_dst_port = (pkt.data[0] << 8) | pkt.data[1];
 
400
        addr = pkt.dst_port;
 
401
 
 
402
        // nasty hack
 
403
        {
 
404
                ticalcs_info("  sending ack:");
 
405
 
 
406
                pkt.unused = 0;
 
407
                pkt.data_size = 2;
 
408
                pkt.src_addr = NSP_SRC_ADDR;
 
409
                pkt.src_port = NSP_PORT_PKT_ACK2;
 
410
                pkt.dst_addr = NSP_DEV_ADDR;
 
411
                pkt.dst_port = nsp_dst_port;
 
412
                pkt.data_sum = 0;
 
413
                pkt.ack = 0;
 
414
                pkt.seq = 0;
 
415
                pkt.hdr_sum = 0;
 
416
                pkt.data[0] = MSB(addr);
 
417
                pkt.data[1] = LSB(addr);
 
418
                TRYF(nsp_send(h, &pkt));
 
419
        }
 
420
 
 
421
        return 0;
 
422
}
 
423
 
 
424
// Fragmenting of packets
 
425
 
 
426
TIEXPORT3 int TICALL nsp_send_data(CalcHandle *h, NSPVirtualPacket *vtl)
 
427
{
 
428
        NSPRawPacket raw;
 
429
        int i, r, q;
 
430
        long offset = 0;
 
431
 
 
432
        if (h == NULL)
 
433
        {
 
434
                ticalcs_critical("%s: h is NULL", __FUNCTION__);
 
435
                return ERR_INVALID_HANDLE;
 
436
        }
 
437
        if (vtl == NULL)
 
438
        {
 
439
                ticalcs_critical("%s: vtl is NULL", __FUNCTION__);
 
440
                return ERR_INVALID_PACKET;
 
441
        }
 
442
 
 
443
        memset(&raw, 0, sizeof(raw));
 
444
        raw.src_addr = vtl->src_addr;
 
445
        raw.src_port = vtl->src_port;
 
446
        raw.dst_addr = vtl->dst_addr;
 
447
        raw.dst_port = vtl->dst_port;
 
448
 
 
449
        q = (vtl->size - offset) / (NSP_DATA_SIZE-1);
 
450
        r = (vtl->size - offset) % (NSP_DATA_SIZE-1);
 
451
 
 
452
        for(i = 1; i <= q; i++)
 
453
        {
 
454
                raw.data_size = NSP_DATA_SIZE;
 
455
                raw.data[0] = vtl->cmd;
 
456
                memcpy(raw.data + 1, vtl->data + offset, NSP_DATA_SIZE-1);
 
457
                offset += NSP_DATA_SIZE-1;
 
458
 
 
459
                TRYF(nsp_send(h, &raw));
 
460
                
 
461
                if(raw.src_port != NSP_PORT_ADDR_ASSIGN && raw.dst_port != NSP_PORT_ADDR_REQUEST)
 
462
                        TRYF(nsp_recv_ack(h));
 
463
 
 
464
                h->updat->max1 = vtl->size;
 
465
                h->updat->cnt1 += NSP_DATA_SIZE;
 
466
                h->updat->pbar();
 
467
        }
 
468
 
 
469
        if(r || !vtl->size)
 
470
        {
 
471
                raw.data_size = r + 1;
 
472
                raw.data[0] = vtl->cmd;
 
473
                memcpy(raw.data + 1, vtl->data + offset, r);
 
474
                offset += r;
 
475
                
 
476
                TRYF(nsp_send(h, &raw));
 
477
 
 
478
                if(raw.src_port != NSP_PORT_ADDR_ASSIGN && raw.dst_port != NSP_PORT_ADDR_REQUEST)
 
479
                        TRYF(nsp_recv_ack(h));
 
480
        }       
 
481
 
 
482
        return 0;
 
483
}
 
484
 
 
485
// Note: data field may be re-allocated.
 
486
TIEXPORT3 int TICALL nsp_recv_data(CalcHandle* h, NSPVirtualPacket* vtl)
 
487
{
 
488
        NSPRawPacket raw;
 
489
        long offset = 0;
 
490
        uint32_t size;
 
491
        int err = 0;
 
492
 
 
493
        if (h == NULL)
 
494
        {
 
495
                ticalcs_critical("%s: h is NULL", __FUNCTION__);
 
496
                return ERR_INVALID_HANDLE;
 
497
        }
 
498
        if (vtl == NULL)
 
499
        {
 
500
                ticalcs_critical("%s: vtl is NULL", __FUNCTION__);
 
501
                return ERR_INVALID_PACKET;
 
502
        }
 
503
 
 
504
        memset(&raw, 0, sizeof(raw));
 
505
 
 
506
        size = vtl->size;
 
507
        vtl->size = 0;
 
508
        vtl->data = g_malloc(NSP_DATA_SIZE);
 
509
 
 
510
        if (vtl->data)
 
511
        {
 
512
                for(;;)
 
513
                {
 
514
                        err = nsp_recv(h, &raw);
 
515
                        if (err)
 
516
                        {
 
517
                                break;
 
518
                        }
 
519
                        if (raw.data_size > 0)
 
520
                        {
 
521
                                vtl->cmd = raw.data[0];
 
522
                                vtl->size += raw.data_size-1;
 
523
 
 
524
                                vtl->data = g_realloc(vtl->data, vtl->size);
 
525
                                memcpy(vtl->data + offset, &(raw.data[1]), raw.data_size-1);
 
526
                                offset += raw.data_size-1;
 
527
 
 
528
                                h->updat->max1 = size ? size : vtl->size;
 
529
                                h->updat->cnt1 += NSP_DATA_SIZE;
 
530
                                h->updat->pbar();
 
531
                        }
 
532
 
 
533
                        if(raw.dst_port == NSP_PORT_LOGIN)
 
534
                        {
 
535
                                err = nsp_send_nack_ex(h, raw.src_port);
 
536
                                if (err)
 
537
                                {
 
538
                                        break;
 
539
                                }
 
540
                        }
 
541
                        else if(raw.src_port != NSP_PORT_ADDR_ASSIGN && raw.dst_port != NSP_PORT_ADDR_REQUEST)
 
542
                        {
 
543
                                err = nsp_send_ack(h);
 
544
                                if (err)
 
545
                                {
 
546
                                        break;
 
547
                                }
 
548
                        }
 
549
 
 
550
                        if (raw.data_size < NSP_DATA_SIZE)
 
551
                                break;
 
552
                        if (size && vtl->size == size)
 
553
                                break;
 
554
                }
 
555
        }
 
556
 
 
557
        vtl->src_addr = raw.src_addr;
 
558
        vtl->src_port = raw.src_port;
 
559
        vtl->dst_addr = raw.dst_addr;
 
560
        vtl->dst_port = raw.dst_port;
 
561
 
 
562
        return err;
 
563
}