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"
33
 
34
 
35
static uint8_t ctrlresp[2] CACHEALIGN_ATTR;
36
static uint32_t dbgrecvbuf[0x80] CACHEALIGN_ATTR;
37
static uint32_t dbgsendbuf[0x80] CACHEALIGN_ATTR;
38
static uint32_t dbgasyncsendbuf[0x80] CACHEALIGN_ATTR;
39
static char dbgendpoints[4] IBSS_ATTR;
40
 
41
enum dbgaction_t
42
{
43
    DBGACTION_IDLE = 0,
44
    DBGACTION_I2CSEND,
45
    DBGACTION_I2CRECV,
46
    DBGACTION_POWEROFF
47
};
48
 
49
static uint32_t dbgstack[0x100] STACK_ATTR;
50
struct wakeup dbgwakeup IBSS_ATTR;
51
extern struct scheduler_thread* scheduler_threads;
52
static enum dbgaction_t dbgaction IBSS_ATTR;
53
static int dbgi2cbus IBSS_ATTR;
54
static int dbgi2cslave IBSS_ATTR;
55
static int dbgi2caddr IBSS_ATTR;
56
static int dbgi2clen IBSS_ATTR;
57
 
58
 
59
static struct usb_device_descriptor CACHEALIGN_ATTR device_descriptor =
60
{
61
    .bLength            = sizeof(struct usb_device_descriptor),
62
    .bDescriptorType    = USB_DT_DEVICE,
63
    .bcdUSB             = 0x0200,
64
    .bDeviceClass       = USB_CLASS_VENDOR_SPEC,
65
    .bDeviceSubClass    = 0xff,
66
    .bDeviceProtocol    = 0xff,
67
    .bMaxPacketSize0    = 64,
68
    .idVendor           = 0xffff,
69
    .idProduct          = 0xe000,
70
    .bcdDevice          = 0x0001,
71
    .iManufacturer      = 1,
72
    .iProduct           = 2,
73
    .iSerialNumber      = 0,
74
    .bNumConfigurations = 1
75
};
76
 
77
static struct usb_config_bundle
78
{
79
    struct usb_config_descriptor config_descriptor;
80
    struct usb_interface_descriptor interface_descriptor;
81
    struct usb_endpoint_descriptor endpoint1_descriptor;
82
    struct usb_endpoint_descriptor endpoint2_descriptor;
83
    struct usb_endpoint_descriptor endpoint3_descriptor;
84
    struct usb_endpoint_descriptor endpoint4_descriptor;
85
} __attribute__((packed)) CACHEALIGN_ATTR config_bundle = 
86
{
87
    .config_descriptor =
88
    {
89
        .bLength             = sizeof(struct usb_config_descriptor),
90
        .bDescriptorType     = USB_DT_CONFIG,
91
        .wTotalLength        = sizeof(struct usb_config_descriptor)
92
                             + sizeof(struct usb_interface_descriptor)
93
                             + sizeof(struct usb_endpoint_descriptor) * 4,
94
        .bNumInterfaces      = 1,
95
        .bConfigurationValue = 1,
96
        .iConfiguration      = 0,
97
        .bmAttributes        = USB_CONFIG_ATT_ONE,
98
        .bMaxPower           = 250
99
    },
100
    .interface_descriptor =
101
    {
102
        .bLength             = sizeof(struct usb_interface_descriptor),
103
        .bDescriptorType     = USB_DT_INTERFACE,
104
        .bInterfaceNumber    = 0,
105
        .bAlternateSetting   = 0,
106
        .bNumEndpoints       = 4,
107
        .bInterfaceClass     = USB_CLASS_VENDOR_SPEC,
108
        .bInterfaceSubClass  = 0xff,
109
        .bInterfaceProtocol  = 0xff,
110
        .iInterface          = 0
111
    },
112
    .endpoint1_descriptor =
113
    {
114
        .bLength             = sizeof(struct usb_endpoint_descriptor),
115
        .bDescriptorType     = USB_DT_ENDPOINT,
116
        .bEndpointAddress    = 0,
117
        .bmAttributes        = USB_ENDPOINT_XFER_BULK,
118
        .wMaxPacketSize      = 0,
119
        .bInterval           = 1
120
    },
121
    .endpoint2_descriptor =
122
    {
123
        .bLength             = sizeof(struct usb_endpoint_descriptor),
124
        .bDescriptorType     = USB_DT_ENDPOINT,
125
        .bEndpointAddress    = 0,
126
        .bmAttributes        = USB_ENDPOINT_XFER_BULK,
127
        .wMaxPacketSize      = 0,
128
        .bInterval           = 1
129
    },
130
    .endpoint3_descriptor =
131
    {
132
        .bLength             = sizeof(struct usb_endpoint_descriptor),
133
        .bDescriptorType     = USB_DT_ENDPOINT,
134
        .bEndpointAddress    = 0,
135
        .bmAttributes        = USB_ENDPOINT_XFER_BULK,
136
        .wMaxPacketSize      = 0,
137
        .bInterval           = 1
138
    },
139
    .endpoint4_descriptor =
140
    {
141
        .bLength             = sizeof(struct usb_endpoint_descriptor),
142
        .bDescriptorType     = USB_DT_ENDPOINT,
143
        .bEndpointAddress    = 0,
144
        .bmAttributes        = USB_ENDPOINT_XFER_BULK,
145
        .wMaxPacketSize      = 0,
146
        .bInterval           = 1
147
    }
148
};
149
 
150
static struct usb_string_descriptor CACHEALIGN_ATTR string_devicename =
151
{
152
    32,
153
    USB_DT_STRING,
154
    {'e', 'm', 'B', 'I', 'O', 'S', ' ', 'D', 'e', 'b', 'u', 'g', 'g', 'e', 'r'}
155
};
156
 
157
static const struct usb_string_descriptor CACHEALIGN_ATTR lang_descriptor =
158
{
159
    4,
160
    USB_DT_STRING,
161
    {0x0409}
162
};
163
 
164
 
165
void usb_setup_dbg_listener()
166
{
167
    usb_drv_recv(dbgendpoints[0], dbgrecvbuf, usb_drv_port_speed() ? 512 : 64);
168
}
169
 
170
void usb_handle_control_request(struct usb_ctrlrequest* req)
171
{
172
    const void* addr;
173
    int size = -1;
174
    switch (req->bRequest)
175
    {
176
    case USB_REQ_GET_STATUS:
177
        if (req->bRequestType == USB_DIR_IN) ctrlresp[0] = 1;
178
        else ctrlresp[0] = 0;
179
        ctrlresp[1] = 0;
180
        addr = ctrlresp;
181
        size = 2;
182
        break;
183
    case USB_REQ_CLEAR_FEATURE:
184
        if (req->bRequestType == USB_RECIP_ENDPOINT && req->wValue == USB_ENDPOINT_HALT)
185
            usb_drv_stall(req->wIndex & 0xf, false, req->wIndex >> 7);
186
        size = 0;
187
        break;
188
    case USB_REQ_SET_FEATURE:
189
        size = 0;
190
        break;
191
    case USB_REQ_SET_ADDRESS:
192
        size = 0;
193
        usb_drv_cancel_all_transfers();
194
        usb_drv_set_address(req->wValue);
195
        usb_setup_dbg_listener();
196
        break;
197
    case USB_REQ_GET_DESCRIPTOR:
198
        switch (req->wValue >> 8)
199
        {
200
        case USB_DT_DEVICE:
201
            addr = &device_descriptor;
202
            size = sizeof(device_descriptor);
203
            break;
204
        case USB_DT_OTHER_SPEED_CONFIG:
205
        case USB_DT_CONFIG:
206
            if ((req->wValue >> 8) == USB_DT_CONFIG)
207
            {
208
                int maxpacket = usb_drv_port_speed() ? 512 : 64;
209
                config_bundle.endpoint1_descriptor.wMaxPacketSize = maxpacket;
210
                config_bundle.endpoint2_descriptor.wMaxPacketSize = maxpacket;
211
                config_bundle.endpoint3_descriptor.wMaxPacketSize = maxpacket;
212
                config_bundle.endpoint4_descriptor.wMaxPacketSize = maxpacket;
213
                config_bundle.config_descriptor.bDescriptorType = USB_DT_CONFIG;
214
            }
215
            else
216
            {
217
                int maxpacket = usb_drv_port_speed() ? 64 : 512;
218
                config_bundle.endpoint1_descriptor.wMaxPacketSize = maxpacket;
219
                config_bundle.endpoint2_descriptor.wMaxPacketSize = maxpacket;
220
                config_bundle.endpoint3_descriptor.wMaxPacketSize = maxpacket;
221
                config_bundle.endpoint4_descriptor.wMaxPacketSize = maxpacket;
222
                config_bundle.config_descriptor.bDescriptorType = USB_DT_OTHER_SPEED_CONFIG;
223
            }
224
            addr = &config_bundle;
225
            size = sizeof(config_bundle);
226
            break;
227
        case USB_DT_STRING:
228
            switch (req->wValue & 0xff)
229
            {
230
            case 0:
231
                addr = &lang_descriptor;
232
                size = sizeof(lang_descriptor);
233
                break;
234
            case 1:
235
                string_devicename.bLength = 14;
236
                addr = &string_devicename;
237
                size = 14;
238
            case 2:
239
                string_devicename.bLength = sizeof(string_devicename);
240
                addr = &string_devicename;
241
                size = sizeof(string_devicename);
242
                break;
243
            }
244
            break;
245
        }
246
        break;
247
    case USB_REQ_GET_CONFIGURATION:
248
        ctrlresp[0] = 1;
249
        addr = ctrlresp;
250
        size = 1;
251
        break;
252
    case USB_REQ_SET_CONFIGURATION:
253
        usb_drv_cancel_all_transfers();
254
        usb_setup_dbg_listener();
255
        size = 0;
256
        break;
257
    }
258
    if (!size) usb_drv_send_nonblocking(0, NULL, 0);
259
    else if (size == -1)
260
    {
261
        usb_drv_stall(0, true, true);
262
        usb_drv_stall(0, true, false);
263
    }
264
    else
265
    {
266
        usb_drv_recv(0, NULL, 0);
267
        usb_drv_send_nonblocking(0, addr, size > req->wLength ? req->wLength : size);
268
    }
269
}
270
 
271
bool set_dbgaction(enum dbgaction_t action)
272
{
273
    if (dbgaction != DBGACTION_IDLE)
274
    {
275
        dbgsendbuf[0] = 3;
276
        usb_drv_send_nonblocking(dbgendpoints[1], dbgsendbuf, 16);
277
        return true;
278
    }
279
    dbgaction = action;
280
    wakeup_signal(&dbgwakeup);
281
    return false;
282
}
283
 
284
void reset() __attribute__((noreturn));
285
 
286
void usb_handle_transfer_complete(int endpoint, int dir, int status, int length)
287
{
288
    void* addr = dbgsendbuf;
289
    int size = 0;
290
    if (endpoint == dbgendpoints[0])
291
    {
292
        switch (dbgrecvbuf[0])
293
        {
294
        case 1:  // GET VERSION
295
            dbgsendbuf[0] = 1;
296
            dbgsendbuf[1] = 0x01010000;
297
            dbgsendbuf[2] = PLATFORM_ID;
298
            dbgsendbuf[3] = usb_drv_port_speed() ? 0x02000200 : 0x00400040;
299
            size = 16;
300
            break;
301
        case 2:  // RESET
302
            reset();
303
            break;
304
        case 3:  // POWER OFF
305
            set_dbgaction(DBGACTION_POWEROFF);
306
            break;
307
        case 4:  // READ MEMORY
308
            dbgsendbuf[0] = 1;
309
            memcpy(&dbgsendbuf[4], (const void*)dbgrecvbuf[1], dbgrecvbuf[2]);
310
            size = dbgrecvbuf[2] + 16;
311
            break;
312
        case 5:  // WRITE MEMORY
313
            dbgsendbuf[0] = 1;
314
            memcpy((void*)dbgrecvbuf[1], &dbgrecvbuf[4], dbgrecvbuf[2]);
315
            size = 16;
316
            break;
317
        case 6:  // READ DMA
318
            dbgsendbuf[0] = 1;
319
            usb_drv_send_nonblocking(dbgendpoints[1], dbgsendbuf, 16);
320
            usb_drv_send_nonblocking(dbgendpoints[3], (const void*)dbgrecvbuf[1], dbgrecvbuf[2]);
321
            break;
322
        case 7:  // WRITE DMA
323
            dbgsendbuf[0] = 1;
324
            size = 16;
325
            usb_drv_recv(dbgendpoints[2], (void*)dbgrecvbuf[1], dbgrecvbuf[2]);
326
            break;
327
        case 8:  // READ I2C
328
            if (set_dbgaction(DBGACTION_I2CRECV)) break;
329
            dbgi2cbus = dbgrecvbuf[1] & 0xff;
330
            dbgi2cslave = (dbgrecvbuf[1] >> 8) & 0xff;
331
            dbgi2caddr = (dbgrecvbuf[1] >> 16) & 0xff;
332
            dbgi2clen = dbgrecvbuf[1] >> 24;
333
            break;
334
        case 9:  // WRITE I2C
335
            if (set_dbgaction(DBGACTION_I2CSEND)) break;
336
            dbgi2cbus = dbgrecvbuf[1] & 0xff;
337
            dbgi2cslave = (dbgrecvbuf[1] >> 8) & 0xff;
338
            dbgi2caddr = (dbgrecvbuf[1] >> 16) & 0xff;
339
            dbgi2clen = dbgrecvbuf[1] >> 24;
340
            memcpy(dbgasyncsendbuf, &dbgsendbuf[4], dbgi2clen);
341
            break;
342
        default:
343
            dbgsendbuf[0] = 2;
344
            size = 16;
345
        }
346
        usb_setup_dbg_listener();
347
        if (size) usb_drv_send_nonblocking(dbgendpoints[1], addr, size);
348
    }
349
}
350
 
351
void usb_handle_bus_reset(void)
352
{
353
    dbgendpoints[0] = usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_OUT);
354
    dbgendpoints[1] = usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_IN);
355
    dbgendpoints[2] = usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_OUT);
356
    dbgendpoints[3] = usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_IN);
357
    config_bundle.endpoint1_descriptor.bEndpointAddress = dbgendpoints[0];
358
    config_bundle.endpoint2_descriptor.bEndpointAddress = dbgendpoints[1];
359
    config_bundle.endpoint3_descriptor.bEndpointAddress = dbgendpoints[2];
360
    config_bundle.endpoint4_descriptor.bEndpointAddress = dbgendpoints[3];
361
    usb_setup_dbg_listener();
362
}
363
 
364
void dbgthread(void)
365
{
366
    int i;
367
    while (1)
368
    {
369
        wakeup_wait(&dbgwakeup, TIMEOUT_BLOCK);
370
        for (i = 0; i < MAX_THREADS; i++)
371
            if (scheduler_threads[i].state == THREAD_DEFUNCT)
372
            {
373
                if (scheduler_threads[i].block_type == THREAD_DEFUNCT_STKOV)
374
                    cprintf(1, "\n*PANIC*\nStack overflow! (%s)\n",
375
                            scheduler_threads[i].name);
376
                scheduler_threads[i].state = THREAD_DEFUNCT_ACK;
377
            }
378
        if (dbgaction != DBGACTION_IDLE)
379
        {
380
            switch (dbgaction)
381
            {
382
            case DBGACTION_I2CSEND:
383
                i2c_send(dbgi2cbus, dbgi2cslave, dbgi2caddr, (uint8_t*)dbgasyncsendbuf, dbgi2clen);
384
                dbgasyncsendbuf[0] = 1;
385
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
386
                break;
387
            case DBGACTION_I2CRECV:
388
                i2c_recv(dbgi2cbus, dbgi2cslave, dbgi2caddr,
389
                         (uint8_t*)(&dbgasyncsendbuf[4]), dbgi2clen);
390
                dbgasyncsendbuf[0] = 1;
391
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16 + dbgi2clen);
392
                break;
393
            case DBGACTION_POWEROFF:
394
                break;
395
            }
396
            dbgaction = DBGACTION_IDLE;
397
        }
398
    }
399
}
400
 
401
void usb_init(void)
402
{
403
    dbgaction = DBGACTION_IDLE;
404
    wakeup_init(&dbgwakeup);
405
    thread_create("Debugger", dbgthread, dbgstack, sizeof(dbgstack), 255, SYSTEM_THREAD, true);
406
    usb_drv_init();
407
}