diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:30:32 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:30:32 -0800 |
commit | 8b23a6c7e1aee255004dd19098d4c2462b61b849 (patch) | |
tree | 7a4d682ba51f0ff0364c5ca2509f515bdaf96de9 /telephony/modem_driver.c | |
parent | f721e3ac031f892af46f255a47d7f54a91317b30 (diff) | |
download | external_qemu-8b23a6c7e1aee255004dd19098d4c2462b61b849.zip external_qemu-8b23a6c7e1aee255004dd19098d4c2462b61b849.tar.gz external_qemu-8b23a6c7e1aee255004dd19098d4c2462b61b849.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'telephony/modem_driver.c')
-rw-r--r-- | telephony/modem_driver.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/telephony/modem_driver.c b/telephony/modem_driver.c new file mode 100644 index 0000000..99bbe6c --- /dev/null +++ b/telephony/modem_driver.c @@ -0,0 +1,148 @@ +/* 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. +*/ +/* implement the modem character device for Android within the QEMU event loop. + * it communicates through a serial port with "rild" (Radio Interface Layer Daemon) + * on the emulated device. + */ +#include "modem_driver.h" +#include "qemu-char.h" + +#define xxDEBUG + +#ifdef DEBUG +# include <stdio.h> +# define D(...) ( fprintf( stderr, __VA_ARGS__ ) ) +#else +# define D(...) ((void)0) +#endif + +AModem android_modem; +CharDriverState* android_modem_cs; + +typedef struct { + CharDriverState* cs; + AModem modem; + char in_buff[ 1024 ]; + int in_pos; + int in_sms; +} ModemDriver; + +/* send unsollicited messages to the device */ +static void +modem_driver_unsol( void* _md, const char* message) +{ + ModemDriver* md = _md; + int len = strlen(message); + + qemu_chr_write(md->cs, (const uint8_t*)message, len); +} + +static int +modem_driver_can_read( void* _md ) +{ + ModemDriver* md = _md; + int ret = sizeof(md->in_buff) - md->in_pos; + + return ret; +} + +/* despite its name, this function is called when the device writes to the modem */ +static void +modem_driver_read( void* _md, const uint8_t* src, int len ) +{ + ModemDriver* md = _md; + const uint8_t* end = src + len; + int nn; + + D( "%s: reading %d from %p bytes:", __FUNCTION__, len, src ); + for (nn = 0; nn < len; nn++) { + int c = src[nn]; + if (c >= 32 && c < 127) + D( "%c", c ); + else if (c == '\n') + D( "<LF>" ); + else if (c == '\r') + D( "<CR>" ); + else + D( "\\x%02x", c ); + } + D( "\n" ); + + for ( ; src < end; src++ ) { + char c = src[0]; + + if (md->in_sms) { + if (c != 26) + goto AppendChar; + + md->in_buff[ md->in_pos ] = c; + md->in_pos++; + md->in_sms = 0; + c = '\n'; + } + + if (c == '\n' || c == '\r') { + const char* answer; + + if (md->in_pos == 0) /* skip empty lines */ + continue; + + md->in_buff[ md->in_pos ] = 0; + md->in_pos = 0; + + D( "%s: << %s\n", __FUNCTION__, md->in_buff ); + answer = amodem_send(android_modem, md->in_buff); + if (answer != NULL) { + D( "%s: >> %s\n", __FUNCTION__, answer ); + len = strlen(answer); + if (len == 2 && answer[0] == '>' && answer[1] == ' ') + md->in_sms = 1; + + qemu_chr_write(md->cs, (const uint8_t*)answer, len); + qemu_chr_write(md->cs, (const uint8_t*)"\r", 1); + } else + D( "%s: -- NO ANSWER\n", __FUNCTION__ ); + + continue; + } + AppendChar: + md->in_buff[ md->in_pos++ ] = c; + if (md->in_pos == sizeof(md->in_buff)) { + /* input is too long !! */ + md->in_pos = 0; + } + } + D( "%s: done\n", __FUNCTION__ ); +} + + +static void +modem_driver_init( int base_port, ModemDriver* dm, CharDriverState* cs ) +{ + dm->cs = cs; + dm->in_pos = 0; + dm->in_sms = 0; + dm->modem = amodem_create( base_port, modem_driver_unsol, dm ); + + qemu_chr_add_handlers( cs, modem_driver_can_read, modem_driver_read, NULL, dm ); +} + + +void android_modem_init( int base_port ) +{ + static ModemDriver modem_driver[1]; + + if (android_modem_cs != NULL) { + modem_driver_init( base_port, modem_driver, android_modem_cs ); + android_modem = modem_driver->modem; + } +} |