@@ -78,7 +78,7 @@ common-obj-y += msmouse.o ps2.o
common-obj-y += qdev.o qdev-properties.o
common-obj-y += qemu-config.o block-migration.o
-common-obj-$(CONFIG_BRLAPI) += baum.o
+common-obj-$(CONFIG_BRLAPI) += baum.o bt-baum.o
common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
@@ -22,5 +22,9 @@
* THE SOFTWARE.
*/
+#include "qemu-char.h"
+#include "bt.h"
/* char device */
CharDriverState *chr_baum_init(QemuOpts *opts);
+/* bluetooth device */
+struct bt_device_s *bt_baum_init(struct bt_scatternet_s *net);
new file mode 100644
@@ -0,0 +1,158 @@
+/*
+ * QEMU Bluetooth Baum driver.
+ *
+ * Copyright (C) 2010 Samuel Thibault <samuel.thibault@ens-lyon.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu-common.h"
+#include "baum.h"
+#include "bt.h"
+
+#define BT_BAUM_MTU 1000
+
+struct bt_baum_device_s {
+ struct bt_l2cap_device_s btdev;
+ struct bt_l2cap_conn_params_s *ch;
+
+ CharDriverState *cdrv;
+};
+
+static int bt_baum_can_read(void *opaque)
+{
+ struct bt_baum_device_s *s = opaque;
+ /* Is there room in the bluetooth socket? */
+
+ if (!s->ch)
+ return 0;
+
+ return s->ch->remote_mtu;
+}
+
+static void bt_baum_read(void *opaque, const uint8_t *buf, int size)
+{
+ /* Got data from the Baum device to send over bluetooth to the guest */
+ struct bt_baum_device_s *s = opaque;
+ uint8_t *pkt;
+ int len;
+ struct bt_l2cap_conn_params_s *ch = s->ch;
+
+ if (!ch)
+ return;
+
+ while (size) {
+ len = MIN(size, ch->remote_mtu);
+ pkt = ch->sdu_out(ch, size);
+ memcpy(pkt, buf, size);
+ ch->sdu_submit(ch);
+ size -= len;
+ buf += len;
+ };
+}
+
+static void bt_baum_sdu(void *opaque, const uint8_t *data, int len)
+{
+ /* Got data from bluetooth, to be sent to the Baum device */
+ struct bt_baum_device_s *s = opaque;
+ qemu_chr_write(s->cdrv, data, len);
+}
+
+static void bt_baum_close_ch(void *opaque)
+{
+ struct bt_baum_device_s *s = opaque;
+
+ s->btdev.device.page_scan = 1;
+ s->btdev.device.inquiry_scan = 1;
+
+ s->ch = NULL;
+ printf("close connection\n");
+}
+
+static int bt_baum_new_ch(struct bt_l2cap_device_s *dev,
+ struct bt_l2cap_conn_params_s *params)
+{
+ struct bt_baum_device_s *s = (struct bt_baum_device_s *) dev;
+
+ if (s->ch) {
+ printf("already there: %p\n", s->ch);
+ return 1;
+ }
+
+ printf("new connection\n");
+ s->ch = params;
+ s->ch->opaque = s;
+ s->ch->close = bt_baum_close_ch;
+ s->ch->sdu_in = bt_baum_sdu;
+
+ s->btdev.device.page_scan = 0;
+ s->btdev.device.inquiry_scan = 0;
+
+ return 0;
+}
+
+static void bt_baum_destroy(struct bt_device_s *dev)
+{
+ struct bt_baum_device_s *s = (struct bt_baum_device_s *) dev;
+
+ bt_l2cap_device_done(&s->btdev);
+
+ qemu_chr_close(s->cdrv);
+
+ qemu_free(s);
+}
+
+struct bt_device_s *bt_baum_init(struct bt_scatternet_s *net)
+{
+ struct bt_baum_device_s *s;
+ /* FIXME */
+ uint32_t class =
+ /* Format type */
+ (0 << 0) |
+ /* Device class */
+ (0 << 2) |
+ (5 << 8) | /* "Peripheral" */
+ /* Service classes */
+ (1 << 13) | /* Limited discoverable mode */
+ (1 << 19); /* Capturing device (?) */
+
+ s = qemu_mallocz(sizeof(*s));
+ if (!s)
+ return NULL;
+
+ s->cdrv = qemu_chr_open("braille", "braille", NULL);
+
+ if (!s->cdrv) {
+ qemu_free(s);
+ return NULL;
+ }
+
+ bt_l2cap_device_init(&s->btdev, net);
+ bt_l2cap_sdp_init(&s->btdev);
+
+ s->btdev.device.lmp_name = "QEMU USB Braille";
+ s->btdev.device.handle_destroy = bt_baum_destroy;
+
+ printf("chan is %p\n", bt_baum_new_ch);
+ bt_l2cap_psm_register(&s->btdev, BT_PSM_RFCOMM,
+ BT_BAUM_MTU, bt_baum_new_ch);
+
+ qemu_chr_add_handlers(s->cdrv, bt_baum_can_read, bt_baum_read, NULL, s);
+
+ s->btdev.device.class[0] = (class >> 0) & 0xff;
+ s->btdev.device.class[1] = (class >> 8) & 0xff;
+ s->btdev.device.class[2] = (class >> 16) & 0xff;
+
+ return &s->btdev.device;
+}
@@ -23,6 +23,9 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#ifndef BT_H
+#define BT_H
+
/* BD Address */
typedef struct {
uint8_t b[6];
@@ -2181,3 +2184,4 @@ enum bt_sdp_attribute_id {
SDP_ATTR_NORMALLY_CONNECTABLE = 0x020d,
SDP_ATTR_BOOT_DEVICE = 0x020e,
};
+#endif
@@ -1741,6 +1741,9 @@ static struct bt_device_s *bt_device_add(const char *opt)
if (!strcmp(devname, "keyboard"))
return bt_keyboard_init(vlan);
+ if (!strcmp(devname, "braille"))
+ return bt_baum_init(vlan);
+
fprintf(stderr, "qemu: unsupported bluetooth device `%s'\n", devname);
return 0;
}