blob: 6f1841f8adf6098b360d267f0e5e8706d7ed0087 [file] [log] [blame]
Brian Swetland9c4c0752009-01-25 16:23:50 -08001/*
2 * Copyright (c) 2009, Google Inc.
3 * All rights reserved.
4 *
Channagoud Kadabi03550162015-03-10 13:32:27 -07005 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Deepa Dinamani26bc2d32013-03-15 13:17:16 -07006 *
Brian Swetland9c4c0752009-01-25 16:23:50 -08007 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
Deepa Dinamani26bc2d32013-03-15 13:17:16 -070010 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
Brian Swetland9c4c0752009-01-25 16:23:50 -080013 * notice, this list of conditions and the following disclaimer in
Deepa Dinamani26bc2d32013-03-15 13:17:16 -070014 * the documentation and/or other materials provided with the
Brian Swetland9c4c0752009-01-25 16:23:50 -080015 * distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
Deepa Dinamani26bc2d32013-03-15 13:17:16 -070024 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
Brian Swetland9c4c0752009-01-25 16:23:50 -080025 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
27 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <debug.h>
32#include <string.h>
33#include <stdlib.h>
Deepa Dinamani0bf2f442012-10-19 11:41:06 -070034#include <platform.h>
Amol Jadi5edf3552013-07-23 14:15:34 -070035#include <target.h>
Brian Swetland9c4c0752009-01-25 16:23:50 -080036#include <kernel/thread.h>
37#include <kernel/event.h>
38#include <dev/udc.h>
Channagoud Kadabia0930b92013-04-16 15:14:37 -070039#include "fastboot.h"
Brian Swetland9c4c0752009-01-25 16:23:50 -080040
Amol Jadi7c4316c2013-10-07 14:19:26 -070041#ifdef USB30_SUPPORT
42#include <usb30_udc.h>
43#endif
44
45typedef struct
46{
47 int (*udc_init)(struct udc_device *devinfo);
48 int (*udc_register_gadget)(struct udc_gadget *gadget);
49 int (*udc_start)(void);
50 int (*udc_stop)(void);
51
52 struct udc_endpoint *(*udc_endpoint_alloc)(unsigned type, unsigned maxpkt);
53 void (*udc_endpoint_free)(struct udc_endpoint *ept);
54 struct udc_request *(*udc_request_alloc)(void);
55 void (*udc_request_free)(struct udc_request *req);
56
57 int (*usb_read)(void *buf, unsigned len);
58 int (*usb_write)(void *buf, unsigned len);
59} usb_controller_interface_t;
60
61usb_controller_interface_t usb_if;
62
Hanumant Singh108cdc62012-12-11 16:48:49 -080063#define MAX_USBFS_BULK_SIZE (32 * 1024)
Channagoud Kadabi87823802014-11-05 13:10:05 -080064#define MAX_USBSS_BULK_SIZE (0x1000000)
Shashank Mittal6a5609f2011-08-04 15:51:59 -070065
Brian Swetland9c4c0752009-01-25 16:23:50 -080066void boot_linux(void *bootimg, unsigned sz);
Amol Jadi5edf3552013-07-23 14:15:34 -070067static void fastboot_notify(struct udc_gadget *gadget, unsigned event);
68static struct udc_endpoint *fastboot_endpoints[2];
69
70static struct udc_device surf_udc_device = {
71 .vendor_id = 0x18d1,
72 .product_id = 0xD00D,
73 .version_id = 0x0100,
74 .manufacturer = "Google",
75 .product = "Android",
76};
77
78static struct udc_gadget fastboot_gadget = {
79 .notify = fastboot_notify,
80 .ifc_class = 0xff,
81 .ifc_subclass = 0x42,
82 .ifc_protocol = 0x03,
83 .ifc_endpoints = 2,
84 .ifc_string = "fastboot",
85 .ept = fastboot_endpoints,
86};
Brian Swetland9c4c0752009-01-25 16:23:50 -080087
88/* todo: give lk strtoul and nuke this */
89static unsigned hex2unsigned(const char *x)
90{
91 unsigned n = 0;
92
93 while(*x) {
94 switch(*x) {
95 case '0': case '1': case '2': case '3': case '4':
96 case '5': case '6': case '7': case '8': case '9':
97 n = (n << 4) | (*x - '0');
98 break;
99 case 'a': case 'b': case 'c':
100 case 'd': case 'e': case 'f':
101 n = (n << 4) | (*x - 'a' + 10);
102 break;
103 case 'A': case 'B': case 'C':
104 case 'D': case 'E': case 'F':
105 n = (n << 4) | (*x - 'A' + 10);
106 break;
107 default:
108 return n;
109 }
110 x++;
111 }
112
113 return n;
114}
115
116struct fastboot_cmd {
117 struct fastboot_cmd *next;
118 const char *prefix;
119 unsigned prefix_len;
120 void (*handle)(const char *arg, void *data, unsigned sz);
121};
122
123struct fastboot_var {
124 struct fastboot_var *next;
125 const char *name;
126 const char *value;
127};
Amol Jadi5edf3552013-07-23 14:15:34 -0700128
Brian Swetland9c4c0752009-01-25 16:23:50 -0800129static struct fastboot_cmd *cmdlist;
130
131void fastboot_register(const char *prefix,
132 void (*handle)(const char *arg, void *data, unsigned sz))
133{
134 struct fastboot_cmd *cmd;
135 cmd = malloc(sizeof(*cmd));
136 if (cmd) {
137 cmd->prefix = prefix;
138 cmd->prefix_len = strlen(prefix);
139 cmd->handle = handle;
140 cmd->next = cmdlist;
141 cmdlist = cmd;
142 }
143}
144
145static struct fastboot_var *varlist;
146
147void fastboot_publish(const char *name, const char *value)
148{
149 struct fastboot_var *var;
150 var = malloc(sizeof(*var));
151 if (var) {
152 var->name = name;
153 var->value = value;
154 var->next = varlist;
155 varlist = var;
156 }
157}
158
159
160static event_t usb_online;
161static event_t txn_done;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800162static struct udc_endpoint *in, *out;
163static struct udc_request *req;
164int txn_status;
165
166static void *download_base;
167static unsigned download_max;
168static unsigned download_size;
169
170#define STATE_OFFLINE 0
171#define STATE_COMMAND 1
172#define STATE_COMPLETE 2
173#define STATE_ERROR 3
174
175static unsigned fastboot_state = STATE_OFFLINE;
176
177static void req_complete(struct udc_request *req, unsigned actual, int status)
178{
179 txn_status = status;
180 req->length = actual;
Hanumant Singh108cdc62012-12-11 16:48:49 -0800181
Brian Swetland9c4c0752009-01-25 16:23:50 -0800182 event_signal(&txn_done, 0);
183}
184
Amol Jadi5e52d722013-08-19 17:10:33 -0700185#ifdef USB30_SUPPORT
Channagoud Kadabi87823802014-11-05 13:10:05 -0800186static int usb30_usb_read(void *_buf, unsigned len)
Amol Jadi5e52d722013-08-19 17:10:33 -0700187{
188 int r;
189 struct udc_request req;
Channagoud Kadabi87823802014-11-05 13:10:05 -0800190 uint32_t xfer;
191 int count = 0;
192 uint32_t trans_len = len;
193 const char *buf = _buf;
Amol Jadi5e52d722013-08-19 17:10:33 -0700194
195 ASSERT(buf);
196 ASSERT(len);
197
198 if (fastboot_state == STATE_ERROR)
199 goto oops;
200
201 dprintf(SPEW, "usb_read(): len = %d\n", len);
202
Channagoud Kadabi87823802014-11-05 13:10:05 -0800203 while (len > 0)
Amol Jadi5e52d722013-08-19 17:10:33 -0700204 {
Channagoud Kadabi87823802014-11-05 13:10:05 -0800205 xfer = (len > MAX_USBSS_BULK_SIZE) ? MAX_USBSS_BULK_SIZE : len;
Amol Jadi5e52d722013-08-19 17:10:33 -0700206
Channagoud Kadabi87823802014-11-05 13:10:05 -0800207 req.buf = (void*) PA((addr_t)buf);
208 req.length = xfer;
209 req.complete = req_complete;
Amol Jadi5e52d722013-08-19 17:10:33 -0700210
Channagoud Kadabi87823802014-11-05 13:10:05 -0800211 r = usb30_udc_request_queue(out, &req);
212 if (r < 0)
213 {
214 dprintf(CRITICAL, "usb_read() queue failed. r = %d\n", r);
215 goto oops;
216 }
217 event_wait(&txn_done);
218
219 if (txn_status < 0)
220 {
221 dprintf(CRITICAL, "usb_read() transaction failed. txn_status = %d\n",
222 txn_status);
223 goto oops;
224 }
225
226 count += req.length;
227 buf += req.length;
228 len -= req.length;
229
230 /* note: req.length is update by callback to reflect the amount of data
231 * actually read.
232 */
233 dprintf(SPEW, "usb_read(): DONE. req.length = %d\n\n", req.length);
234
235 /* For USB3.0 if the data transfer is less than MaxpacketSize, its
236 * short packet and DWC layer generates transfer complete. App layer
237 * shold handle this and continue trasnferring the data instead of treating
238 * this as a transfer complete. This case is not applicable for transfers
239 * which involve protocol communication to exchange information whose length
240 * is always equal to MAX_RSP_SIZE. This check ensures that we dont abort
241 * data transfers on short packet.
242 */
243 if (req.length != xfer && trans_len == MAX_RSP_SIZE) break;
244 }
Amol Jadi5e52d722013-08-19 17:10:33 -0700245
246 /* invalidate any cached buf data (controller updates main memory) */
Channagoud Kadabi87823802014-11-05 13:10:05 -0800247 arch_invalidate_cache_range((addr_t) _buf, count);
Amol Jadi5e52d722013-08-19 17:10:33 -0700248
Channagoud Kadabi87823802014-11-05 13:10:05 -0800249 return count;
Amol Jadi5e52d722013-08-19 17:10:33 -0700250
251oops:
252 fastboot_state = STATE_ERROR;
253 dprintf(CRITICAL, "usb_read(): DONE: ERROR: len = %d\n", len);
254 return -1;
255}
256
Amol Jadi7c4316c2013-10-07 14:19:26 -0700257static int usb30_usb_write(void *buf, unsigned len)
Amol Jadi5e52d722013-08-19 17:10:33 -0700258{
259 int r;
260 struct udc_request req;
261
262 ASSERT(buf);
263 ASSERT(len);
264
265 if (fastboot_state == STATE_ERROR)
266 goto oops;
267
268 dprintf(SPEW, "usb_write(): len = %d str = %s\n", len, (char *) buf);
269
270 /* flush buffer to main memory before giving to udc */
271 arch_clean_invalidate_cache_range((addr_t) buf, len);
272
273 req.buf = (void*) PA((addr_t)buf);
274 req.length = len;
275 req.complete = req_complete;
276
Amol Jadi7c4316c2013-10-07 14:19:26 -0700277 r = usb30_udc_request_queue(in, &req);
Amol Jadi5e52d722013-08-19 17:10:33 -0700278 if (r < 0) {
279 dprintf(CRITICAL, "usb_write() queue failed. r = %d\n", r);
280 goto oops;
281 }
282 event_wait(&txn_done);
283
284 dprintf(SPEW, "usb_write(): DONE: len = %d req->length = %d str = %s\n",
285 len, req.length, (char *) buf);
286
287 if (txn_status < 0) {
288 dprintf(CRITICAL, "usb_write() transaction failed. txn_status = %d\n",
289 txn_status);
290 goto oops;
291 }
292
293 return req.length;
294
295oops:
296 fastboot_state = STATE_ERROR;
297 dprintf(CRITICAL, "usb_write(): DONE: ERROR: len = %d\n", len);
298 return -1;
299}
Amol Jadi7c4316c2013-10-07 14:19:26 -0700300#endif
Amol Jadi5e52d722013-08-19 17:10:33 -0700301
Amol Jadi7c4316c2013-10-07 14:19:26 -0700302static int hsusb_usb_read(void *_buf, unsigned len)
Brian Swetland9c4c0752009-01-25 16:23:50 -0800303{
304 int r;
305 unsigned xfer;
306 unsigned char *buf = _buf;
307 int count = 0;
308
309 if (fastboot_state == STATE_ERROR)
310 goto oops;
311
312 while (len > 0) {
Shashank Mittal1cc65b02011-12-20 15:30:17 -0800313 xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530314 req->buf = (unsigned char *)PA((addr_t)buf);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800315 req->length = xfer;
316 req->complete = req_complete;
317 r = udc_request_queue(out, req);
318 if (r < 0) {
319 dprintf(INFO, "usb_read() queue failed\n");
320 goto oops;
321 }
322 event_wait(&txn_done);
323
324 if (txn_status < 0) {
325 dprintf(INFO, "usb_read() transaction failed\n");
326 goto oops;
327 }
328
329 count += req->length;
330 buf += req->length;
331 len -= req->length;
332
333 /* short transfer? */
334 if (req->length != xfer) break;
335 }
Hanumant Singh108cdc62012-12-11 16:48:49 -0800336 /*
337 * Force reload of buffer from memory
338 * since transaction is complete now.
339 */
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530340 arch_invalidate_cache_range((addr_t)_buf, count);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800341 return count;
342
343oops:
344 fastboot_state = STATE_ERROR;
345 return -1;
346}
347
Amol Jadi7c4316c2013-10-07 14:19:26 -0700348static int hsusb_usb_write(void *buf, unsigned len)
Brian Swetland9c4c0752009-01-25 16:23:50 -0800349{
350 int r;
Channagoud Kadabiad50b6a2014-04-07 17:56:05 -0700351 uint32_t xfer;
352 unsigned char *_buf = buf;
353 int count = 0;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800354
355 if (fastboot_state == STATE_ERROR)
356 goto oops;
357
Channagoud Kadabiad50b6a2014-04-07 17:56:05 -0700358 while (len > 0) {
359 xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530360 req->buf = (unsigned char *)PA((addr_t)_buf);
Channagoud Kadabiad50b6a2014-04-07 17:56:05 -0700361 req->length = xfer;
362 req->complete = req_complete;
363 r = udc_request_queue(in, req);
364 if (r < 0) {
365 dprintf(INFO, "usb_write() queue failed\n");
366 goto oops;
367 }
368 event_wait(&txn_done);
369 if (txn_status < 0) {
370 dprintf(INFO, "usb_write() transaction failed\n");
371 goto oops;
372 }
373
374 count += req->length;
375 _buf += req->length;
376 len -= req->length;
377
378 /* short transfer? */
379 if (req->length != xfer) break;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800380 }
Channagoud Kadabiad50b6a2014-04-07 17:56:05 -0700381
382 return count;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800383
384oops:
385 fastboot_state = STATE_ERROR;
386 return -1;
387}
388
389void fastboot_ack(const char *code, const char *reason)
390{
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700391 STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800392
393 if (fastboot_state != STATE_COMMAND)
394 return;
395
396 if (reason == 0)
397 reason = "";
398
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530399 snprintf((char *)response, MAX_RSP_SIZE, "%s%s", code, reason);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800400 fastboot_state = STATE_COMPLETE;
401
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530402 usb_if.usb_write(response, strlen((const char *)response));
Brian Swetland9c4c0752009-01-25 16:23:50 -0800403
404}
405
Shashank Mittal6a5609f2011-08-04 15:51:59 -0700406void fastboot_info(const char *reason)
407{
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700408 STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
Shashank Mittal6a5609f2011-08-04 15:51:59 -0700409
410 if (fastboot_state != STATE_COMMAND)
411 return;
412
413 if (reason == 0)
414 return;
415
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530416 snprintf((char *)response, MAX_RSP_SIZE, "INFO%s", reason);
Shashank Mittal6a5609f2011-08-04 15:51:59 -0700417
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530418 usb_if.usb_write(response, strlen((const char *)response));
Shashank Mittal6a5609f2011-08-04 15:51:59 -0700419}
420
Brian Swetland9c4c0752009-01-25 16:23:50 -0800421void fastboot_fail(const char *reason)
422{
423 fastboot_ack("FAIL", reason);
424}
425
426void fastboot_okay(const char *info)
427{
428 fastboot_ack("OKAY", info);
429}
430
Channagoud Kadabi03550162015-03-10 13:32:27 -0700431static void getvar_all()
432{
433 struct fastboot_var *var;
434 char getvar_all[64];
435
436 for (var = varlist; var; var = var->next)
437 {
438 strlcpy((char *) getvar_all, var->name, sizeof(getvar_all));
439 strlcat((char *) getvar_all, ":", sizeof(getvar_all));
440 strlcat((char *) getvar_all, var->value, sizeof(getvar_all));
441 fastboot_info(getvar_all);
442 memset((void *) getvar_all, '\0', sizeof(getvar_all));
443 }
444 fastboot_okay("");
445}
446
Brian Swetland9c4c0752009-01-25 16:23:50 -0800447static void cmd_getvar(const char *arg, void *data, unsigned sz)
448{
449 struct fastboot_var *var;
450
Channagoud Kadabi03550162015-03-10 13:32:27 -0700451 if (!strncmp("all", arg, strlen(arg)))
452 {
453 getvar_all();
454 return;
455 }
456
Brian Swetland9c4c0752009-01-25 16:23:50 -0800457 for (var = varlist; var; var = var->next) {
458 if (!strcmp(var->name, arg)) {
459 fastboot_okay(var->value);
460 return;
461 }
462 }
463 fastboot_okay("");
464}
465
466static void cmd_download(const char *arg, void *data, unsigned sz)
467{
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700468 STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800469 unsigned len = hex2unsigned(arg);
470 int r;
471
472 download_size = 0;
473 if (len > download_max) {
474 fastboot_fail("data too large");
475 return;
476 }
477
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530478 snprintf((char *)response, MAX_RSP_SIZE, "DATA%08x", len);
479 if (usb_if.usb_write(response, strlen((const char *)response)) < 0)
Brian Swetland9c4c0752009-01-25 16:23:50 -0800480 return;
Channagoud Kadabi5389f372015-02-27 15:26:28 -0800481 /*
482 * Discard the cache contents before starting the download
483 */
484 arch_invalidate_cache_range((addr_t) download_base, sz);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800485
Amol Jadi7c4316c2013-10-07 14:19:26 -0700486 r = usb_if.usb_read(download_base, len);
Greg Griscod6250552011-06-29 14:40:23 -0700487 if ((r < 0) || ((unsigned) r != len)) {
Brian Swetland9c4c0752009-01-25 16:23:50 -0800488 fastboot_state = STATE_ERROR;
489 return;
490 }
491 download_size = len;
492 fastboot_okay("");
493}
494
495static void fastboot_command_loop(void)
496{
497 struct fastboot_cmd *cmd;
498 int r;
499 dprintf(INFO,"fastboot: processing commands\n");
500
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700501 uint8_t *buffer = (uint8_t *)memalign(CACHE_LINE, ROUNDUP(4096, CACHE_LINE));
502 if (!buffer)
503 {
504 dprintf(CRITICAL, "Could not allocate memory for fastboot buffer\n.");
505 ASSERT(0);
506 }
Brian Swetland9c4c0752009-01-25 16:23:50 -0800507again:
508 while (fastboot_state != STATE_ERROR) {
Amol Jadi5edf3552013-07-23 14:15:34 -0700509
510 /* Read buffer must be cleared first. If buffer is not cleared,
511 * the original data in buf trailing the received command is
512 * interpreted as part of the command.
513 */
514 memset(buffer, 0, MAX_RSP_SIZE);
515 arch_clean_invalidate_cache_range((addr_t) buffer, MAX_RSP_SIZE);
516
Amol Jadi7c4316c2013-10-07 14:19:26 -0700517 r = usb_if.usb_read(buffer, MAX_RSP_SIZE);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800518 if (r < 0) break;
519 buffer[r] = 0;
520 dprintf(INFO,"fastboot: %s\n", buffer);
521
Channagoud Kadabi69c16732013-12-05 17:29:18 -0800522 fastboot_state = STATE_COMMAND;
523
Brian Swetland9c4c0752009-01-25 16:23:50 -0800524 for (cmd = cmdlist; cmd; cmd = cmd->next) {
525 if (memcmp(buffer, cmd->prefix, cmd->prefix_len))
526 continue;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800527 cmd->handle((const char*) buffer + cmd->prefix_len,
528 (void*) download_base, download_size);
529 if (fastboot_state == STATE_COMMAND)
530 fastboot_fail("unknown reason");
531 goto again;
532 }
533
534 fastboot_fail("unknown command");
Amol Jadi5edf3552013-07-23 14:15:34 -0700535
Brian Swetland9c4c0752009-01-25 16:23:50 -0800536 }
537 fastboot_state = STATE_OFFLINE;
538 dprintf(INFO,"fastboot: oops!\n");
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700539 free(buffer);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800540}
541
542static int fastboot_handler(void *arg)
543{
544 for (;;) {
545 event_wait(&usb_online);
546 fastboot_command_loop();
547 }
548 return 0;
549}
550
551static void fastboot_notify(struct udc_gadget *gadget, unsigned event)
552{
553 if (event == UDC_EVENT_ONLINE) {
554 event_signal(&usb_online, 0);
555 }
556}
557
Brian Swetland9c4c0752009-01-25 16:23:50 -0800558int fastboot_init(void *base, unsigned size)
559{
Amol Jadi5edf3552013-07-23 14:15:34 -0700560 char sn_buf[13];
Brian Swetland9c4c0752009-01-25 16:23:50 -0800561 thread_t *thr;
562 dprintf(INFO, "fastboot_init()\n");
563
564 download_base = base;
565 download_max = size;
566
Amol Jadi5edf3552013-07-23 14:15:34 -0700567 /* target specific initialization before going into fastboot. */
568 target_fastboot_init();
569
570 /* setup serialno */
571 target_serialno((unsigned char *) sn_buf);
572 dprintf(SPEW,"serial number: %s\n",sn_buf);
573 surf_udc_device.serialno = sn_buf;
574
Amol Jadi7c4316c2013-10-07 14:19:26 -0700575 if(!strcmp(target_usb_controller(), "dwc"))
576 {
577#ifdef USB30_SUPPORT
Channagoud Kadabi728ef0a2014-02-04 17:11:08 -0800578 surf_udc_device.t_usb_if = target_usb30_init();
579
Amol Jadi7c4316c2013-10-07 14:19:26 -0700580 /* initialize udc functions to use dwc controller */
581 usb_if.udc_init = usb30_udc_init;
582 usb_if.udc_register_gadget = usb30_udc_register_gadget;
583 usb_if.udc_start = usb30_udc_start;
584 usb_if.udc_stop = usb30_udc_stop;
585
586 usb_if.udc_endpoint_alloc = usb30_udc_endpoint_alloc;
587 usb_if.udc_request_alloc = usb30_udc_request_alloc;
588 usb_if.udc_request_free = usb30_udc_request_free;
589
590 usb_if.usb_read = usb30_usb_read;
591 usb_if.usb_write = usb30_usb_write;
592#else
593 dprintf(CRITICAL, "USB30 needs to be enabled for this target.\n");
594 ASSERT(0);
595#endif
596 }
597 else
598 {
599 /* initialize udc functions to use the default chipidea controller */
600 usb_if.udc_init = udc_init;
601 usb_if.udc_register_gadget = udc_register_gadget;
602 usb_if.udc_start = udc_start;
603 usb_if.udc_stop = udc_stop;
604
605 usb_if.udc_endpoint_alloc = udc_endpoint_alloc;
606 usb_if.udc_request_alloc = udc_request_alloc;
607 usb_if.udc_request_free = udc_request_free;
608
609 usb_if.usb_read = hsusb_usb_read;
610 usb_if.usb_write = hsusb_usb_write;
611 }
612
Amol Jadi5edf3552013-07-23 14:15:34 -0700613 /* register udc device */
Amol Jadi7c4316c2013-10-07 14:19:26 -0700614 usb_if.udc_init(&surf_udc_device);
Amol Jadi5edf3552013-07-23 14:15:34 -0700615
Brian Swetland9c4c0752009-01-25 16:23:50 -0800616 event_init(&usb_online, 0, EVENT_FLAG_AUTOUNSIGNAL);
617 event_init(&txn_done, 0, EVENT_FLAG_AUTOUNSIGNAL);
618
Amol Jadi7c4316c2013-10-07 14:19:26 -0700619 in = usb_if.udc_endpoint_alloc(UDC_TYPE_BULK_IN, 512);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800620 if (!in)
621 goto fail_alloc_in;
Amol Jadi7c4316c2013-10-07 14:19:26 -0700622 out = usb_if.udc_endpoint_alloc(UDC_TYPE_BULK_OUT, 512);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800623 if (!out)
624 goto fail_alloc_out;
625
626 fastboot_endpoints[0] = in;
627 fastboot_endpoints[1] = out;
628
Amol Jadi7c4316c2013-10-07 14:19:26 -0700629 req = usb_if.udc_request_alloc();
Brian Swetland9c4c0752009-01-25 16:23:50 -0800630 if (!req)
631 goto fail_alloc_req;
632
Amol Jadi5edf3552013-07-23 14:15:34 -0700633 /* register gadget */
Amol Jadi7c4316c2013-10-07 14:19:26 -0700634 if (usb_if.udc_register_gadget(&fastboot_gadget))
Brian Swetland9c4c0752009-01-25 16:23:50 -0800635 goto fail_udc_register;
636
637 fastboot_register("getvar:", cmd_getvar);
638 fastboot_register("download:", cmd_download);
639 fastboot_publish("version", "0.5");
640
641 thr = thread_create("fastboot", fastboot_handler, 0, DEFAULT_PRIORITY, 4096);
neetid32ba8472011-12-07 16:34:06 -0800642 if (!thr)
643 {
644 goto fail_alloc_in;
645 }
Brian Swetland9c4c0752009-01-25 16:23:50 -0800646 thread_resume(thr);
Amol Jadi5edf3552013-07-23 14:15:34 -0700647
Amol Jadi7c4316c2013-10-07 14:19:26 -0700648 usb_if.udc_start();
Amol Jadi5edf3552013-07-23 14:15:34 -0700649
Brian Swetland9c4c0752009-01-25 16:23:50 -0800650 return 0;
651
652fail_udc_register:
Amol Jadi7c4316c2013-10-07 14:19:26 -0700653 usb_if.udc_request_free(req);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800654fail_alloc_req:
Amol Jadi7c4316c2013-10-07 14:19:26 -0700655 usb_if.udc_endpoint_free(out);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800656fail_alloc_out:
Amol Jadi7c4316c2013-10-07 14:19:26 -0700657 usb_if.udc_endpoint_free(in);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800658fail_alloc_in:
659 return -1;
660}
Amol Jadi7c4316c2013-10-07 14:19:26 -0700661
662void fastboot_stop(void)
663{
664 usb_if.udc_stop();
665}