1a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross/*
2a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * Copyright (c) 2009-2013, Google Inc.
3a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * All rights reserved.
4a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross *
5a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * Redistribution and use in source and binary forms, with or without
6a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * modification, are permitted provided that the following conditions
7a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * are met:
8a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross *  * Redistributions of source code must retain the above copyright
9a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross *    notice, this list of conditions and the following disclaimer.
10a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross *  * Redistributions in binary form must reproduce the above copyright
11a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross *    notice, this list of conditions and the following disclaimer in
12a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross *    the documentation and/or other materials provided with the
13a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross *    distribution.
14a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross *  * Neither the name of Google, Inc. nor the names of its contributors
15a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross *    may be used to endorse or promote products derived from this
16a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross *    software without specific prior written permission.
17a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross *
18a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross * SUCH DAMAGE.
30a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross */
31a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
32a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#include <stddef.h>
33a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#include <stdio.h>
34a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#include <stdlib.h>
35a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#include <string.h>
36a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
37a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#include "debug.h"
38a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#include "protocol.h"
39a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#include "transport.h"
40a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
41a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#define STATE_OFFLINE   0
42a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#define STATE_COMMAND   1
43a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#define STATE_COMPLETE  2
44a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross#define STATE_ERROR     3
45a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
46a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossstruct fastboot_cmd {
47a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    struct fastboot_cmd *next;
48a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    const char *prefix;
49a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    unsigned prefix_len;
50a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    void (*execute)(struct protocol_handle *phandle, const char *arg);
51a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross};
52a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
53a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossstruct fastboot_var {
54a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    struct fastboot_var *next;
55a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    const char *name;
56a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    const char *value;
57a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross};
58a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
59a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossstatic struct fastboot_cmd *cmdlist;
60a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
61a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossvoid fastboot_register(const char *prefix,
62a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        void (*phandle)(struct protocol_handle *phandle, const char *arg))
63a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{
64a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    struct fastboot_cmd *cmd;
65a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    cmd = malloc(sizeof(*cmd));
66a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    if (cmd) {
67a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        cmd->prefix = prefix;
68a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        cmd->prefix_len = strlen(prefix);
69a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        cmd->execute = phandle;
70a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        cmd->next = cmdlist;
71a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        cmdlist = cmd;
72a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    }
73a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross}
74a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
75a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossstatic struct fastboot_var *varlist;
76a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
77a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossvoid fastboot_publish(const char *name, const char *value)
78a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{
79a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    struct fastboot_var *var;
80a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    var = malloc(sizeof(*var));
81a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    if (var) {
82a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        var->name = name;
83a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        var->value = value;
84a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        var->next = varlist;
85a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        varlist = var;
86a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    }
87a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross}
88a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
89a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossconst char *fastboot_getvar(const char *name)
90a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{
91a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    struct fastboot_var *var;
92a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
93a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    for (var = varlist; var; var = var->next) {
94a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        if (!strcmp(var->name, name)) {
95a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross            return var->value;
96a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        }
97a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    }
98a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
99a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    return "";
100a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross}
101a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
102a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossint protocol_handle_download(struct protocol_handle *phandle, size_t len)
103a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{
104a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    return transport_handle_download(phandle->transport_handle, len);
105a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross}
106a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
107a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossstatic ssize_t protocol_handle_write(struct protocol_handle *phandle,
108a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        char *buffer, size_t len)
109a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{
110a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    return transport_handle_write(phandle->transport_handle, buffer, len);
111a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross}
112a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
113a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossstatic void fastboot_ack(struct protocol_handle *phandle, const char *code,
114a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        const char *reason)
115a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{
116a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    char response[64];
117a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
118a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    if (phandle->state != STATE_COMMAND)
119a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        return;
120a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
121a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    if (reason == 0)
122a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        reason = "";
123a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
124a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    snprintf(response, 64, "%s%s", code, reason);
125a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    phandle->state = STATE_COMPLETE;
126a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
127a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    protocol_handle_write(phandle, response, strlen(response));
128a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross}
129a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
130a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossvoid fastboot_fail(struct protocol_handle *phandle, const char *reason)
131a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{
132a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    fastboot_ack(phandle, "FAIL", reason);
133a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross}
134a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
135a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossvoid fastboot_okay(struct protocol_handle *phandle, const char *info)
136a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{
137a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    fastboot_ack(phandle, "OKAY", info);
138a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross}
139a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
140a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossvoid fastboot_data(struct protocol_handle *phandle, size_t len)
141a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{
142a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    char response[64];
143a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    ssize_t ret;
144a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
145a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    snprintf(response, 64, "DATA%08x", len);
146a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    ret = protocol_handle_write(phandle, response, strlen(response));
147a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    if (ret < 0)
148a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        return;
149a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross}
150a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
151a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossvoid protocol_handle_command(struct protocol_handle *phandle, char *buffer)
152a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{
153a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    D(INFO,"fastboot: %s\n", buffer);
154a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
155a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    struct fastboot_cmd *cmd;
156a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
157a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    for (cmd = cmdlist; cmd; cmd = cmd->next) {
158a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        if (memcmp(buffer, cmd->prefix, cmd->prefix_len))
159a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross            continue;
160a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        phandle->state = STATE_COMMAND;
161a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        cmd->execute(phandle, buffer + cmd->prefix_len);
162a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        if (phandle->state == STATE_COMMAND)
163a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross            fastboot_fail(phandle, "unknown reason");
164a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross        return;
165a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    }
166a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
167a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    fastboot_fail(phandle, "unknown command");
168a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross}
169a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
170a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossstruct protocol_handle *create_protocol_handle(struct transport_handle *thandle)
171a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{
172a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    struct protocol_handle *phandle;
173a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
174a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    phandle = calloc(sizeof(struct protocol_handle), 1);
175a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
176a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    phandle->transport_handle = thandle;
177a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    phandle->state = STATE_OFFLINE;
178a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    phandle->download_fd = -1;
179a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
180a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    pthread_mutex_init(&phandle->lock, NULL);
181a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
182a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    return phandle;
183a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross}
184a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
185a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Crossint protocol_get_download(struct protocol_handle *phandle)
186a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross{
187a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    int fd;
188a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
189a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    pthread_mutex_lock(&phandle->lock);
190a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    fd = phandle->download_fd;
191a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    phandle->download_fd = -1;
192a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    pthread_mutex_unlock(&phandle->lock);
193a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross
194a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross    return fd;
195a3d386ea56ef53bb070b87ea7c28e103c5a53e45Colin Cross}
196