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