• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
37 typedef struct BipBuffer {
38     struct BipBuffer*  next;
39     CBuffer            cb[1];
40     char               buff[ BIP_BUFFER_SIZE ];
41 } BipBuffer;
42 
43 static BipBuffer*  _free_bip_buffers;
44 
45 static BipBuffer*
bip_buffer_alloc(void)46 bip_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 
63 static void
bip_buffer_free(BipBuffer * bip)64 bip_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 */
71 typedef 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 
80 static void
charpipehalf_close(CharDriverState * cs)81 charpipehalf_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 
95 static int
charpipehalf_write(CharDriverState * cs,const uint8_t * buf,int len)96 charpipehalf_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 
155 static void
charpipehalf_poll(CharPipeHalf * ph)156 charpipehalf_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 
203 static void
charpipehalf_init(CharPipeHalf * ph,CharPipeHalf * peer)204 charpipehalf_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 
220 typedef struct CharPipeState {
221     CharPipeHalf  a[1];
222     CharPipeHalf  b[1];
223 } CharPipeState;
224 
225 
226 
227 #define   MAX_CHAR_PIPES   8
228 
229 static CharPipeState  _s_charpipes[ MAX_CHAR_PIPES ];
230 
231 int
qemu_chr_open_charpipe(CharDriverState ** pfirst,CharDriverState ** psecond)232 qemu_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 
265 typedef 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 
274 static void
charbuffer_close(CharDriverState * cs)275 charbuffer_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 
293 static int
charbuffer_write(CharDriverState * cs,const uint8_t * buf,int len)294 charbuffer_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 
345 static void
charbuffer_poll(CharBuffer * cbuf)346 charbuffer_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 
386 static void
charbuffer_update_handlers(CharDriverState * cs)387 charbuffer_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 
399 static void
charbuffer_init(CharBuffer * cbuf,CharDriverState * endpoint)400 charbuffer_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 
418 static CharBuffer  _s_charbuffers[ MAX_CHAR_BUFFERS ];
419 
420 CharDriverState*
qemu_chr_open_buffer(CharDriverState * endpoint)421 qemu_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 
442 void
charpipe_poll(void)443 charpipe_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