Subversion Repositories freemyipod

Rev

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