blob: bcb58bdbcbba72ed458931ae80d9b1498e1b6d1f [file] [log] [blame]
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +00001//===-- AdbClient.cpp -------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// Other libraries and framework includes
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000011#include "llvm/ADT/SmallVector.h"
12#include "llvm/ADT/StringRef.h"
13#include "llvm/ADT/STLExtras.h"
14
15// Project includes
16#include "AdbClient.h"
17
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000018#include <algorithm>
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000019#include <sstream>
20
21using namespace lldb;
22using namespace lldb_private;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000023using namespace lldb_private::platform_android;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000024
25namespace {
26
27const uint32_t kConnTimeout = 10000; // 10 ms
28const char * kOKAY = "OKAY";
29const char * kFAIL = "FAIL";
30
31} // namespace
32
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000033Error
Chaoren Lin3ea689b2015-05-01 16:49:28 +000034AdbClient::CreateByDeviceID(const std::string &device_id, AdbClient &adb)
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000035{
36 DeviceIDList connect_devices;
Chaoren Lin3ea689b2015-05-01 16:49:28 +000037 auto error = adb.GetDevices(connect_devices);
38 if (error.Fail())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000039 return error;
40
Chaoren Lin3ea689b2015-05-01 16:49:28 +000041 if (device_id.empty())
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000042 {
Chaoren Lin3ea689b2015-05-01 16:49:28 +000043 if (connect_devices.size() != 1)
44 return Error("Expected a single connected device, got instead %" PRIu64,
45 static_cast<uint64_t>(connect_devices.size()));
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000046
Chaoren Lin3ea689b2015-05-01 16:49:28 +000047 adb.SetDeviceID(connect_devices.front());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000048 }
49 else
50 {
Chaoren Lin3ea689b2015-05-01 16:49:28 +000051 auto find_it = std::find(connect_devices.begin(), connect_devices.end(), device_id);
52 if (find_it == connect_devices.end())
53 return Error("Device \"%s\" not found", device_id.c_str());
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000054
Chaoren Lin3ea689b2015-05-01 16:49:28 +000055 adb.SetDeviceID(*find_it);
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000056 }
57 return error;
58}
59
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000060AdbClient::AdbClient (const std::string &device_id)
61 : m_device_id (device_id)
62{
63}
64
65void
66AdbClient::SetDeviceID (const std::string& device_id)
67{
68 m_device_id = device_id;
69}
70
Oleksiy Vyalov6f001062015-03-25 17:58:13 +000071const std::string&
72AdbClient::GetDeviceID() const
73{
74 return m_device_id;
75}
76
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +000077Error
78AdbClient::Connect ()
79{
80 Error error;
81 m_conn.Connect ("connect://localhost:5037", &error);
82
83 return error;
84}
85
86Error
87AdbClient::GetDevices (DeviceIDList &device_list)
88{
89 device_list.clear ();
90
91 auto error = SendMessage ("host:devices");
92 if (error.Fail ())
93 return error;
94
95 error = ReadResponseStatus ();
96 if (error.Fail ())
97 return error;
98
99 std::string in_buffer;
100 error = ReadMessage (in_buffer);
101
102 llvm::StringRef response (in_buffer);
103 llvm::SmallVector<llvm::StringRef, 4> devices;
104 response.split (devices, "\n", -1, false);
105
106 for (const auto device: devices)
107 device_list.push_back (device.split ('\t').first);
108
109 return error;
110}
111
112Error
113AdbClient::SetPortForwarding (const uint16_t port)
114{
115 char message[48];
116 snprintf (message, sizeof (message), "forward:tcp:%d;tcp:%d", port, port);
117
118 const auto error = SendDeviceMessage (message);
119 if (error.Fail ())
120 return error;
121
122 return ReadResponseStatus ();
123}
124
125Error
126AdbClient::DeletePortForwarding (const uint16_t port)
127{
128 char message[32];
129 snprintf (message, sizeof (message), "killforward:tcp:%d", port);
130
131 const auto error = SendDeviceMessage (message);
132 if (error.Fail ())
133 return error;
134
135 return ReadResponseStatus ();
136}
137
138Error
139AdbClient::SendMessage (const std::string &packet)
140{
141 auto error = Connect ();
142 if (error.Fail ())
143 return error;
144
145 char length_buffer[5];
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000146 snprintf (length_buffer, sizeof (length_buffer), "%04x", static_cast<int>(packet.size ()));
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000147
148 ConnectionStatus status;
149
150 m_conn.Write (length_buffer, 4, status, &error);
151 if (error.Fail ())
152 return error;
153
154 m_conn.Write (packet.c_str (), packet.size (), status, &error);
155 return error;
156}
157
158Error
159AdbClient::SendDeviceMessage (const std::string &packet)
160{
161 std::ostringstream msg;
162 msg << "host-serial:" << m_device_id << ":" << packet;
163 return SendMessage (msg.str ());
164}
165
166Error
167AdbClient::ReadMessage (std::string &message)
168{
169 message.clear ();
170
171 char buffer[5];
172 buffer[4] = 0;
173
174 Error error;
175 ConnectionStatus status;
176
177 m_conn.Read (buffer, 4, kConnTimeout, status, &error);
178 if (error.Fail ())
179 return error;
180
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000181 unsigned int packet_len = 0;
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000182 sscanf (buffer, "%x", &packet_len);
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000183 std::string result (packet_len, 0);
184 m_conn.Read (&result[0], packet_len, kConnTimeout, status, &error);
185 if (error.Success ())
186 result.swap (message);
187
188 return error;
189}
190
191Error
192AdbClient::ReadResponseStatus()
193{
194 char buffer[5];
195
196 static const size_t packet_len = 4;
197 buffer[packet_len] = 0;
198
199 Error error;
200 ConnectionStatus status;
201
202 m_conn.Read (buffer, packet_len, kConnTimeout, status, &error);
203 if (error.Fail ())
Oleksiy Vyalove17800c2015-04-10 03:59:52 +0000204 return error;
Oleksiy Vyalov05a55de2015-03-23 21:03:02 +0000205
206 if (strncmp (buffer, kOKAY, packet_len) != 0)
207 {
208 if (strncmp (buffer, kFAIL, packet_len) == 0)
209 {
210 std::string error_message;
211 error = ReadMessage (error_message);
212 if (error.Fail ())
213 return error;
214 error.SetErrorString (error_message.c_str ());
215 }
216 else
217 error.SetErrorStringWithFormat ("\"%s\" expected from adb, received: \"%s\"", kOKAY, buffer);
218 }
219
220 return error;
221}