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