Home | History | Annotate | Download | only in OpenglSystemCommon
      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         flush();
     44         ::close(m_sock);
     45     }
     46     if (m_buf != NULL) {
     47         free(m_buf);
     48     }
     49 }
     50 
     51 
     52 int QemuPipeStream::connect(void)
     53 {
     54     m_sock = qemu_pipe_open("opengles");
     55     if (!valid()) return -1;
     56     return 0;
     57 }
     58 
     59 void *QemuPipeStream::allocBuffer(size_t minSize)
     60 {
     61     size_t allocSize = (m_bufsize < minSize ? minSize : m_bufsize);
     62     if (!m_buf) {
     63         m_buf = (unsigned char *)malloc(allocSize);
     64     }
     65     else if (m_bufsize < allocSize) {
     66         unsigned char *p = (unsigned char *)realloc(m_buf, allocSize);
     67         if (p != NULL) {
     68             m_buf = p;
     69             m_bufsize = allocSize;
     70         } else {
     71             ERR("realloc (%d) failed\n", allocSize);
     72             free(m_buf);
     73             m_buf = NULL;
     74             m_bufsize = 0;
     75         }
     76     }
     77 
     78     return m_buf;
     79 };
     80 
     81 int QemuPipeStream::commitBuffer(size_t size)
     82 {
     83     return writeFully(m_buf, size);
     84 }
     85 
     86 int QemuPipeStream::writeFully(const void *buf, size_t len)
     87 {
     88     //DBG(">> QemuPipeStream::writeFully %d\n", len);
     89     if (!valid()) return -1;
     90     if (!buf) {
     91        if (len>0) {
     92             // If len is non-zero, buf must not be NULL. Otherwise the pipe would be
     93             // in a corrupted state, which is lethal for the emulator.
     94            ERR("QemuPipeStream::writeFully failed, buf=NULL, len %d,"
     95                    " lethal error, exiting", len);
     96            abort();
     97        }
     98        return 0;
     99     }
    100 
    101     size_t res = len;
    102     int retval = 0;
    103 
    104     while (res > 0) {
    105         ssize_t stat = ::write(m_sock, (const char *)(buf) + (len - res), res);
    106         if (stat > 0) {
    107             res -= stat;
    108             continue;
    109         }
    110         if (stat == 0) { /* EOF */
    111             ERR("QemuPipeStream::writeFully failed: premature EOF\n");
    112             retval = -1;
    113             break;
    114         }
    115         if (errno == EINTR) {
    116             continue;
    117         }
    118         retval =  stat;
    119         ERR("QemuPipeStream::writeFully failed: %s, lethal error, exiting.\n",
    120                 strerror(errno));
    121         abort();
    122     }
    123     //DBG("<< QemuPipeStream::writeFully %d\n", len );
    124     return retval;
    125 }
    126 
    127 const unsigned char *QemuPipeStream::readFully(void *buf, size_t len)
    128 {
    129     //DBG(">> QemuPipeStream::readFully %d\n", len);
    130     if (!valid()) return NULL;
    131     if (!buf) {
    132         if (len > 0) {
    133             // If len is non-zero, buf must not be NULL. Otherwise the pipe would be
    134             // in a corrupted state, which is lethal for the emulator.
    135             ERR("QemuPipeStream::readFully failed, buf=NULL, len %zu, lethal"
    136                     " error, exiting.", len);
    137             abort();
    138         }
    139         return NULL;  // do not allow NULL buf in that implementation
    140     }
    141     size_t res = len;
    142     while (res > 0) {
    143         ssize_t stat = ::read(m_sock, (char *)(buf) + len - res, res);
    144         if (stat == 0) {
    145             // client shutdown;
    146             return NULL;
    147         } else if (stat < 0) {
    148             if (errno == EINTR) {
    149                 continue;
    150             } else {
    151                 ERR("QemuPipeStream::readFully failed (buf %p, len %zu"
    152                     ", res %zu): %s, lethal error, exiting.", buf, len, res,
    153                     strerror(errno));
    154                 abort();
    155             }
    156         } else {
    157             res -= stat;
    158         }
    159     }
    160     //DBG("<< QemuPipeStream::readFully %d\n", len);
    161     return (const unsigned char *)buf;
    162 }
    163 
    164 const unsigned char *QemuPipeStream::read( void *buf, size_t *inout_len)
    165 {
    166     //DBG(">> QemuPipeStream::read %d\n", *inout_len);
    167     if (!valid()) return NULL;
    168     if (!buf) {
    169       ERR("QemuPipeStream::read failed, buf=NULL");
    170       return NULL;  // do not allow NULL buf in that implementation
    171     }
    172 
    173     int n = recv(buf, *inout_len);
    174 
    175     if (n > 0) {
    176         *inout_len = n;
    177         return (const unsigned char *)buf;
    178     }
    179 
    180     //DBG("<< QemuPipeStream::read %d\n", *inout_len);
    181     return NULL;
    182 }
    183 
    184 int QemuPipeStream::recv(void *buf, size_t len)
    185 {
    186     if (!valid()) return int(ERR_INVALID_SOCKET);
    187     char* p = (char *)buf;
    188     int ret = 0;
    189     while(len > 0) {
    190         int res = ::read(m_sock, p, len);
    191         if (res > 0) {
    192             p += res;
    193             ret += res;
    194             len -= res;
    195             continue;
    196         }
    197         if (res == 0) { /* EOF */
    198              break;
    199         }
    200         if (errno == EINTR)
    201             continue;
    202 
    203         /* A real error */
    204         if (ret == 0)
    205             ret = -1;
    206         break;
    207     }
    208     return ret;
    209 }
    210