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 
     91     size_t res = len;
     92     int retval = 0;
     93 
     94     while (res > 0) {
     95         ssize_t stat = ::write(m_sock, (const char *)(buf) + (len - res), res);
     96         if (stat > 0) {
     97             res -= stat;
     98             continue;
     99         }
    100         if (stat == 0) { /* EOF */
    101             ERR("QemuPipeStream::writeFully failed: premature EOF\n");
    102             retval = -1;
    103             break;
    104         }
    105         if (errno == EINTR) {
    106             continue;
    107         }
    108         retval =  stat;
    109         ERR("QemuPipeStream::writeFully failed: %s\n", strerror(errno));
    110         break;
    111     }
    112     //DBG("<< QemuPipeStream::writeFully %d\n", len );
    113     return retval;
    114 }
    115 
    116 const unsigned char *QemuPipeStream::readFully(void *buf, size_t len)
    117 {
    118     //DBG(">> QemuPipeStream::readFully %d\n", len);
    119     if (!valid()) return NULL;
    120     if (!buf) {
    121         if (len>0) ERR("QemuPipeStream::readFully failed, buf=NULL, len %d", len);
    122         return NULL;  // do not allow NULL buf in that implementation
    123     }
    124     size_t res = len;
    125     while (res > 0) {
    126         ssize_t stat = ::read(m_sock, (char *)(buf) + len - res, len);
    127         if (stat == 0) {
    128             // client shutdown;
    129             return NULL;
    130         } else if (stat < 0) {
    131             if (errno == EINTR) {
    132                 continue;
    133             } else {
    134                 ERR("QemuPipeStream::readFully failed (buf %p): %s\n",
    135                     buf, strerror(errno));
    136                 return NULL;
    137             }
    138         } else {
    139             res -= stat;
    140         }
    141     }
    142     //DBG("<< QemuPipeStream::readFully %d\n", len);
    143     return (const unsigned char *)buf;
    144 }
    145 
    146 const unsigned char *QemuPipeStream::read( void *buf, size_t *inout_len)
    147 {
    148     //DBG(">> QemuPipeStream::read %d\n", *inout_len);
    149     if (!valid()) return NULL;
    150     if (!buf) {
    151       ERR("QemuPipeStream::read failed, buf=NULL");
    152       return NULL;  // do not allow NULL buf in that implementation
    153     }
    154 
    155     int n = recv(buf, *inout_len);
    156 
    157     if (n > 0) {
    158         *inout_len = n;
    159         return (const unsigned char *)buf;
    160     }
    161 
    162     //DBG("<< QemuPipeStream::read %d\n", *inout_len);
    163     return NULL;
    164 }
    165 
    166 int QemuPipeStream::recv(void *buf, size_t len)
    167 {
    168     if (!valid()) return int(ERR_INVALID_SOCKET);
    169     char* p = (char *)buf;
    170     int ret = 0;
    171     while(len > 0) {
    172         int res = ::read(m_sock, p, len);
    173         if (res > 0) {
    174             p += res;
    175             ret += res;
    176             len -= res;
    177             continue;
    178         }
    179         if (res == 0) { /* EOF */
    180              break;
    181         }
    182         if (errno == EINTR)
    183             continue;
    184 
    185         /* A real error */
    186         if (ret == 0)
    187             ret = -1;
    188         break;
    189     }
    190     return ret;
    191 }
    192