blob: 232c99929054148f694abb4eae7f93dcdfca558d [file] [log] [blame]
Colin Crossa3d386e2013-02-06 21:03:34 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Elliott Hughes0badbd62014-12-29 12:24:25 -080017#include <errno.h>
Colin Crossa3d386e2013-02-06 21:03:34 -080018#include <pthread.h>
19#include <stddef.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <unistd.h>
23#include <sys/mman.h>
24
25#include "debug.h"
26#include "protocol.h"
27#include "transport.h"
28
29#define COMMAND_BUF_SIZE 64
30
31ssize_t transport_handle_write(struct transport_handle *thandle, char *buffer, size_t len)
32{
33 return thandle->transport->write(thandle, buffer, len);
34}
35
36void transport_handle_close(struct transport_handle *thandle)
37{
38 thandle->transport->close(thandle);
39}
40
41int transport_handle_download(struct transport_handle *thandle, size_t len)
42{
43 ssize_t ret;
44 size_t n = 0;
45 int fd;
46 // TODO: move out of /dev
47 char tempname[] = "/dev/fastboot_download_XXXXXX";
48 char *buffer;
49
50 fd = mkstemp(tempname);
51 if (fd < 0)
52 return -1;
53
54 unlink(tempname);
55
56 ftruncate(fd, len);
57
58 buffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
Hurri Lu473a7292014-05-22 11:38:12 +080059 if (buffer == MAP_FAILED) {
Elliott Hughesccecf142014-01-16 10:53:11 -080060 D(ERR, "mmap(%zu) failed: %d %s", len, errno, strerror(errno));
Colin Crossa3d386e2013-02-06 21:03:34 -080061 goto err;
62 }
63
64 while (n < len) {
65 ret = thandle->transport->read(thandle, buffer + n, len - n);
66 if (ret <= 0) {
Elliott Hughesccecf142014-01-16 10:53:11 -080067 D(WARN, "transport read failed, ret=%zd %s", ret, strerror(-ret));
Colin Crossa3d386e2013-02-06 21:03:34 -080068 break;
69 }
70 n += ret;
71 }
72
73 munmap(buffer, len);
74
75 if (n != len)
76 goto err;
77
78 return fd;
79
80err:
81 close(fd);
82 transport_handle_close(thandle);
83 return -1;
84}
85
86static void *transport_data_thread(void *arg)
87{
88 struct transport_handle *thandle = arg;
89 struct protocol_handle *phandle = create_protocol_handle(thandle);
90
91 while (!thandle->stopped) {
92 int ret;
93 char buffer[COMMAND_BUF_SIZE + 1];
94 D(VERBOSE, "transport_data_thread\n");
95
96 ret = thandle->transport->read(thandle, buffer, COMMAND_BUF_SIZE);
97 if (ret <= 0) {
98 D(DEBUG, "ret = %d\n", ret);
99 break;
100 }
101 if (ret > 0) {
102 buffer[ret] = 0;
Szymon Starzycki2a656c32013-09-05 14:26:28 -0700103 //TODO: multiple threads
Colin Crossa3d386e2013-02-06 21:03:34 -0800104 protocol_handle_command(phandle, buffer);
105 }
106 }
107
108 transport_handle_close(thandle);
109 free(thandle);
110
111 return NULL;
112}
113
114static void *transport_connect_thread(void *arg)
115{
116 struct transport *transport = arg;
117 while (!transport->stopped) {
118 struct transport_handle *thandle;
119 pthread_t thread;
120 pthread_attr_t attr;
121
122 D(VERBOSE, "transport_connect_thread\n");
123 thandle = transport->connect(transport);
124 if (thandle == NULL) {
125 D(ERR, "transport connect failed\n");
126 sleep(1);
127 continue;
128 }
129 thandle->transport = transport;
130
131 pthread_attr_init(&attr);
132 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
133
134 pthread_create(&thread, &attr, transport_data_thread, thandle);
135
136 sleep(1);
137 }
138
139 return NULL;
140}
141
142void transport_register(struct transport *transport)
143{
144 pthread_t thread;
145 pthread_attr_t attr;
146
147 pthread_attr_init(&attr);
148 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
149
150 pthread_create(&thread, &attr, transport_connect_thread, transport);
151}