blob: 3ba0e9a9d40fa63f057aa7679f6e7b46c87cc89b [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>
Elliott Hughesa744b052015-01-28 11:37:57 -080022#include <string.h>
Colin Crossa3d386e2013-02-06 21:03:34 -080023#include <unistd.h>
24#include <sys/mman.h>
25
26#include "debug.h"
27#include "protocol.h"
28#include "transport.h"
29
30#define COMMAND_BUF_SIZE 64
31
32ssize_t transport_handle_write(struct transport_handle *thandle, char *buffer, size_t len)
33{
34 return thandle->transport->write(thandle, buffer, len);
35}
36
37void transport_handle_close(struct transport_handle *thandle)
38{
39 thandle->transport->close(thandle);
40}
41
42int transport_handle_download(struct transport_handle *thandle, size_t len)
43{
44 ssize_t ret;
45 size_t n = 0;
46 int fd;
47 // TODO: move out of /dev
48 char tempname[] = "/dev/fastboot_download_XXXXXX";
49 char *buffer;
50
51 fd = mkstemp(tempname);
52 if (fd < 0)
53 return -1;
54
55 unlink(tempname);
56
57 ftruncate(fd, len);
58
59 buffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
Hurri Lu473a7292014-05-22 11:38:12 +080060 if (buffer == MAP_FAILED) {
Elliott Hughesccecf142014-01-16 10:53:11 -080061 D(ERR, "mmap(%zu) failed: %d %s", len, errno, strerror(errno));
Colin Crossa3d386e2013-02-06 21:03:34 -080062 goto err;
63 }
64
65 while (n < len) {
66 ret = thandle->transport->read(thandle, buffer + n, len - n);
67 if (ret <= 0) {
Elliott Hughesccecf142014-01-16 10:53:11 -080068 D(WARN, "transport read failed, ret=%zd %s", ret, strerror(-ret));
Colin Crossa3d386e2013-02-06 21:03:34 -080069 break;
70 }
71 n += ret;
72 }
73
74 munmap(buffer, len);
75
76 if (n != len)
77 goto err;
78
79 return fd;
80
81err:
82 close(fd);
83 transport_handle_close(thandle);
84 return -1;
85}
86
87static void *transport_data_thread(void *arg)
88{
89 struct transport_handle *thandle = arg;
90 struct protocol_handle *phandle = create_protocol_handle(thandle);
91
92 while (!thandle->stopped) {
93 int ret;
94 char buffer[COMMAND_BUF_SIZE + 1];
95 D(VERBOSE, "transport_data_thread\n");
96
97 ret = thandle->transport->read(thandle, buffer, COMMAND_BUF_SIZE);
98 if (ret <= 0) {
99 D(DEBUG, "ret = %d\n", ret);
100 break;
101 }
102 if (ret > 0) {
103 buffer[ret] = 0;
Szymon Starzycki2a656c32013-09-05 14:26:28 -0700104 //TODO: multiple threads
Colin Crossa3d386e2013-02-06 21:03:34 -0800105 protocol_handle_command(phandle, buffer);
106 }
107 }
108
109 transport_handle_close(thandle);
110 free(thandle);
111
112 return NULL;
113}
114
115static void *transport_connect_thread(void *arg)
116{
117 struct transport *transport = arg;
118 while (!transport->stopped) {
119 struct transport_handle *thandle;
120 pthread_t thread;
121 pthread_attr_t attr;
122
123 D(VERBOSE, "transport_connect_thread\n");
124 thandle = transport->connect(transport);
125 if (thandle == NULL) {
126 D(ERR, "transport connect failed\n");
127 sleep(1);
128 continue;
129 }
130 thandle->transport = transport;
131
132 pthread_attr_init(&attr);
133 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
134
135 pthread_create(&thread, &attr, transport_data_thread, thandle);
136
137 sleep(1);
138 }
139
140 return NULL;
141}
142
143void transport_register(struct transport *transport)
144{
145 pthread_t thread;
146 pthread_attr_t attr;
147
148 pthread_attr_init(&attr);
149 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
150
151 pthread_create(&thread, &attr, transport_connect_thread, transport);
152}