aboutsummaryrefslogtreecommitdiffstats
path: root/telephony/modem_driver.c
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commit55f4e4a5ec657a017e3bf75299ad71fd1c968dd3 (patch)
tree550ce922ea0e125ac6a9738210ce2939bf2fe901 /telephony/modem_driver.c
parent413f05aaf54fa08c0ae7e997327a4f4a473c0a8d (diff)
downloadexternal_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.zip
external_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.tar.gz
external_qemu-55f4e4a5ec657a017e3bf75299ad71fd1c968dd3.tar.bz2
Initial Contribution
Diffstat (limited to 'telephony/modem_driver.c')
-rw-r--r--telephony/modem_driver.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/telephony/modem_driver.c b/telephony/modem_driver.c
new file mode 100644
index 0000000..7de475f
--- /dev/null
+++ b/telephony/modem_driver.c
@@ -0,0 +1,147 @@
+/* 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"
+
+#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, "\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_read_handler( cs, modem_driver_can_read, modem_driver_read, 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;
+ }
+}