1 /*
2  * Copyright (C) 2023 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 <string>
18 #include <qemud.h>
19 #include <qemu_pipe_bp.h>
20 #include <debug.h>
21 #include "qemu_channel.h"
22 
23 namespace android {
24 namespace hardware {
25 namespace camera {
26 namespace provider {
27 namespace implementation {
28 namespace hw {
29 namespace {
30 const char kServiceName[] = "camera";
31 
qemuReceiveMessage(const int fd,std::vector<uint8_t> * data)32 int qemuReceiveMessage(const int fd, std::vector<uint8_t>* data) {
33     char len16[9];
34     int e = qemu_pipe_read_fully(fd, len16, 8);
35     if (e < 0) {
36         return FAILURE(e);
37     }
38     len16[8] = 0;
39 
40     unsigned len;
41     if (sscanf(len16, "%x", &len) != 1) {
42         return FAILURE(-EINVAL);
43     }
44 
45     data->resize(len);
46     e = qemu_pipe_read_fully(fd, data->data(), len);
47     if (e < 0) {
48         return FAILURE(e);
49     }
50 
51     return 0;
52 }
53 
54 } // namespace
55 
qemuOpenChannel()56 base::unique_fd qemuOpenChannel() {
57     return base::unique_fd(qemud_channel_open(kServiceName));
58 }
59 
qemuOpenChannel(const std::string_view param)60 base::unique_fd qemuOpenChannel(const std::string_view param) {
61     if (param.empty()) {
62         return qemuOpenChannel();
63     } else {
64         return base::unique_fd(qemud_channel_open(
65             (std::string(kServiceName) + ":" +
66              std::string(param.begin(), param.end())).c_str()));
67     }
68 }
69 
qemuRunQuery(const int fd,const char * const query,const size_t querySize,std::vector<uint8_t> * result)70 int qemuRunQuery(const int fd,
71                  const char* const query,
72                  const size_t querySize,
73                  std::vector<uint8_t>* result) {
74     static const uint8_t kZero = 0;
75     static const uint8_t kSeparator = ' ';
76     static const uint8_t kColon = ':';
77 
78     int e = qemu_pipe_write_fully(fd, query, querySize);
79     if (e < 0) {
80         return FAILURE(e);
81     }
82 
83     std::vector<uint8_t> reply;
84     e = qemuReceiveMessage(fd, &reply);
85     if (e < 0) {
86         return e;
87     }
88 
89     if (reply.size() >= 3) {
90         bool ok;
91 
92         if (!memcmp(reply.data(), "ok", 2)) {
93             ok = true;
94         } else if (!memcmp(reply.data(), "ko", 2)) {
95             ok = false;
96         } else {
97             return FAILURE(-EBADE);
98         }
99 
100         switch (reply[2]) {
101         case kZero:
102             return ok ? 0 : FAILURE(-EBADE);
103 
104         case kColon:
105             if (!ok) {
106                 const int msgSize = reply.size() - 3;
107                 if (msgSize > 0) {
108                     return FAILURE_V(-EBADE, "failed to exec '%s' query with %.*s",
109                                      query, msgSize, &reply[3]);
110                 } else {
111                     return FAILURE_V(-EBADE, "failed to exec '%s' query", query);
112                 }
113             } else if (result) {
114                 reply.erase(reply.begin(), reply.begin() + 3);
115                 *result = std::move(reply);
116                 return result->size();
117             } else {
118                 return reply.size() - 3;
119             }
120 
121         default:
122             return FAILURE(-EBADE);
123         }
124     } else {
125         return FAILURE(-EBADE);
126     }
127 }
128 
129 }  // namespace hw
130 }  // namespace implementation
131 }  // namespace provider
132 }  // namespace camera
133 }  // namespace hardware
134 }  // namespace android
135