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