Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
This commit is contained in:
commit
57f784fed3
|
@ -177,7 +177,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||||
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
|
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
BT_ERR("Can't allocate memory for data structure");
|
BT_ERR("Can't allocate memory for data structure");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -189,14 +189,12 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||||
data->urb = usb_alloc_urb(0, GFP_KERNEL);
|
data->urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||||
if (!data->urb) {
|
if (!data->urb) {
|
||||||
BT_ERR("Can't allocate URB");
|
BT_ERR("Can't allocate URB");
|
||||||
kfree(data);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) {
|
if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) {
|
||||||
BT_ERR("Mini driver request failed");
|
BT_ERR("Mini driver request failed");
|
||||||
usb_free_urb(data->urb);
|
usb_free_urb(data->urb);
|
||||||
kfree(data);
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +207,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||||
BT_ERR("Can't allocate memory for mini driver");
|
BT_ERR("Can't allocate memory for mini driver");
|
||||||
release_firmware(firmware);
|
release_firmware(firmware);
|
||||||
usb_free_urb(data->urb);
|
usb_free_urb(data->urb);
|
||||||
kfree(data);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +221,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||||
BT_ERR("Firmware request failed");
|
BT_ERR("Firmware request failed");
|
||||||
usb_free_urb(data->urb);
|
usb_free_urb(data->urb);
|
||||||
kfree(data->buffer);
|
kfree(data->buffer);
|
||||||
kfree(data);
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +232,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||||
release_firmware(firmware);
|
release_firmware(firmware);
|
||||||
usb_free_urb(data->urb);
|
usb_free_urb(data->urb);
|
||||||
kfree(data->buffer);
|
kfree(data->buffer);
|
||||||
kfree(data);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,7 +266,6 @@ static void bcm203x_disconnect(struct usb_interface *intf)
|
||||||
usb_free_urb(data->urb);
|
usb_free_urb(data->urb);
|
||||||
kfree(data->fw_data);
|
kfree(data->fw_data);
|
||||||
kfree(data->buffer);
|
kfree(data->buffer);
|
||||||
kfree(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct usb_driver bcm203x_driver = {
|
static struct usb_driver bcm203x_driver = {
|
||||||
|
|
|
@ -653,7 +653,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize control structure and load firmware */
|
/* Initialize control structure and load firmware */
|
||||||
data = kzalloc(sizeof(struct bfusb_data), GFP_KERNEL);
|
data = devm_kzalloc(&intf->dev, sizeof(struct bfusb_data), GFP_KERNEL);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
BT_ERR("Can't allocate memory for control structure");
|
BT_ERR("Can't allocate memory for control structure");
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -674,7 +674,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||||
|
|
||||||
if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) {
|
if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) {
|
||||||
BT_ERR("Firmware request failed");
|
BT_ERR("Firmware request failed");
|
||||||
goto error;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
|
BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
|
||||||
|
@ -690,7 +690,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||||
hdev = hci_alloc_dev();
|
hdev = hci_alloc_dev();
|
||||||
if (!hdev) {
|
if (!hdev) {
|
||||||
BT_ERR("Can't allocate HCI device");
|
BT_ERR("Can't allocate HCI device");
|
||||||
goto error;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->hdev = hdev;
|
data->hdev = hdev;
|
||||||
|
@ -708,7 +708,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||||
if (hci_register_dev(hdev) < 0) {
|
if (hci_register_dev(hdev) < 0) {
|
||||||
BT_ERR("Can't register HCI device");
|
BT_ERR("Can't register HCI device");
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
goto error;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_set_intfdata(intf, data);
|
usb_set_intfdata(intf, data);
|
||||||
|
@ -718,9 +718,6 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||||
release:
|
release:
|
||||||
release_firmware(firmware);
|
release_firmware(firmware);
|
||||||
|
|
||||||
error:
|
|
||||||
kfree(data);
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
@ -741,7 +738,6 @@ static void bfusb_disconnect(struct usb_interface *intf)
|
||||||
|
|
||||||
hci_unregister_dev(hdev);
|
hci_unregister_dev(hdev);
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
kfree(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct usb_driver bfusb_driver = {
|
static struct usb_driver bfusb_driver = {
|
||||||
|
|
|
@ -849,7 +849,7 @@ static int bluecard_probe(struct pcmcia_device *link)
|
||||||
bluecard_info_t *info;
|
bluecard_info_t *info;
|
||||||
|
|
||||||
/* Create new info device */
|
/* Create new info device */
|
||||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
|
||||||
if (!info)
|
if (!info)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -864,10 +864,7 @@ static int bluecard_probe(struct pcmcia_device *link)
|
||||||
|
|
||||||
static void bluecard_detach(struct pcmcia_device *link)
|
static void bluecard_detach(struct pcmcia_device *link)
|
||||||
{
|
{
|
||||||
bluecard_info_t *info = link->priv;
|
|
||||||
|
|
||||||
bluecard_release(link);
|
bluecard_release(link);
|
||||||
kfree(info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -443,7 +443,7 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||||
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
|
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
|
||||||
if (!data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -453,10 +453,8 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||||
init_usb_anchor(&data->rx_anchor);
|
init_usb_anchor(&data->rx_anchor);
|
||||||
|
|
||||||
hdev = hci_alloc_dev();
|
hdev = hci_alloc_dev();
|
||||||
if (!hdev) {
|
if (!hdev)
|
||||||
kfree(data);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
hdev->bus = HCI_USB;
|
hdev->bus = HCI_USB;
|
||||||
hci_set_drvdata(hdev, data);
|
hci_set_drvdata(hdev, data);
|
||||||
|
@ -475,7 +473,6 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||||
err = hci_register_dev(hdev);
|
err = hci_register_dev(hdev);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
kfree(data);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,7 +497,6 @@ static void bpa10x_disconnect(struct usb_interface *intf)
|
||||||
hci_free_dev(data->hdev);
|
hci_free_dev(data->hdev);
|
||||||
kfree_skb(data->rx_skb[0]);
|
kfree_skb(data->rx_skb[0]);
|
||||||
kfree_skb(data->rx_skb[1]);
|
kfree_skb(data->rx_skb[1]);
|
||||||
kfree(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct usb_driver bpa10x_driver = {
|
static struct usb_driver bpa10x_driver = {
|
||||||
|
|
|
@ -638,7 +638,7 @@ static int bt3c_probe(struct pcmcia_device *link)
|
||||||
bt3c_info_t *info;
|
bt3c_info_t *info;
|
||||||
|
|
||||||
/* Create new info device */
|
/* Create new info device */
|
||||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
|
||||||
if (!info)
|
if (!info)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -654,10 +654,7 @@ static int bt3c_probe(struct pcmcia_device *link)
|
||||||
|
|
||||||
static void bt3c_detach(struct pcmcia_device *link)
|
static void bt3c_detach(struct pcmcia_device *link)
|
||||||
{
|
{
|
||||||
bt3c_info_t *info = link->priv;
|
|
||||||
|
|
||||||
bt3c_release(link);
|
bt3c_release(link);
|
||||||
kfree(info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data)
|
static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data)
|
||||||
|
|
|
@ -956,11 +956,9 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
|
||||||
BT_INFO("vendor=0x%x, device=0x%x, class=%d, fn=%d",
|
BT_INFO("vendor=0x%x, device=0x%x, class=%d, fn=%d",
|
||||||
id->vendor, id->device, id->class, func->num);
|
id->vendor, id->device, id->class, func->num);
|
||||||
|
|
||||||
card = kzalloc(sizeof(*card), GFP_KERNEL);
|
card = devm_kzalloc(&func->dev, sizeof(*card), GFP_KERNEL);
|
||||||
if (!card) {
|
if (!card)
|
||||||
ret = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
card->func = func;
|
card->func = func;
|
||||||
|
|
||||||
|
@ -974,8 +972,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
|
||||||
|
|
||||||
if (btmrvl_sdio_register_dev(card) < 0) {
|
if (btmrvl_sdio_register_dev(card) < 0) {
|
||||||
BT_ERR("Failed to register BT device!");
|
BT_ERR("Failed to register BT device!");
|
||||||
ret = -ENODEV;
|
return -ENODEV;
|
||||||
goto free_card;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable the interrupts on the card */
|
/* Disable the interrupts on the card */
|
||||||
|
@ -1023,9 +1020,6 @@ disable_host_int:
|
||||||
btmrvl_sdio_disable_host_int(card);
|
btmrvl_sdio_disable_host_int(card);
|
||||||
unreg_dev:
|
unreg_dev:
|
||||||
btmrvl_sdio_unregister_dev(card);
|
btmrvl_sdio_unregister_dev(card);
|
||||||
free_card:
|
|
||||||
kfree(card);
|
|
||||||
done:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1047,7 +1041,6 @@ static void btmrvl_sdio_remove(struct sdio_func *func)
|
||||||
BT_DBG("unregester dev");
|
BT_DBG("unregester dev");
|
||||||
btmrvl_sdio_unregister_dev(card);
|
btmrvl_sdio_unregister_dev(card);
|
||||||
btmrvl_remove_card(card->priv);
|
btmrvl_remove_card(card->priv);
|
||||||
kfree(card);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -304,7 +304,7 @@ static int btsdio_probe(struct sdio_func *func,
|
||||||
tuple = tuple->next;
|
tuple = tuple->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL);
|
||||||
if (!data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -315,10 +315,8 @@ static int btsdio_probe(struct sdio_func *func,
|
||||||
skb_queue_head_init(&data->txq);
|
skb_queue_head_init(&data->txq);
|
||||||
|
|
||||||
hdev = hci_alloc_dev();
|
hdev = hci_alloc_dev();
|
||||||
if (!hdev) {
|
if (!hdev)
|
||||||
kfree(data);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
hdev->bus = HCI_SDIO;
|
hdev->bus = HCI_SDIO;
|
||||||
hci_set_drvdata(hdev, data);
|
hci_set_drvdata(hdev, data);
|
||||||
|
@ -340,7 +338,6 @@ static int btsdio_probe(struct sdio_func *func,
|
||||||
err = hci_register_dev(hdev);
|
err = hci_register_dev(hdev);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
kfree(data);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,7 +363,6 @@ static void btsdio_remove(struct sdio_func *func)
|
||||||
hci_unregister_dev(hdev);
|
hci_unregister_dev(hdev);
|
||||||
|
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
kfree(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sdio_driver btsdio_driver = {
|
static struct sdio_driver btsdio_driver = {
|
||||||
|
|
|
@ -567,7 +567,7 @@ static int btuart_probe(struct pcmcia_device *link)
|
||||||
btuart_info_t *info;
|
btuart_info_t *info;
|
||||||
|
|
||||||
/* Create new info device */
|
/* Create new info device */
|
||||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
|
||||||
if (!info)
|
if (!info)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -583,10 +583,7 @@ static int btuart_probe(struct pcmcia_device *link)
|
||||||
|
|
||||||
static void btuart_detach(struct pcmcia_device *link)
|
static void btuart_detach(struct pcmcia_device *link)
|
||||||
{
|
{
|
||||||
btuart_info_t *info = link->priv;
|
|
||||||
|
|
||||||
btuart_release(link);
|
btuart_release(link);
|
||||||
kfree(info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data)
|
static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data)
|
||||||
|
|
|
@ -952,7 +952,7 @@ static int btusb_probe(struct usb_interface *intf,
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
|
||||||
if (!data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -975,10 +975,8 @@ static int btusb_probe(struct usb_interface *intf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) {
|
if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep)
|
||||||
kfree(data);
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
|
||||||
|
|
||||||
data->cmdreq_type = USB_TYPE_CLASS;
|
data->cmdreq_type = USB_TYPE_CLASS;
|
||||||
|
|
||||||
|
@ -998,10 +996,8 @@ static int btusb_probe(struct usb_interface *intf,
|
||||||
init_usb_anchor(&data->deferred);
|
init_usb_anchor(&data->deferred);
|
||||||
|
|
||||||
hdev = hci_alloc_dev();
|
hdev = hci_alloc_dev();
|
||||||
if (!hdev) {
|
if (!hdev)
|
||||||
kfree(data);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
hdev->bus = HCI_USB;
|
hdev->bus = HCI_USB;
|
||||||
hci_set_drvdata(hdev, data);
|
hci_set_drvdata(hdev, data);
|
||||||
|
@ -1069,7 +1065,6 @@ static int btusb_probe(struct usb_interface *intf,
|
||||||
data->isoc, data);
|
data->isoc, data);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
kfree(data);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1077,7 +1072,6 @@ static int btusb_probe(struct usb_interface *intf,
|
||||||
err = hci_register_dev(hdev);
|
err = hci_register_dev(hdev);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
kfree(data);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1110,7 +1104,6 @@ static void btusb_disconnect(struct usb_interface *intf)
|
||||||
usb_driver_release_interface(&btusb_driver, data->isoc);
|
usb_driver_release_interface(&btusb_driver, data->isoc);
|
||||||
|
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
kfree(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
|
|
|
@ -297,16 +297,14 @@ static int bt_ti_probe(struct platform_device *pdev)
|
||||||
struct hci_dev *hdev;
|
struct hci_dev *hdev;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
hst = kzalloc(sizeof(struct ti_st), GFP_KERNEL);
|
hst = devm_kzalloc(&pdev->dev, sizeof(struct ti_st), GFP_KERNEL);
|
||||||
if (!hst)
|
if (!hst)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* Expose "hciX" device to user space */
|
/* Expose "hciX" device to user space */
|
||||||
hdev = hci_alloc_dev();
|
hdev = hci_alloc_dev();
|
||||||
if (!hdev) {
|
if (!hdev)
|
||||||
kfree(hst);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
BT_DBG("hdev %p", hdev);
|
BT_DBG("hdev %p", hdev);
|
||||||
|
|
||||||
|
@ -321,7 +319,6 @@ static int bt_ti_probe(struct platform_device *pdev)
|
||||||
err = hci_register_dev(hdev);
|
err = hci_register_dev(hdev);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
BT_ERR("Can't register HCI device error %d", err);
|
BT_ERR("Can't register HCI device error %d", err);
|
||||||
kfree(hst);
|
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -347,7 +344,6 @@ static int bt_ti_remove(struct platform_device *pdev)
|
||||||
hci_unregister_dev(hdev);
|
hci_unregister_dev(hdev);
|
||||||
|
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
kfree(hst);
|
|
||||||
|
|
||||||
dev_set_drvdata(&pdev->dev, NULL);
|
dev_set_drvdata(&pdev->dev, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -550,7 +550,7 @@ static int dtl1_probe(struct pcmcia_device *link)
|
||||||
dtl1_info_t *info;
|
dtl1_info_t *info;
|
||||||
|
|
||||||
/* Create new info device */
|
/* Create new info device */
|
||||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
|
||||||
if (!info)
|
if (!info)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -569,7 +569,6 @@ static void dtl1_detach(struct pcmcia_device *link)
|
||||||
|
|
||||||
dtl1_close(info);
|
dtl1_close(info);
|
||||||
pcmcia_disable_device(link);
|
pcmcia_disable_device(link);
|
||||||
kfree(info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data)
|
static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data)
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include <linux/poll.h>
|
#include <linux/poll.h>
|
||||||
#include <net/sock.h>
|
#include <net/sock.h>
|
||||||
|
#include <linux/seq_file.h>
|
||||||
|
|
||||||
#ifndef AF_BLUETOOTH
|
#ifndef AF_BLUETOOTH
|
||||||
#define AF_BLUETOOTH 31
|
#define AF_BLUETOOTH 31
|
||||||
|
@ -202,6 +203,10 @@ enum {
|
||||||
struct bt_sock_list {
|
struct bt_sock_list {
|
||||||
struct hlist_head head;
|
struct hlist_head head;
|
||||||
rwlock_t lock;
|
rwlock_t lock;
|
||||||
|
#ifdef CONFIG_PROC_FS
|
||||||
|
struct file_operations fops;
|
||||||
|
int (* custom_seq_show)(struct seq_file *, void *);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
int bt_sock_register(int proto, const struct net_proto_family *ops);
|
int bt_sock_register(int proto, const struct net_proto_family *ops);
|
||||||
|
@ -292,6 +297,11 @@ extern void hci_sock_cleanup(void);
|
||||||
extern int bt_sysfs_init(void);
|
extern int bt_sysfs_init(void);
|
||||||
extern void bt_sysfs_cleanup(void);
|
extern void bt_sysfs_cleanup(void);
|
||||||
|
|
||||||
|
extern int bt_procfs_init(struct module* module, struct net *net, const char *name,
|
||||||
|
struct bt_sock_list* sk_list,
|
||||||
|
int (* seq_show)(struct seq_file *, void *));
|
||||||
|
extern void bt_procfs_cleanup(struct net *net, const char *name);
|
||||||
|
|
||||||
extern struct dentry *bt_debugfs;
|
extern struct dentry *bt_debugfs;
|
||||||
|
|
||||||
int l2cap_init(void);
|
int l2cap_init(void);
|
||||||
|
|
|
@ -62,6 +62,15 @@
|
||||||
/* First BR/EDR Controller shall have ID = 0 */
|
/* First BR/EDR Controller shall have ID = 0 */
|
||||||
#define HCI_BREDR_ID 0
|
#define HCI_BREDR_ID 0
|
||||||
|
|
||||||
|
/* AMP controller status */
|
||||||
|
#define AMP_CTRL_POWERED_DOWN 0x00
|
||||||
|
#define AMP_CTRL_BLUETOOTH_ONLY 0x01
|
||||||
|
#define AMP_CTRL_NO_CAPACITY 0x02
|
||||||
|
#define AMP_CTRL_LOW_CAPACITY 0x03
|
||||||
|
#define AMP_CTRL_MEDIUM_CAPACITY 0x04
|
||||||
|
#define AMP_CTRL_HIGH_CAPACITY 0x05
|
||||||
|
#define AMP_CTRL_FULL_CAPACITY 0x06
|
||||||
|
|
||||||
/* HCI device quirks */
|
/* HCI device quirks */
|
||||||
enum {
|
enum {
|
||||||
HCI_QUIRK_RESET_ON_CLOSE,
|
HCI_QUIRK_RESET_ON_CLOSE,
|
||||||
|
@ -1295,6 +1304,8 @@ struct hci_ev_num_comp_blocks {
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
/* Low energy meta events */
|
/* Low energy meta events */
|
||||||
|
#define LE_CONN_ROLE_MASTER 0x00
|
||||||
|
|
||||||
#define HCI_EV_LE_CONN_COMPLETE 0x01
|
#define HCI_EV_LE_CONN_COMPLETE 0x01
|
||||||
struct hci_ev_le_conn_complete {
|
struct hci_ev_le_conn_complete {
|
||||||
__u8 status;
|
__u8 status;
|
||||||
|
|
|
@ -115,12 +115,6 @@ struct oob_data {
|
||||||
u8 randomizer[16];
|
u8 randomizer[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct adv_entry {
|
|
||||||
struct list_head list;
|
|
||||||
bdaddr_t bdaddr;
|
|
||||||
u8 bdaddr_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct le_scan_params {
|
struct le_scan_params {
|
||||||
u8 type;
|
u8 type;
|
||||||
u16 interval;
|
u16 interval;
|
||||||
|
@ -356,16 +350,16 @@ extern rwlock_t hci_cb_list_lock;
|
||||||
|
|
||||||
/* ----- HCI interface to upper protocols ----- */
|
/* ----- HCI interface to upper protocols ----- */
|
||||||
extern int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
|
extern int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
|
||||||
extern int l2cap_connect_cfm(struct hci_conn *hcon, u8 status);
|
extern void l2cap_connect_cfm(struct hci_conn *hcon, u8 status);
|
||||||
extern int l2cap_disconn_ind(struct hci_conn *hcon);
|
extern int l2cap_disconn_ind(struct hci_conn *hcon);
|
||||||
extern int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason);
|
extern void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason);
|
||||||
extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
|
extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
|
||||||
extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb,
|
extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb,
|
||||||
u16 flags);
|
u16 flags);
|
||||||
|
|
||||||
extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
|
extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
|
||||||
extern int sco_connect_cfm(struct hci_conn *hcon, __u8 status);
|
extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status);
|
||||||
extern int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
|
extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
|
||||||
extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
|
extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
|
||||||
|
|
||||||
/* ----- Inquiry cache ----- */
|
/* ----- Inquiry cache ----- */
|
||||||
|
@ -587,8 +581,7 @@ void hci_conn_put_device(struct hci_conn *conn);
|
||||||
|
|
||||||
static inline void hci_conn_hold(struct hci_conn *conn)
|
static inline void hci_conn_hold(struct hci_conn *conn)
|
||||||
{
|
{
|
||||||
BT_DBG("hcon %p refcnt %d -> %d", conn, atomic_read(&conn->refcnt),
|
BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt));
|
||||||
atomic_read(&conn->refcnt) + 1);
|
|
||||||
|
|
||||||
atomic_inc(&conn->refcnt);
|
atomic_inc(&conn->refcnt);
|
||||||
cancel_delayed_work(&conn->disc_work);
|
cancel_delayed_work(&conn->disc_work);
|
||||||
|
@ -596,8 +589,7 @@ static inline void hci_conn_hold(struct hci_conn *conn)
|
||||||
|
|
||||||
static inline void hci_conn_put(struct hci_conn *conn)
|
static inline void hci_conn_put(struct hci_conn *conn)
|
||||||
{
|
{
|
||||||
BT_DBG("hcon %p refcnt %d -> %d", conn, atomic_read(&conn->refcnt),
|
BT_DBG("hcon %p orig refcnt %d", conn, atomic_read(&conn->refcnt));
|
||||||
atomic_read(&conn->refcnt) - 1);
|
|
||||||
|
|
||||||
if (atomic_dec_and_test(&conn->refcnt)) {
|
if (atomic_dec_and_test(&conn->refcnt)) {
|
||||||
unsigned long timeo;
|
unsigned long timeo;
|
||||||
|
@ -1056,7 +1048,7 @@ int mgmt_discovering(struct hci_dev *hdev, u8 discovering);
|
||||||
int mgmt_interleaved_discovery(struct hci_dev *hdev);
|
int mgmt_interleaved_discovery(struct hci_dev *hdev);
|
||||||
int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
|
int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
|
||||||
int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
|
int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
|
||||||
|
bool mgmt_valid_hdev(struct hci_dev *hdev);
|
||||||
int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent);
|
int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent);
|
||||||
|
|
||||||
/* HCI info for socket */
|
/* HCI info for socket */
|
||||||
|
|
|
@ -671,20 +671,8 @@ enum {
|
||||||
L2CAP_EV_RECV_FRAME,
|
L2CAP_EV_RECV_FRAME,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void l2cap_chan_hold(struct l2cap_chan *c)
|
void l2cap_chan_hold(struct l2cap_chan *c);
|
||||||
{
|
void l2cap_chan_put(struct l2cap_chan *c);
|
||||||
BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt));
|
|
||||||
|
|
||||||
atomic_inc(&c->refcnt);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void l2cap_chan_put(struct l2cap_chan *c)
|
|
||||||
{
|
|
||||||
BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt));
|
|
||||||
|
|
||||||
if (atomic_dec_and_test(&c->refcnt))
|
|
||||||
kfree(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void l2cap_chan_lock(struct l2cap_chan *chan)
|
static inline void l2cap_chan_lock(struct l2cap_chan *chan)
|
||||||
{
|
{
|
||||||
|
@ -771,7 +759,6 @@ int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
|
||||||
|
|
||||||
struct l2cap_chan *l2cap_chan_create(void);
|
struct l2cap_chan *l2cap_chan_create(void);
|
||||||
void l2cap_chan_close(struct l2cap_chan *chan, int reason);
|
void l2cap_chan_close(struct l2cap_chan *chan, int reason);
|
||||||
void l2cap_chan_destroy(struct l2cap_chan *chan);
|
|
||||||
int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
|
int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
|
||||||
bdaddr_t *dst, u8 dst_type);
|
bdaddr_t *dst, u8 dst_type);
|
||||||
int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
|
int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
|
||||||
|
|
|
@ -108,8 +108,8 @@ struct smp_cmd_security_req {
|
||||||
#define SMP_CONFIRM_FAILED 0x04
|
#define SMP_CONFIRM_FAILED 0x04
|
||||||
#define SMP_PAIRING_NOTSUPP 0x05
|
#define SMP_PAIRING_NOTSUPP 0x05
|
||||||
#define SMP_ENC_KEY_SIZE 0x06
|
#define SMP_ENC_KEY_SIZE 0x06
|
||||||
#define SMP_CMD_NOTSUPP 0x07
|
#define SMP_CMD_NOTSUPP 0x07
|
||||||
#define SMP_UNSPECIFIED 0x08
|
#define SMP_UNSPECIFIED 0x08
|
||||||
#define SMP_REPEATED_ATTEMPTS 0x09
|
#define SMP_REPEATED_ATTEMPTS 0x09
|
||||||
|
|
||||||
#define SMP_MIN_ENC_KEY_SIZE 7
|
#define SMP_MIN_ENC_KEY_SIZE 7
|
||||||
|
@ -123,8 +123,8 @@ struct smp_chan {
|
||||||
struct l2cap_conn *conn;
|
struct l2cap_conn *conn;
|
||||||
u8 preq[7]; /* SMP Pairing Request */
|
u8 preq[7]; /* SMP Pairing Request */
|
||||||
u8 prsp[7]; /* SMP Pairing Response */
|
u8 prsp[7]; /* SMP Pairing Response */
|
||||||
u8 prnd[16]; /* SMP Pairing Random (local) */
|
u8 prnd[16]; /* SMP Pairing Random (local) */
|
||||||
u8 rrnd[16]; /* SMP Pairing Random (remote) */
|
u8 rrnd[16]; /* SMP Pairing Random (remote) */
|
||||||
u8 pcnf[16]; /* SMP Pairing Confirm */
|
u8 pcnf[16]; /* SMP Pairing Confirm */
|
||||||
u8 tk[16]; /* SMP Temporary Key */
|
u8 tk[16]; /* SMP Temporary Key */
|
||||||
u8 enc_key_size;
|
u8 enc_key_size;
|
||||||
|
|
|
@ -316,7 +316,7 @@ send_rsp:
|
||||||
static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
|
static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
|
||||||
struct a2mp_cmd *hdr)
|
struct a2mp_cmd *hdr)
|
||||||
{
|
{
|
||||||
BT_DBG("ident %d code %d", hdr->ident, hdr->code);
|
BT_DBG("ident %d code 0x%2.2x", hdr->ident, hdr->code);
|
||||||
|
|
||||||
skb_pull(skb, le16_to_cpu(hdr->len));
|
skb_pull(skb, le16_to_cpu(hdr->len));
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -325,17 +325,19 @@ static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
|
||||||
/* Handle A2MP signalling */
|
/* Handle A2MP signalling */
|
||||||
static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
|
static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct a2mp_cmd *hdr = (void *) skb->data;
|
struct a2mp_cmd *hdr;
|
||||||
struct amp_mgr *mgr = chan->data;
|
struct amp_mgr *mgr = chan->data;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
amp_mgr_get(mgr);
|
amp_mgr_get(mgr);
|
||||||
|
|
||||||
while (skb->len >= sizeof(*hdr)) {
|
while (skb->len >= sizeof(*hdr)) {
|
||||||
struct a2mp_cmd *hdr = (void *) skb->data;
|
u16 len;
|
||||||
u16 len = le16_to_cpu(hdr->len);
|
|
||||||
|
|
||||||
BT_DBG("code 0x%02x id %d len %d", hdr->code, hdr->ident, len);
|
hdr = (void *) skb->data;
|
||||||
|
len = le16_to_cpu(hdr->len);
|
||||||
|
|
||||||
|
BT_DBG("code 0x%2.2x id %d len %u", hdr->code, hdr->ident, len);
|
||||||
|
|
||||||
skb_pull(skb, sizeof(*hdr));
|
skb_pull(skb, sizeof(*hdr));
|
||||||
|
|
||||||
|
@ -393,7 +395,9 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
struct a2mp_cmd_rej rej;
|
struct a2mp_cmd_rej rej;
|
||||||
|
|
||||||
rej.reason = __constant_cpu_to_le16(0);
|
rej.reason = __constant_cpu_to_le16(0);
|
||||||
|
hdr = (void *) skb->data;
|
||||||
|
|
||||||
BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err);
|
BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err);
|
||||||
|
|
||||||
|
@ -412,7 +416,7 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
|
||||||
|
|
||||||
static void a2mp_chan_close_cb(struct l2cap_chan *chan)
|
static void a2mp_chan_close_cb(struct l2cap_chan *chan)
|
||||||
{
|
{
|
||||||
l2cap_chan_destroy(chan);
|
l2cap_chan_put(chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state)
|
static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state)
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <asm/ioctls.h>
|
#include <asm/ioctls.h>
|
||||||
|
|
||||||
#include <net/bluetooth/bluetooth.h>
|
#include <net/bluetooth/bluetooth.h>
|
||||||
|
#include <linux/proc_fs.h>
|
||||||
|
|
||||||
#define VERSION "2.16"
|
#define VERSION "2.16"
|
||||||
|
|
||||||
|
@ -532,6 +533,146 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(bt_sock_wait_state);
|
EXPORT_SYMBOL(bt_sock_wait_state);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PROC_FS
|
||||||
|
struct bt_seq_state {
|
||||||
|
struct bt_sock_list *l;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *bt_seq_start(struct seq_file *seq, loff_t *pos)
|
||||||
|
__acquires(seq->private->l->lock)
|
||||||
|
{
|
||||||
|
struct bt_seq_state *s = seq->private;
|
||||||
|
struct bt_sock_list *l = s->l;
|
||||||
|
|
||||||
|
read_lock(&l->lock);
|
||||||
|
return seq_hlist_start_head(&l->head, *pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *bt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
|
||||||
|
{
|
||||||
|
struct bt_seq_state *s = seq->private;
|
||||||
|
struct bt_sock_list *l = s->l;
|
||||||
|
|
||||||
|
return seq_hlist_next(v, &l->head, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bt_seq_stop(struct seq_file *seq, void *v)
|
||||||
|
__releases(seq->private->l->lock)
|
||||||
|
{
|
||||||
|
struct bt_seq_state *s = seq->private;
|
||||||
|
struct bt_sock_list *l = s->l;
|
||||||
|
|
||||||
|
read_unlock(&l->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bt_seq_show(struct seq_file *seq, void *v)
|
||||||
|
{
|
||||||
|
struct sock *sk;
|
||||||
|
struct bt_sock *bt;
|
||||||
|
struct bt_seq_state *s = seq->private;
|
||||||
|
struct bt_sock_list *l = s->l;
|
||||||
|
bdaddr_t src_baswapped, dst_baswapped;
|
||||||
|
|
||||||
|
if (v == SEQ_START_TOKEN) {
|
||||||
|
seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent");
|
||||||
|
|
||||||
|
if (l->custom_seq_show) {
|
||||||
|
seq_putc(seq, ' ');
|
||||||
|
l->custom_seq_show(seq, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
seq_putc(seq, '\n');
|
||||||
|
} else {
|
||||||
|
sk = sk_entry(v);
|
||||||
|
bt = bt_sk(sk);
|
||||||
|
baswap(&src_baswapped, &bt->src);
|
||||||
|
baswap(&dst_baswapped, &bt->dst);
|
||||||
|
|
||||||
|
seq_printf(seq, "%pK %-6d %-6u %-6u %-6u %-6lu %pM %pM %-6lu",
|
||||||
|
sk,
|
||||||
|
atomic_read(&sk->sk_refcnt),
|
||||||
|
sk_rmem_alloc_get(sk),
|
||||||
|
sk_wmem_alloc_get(sk),
|
||||||
|
sock_i_uid(sk),
|
||||||
|
sock_i_ino(sk),
|
||||||
|
&src_baswapped,
|
||||||
|
&dst_baswapped,
|
||||||
|
bt->parent? sock_i_ino(bt->parent): 0LU);
|
||||||
|
|
||||||
|
if (l->custom_seq_show) {
|
||||||
|
seq_putc(seq, ' ');
|
||||||
|
l->custom_seq_show(seq, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
seq_putc(seq, '\n');
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct seq_operations bt_seq_ops = {
|
||||||
|
.start = bt_seq_start,
|
||||||
|
.next = bt_seq_next,
|
||||||
|
.stop = bt_seq_stop,
|
||||||
|
.show = bt_seq_show,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int bt_seq_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
struct bt_sock_list *sk_list;
|
||||||
|
struct bt_seq_state *s;
|
||||||
|
|
||||||
|
sk_list = PDE(inode)->data;
|
||||||
|
s = __seq_open_private(file, &bt_seq_ops,
|
||||||
|
sizeof(struct bt_seq_state));
|
||||||
|
if (s == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
s->l = sk_list;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bt_procfs_init(struct module* module, struct net *net, const char *name,
|
||||||
|
struct bt_sock_list* sk_list,
|
||||||
|
int (* seq_show)(struct seq_file *, void *))
|
||||||
|
{
|
||||||
|
struct proc_dir_entry * pde;
|
||||||
|
|
||||||
|
sk_list->custom_seq_show = seq_show;
|
||||||
|
|
||||||
|
sk_list->fops.owner = module;
|
||||||
|
sk_list->fops.open = bt_seq_open;
|
||||||
|
sk_list->fops.read = seq_read;
|
||||||
|
sk_list->fops.llseek = seq_lseek;
|
||||||
|
sk_list->fops.release = seq_release_private;
|
||||||
|
|
||||||
|
pde = proc_net_fops_create(net, name, 0, &sk_list->fops);
|
||||||
|
if (pde == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
pde->data = sk_list;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bt_procfs_cleanup(struct net *net, const char *name)
|
||||||
|
{
|
||||||
|
proc_net_remove(net, name);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int bt_procfs_init(struct module* module, struct net *net, const char *name,
|
||||||
|
struct bt_sock_list* sk_list,
|
||||||
|
int (* seq_show)(struct seq_file *, void *))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bt_procfs_cleanup(struct net *net, const char *name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
EXPORT_SYMBOL(bt_procfs_init);
|
||||||
|
EXPORT_SYMBOL(bt_procfs_cleanup);
|
||||||
|
|
||||||
static struct net_proto_family bt_sock_family_ops = {
|
static struct net_proto_family bt_sock_family_ops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.family = PF_BLUETOOTH,
|
.family = PF_BLUETOOTH,
|
||||||
|
|
|
@ -29,6 +29,10 @@
|
||||||
|
|
||||||
#include "bnep.h"
|
#include "bnep.h"
|
||||||
|
|
||||||
|
static struct bt_sock_list bnep_sk_list = {
|
||||||
|
.lock = __RW_LOCK_UNLOCKED(bnep_sk_list.lock)
|
||||||
|
};
|
||||||
|
|
||||||
static int bnep_sock_release(struct socket *sock)
|
static int bnep_sock_release(struct socket *sock)
|
||||||
{
|
{
|
||||||
struct sock *sk = sock->sk;
|
struct sock *sk = sock->sk;
|
||||||
|
@ -38,6 +42,8 @@ static int bnep_sock_release(struct socket *sock)
|
||||||
if (!sk)
|
if (!sk)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
bt_sock_unlink(&bnep_sk_list, sk);
|
||||||
|
|
||||||
sock_orphan(sk);
|
sock_orphan(sk);
|
||||||
sock_put(sk);
|
sock_put(sk);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -204,6 +210,7 @@ static int bnep_sock_create(struct net *net, struct socket *sock, int protocol,
|
||||||
sk->sk_protocol = protocol;
|
sk->sk_protocol = protocol;
|
||||||
sk->sk_state = BT_OPEN;
|
sk->sk_state = BT_OPEN;
|
||||||
|
|
||||||
|
bt_sock_link(&bnep_sk_list, sk);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,19 +229,30 @@ int __init bnep_sock_init(void)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops);
|
err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops);
|
||||||
if (err < 0)
|
if (err < 0) {
|
||||||
|
BT_ERR("Can't register BNEP socket");
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_procfs_init(THIS_MODULE, &init_net, "bnep", &bnep_sk_list, NULL);
|
||||||
|
if (err < 0) {
|
||||||
|
BT_ERR("Failed to create BNEP proc file");
|
||||||
|
bt_sock_unregister(BTPROTO_BNEP);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
BT_INFO("BNEP socket layer initialized");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
BT_ERR("Can't register BNEP socket");
|
|
||||||
proto_unregister(&bnep_proto);
|
proto_unregister(&bnep_proto);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __exit bnep_sock_cleanup(void)
|
void __exit bnep_sock_cleanup(void)
|
||||||
{
|
{
|
||||||
|
bt_procfs_cleanup(&init_net, "bnep");
|
||||||
if (bt_sock_unregister(BTPROTO_BNEP) < 0)
|
if (bt_sock_unregister(BTPROTO_BNEP) < 0)
|
||||||
BT_ERR("Can't unregister BNEP socket");
|
BT_ERR("Can't unregister BNEP socket");
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,10 @@
|
||||||
|
|
||||||
#include "cmtp.h"
|
#include "cmtp.h"
|
||||||
|
|
||||||
|
static struct bt_sock_list cmtp_sk_list = {
|
||||||
|
.lock = __RW_LOCK_UNLOCKED(cmtp_sk_list.lock)
|
||||||
|
};
|
||||||
|
|
||||||
static int cmtp_sock_release(struct socket *sock)
|
static int cmtp_sock_release(struct socket *sock)
|
||||||
{
|
{
|
||||||
struct sock *sk = sock->sk;
|
struct sock *sk = sock->sk;
|
||||||
|
@ -51,6 +55,8 @@ static int cmtp_sock_release(struct socket *sock)
|
||||||
if (!sk)
|
if (!sk)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
bt_sock_unlink(&cmtp_sk_list, sk);
|
||||||
|
|
||||||
sock_orphan(sk);
|
sock_orphan(sk);
|
||||||
sock_put(sk);
|
sock_put(sk);
|
||||||
|
|
||||||
|
@ -214,6 +220,8 @@ static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol,
|
||||||
sk->sk_protocol = protocol;
|
sk->sk_protocol = protocol;
|
||||||
sk->sk_state = BT_OPEN;
|
sk->sk_state = BT_OPEN;
|
||||||
|
|
||||||
|
bt_sock_link(&cmtp_sk_list, sk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,19 +240,30 @@ int cmtp_init_sockets(void)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = bt_sock_register(BTPROTO_CMTP, &cmtp_sock_family_ops);
|
err = bt_sock_register(BTPROTO_CMTP, &cmtp_sock_family_ops);
|
||||||
if (err < 0)
|
if (err < 0) {
|
||||||
|
BT_ERR("Can't register CMTP socket");
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_procfs_init(THIS_MODULE, &init_net, "cmtp", &cmtp_sk_list, NULL);
|
||||||
|
if (err < 0) {
|
||||||
|
BT_ERR("Failed to create CMTP proc file");
|
||||||
|
bt_sock_unregister(BTPROTO_HIDP);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
BT_INFO("CMTP socket layer initialized");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
BT_ERR("Can't register CMTP socket");
|
|
||||||
proto_unregister(&cmtp_proto);
|
proto_unregister(&cmtp_proto);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmtp_cleanup_sockets(void)
|
void cmtp_cleanup_sockets(void)
|
||||||
{
|
{
|
||||||
|
bt_procfs_cleanup(&init_net, "cmtp");
|
||||||
if (bt_sock_unregister(BTPROTO_CMTP) < 0)
|
if (bt_sock_unregister(BTPROTO_CMTP) < 0)
|
||||||
BT_ERR("Can't unregister CMTP socket");
|
BT_ERR("Can't unregister CMTP socket");
|
||||||
|
|
||||||
|
|
|
@ -696,7 +696,8 @@ int hci_dev_open(__u16 dev)
|
||||||
hci_dev_hold(hdev);
|
hci_dev_hold(hdev);
|
||||||
set_bit(HCI_UP, &hdev->flags);
|
set_bit(HCI_UP, &hdev->flags);
|
||||||
hci_notify(hdev, HCI_DEV_UP);
|
hci_notify(hdev, HCI_DEV_UP);
|
||||||
if (!test_bit(HCI_SETUP, &hdev->dev_flags)) {
|
if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
|
||||||
|
mgmt_valid_hdev(hdev)) {
|
||||||
hci_dev_lock(hdev);
|
hci_dev_lock(hdev);
|
||||||
mgmt_powered(hdev, 1);
|
mgmt_powered(hdev, 1);
|
||||||
hci_dev_unlock(hdev);
|
hci_dev_unlock(hdev);
|
||||||
|
@ -797,7 +798,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
|
||||||
* and no tasks are scheduled. */
|
* and no tasks are scheduled. */
|
||||||
hdev->close(hdev);
|
hdev->close(hdev);
|
||||||
|
|
||||||
if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
|
if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags) &&
|
||||||
|
mgmt_valid_hdev(hdev)) {
|
||||||
hci_dev_lock(hdev);
|
hci_dev_lock(hdev);
|
||||||
mgmt_powered(hdev, 0);
|
mgmt_powered(hdev, 0);
|
||||||
hci_dev_unlock(hdev);
|
hci_dev_unlock(hdev);
|
||||||
|
|
|
@ -513,7 +513,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
|
||||||
if (hdev->features[3] & LMP_RSSI_INQ)
|
if (hdev->features[3] & LMP_RSSI_INQ)
|
||||||
events[4] |= 0x02; /* Inquiry Result with RSSI */
|
events[4] |= 0x02; /* Inquiry Result with RSSI */
|
||||||
|
|
||||||
if (hdev->features[5] & LMP_SNIFF_SUBR)
|
if (lmp_sniffsubr_capable(hdev))
|
||||||
events[5] |= 0x20; /* Sniff Subrating */
|
events[5] |= 0x20; /* Sniff Subrating */
|
||||||
|
|
||||||
if (hdev->features[5] & LMP_PAUSE_ENC)
|
if (hdev->features[5] & LMP_PAUSE_ENC)
|
||||||
|
@ -522,13 +522,13 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
|
||||||
if (hdev->features[6] & LMP_EXT_INQ)
|
if (hdev->features[6] & LMP_EXT_INQ)
|
||||||
events[5] |= 0x40; /* Extended Inquiry Result */
|
events[5] |= 0x40; /* Extended Inquiry Result */
|
||||||
|
|
||||||
if (hdev->features[6] & LMP_NO_FLUSH)
|
if (lmp_no_flush_capable(hdev))
|
||||||
events[7] |= 0x01; /* Enhanced Flush Complete */
|
events[7] |= 0x01; /* Enhanced Flush Complete */
|
||||||
|
|
||||||
if (hdev->features[7] & LMP_LSTO)
|
if (hdev->features[7] & LMP_LSTO)
|
||||||
events[6] |= 0x80; /* Link Supervision Timeout Changed */
|
events[6] |= 0x80; /* Link Supervision Timeout Changed */
|
||||||
|
|
||||||
if (hdev->features[6] & LMP_SIMPLE_PAIR) {
|
if (lmp_ssp_capable(hdev)) {
|
||||||
events[6] |= 0x01; /* IO Capability Request */
|
events[6] |= 0x01; /* IO Capability Request */
|
||||||
events[6] |= 0x02; /* IO Capability Response */
|
events[6] |= 0x02; /* IO Capability Response */
|
||||||
events[6] |= 0x04; /* User Confirmation Request */
|
events[6] |= 0x04; /* User Confirmation Request */
|
||||||
|
@ -541,7 +541,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
|
||||||
* Features Notification */
|
* Features Notification */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hdev->features[4] & LMP_LE)
|
if (lmp_le_capable(hdev))
|
||||||
events[7] |= 0x20; /* LE Meta-Event */
|
events[7] |= 0x20; /* LE Meta-Event */
|
||||||
|
|
||||||
hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
|
hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
|
||||||
|
@ -623,11 +623,11 @@ static void hci_setup_link_policy(struct hci_dev *hdev)
|
||||||
struct hci_cp_write_def_link_policy cp;
|
struct hci_cp_write_def_link_policy cp;
|
||||||
u16 link_policy = 0;
|
u16 link_policy = 0;
|
||||||
|
|
||||||
if (hdev->features[0] & LMP_RSWITCH)
|
if (lmp_rswitch_capable(hdev))
|
||||||
link_policy |= HCI_LP_RSWITCH;
|
link_policy |= HCI_LP_RSWITCH;
|
||||||
if (hdev->features[0] & LMP_HOLD)
|
if (hdev->features[0] & LMP_HOLD)
|
||||||
link_policy |= HCI_LP_HOLD;
|
link_policy |= HCI_LP_HOLD;
|
||||||
if (hdev->features[0] & LMP_SNIFF)
|
if (lmp_sniff_capable(hdev))
|
||||||
link_policy |= HCI_LP_SNIFF;
|
link_policy |= HCI_LP_SNIFF;
|
||||||
if (hdev->features[1] & LMP_PARK)
|
if (hdev->features[1] & LMP_PARK)
|
||||||
link_policy |= HCI_LP_PARK;
|
link_policy |= HCI_LP_PARK;
|
||||||
|
@ -686,7 +686,7 @@ static void hci_cc_read_local_features(struct hci_dev *hdev,
|
||||||
hdev->esco_type |= (ESCO_HV3);
|
hdev->esco_type |= (ESCO_HV3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hdev->features[3] & LMP_ESCO)
|
if (lmp_esco_capable(hdev))
|
||||||
hdev->esco_type |= (ESCO_EV3);
|
hdev->esco_type |= (ESCO_EV3);
|
||||||
|
|
||||||
if (hdev->features[4] & LMP_EV4)
|
if (hdev->features[4] & LMP_EV4)
|
||||||
|
@ -746,7 +746,7 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_bit(HCI_INIT, &hdev->flags) && hdev->features[4] & LMP_LE)
|
if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev))
|
||||||
hci_set_le_support(hdev);
|
hci_set_le_support(hdev);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -1614,43 +1614,30 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
|
||||||
|
|
||||||
static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
|
static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
|
||||||
{
|
{
|
||||||
struct hci_cp_le_create_conn *cp;
|
|
||||||
struct hci_conn *conn;
|
struct hci_conn *conn;
|
||||||
|
|
||||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||||
|
|
||||||
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
|
|
||||||
if (!cp)
|
|
||||||
return;
|
|
||||||
|
|
||||||
hci_dev_lock(hdev);
|
|
||||||
|
|
||||||
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
|
|
||||||
|
|
||||||
BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
|
|
||||||
conn);
|
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
if (conn && conn->state == BT_CONNECT) {
|
hci_dev_lock(hdev);
|
||||||
conn->state = BT_CLOSED;
|
|
||||||
mgmt_connect_failed(hdev, &cp->peer_addr, conn->type,
|
|
||||||
conn->dst_type, status);
|
|
||||||
hci_proto_connect_cfm(conn, status);
|
|
||||||
hci_conn_del(conn);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!conn) {
|
|
||||||
conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
|
|
||||||
if (conn) {
|
|
||||||
conn->dst_type = cp->peer_addr_type;
|
|
||||||
conn->out = true;
|
|
||||||
} else {
|
|
||||||
BT_ERR("No memory for new connection");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hci_dev_unlock(hdev);
|
conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
|
||||||
|
if (!conn) {
|
||||||
|
hci_dev_unlock(hdev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst),
|
||||||
|
conn);
|
||||||
|
|
||||||
|
conn->state = BT_CLOSED;
|
||||||
|
mgmt_connect_failed(hdev, &conn->dst, conn->type,
|
||||||
|
conn->dst_type, status);
|
||||||
|
hci_proto_connect_cfm(conn, status);
|
||||||
|
hci_conn_del(conn);
|
||||||
|
|
||||||
|
hci_dev_unlock(hdev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
|
static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
|
||||||
|
@ -3252,12 +3239,8 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev,
|
||||||
|
|
||||||
BT_DBG("%s", hdev->name);
|
BT_DBG("%s", hdev->name);
|
||||||
|
|
||||||
hci_dev_lock(hdev);
|
|
||||||
|
|
||||||
if (test_bit(HCI_MGMT, &hdev->dev_flags))
|
if (test_bit(HCI_MGMT, &hdev->dev_flags))
|
||||||
mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
|
mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
|
||||||
|
|
||||||
hci_dev_unlock(hdev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
|
static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
|
||||||
|
@ -3350,11 +3333,23 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||||
|
|
||||||
hci_dev_lock(hdev);
|
hci_dev_lock(hdev);
|
||||||
|
|
||||||
if (ev->status) {
|
conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
|
||||||
conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
|
if (!conn) {
|
||||||
if (!conn)
|
conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
|
||||||
|
if (!conn) {
|
||||||
|
BT_ERR("No memory for new connection");
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn->dst_type = ev->bdaddr_type;
|
||||||
|
|
||||||
|
if (ev->role == LE_CONN_ROLE_MASTER) {
|
||||||
|
conn->out = true;
|
||||||
|
conn->link_mode |= HCI_LM_MASTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev->status) {
|
||||||
mgmt_connect_failed(hdev, &conn->dst, conn->type,
|
mgmt_connect_failed(hdev, &conn->dst, conn->type,
|
||||||
conn->dst_type, ev->status);
|
conn->dst_type, ev->status);
|
||||||
hci_proto_connect_cfm(conn, ev->status);
|
hci_proto_connect_cfm(conn, ev->status);
|
||||||
|
@ -3363,18 +3358,6 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
|
|
||||||
if (!conn) {
|
|
||||||
conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
|
|
||||||
if (!conn) {
|
|
||||||
BT_ERR("No memory for new connection");
|
|
||||||
hci_dev_unlock(hdev);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
conn->dst_type = ev->bdaddr_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
|
if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
|
||||||
mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
|
mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
|
||||||
conn->dst_type, 0, NULL, 0, NULL);
|
conn->dst_type, 0, NULL, 0, NULL);
|
||||||
|
|
|
@ -1100,21 +1100,30 @@ int __init hci_sock_init(void)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);
|
err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);
|
||||||
if (err < 0)
|
if (err < 0) {
|
||||||
|
BT_ERR("HCI socket registration failed");
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_procfs_init(THIS_MODULE, &init_net, "hci", &hci_sk_list, NULL);
|
||||||
|
if (err < 0) {
|
||||||
|
BT_ERR("Failed to create HCI proc file");
|
||||||
|
bt_sock_unregister(BTPROTO_HCI);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
BT_INFO("HCI socket layer initialized");
|
BT_INFO("HCI socket layer initialized");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
BT_ERR("HCI socket registration failed");
|
|
||||||
proto_unregister(&hci_sk_proto);
|
proto_unregister(&hci_sk_proto);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hci_sock_cleanup(void)
|
void hci_sock_cleanup(void)
|
||||||
{
|
{
|
||||||
|
bt_procfs_cleanup(&init_net, "hci");
|
||||||
if (bt_sock_unregister(BTPROTO_HCI) < 0)
|
if (bt_sock_unregister(BTPROTO_HCI) < 0)
|
||||||
BT_ERR("HCI socket unregistration failed");
|
BT_ERR("HCI socket unregistration failed");
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,10 @@
|
||||||
|
|
||||||
#include "hidp.h"
|
#include "hidp.h"
|
||||||
|
|
||||||
|
static struct bt_sock_list hidp_sk_list = {
|
||||||
|
.lock = __RW_LOCK_UNLOCKED(hidp_sk_list.lock)
|
||||||
|
};
|
||||||
|
|
||||||
static int hidp_sock_release(struct socket *sock)
|
static int hidp_sock_release(struct socket *sock)
|
||||||
{
|
{
|
||||||
struct sock *sk = sock->sk;
|
struct sock *sk = sock->sk;
|
||||||
|
@ -34,6 +38,8 @@ static int hidp_sock_release(struct socket *sock)
|
||||||
if (!sk)
|
if (!sk)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
bt_sock_unlink(&hidp_sk_list, sk);
|
||||||
|
|
||||||
sock_orphan(sk);
|
sock_orphan(sk);
|
||||||
sock_put(sk);
|
sock_put(sk);
|
||||||
|
|
||||||
|
@ -253,6 +259,8 @@ static int hidp_sock_create(struct net *net, struct socket *sock, int protocol,
|
||||||
sk->sk_protocol = protocol;
|
sk->sk_protocol = protocol;
|
||||||
sk->sk_state = BT_OPEN;
|
sk->sk_state = BT_OPEN;
|
||||||
|
|
||||||
|
bt_sock_link(&hidp_sk_list, sk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,8 +279,19 @@ int __init hidp_init_sockets(void)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops);
|
err = bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops);
|
||||||
if (err < 0)
|
if (err < 0) {
|
||||||
|
BT_ERR("Can't register HIDP socket");
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_procfs_init(THIS_MODULE, &init_net, "hidp", &hidp_sk_list, NULL);
|
||||||
|
if (err < 0) {
|
||||||
|
BT_ERR("Failed to create HIDP proc file");
|
||||||
|
bt_sock_unregister(BTPROTO_HIDP);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
BT_INFO("HIDP socket layer initialized");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -284,6 +303,7 @@ error:
|
||||||
|
|
||||||
void __exit hidp_cleanup_sockets(void)
|
void __exit hidp_cleanup_sockets(void)
|
||||||
{
|
{
|
||||||
|
bt_procfs_cleanup(&init_net, "hidp");
|
||||||
if (bt_sock_unregister(BTPROTO_HIDP) < 0)
|
if (bt_sock_unregister(BTPROTO_HIDP) < 0)
|
||||||
BT_ERR("Can't unregister HIDP socket");
|
BT_ERR("Can't unregister HIDP socket");
|
||||||
|
|
||||||
|
|
|
@ -416,13 +416,30 @@ struct l2cap_chan *l2cap_chan_create(void)
|
||||||
return chan;
|
return chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
void l2cap_chan_destroy(struct l2cap_chan *chan)
|
static void l2cap_chan_destroy(struct l2cap_chan *chan)
|
||||||
{
|
{
|
||||||
|
BT_DBG("chan %p", chan);
|
||||||
|
|
||||||
write_lock(&chan_list_lock);
|
write_lock(&chan_list_lock);
|
||||||
list_del(&chan->global_l);
|
list_del(&chan->global_l);
|
||||||
write_unlock(&chan_list_lock);
|
write_unlock(&chan_list_lock);
|
||||||
|
|
||||||
l2cap_chan_put(chan);
|
kfree(chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
void l2cap_chan_hold(struct l2cap_chan *c)
|
||||||
|
{
|
||||||
|
BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt));
|
||||||
|
|
||||||
|
atomic_inc(&c->refcnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void l2cap_chan_put(struct l2cap_chan *c)
|
||||||
|
{
|
||||||
|
BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt));
|
||||||
|
|
||||||
|
if (atomic_dec_and_test(&c->refcnt))
|
||||||
|
l2cap_chan_destroy(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void l2cap_chan_set_defaults(struct l2cap_chan *chan)
|
void l2cap_chan_set_defaults(struct l2cap_chan *chan)
|
||||||
|
@ -5329,7 +5346,7 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
|
||||||
return exact ? lm1 : lm2;
|
return exact ? lm1 : lm2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
|
void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
|
||||||
{
|
{
|
||||||
struct l2cap_conn *conn;
|
struct l2cap_conn *conn;
|
||||||
|
|
||||||
|
@ -5342,7 +5359,6 @@ int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
|
||||||
} else
|
} else
|
||||||
l2cap_conn_del(hcon, bt_to_errno(status));
|
l2cap_conn_del(hcon, bt_to_errno(status));
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int l2cap_disconn_ind(struct hci_conn *hcon)
|
int l2cap_disconn_ind(struct hci_conn *hcon)
|
||||||
|
@ -5356,12 +5372,11 @@ int l2cap_disconn_ind(struct hci_conn *hcon)
|
||||||
return conn->disc_reason;
|
return conn->disc_reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
|
void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
|
||||||
{
|
{
|
||||||
BT_DBG("hcon %p reason %d", hcon, reason);
|
BT_DBG("hcon %p reason %d", hcon, reason);
|
||||||
|
|
||||||
l2cap_conn_del(hcon, bt_to_errno(reason));
|
l2cap_conn_del(hcon, bt_to_errno(reason));
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
|
static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
|
||||||
|
@ -5404,6 +5419,11 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
|
||||||
BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
|
BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
|
||||||
state_to_string(chan->state));
|
state_to_string(chan->state));
|
||||||
|
|
||||||
|
if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) {
|
||||||
|
l2cap_chan_unlock(chan);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (chan->scid == L2CAP_CID_LE_DATA) {
|
if (chan->scid == L2CAP_CID_LE_DATA) {
|
||||||
if (!status && encrypt) {
|
if (!status && encrypt) {
|
||||||
chan->sec_level = hcon->sec_level;
|
chan->sec_level = hcon->sec_level;
|
||||||
|
|
|
@ -34,6 +34,10 @@
|
||||||
#include <net/bluetooth/l2cap.h>
|
#include <net/bluetooth/l2cap.h>
|
||||||
#include <net/bluetooth/smp.h>
|
#include <net/bluetooth/smp.h>
|
||||||
|
|
||||||
|
static struct bt_sock_list l2cap_sk_list = {
|
||||||
|
.lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
|
||||||
|
};
|
||||||
|
|
||||||
static const struct proto_ops l2cap_sock_ops;
|
static const struct proto_ops l2cap_sock_ops;
|
||||||
static void l2cap_sock_init(struct sock *sk, struct sock *parent);
|
static void l2cap_sock_init(struct sock *sk, struct sock *parent);
|
||||||
static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio);
|
static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio);
|
||||||
|
@ -823,7 +827,7 @@ static void l2cap_sock_kill(struct sock *sk)
|
||||||
|
|
||||||
/* Kill poor orphan */
|
/* Kill poor orphan */
|
||||||
|
|
||||||
l2cap_chan_destroy(l2cap_pi(sk)->chan);
|
l2cap_chan_put(l2cap_pi(sk)->chan);
|
||||||
sock_set_flag(sk, SOCK_DEAD);
|
sock_set_flag(sk, SOCK_DEAD);
|
||||||
sock_put(sk);
|
sock_put(sk);
|
||||||
}
|
}
|
||||||
|
@ -886,6 +890,8 @@ static int l2cap_sock_release(struct socket *sock)
|
||||||
if (!sk)
|
if (!sk)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
bt_sock_unlink(&l2cap_sk_list, sk);
|
||||||
|
|
||||||
err = l2cap_sock_shutdown(sock, 2);
|
err = l2cap_sock_shutdown(sock, 2);
|
||||||
|
|
||||||
sock_orphan(sk);
|
sock_orphan(sk);
|
||||||
|
@ -1210,6 +1216,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
l2cap_sock_init(sk, NULL);
|
l2cap_sock_init(sk, NULL);
|
||||||
|
bt_sock_link(&l2cap_sk_list, sk);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1248,21 +1255,30 @@ int __init l2cap_init_sockets(void)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
|
err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
|
||||||
if (err < 0)
|
if (err < 0) {
|
||||||
|
BT_ERR("L2CAP socket registration failed");
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list, NULL);
|
||||||
|
if (err < 0) {
|
||||||
|
BT_ERR("Failed to create L2CAP proc file");
|
||||||
|
bt_sock_unregister(BTPROTO_L2CAP);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
BT_INFO("L2CAP socket layer initialized");
|
BT_INFO("L2CAP socket layer initialized");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
BT_ERR("L2CAP socket registration failed");
|
|
||||||
proto_unregister(&l2cap_proto);
|
proto_unregister(&l2cap_proto);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void l2cap_cleanup_sockets(void)
|
void l2cap_cleanup_sockets(void)
|
||||||
{
|
{
|
||||||
|
bt_procfs_cleanup(&init_net, "l2cap");
|
||||||
if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
|
if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
|
||||||
BT_ERR("L2CAP socket unregistration failed");
|
BT_ERR("L2CAP socket unregistration failed");
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,11 @@ static u8 mgmt_status_table[] = {
|
||||||
MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
|
MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool mgmt_valid_hdev(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
return hdev->dev_type == HCI_BREDR;
|
||||||
|
}
|
||||||
|
|
||||||
static u8 mgmt_status(u8 hci_status)
|
static u8 mgmt_status(u8 hci_status)
|
||||||
{
|
{
|
||||||
if (hci_status < ARRAY_SIZE(mgmt_status_table))
|
if (hci_status < ARRAY_SIZE(mgmt_status_table))
|
||||||
|
@ -317,7 +322,6 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
|
||||||
u16 data_len)
|
u16 data_len)
|
||||||
{
|
{
|
||||||
struct mgmt_rp_read_index_list *rp;
|
struct mgmt_rp_read_index_list *rp;
|
||||||
struct list_head *p;
|
|
||||||
struct hci_dev *d;
|
struct hci_dev *d;
|
||||||
size_t rp_len;
|
size_t rp_len;
|
||||||
u16 count;
|
u16 count;
|
||||||
|
@ -328,7 +332,10 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
|
||||||
read_lock(&hci_dev_list_lock);
|
read_lock(&hci_dev_list_lock);
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
list_for_each(p, &hci_dev_list) {
|
list_for_each_entry(d, &hci_dev_list, list) {
|
||||||
|
if (!mgmt_valid_hdev(d))
|
||||||
|
continue;
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,6 +353,9 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
|
||||||
if (test_bit(HCI_SETUP, &d->dev_flags))
|
if (test_bit(HCI_SETUP, &d->dev_flags))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!mgmt_valid_hdev(d))
|
||||||
|
continue;
|
||||||
|
|
||||||
rp->index[i++] = cpu_to_le16(d->id);
|
rp->index[i++] = cpu_to_le16(d->id);
|
||||||
BT_DBG("Added hci%u", d->id);
|
BT_DBG("Added hci%u", d->id);
|
||||||
}
|
}
|
||||||
|
@ -370,10 +380,10 @@ static u32 get_supported_settings(struct hci_dev *hdev)
|
||||||
settings |= MGMT_SETTING_DISCOVERABLE;
|
settings |= MGMT_SETTING_DISCOVERABLE;
|
||||||
settings |= MGMT_SETTING_PAIRABLE;
|
settings |= MGMT_SETTING_PAIRABLE;
|
||||||
|
|
||||||
if (hdev->features[6] & LMP_SIMPLE_PAIR)
|
if (lmp_ssp_capable(hdev))
|
||||||
settings |= MGMT_SETTING_SSP;
|
settings |= MGMT_SETTING_SSP;
|
||||||
|
|
||||||
if (!(hdev->features[4] & LMP_NO_BREDR)) {
|
if (lmp_bredr_capable(hdev)) {
|
||||||
settings |= MGMT_SETTING_BREDR;
|
settings |= MGMT_SETTING_BREDR;
|
||||||
settings |= MGMT_SETTING_LINK_SECURITY;
|
settings |= MGMT_SETTING_LINK_SECURITY;
|
||||||
}
|
}
|
||||||
|
@ -381,7 +391,7 @@ static u32 get_supported_settings(struct hci_dev *hdev)
|
||||||
if (enable_hs)
|
if (enable_hs)
|
||||||
settings |= MGMT_SETTING_HS;
|
settings |= MGMT_SETTING_HS;
|
||||||
|
|
||||||
if (hdev->features[4] & LMP_LE)
|
if (lmp_le_capable(hdev))
|
||||||
settings |= MGMT_SETTING_LE;
|
settings |= MGMT_SETTING_LE;
|
||||||
|
|
||||||
return settings;
|
return settings;
|
||||||
|
@ -403,7 +413,7 @@ static u32 get_current_settings(struct hci_dev *hdev)
|
||||||
if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
|
if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
|
||||||
settings |= MGMT_SETTING_PAIRABLE;
|
settings |= MGMT_SETTING_PAIRABLE;
|
||||||
|
|
||||||
if (!(hdev->features[4] & LMP_NO_BREDR))
|
if (lmp_bredr_capable(hdev))
|
||||||
settings |= MGMT_SETTING_BREDR;
|
settings |= MGMT_SETTING_BREDR;
|
||||||
|
|
||||||
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
|
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
|
||||||
|
@ -1111,7 +1121,7 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
|
||||||
|
|
||||||
hci_dev_lock(hdev);
|
hci_dev_lock(hdev);
|
||||||
|
|
||||||
if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
|
if (!lmp_ssp_capable(hdev)) {
|
||||||
err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
|
err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
|
||||||
MGMT_STATUS_NOT_SUPPORTED);
|
MGMT_STATUS_NOT_SUPPORTED);
|
||||||
goto failed;
|
goto failed;
|
||||||
|
@ -1195,7 +1205,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
|
||||||
|
|
||||||
hci_dev_lock(hdev);
|
hci_dev_lock(hdev);
|
||||||
|
|
||||||
if (!(hdev->features[4] & LMP_LE)) {
|
if (!lmp_le_capable(hdev)) {
|
||||||
err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
|
err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
|
||||||
MGMT_STATUS_NOT_SUPPORTED);
|
MGMT_STATUS_NOT_SUPPORTED);
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
@ -2191,7 +2201,7 @@ static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
|
if (!lmp_ssp_capable(hdev)) {
|
||||||
err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
|
err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
|
||||||
MGMT_STATUS_NOT_SUPPORTED);
|
MGMT_STATUS_NOT_SUPPORTED);
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
@ -2820,6 +2830,9 @@ static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
|
||||||
|
|
||||||
int mgmt_index_added(struct hci_dev *hdev)
|
int mgmt_index_added(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
|
if (!mgmt_valid_hdev(hdev))
|
||||||
|
return -ENOTSUPP;
|
||||||
|
|
||||||
return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
|
return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2827,6 +2840,9 @@ int mgmt_index_removed(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
u8 status = MGMT_STATUS_INVALID_INDEX;
|
u8 status = MGMT_STATUS_INVALID_INDEX;
|
||||||
|
|
||||||
|
if (!mgmt_valid_hdev(hdev))
|
||||||
|
return -ENOTSUPP;
|
||||||
|
|
||||||
mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
|
mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
|
||||||
|
|
||||||
return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
|
return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
|
||||||
|
|
|
@ -1033,8 +1033,17 @@ int __init rfcomm_init_sockets(void)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = bt_sock_register(BTPROTO_RFCOMM, &rfcomm_sock_family_ops);
|
err = bt_sock_register(BTPROTO_RFCOMM, &rfcomm_sock_family_ops);
|
||||||
if (err < 0)
|
if (err < 0) {
|
||||||
|
BT_ERR("RFCOMM socket layer registration failed");
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_procfs_init(THIS_MODULE, &init_net, "rfcomm", &rfcomm_sk_list, NULL);
|
||||||
|
if (err < 0) {
|
||||||
|
BT_ERR("Failed to create RFCOMM proc file");
|
||||||
|
bt_sock_unregister(BTPROTO_RFCOMM);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
if (bt_debugfs) {
|
if (bt_debugfs) {
|
||||||
rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444,
|
rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444,
|
||||||
|
@ -1048,13 +1057,14 @@ int __init rfcomm_init_sockets(void)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
BT_ERR("RFCOMM socket layer registration failed");
|
|
||||||
proto_unregister(&rfcomm_proto);
|
proto_unregister(&rfcomm_proto);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __exit rfcomm_cleanup_sockets(void)
|
void __exit rfcomm_cleanup_sockets(void)
|
||||||
{
|
{
|
||||||
|
bt_procfs_cleanup(&init_net, "rfcomm");
|
||||||
|
|
||||||
debugfs_remove(rfcomm_sock_debugfs);
|
debugfs_remove(rfcomm_sock_debugfs);
|
||||||
|
|
||||||
if (bt_sock_unregister(BTPROTO_RFCOMM) < 0)
|
if (bt_sock_unregister(BTPROTO_RFCOMM) < 0)
|
||||||
|
|
|
@ -913,7 +913,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
|
||||||
return lm;
|
return lm;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
|
void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
|
||||||
{
|
{
|
||||||
BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
|
BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
|
||||||
if (!status) {
|
if (!status) {
|
||||||
|
@ -924,16 +924,13 @@ int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
|
||||||
sco_conn_ready(conn);
|
sco_conn_ready(conn);
|
||||||
} else
|
} else
|
||||||
sco_conn_del(hcon, bt_to_errno(status));
|
sco_conn_del(hcon, bt_to_errno(status));
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
|
void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
|
||||||
{
|
{
|
||||||
BT_DBG("hcon %p reason %d", hcon, reason);
|
BT_DBG("hcon %p reason %d", hcon, reason);
|
||||||
|
|
||||||
sco_conn_del(hcon, bt_to_errno(reason));
|
sco_conn_del(hcon, bt_to_errno(reason));
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
|
int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
|
||||||
|
@ -1026,6 +1023,13 @@ int __init sco_init(void)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = bt_procfs_init(THIS_MODULE, &init_net, "sco", &sco_sk_list, NULL);
|
||||||
|
if (err < 0) {
|
||||||
|
BT_ERR("Failed to create SCO proc file");
|
||||||
|
bt_sock_unregister(BTPROTO_SCO);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
if (bt_debugfs) {
|
if (bt_debugfs) {
|
||||||
sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs,
|
sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs,
|
||||||
NULL, &sco_debugfs_fops);
|
NULL, &sco_debugfs_fops);
|
||||||
|
@ -1044,6 +1048,8 @@ error:
|
||||||
|
|
||||||
void __exit sco_exit(void)
|
void __exit sco_exit(void)
|
||||||
{
|
{
|
||||||
|
bt_procfs_cleanup(&init_net, "sco");
|
||||||
|
|
||||||
debugfs_remove(sco_debugfs);
|
debugfs_remove(sco_debugfs);
|
||||||
|
|
||||||
if (bt_sock_unregister(BTPROTO_SCO) < 0)
|
if (bt_sock_unregister(BTPROTO_SCO) < 0)
|
||||||
|
|
Loading…
Reference in New Issue