break;
case HCI_SCODATA_PKT:
- hdev->stat.cmd_tx++;
+ hdev->stat.sco_tx++;
break;
}
}
static int hci_uart_send_frame(struct sk_buff *skb)
{
struct hci_dev* hdev = (struct hci_dev *) skb->dev;
- struct tty_struct *tty;
struct hci_uart *hu;
if (!hdev) {
return -EBUSY;
hu = (struct hci_uart *) hdev->driver_data;
- tty = hu->tty;
BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
return;
BT_DBG("%s", hdev->name);
- kfree(hdev->driver_data);
}
/* ------ LDISC part ------ */
BT_DBG("tty %p", tty);
+ /* FIXME: This btw is bogus, nothing requires the old ldisc to clear
+ the pointer */
if (hu)
return -EEXIST;
+ /* Error if the tty has no write op instead of leaving an exploitable
+ hole */
+ if (tty->ops->write == NULL)
+ return -EOPNOTSUPP;
+
if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) {
BT_ERR("Can't allocate control structure");
return -ENFILE;
hci_uart_close(hdev);
if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
+ if (hdev) {
+ hci_unregister_dev(hdev);
+ hci_free_dev(hdev);
+ }
hu->proto->close(hu);
- hci_unregister_dev(hdev);
- hci_free_dev(hdev);
}
+ kfree(hu);
}
}
hdev->flush = hci_uart_flush;
hdev->send = hci_uart_send_frame;
hdev->destruct = hci_uart_destruct;
+ hdev->parent = hu->tty->dev;
hdev->owner = THIS_MODULE;
if (!reset)
set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
+ if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))
+ set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
+
if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device");
hci_free_dev(hdev);
return hu->hdev->id;
return -EUNATCH;
+ case HCIUARTSETFLAGS:
+ if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
+ return -EBUSY;
+ hu->hdev_flags = arg;
+ break;
+
+ case HCIUARTGETFLAGS:
+ return hu->hdev_flags;
+
default:
err = n_tty_ioctl_helper(tty, file, cmd, arg);
break;
#ifdef CONFIG_BT_HCIUART_LL
ll_init();
#endif
+#ifdef CONFIG_BT_HCIUART_ATH3K
+ ath_init();
+#endif
return 0;
}
#ifdef CONFIG_BT_HCIUART_LL
ll_deinit();
#endif
+#ifdef CONFIG_BT_HCIUART_ATH3K
+ ath_deinit();
+#endif
/* Release tty registration of line discipline */
if ((err = tty_unregister_ldisc(N_HCI)))