Subversion Repositories freemyipod

Rev

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

Rev Author Line No. Line
15 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
6
//    This file is part of emBIOS.
7
//
8
//    emBIOS 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
//    emBIOS 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 emBIOS.  If not, see <http://www.gnu.org/licenses/>.
20
//
21
//
22
 
23
 
24
#include "global.h"
25
#include "panic.h"
26
#include "usb.h"
27
#include "usb_ch9.h"
28
#include "usbdrv.h"
29
#include "thread.h"
30
#include "console.h"
31
#include "util.h"
25 theseven 32
#include "contextswitch.h"
54 theseven 33
#include "power.h"
35 theseven 34
#include "mmu.h"
29 theseven 35
#include "shutdown.h"
92 theseven 36
#include "execimage.h"
85 theseven 37
#ifdef HAVE_I2C
38
#include "i2c.h"
39
#endif
15 theseven 40
 
41
 
42
static uint8_t ctrlresp[2] CACHEALIGN_ATTR;
43
static uint32_t dbgrecvbuf[0x80] CACHEALIGN_ATTR;
44
static uint32_t dbgsendbuf[0x80] CACHEALIGN_ATTR;
45
static uint32_t dbgasyncsendbuf[0x80] CACHEALIGN_ATTR;
46
static char dbgendpoints[4] IBSS_ATTR;
47
 
48
enum dbgaction_t
49
{
50
    DBGACTION_IDLE = 0,
51
    DBGACTION_I2CSEND,
52
    DBGACTION_I2CRECV,
29 theseven 53
    DBGACTION_RESET,
54
    DBGACTION_POWEROFF,
55
    DBGACTION_CWRITE,
56
    DBGACTION_CREAD,
92 theseven 57
    DBGACTION_CFLUSH,
58
    DBGACTION_EXECIMAGE
15 theseven 59
};
60
 
61
static uint32_t dbgstack[0x100] STACK_ATTR;
62
struct wakeup dbgwakeup IBSS_ATTR;
63
extern struct scheduler_thread* scheduler_threads;
64
static enum dbgaction_t dbgaction IBSS_ATTR;
29 theseven 65
static int dbgi2cbus;
66
static int dbgi2cslave;
67
static int dbgactionaddr;
68
static int dbgactionlength;
69
static int dbgactionconsoles;
70
static int dbgactiontype;
25 theseven 71
static char dbgconsendbuf[4096];
72
static char dbgconrecvbuf[1024];
73
static int dbgconsendreadidx IBSS_ATTR;
74
static int dbgconsendwriteidx IBSS_ATTR;
75
static int dbgconrecvreadidx IBSS_ATTR;
76
static int dbgconrecvwriteidx IBSS_ATTR;
77
static struct wakeup dbgconsendwakeup IBSS_ATTR;
78
static struct wakeup dbgconrecvwakeup IBSS_ATTR;
79
static bool dbgconsoleattached IBSS_ATTR;
15 theseven 80
 
25 theseven 81
static const char dbgconoverflowstr[] = "\n\n[overflowed]\n\n";
15 theseven 82
 
35 theseven 83
extern int _initstart;   // These aren't ints at all, but gcc complains about void types being
84
extern int _sdramstart;  // used here, and we only need the address, so forget about it...
25 theseven 85
 
35 theseven 86
 
15 theseven 87
static struct usb_device_descriptor CACHEALIGN_ATTR device_descriptor =
88
{
89
    .bLength            = sizeof(struct usb_device_descriptor),
90
    .bDescriptorType    = USB_DT_DEVICE,
91
    .bcdUSB             = 0x0200,
92
    .bDeviceClass       = USB_CLASS_VENDOR_SPEC,
93
    .bDeviceSubClass    = 0xff,
94
    .bDeviceProtocol    = 0xff,
95
    .bMaxPacketSize0    = 64,
96
    .idVendor           = 0xffff,
97
    .idProduct          = 0xe000,
98
    .bcdDevice          = 0x0001,
99
    .iManufacturer      = 1,
100
    .iProduct           = 2,
101
    .iSerialNumber      = 0,
102
    .bNumConfigurations = 1
103
};
104
 
105
static struct usb_config_bundle
106
{
107
    struct usb_config_descriptor config_descriptor;
108
    struct usb_interface_descriptor interface_descriptor;
109
    struct usb_endpoint_descriptor endpoint1_descriptor;
110
    struct usb_endpoint_descriptor endpoint2_descriptor;
111
    struct usb_endpoint_descriptor endpoint3_descriptor;
112
    struct usb_endpoint_descriptor endpoint4_descriptor;
113
} __attribute__((packed)) CACHEALIGN_ATTR config_bundle = 
114
{
115
    .config_descriptor =
116
    {
117
        .bLength             = sizeof(struct usb_config_descriptor),
118
        .bDescriptorType     = USB_DT_CONFIG,
119
        .wTotalLength        = sizeof(struct usb_config_descriptor)
120
                             + sizeof(struct usb_interface_descriptor)
121
                             + sizeof(struct usb_endpoint_descriptor) * 4,
122
        .bNumInterfaces      = 1,
123
        .bConfigurationValue = 1,
124
        .iConfiguration      = 0,
125
        .bmAttributes        = USB_CONFIG_ATT_ONE,
126
        .bMaxPower           = 250
127
    },
128
    .interface_descriptor =
129
    {
130
        .bLength             = sizeof(struct usb_interface_descriptor),
131
        .bDescriptorType     = USB_DT_INTERFACE,
132
        .bInterfaceNumber    = 0,
133
        .bAlternateSetting   = 0,
134
        .bNumEndpoints       = 4,
135
        .bInterfaceClass     = USB_CLASS_VENDOR_SPEC,
136
        .bInterfaceSubClass  = 0xff,
137
        .bInterfaceProtocol  = 0xff,
138
        .iInterface          = 0
139
    },
140
    .endpoint1_descriptor =
141
    {
142
        .bLength             = sizeof(struct usb_endpoint_descriptor),
143
        .bDescriptorType     = USB_DT_ENDPOINT,
144
        .bEndpointAddress    = 0,
145
        .bmAttributes        = USB_ENDPOINT_XFER_BULK,
146
        .wMaxPacketSize      = 0,
147
        .bInterval           = 1
148
    },
149
    .endpoint2_descriptor =
150
    {
151
        .bLength             = sizeof(struct usb_endpoint_descriptor),
152
        .bDescriptorType     = USB_DT_ENDPOINT,
153
        .bEndpointAddress    = 0,
154
        .bmAttributes        = USB_ENDPOINT_XFER_BULK,
155
        .wMaxPacketSize      = 0,
156
        .bInterval           = 1
157
    },
158
    .endpoint3_descriptor =
159
    {
160
        .bLength             = sizeof(struct usb_endpoint_descriptor),
161
        .bDescriptorType     = USB_DT_ENDPOINT,
162
        .bEndpointAddress    = 0,
163
        .bmAttributes        = USB_ENDPOINT_XFER_BULK,
164
        .wMaxPacketSize      = 0,
165
        .bInterval           = 1
166
    },
167
    .endpoint4_descriptor =
168
    {
169
        .bLength             = sizeof(struct usb_endpoint_descriptor),
170
        .bDescriptorType     = USB_DT_ENDPOINT,
171
        .bEndpointAddress    = 0,
172
        .bmAttributes        = USB_ENDPOINT_XFER_BULK,
173
        .wMaxPacketSize      = 0,
174
        .bInterval           = 1
175
    }
176
};
177
 
178
static struct usb_string_descriptor CACHEALIGN_ATTR string_devicename =
179
{
180
    32,
181
    USB_DT_STRING,
182
    {'e', 'm', 'B', 'I', 'O', 'S', ' ', 'D', 'e', 'b', 'u', 'g', 'g', 'e', 'r'}
183
};
184
 
185
static const struct usb_string_descriptor CACHEALIGN_ATTR lang_descriptor =
186
{
187
    4,
188
    USB_DT_STRING,
189
    {0x0409}
190
};
191
 
192
 
193
void usb_setup_dbg_listener()
194
{
195
    usb_drv_recv(dbgendpoints[0], dbgrecvbuf, usb_drv_port_speed() ? 512 : 64);
196
}
197
 
198
void usb_handle_control_request(struct usb_ctrlrequest* req)
199
{
200
    const void* addr;
201
    int size = -1;
202
    switch (req->bRequest)
203
    {
204
    case USB_REQ_GET_STATUS:
205
        if (req->bRequestType == USB_DIR_IN) ctrlresp[0] = 1;
206
        else ctrlresp[0] = 0;
207
        ctrlresp[1] = 0;
208
        addr = ctrlresp;
209
        size = 2;
210
        break;
211
    case USB_REQ_CLEAR_FEATURE:
212
        if (req->bRequestType == USB_RECIP_ENDPOINT && req->wValue == USB_ENDPOINT_HALT)
213
            usb_drv_stall(req->wIndex & 0xf, false, req->wIndex >> 7);
214
        size = 0;
215
        break;
216
    case USB_REQ_SET_FEATURE:
217
        size = 0;
218
        break;
219
    case USB_REQ_SET_ADDRESS:
220
        size = 0;
221
        usb_drv_cancel_all_transfers();
222
        usb_drv_set_address(req->wValue);
223
        usb_setup_dbg_listener();
224
        break;
225
    case USB_REQ_GET_DESCRIPTOR:
226
        switch (req->wValue >> 8)
227
        {
228
        case USB_DT_DEVICE:
229
            addr = &device_descriptor;
230
            size = sizeof(device_descriptor);
231
            break;
232
        case USB_DT_OTHER_SPEED_CONFIG:
233
        case USB_DT_CONFIG:
234
            if ((req->wValue >> 8) == USB_DT_CONFIG)
235
            {
236
                int maxpacket = usb_drv_port_speed() ? 512 : 64;
237
                config_bundle.endpoint1_descriptor.wMaxPacketSize = maxpacket;
238
                config_bundle.endpoint2_descriptor.wMaxPacketSize = maxpacket;
239
                config_bundle.endpoint3_descriptor.wMaxPacketSize = maxpacket;
240
                config_bundle.endpoint4_descriptor.wMaxPacketSize = maxpacket;
241
                config_bundle.config_descriptor.bDescriptorType = USB_DT_CONFIG;
242
            }
243
            else
244
            {
245
                int maxpacket = usb_drv_port_speed() ? 64 : 512;
246
                config_bundle.endpoint1_descriptor.wMaxPacketSize = maxpacket;
247
                config_bundle.endpoint2_descriptor.wMaxPacketSize = maxpacket;
248
                config_bundle.endpoint3_descriptor.wMaxPacketSize = maxpacket;
249
                config_bundle.endpoint4_descriptor.wMaxPacketSize = maxpacket;
250
                config_bundle.config_descriptor.bDescriptorType = USB_DT_OTHER_SPEED_CONFIG;
251
            }
252
            addr = &config_bundle;
253
            size = sizeof(config_bundle);
254
            break;
255
        case USB_DT_STRING:
256
            switch (req->wValue & 0xff)
257
            {
258
            case 0:
259
                addr = &lang_descriptor;
260
                size = sizeof(lang_descriptor);
261
                break;
262
            case 1:
263
                string_devicename.bLength = 14;
264
                addr = &string_devicename;
265
                size = 14;
266
            case 2:
267
                string_devicename.bLength = sizeof(string_devicename);
268
                addr = &string_devicename;
269
                size = sizeof(string_devicename);
270
                break;
271
            }
272
            break;
273
        }
274
        break;
275
    case USB_REQ_GET_CONFIGURATION:
276
        ctrlresp[0] = 1;
277
        addr = ctrlresp;
278
        size = 1;
279
        break;
280
    case USB_REQ_SET_CONFIGURATION:
281
        usb_drv_cancel_all_transfers();
282
        usb_setup_dbg_listener();
283
        size = 0;
284
        break;
285
    }
286
    if (!size) usb_drv_send_nonblocking(0, NULL, 0);
287
    else if (size == -1)
288
    {
289
        usb_drv_stall(0, true, true);
290
        usb_drv_stall(0, true, false);
291
    }
292
    else
293
    {
294
        usb_drv_recv(0, NULL, 0);
295
        usb_drv_send_nonblocking(0, addr, size > req->wLength ? req->wLength : size);
296
    }
297
}
298
 
29 theseven 299
bool set_dbgaction(enum dbgaction_t action, int addsize)
15 theseven 300
{
301
    if (dbgaction != DBGACTION_IDLE)
302
    {
303
        dbgsendbuf[0] = 3;
29 theseven 304
        usb_drv_send_nonblocking(dbgendpoints[1], dbgsendbuf, 16 + addsize);
15 theseven 305
        return true;
306
    }
307
    dbgaction = action;
308
    wakeup_signal(&dbgwakeup);
309
    return false;
310
}
311
 
312
void reset() __attribute__((noreturn));
313
 
314
void usb_handle_transfer_complete(int endpoint, int dir, int status, int length)
315
{
316
    void* addr = dbgsendbuf;
317
    int size = 0;
318
    if (endpoint == dbgendpoints[0])
319
    {
320
        switch (dbgrecvbuf[0])
321
        {
28 theseven 322
        case 1:  // GET INFO
15 theseven 323
            dbgsendbuf[0] = 1;
324
            size = 16;
28 theseven 325
            switch (dbgrecvbuf[1])
326
            {
327
            case 0:  // GET VERSION INFO
85 theseven 328
                dbgsendbuf[1] = VERSION_SVN_INT;
329
                dbgsendbuf[2] = VERSION_MAJOR | (VERSION_MINOR << 8)
28 theseven 330
                              | (VERSION_PATCH << 16) | (1 << 24);
85 theseven 331
                dbgsendbuf[3] = PLATFORM_ID;
28 theseven 332
                break;
333
            case 1:  // GET PACKET SIZE INFO
334
                dbgsendbuf[1] = 0x02000200;
335
                dbgsendbuf[2] = usb_drv_get_max_out_size();
336
                dbgsendbuf[3] = usb_drv_get_max_in_size();
337
                break;
35 theseven 338
            case 2:  // GET USER MEMORY INFO
339
                dbgsendbuf[1] = (uint32_t)&_initstart;
340
                dbgsendbuf[2] = (uint32_t)&_sdramstart;
341
                break;
28 theseven 342
            default:
343
                dbgsendbuf[0] = 2;
344
            }
15 theseven 345
            break;
346
        case 2:  // RESET
29 theseven 347
            if (dbgrecvbuf[1])
348
            {
349
                if (set_dbgaction(DBGACTION_RESET, 0)) break;
350
                dbgsendbuf[0] = 1;
351
                size = 16;
352
            }
353
            else reset();
15 theseven 354
            break;
355
        case 3:  // POWER OFF
29 theseven 356
            if (set_dbgaction(DBGACTION_POWEROFF, 0)) break;
357
            dbgactiontype = dbgrecvbuf[1];
358
            dbgsendbuf[0] = 1;
359
            size = 16;
15 theseven 360
            break;
361
        case 4:  // READ MEMORY
362
            dbgsendbuf[0] = 1;
363
            memcpy(&dbgsendbuf[4], (const void*)dbgrecvbuf[1], dbgrecvbuf[2]);
364
            size = dbgrecvbuf[2] + 16;
365
            break;
366
        case 5:  // WRITE MEMORY
367
            dbgsendbuf[0] = 1;
368
            memcpy((void*)dbgrecvbuf[1], &dbgrecvbuf[4], dbgrecvbuf[2]);
369
            size = 16;
370
            break;
371
        case 6:  // READ DMA
372
            dbgsendbuf[0] = 1;
373
            usb_drv_send_nonblocking(dbgendpoints[1], dbgsendbuf, 16);
374
            usb_drv_send_nonblocking(dbgendpoints[3], (const void*)dbgrecvbuf[1], dbgrecvbuf[2]);
375
            break;
376
        case 7:  // WRITE DMA
377
            dbgsendbuf[0] = 1;
378
            size = 16;
379
            usb_drv_recv(dbgendpoints[2], (void*)dbgrecvbuf[1], dbgrecvbuf[2]);
380
            break;
85 theseven 381
#ifdef HAVE_I2C
15 theseven 382
        case 8:  // READ I2C
29 theseven 383
            if (set_dbgaction(DBGACTION_I2CRECV, dbgrecvbuf[1] >> 24)) break;
15 theseven 384
            dbgi2cbus = dbgrecvbuf[1] & 0xff;
385
            dbgi2cslave = (dbgrecvbuf[1] >> 8) & 0xff;
29 theseven 386
            dbgactionaddr = (dbgrecvbuf[1] >> 16) & 0xff;
387
            dbgactionlength = dbgrecvbuf[1] >> 24;
15 theseven 388
            break;
389
        case 9:  // WRITE I2C
29 theseven 390
            if (set_dbgaction(DBGACTION_I2CSEND, 0)) break;
15 theseven 391
            dbgi2cbus = dbgrecvbuf[1] & 0xff;
392
            dbgi2cslave = (dbgrecvbuf[1] >> 8) & 0xff;
29 theseven 393
            dbgactionaddr = (dbgrecvbuf[1] >> 16) & 0xff;
394
            dbgactionlength = dbgrecvbuf[1] >> 24;
395
            memcpy(dbgasyncsendbuf, &dbgsendbuf[4], dbgactionlength);
15 theseven 396
            break;
85 theseven 397
#endif
25 theseven 398
        case 10:  // READ CONSOLE
399
            dbgconsoleattached = true;
400
            int bytes = dbgconsendwriteidx - dbgconsendreadidx;
401
            if (bytes >= sizeof(dbgconsendbuf)) bytes -= sizeof(dbgconsendbuf);
402
            if (bytes)
403
            {
404
                if (bytes < 0) bytes += sizeof(dbgconsendbuf);
405
                if (bytes > dbgrecvbuf[1]) bytes = dbgrecvbuf[1];
406
                int readbytes = bytes;
407
                char* outptr = (char*)&dbgsendbuf[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;
26 theseven 418
                wakeup_signal(&dbgconsendwakeup);
25 theseven 419
            }
420
            dbgsendbuf[0] = 1;
421
            dbgsendbuf[1] = bytes;
422
            dbgsendbuf[2] = sizeof(dbgconsendbuf);
423
            dbgsendbuf[3] = dbgconsendwriteidx - dbgconsendreadidx;
424
            size = 16 + dbgrecvbuf[1];
425
            break;
26 theseven 426
        case 11:  // WRITE CONSOLE
427
            bytes = dbgconrecvreadidx - dbgconrecvwriteidx - 1;
428
            if (bytes < 0) bytes += sizeof(dbgconrecvbuf);
429
            if (bytes)
430
            {
431
                if (bytes > dbgrecvbuf[1]) bytes = dbgrecvbuf[1];
432
                int writebytes = bytes;
433
                char* readptr = (char*)&dbgrecvbuf[4];
434
                if (dbgconrecvwriteidx + bytes >= sizeof(dbgconrecvbuf))
435
                {
436
                    writebytes = sizeof(dbgconrecvbuf) - dbgconrecvwriteidx;
437
                    memcpy(&dbgconrecvbuf[dbgconrecvwriteidx], readptr, writebytes);
438
                    dbgconrecvwriteidx = 0;
439
                    readptr = &readptr[writebytes];
440
                    writebytes = bytes - writebytes;
441
                }
442
                if (writebytes) memcpy(&dbgconrecvbuf[dbgconrecvwriteidx], readptr, writebytes);
443
                dbgconrecvwriteidx += writebytes;
444
                wakeup_signal(&dbgconrecvwakeup);
445
            }
446
            dbgsendbuf[0] = 1;
447
            dbgsendbuf[1] = bytes;
448
            dbgsendbuf[2] = sizeof(dbgconrecvbuf);
449
            dbgsendbuf[3] = dbgconrecvreadidx - dbgconrecvwriteidx - 1;
450
            size = 16;
451
            break;
29 theseven 452
        case 12:  // CWRITE
453
            if (set_dbgaction(DBGACTION_CWRITE, 0)) break;
454
            dbgactionconsoles = dbgrecvbuf[1];
455
            dbgactionlength = dbgrecvbuf[2];
456
            memcpy(dbgasyncsendbuf, &dbgrecvbuf[4], dbgactionlength);
457
            break;
458
        case 13:  // CREAD
459
            if (set_dbgaction(DBGACTION_CREAD, dbgrecvbuf[2])) break;
460
            dbgactionconsoles = dbgrecvbuf[1];
461
            dbgactionlength = dbgrecvbuf[2];
462
            break;
463
        case 14:  // CFLUSH
464
            if (set_dbgaction(DBGACTION_CFLUSH, 0)) break;
465
            dbgactionconsoles = dbgrecvbuf[1];
466
            break;
31 theseven 467
        case 15:  // GET PROCESS INFO
468
            dbgsendbuf[0] = 1;
469
            dbgsendbuf[1] = SCHEDULER_THREAD_INFO_VERSION;
470
            dbgsendbuf[2] = MAX_THREADS * sizeof(struct scheduler_thread);
57 theseven 471
            memcpy(&dbgsendbuf[4], (void*)((uint32_t)scheduler_threads + dbgrecvbuf[1]),
472
                   dbgrecvbuf[2]);
473
            size = dbgrecvbuf[2] + 16;
31 theseven 474
            break;
34 theseven 475
        case 16:  // FREEZE SCHEDULER
54 theseven 476
            dbgsendbuf[1] = scheduler_freeze(dbgrecvbuf[1]);
34 theseven 477
            dbgsendbuf[0] = 1;
478
            size = 16;
479
            break;
35 theseven 480
        case 17:  // SUSPEND THREAD
54 theseven 481
            if (dbgrecvbuf[1])
482
            {
483
                if (thread_suspend(dbgrecvbuf[2]) == -4) dbgsendbuf[1] = 1;
484
                else dbgsendbuf[1] = 0;
485
            }
486
            else
487
            {
488
                if (thread_resume(dbgrecvbuf[2]) == -5) dbgsendbuf[1] = 0;
489
                else dbgsendbuf[1] = 1;
490
            }
35 theseven 491
            dbgsendbuf[0] = 1;
492
            size = 16;
493
            break;
494
        case 18:  // KILL THREAD
495
            thread_terminate(dbgrecvbuf[1]);
496
            dbgsendbuf[0] = 1;
497
            size = 16;
498
            break;
57 theseven 499
        case 19:  // KILL THREAD
35 theseven 500
            dbgsendbuf[0] = 1;
501
            dbgsendbuf[1] = thread_create((const char*)dbgsendbuf[1], (const void*)dbgsendbuf[2],
502
                                          (char*)dbgsendbuf[3], dbgsendbuf[4], dbgsendbuf[5],
503
                                          dbgsendbuf[6], dbgsendbuf[7]);
504
            size = 16;
505
            break;
506
        case 20:  // FLUSH CACHE
507
            clean_dcache();
508
            invalidate_icache();
509
            dbgsendbuf[0] = 1;
510
            size = 16;
511
            break;
92 theseven 512
        case 21:  // EXECIMAGE
513
            if (set_dbgaction(DBGACTION_EXECIMAGE, 0)) break;
514
            dbgactionaddr = dbgrecvbuf[1];
515
            break;
15 theseven 516
        default:
517
            dbgsendbuf[0] = 2;
518
            size = 16;
519
        }
520
        usb_setup_dbg_listener();
521
        if (size) usb_drv_send_nonblocking(dbgendpoints[1], addr, size);
522
    }
523
}
524
 
525
void usb_handle_bus_reset(void)
526
{
527
    dbgendpoints[0] = usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_OUT);
528
    dbgendpoints[1] = usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_IN);
529
    dbgendpoints[2] = usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_OUT);
530
    dbgendpoints[3] = usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_IN);
531
    config_bundle.endpoint1_descriptor.bEndpointAddress = dbgendpoints[0];
532
    config_bundle.endpoint2_descriptor.bEndpointAddress = dbgendpoints[1];
533
    config_bundle.endpoint3_descriptor.bEndpointAddress = dbgendpoints[2];
534
    config_bundle.endpoint4_descriptor.bEndpointAddress = dbgendpoints[3];
535
    usb_setup_dbg_listener();
536
}
537
 
538
void dbgthread(void)
539
{
540
    int i;
25 theseven 541
    int t;
15 theseven 542
    while (1)
543
    {
544
        wakeup_wait(&dbgwakeup, TIMEOUT_BLOCK);
545
        for (i = 0; i < MAX_THREADS; i++)
546
            if (scheduler_threads[i].state == THREAD_DEFUNCT)
547
            {
548
                if (scheduler_threads[i].block_type == THREAD_DEFUNCT_STKOV)
35 theseven 549
                {
550
                    if (scheduler_threads[i].name)
551
                        cprintf(1, "\n*PANIC*\nStack overflow! (%s)\n",
552
                                scheduler_threads[i].name);
553
                    else cprintf(1, "\n*PANIC*\nStack overflow! (ID %d)\n", i);
554
                }
15 theseven 555
                scheduler_threads[i].state = THREAD_DEFUNCT_ACK;
556
            }
557
        if (dbgaction != DBGACTION_IDLE)
558
        {
559
            switch (dbgaction)
560
            {
85 theseven 561
#ifdef HAVE_I2C
15 theseven 562
            case DBGACTION_I2CSEND:
29 theseven 563
                i2c_send(dbgi2cbus, dbgi2cslave, dbgactionaddr,
564
                         (uint8_t*)dbgasyncsendbuf, dbgactionlength);
15 theseven 565
                dbgasyncsendbuf[0] = 1;
566
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
567
                break;
568
            case DBGACTION_I2CRECV:
29 theseven 569
                i2c_recv(dbgi2cbus, dbgi2cslave, dbgactionaddr,
570
                         (uint8_t*)(&dbgasyncsendbuf[4]), dbgactionlength);
15 theseven 571
                dbgasyncsendbuf[0] = 1;
29 theseven 572
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16 + dbgactionlength);
15 theseven 573
                break;
85 theseven 574
#endif
15 theseven 575
            case DBGACTION_POWEROFF:
29 theseven 576
                if (dbgactiontype) shutdown();
54 theseven 577
                power_off();
15 theseven 578
                break;
29 theseven 579
            case DBGACTION_RESET:
580
                shutdown();
581
                reset();
582
                break;
583
            case DBGACTION_CWRITE:
584
                cwrite(dbgactionconsoles, (const char*)dbgasyncsendbuf, dbgactionlength);
585
                dbgasyncsendbuf[0] = 1;
586
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
587
                break;
588
            case DBGACTION_CREAD:
589
                dbgasyncsendbuf[0] = 1;
30 theseven 590
                dbgasyncsendbuf[1] = cread(dbgactionconsoles, (char*)&dbgasyncsendbuf[4],
591
                                           dbgactionlength, 0);
29 theseven 592
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
593
                break;
594
            case DBGACTION_CFLUSH:
595
                cflush(dbgactionconsoles);
596
                dbgasyncsendbuf[0] = 1;
597
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
598
                break;
92 theseven 599
            case DBGACTION_EXECIMAGE:
600
                dbgasyncsendbuf[0] = 1;
601
                dbgasyncsendbuf[1] = execimage((void*)dbgactionaddr);
602
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
603
                break;
15 theseven 604
            }
605
            dbgaction = DBGACTION_IDLE;
606
        }
607
    }
608
}
609
 
610
void usb_init(void)
611
{
612
    dbgaction = DBGACTION_IDLE;
613
    wakeup_init(&dbgwakeup);
25 theseven 614
    dbgconsendreadidx = 0;
615
    dbgconsendwriteidx = 0;
616
    dbgconrecvreadidx = 0;
617
    dbgconrecvwriteidx = 0;
618
    wakeup_init(&dbgconsendwakeup);
619
    wakeup_init(&dbgconrecvwakeup);
85 theseven 620
    dbgconsoleattached = false;
15 theseven 621
    thread_create("Debugger", dbgthread, dbgstack, sizeof(dbgstack), 255, SYSTEM_THREAD, true);
622
    usb_drv_init();
623
}
25 theseven 624
 
625
int dbgconsole_getfree() ICODE_ATTR;
626
int dbgconsole_getfree()
627
{
628
    int free = dbgconsendreadidx - dbgconsendwriteidx - 1;
629
    if (free < 0) free += sizeof(dbgconsendbuf);
630
    return free;
631
}
632
 
633
int dbgconsole_makespace(int length) ICODE_ATTR;
634
int dbgconsole_makespace(int length)
635
{
636
    int free = dbgconsole_getfree();
637
    while (!free && dbgconsoleattached)
638
    {
639
        if (wakeup_wait(&dbgconsendwakeup, 2000000) == THREAD_TIMEOUT)
640
            dbgconsoleattached = false;
641
        free = dbgconsole_getfree();
642
    }
643
    if (free) return free > length ? length : free;
644
    if (length > sizeof(dbgconsendbuf) - 17) length = sizeof(dbgconsendbuf) - 17;
645
    uint32_t mode = enter_critical_section();
646
    dbgconsendreadidx += length;
647
    if (dbgconsendreadidx >= sizeof(dbgconsendbuf))
648
        dbgconsendreadidx -= sizeof(dbgconsendbuf);
649
    int offset = 0;
650
    int idx = dbgconsendreadidx;
651
    if (idx + 16 >= sizeof(dbgconsendbuf))
652
    {
653
        offset = sizeof(dbgconsendbuf) - dbgconsendreadidx;
654
        memcpy(&dbgconsendbuf[dbgconsendreadidx], dbgconoverflowstr, offset);
655
        idx = 0;
656
    }
657
    if (offset != 16) memcpy(&dbgconsendbuf[idx], &dbgconoverflowstr[offset], 16 - offset);
658
    leave_critical_section(mode);
659
    return length;
660
}
661
 
662
void dbgconsole_putc(char string)
663
{
664
    dbgconsole_makespace(1);
665
    dbgconsendbuf[dbgconsendwriteidx++] = string;
666
    if (dbgconsendwriteidx >= sizeof(dbgconsendbuf))
667
        dbgconsendwriteidx -= sizeof(dbgconsendbuf);
668
}
669
 
670
void dbgconsole_write(const char* string, size_t length)
671
{
672
    while (length)
673
    {
674
        int space = dbgconsole_makespace(length);
675
        if (dbgconsendwriteidx + space >= sizeof(dbgconsendbuf))
676
        {
677
            int bytes = sizeof(dbgconsendbuf) - dbgconsendwriteidx;
678
            memcpy(&dbgconsendbuf[dbgconsendwriteidx], string, bytes);
679
            dbgconsendwriteidx = 0;
680
            string = &string[bytes];
681
            space -= bytes;
682
            length -= bytes;
683
        }
684
        if (space) memcpy(&dbgconsendbuf[dbgconsendwriteidx], string, space);
685
        dbgconsendwriteidx += space;
686
        string = &string[space];
687
        length -= space;
688
    }
689
}
690
 
691
void dbgconsole_puts(const char* string)
692
{
693
    dbgconsole_write(string, strlen(string));
694
}
26 theseven 695
 
696
int dbgconsole_getavailable() ICODE_ATTR;
697
int dbgconsole_getavailable()
698
{
699
    int available = dbgconrecvwriteidx - dbgconrecvreadidx;
700
    if (available < 0) available += sizeof(dbgconrecvbuf);
701
    return available;
702
}
703
 
704
int dbgconsole_getc(int timeout)
705
{
706
    if (!dbgconsole_getavailable())
707
    {
708
        wakeup_wait(&dbgconrecvwakeup, TIMEOUT_NONE);
709
        if (!dbgconsole_getavailable())
710
        {
711
            wakeup_wait(&dbgconrecvwakeup, timeout);
712
            if (!dbgconsole_getavailable()) return -1;
713
        }
714
    }
715
    int byte = dbgconrecvbuf[dbgconrecvreadidx++];
716
    if (dbgconrecvreadidx >= sizeof(dbgconrecvbuf))
717
        dbgconrecvreadidx -= sizeof(dbgconrecvbuf);
718
    return byte;
719
}
720
 
721
int dbgconsole_read(char* buffer, size_t length, int timeout)
722
{
723
    if (!length) return 0;
724
    int available = dbgconsole_getavailable();
725
    if (!available)
726
    {
727
        wakeup_wait(&dbgconrecvwakeup, TIMEOUT_NONE);
728
        int available = dbgconsole_getavailable();
729
        if (!available)
730
        {
731
            wakeup_wait(&dbgconrecvwakeup, timeout);
732
            int available = dbgconsole_getavailable();
733
            if (!available) return 0;
734
        }
735
    }
736
    if (available > length) available = length;
737
    int left = available;
738
    if (dbgconrecvreadidx + available >= sizeof(dbgconrecvbuf))
739
    {
740
        int bytes = sizeof(dbgconrecvbuf) - dbgconrecvreadidx;
741
        memcpy(buffer, &dbgconrecvbuf[dbgconrecvreadidx], bytes);
742
        dbgconrecvreadidx = 0;
743
        buffer = &buffer[bytes];
744
        left -= bytes;
745
    }
746
    if (left) memcpy(buffer, &dbgconrecvbuf[dbgconrecvreadidx], left);
747
    dbgconrecvreadidx += left;
748
    return available;
749
}