aboutsummaryrefslogtreecommitdiff
path: root/hw/usb/dev-serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/usb/dev-serial.c')
-rw-r--r--hw/usb/dev-serial.c56
1 files changed, 32 insertions, 24 deletions
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index 8aa655286b..20cf5337b7 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -9,10 +9,10 @@
*/
#include "qemu-common.h"
-#include "qemu-error.h"
+#include "qemu/error-report.h"
#include "hw/usb.h"
#include "hw/usb/desc.h"
-#include "qemu-char.h"
+#include "char/char.h"
//#define DEBUG_Serial
@@ -113,7 +113,7 @@ enum {
static const USBDescStrings desc_strings = {
[STR_MANUFACTURER] = "QEMU",
[STR_PRODUCT_SERIAL] = "QEMU USB SERIAL",
- [STR_PRODUCT_BRAILLE] = "QEMU USB BRAILLE",
+ [STR_PRODUCT_BRAILLE] = "QEMU USB BAUM BRAILLE",
[STR_SERIALNUMBER] = "1",
};
@@ -219,7 +219,7 @@ static uint8_t usb_get_modem_lines(USBSerialState *s)
return ret;
}
-static int usb_serial_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_serial_handle_control(USBDevice *dev, USBPacket *p,
int request, int value, int index, int length, uint8_t *data)
{
USBSerialState *s = (USBSerialState *)dev;
@@ -228,13 +228,11 @@ static int usb_serial_handle_control(USBDevice *dev, USBPacket *p,
DPRINTF("got control %x, value %x\n",request, value);
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
if (ret >= 0) {
- return ret;
+ return;
}
- ret = 0;
switch (request) {
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
- ret = 0;
break;
/* Class specific requests. */
@@ -323,7 +321,7 @@ static int usb_serial_handle_control(USBDevice *dev, USBPacket *p,
case DeviceInVendor | FTDI_GET_MDM_ST:
data[0] = usb_get_modem_lines(s) | 1;
data[1] = 0;
- ret = 2;
+ p->actual_length = 2;
break;
case DeviceOutVendor | FTDI_SET_EVENT_CHR:
/* TODO: handle it */
@@ -338,25 +336,23 @@ static int usb_serial_handle_control(USBDevice *dev, USBPacket *p,
break;
case DeviceInVendor | FTDI_GET_LATENCY:
data[0] = s->latency;
- ret = 1;
+ p->actual_length = 1;
break;
default:
fail:
DPRINTF("got unsupported/bogus control %x, value %x\n", request, value);
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
- return ret;
}
-static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_serial_handle_data(USBDevice *dev, USBPacket *p)
{
USBSerialState *s = (USBSerialState *)dev;
- int i, ret = 0;
uint8_t devep = p->ep->nr;
struct iovec *iov;
uint8_t header[2];
- int first_len, len;
+ int i, first_len, len;
switch (p->pid) {
case USB_TOKEN_OUT:
@@ -366,6 +362,7 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
iov = p->iov.iov + i;
qemu_chr_fe_write(s->cs, iov->iov_base, iov->iov_len);
}
+ p->actual_length = p->iov.size;
break;
case USB_TOKEN_IN:
@@ -374,7 +371,7 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
first_len = RECV_BUF - s->recv_ptr;
len = p->iov.size;
if (len <= 2) {
- ret = USB_RET_NAK;
+ p->status = USB_RET_NAK;
break;
}
header[0] = usb_get_modem_lines(s) | 1;
@@ -384,7 +381,6 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
s->event_trigger &= ~FTDI_BI;
header[1] = FTDI_BI;
usb_packet_copy(p, header, 2);
- ret = 2;
break;
} else {
header[1] = 0;
@@ -393,7 +389,7 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
if (len > s->recv_used)
len = s->recv_used;
if (!len) {
- ret = USB_RET_NAK;
+ p->status = USB_RET_NAK;
break;
}
if (first_len > len)
@@ -404,29 +400,30 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
usb_packet_copy(p, s->recv_buf, len - first_len);
s->recv_used -= len;
s->recv_ptr = (s->recv_ptr + len) % RECV_BUF;
- ret = len + 2;
break;
default:
DPRINTF("Bad token\n");
fail:
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
-
- return ret;
}
static void usb_serial_handle_destroy(USBDevice *dev)
{
USBSerialState *s = (USBSerialState *)dev;
- qemu_chr_delete(s->cs);
+ qemu_chr_add_handlers(s->cs, NULL, NULL, NULL, NULL);
}
static int usb_serial_can_read(void *opaque)
{
USBSerialState *s = opaque;
+
+ if (!s->dev.attached) {
+ return 0;
+ }
return RECV_BUF - s->recv_used;
}
@@ -469,8 +466,14 @@ static void usb_serial_event(void *opaque, int event)
case CHR_EVENT_FOCUS:
break;
case CHR_EVENT_OPENED:
- usb_serial_reset(s);
- /* TODO: Reset USB port */
+ if (!s->dev.attached) {
+ usb_device_attach(&s->dev);
+ }
+ break;
+ case CHR_EVENT_CLOSED:
+ if (s->dev.attached) {
+ usb_device_detach(&s->dev);
+ }
break;
}
}
@@ -481,6 +484,7 @@ static int usb_serial_initfn(USBDevice *dev)
usb_desc_create_serial(dev);
usb_desc_init(dev);
+ dev->auto_attach = 0;
if (!s->cs) {
error_report("Property chardev is required");
@@ -490,6 +494,10 @@ static int usb_serial_initfn(USBDevice *dev)
qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
usb_serial_event, s);
usb_serial_handle_reset(dev);
+
+ if (s->cs->opened && !dev->attached) {
+ usb_device_attach(dev);
+ }
return 0;
}