blob: 992b45a24d0635d7ce4b81a4b7c473ba89f2a547 [file] [log] [blame]
The Android Open Source Project6370eab2009-12-15 16:36:26 -08001/* 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 "qemu-char.h"
13#include "cbuffer.h"
14#include "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}