Commit dc72ac14d8ceeaac0ca63f385ba3f44fd580b963
1 parent
793a10a2
Add the -bt switch for setting up bluetooth stuff.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5652 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
172 additions
and
2 deletions
vl.c
| @@ -169,6 +169,9 @@ | @@ -169,6 +169,9 @@ | ||
| 169 | /* Max number of USB devices that can be specified on the commandline. */ | 169 | /* Max number of USB devices that can be specified on the commandline. */ |
| 170 | #define MAX_USB_CMDLINE 8 | 170 | #define MAX_USB_CMDLINE 8 |
| 171 | 171 | ||
| 172 | +/* Max number of bluetooth switches on the commandline. */ | ||
| 173 | +#define MAX_BT_CMDLINE 10 | ||
| 174 | + | ||
| 172 | /* XXX: use a two level table to limit memory usage */ | 175 | /* XXX: use a two level table to limit memory usage */ |
| 173 | #define MAX_IOPORTS 65536 | 176 | #define MAX_IOPORTS 65536 |
| 174 | 177 | ||
| @@ -1935,7 +1938,7 @@ int check_params(char *buf, int buf_size, | @@ -1935,7 +1938,7 @@ int check_params(char *buf, int buf_size, | ||
| 1935 | static int nb_hcis; | 1938 | static int nb_hcis; |
| 1936 | static int cur_hci; | 1939 | static int cur_hci; |
| 1937 | static struct HCIInfo *hci_table[MAX_NICS]; | 1940 | static struct HCIInfo *hci_table[MAX_NICS]; |
| 1938 | -#if 0 | 1941 | + |
| 1939 | static struct bt_vlan_s { | 1942 | static struct bt_vlan_s { |
| 1940 | struct bt_scatternet_s net; | 1943 | struct bt_scatternet_s net; |
| 1941 | int id; | 1944 | int id; |
| @@ -1958,7 +1961,6 @@ static struct bt_scatternet_s *qemu_find_bt_vlan(int id) | @@ -1958,7 +1961,6 @@ static struct bt_scatternet_s *qemu_find_bt_vlan(int id) | ||
| 1958 | *pvlan = vlan; | 1961 | *pvlan = vlan; |
| 1959 | return &vlan->net; | 1962 | return &vlan->net; |
| 1960 | } | 1963 | } |
| 1961 | -#endif | ||
| 1962 | 1964 | ||
| 1963 | static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len) | 1965 | static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len) |
| 1964 | { | 1966 | { |
| @@ -1984,6 +1986,144 @@ struct HCIInfo *qemu_next_hci(void) | @@ -1984,6 +1986,144 @@ struct HCIInfo *qemu_next_hci(void) | ||
| 1984 | return hci_table[cur_hci++]; | 1986 | return hci_table[cur_hci++]; |
| 1985 | } | 1987 | } |
| 1986 | 1988 | ||
| 1989 | +static struct HCIInfo *hci_init(const char *str) | ||
| 1990 | +{ | ||
| 1991 | + char *endp; | ||
| 1992 | + struct bt_scatternet_s *vlan = 0; | ||
| 1993 | + | ||
| 1994 | + if (!strcmp(str, "null")) | ||
| 1995 | + /* null */ | ||
| 1996 | + return &null_hci; | ||
| 1997 | + else if (!strncmp(str, "host", 4) && (str[4] == '\0' || str[4] == ':')) | ||
| 1998 | + /* host[:hciN] */ | ||
| 1999 | + return bt_host_hci(str[4] ? str + 5 : "hci0"); | ||
| 2000 | + else if (!strncmp(str, "hci", 3)) { | ||
| 2001 | + /* hci[,vlan=n] */ | ||
| 2002 | + if (str[3]) { | ||
| 2003 | + if (!strncmp(str + 3, ",vlan=", 6)) { | ||
| 2004 | + vlan = qemu_find_bt_vlan(strtol(str + 9, &endp, 0)); | ||
| 2005 | + if (*endp) | ||
| 2006 | + vlan = 0; | ||
| 2007 | + } | ||
| 2008 | + } else | ||
| 2009 | + vlan = qemu_find_bt_vlan(0); | ||
| 2010 | + if (vlan) | ||
| 2011 | + return bt_new_hci(vlan); | ||
| 2012 | + } | ||
| 2013 | + | ||
| 2014 | + fprintf(stderr, "qemu: Unknown bluetooth HCI `%s'.\n", str); | ||
| 2015 | + | ||
| 2016 | + return 0; | ||
| 2017 | +} | ||
| 2018 | + | ||
| 2019 | +static int bt_hci_parse(const char *str) | ||
| 2020 | +{ | ||
| 2021 | + struct HCIInfo *hci; | ||
| 2022 | + bdaddr_t bdaddr; | ||
| 2023 | + | ||
| 2024 | + if (nb_hcis >= MAX_NICS) { | ||
| 2025 | + fprintf(stderr, "qemu: Too many bluetooth HCIs (max %i).\n", MAX_NICS); | ||
| 2026 | + return -1; | ||
| 2027 | + } | ||
| 2028 | + | ||
| 2029 | + hci = hci_init(str); | ||
| 2030 | + if (!hci) | ||
| 2031 | + return -1; | ||
| 2032 | + | ||
| 2033 | + bdaddr.b[0] = 0x52; | ||
| 2034 | + bdaddr.b[1] = 0x54; | ||
| 2035 | + bdaddr.b[2] = 0x00; | ||
| 2036 | + bdaddr.b[3] = 0x12; | ||
| 2037 | + bdaddr.b[4] = 0x34; | ||
| 2038 | + bdaddr.b[5] = 0x56 + nb_hcis; | ||
| 2039 | + hci->bdaddr_set(hci, bdaddr.b); | ||
| 2040 | + | ||
| 2041 | + hci_table[nb_hcis++] = hci; | ||
| 2042 | + | ||
| 2043 | + return 0; | ||
| 2044 | +} | ||
| 2045 | + | ||
| 2046 | +static void bt_vhci_add(int vlan_id) | ||
| 2047 | +{ | ||
| 2048 | + struct bt_scatternet_s *vlan = qemu_find_bt_vlan(vlan_id); | ||
| 2049 | + | ||
| 2050 | + if (!vlan->slave) | ||
| 2051 | + fprintf(stderr, "qemu: warning: adding a VHCI to " | ||
| 2052 | + "an empty scatternet %i\n", vlan_id); | ||
| 2053 | + | ||
| 2054 | + bt_vhci_init(bt_new_hci(vlan)); | ||
| 2055 | +} | ||
| 2056 | + | ||
| 2057 | +static struct bt_device_s *bt_device_add(const char *opt) | ||
| 2058 | +{ | ||
| 2059 | + struct bt_scatternet_s *vlan; | ||
| 2060 | + int vlan_id = 0; | ||
| 2061 | + char *endp = strstr(opt, ",vlan="); | ||
| 2062 | + int len = (endp ? endp - opt : strlen(opt)) + 1; | ||
| 2063 | + char devname[10]; | ||
| 2064 | + | ||
| 2065 | + pstrcpy(devname, MIN(sizeof(devname), len), opt); | ||
| 2066 | + | ||
| 2067 | + if (endp) { | ||
| 2068 | + vlan_id = strtol(endp + 6, &endp, 0); | ||
| 2069 | + if (*endp) { | ||
| 2070 | + fprintf(stderr, "qemu: unrecognised bluetooth vlan Id\n"); | ||
| 2071 | + return 0; | ||
| 2072 | + } | ||
| 2073 | + } | ||
| 2074 | + | ||
| 2075 | + vlan = qemu_find_bt_vlan(vlan_id); | ||
| 2076 | + | ||
| 2077 | + if (!vlan->slave) | ||
| 2078 | + fprintf(stderr, "qemu: warning: adding a slave device to " | ||
| 2079 | + "an empty scatternet %i\n", vlan_id); | ||
| 2080 | + | ||
| 2081 | + if (!strcmp(devname, "keyboard")) | ||
| 2082 | + return bt_keyboard_init(vlan); | ||
| 2083 | + | ||
| 2084 | + fprintf(stderr, "qemu: unsupported bluetooth device `%s'\n", devname); | ||
| 2085 | + return 0; | ||
| 2086 | +} | ||
| 2087 | + | ||
| 2088 | +static int bt_parse(const char *opt) | ||
| 2089 | +{ | ||
| 2090 | + const char *endp, *p; | ||
| 2091 | + int vlan; | ||
| 2092 | + | ||
| 2093 | + if (strstart(opt, "hci", &endp)) { | ||
| 2094 | + if (!*endp || *endp == ',') { | ||
| 2095 | + if (*endp) | ||
| 2096 | + if (!strstart(endp, ",vlan=", 0)) | ||
| 2097 | + opt = endp + 1; | ||
| 2098 | + | ||
| 2099 | + return bt_hci_parse(opt); | ||
| 2100 | + } | ||
| 2101 | + } else if (strstart(opt, "vhci", &endp)) { | ||
| 2102 | + if (!*endp || *endp == ',') { | ||
| 2103 | + if (*endp) { | ||
| 2104 | + if (strstart(endp, ",vlan=", &p)) { | ||
| 2105 | + vlan = strtol(p, (char **) &endp, 0); | ||
| 2106 | + if (*endp) { | ||
| 2107 | + fprintf(stderr, "qemu: bad scatternet '%s'\n", p); | ||
| 2108 | + return 1; | ||
| 2109 | + } | ||
| 2110 | + } else { | ||
| 2111 | + fprintf(stderr, "qemu: bad parameter '%s'\n", endp + 1); | ||
| 2112 | + return 1; | ||
| 2113 | + } | ||
| 2114 | + } else | ||
| 2115 | + vlan = 0; | ||
| 2116 | + | ||
| 2117 | + bt_vhci_add(vlan); | ||
| 2118 | + return 0; | ||
| 2119 | + } | ||
| 2120 | + } else if (strstart(opt, "device:", &endp)) | ||
| 2121 | + return !bt_device_add(endp); | ||
| 2122 | + | ||
| 2123 | + fprintf(stderr, "qemu: bad bluetooth parameter '%s'\n", opt); | ||
| 2124 | + return 1; | ||
| 2125 | +} | ||
| 2126 | + | ||
| 1987 | /***********************************************************/ | 2127 | /***********************************************************/ |
| 1988 | /* QEMU Block devices */ | 2128 | /* QEMU Block devices */ |
| 1989 | 2129 | ||
| @@ -2440,6 +2580,9 @@ static int usb_device_add(const char *devname) | @@ -2440,6 +2580,9 @@ static int usb_device_add(const char *devname) | ||
| 2440 | return -1; | 2580 | return -1; |
| 2441 | nd_table[nic].model = "usb"; | 2581 | nd_table[nic].model = "usb"; |
| 2442 | dev = usb_net_init(&nd_table[nic]); | 2582 | dev = usb_net_init(&nd_table[nic]); |
| 2583 | + } else if (!strcmp(devname, "bt") || strstart(devname, "bt:", &p)) { | ||
| 2584 | + dev = usb_bt_init(devname[2] ? hci_init(p) : | ||
| 2585 | + bt_new_hci(qemu_find_bt_vlan(0))); | ||
| 2443 | } else { | 2586 | } else { |
| 2444 | return -1; | 2587 | return -1; |
| 2445 | } | 2588 | } |
| @@ -4823,6 +4966,16 @@ static void help(int exitcode) | @@ -4823,6 +4966,16 @@ static void help(int exitcode) | ||
| 4823 | "-net none use it alone to have zero network devices; if no -net option\n" | 4966 | "-net none use it alone to have zero network devices; if no -net option\n" |
| 4824 | " is provided, the default is '-net nic -net user'\n" | 4967 | " is provided, the default is '-net nic -net user'\n" |
| 4825 | "\n" | 4968 | "\n" |
| 4969 | + "-bt hci,null Dumb bluetooth HCI - doesn't respond to commands\n" | ||
| 4970 | + "-bt hci,host[:id]\n" | ||
| 4971 | + " Use host's HCI with the given name\n" | ||
| 4972 | + "-bt hci[,vlan=n]\n" | ||
| 4973 | + " Emulate a standard HCI in virtual scatternet 'n'\n" | ||
| 4974 | + "-bt vhci[,vlan=n]\n" | ||
| 4975 | + " Add host computer to virtual scatternet 'n' using VHCI\n" | ||
| 4976 | + "-bt device:dev[,vlan=n]\n" | ||
| 4977 | + " Emulate a bluetooth device 'dev' in scatternet 'n'\n" | ||
| 4978 | + "\n" | ||
| 4826 | #ifdef CONFIG_SLIRP | 4979 | #ifdef CONFIG_SLIRP |
| 4827 | "-tftp dir allow tftp access to files in dir [-net user]\n" | 4980 | "-tftp dir allow tftp access to files in dir [-net user]\n" |
| 4828 | "-bootp file advertise file in BOOTP replies\n" | 4981 | "-bootp file advertise file in BOOTP replies\n" |
| @@ -4934,6 +5087,7 @@ enum { | @@ -4934,6 +5087,7 @@ enum { | ||
| 4934 | QEMU_OPTION_bootp, | 5087 | QEMU_OPTION_bootp, |
| 4935 | QEMU_OPTION_smb, | 5088 | QEMU_OPTION_smb, |
| 4936 | QEMU_OPTION_redir, | 5089 | QEMU_OPTION_redir, |
| 5090 | + QEMU_OPTION_bt, | ||
| 4937 | 5091 | ||
| 4938 | QEMU_OPTION_kernel, | 5092 | QEMU_OPTION_kernel, |
| 4939 | QEMU_OPTION_append, | 5093 | QEMU_OPTION_append, |
| @@ -5033,6 +5187,7 @@ static const QEMUOption qemu_options[] = { | @@ -5033,6 +5187,7 @@ static const QEMUOption qemu_options[] = { | ||
| 5033 | #endif | 5187 | #endif |
| 5034 | { "redir", HAS_ARG, QEMU_OPTION_redir }, | 5188 | { "redir", HAS_ARG, QEMU_OPTION_redir }, |
| 5035 | #endif | 5189 | #endif |
| 5190 | + { "bt", HAS_ARG, QEMU_OPTION_bt }, | ||
| 5036 | 5191 | ||
| 5037 | { "kernel", HAS_ARG, QEMU_OPTION_kernel }, | 5192 | { "kernel", HAS_ARG, QEMU_OPTION_kernel }, |
| 5038 | { "append", HAS_ARG, QEMU_OPTION_append }, | 5193 | { "append", HAS_ARG, QEMU_OPTION_append }, |
| @@ -5374,6 +5529,8 @@ int main(int argc, char **argv) | @@ -5374,6 +5529,8 @@ int main(int argc, char **argv) | ||
| 5374 | int cyls, heads, secs, translation; | 5529 | int cyls, heads, secs, translation; |
| 5375 | const char *net_clients[MAX_NET_CLIENTS]; | 5530 | const char *net_clients[MAX_NET_CLIENTS]; |
| 5376 | int nb_net_clients; | 5531 | int nb_net_clients; |
| 5532 | + const char *bt_opts[MAX_BT_CMDLINE]; | ||
| 5533 | + int nb_bt_opts; | ||
| 5377 | int hda_index; | 5534 | int hda_index; |
| 5378 | int optind; | 5535 | int optind; |
| 5379 | const char *r, *optarg; | 5536 | const char *r, *optarg; |
| @@ -5457,6 +5614,7 @@ int main(int argc, char **argv) | @@ -5457,6 +5614,7 @@ int main(int argc, char **argv) | ||
| 5457 | usb_devices_index = 0; | 5614 | usb_devices_index = 0; |
| 5458 | 5615 | ||
| 5459 | nb_net_clients = 0; | 5616 | nb_net_clients = 0; |
| 5617 | + nb_bt_opts = 0; | ||
| 5460 | nb_drives = 0; | 5618 | nb_drives = 0; |
| 5461 | nb_drives_opt = 0; | 5619 | nb_drives_opt = 0; |
| 5462 | hda_index = -1; | 5620 | hda_index = -1; |
| @@ -5692,6 +5850,13 @@ int main(int argc, char **argv) | @@ -5692,6 +5850,13 @@ int main(int argc, char **argv) | ||
| 5692 | net_slirp_redir(optarg); | 5850 | net_slirp_redir(optarg); |
| 5693 | break; | 5851 | break; |
| 5694 | #endif | 5852 | #endif |
| 5853 | + case QEMU_OPTION_bt: | ||
| 5854 | + if (nb_bt_opts >= MAX_BT_CMDLINE) { | ||
| 5855 | + fprintf(stderr, "qemu: too many bluetooth options\n"); | ||
| 5856 | + exit(1); | ||
| 5857 | + } | ||
| 5858 | + bt_opts[nb_bt_opts++] = optarg; | ||
| 5859 | + break; | ||
| 5695 | #ifdef HAS_AUDIO | 5860 | #ifdef HAS_AUDIO |
| 5696 | case QEMU_OPTION_audio_help: | 5861 | case QEMU_OPTION_audio_help: |
| 5697 | AUD_help (); | 5862 | AUD_help (); |
| @@ -6182,6 +6347,11 @@ int main(int argc, char **argv) | @@ -6182,6 +6347,11 @@ int main(int argc, char **argv) | ||
| 6182 | } | 6347 | } |
| 6183 | #endif | 6348 | #endif |
| 6184 | 6349 | ||
| 6350 | + /* init the bluetooth world */ | ||
| 6351 | + for (i = 0; i < nb_bt_opts; i++) | ||
| 6352 | + if (bt_parse(bt_opts[i])) | ||
| 6353 | + exit(1); | ||
| 6354 | + | ||
| 6185 | /* init the memory */ | 6355 | /* init the memory */ |
| 6186 | phys_ram_size = machine->ram_require & ~RAMSIZE_FIXED; | 6356 | phys_ram_size = machine->ram_require & ~RAMSIZE_FIXED; |
| 6187 | 6357 |