Subversion Repositories freemyipod

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
892 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
6
//    This file is part of emCORE.
7
//
8
//    emCORE is free software: you can redistribute it and/or
9
//    modify it under the terms of the GNU General Public License as
10
//    published by the Free Software Foundation, either version 2 of the
11
//    License, or (at your option) any later version.
12
//
13
//    emCORE is distributed in the hope that it will be useful,
14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
17
//
18
//    You should have received a copy of the GNU General Public License along
19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
20
//
21
//
22
 
23
 
24
#include "global.h"
25
#include "usbdebug.h"
26
#include "panic.h"
27
#include "usb.h"
28
#include "thread.h"
29
#include "console.h"
30
#include "util.h"
31
#include "contextswitch.h"
32
#include "power.h"
33
#include "mmu.h"
34
#include "shutdown.h"
35
#include "execimage.h"
36
#ifdef HAVE_I2C
37
#include "i2c.h"
38
#endif
39
#ifdef HAVE_BOOTFLASH
40
#include "bootflash.h"
41
#endif
42
#ifdef HAVE_HWKEYAES
43
#include "hwkeyaes.h"
44
#endif
45
#ifdef HAVE_HMACSHA1
46
#include "hmacsha1.h"
47
#endif
48
#ifdef USB_HAVE_TARGET_SPECIFIC_REQUESTS
49
#include "usbtarget.h"
50
#endif
51
#ifdef HAVE_STORAGE
52
#include "storage.h"
53
#include "disk.h"
54
#include "file.h"
55
#include "dir.h"
56
#include "libc/include/errno.h"
57
#endif
58
 
59
 
60
static uint32_t dbgbuf[16] CACHEALIGN_ATTR;
61
 
62
enum dbgstate_t
63
{
64
    DBGSTATE_IDLE = 0,
65
    DBGSTATE_SETUP,
66
    DBGSTATE_WRITE_MEM,
896 theseven 67
    DBGSTATE_WRITE_CONSOLE,
892 theseven 68
    DBGSTATE_ASYNC,
69
    DBGSTATE_RESPOND,
896 theseven 70
    DBGSTATE_READ_CONSOLE,
892 theseven 71
};
72
 
73
static struct scheduler_thread dbgthread_handle IBSS_ATTR;
74
static uint32_t dbgstack[0x200] STACK_ATTR;
75
struct wakeup dbgwakeup IBSS_ATTR;
76
static bool dbgenabled IBSS_ATTR;
77
static bool dbgbusy IBSS_ATTR;
78
static const struct usb_instance* dbgusb IBSS_ATTR;
79
static enum dbgstate_t dbgstate IBSS_ATTR;
80
static void* dbgmemaddr IBSS_ATTR;
81
static uint32_t dbgmemlen IBSS_ATTR;
82
static char dbgconsendbuf[4096];
83
static char dbgconrecvbuf[1024];
84
static int dbgconsendreadidx IBSS_ATTR;
85
static int dbgconsendwriteidx IBSS_ATTR;
86
static int dbgconrecvreadidx IBSS_ATTR;
87
static int dbgconrecvwriteidx IBSS_ATTR;
88
static struct wakeup dbgconsendwakeup IBSS_ATTR;
89
static struct wakeup dbgconrecvwakeup IBSS_ATTR;
90
static bool dbgconsoleattached IBSS_ATTR;
91
 
92
static const char dbgconoverflowstr[] = "\n\n[overflowed]\n\n";
93
 
94
extern int _poolstart;   // These aren't ints at all, but gcc complains about void types being
95
extern int _poolend;     // used here, and we only need the address, so just make it happy...
96
 
97
 
98
void reset() __attribute__((noreturn));
99
 
100
void usbdebug_enable(const struct usb_instance* data, int interface, int altsetting)
101
{
102
    dbgusb = data;
103
    dbgstate = DBGSTATE_IDLE;
104
    dbgenabled = true;
105
}
106
 
107
void usbdebug_disable(const struct usb_instance* data, int interface, int altsetting)
108
{
109
    dbgenabled = false;
110
    dbgstate = DBGSTATE_IDLE;
111
}
112
 
113
bool usbdebug_handle_data(const struct usb_instance* data, int bytesleft)
114
{
115
    uint32_t* buf = (uint32_t*)data->buffer->raw;
116
    usb_ep0_start_rx(dbgusb, 0, NULL);
117
    switch (dbgstate)
118
    {
119
    case DBGSTATE_SETUP:
120
        switch (buf[0])
121
        {
122
        case 1:  // GET INFO
123
            dbgbuf[0] = 1;
124
            switch (buf[1])
125
            {
126
            case 0:  // GET VERSION INFO
127
                dbgbuf[1] = VERSION_SVN_INT;
128
                dbgbuf[2] = VERSION_MAJOR | (VERSION_MINOR << 8) | (VERSION_PATCH << 16) | (2 << 24);
129
                dbgbuf[3] = PLATFORM_ID;
130
                break;
131
            case 1:  // GET USER MEMORY INFO
132
                dbgbuf[1] = (uint32_t)&_poolstart;
133
                dbgbuf[2] = (uint32_t)&_poolend;
134
                break;
135
            default:
136
                dbgbuf[0] = 2;
137
            }
138
            break;
139
        case 4:  // READ MEMORY
140
            dbgbuf[0] = 1;
141
            dbgmemaddr = (void*)buf[1];
142
            dbgmemlen = buf[2];
143
            break;
144
        case 5:  // WRITE MEMORY
145
        {
146
            dbgmemaddr = (void*)buf[1];
147
            dbgmemlen = buf[2];
148
            int len = MIN(48, dbgmemlen);
149
            dbgmemlen -= len;
150
            memcpy(dbgmemaddr, &buf[4], len);
151
            if (dbgmemlen)
152
            {
153
                dbgmemaddr += len;
154
                dbgstate = DBGSTATE_WRITE_MEM;
155
                usb_ep0_start_rx(dbgusb, 1, usbdebug_handle_data);
156
                return true;
157
            }
158
            dbgbuf[0] = 1;
159
            break;
160
        }
161
        case 10:  // READ CONSOLE
896 theseven 162
            dbgmemaddr = (void*)buf[1];
163
            dbgstate = DBGSTATE_READ_CONSOLE;
164
            usb_ep0_start_tx(dbgusb, NULL, 0, true, NULL);
165
            return true;
892 theseven 166
            break;
167
        case 11:  // WRITE CONSOLE
896 theseven 168
        {
169
            int total = 0;
170
            int bytes = dbgconrecvreadidx - dbgconrecvwriteidx - 1;
892 theseven 171
            if (bytes < 0) bytes += sizeof(dbgconrecvbuf);
172
            if (bytes)
173
            {
174
                if (bytes > buf[1]) bytes = buf[1];
896 theseven 175
                total = bytes;
176
                if (bytes > 48) bytes = 48;
892 theseven 177
                int writebytes = bytes;
178
                char* readptr = (char*)&buf[4];
179
                if (dbgconrecvwriteidx + bytes >= sizeof(dbgconrecvbuf))
180
                {
181
                    writebytes = sizeof(dbgconrecvbuf) - dbgconrecvwriteidx;
182
                    memcpy(&dbgconrecvbuf[dbgconrecvwriteidx], readptr, writebytes);
183
                    dbgconrecvwriteidx = 0;
184
                    readptr = &readptr[writebytes];
185
                    writebytes = bytes - writebytes;
186
                }
187
                if (writebytes) memcpy(&dbgconrecvbuf[dbgconrecvwriteidx], readptr, writebytes);
188
                dbgconrecvwriteidx += writebytes;
189
                wakeup_signal(&dbgconrecvwakeup);
190
            }
191
            dbgbuf[0] = 1;
896 theseven 192
            dbgbuf[1] = total;
892 theseven 193
            dbgbuf[2] = sizeof(dbgconrecvbuf);
896 theseven 194
            if (total > 48)
195
            {
196
                dbgmemlen = total - 48;
197
                dbgstate = DBGSTATE_WRITE_CONSOLE;
198
                usb_ep0_start_rx(dbgusb, 1, usbdebug_handle_data);
199
                return true;
200
            }
892 theseven 201
            dbgbuf[3] = dbgconrecvreadidx - dbgconrecvwriteidx - 1;
202
            break;
896 theseven 203
        }
892 theseven 204
        case 15:  // GET PROCESS INFO
205
            dbgbuf[0] = 1;
206
            dbgbuf[1] = SCHEDULER_THREAD_INFO_VERSION;
207
            dbgbuf[2] = (uint32_t)head_thread;
208
            break;
209
        case 16:  // FREEZE SCHEDULER
210
            dbgbuf[1] = scheduler_freeze(buf[1]);
211
            scheduler_switch(NULL, NULL);
212
            dbgbuf[0] = 1;
213
            break;
214
        case 17:  // SUSPEND THREAD
215
            if (buf[1])
216
            {
217
                if (thread_suspend((struct scheduler_thread*)(buf[2])) == ALREADY_SUSPENDED)
218
                    dbgbuf[1] = 1;
219
                else dbgbuf[1] = 0;
220
            }
221
            else
222
            {
223
                if (thread_resume((struct scheduler_thread*)(buf[2])) == ALREADY_RESUMED)
224
                    dbgbuf[1] = 0;
225
                else dbgbuf[1] = 1;
226
            }
227
            dbgbuf[0] = 1;
228
            break;
229
        case 18:  // KILL THREAD
230
            thread_terminate((struct scheduler_thread*)(buf[1]));
231
            dbgbuf[0] = 1;
232
            break;
233
        case 19:  // CREATE THREAD
234
            dbgbuf[0] = 1;
235
            dbgbuf[1] = (uint32_t)thread_create(NULL, (const char*)(buf[1]), (const void*)(buf[2]),
236
                                                (char*)(buf[3]), buf[4], (enum thread_type)buf[5],
237
                                                buf[6], buf[7], (void*)buf[8], (void*)buf[9],
238
                                                (void*)buf[10], (void*)buf[11]);
239
            break;
240
        case 20:  // FLUSH CACHE
241
            clean_dcache();
242
            invalidate_icache();
243
            buf[0] = 1;
244
            break;
245
        case 2:  // RESET
246
            if (!buf[1]) reset();
247
        default:
248
            if (!dbgbusy)
249
            {
250
                memcpy(dbgbuf, buf, 64);
251
                dbgstate = DBGSTATE_ASYNC;
252
                dbgbusy = 1;
253
                wakeup_signal(&dbgwakeup);
254
                return true;
255
            }
256
            buf[0] = 3;
257
            break;
258
        }
259
        break;
260
    case DBGSTATE_WRITE_MEM:
261
    {
896 theseven 262
        int len = MIN(64 - bytesleft, dbgmemlen);
892 theseven 263
        dbgmemlen -= len;
264
        memcpy(dbgmemaddr, buf, len);
896 theseven 265
        if (dbgmemlen && !bytesleft)
892 theseven 266
        {
267
            dbgmemaddr += len;
268
            usb_ep0_start_rx(dbgusb, 1, usbdebug_handle_data);
269
            return true;
270
        }
271
        dbgbuf[0] = 1;
272
        break;
273
    }
896 theseven 274
    case DBGSTATE_WRITE_CONSOLE:
275
    {
276
        int bytes = MIN(64 - bytesleft, dbgmemlen);
277
        dbgmemlen -= bytes;
278
        if (bytes)
279
        {
280
            int writebytes = bytes;
281
            char* readptr = (char*)buf;
282
            if (dbgconrecvwriteidx + bytes >= sizeof(dbgconrecvbuf))
283
            {
284
                writebytes = sizeof(dbgconrecvbuf) - dbgconrecvwriteidx;
285
                memcpy(&dbgconrecvbuf[dbgconrecvwriteidx], readptr, writebytes);
286
                dbgconrecvwriteidx = 0;
287
                readptr = &readptr[writebytes];
288
                writebytes = bytes - writebytes;
289
            }
290
            if (writebytes) memcpy(&dbgconrecvbuf[dbgconrecvwriteidx], readptr, writebytes);
291
            dbgconrecvwriteidx += writebytes;
292
            wakeup_signal(&dbgconrecvwakeup);
293
            if (dbgmemlen && !bytesleft)
294
            {
295
                usb_ep0_start_rx(dbgusb, 1, usbdebug_handle_data);
296
                return true;
297
            }
298
        }
299
        dbgbuf[3] = dbgconrecvreadidx - dbgconrecvwriteidx - 1;
300
        if (dbgbuf[3] < 0) dbgbuf[3] += sizeof(dbgconrecvbuf);
301
    }
892 theseven 302
    default: break;
303
    }
304
    dbgstate = DBGSTATE_RESPOND;
305
    usb_ep0_start_tx(dbgusb, NULL, 0, true, NULL);
306
    return true;
307
}
308
 
896 theseven 309
bool read_console_callback(const struct usb_instance* data, int bytesleft)
310
{
311
    if (bytesleft || !dbgmemaddr) return false;
312
    dbgconsoleattached = true;
313
    int bytes = MIN(64, dbgmemlen);
314
    if (bytes)
315
    {
316
        int readbytes = bytes;
317
        char* outptr = (char*)dbgbuf;
318
        if (dbgconsendreadidx + bytes >= sizeof(dbgconsendbuf))
319
        {
320
            readbytes = sizeof(dbgconsendbuf) - dbgconsendreadidx;
321
            memcpy(outptr, &dbgconsendbuf[dbgconsendreadidx], readbytes);
322
            dbgconsendreadidx = 0;
323
            outptr = &outptr[readbytes];
324
            readbytes = bytes - readbytes;
325
        }
326
        if (readbytes) memcpy(outptr, &dbgconsendbuf[dbgconsendreadidx], readbytes);
327
        dbgconsendreadidx += readbytes;
328
        wakeup_signal(&dbgconsendwakeup);
329
        dbgmemlen -= bytes;
330
    }
331
    bytes = MIN(64, (int)dbgmemaddr);
332
    dbgmemaddr -= bytes;
333
    if (dbgmemaddr)
334
    {
335
        usb_ep0_start_rx(dbgusb, 0, NULL);
336
        usb_ep0_start_tx(dbgusb, dbgbuf, bytes, false, read_console_callback);
337
    }
338
    else usb_ep0_start_tx(dbgusb, dbgbuf, bytes, true, NULL);
339
    return true;
340
}
341
 
892 theseven 342
int usbdebug_handle_setup(const struct usb_instance* data, int interface, union usb_ep0_buffer* request, const void** response)
343
{
344
    int size = -1;
345
    switch (request->setup.bmRequestType.type)
346
    {
347
    case USB_SETUP_BMREQUESTTYPE_TYPE_VENDOR:
348
        switch (request->setup.bRequest.raw)
349
        {
350
        case 0x00:
351
            switch (data->buffer->setup.bmRequestType.direction)
352
            {
353
            case USB_SETUP_BMREQUESTTYPE_DIRECTION_OUT:
354
                dbgstate = DBGSTATE_SETUP;
355
                dbgmemlen = 0;
356
                usb_ep0_start_rx(dbgusb, 1, usbdebug_handle_data);
357
                return -3;
358
            case USB_SETUP_BMREQUESTTYPE_DIRECTION_IN:
359
                switch (dbgstate)
360
                {
361
                case DBGSTATE_RESPOND:
362
                {
363
                    int len = MIN(48, dbgmemlen);
364
                    if (len) memcpy(&dbgbuf[4], dbgmemaddr, len);
365
                    dbgmemlen -= len;
366
                    if (dbgmemlen)
367
                    {
368
                        usb_ep0_start_rx(dbgusb, 0, NULL);
369
                        data->state->ep0_tx_ptr = dbgmemaddr - 16;
370
                        data->state->ep0_tx_len = dbgmemlen;
896 theseven 371
                        usb_ep0_start_tx(dbgusb, dbgbuf, len + 16, false, usb_ep0_tx_callback);
892 theseven 372
                        return -3;
373
                    }
374
                    dbgstate = DBGSTATE_IDLE;
375
                    *response = dbgbuf;
376
                    return len + 16;
377
                }
896 theseven 378
                case DBGSTATE_READ_CONSOLE:
379
                {
380
                    dbgconsoleattached = true;
381
                    dbgmemlen = dbgconsendwriteidx - dbgconsendreadidx;
382
                    if (dbgmemlen < 0) dbgmemlen += sizeof(dbgconsendbuf);
383
                    int used = dbgmemlen;
384
                    if (dbgmemlen > (int)dbgmemaddr) dbgmemlen = (int)dbgmemaddr;
385
                    int bytes = MIN(48, dbgmemlen);
386
                    dbgbuf[0] = 1;
387
                    dbgbuf[1] = dbgmemlen;
388
                    dbgbuf[2] = sizeof(dbgconsendbuf);
389
                    dbgbuf[3] = used - dbgmemlen;
390
                    if (bytes)
391
                    {
392
                        int readbytes = bytes;
393
                        char* outptr = (char*)&dbgbuf[4];
394
                        if (dbgconsendreadidx + bytes >= sizeof(dbgconsendbuf))
395
                        {
396
                            readbytes = sizeof(dbgconsendbuf) - dbgconsendreadidx;
397
                            memcpy(outptr, &dbgconsendbuf[dbgconsendreadidx], readbytes);
398
                            dbgconsendreadidx = 0;
399
                            outptr = &outptr[readbytes];
400
                            readbytes = bytes - readbytes;
401
                        }
402
                        if (readbytes) memcpy(outptr, &dbgconsendbuf[dbgconsendreadidx], readbytes);
403
                        dbgconsendreadidx += readbytes;
404
                        wakeup_signal(&dbgconsendwakeup);
405
                    }
406
                    dbgmemlen -= bytes;
407
                    bytes = MIN(48, (int)dbgmemaddr);
408
                    dbgmemaddr -= bytes;
409
                    if (dbgmemaddr)
410
                    {
411
                        usb_ep0_start_rx(dbgusb, 0, NULL);
412
                        usb_ep0_start_tx(dbgusb, dbgbuf, bytes + 16, false, read_console_callback);
413
                        return -3;
414
                    }
415
                    dbgstate = DBGSTATE_IDLE;
416
                    *response = dbgbuf;
417
                    return bytes + 16;
418
                }
892 theseven 419
                default: return -2;
420
                }
421
                break;
422
            }
423
            break;
424
        default: break;
425
        }
426
        break;
427
        default: break;
428
    }
429
    return size;
430
}
431
 
432
void dbgthread(void* arg0, void* arg1, void* arg2, void* arg3)
433
{
434
    struct scheduler_thread* t;
435
    while (1)
436
    {
437
        wakeup_wait(&dbgwakeup, TIMEOUT_BLOCK);
438
        for (t = head_thread; t; t = t->thread_next)
439
            if (t->state == THREAD_DEFUNCT)
440
            {
441
                if (t->block_type == THREAD_DEFUNCT_STKOV)
442
                {
443
                    if (t->name) cprintf(1, "\n*PANIC*\nStack overflow! (%s)\n", t->name);
444
                    else cprintf(1, "\n*PANIC*\nStack overflow! (%08X)\n", t);
445
                }
446
                t->state = THREAD_DEFUNCT_ACK;
447
            }
448
        uint32_t mode = enter_critical_section();
449
        uint32_t buf[16];
450
        if (dbgstate == DBGSTATE_ASYNC)
451
        {
452
            memcpy(buf, dbgbuf, 64);
453
            leave_critical_section(mode);
454
            void* addr = &buf[4];
455
            int len = 0;
456
            switch (buf[0])
457
            {
458
                case 2:  // RESET
459
                    shutdown(false);
460
                    reset();
461
                case 3:  // POWER OFF
462
                    if (buf[1]) shutdown(true);
463
                    power_off();
464
                    buf[0] = 1;
465
                    break;
466
#ifdef HAVE_I2C
467
                case 8:  // READ I2C
468
                    len = buf[1] >> 24;
469
                    i2c_recv(buf[1] & 0xff, (buf[1] >> 8) & 0xff, (buf[1] >> 16) & 0xff,
470
                             (uint8_t*)&buf[4], len);
471
                    buf[0] = 1;
472
                    break;
473
                case 9:  // WRITE I2C
474
                    i2c_send(buf[1] & 0xff, (buf[1] >> 8) & 0xff, (buf[1] >> 16) & 0xff,
475
                             (uint8_t*)&buf[4], buf[1] >> 24);
476
                    buf[0] = 1;
477
                    break;
478
#endif
479
                case 12:  // CWRITE
480
                    cwrite(buf[1], (const char*)&buf[4], buf[2]);
481
                    buf[0] = 1;
482
                    break;
483
                case 13:  // CREAD
484
                    buf[0] = 1;
485
                    buf[1] = cread(buf[1], (char*)&buf[4], buf[2], 0);
486
                    break;
487
                case 14:  // CFLUSH
488
                    cflush(buf[1]);
489
                    buf[0] = 1;
490
                    break;
491
                case 21:  // EXECIMAGE
492
                {
493
                    int argc = buf[2] >> 24;
494
                    if (!buf[3])
495
                    {
496
                        buf[3] = (uint32_t)&buf[4];
497
                        int i;
498
                        for (i = 0; i < argc; i++) buf[i + 4] += buf[3];
499
                    }
500
                    buf[0] = 1;
501
                    buf[1] = (uint32_t)execimage((void*)buf[1], buf[2] & 0x10000, argc, (const char* const*)buf[3]);
502
                    break;
503
                }
504
#ifdef HAVE_BOOTFLASH
505
                case 22:  // READ BOOT FLASH
506
                    bootflash_readraw((void*)buf[1], buf[2], buf[3]);
507
                    buf[0] = 1;
508
                    break;
509
                case 23:  // WRITE BOOT FLASH
510
                    bootflash_writeraw((void*)buf[1], buf[2], buf[3]);
511
                    buf[0] = 1;
512
                    break;
513
#endif
514
                case 24:  // EXECFIRMWARE
515
                    shutdown(false);
516
                    execfirmware((void*)buf[1], (void*)buf[2], (size_t)buf[3]);
517
                    buf[0] = 1;
518
                    break;
519
#ifdef HAVE_HWKEYAES
520
                case 25:  // HWKEYAES
521
                    hwkeyaes((enum hwkeyaes_direction)((uint8_t*)buf)[4], ((uint16_t*)buf)[3], (void*)buf[2], buf[3]);
522
                    buf[0] = 1;
523
                    break;
524
#endif
525
#ifdef HAVE_HMACSHA1
526
                case 26:  // HMACSHA1
527
                    hmacsha1((void*)buf[1], buf[2], (void*)buf[3]);
528
                    buf[0] = 1;
529
                    break;
530
#endif
531
#ifdef HAVE_STORAGE
532
                case 27:  // STORAGE_GET_INFO
533
                    buf[0] = 1;
534
                    storage_get_info(buf[1], (struct storage_info*)&buf[4]);
535
                    buf[1] = 1;
933 theseven 536
                    len = (sizeof(struct storage_info) + 3) / 4 * 4;
892 theseven 537
                    break;
538
                case 28:  // STORAGE_READ_SECTORS_MD
539
                    buf[0] = 1;
540
                    buf[1] = (uint32_t)storage_read_sectors_md(buf[1], buf[2] | (((uint64_t)(buf[3]) << 32)),
541
                                                               buf[4], (void*)(buf[5]));
542
                    break;
543
                case 29:  // STORAGE_WRITE_SECTORS_MD
544
                    buf[0] = 1;
545
                    buf[1] = (uint32_t)storage_write_sectors_md(buf[1], buf[2] | (((uint64_t)(buf[3]) << 32)),
546
                                                                buf[4], (void*)(buf[5]));
547
                    break;
548
                case 30:  // FILE_OPEN
549
                {
550
                    buf[0] = 1;
551
                    if (!buf[3]) buf[3] = (uint32_t)&buf[4];
552
                    int fd = file_open((char*)buf[3], (int)buf[1]);
553
                    if (fd > 0) reown_file(fd, KERNEL_OWNER(KERNEL_OWNER_USB_MONITOR));
554
                    buf[1] = (uint32_t)fd;
555
                    break;
556
                }
557
                case 31:  // FILESIZE
558
                    buf[0] = 1;
559
                    buf[1] = (uint32_t)filesize((int)buf[1]);
560
                    break;
561
                case 32:  // READ
562
                    buf[0] = 1;
563
                    buf[1] = (uint32_t)read((int)buf[1], (void*)buf[2], (size_t)buf[3]);
564
                    break;
565
                case 33:  // WRITE
566
                    buf[0] = 1;
567
                    buf[1] = (uint32_t)write((int)buf[1], (void*)buf[2], (size_t)buf[3]);
568
                    break;
569
                case 34:  // LSEEK
570
                    buf[0] = 1;
571
                    buf[1] = (uint32_t)lseek((int)buf[1], (off_t)buf[2], (int)buf[3]);
572
                    break;
573
                case 35:  // FTRUNCATE
574
                    buf[0] = 1;
575
                    buf[1] = (uint32_t)ftruncate((int)buf[1], (off_t)buf[2]);
576
                    break;
577
                case 36:  // FSYNC
578
                    buf[0] = 1;
579
                    buf[1] = (uint32_t)fsync((int)buf[1]);
580
                    break;
581
                case 37:  // CLOSE
582
                    buf[0] = 1;
583
                    buf[1] = (uint32_t)close((int)buf[1]);
584
                    break;
585
                case 38:  // CLOSE_MONITOR_FILES
586
                    buf[0] = 1;
587
                    buf[1] = (uint32_t)close_all_of_process(KERNEL_OWNER(KERNEL_OWNER_USB_MONITOR));
588
                    break;
589
                case 39:  // RELEASE_FILES
590
                    buf[0] = 1;
591
                    buf[1] = (uint32_t)release_files((int)buf[1]);
592
                    break;
593
                case 40:  // REMOVE
594
                    buf[0] = 1;
595
                    if (!buf[3]) buf[3] = (uint32_t)&buf[4];
596
                    buf[1] = (uint32_t)remove((char*)buf[3]);
597
                    break;
598
                case 41:  // RENAME
599
                    buf[0] = 1;
600
                    buf[1] = (uint32_t)rename((char*)buf[2], (char*)buf[3]);
601
                    break;
602
                case 42:  // OPENDIR
603
                {
604
                    buf[0] = 1;
605
                    if (!buf[3]) buf[3] = (uint32_t)&buf[4];
606
                    DIR* dir = opendir((char*)buf[3]);
607
                    if (dir > 0) reown_dir(dir, KERNEL_OWNER(KERNEL_OWNER_USB_MONITOR));
608
                    buf[1] = (uint32_t)dir;
609
                    break;
610
                }
611
                case 43:  // READDIR
612
                    buf[0] = 1;
613
                    buf[3] = (uint32_t)readdir((DIR*)buf[1]);
614
                    buf[1] = 1;
615
                    buf[2] = MAX_PATH;
616
                    break;
617
                case 44:  // CLOSEDIR
618
                    buf[0] = 1;
619
                    buf[1] = (uint32_t)closedir((DIR*)buf[1]);
620
                    break;
621
                case 45:  // CLOSE_MONITOR_DIRS
622
                    buf[0] = 1;
623
                    buf[1] = (uint32_t)closedir_all_of_process(KERNEL_OWNER(KERNEL_OWNER_USB_MONITOR));
624
                    break;
625
                case 46:  // RELEASE_DIRS
626
                    buf[0] = 1;
627
                    buf[1] = (uint32_t)release_dirs((int)buf[1]);
628
                    break;
629
                case 47:  // MKDIR
630
                    buf[0] = 1;
631
                    if (!buf[3]) buf[3] = (uint32_t)&buf[4];
632
                    buf[1] = (uint32_t)mkdir((char*)buf[3]);
633
                    break;
634
                case 48:  // RMDIR
635
                    buf[0] = 1;
636
                    if (!buf[3]) buf[3] = (uint32_t)&buf[4];
637
                    buf[1] = (uint32_t)rmdir((char*)buf[3]);
638
                    break;
639
                case 49:  // ERRNO
640
                    buf[0] = 1;
641
                    buf[1] = (uint32_t)errno;
642
                    break;
643
#ifdef HAVE_HOTSWAP
644
                case 50:  // DISK_MOUNT
645
                    buf[0] = 1;
646
                    buf[1] = (uint32_t)disk_mount((int)buf[1]);
647
                    break;
648
                case 51:  // DISK_UNMOUNT
649
                    buf[0] = 1;
650
                    buf[1] = (uint32_t)disk_unmount((int)buf[1]);
651
                    break;
652
#endif
653
                case 58:  // FAT_ENABLE_FLUSHING
654
                    buf[0] = 1;
655
                    fat_enable_flushing((bool)buf[1]);
656
                    break;
657
                case 59:  // FAT_SIZE
658
                    buf[0] = 1;
659
                    fat_size_mv(buf[1], &buf[1], &buf[2]);
660
                    break;
661
#endif
662
                case 52:  // MALLOC
663
                    buf[0] = 1;
664
                    buf[1] = (uint32_t)malloc((size_t)buf[1]);
665
                    if (buf[1]) reownalloc(buf[1], KERNEL_OWNER(KERNEL_OWNER_USB_MONITOR));
666
                    break;
667
                case 53:  // MEMALIGN
668
                    buf[0] = 1;
669
                    buf[1] = (uint32_t)memalign((size_t)buf[1], (size_t)buf[2]);
670
                    if (buf[1]) reownalloc(buf[1], KERNEL_OWNER(KERNEL_OWNER_USB_MONITOR));
671
                    break;
672
                case 54:  // REALLOC
673
                    buf[0] = 1;
674
                    buf[1] = (uint32_t)realloc((void*)buf[1], (size_t)buf[2]);
675
                    break;
676
                case 55:  // REOWNALLOC
677
                    buf[0] = 1;
678
                    reownalloc((void*)buf[1], (void*)buf[2]);
679
                    break;
680
                case 56:  // FREE
681
                    buf[0] = 1;
682
                    free((void*)buf[1]);
683
                    break;
684
                case 57:  // FREE MONITOR ALLOCATIONS
685
                    buf[0] = 1;
686
                    buf[1] = (uint32_t)free_all_of_thread(KERNEL_OWNER(KERNEL_OWNER_USB_MONITOR));
687
                    break;
688
#ifdef HAVE_RTC
689
                case 60:  // RTC READ
690
                    buf[0] = 1;
691
                    rtc_read_datetime((struct rtc_datetime*)&buf[1]);
692
                    break;
693
                case 61:  // RTC WRITE
694
                    buf[0] = 1;
695
                    rtc_write_datetime((const struct rtc_datetime*)&buf[1]);
696
                    break;
697
#endif
931 theseven 698
                default:
892 theseven 699
#ifdef USB_HAVE_TARGET_SPECIFIC_REQUESTS
931 theseven 700
                    if (buf[0] >= 0xffff0000)
701
                        len = usb_target_handle_request(buf, sizeof(buf), &addr);
932 theseven 702
                    else buf[0] = 2;
703
#else
704
                    buf[0] = 2;
892 theseven 705
#endif
706
                    break;
707
            }
708
            mode = enter_critical_section();
709
            if (dbgstate == DBGSTATE_ASYNC)
710
            {
711
                usb_ep0_start_tx(dbgusb, NULL, 0, true, NULL);
712
                dbgstate = DBGSTATE_RESPOND;
713
                dbgmemaddr = addr;
714
                dbgmemlen = len;
933 theseven 715
                memcpy(dbgbuf, buf, 16);
892 theseven 716
            }
717
        }
718
        dbgbusy = false;
719
        leave_critical_section(mode);
720
    }
721
}
722
 
723
void usbdebug_init(void)
724
{
725
    wakeup_init(&dbgwakeup);
726
    dbgconsendreadidx = 0;
727
    dbgconsendwriteidx = 0;
728
    dbgconrecvreadidx = 0;
729
    dbgconrecvwriteidx = 0;
730
    wakeup_init(&dbgconsendwakeup);
731
    wakeup_init(&dbgconrecvwakeup);
732
    dbgenabled = false;
733
    dbgbusy = false;
734
    dbgstate = DBGSTATE_IDLE;
735
    dbgconsoleattached = false;
736
    thread_create(&dbgthread_handle, "monitor worker", dbgthread, dbgstack,
737
                  sizeof(dbgstack), CORE_THREAD, 255, true, NULL, NULL, NULL, NULL);
738
}
739
 
740
int dbgconsole_getfree() ICODE_ATTR;
741
int dbgconsole_getfree()
742
{
743
    int free = dbgconsendreadidx - dbgconsendwriteidx - 1;
744
    if (free < 0) free += sizeof(dbgconsendbuf);
745
    return free;
746
}
747
 
748
int dbgconsole_makespace(int length, bool safe) ICODE_ATTR;
749
int dbgconsole_makespace(int length, bool safe)
750
{
751
    int free = dbgconsole_getfree();
752
    while (!free && dbgconsoleattached && !safe)
753
    {
754
        dbgconsoleattached = false;
755
        wakeup_wait(&dbgconsendwakeup, 2000000);
756
        free = dbgconsole_getfree();
757
    }
758
    if (free) return free > length ? length : free;
759
    if (length > sizeof(dbgconsendbuf) - 17) length = sizeof(dbgconsendbuf) - 17;
760
    uint32_t mode = enter_critical_section();
761
    dbgconsendreadidx += length;
762
    if (dbgconsendreadidx >= sizeof(dbgconsendbuf))
763
        dbgconsendreadidx -= sizeof(dbgconsendbuf);
764
    int offset = 0;
765
    int idx = dbgconsendreadidx;
766
    if (idx + 16 >= sizeof(dbgconsendbuf))
767
    {
768
        offset = sizeof(dbgconsendbuf) - dbgconsendreadidx;
769
        memcpy(&dbgconsendbuf[dbgconsendreadidx], dbgconoverflowstr, offset);
770
        idx = 0;
771
    }
772
    if (offset != 16) memcpy(&dbgconsendbuf[idx], &dbgconoverflowstr[offset], 16 - offset);
773
    leave_critical_section(mode);
774
    return length;
775
}
776
 
777
void dbgconsole_putc_internal(char string, bool safe)
778
{
779
    dbgconsole_makespace(1, safe);
780
    dbgconsendbuf[dbgconsendwriteidx++] = string;
781
    if (dbgconsendwriteidx >= sizeof(dbgconsendbuf))
782
        dbgconsendwriteidx -= sizeof(dbgconsendbuf);
783
}
784
 
785
void dbgconsole_putc(char string)
786
{
787
    dbgconsole_putc_internal(string, false);
788
}
789
 
790
void dbgconsole_sputc(char string)
791
{
792
    dbgconsole_putc_internal(string, true);
793
}
794
 
795
void dbgconsole_write_internal(const char* string, size_t length, bool safe)
796
{
797
    while (length)
798
    {
799
        int space = dbgconsole_makespace(length, safe);
800
        if (dbgconsendwriteidx + space >= sizeof(dbgconsendbuf))
801
        {
802
            int bytes = sizeof(dbgconsendbuf) - dbgconsendwriteidx;
803
            memcpy(&dbgconsendbuf[dbgconsendwriteidx], string, bytes);
804
            dbgconsendwriteidx = 0;
805
            string = &string[bytes];
806
            space -= bytes;
807
            length -= bytes;
808
        }
809
        if (space) memcpy(&dbgconsendbuf[dbgconsendwriteidx], string, space);
810
        dbgconsendwriteidx += space;
811
        string = &string[space];
812
        length -= space;
813
    }
814
}
815
 
816
void dbgconsole_write(const char* string, size_t length)
817
{
818
    dbgconsole_write_internal(string, length, false);
819
}
820
 
821
void dbgconsole_swrite(const char* string, size_t length)
822
{
823
    dbgconsole_write_internal(string, length, true);
824
}
825
 
826
void dbgconsole_puts(const char* string)
827
{
828
    dbgconsole_write(string, strlen(string));
829
}
830
 
831
void dbgconsole_sputs(const char* string)
832
{
833
    dbgconsole_swrite(string, strlen(string));
834
}
835
 
836
int dbgconsole_getavailable() ICODE_ATTR;
837
int dbgconsole_getavailable()
838
{
839
    int available = dbgconrecvwriteidx - dbgconrecvreadidx;
840
    if (available < 0) available += sizeof(dbgconrecvbuf);
841
    return available;
842
}
843
 
844
int dbgconsole_getc(int timeout)
845
{
846
    if (!dbgconsole_getavailable())
847
    {
848
        wakeup_wait(&dbgconrecvwakeup, TIMEOUT_NONE);
849
        if (!dbgconsole_getavailable())
850
        {
851
            wakeup_wait(&dbgconrecvwakeup, timeout);
852
            if (!dbgconsole_getavailable()) return -1;
853
        }
854
    }
855
    int byte = dbgconrecvbuf[dbgconrecvreadidx++];
856
    if (dbgconrecvreadidx >= sizeof(dbgconrecvbuf))
857
        dbgconrecvreadidx -= sizeof(dbgconrecvbuf);
858
    return byte;
859
}
860
 
861
int dbgconsole_read(char* buffer, size_t length, int timeout)
862
{
863
    if (!length) return 0;
864
    int available = dbgconsole_getavailable();
865
    if (!available)
866
    {
867
        wakeup_wait(&dbgconrecvwakeup, TIMEOUT_NONE);
868
        int available = dbgconsole_getavailable();
869
        if (!available)
870
        {
871
            wakeup_wait(&dbgconrecvwakeup, timeout);
872
            int available = dbgconsole_getavailable();
873
            if (!available) return 0;
874
        }
875
    }
876
    if (available > length) available = length;
877
    int left = available;
878
    if (dbgconrecvreadidx + available >= sizeof(dbgconrecvbuf))
879
    {
880
        int bytes = sizeof(dbgconrecvbuf) - dbgconrecvreadidx;
881
        memcpy(buffer, &dbgconrecvbuf[dbgconrecvreadidx], bytes);
882
        dbgconrecvreadidx = 0;
883
        buffer = &buffer[bytes];
884
        left -= bytes;
885
    }
886
    if (left) memcpy(buffer, &dbgconrecvbuf[dbgconrecvreadidx], left);
887
    dbgconrecvreadidx += left;
888
    return available;
889
}
890