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