aboutsummaryrefslogtreecommitdiffstats
path: root/android/qemud.c
diff options
context:
space:
mode:
Diffstat (limited to 'android/qemud.c')
-rw-r--r--android/qemud.c456
1 files changed, 0 insertions, 456 deletions
diff --git a/android/qemud.c b/android/qemud.c
deleted file mode 100644
index b127fc9..0000000
--- a/android/qemud.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/* Copyright (C) 2007-2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-#include "android/qemud.h"
-#include "android/utils/debug.h"
-#include "android/utils/misc.h"
-#include "qemu-char.h"
-#include "charpipe.h"
-#include "cbuffer.h"
-
-#define D(...) VERBOSE_PRINT(qemud,__VA_ARGS__)
-#define D_ACTIVE VERBOSE_CHECK(qemud)
-
-/* the T(...) macro is used to dump traffic */
-#define T_ACTIVE 0
-
-#if T_ACTIVE
-#define T(...) VERBOSE_PRINT(qemud,__VA_ARGS__)
-#else
-#define T(...) ((void)0)
-#endif
-
-#define MAX_PAYLOAD 4000
-#define MAX_CHANNELS 8
-
-#define CHANNEL_CONTROL_INDEX 0
-
-/** packets
- **/
-#define HEADER_SIZE 6
-
-typedef struct Packet {
- struct Packet* next;
- int len;
- uint8_t header[HEADER_SIZE];
- uint8_t data[MAX_PAYLOAD];
-} Packet;
-
-static Packet* _free_packets;
-
-static void
-packet_free( Packet* p )
-{
- p->next = _free_packets;
- _free_packets = p;
-}
-
-static Packet*
-packet_alloc( void )
-{
- Packet* p = _free_packets;
- if (p != NULL) {
- _free_packets = p->next;
- } else {
- p = malloc(sizeof(*p));
- if (p == NULL) {
- derror("%s: not enough memory", __FUNCTION__);
- exit(1);
- }
- }
- p->next = NULL;
- p->len = 0;
- return p;
-}
-
-/** channels
- **/
-typedef void (*EnqueueFunc)( void* user, Packet* p );
-
-typedef struct {
- const char* name;
- int index;
- CharDriverState* cs;
- EnqueueFunc enq_func;
- void* enq_user;
-} Channel;
-
-
-static int
-channel_can_read( void* opaque )
-{
- Channel* c = opaque;
-
- return c->index < 0 ? 0 : MAX_PAYLOAD;
-}
-
-
-/* here, the data comes from the emulated device (e.g. GSM modem) through
- * a charpipe, we simply need to send it through the multiplexer */
-static void
-channel_read( void* opaque, const uint8_t* from, int len )
-{
- Channel* c = opaque;
-
- if (c->enq_func != NULL) {
- Packet* p = packet_alloc();
-
- if (len > MAX_PAYLOAD)
- len = MAX_PAYLOAD;
-
- memcpy( p->data, from, len );
- p->len = len + HEADER_SIZE;
- int2hex( p->header+0, 4, len );
- int2hex( p->header+4, 2, c->index );
-
- c->enq_func( c->enq_user, p );
- }
- else
- {
- D("%s: discarding %d bytes for channel '%s'",
- __FUNCTION__, len, c->name);
- }
-}
-
-static void
-channel_init( Channel* c, const char* name, CharDriverState* peer_cs )
-{
- c->name = name;
- c->index = -1;
- c->enq_func = NULL;
- c->enq_user = NULL;
- c->cs = peer_cs;
-}
-
-
-static void
-channel_set_peer( Channel* c, int index, EnqueueFunc enq_func, void* enq_user )
-{
- c->index = index;
- qemu_chr_add_handlers( c->cs,
- channel_can_read,
- channel_read,
- NULL,
- c );
- c->enq_func = enq_func;
- c->enq_user = enq_user;
-}
-
-
-static int
-channel_write( Channel*c , const uint8_t* buf, int len )
-{
- return qemu_chr_write( c->cs, buf, len );
-}
-
-/** multiplexer
- **/
-#define IN_BUFF_SIZE (2*MAX_PAYLOAD)
-
-typedef struct {
- CharDriverState* cs;
-
- CBuffer in_cbuffer[1];
- int in_datalen;
- int in_channel;
-
- int count;
- Channel channels[MAX_CHANNELS];
- uint8_t in_buff[ IN_BUFF_SIZE + HEADER_SIZE ];
-} Multiplexer;
-
-
-/* called by channel_read when data comes from an emulated
- * device, and needs to be multiplexed through the serial
- * port
- */
-static void
-multiplexer_enqueue( Multiplexer* m, Packet* p )
-{
- T("%s: sending %d bytes: '%s'", __FUNCTION__,
- p->len - HEADER_SIZE, quote_bytes( p->data, p->len - HEADER_SIZE ) );
-
- qemu_chr_write( m->cs, p->header, HEADER_SIZE );
- qemu_chr_write( m->cs, p->data, p->len - HEADER_SIZE );
- packet_free(p);
-}
-
-/* called when we received a channel registration from the
- * qemud daemon
- */
-static void
-multiplexer_register_channel( Multiplexer* m,
- const char* name,
- int index )
-{
- Channel* c = m->channels;
- Channel* c_end = c + m->count;
-
- for ( ; c < c_end; c++ ) {
- if ( !strcmp(c->name, name) )
- break;
- }
-
- if (c >= c_end) {
- D( "%s: unknown channel name '%s'",
- __FUNCTION__, name );
- return;
- }
-
- if (c->index >= 0) {
- D( "%s: channel '%s' re-assigned index %d",
- __FUNCTION__, name, index );
- c->index = index;
- return;
- }
- channel_set_peer( c, index, (EnqueueFunc) multiplexer_enqueue, m );
- D( "%s: channel '%s' registered as index %d",
- __FUNCTION__, c->name, c->index );
-}
-
-
-/* handle answers from the control channel */
-static void
-multiplexer_handle_control( Multiplexer* m, Packet* p )
-{
- int len = p->len - HEADER_SIZE;
-
- /* for now, the only supported answer is 'ok:connect:<name>:<XX>' where
- * <XX> is a hexdecimal channel numner */
- D( "%s: received '%s'", __FUNCTION__, quote_bytes( (const void*)p->data, (unsigned)len ) );
- if ( !memcmp( p->data, "ok:connect:", 11 ) ) do {
- char* name = (char*)p->data + 11;
- char* q = strchr( name, ':' );
- int index;
-
- if (q == NULL)
- break;
-
- q[0] = 0;
- if (q + 3 > (char*)p->data + len)
- break;
-
- index = hex2int( (uint8_t*)q+1, 2 );
- if (index < 0)
- break;
-
- multiplexer_register_channel( m, name, index );
- goto Exit;
- }
- while(0);
-
- D( "%s: unsupported message !!", __FUNCTION__ );
-Exit:
- packet_free(p);
-}
-
-
-static int
-multiplexer_can_read( void* opaque )
-{
- Multiplexer* m = opaque;
-
- return cbuffer_write_avail( m->in_cbuffer );
-}
-
-/* the data comes from the serial port, we need to reconstruct packets then
- * dispatch them to the appropriate channel */
-static void
-multiplexer_read( void* opaque, const uint8_t* from, int len )
-{
- Multiplexer* m = opaque;
- CBuffer* cb = m->in_cbuffer;
- int ret = 0;
-
- T("%s: received %d bytes from serial: '%s'",
- __FUNCTION__, len, quote_bytes( from, len ));
-
- ret = cbuffer_write( cb, from, len );
- if (ret == 0)
- return;
-
- for (;;) {
- int len = cbuffer_read_avail( cb );
-
- if (m->in_datalen == 0) {
- uint8_t header[HEADER_SIZE];
-
- if (len < HEADER_SIZE)
- break;
-
- cbuffer_read( cb, header, HEADER_SIZE );
- m->in_datalen = hex2int( header+0, 4 );
- m->in_channel = hex2int( header+4, 2 );
- }
- else
- {
- Packet* p;
-
- if (len < m->in_datalen)
- break;
-
- /* a full packet was received */
- p = packet_alloc();
- cbuffer_read( cb, p->data, m->in_datalen );
- p->len = HEADER_SIZE + m->in_datalen;
-
- /* find the channel for this packet */
- if (m->in_channel == CHANNEL_CONTROL_INDEX)
- multiplexer_handle_control( m, p );
- else {
- Channel* c = m->channels;
- Channel* c_end = c + m->count;
-
- for ( ; c < c_end; c++ ) {
- if (c->index == m->in_channel) {
- channel_write( c, p->data, m->in_datalen );
- break;
- }
- }
- packet_free(p);
- }
- m->in_datalen = 0;
- }
-
- }
- return;
-}
-
-static void
-multiplexer_query_channel( Multiplexer* m, const char* name )
-{
- Packet* p = packet_alloc();
- int len;
-
- len = snprintf( (char*)p->data, MAX_PAYLOAD, "connect:%s", name );
-
- int2hex( p->header+0, 4, len );
- int2hex( p->header+4, 2, CHANNEL_CONTROL_INDEX );
- p->len = HEADER_SIZE + len;
-
- multiplexer_enqueue( m, p );
-}
-
-
-static Channel*
-multiplexer_find_channel( Multiplexer* m, const char* name )
-{
- int n;
- for (n = 0; n < m->count; n++)
- if ( !strcmp(m->channels[n].name, name) )
- return m->channels + n;
-
- return NULL;
-}
-
-
-static Multiplexer _multiplexer[1];
-static CharDriverState* android_qemud_cs;
-
-extern void
-android_qemud_init( void )
-{
- Multiplexer* m = _multiplexer;
-
- if (android_qemud_cs != NULL)
- return;
-
- m->count = 0;
-
- cbuffer_reset( m->in_cbuffer, m->in_buff, sizeof(m->in_buff) );
- m->in_datalen = 0;
- m->in_channel = 0;
-
- if (qemu_chr_open_charpipe( &android_qemud_cs, &m->cs ) < 0) {
- derror( "%s: can't create charpipe to serial port",
- __FUNCTION__ );
- exit(1);
- }
-
- qemu_chr_add_handlers( m->cs, multiplexer_can_read,
- multiplexer_read, NULL, m );
-}
-
-
-CharDriverState* android_qemud_get_cs( void )
-{
- if (android_qemud_cs == NULL)
- android_qemud_init();
-
- return android_qemud_cs;
-}
-
-
-extern int
-android_qemud_get_channel( const char* name, CharDriverState** pcs )
-{
- Multiplexer* m = _multiplexer;
- Channel* c;
- CharDriverState* peer_cs;
- int ret;
-
- if (m->cs == NULL)
- android_qemud_init();
-
- c = multiplexer_find_channel( m, name );
- if (c) {
- derror( "%s: trying to get already-opened qemud channel '%s'",
- __FUNCTION__, name );
- return -1;
- }
-
- if (m->count >= MAX_CHANNELS) {
- derror( "%s: too many registered channels (%d)",
- __FUNCTION__, m->count );
- return -1;
- }
-
- c = m->channels + m->count;
-
- ret = qemu_chr_open_charpipe( &peer_cs, pcs );
- if (ret == 0) {
- channel_init(c, name, peer_cs);
- m->count += 1;
- multiplexer_query_channel( m, c->name );
- }
-
- return ret;
-}
-
-extern int
-android_qemud_set_channel( const char* name, CharDriverState* peer_cs )
-{
- Multiplexer* m = _multiplexer;
- Channel* c;
-
- if (m->cs == NULL)
- android_qemud_init();
-
- c = multiplexer_find_channel(m, name);
- if (c != NULL) {
- derror( "%s: trying to set opened qemud channel '%s'",
- __FUNCTION__, name );
- return -1;
- }
-
- if (m->count >= MAX_CHANNELS) {
- derror( "%s: too many registered channels (%d)",
- __FUNCTION__, m->count );
- return -1;
- }
-
- c = m->channels + m->count;
- channel_init(c, name, peer_cs);
- m->count += 1;
- multiplexer_query_channel( m, c->name );
-
- return 0;
-}