1 /* 2 * Copyright (C) 2008 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 #ifndef ANDROID_INCLUDE_HARDWARE_QEMUD_H 18 #define ANDROID_INCLUDE_HARDWARE_QEMUD_H 19 20 #include <cutils/sockets.h> 21 #include "qemu_pipe.h" 22 23 /* the following is helper code that is used by the QEMU-specific 24 * hardware HAL modules to communicate with the emulator program 25 * through the 'qemud' multiplexing daemon, or through the qemud 26 * pipe. 27 * 28 * see the documentation comments for details in 29 * development/emulator/qemud/qemud.c 30 * 31 * all definitions here are built into the HAL module to avoid 32 * having to write a tiny shared library for this. 33 */ 34 35 /* we expect the D macro to be defined to a function macro 36 * that sends its formatted string argument(s) to the log. 37 * If not, ignore the traces. 38 */ 39 #ifndef D 40 # define D(...) do{}while(0) 41 #endif 42 43 44 static __inline__ int 45 qemud_channel_open(const char* name) 46 { 47 int fd; 48 int namelen = strlen(name); 49 char answer[2]; 50 char pipe_name[256]; 51 52 /* First, try to connect to the pipe. */ 53 snprintf(pipe_name, sizeof(pipe_name), "qemud:%s", name); 54 fd = qemu_pipe_open(pipe_name); 55 D("%s: pipe name %s (name %s) fd %d", __FUNCTION__, pipe_name, name, fd); 56 if (fd < 0) { 57 D("QEMUD pipe is not available for %s: %s", name, strerror(errno)); 58 /* If pipe is not available, connect to qemud control socket */ 59 fd = socket_local_client( "qemud", 60 ANDROID_SOCKET_NAMESPACE_RESERVED, 61 SOCK_STREAM ); 62 if (fd < 0) { 63 D("no qemud control socket: %s", strerror(errno)); 64 return -1; 65 } 66 67 /* send service name to connect */ 68 if (!WriteFully(fd, name, namelen)) { 69 D("can't send service name to qemud: %s", 70 strerror(errno)); 71 close(fd); 72 return -1; 73 } 74 75 /* read answer from daemon */ 76 if (!ReadFully(fd, answer, 2) || 77 answer[0] != 'O' || answer[1] != 'K') { 78 D("cant' connect to %s service through qemud", name); 79 close(fd); 80 return -1; 81 } 82 } 83 return fd; 84 } 85 86 static __inline__ int 87 qemud_channel_send(int fd, const void* msg, int msglen) 88 { 89 char header[5]; 90 91 if (msglen < 0) 92 msglen = strlen((const char*)msg); 93 94 if (msglen == 0) 95 return 0; 96 97 snprintf(header, sizeof header, "%04x", msglen); 98 if (!WriteFully(fd, header, 4)) { 99 D("can't write qemud frame header: %s", strerror(errno)); 100 return -1; 101 } 102 103 if (!WriteFully(fd, msg, msglen)) { 104 D("can4t write qemud frame payload: %s", strerror(errno)); 105 return -1; 106 } 107 return 0; 108 } 109 110 static __inline__ int 111 qemud_channel_recv(int fd, void* msg, int msgsize) 112 { 113 char header[5]; 114 int size; 115 116 if (!ReadFully(fd, header, 4)) { 117 D("can't read qemud frame header: %s", strerror(errno)); 118 return -1; 119 } 120 header[4] = 0; 121 if (sscanf(header, "%04x", &size) != 1) { 122 D("malformed qemud frame header: '%.*s'", 4, header); 123 return -1; 124 } 125 if (size > msgsize) 126 return -1; 127 128 if (!ReadFully(fd, msg, size)) { 129 D("can't read qemud frame payload: %s", strerror(errno)); 130 return -1; 131 } 132 return size; 133 } 134 135 #endif /* ANDROID_INCLUDE_HARDWARE_QEMUD_H */ 136