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