void android_gps_send_nmea( const char* sentence ) { if (sentence == NULL) return; D("sending '%s'", sentence); if (android_gps_cs == NULL) { D("missing GPS channel, ignored"); return; } qemu_chr_write( android_gps_cs, (const void*)sentence, strlen(sentence) ); qemu_chr_write( android_gps_cs, (const void*)"\n", 1 ); }
static void ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { struct etrax_serial *s = opaque; unsigned char ch = value; D(CPUState *env = s->env); D(printf ("%s %x %x\n", __func__, addr, value)); addr >>= 2; switch (addr) { case RW_DOUT: qemu_chr_write(s->chr, &ch, 1); s->regs[R_INTR] |= 1; s->pending_tx = 1; s->regs[addr] = value; break; case RW_ACK_INTR: s->regs[addr] = value; if (s->pending_tx && (s->regs[addr] & 1)) { s->regs[R_INTR] |= 1; s->pending_tx = 0; s->regs[addr] &= ~1; } break; default: s->regs[addr] = value; break; } ser_update_irq(s); }
static void uart_write(void *opaque, target_phys_addr_t addr, uint32_t value) { LM32UartState *s = opaque; unsigned char ch = value; trace_lm32_uart_memory_write(addr, value); addr >>= 2; switch (addr) { case R_RXTX: if (s->chr) { qemu_chr_write(s->chr, &ch, 1); } break; case R_IER: case R_LCR: case R_MCR: case R_DIV: s->regs[addr] = value; break; case R_IIR: case R_LSR: case R_MSR: error_report("lm32_uart: write access to read only register 0x" TARGET_FMT_plx, addr << 2); break; default: error_report("lm32_uart: write access to unknown register 0x" TARGET_FMT_plx, addr << 2); break; } uart_update_irq(s); }
static void ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { struct etrax_serial *s = opaque; unsigned char ch = value; D(CPUState *env = s->env); D(printf ("%s " TARGET_FMT_plx "=%x\n", __func__, addr, value)); addr >>= 2; switch (addr) { case RW_DOUT: qemu_chr_write(s->chr, &ch, 1); s->regs[R_INTR] |= 3; s->pending_tx = 1; s->regs[addr] = value; break; case RW_ACK_INTR: if (s->pending_tx) { value &= ~1; s->pending_tx = 0; D(printf("fixedup value=%x r_intr=%x\n", value, s->regs[R_INTR])); } s->regs[addr] = value; s->regs[R_INTR] &= ~value; D(printf("r_intr=%x\n", s->regs[R_INTR])); break; default: s->regs[addr] = value; break; } ser_update_irq(s); }
/* called whenever a new message arrives from a qemud client. * this simply sends the message through the charpipe to the user. */ static void _qemud_char_client_recv( void* opaque, uint8_t* msg, int msglen, QemudClient* client ) { CharDriverState* cs = opaque; qemu_chr_write(cs, msg, msglen); }
static void grlib_apbuart_writel(void *opaque, target_phys_addr_t addr, uint32_t value) { UART *uart = opaque; unsigned char c = 0; addr &= 0xff; /* Unit registers */ switch (addr) { case DATA_OFFSET: c = value & 0xFF; qemu_chr_write(uart->chr, &c, 1); return; case STATUS_OFFSET: /* Read Only */ return; case CONTROL_OFFSET: /* Not supported */ return; case SCALER_OFFSET: /* Not supported */ return; default: break; } trace_grlib_apbuart_writel_unknown(addr, value); }
/* 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); }
/* Callback function that's called when the guest sends us data */ static size_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len) { VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port); ssize_t ret; ret = qemu_chr_write(vcon->chr, buf, len); return ret < 0 ? 0 : ret; }
ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags) { if (so->s == -1 && so->extra) { qemu_chr_write(so->extra, buf, len); return len; } return send(so->s, buf, len, flags); }
static void qemud_serial_send_legacy_probe( QemudSerial* s ) { /* we're going to send a specially crafted packet to the qemud * daemon, this will help us determine whether we're talking * to a legacy or a normal daemon. * * the trick is to known that a legacy daemon uses the following * header: * * <length><channel><payload> * * while the normal one uses: * * <channel><length><payload> * * where <channel> is a 2-hexchar string, and <length> a 4-hexchar * string. * * if we send a header of "000100", it is interpreted: * * - as the header of a 1-byte payload by the legacy daemon * - as the header of a 256-byte payload by the normal one. * * we're going to send something that looks like: * * "000100" + "X" + * "000b00" + "connect:gsm" + * "000b00" + "connect:gps" + * "000f00" + "connect:control" + * "00c210" + "0"*194 * * the normal daemon will interpret this as a 256-byte payload * for channel 0, with garbage content ("X000b00conn...") which * will be silently ignored. * * on the other hand, the legacy daemon will see it as a * series of packets: * * one message "X" on channel 0, which will force the daemon * to send back "001200ko:unknown command" as its first answer. * * three "connect:<xxx>" messages used to receive the channel * numbers of the three legacy services implemented by the daemon. * * a garbage packet of 194 zeroes for channel 16, which will be * silently ignored. */ uint8_t tab[194]; memset(tab, 0, sizeof(tab)); qemu_chr_write(s->cs, (uint8_t*)"000100X", 7); qemu_chr_write(s->cs, (uint8_t*)"000b00connect:gsm", 17); qemu_chr_write(s->cs, (uint8_t*)"000b00connect:gps", 17); qemu_chr_write(s->cs, (uint8_t*)"000f00connect:control", 21); qemu_chr_write(s->cs, (uint8_t*)"00c210", 6); qemu_chr_write(s->cs, tab, sizeof(tab)); }
static int charbuffer_write( CharDriverState* cs, const uint8_t* buf, int len ) { CharBuffer* cbuf = cs->opaque; CharDriverState* peer = cbuf->endpoint; BipBuffer* bip = cbuf->bip_last; int ret = 0; D("%s: writing %d bytes to %p: '%s'", __FUNCTION__, len, cbuf, quote_bytes( buf, len )); if (bip == NULL && peer != NULL) { /* no buffered data, try to write directly to the peer */ int size = qemu_chr_write(peer, buf, len); if (size < 0) /* just to be safe */ size = 0; else if (size > len) size = len; buf += size; ret += size; len -= size; } if (len == 0) return ret; /* buffer the remaining data */ if (bip == NULL) { bip = bip_buffer_alloc(); cbuf->bip_first = cbuf->bip_last = bip; } while (len > 0) { int len2 = cbuffer_write( bip->cb, buf, len ); buf += len2; ret += len2; len -= len2; if (len == 0) break; /* ok, we need another buffer */ cbuf->bip_last = bip_buffer_alloc(); bip->next = cbuf->bip_last; bip = cbuf->bip_last; } return ret; }
/* This replaces the definition in monitor.c which is in a * #ifndef CONFIG_ANDROID .. #endif block. */ void monitor_flush(Monitor *mon) { if (!mon) return; if (mon->fake_func != NULL) { mon->fake_func(mon->fake_opaque, (void*)mon->outbuf, mon->outbuf_index); mon->outbuf_index = 0; mon->fake_count += mon->outbuf_index; } else if (!mon->mux_out) { qemu_chr_write(mon->chr, mon->outbuf, mon->outbuf_index); mon->outbuf_index = 0; } }
static void virtio_console_handle_output(VirtIODevice *vdev, VirtQueue *vq) { VirtIOConsole *s = to_virtio_console(vdev); VirtQueueElement elem; while (virtqueue_pop(vq, &elem)) { ssize_t len = 0; int d; for (d=0; d < elem.out_num; d++) len += qemu_chr_write(s->chr, elem.out_sg[d].iov_base,elem.out_sg[d].iov_len); virtqueue_push(vq, &elem, len); virtio_notify(vdev, vq); } }
static void ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { struct etrax_serial_t *s = opaque; unsigned char ch = value; D(CPUState *env = s->env); switch (addr) { case RW_TR_CTRL: D(printf("rw_tr_ctrl=%x\n", value)); s->rw_tr_ctrl = value; break; case RW_TR_DMA_EN: D(printf("rw_tr_dma_en=%x\n", value)); s->rw_tr_dma_en = value; break; case RW_DOUT: qemu_chr_write(s->chr, &ch, 1); s->r_intr |= 1; s->pending_tx = 1; break; case RW_ACK_INTR: D(printf("rw_ack_intr=%x\n", value)); s->rw_ack_intr = value; if (s->pending_tx && (s->rw_ack_intr & 1)) { s->r_intr |= 1; s->pending_tx = 0; s->rw_ack_intr &= ~1; } break; case RW_INTR_MASK: D(printf("r_intr_mask=%x\n", value)); s->rw_intr_mask = value; break; default: D(printf ("%s %x %x\n", __func__, addr, value)); break; } ser_update_irq(s); }
static void charbuffer_poll( CharBuffer* cbuf ) { CharDriverState* peer = cbuf->endpoint; if (peer == NULL) return; while (1) { BipBuffer* bip = cbuf->bip_first; uint8_t* base; int avail; int size; if (bip == NULL) break; avail = cbuffer_read_peek( bip->cb, &base ); if (avail == 0) { cbuf->bip_first = bip->next; if (cbuf->bip_first == NULL) cbuf->bip_last = NULL; bip_buffer_free(bip); continue; } size = qemu_chr_write( peer, base, avail ); if (size < 0) /* just to be safe */ size = 0; else if (size > avail) size = avail; cbuffer_read_step( bip->cb, size ); if (size < avail) break; } }
static void xencons_send(struct XenConsole *con) { ssize_t len, size; size = con->buffer.size - con->buffer.consumed; if (con->chr) len = qemu_chr_write(con->chr, con->buffer.data + con->buffer.consumed, size); else len = size; if (len < 1) { if (!con->backlog) { con->backlog = 1; xen_be_printf(&con->xendev, 1, "backlog piling up, nobody listening?\n"); } } else { buffer_advance(&con->buffer, len); if (con->backlog && len == size) { con->backlog = 0; xen_be_printf(&con->xendev, 1, "backlog is gone\n"); } } }
static void parallel_ioport_write_sw(void *opaque, uint32_t addr, uint32_t val) { ParallelState *s = opaque; pdebug("write addr=0x%02x val=0x%02x\n", addr, val); addr &= 7; switch(addr) { case PARA_REG_DATA: s->dataw = val; parallel_update_irq(s); break; case PARA_REG_CTR: val |= 0xc0; if ((val & PARA_CTR_INIT) == 0 ) { s->status = PARA_STS_BUSY; s->status |= PARA_STS_ACK; s->status |= PARA_STS_ONLINE; s->status |= PARA_STS_ERROR; } else if (val & PARA_CTR_SELECT) { if (val & PARA_CTR_STROBE) { s->status &= ~PARA_STS_BUSY; if ((s->control & PARA_CTR_STROBE) == 0) qemu_chr_write(s->chr, &s->dataw, 1); } else { if (s->control & PARA_CTR_INTEN) { s->irq_pending = 1; } } } parallel_update_irq(s); s->control = val; break; } }
static void sh_serial_ioport_write(void *opaque, uint32_t offs, uint32_t val) { sh_serial_state *s = opaque; unsigned char ch; #ifdef DEBUG_SERIAL printf("sh_serial: write offs=0x%02x val=0x%02x\n", offs, val); #endif switch(offs) { case 0x00: /* SMR */ s->smr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0x7b : 0xff); return; case 0x04: /* BRR */ s->brr = val; return; case 0x08: /* SCR */ /* TODO : For SH7751, SCIF mask should be 0xfb. */ s->scr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0xfa : 0xff); if (!(val & (1 << 5))) s->flags |= SH_SERIAL_FLAG_TEND; if ((s->feat & SH_SERIAL_FEAT_SCIF) && s->txi) { qemu_set_irq(s->txi, val & (1 << 7)); } if (!(val & (1 << 6))) { qemu_set_irq(s->rxi, 0); } return; case 0x0c: /* FTDR / TDR */ if (s->chr) { ch = val; qemu_chr_write(s->chr, &ch, 1); } s->dr = val; s->flags &= ~SH_SERIAL_FLAG_TDE; return; #if 0 case 0x14: /* FRDR / RDR */ ret = 0; break; #endif } if (s->feat & SH_SERIAL_FEAT_SCIF) { switch(offs) { case 0x10: /* FSR */ if (!(val & (1 << 6))) s->flags &= ~SH_SERIAL_FLAG_TEND; if (!(val & (1 << 5))) s->flags &= ~SH_SERIAL_FLAG_TDE; if (!(val & (1 << 4))) s->flags &= ~SH_SERIAL_FLAG_BRK; if (!(val & (1 << 1))) s->flags &= ~SH_SERIAL_FLAG_RDF; if (!(val & (1 << 0))) s->flags &= ~SH_SERIAL_FLAG_DR; if (!(val & (1 << 1)) || !(val & (1 << 0))) { if (s->rxi) { qemu_set_irq(s->rxi, 0); } } return; case 0x18: /* FCR */ s->fcr = val; switch ((val >> 6) & 3) { case 0: s->rtrg = 1; break; case 1: s->rtrg = 4; break; case 2: s->rtrg = 8; break; case 3: s->rtrg = 14; break; } if (val & (1 << 1)) { sh_serial_clear_fifo(s); s->sr &= ~(1 << 1); } return; case 0x20: /* SPTR */ s->sptr = val & 0xf3; return; case 0x24: /* LSR */ return; } } else { switch(offs) {
/* send a message to the serial port. This will add the necessary * header. */ static void qemud_serial_send( QemudSerial* s, int channel, ABool framing, const uint8_t* msg, int msglen ) { uint8_t header[HEADER_SIZE]; uint8_t frame[FRAME_HEADER_SIZE]; int avail, len = msglen; if (msglen <= 0 || channel < 0) return; D("%s: channel=%2d len=%3d '%s'", __FUNCTION__, channel, msglen, quote_bytes((const void*)msg, msglen)); if (framing) { len += FRAME_HEADER_SIZE; } /* packetize the payload for the serial MTU */ while (len > 0) { avail = len; if (avail > MAX_SERIAL_PAYLOAD) avail = MAX_SERIAL_PAYLOAD; /* write this packet's header */ #if SUPPORT_LEGACY_QEMUD if (s->version == QEMUD_VERSION_LEGACY) { int2hex(header + LEGACY_LENGTH_OFFSET, LENGTH_SIZE, avail); int2hex(header + LEGACY_CHANNEL_OFFSET, CHANNEL_SIZE, channel); } else { int2hex(header + LENGTH_OFFSET, LENGTH_SIZE, avail); int2hex(header + CHANNEL_OFFSET, CHANNEL_SIZE, channel); } #else int2hex(header + LENGTH_OFFSET, LENGTH_SIZE, avail); int2hex(header + CHANNEL_OFFSET, CHANNEL_SIZE, channel); #endif T("%s: '%.*s'", __FUNCTION__, HEADER_SIZE, header); qemu_chr_write(s->cs, header, HEADER_SIZE); /* insert frame header when needed */ if (framing) { int2hex(frame, FRAME_HEADER_SIZE, msglen); T("%s: '%.*s'", __FUNCTION__, FRAME_HEADER_SIZE, frame); qemu_chr_write(s->cs, frame, FRAME_HEADER_SIZE); avail -= FRAME_HEADER_SIZE; len -= FRAME_HEADER_SIZE; framing = 0; } /* write message content */ T("%s: '%.*s'", __FUNCTION__, avail, msg); qemu_chr_write(s->cs, msg, avail); msg += avail; len -= avail; } }
/* 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; //MTK-START [mtk80950] [ALPSXXXXXXXX] [111115] porting MTK-code to ICS //YQ_TODO int templen = strlen(answer); char an[templen+1]; strcpy(an,"@"); strcat(an,answer); answer=an; if( memcmp(answer, "@+CSQ", 5)){ printf("[Emu] response %s\r\n",answer); } qemu_chr_write(md->cs, (const uint8_t*)answer, len+1); //MTK-END [mtk80950] [ALPSXXXXXXXX] [111115] porting MTK-code to ICS 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 goldfish_tty_write(void *opaque, hwaddr offset, uint32_t value) { struct tty_state *s = (struct tty_state *)opaque; //printf("goldfish_tty_read %x %x %x\n", offset, value, size); switch(offset) { case TTY_PUT_CHAR: { uint8_t ch = value; if(s->cs) qemu_chr_write(s->cs, &ch, 1); } break; case TTY_CMD: switch(value) { case TTY_CMD_INT_DISABLE: if(s->ready) { if(s->data_count > 0) goldfish_device_set_irq(&s->dev, 0, 0); s->ready = 0; } break; case TTY_CMD_INT_ENABLE: if(!s->ready) { if(s->data_count > 0) goldfish_device_set_irq(&s->dev, 0, 1); s->ready = 1; } break; case TTY_CMD_WRITE_BUFFER: if(s->cs) { int len; hwaddr buf; buf = s->ptr; len = s->ptr_len; while (len) { char temp[64]; int to_write = sizeof(temp); if (to_write > len) to_write = len; safe_memory_rw_debug(cpu_single_env, buf, (uint8_t*)temp, to_write, 0); qemu_chr_write(s->cs, (const uint8_t*)temp, to_write); buf += to_write; len -= to_write; } //printf("goldfish_tty_write: got %d bytes from %x\n", s->ptr_len, s->ptr); } break; case TTY_CMD_READ_BUFFER: if(s->ptr_len > s->data_count) cpu_abort (cpu_single_env, "goldfish_tty_write: reading more data than available %d %d\n", s->ptr_len, s->data_count); safe_memory_rw_debug(cpu_single_env,s->ptr, s->data, s->ptr_len,1); //printf("goldfish_tty_write: read %d bytes to %x\n", s->ptr_len, s->ptr); if(s->data_count > s->ptr_len) memmove(s->data, s->data + s->ptr_len, s->data_count - s->ptr_len); s->data_count -= s->ptr_len; if(s->data_count == 0 && s->ready) goldfish_device_set_irq(&s->dev, 0, 0); break; default: cpu_abort (cpu_single_env, "goldfish_tty_write: Bad command %x\n", value); }; break; case TTY_DATA_PTR: s->ptr = value; break; case TTY_DATA_LEN: s->ptr_len = value; break; default: cpu_abort (cpu_single_env, "goldfish_tty_write: Bad offset %x\n", offset); } }
static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) { SerialState *serial = opaque; ChannelState *s; uint32_t saddr; int newreg, channel; val &= 0xff; saddr = (addr & 3) >> 1; channel = (addr & SERIAL_MAXADDR) >> 2; s = &serial->chn[channel]; switch (saddr) { case SERIAL_CTRL: SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, val & 0xff); newreg = 0; switch (s->reg) { case W_CMD: newreg = val & CMD_PTR_MASK; val &= CMD_CMD_MASK; switch (val) { case CMD_HI: newreg |= CMD_HI; break; case CMD_CLR_TXINT: clr_txint(s); break; case CMD_CLR_IUS: if (s->rxint_under_svc) clr_rxint(s); else if (s->txint_under_svc) clr_txint(s); break; default: break; } break; case W_INTR ... W_RXCTRL: case W_SYNC1 ... W_TXBUF: case W_MISC1 ... W_CLOCK: case W_MISC2 ... W_EXTINT: s->wregs[s->reg] = val; break; case W_TXCTRL1: case W_TXCTRL2: case W_BRGLO: case W_BRGHI: s->wregs[s->reg] = val; slavio_serial_update_parameters(s); break; case W_MINTR: switch (val & MINTR_RST_MASK) { case 0: default: break; case MINTR_RST_B: slavio_serial_reset_chn(&serial->chn[1]); return; case MINTR_RST_A: slavio_serial_reset_chn(&serial->chn[0]); return; case MINTR_RST_ALL: slavio_serial_reset(serial); return; } break; default: break; } if (s->reg == 0) s->reg = newreg; else s->reg = 0; break; case SERIAL_DATA: SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val); s->tx = val; if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled if (s->chr) qemu_chr_write(s->chr, &s->tx, 1); else if (s->type == kbd && !s->disabled) { handle_kbd_command(s, val); } } s->rregs[R_STATUS] |= STATUS_TXEMPTY; // Tx buffer empty s->rregs[R_SPEC] |= SPEC_ALLSENT; // All sent set_txint(s); break; default: break; } }
static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) { SerialState *ser = opaque; ChannelState *s; uint32_t saddr; int newreg, channel; val &= 0xff; saddr = (addr & 3) >> 1; channel = (addr & SERIAL_MAXADDR) >> 2; s = &ser->chn[channel]; switch (saddr) { case 0: SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, val & 0xff); newreg = 0; switch (s->reg) { case 0: newreg = val & 7; val &= 0x38; switch (val) { case 8: newreg |= 0x8; break; case 0x28: clr_txint(s); break; case 0x38: if (s->rxint_under_svc) clr_rxint(s); else if (s->txint_under_svc) clr_txint(s); break; default: break; } break; case 1 ... 3: case 6 ... 8: case 10 ... 11: case 14 ... 15: s->wregs[s->reg] = val; break; case 4: case 5: case 12: case 13: s->wregs[s->reg] = val; slavio_serial_update_parameters(s); break; case 9: switch (val & 0xc0) { case 0: default: break; case 0x40: slavio_serial_reset_chn(&ser->chn[1]); return; case 0x80: slavio_serial_reset_chn(&ser->chn[0]); return; case 0xc0: slavio_serial_reset(ser); return; } break; default: break; } if (s->reg == 0) s->reg = newreg; else s->reg = 0; break; case 1: SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val); if (s->wregs[5] & 8) { // tx enabled s->tx = val; if (s->chr) qemu_chr_write(s->chr, &s->tx, 1); else if (s->type == kbd) { handle_kbd_command(s, val); } s->rregs[0] |= 4; // Tx buffer empty s->rregs[1] |= 1; // All sent set_txint(s); } break; default: break; } }