r1929 - in trunk/src/host/qemu-neo1973: . hw
andrew at sita.openmoko.org
andrew at sita.openmoko.org
Tue May 8 17:25:54 CEST 2007
Author: andrew
Date: 2007-05-08 17:25:51 +0200 (Tue, 08 May 2007)
New Revision: 1929
Modified:
trunk/src/host/qemu-neo1973/hw/usb.c
trunk/src/host/qemu-neo1973/hw/usb.h
trunk/src/host/qemu-neo1973/monitor.c
trunk/src/host/qemu-neo1973/usb-linux-gadget.c
trunk/src/host/qemu-neo1973/vl.c
trunk/src/host/qemu-neo1973/vl.h
Log:
New monitor commands for managing multiple USB slave configurations (should be user-ready now).
Modified: trunk/src/host/qemu-neo1973/hw/usb.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/usb.c 2007-05-08 09:21:11 UTC (rev 1928)
+++ trunk/src/host/qemu-neo1973/hw/usb.c 2007-05-08 15:25:51 UTC (rev 1929)
@@ -184,7 +184,7 @@
q = buf;
len = strlen(str);
*q++ = 2 * len + 2;
- *q++ = 3;
+ *q++ = USB_DT_STRING;
for(i = 0; i < len; i++) {
*q++ = str[i];
*q++ = 0;
@@ -192,6 +192,22 @@
return q - buf;
}
+int get_usb_string(char *buf, const uint8_t *str)
+{
+ int len, i;
+ char *q;
+
+ q = str;
+ len = (*q++ - 2) / 2;
+ q++;
+ for(i = 0; i < len; i++) {
+ buf[i] = *q++;
+ q++;
+ }
+ buf[i] = 0;
+ return len;
+}
+
/* Send an internal message to a USB device. */
void usb_send_msg(USBDevice *dev, int msg)
{
Modified: trunk/src/host/qemu-neo1973/hw/usb.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/usb.h 2007-05-08 09:21:11 UTC (rev 1928)
+++ trunk/src/host/qemu-neo1973/hw/usb.h 2007-05-08 15:25:51 UTC (rev 1929)
@@ -195,6 +195,7 @@
void usb_attach(USBPort *port, USBDevice *dev);
int usb_generic_handle_packet(USBDevice *s, USBPacket *p);
int set_usb_string(uint8_t *buf, const char *str);
+int get_usb_string(char *buf, const uint8_t *str);
void usb_send_msg(USBDevice *dev, int msg);
void usb_packet_complete(USBPacket *p);
@@ -216,6 +217,7 @@
/* usb-linux-gadget.c */
int usb_gadget_init(void);
+void usb_gadget_config_set(USBPort *port, int config);
/* usb-hid.c */
USBDevice *usb_mouse_init(void);
Modified: trunk/src/host/qemu-neo1973/monitor.c
===================================================================
--- trunk/src/host/qemu-neo1973/monitor.c 2007-05-08 09:21:11 UTC (rev 1928)
+++ trunk/src/host/qemu-neo1973/monitor.c 2007-05-08 15:25:51 UTC (rev 1929)
@@ -1279,6 +1279,8 @@
"", "show guest USB devices", },
{ "usbhost", "", usb_host_info,
"", "show host USB devices", },
+ { "usbslave", "", usb_slave_info,
+ "", "show USB configurations exported by guest", },
{ "profile", "", do_info_profile,
"", "show profiling information", },
{ "capture", "", do_info_capture,
Modified: trunk/src/host/qemu-neo1973/usb-linux-gadget.c
===================================================================
--- trunk/src/host/qemu-neo1973/usb-linux-gadget.c 2007-05-08 09:21:11 UTC (rev 1928)
+++ trunk/src/host/qemu-neo1973/usb-linux-gadget.c 2007-05-08 15:25:51 UTC (rev 1929)
@@ -797,6 +797,12 @@
return ret;
}
+void usb_gadget_config_set(USBPort *port, int config)
+{
+ struct gadget_state_s *hci = (struct gadget_state_s *) port->opaque;
+ hci->config_num = config;
+}
+
#else
#include "vl.h"
@@ -805,4 +811,8 @@
return -ENODEV;
}
+void usb_gadget_config_set(USBPort *port, int config)
+{
+}
+
#endif
Modified: trunk/src/host/qemu-neo1973/vl.c
===================================================================
--- trunk/src/host/qemu-neo1973/vl.c 2007-05-08 09:21:11 UTC (rev 1928)
+++ trunk/src/host/qemu-neo1973/vl.c 2007-05-08 15:25:51 UTC (rev 1929)
@@ -4001,11 +4001,15 @@
if (nr >= (unsigned int)nb_nics || strcmp(nd_table[nr].model, "usb"))
return -1;
dev = usb_net_init(&nd_table[nr]);
- } else if (!strcmp(devname, "gadget")) {
+ } else if (strstart(devname, "gadget", &p)) {
dev = usb_gadget;
port = host_usb_ports;
if (!dev || !port)
return -1;
+ if (p[0] == ':')
+ usb_gadget_config_set(port, strtoul(&p[1], NULL, 0));
+ else if (p[0] != 0)
+ return -1;
goto attach;
} else {
return 0;
@@ -4132,6 +4136,187 @@
}
}
+struct usb_slave_info_s {
+ uint8_t buffer[256];
+ int config_num;
+ int packet_num;
+ USBPacket packet[2];
+ uint64_t timeout;
+ USBDevice *slave;
+ int timedout;
+ int config;
+ int manf_str;
+ int prod_str;
+ USBCallback *cb;
+ QEMUTimer *timeout_tm;
+};
+
+static void usb_packet_next(USBPacket *prev, void *opaque)
+{
+ struct usb_slave_info_s *info = (struct usb_slave_info_s *) opaque;
+ int ret;
+ int num;
+
+ if (info->timedout)
+ return;
+
+ num = info->packet_num ++;
+
+ if (num >= 2) {
+ if (qemu_timer_pending(info->timeout_tm))
+ qemu_del_timer(info->timeout_tm);
+ info->cb(prev, opaque);
+ return;
+ }
+
+ ret = info->slave->handle_packet(info->slave, &info->packet[num]);
+
+ if (ret >= 0) {
+ info->packet[num].len = ret;
+ info->packet[num].complete_cb(&info->packet[num],
+ info->packet[num].complete_opaque);
+ } else if (ret == USB_RET_ASYNC) {
+ qemu_mod_timer(info->timeout_tm,
+ qemu_get_clock(rt_clock) + info->timeout);
+ } else {
+ term_printf("Packet not handled\n");
+ }
+}
+
+static void usb_get_descriptor(struct usb_slave_info_s *info, USBCallback cb,
+ int desc, int idx)
+{
+ info->packet_num = 0;
+ info->cb = cb;
+
+ /* Ask for the descriptor */
+ info->packet[0].pid = USB_TOKEN_SETUP;
+ info->packet[0].devaddr = 0;
+ info->packet[0].devep = 0;
+ info->packet[0].data = info->buffer;
+ info->packet[0].len = 8;
+ info->packet[0].complete_cb = usb_packet_next;
+ info->packet[0].complete_opaque = info;
+
+ info->buffer[0] = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
+ info->buffer[1] = USB_REQ_GET_DESCRIPTOR;
+ info->buffer[2] = idx;
+ info->buffer[3] = desc;
+ info->buffer[4] = 0x00;
+ info->buffer[5] = 0x00;
+ info->buffer[6] = sizeof(info->buffer) & 0xff;
+ info->buffer[7] = sizeof(info->buffer) >> 8;
+
+ /* Read the response */
+ info->packet[1].pid = USB_TOKEN_IN;
+ info->packet[1].devaddr = 0;
+ info->packet[1].devep = 0;
+ info->packet[1].data = info->buffer;
+ info->packet[1].len = sizeof(info->buffer);
+ info->packet[1].complete_cb = usb_packet_next;
+ info->packet[1].complete_opaque = info;
+
+ usb_packet_next(0, info);
+}
+
+static void usb_config_desc(USBPacket *packet, void *opaque)
+{
+ struct usb_slave_info_s *info = (struct usb_slave_info_s *) opaque;
+ char buffer[128];
+ int config_str;
+
+ if (packet->data[1] == USB_DT_CONFIG) {
+ config_str = packet->data[6];
+ usb_get_descriptor(info, usb_config_desc, USB_DT_STRING, config_str);
+ } else if (packet->data[1] == USB_DT_STRING) {
+ get_usb_string(buffer, packet->data);
+ term_printf("Configuration %i: %s\n", info->config, buffer);
+
+ if (++ info->config < info->config_num)
+ usb_get_descriptor(info, usb_config_desc,
+ USB_DT_CONFIG, info->config);
+ } else {
+ term_printf("Response unrecognised\n");
+ }
+}
+
+static void usb_prod_string(USBPacket *packet, void *opaque)
+{
+ struct usb_slave_info_s *info = (struct usb_slave_info_s *) opaque;
+ char buffer[128];
+
+ if (packet->data[1] != USB_DT_STRING) {
+ term_printf("Response unrecognised\n");
+ return;
+ }
+
+ get_usb_string(buffer, packet->data);
+ term_printf("Product: %s\n", buffer);
+
+ info->config = 0;
+ usb_get_descriptor(info, usb_config_desc, USB_DT_CONFIG, 0);
+}
+
+static void usb_manf_string(USBPacket *packet, void *opaque)
+{
+ struct usb_slave_info_s *info = (struct usb_slave_info_s *) opaque;
+ char buffer[128];
+
+ if (packet->data[1] != USB_DT_STRING) {
+ term_printf("Response unrecognised\n");
+ return;
+ }
+
+ get_usb_string(buffer, packet->data);
+ term_printf("Manufacturer: %s\n", buffer);
+
+ usb_get_descriptor(info, usb_prod_string, USB_DT_STRING, info->prod_str);
+}
+
+static void usb_dev_desc(USBPacket *packet, void *opaque)
+{
+ struct usb_slave_info_s *info = (struct usb_slave_info_s *) opaque;
+
+ if (packet->data[1] != USB_DT_DEVICE) {
+ term_printf("Response unrecognised\n");
+ return;
+ }
+
+ info->config_num = packet->data[17];
+ info->manf_str = packet->data[14];
+ info->prod_str = packet->data[15];
+ term_printf("USB%x.%x device %04x:%04x:\n",
+ packet->data[3], packet->data[4],
+ (packet->data[9] << 8) | packet->data[8],
+ (packet->data[11] << 8) | packet->data[10]);
+
+ usb_get_descriptor(info, usb_manf_string, USB_DT_STRING, info->manf_str);
+}
+
+void usb_timeout_tick(void *opaque)
+{
+ struct usb_slave_info_s *info = (struct usb_slave_info_s *) opaque;
+ term_printf("Slave device response time-out\n");
+ info->timedout = 1;
+}
+
+void usb_slave_info(void)
+{
+ struct usb_slave_info_s *info =
+ qemu_mallocz(sizeof(struct usb_slave_info_s));
+ if (!usb_gadget) {
+ term_printf("No USB slave functionality\n");
+ return;
+ }
+
+ info->slave = usb_gadget;
+ info->timeout = 500;
+ info->timedout = 0;
+ info->timeout_tm = qemu_new_timer(rt_clock, usb_timeout_tick, info);
+
+ usb_get_descriptor(info, usb_dev_desc, USB_DT_DEVICE, 0);
+}
+
/***********************************************************/
/* PCMCIA/Cardbus */
Modified: trunk/src/host/qemu-neo1973/vl.h
===================================================================
--- trunk/src/host/qemu-neo1973/vl.h 2007-05-08 09:21:11 UTC (rev 1928)
+++ trunk/src/host/qemu-neo1973/vl.h 2007-05-08 15:25:51 UTC (rev 1929)
@@ -1239,6 +1239,7 @@
void do_usb_add(const char *devname);
void do_usb_del(const char *devname);
void usb_info(void);
+void usb_slave_info(void);
/* scsi-disk.c */
enum scsi_reason {
More information about the commitlog
mailing list