1 /* 2 * Copyright (C) 2011 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 #include "QemuPipeStream.h" 17 #include <hardware/qemu_pipe.h> 18 #include <errno.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <unistd.h> 22 #include <string.h> 23 24 QemuPipeStream::QemuPipeStream(size_t bufSize) : 25 IOStream(bufSize), 26 m_sock(-1), 27 m_bufsize(bufSize), 28 m_buf(NULL) 29 { 30 } 31 32 QemuPipeStream::QemuPipeStream(int sock, size_t bufSize) : 33 IOStream(bufSize), 34 m_sock(sock), 35 m_bufsize(bufSize), 36 m_buf(NULL) 37 { 38 } 39 40 QemuPipeStream::~QemuPipeStream() 41 { 42 if (m_sock >= 0) { 43 ::close(m_sock); 44 } 45 if (m_buf != NULL) { 46 free(m_buf); 47 } 48 } 49 50 51 int QemuPipeStream::connect(void) 52 { 53 m_sock = qemu_pipe_open("opengles"); 54 if (!valid()) return -1; 55 return 0; 56 } 57 58 void *QemuPipeStream::allocBuffer(size_t minSize) 59 { 60 size_t allocSize = (m_bufsize < minSize ? minSize : m_bufsize); 61 if (!m_buf) { 62 m_buf = (unsigned char *)malloc(allocSize); 63 } 64 else if (m_bufsize < allocSize) { 65 unsigned char *p = (unsigned char *)realloc(m_buf, allocSize); 66 if (p != NULL) { 67 m_buf = p; 68 m_bufsize = allocSize; 69 } else { 70 ERR("realloc (%d) failed\n", allocSize); 71 free(m_buf); 72 m_buf = NULL; 73 m_bufsize = 0; 74 } 75 } 76 77 return m_buf; 78 }; 79 80 int QemuPipeStream::commitBuffer(size_t size) 81 { 82 return writeFully(m_buf, size); 83 } 84 85 int QemuPipeStream::writeFully(const void *buf, size_t len) 86 { 87 //DBG(">> QemuPipeStream::writeFully %d\n", len); 88 if (!valid()) return -1; 89 90 size_t res = len; 91 int retval = 0; 92 93 while (res > 0) { 94 ssize_t stat = ::write(m_sock, (const char *)(buf) + (len - res), res); 95 if (stat > 0) { 96 res -= stat; 97 continue; 98 } 99 if (stat == 0) { /* EOF */ 100 ERR("QemuPipeStream::writeFully failed: premature EOF\n"); 101 retval = -1; 102 break; 103 } 104 if (errno == EINTR) { 105 continue; 106 } 107 retval = stat; 108 ERR("QemuPipeStream::writeFully failed: %s\n", strerror(errno)); 109 break; 110 } 111 //DBG("<< QemuPipeStream::writeFully %d\n", len ); 112 return retval; 113 } 114 115 const unsigned char *QemuPipeStream::readFully(void *buf, size_t len) 116 { 117 //DBG(">> QemuPipeStream::readFully %d\n", len); 118 if (!valid()) return NULL; 119 if (!buf) { 120 if (len>0) ERR("QemuPipeStream::readFully failed, buf=NULL, len %d", len); 121 return NULL; // do not allow NULL buf in that implementation 122 } 123 size_t res = len; 124 while (res > 0) { 125 ssize_t stat = ::read(m_sock, (char *)(buf) + len - res, len); 126 if (stat == 0) { 127 // client shutdown; 128 return NULL; 129 } else if (stat < 0) { 130 if (errno == EINTR) { 131 continue; 132 } else { 133 ERR("QemuPipeStream::readFully failed (buf %p): %s\n", 134 buf, strerror(errno)); 135 return NULL; 136 } 137 } else { 138 res -= stat; 139 } 140 } 141 //DBG("<< QemuPipeStream::readFully %d\n", len); 142 return (const unsigned char *)buf; 143 } 144 145 const unsigned char *QemuPipeStream::read( void *buf, size_t *inout_len) 146 { 147 //DBG(">> QemuPipeStream::read %d\n", *inout_len); 148 if (!valid()) return NULL; 149 if (!buf) { 150 ERR("QemuPipeStream::read failed, buf=NULL"); 151 return NULL; // do not allow NULL buf in that implementation 152 } 153 154 int n = recv(buf, *inout_len); 155 156 if (n > 0) { 157 *inout_len = n; 158 return (const unsigned char *)buf; 159 } 160 161 //DBG("<< QemuPipeStream::read %d\n", *inout_len); 162 return NULL; 163 } 164 165 int QemuPipeStream::recv(void *buf, size_t len) 166 { 167 if (!valid()) return int(ERR_INVALID_SOCKET); 168 char* p = (char *)buf; 169 int ret = 0; 170 while(len > 0) { 171 int res = ::read(m_sock, p, len); 172 if (res > 0) { 173 p += res; 174 ret += res; 175 len -= res; 176 continue; 177 } 178 if (res == 0) { /* EOF */ 179 break; 180 } 181 if (errno == EINTR) 182 continue; 183 184 /* A real error */ 185 if (ret == 0) 186 ret = -1; 187 break; 188 } 189 return ret; 190 } 191