1/* Copyright (C) 2007-2008 The Android Open Source Project
2**
3** This software is licensed under the terms of the GNU General Public
4** License version 2, as published by the Free Software Foundation, and
5** may be copied, distributed, and modified under those terms.
6**
7** This program is distributed in the hope that it will be useful,
8** but WITHOUT ANY WARRANTY; without even the implied warranty of
9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10** GNU General Public License for more details.
11*/
12#include "sysemu/char.h"
13#include "android/cbuffer.h"
14#include "android/qemu-debug.h"
15
16#define  xxDEBUG
17
18#ifdef DEBUG
19#  include <stdio.h>
20#  define  D(...)   ( fprintf( stderr, __VA_ARGS__ ), fprintf(stderr, "\n") )
21#else
22#  define  D(...)   ((void)0)
23#endif
24
25/* we want to implement a bi-directionnal communication channel
26 * between two QEMU character drivers that merge well into the
27 * QEMU event loop.
28 *
29 * each half of the channel has its own object and buffer, and
30 * we implement communication through charpipe_poll() which
31 * must be called by the main event loop after its call to select()
32 *
33 */
34
35#define  BIP_BUFFER_SIZE  512
36
37typedef struct BipBuffer {
38    struct BipBuffer*  next;
39    CBuffer            cb[1];
40    char               buff[ BIP_BUFFER_SIZE ];
41} BipBuffer;
42
43static BipBuffer*  _free_bip_buffers;
44
45static BipBuffer*
46bip_buffer_alloc( void )
47{
48    BipBuffer*  bip = _free_bip_buffers;
49    if (bip != NULL) {
50        _free_bip_buffers = bip->next;
51    } else {
52        bip = malloc( sizeof(*bip) );
53        if (bip == NULL) {
54            derror( "%s: not enough memory", __FUNCTION__ );
55            exit(1);
56        }
57    }
58    bip->next = NULL;
59    cbuffer_reset( bip->cb, bip->buff, sizeof(bip->buff) );
60    return bip;
61}
62
63static void
64bip_buffer_free( BipBuffer*  bip )
65{
66    bip->next         = _free_bip_buffers;
67    _free_bip_buffers = bip;
68}
69
70/* this models each half of the charpipe */
71typedef struct CharPipeHalf {
72    CharDriverState       cs[1];
73    BipBuffer*            bip_first;
74    BipBuffer*            bip_last;
75    struct CharPipeHalf*  peer;         /* NULL if closed */
76} CharPipeHalf;
77
78
79
80static void
81charpipehalf_close( CharDriverState*  cs )
82{
83    CharPipeHalf*  ph = cs->opaque;
84
85    while (ph->bip_first) {
86        BipBuffer*  bip = ph->bip_first;
87        ph->bip_first = bip->next;
88        bip_buffer_free(bip);
89    }
90    ph->bip_last    = NULL;
91    ph->peer        = NULL;
92}
93
94
95static int
96charpipehalf_write( CharDriverState*  cs, const uint8_t*  buf, int  len )
97{
98    CharPipeHalf*  ph   = cs->opaque;
99    CharPipeHalf*  peer = ph->peer;
100    BipBuffer*     bip  = ph->bip_last;
101    int            ret  = 0;
102
103    D("%s: writing %d bytes to %p: '%s'", __FUNCTION__,
104      len, ph, quote_bytes( buf, len ));
105
106    if (bip == NULL && peer != NULL && peer->cs->chr_read != NULL) {
107        /* no buffered data, try to write directly to the peer */
108        while (len > 0) {
109            int  size;
110
111            if (peer->cs->chr_can_read) {
112                size = qemu_chr_can_read( peer->cs );
113                if (size == 0)
114                    break;
115
116                if (size > len)
117                    size = len;
118            } else
119                size = len;
120
121            qemu_chr_read( peer->cs, (uint8_t*)buf, size );
122            buf += size;
123            len -= size;
124            ret += size;
125        }
126    }
127
128    if (len == 0)
129        return ret;
130
131    /* buffer the remaining data */
132    if (bip == NULL) {
133        bip = bip_buffer_alloc();
134        ph->bip_first = ph->bip_last = bip;
135    }
136
137    while (len > 0) {
138        int  len2 = cbuffer_write( bip->cb, buf, len );
139
140        buf += len2;
141        ret += len2;
142        len -= len2;
143        if (len == 0)
144            break;
145
146        /* ok, we need another buffer */
147        ph->bip_last = bip_buffer_alloc();
148        bip->next = ph->bip_last;
149        bip       = ph->bip_last;
150    }
151    return  ret;
152}
153
154
155static void
156charpipehalf_poll( CharPipeHalf*  ph )
157{
158    CharPipeHalf*   peer = ph->peer;
159    int             size;
160
161    if (peer == NULL || peer->cs->chr_read == NULL)
162        return;
163
164    while (1) {
165        BipBuffer*  bip = ph->bip_first;
166        uint8_t*    base;
167        int         avail;
168
169        if (bip == NULL)
170            break;
171
172        size = cbuffer_read_avail(bip->cb);
173        if (size == 0) {
174            ph->bip_first = bip->next;
175            if (ph->bip_first == NULL)
176                ph->bip_last = NULL;
177            bip_buffer_free(bip);
178            continue;
179        }
180
181        if (ph->cs->chr_can_read) {
182            int  size2 = qemu_chr_can_read(peer->cs);
183
184            if (size2 == 0)
185                break;
186
187            if (size > size2)
188                size = size2;
189        }
190
191        avail = cbuffer_read_peek( bip->cb, &base );
192        if (avail > size)
193            avail = size;
194        D("%s: sending %d bytes from %p: '%s'", __FUNCTION__,
195            avail, ph, quote_bytes( base, avail ));
196
197        qemu_chr_read( peer->cs, base, avail );
198        cbuffer_read_step( bip->cb, avail );
199    }
200}
201
202
203static void
204charpipehalf_init( CharPipeHalf*  ph, CharPipeHalf*  peer )
205{
206    CharDriverState*  cs = ph->cs;
207
208    ph->bip_first   = NULL;
209    ph->bip_last    = NULL;
210    ph->peer        = peer;
211
212    cs->chr_write            = charpipehalf_write;
213    cs->chr_ioctl            = NULL;
214    cs->chr_send_event       = NULL;
215    cs->chr_close            = charpipehalf_close;
216    cs->opaque               = ph;
217}
218
219
220typedef struct CharPipeState {
221    CharPipeHalf  a[1];
222    CharPipeHalf  b[1];
223} CharPipeState;
224
225
226
227#define   MAX_CHAR_PIPES   8
228
229static CharPipeState  _s_charpipes[ MAX_CHAR_PIPES ];
230
231int
232qemu_chr_open_charpipe( CharDriverState*  *pfirst, CharDriverState*  *psecond )
233{
234    CharPipeState*  cp     = _s_charpipes;
235    CharPipeState*  cp_end = cp + MAX_CHAR_PIPES;
236
237    for ( ; cp < cp_end; cp++ ) {
238        if ( cp->a->peer == NULL && cp->b->peer == NULL )
239            break;
240    }
241
242    if (cp == cp_end) {  /* can't allocate one */
243        *pfirst  = NULL;
244        *psecond = NULL;
245        return -1;
246    }
247
248    charpipehalf_init( cp->a, cp->b );
249    charpipehalf_init( cp->b, cp->a );
250
251    *pfirst  = cp->a->cs;
252    *psecond = cp->b->cs;
253    return 0;
254}
255
256/** This models a charbuffer, an object used to buffer
257 ** the data that is sent to a given endpoint CharDriverState
258 ** object.
259 **
260 ** On the other hand, any can_read() / read() request performed
261 ** by the endpoint will be passed to the CharBuffer's corresponding
262 ** handlers.
263 **/
264
265typedef struct CharBuffer {
266    CharDriverState  cs[1];
267    BipBuffer*       bip_first;
268    BipBuffer*       bip_last;
269    CharDriverState* endpoint;  /* NULL if closed */
270    char             closing;
271} CharBuffer;
272
273
274static void
275charbuffer_close( CharDriverState*  cs )
276{
277    CharBuffer*  cbuf = cs->opaque;
278
279    while (cbuf->bip_first) {
280        BipBuffer*  bip = cbuf->bip_first;
281        cbuf->bip_first = bip->next;
282        bip_buffer_free(bip);
283    }
284    cbuf->bip_last = NULL;
285    cbuf->endpoint = NULL;
286
287    if (cbuf->endpoint != NULL) {
288        qemu_chr_close(cbuf->endpoint);
289        cbuf->endpoint = NULL;
290    }
291}
292
293static int
294charbuffer_write( CharDriverState*  cs, const uint8_t*  buf, int  len )
295{
296    CharBuffer*       cbuf = cs->opaque;
297    CharDriverState*  peer = cbuf->endpoint;
298    BipBuffer*        bip  = cbuf->bip_last;
299    int               ret  = 0;
300
301    D("%s: writing %d bytes to %p: '%s'", __FUNCTION__,
302      len, cbuf, quote_bytes( buf, len ));
303
304    if (bip == NULL && peer != NULL) {
305        /* no buffered data, try to write directly to the peer */
306        int  size = qemu_chr_write(peer, buf, len);
307
308        if (size < 0)  /* just to be safe */
309            size = 0;
310        else if (size > len)
311            size = len;
312
313        buf += size;
314        ret += size;
315        len -= size;
316    }
317
318    if (len == 0)
319        return ret;
320
321    /* buffer the remaining data */
322    if (bip == NULL) {
323        bip = bip_buffer_alloc();
324        cbuf->bip_first = cbuf->bip_last = bip;
325    }
326
327    while (len > 0) {
328        int  len2 = cbuffer_write( bip->cb, buf, len );
329
330        buf += len2;
331        ret += len2;
332        len -= len2;
333        if (len == 0)
334            break;
335
336        /* ok, we need another buffer */
337        cbuf->bip_last = bip_buffer_alloc();
338        bip->next = cbuf->bip_last;
339        bip       = cbuf->bip_last;
340    }
341    return  ret;
342}
343
344
345static void
346charbuffer_poll( CharBuffer*  cbuf )
347{
348    CharDriverState*  peer = cbuf->endpoint;
349
350    if (peer == NULL)
351        return;
352
353    while (1) {
354        BipBuffer*  bip = cbuf->bip_first;
355        uint8_t*    base;
356        int         avail;
357        int         size;
358
359        if (bip == NULL)
360            break;
361
362        avail = cbuffer_read_peek( bip->cb, &base );
363        if (avail == 0) {
364            cbuf->bip_first = bip->next;
365            if (cbuf->bip_first == NULL)
366                cbuf->bip_last = NULL;
367            bip_buffer_free(bip);
368            continue;
369        }
370
371        size = qemu_chr_write( peer, base, avail );
372
373        if (size < 0)  /* just to be safe */
374            size = 0;
375        else if (size > avail)
376            size = avail;
377
378        cbuffer_read_step( bip->cb, size );
379
380        if (size < avail)
381            break;
382    }
383}
384
385
386static void
387charbuffer_update_handlers( CharDriverState*  cs )
388{
389    CharBuffer*  cbuf = cs->opaque;
390
391    qemu_chr_add_handlers( cbuf->endpoint,
392                           cs->chr_can_read,
393                           cs->chr_read,
394                           cs->chr_event,
395                           cs->handler_opaque );
396}
397
398
399static void
400charbuffer_init( CharBuffer*  cbuf, CharDriverState*  endpoint )
401{
402    CharDriverState*  cs = cbuf->cs;
403
404    cbuf->bip_first   = NULL;
405    cbuf->bip_last    = NULL;
406    cbuf->endpoint    = endpoint;
407
408    cs->chr_write               = charbuffer_write;
409    cs->chr_ioctl               = NULL;
410    cs->chr_send_event          = NULL;
411    cs->chr_close               = charbuffer_close;
412    cs->chr_update_read_handler = charbuffer_update_handlers;
413    cs->opaque                  = cbuf;
414}
415
416#define MAX_CHAR_BUFFERS  8
417
418static CharBuffer  _s_charbuffers[ MAX_CHAR_BUFFERS ];
419
420CharDriverState*
421qemu_chr_open_buffer( CharDriverState*  endpoint )
422{
423    CharBuffer*  cbuf     = _s_charbuffers;
424    CharBuffer*  cbuf_end = cbuf + MAX_CHAR_BUFFERS;
425
426    if (endpoint == NULL)
427        return NULL;
428
429    for ( ; cbuf < cbuf_end; cbuf++ ) {
430        if (cbuf->endpoint == NULL)
431            break;
432    }
433
434    if (cbuf == cbuf_end)
435        return NULL;
436
437    charbuffer_init(cbuf, endpoint);
438    return cbuf->cs;
439}
440
441
442void
443charpipe_poll( void )
444{
445    CharPipeState*  cp     = _s_charpipes;
446    CharPipeState*  cp_end = cp + MAX_CHAR_PIPES;
447
448    CharBuffer*     cb     = _s_charbuffers;
449    CharBuffer*     cb_end = cb + MAX_CHAR_BUFFERS;
450
451    /* poll the charpipes */
452    for ( ; cp < cp_end; cp++ ) {
453        CharPipeHalf*  half;
454
455        half = cp->a;
456        if (half->peer != NULL)
457            charpipehalf_poll(half);
458
459        half = cp->b;
460        if (half->peer != NULL)
461            charpipehalf_poll(half);
462    }
463
464    /* poll the charbuffers */
465    for ( ; cb < cb_end; cb++ ) {
466        if (cb->endpoint != NULL)
467            charbuffer_poll(cb);
468    }
469}
470