]> git.proxmox.com Git - qemu.git/blobdiff - hw/usb-serial.c
usb: hook unplug into qdev, cleanups + fixes.
[qemu.git] / hw / usb-serial.c
index 40d04cb2dba3542c7bb2f496fe2809879dfcd9b0..e2379c4d5ec2483bbad055cd1d1c17f3054f59ce 100644 (file)
 //#define DEBUG_Serial
 
 #ifdef DEBUG_Serial
-#define DPRINTF(fmt, args...) \
-do { printf("usb-serial: " fmt , ##args); } while (0)
+#define DPRINTF(fmt, ...) \
+do { printf("usb-serial: " fmt , ## __VA_ARGS__); } while (0)
 #else
-#define DPRINTF(fmt, args...) do {} while(0)
+#define DPRINTF(fmt, ...) do {} while(0)
 #endif
 
 #define RECV_BUF 384
@@ -445,7 +445,15 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
         }
         *data++ = usb_get_modem_lines(s) | 1;
         /* We do not have the uart details */
-        *data++ = 0;
+        /* handle serial break */
+        if (s->event_trigger && s->event_trigger & FTDI_BI) {
+            s->event_trigger &= ~FTDI_BI;
+            *data++ = FTDI_BI;
+            ret = 2;
+            break;
+        } else {
+            *data++ = 0;
+        }
         len -= 2;
         if (len > s->recv_used)
             len = s->recv_used;
@@ -478,7 +486,6 @@ static void usb_serial_handle_destroy(USBDevice *dev)
     USBSerialState *s = (USBSerialState *)dev;
 
     qemu_chr_close(s->cs);
-    qemu_free(s);
 }
 
 static int usb_serial_can_read(void *opaque)
@@ -505,7 +512,7 @@ static void usb_serial_event(void *opaque, int event)
 
     switch (event) {
         case CHR_EVENT_BREAK:
-            /* TODO: Send Break to USB */
+            s->event_trigger |= FTDI_BI;
             break;
         case CHR_EVENT_FOCUS:
             break;
@@ -516,11 +523,21 @@ static void usb_serial_event(void *opaque, int event)
     }
 }
 
+static int usb_serial_initfn(USBDevice *dev)
+{
+    USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
+    s->dev.speed = USB_SPEED_FULL;
+    return 0;
+}
+
 USBDevice *usb_serial_init(const char *filename)
 {
+    USBDevice *dev;
     USBSerialState *s;
     CharDriverState *cdrv;
     unsigned short vendorid = 0x0403, productid = 0x6001;
+    char label[32];
+    static int index;
 
     while (*filename && *filename != ':') {
         const char *p;
@@ -551,33 +568,40 @@ USBDevice *usb_serial_init(const char *filename)
         return NULL;
     }
     filename++;
-    s = qemu_mallocz(sizeof(USBSerialState));
-    if (!s)
-        return NULL;
 
-    cdrv = qemu_chr_open(filename);
+    snprintf(label, sizeof(label), "usbserial%d", index++);
+    cdrv = qemu_chr_open(label, filename, NULL);
     if (!cdrv)
-        goto fail;
-    s->cs = cdrv;
-    qemu_chr_add_handlers(cdrv, usb_serial_can_read, usb_serial_read, usb_serial_event, s);
-
-    s->dev.speed = USB_SPEED_FULL;
-    s->dev.handle_packet = usb_generic_handle_packet;
-
-    s->dev.handle_reset = usb_serial_handle_reset;
-    s->dev.handle_control = usb_serial_handle_control;
-    s->dev.handle_data = usb_serial_handle_data;
-    s->dev.handle_destroy = usb_serial_handle_destroy;
+        return NULL;
 
+    dev = usb_create_simple(NULL /* FIXME */, "QEMU USB Serial");
+    s = DO_UPCAST(USBSerialState, dev, dev);
+    s->cs = cdrv;
     s->vendorid = vendorid;
     s->productid = productid;
-
     snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Serial(%.16s)",
              filename);
 
+    qemu_chr_add_handlers(cdrv, usb_serial_can_read, usb_serial_read,
+                          usb_serial_event, s);
+
     usb_serial_handle_reset((USBDevice *)s);
     return (USBDevice *)s;
- fail:
-    qemu_free(s);
-    return NULL;
 }
+
+static struct USBDeviceInfo serial_info = {
+    .qdev.name      = "QEMU USB Serial",
+    .qdev.size      = sizeof(USBSerialState),
+    .init           = usb_serial_initfn,
+    .handle_packet  = usb_generic_handle_packet,
+    .handle_reset   = usb_serial_handle_reset,
+    .handle_control = usb_serial_handle_control,
+    .handle_data    = usb_serial_handle_data,
+    .handle_destroy = usb_serial_handle_destroy,
+};
+
+static void usb_serial_register_devices(void)
+{
+    usb_qdev_register(&serial_info);
+}
+device_init(usb_serial_register_devices)