2009-03-19 01:39:47 +01:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2008 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef ANDROID_INCLUDE_HARDWARE_QEMUD_H
|
|
|
|
#define ANDROID_INCLUDE_HARDWARE_QEMUD_H
|
|
|
|
|
|
|
|
#include <cutils/sockets.h>
|
2011-08-04 22:52:12 +02:00
|
|
|
#include "qemu_pipe.h"
|
2009-03-19 01:39:47 +01:00
|
|
|
|
|
|
|
/* the following is helper code that is used by the QEMU-specific
|
|
|
|
* hardware HAL modules to communicate with the emulator program
|
2011-08-04 22:52:12 +02:00
|
|
|
* through the 'qemud' multiplexing daemon, or through the qemud
|
|
|
|
* pipe.
|
2009-03-19 01:39:47 +01:00
|
|
|
*
|
|
|
|
* see the documentation comments for details in
|
|
|
|
* development/emulator/qemud/qemud.c
|
|
|
|
*
|
|
|
|
* all definitions here are built into the HAL module to avoid
|
|
|
|
* having to write a tiny shared library for this.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* we expect the D macro to be defined to a function macro
|
|
|
|
* that sends its formatted string argument(s) to the log.
|
|
|
|
* If not, ignore the traces.
|
|
|
|
*/
|
|
|
|
#ifndef D
|
|
|
|
# define D(...) ((void)0)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static __inline__ int
|
|
|
|
qemud_fd_write(int fd, const void* buff, int len)
|
|
|
|
{
|
|
|
|
int len2;
|
|
|
|
do {
|
|
|
|
len2 = write(fd, buff, len);
|
|
|
|
} while (len2 < 0 && errno == EINTR);
|
|
|
|
return len2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ int
|
|
|
|
qemud_fd_read(int fd, void* buff, int len)
|
|
|
|
{
|
|
|
|
int len2;
|
|
|
|
do {
|
|
|
|
len2 = read(fd, buff, len);
|
|
|
|
} while (len2 < 0 && errno == EINTR);
|
|
|
|
return len2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ int
|
|
|
|
qemud_channel_open(const char* name)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
int namelen = strlen(name);
|
|
|
|
char answer[2];
|
2011-08-04 22:52:12 +02:00
|
|
|
char pipe_name[256];
|
2009-03-19 01:39:47 +01:00
|
|
|
|
2011-08-04 22:52:12 +02:00
|
|
|
/* First, try to connect to the pipe. */
|
|
|
|
snprintf(pipe_name, sizeof(pipe_name), "qemud:%s", name);
|
|
|
|
fd = qemu_pipe_open(pipe_name);
|
2009-03-19 01:39:47 +01:00
|
|
|
if (fd < 0) {
|
2011-08-04 22:52:12 +02:00
|
|
|
D("QEMUD pipe is not available for %s: %s", name, strerror(errno));
|
|
|
|
/* If pipe is not available, connect to qemud control socket */
|
|
|
|
fd = socket_local_client( "qemud",
|
|
|
|
ANDROID_SOCKET_NAMESPACE_RESERVED,
|
|
|
|
SOCK_STREAM );
|
|
|
|
if (fd < 0) {
|
|
|
|
D("no qemud control socket: %s", strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
2009-03-19 01:39:47 +01:00
|
|
|
|
2011-08-04 22:52:12 +02:00
|
|
|
/* send service name to connect */
|
|
|
|
if (qemud_fd_write(fd, name, namelen) != namelen) {
|
|
|
|
D("can't send service name to qemud: %s",
|
|
|
|
strerror(errno));
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-03-19 01:39:47 +01:00
|
|
|
|
2011-08-04 22:52:12 +02:00
|
|
|
/* read answer from daemon */
|
|
|
|
if (qemud_fd_read(fd, answer, 2) != 2 ||
|
|
|
|
answer[0] != 'O' || answer[1] != 'K') {
|
|
|
|
D("cant' connect to %s service through qemud", name);
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-03-19 01:39:47 +01:00
|
|
|
}
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ int
|
|
|
|
qemud_channel_send(int fd, const void* msg, int msglen)
|
|
|
|
{
|
|
|
|
char header[5];
|
|
|
|
|
|
|
|
if (msglen < 0)
|
|
|
|
msglen = strlen((const char*)msg);
|
|
|
|
|
|
|
|
if (msglen == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
snprintf(header, sizeof header, "%04x", msglen);
|
|
|
|
if (qemud_fd_write(fd, header, 4) != 4) {
|
|
|
|
D("can't write qemud frame header: %s", strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qemud_fd_write(fd, msg, msglen) != msglen) {
|
|
|
|
D("can4t write qemud frame payload: %s", strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ int
|
|
|
|
qemud_channel_recv(int fd, void* msg, int msgsize)
|
|
|
|
{
|
|
|
|
char header[5];
|
|
|
|
int size, avail;
|
|
|
|
|
|
|
|
if (qemud_fd_read(fd, header, 4) != 4) {
|
|
|
|
D("can't read qemud frame header: %s", strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
header[4] = 0;
|
|
|
|
if (sscanf(header, "%04x", &size) != 1) {
|
|
|
|
D("malformed qemud frame header: '%.*s'", 4, header);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (size > msgsize)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (qemud_fd_read(fd, msg, size) != size) {
|
|
|
|
D("can't read qemud frame payload: %s", strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* ANDROID_INCLUDE_HARDWARE_QEMUD_H */
|