Commit 4a934eca authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'for-net-next-2022-07-22' of...

Merge tag 'for-net-next-2022-07-22' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next

Luiz Augusto von Dentz says:

====================
bluetooth-next pull request for net-next:

 - Add support for IM Networks PID 0x3568
 - Add support for BCM4349B1
 - Add support for CYW55572
 - Add support for MT7922 VID/PID 0489/e0e2
 - Add support for Realtek RTL8852C
 - Initial support for Isochronous Channels/ISO sockets
 - Remove HCI_QUIRK_BROKEN_ERR_DATA_REPORTING quirk

* tag 'for-net-next-2022-07-22' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next: (58 commits)
  Bluetooth: btusb: Detect if an ACL packet is in fact an ISO packet
  Bluetooth: btusb: Add support for ISO packets
  Bluetooth: ISO: Add broadcast support
  Bluetooth: Add initial implementation of BIS connections
  Bluetooth: Add BTPROTO_ISO socket type
  Bluetooth: Add initial implementation of CIS connections
  Bluetooth: hci_core: Introduce hci_recv_event_data
  Bluetooth: Convert delayed discov_off to hci_sync
  Bluetooth: Remove update_scan hci_request dependancy
  Bluetooth: Remove dead code from hci_request.c
  Bluetooth: btrtl: Fix typo in comment
  Bluetooth: MGMT: Fix holding hci_conn reference while command is queued
  Bluetooth: mgmt: Fix using hci_conn_abort
  Bluetooth: Use bt_status to convert from errno
  Bluetooth: Add bt_status
  Bluetooth: hci_sync: Split hci_dev_open_sync
  Bluetooth: hci_sync: Refactor remove Adv Monitor
  Bluetooth: hci_sync: Refactor add Adv Monitor
  Bluetooth: hci_sync: Remove HCI_QUIRK_BROKEN_ERR_DATA_REPORTING
  Bluetooth: btusb: Remove HCI_QUIRK_BROKEN_ERR_DATA_REPORTING for fake CSR
  ...
====================

Link: https://lore.kernel.org/r/20220723002232.964796-1-luiz.dentz@gmail.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents b3fce974 14202eff
...@@ -23,6 +23,8 @@ properties: ...@@ -23,6 +23,8 @@ properties:
- brcm,bcm4345c5 - brcm,bcm4345c5
- brcm,bcm43540-bt - brcm,bcm43540-bt
- brcm,bcm4335a0 - brcm,bcm4335a0
- brcm,bcm4349-bt
- infineon,cyw55572-bt
shutdown-gpios: shutdown-gpios:
maxItems: 1 maxItems: 1
...@@ -92,6 +94,13 @@ properties: ...@@ -92,6 +94,13 @@ properties:
pcm-sync-mode: slave, master pcm-sync-mode: slave, master
pcm-clock-mode: slave, master pcm-clock-mode: slave, master
brcm,requires-autobaud-mode:
type: boolean
description:
Set this property if autobaud mode is required. Autobaud mode is required
if the device's initial baud rate in normal mode is not supported by the
host or if the device requires autobaud mode startup before loading FW.
interrupts: interrupts:
items: items:
- description: Handle to the line HOST_WAKE used to wake - description: Handle to the line HOST_WAKE used to wake
...@@ -108,6 +117,22 @@ properties: ...@@ -108,6 +117,22 @@ properties:
required: required:
- compatible - compatible
dependencies:
brcm,requires-autobaud-mode: [ 'shutdown-gpios' ]
if:
not:
properties:
compatible:
contains:
enum:
- brcm,bcm20702a1
- brcm,bcm4329-bt
- brcm,bcm4330-bt
then:
properties:
reset-gpios: false
additionalProperties: false additionalProperties: false
examples: examples:
......
...@@ -403,6 +403,13 @@ static int btbcm_read_info(struct hci_dev *hdev) ...@@ -403,6 +403,13 @@ static int btbcm_read_info(struct hci_dev *hdev)
bt_dev_info(hdev, "BCM: chip id %u", skb->data[1]); bt_dev_info(hdev, "BCM: chip id %u", skb->data[1]);
kfree_skb(skb); kfree_skb(skb);
return 0;
}
static int btbcm_print_controller_features(struct hci_dev *hdev)
{
struct sk_buff *skb;
/* Read Controller Features */ /* Read Controller Features */
skb = btbcm_read_controller_features(hdev); skb = btbcm_read_controller_features(hdev);
if (IS_ERR(skb)) if (IS_ERR(skb))
...@@ -454,6 +461,8 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = { ...@@ -454,6 +461,8 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = {
{ 0x6606, "BCM4345C5" }, /* 003.006.006 */ { 0x6606, "BCM4345C5" }, /* 003.006.006 */
{ 0x230f, "BCM4356A2" }, /* 001.003.015 */ { 0x230f, "BCM4356A2" }, /* 001.003.015 */
{ 0x220e, "BCM20702A1" }, /* 001.002.014 */ { 0x220e, "BCM20702A1" }, /* 001.002.014 */
{ 0x420d, "BCM4349B1" }, /* 002.002.013 */
{ 0x420e, "BCM4349B1" }, /* 002.002.014 */
{ 0x4217, "BCM4329B1" }, /* 002.002.023 */ { 0x4217, "BCM4329B1" }, /* 002.002.023 */
{ 0x6106, "BCM4359C0" }, /* 003.001.006 */ { 0x6106, "BCM4359C0" }, /* 003.001.006 */
{ 0x4106, "BCM4335A0" }, /* 002.001.006 */ { 0x4106, "BCM4335A0" }, /* 002.001.006 */
...@@ -514,7 +523,7 @@ static const char *btbcm_get_board_name(struct device *dev) ...@@ -514,7 +523,7 @@ static const char *btbcm_get_board_name(struct device *dev)
#endif #endif
} }
int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done) int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode)
{ {
u16 subver, rev, pid, vid; u16 subver, rev, pid, vid;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -551,9 +560,16 @@ int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done) ...@@ -551,9 +560,16 @@ int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done)
if (err) if (err)
return err; return err;
} }
err = btbcm_print_local_name(hdev);
if (err) if (!use_autobaud_mode) {
return err; err = btbcm_print_controller_features(hdev);
if (err)
return err;
err = btbcm_print_local_name(hdev);
if (err)
return err;
}
bcm_subver_table = (hdev->bus == HCI_USB) ? bcm_usb_subver_table : bcm_subver_table = (hdev->bus == HCI_USB) ? bcm_usb_subver_table :
bcm_uart_subver_table; bcm_uart_subver_table;
...@@ -636,13 +652,13 @@ int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done) ...@@ -636,13 +652,13 @@ int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done)
} }
EXPORT_SYMBOL_GPL(btbcm_initialize); EXPORT_SYMBOL_GPL(btbcm_initialize);
int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done) int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode)
{ {
int err; int err;
/* Re-initialize if necessary */ /* Re-initialize if necessary */
if (*fw_load_done) { if (*fw_load_done) {
err = btbcm_initialize(hdev, fw_load_done); err = btbcm_initialize(hdev, fw_load_done, use_autobaud_mode);
if (err) if (err)
return err; return err;
} }
...@@ -658,15 +674,16 @@ EXPORT_SYMBOL_GPL(btbcm_finalize); ...@@ -658,15 +674,16 @@ EXPORT_SYMBOL_GPL(btbcm_finalize);
int btbcm_setup_patchram(struct hci_dev *hdev) int btbcm_setup_patchram(struct hci_dev *hdev)
{ {
bool fw_load_done = false; bool fw_load_done = false;
bool use_autobaud_mode = false;
int err; int err;
/* Initialize */ /* Initialize */
err = btbcm_initialize(hdev, &fw_load_done); err = btbcm_initialize(hdev, &fw_load_done, use_autobaud_mode);
if (err) if (err)
return err; return err;
/* Re-initialize after loading Patch */ /* Re-initialize after loading Patch */
return btbcm_finalize(hdev, &fw_load_done); return btbcm_finalize(hdev, &fw_load_done, use_autobaud_mode);
} }
EXPORT_SYMBOL_GPL(btbcm_setup_patchram); EXPORT_SYMBOL_GPL(btbcm_setup_patchram);
......
...@@ -62,8 +62,8 @@ int btbcm_write_pcm_int_params(struct hci_dev *hdev, ...@@ -62,8 +62,8 @@ int btbcm_write_pcm_int_params(struct hci_dev *hdev,
int btbcm_setup_patchram(struct hci_dev *hdev); int btbcm_setup_patchram(struct hci_dev *hdev);
int btbcm_setup_apple(struct hci_dev *hdev); int btbcm_setup_apple(struct hci_dev *hdev);
int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done); int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode);
int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done); int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode);
#else #else
...@@ -104,12 +104,12 @@ static inline int btbcm_setup_apple(struct hci_dev *hdev) ...@@ -104,12 +104,12 @@ static inline int btbcm_setup_apple(struct hci_dev *hdev)
return 0; return 0;
} }
static inline int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done) static inline int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode)
{ {
return 0; return 0;
} }
static inline int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done) static inline int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode)
{ {
return 0; return 0;
} }
......
...@@ -1282,6 +1282,13 @@ static void btmtksdio_cmd_timeout(struct hci_dev *hdev) ...@@ -1282,6 +1282,13 @@ static void btmtksdio_cmd_timeout(struct hci_dev *hdev)
hci_reset_dev(hdev); hci_reset_dev(hdev);
} }
static bool btmtksdio_sdio_inband_wakeup(struct hci_dev *hdev)
{
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
return device_may_wakeup(bdev->dev);
}
static bool btmtksdio_sdio_wakeup(struct hci_dev *hdev) static bool btmtksdio_sdio_wakeup(struct hci_dev *hdev)
{ {
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev); struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
...@@ -1349,6 +1356,14 @@ static int btmtksdio_probe(struct sdio_func *func, ...@@ -1349,6 +1356,14 @@ static int btmtksdio_probe(struct sdio_func *func,
hdev->shutdown = btmtksdio_shutdown; hdev->shutdown = btmtksdio_shutdown;
hdev->send = btmtksdio_send_frame; hdev->send = btmtksdio_send_frame;
hdev->wakeup = btmtksdio_sdio_wakeup; hdev->wakeup = btmtksdio_sdio_wakeup;
/*
* If SDIO controller supports wake on Bluetooth, sending a wakeon
* command is not necessary.
*/
if (device_can_wakeup(func->card->host->parent))
hdev->wakeup = btmtksdio_sdio_inband_wakeup;
else
hdev->wakeup = btmtksdio_sdio_wakeup;
hdev->set_bdaddr = btmtk_set_bdaddr; hdev->set_bdaddr = btmtk_set_bdaddr;
SET_HCIDEV_DEV(hdev, &func->dev); SET_HCIDEV_DEV(hdev, &func->dev);
......
...@@ -330,7 +330,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev, ...@@ -330,7 +330,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev,
/* Loop from the end of the firmware parsing instructions, until /* Loop from the end of the firmware parsing instructions, until
* we find an instruction that identifies the "project ID" for the * we find an instruction that identifies the "project ID" for the
* hardware supported by this firwmare file. * hardware supported by this firwmare file.
* Once we have that, we double-check that that project_id is suitable * Once we have that, we double-check that project_id is suitable
* for the hardware we are working with. * for the hardware we are working with.
*/ */
while (fwptr >= btrtl_dev->fw_data + (sizeof(*epatch_info) + 3)) { while (fwptr >= btrtl_dev->fw_data + (sizeof(*epatch_info) + 3)) {
......
...@@ -427,6 +427,18 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -427,6 +427,18 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x04ca, 0x4006), .driver_info = BTUSB_REALTEK | { USB_DEVICE(0x04ca, 0x4006), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH }, BTUSB_WIDEBAND_SPEECH },
/* Realtek 8852CE Bluetooth devices */
{ USB_DEVICE(0x04ca, 0x4007), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x04c5, 0x1675), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x0cb8, 0xc558), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3587), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x13d3, 0x3586), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
/* Realtek Bluetooth devices */ /* Realtek Bluetooth devices */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01), { USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01),
.driver_info = BTUSB_REALTEK }, .driver_info = BTUSB_REALTEK },
...@@ -477,6 +489,12 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -477,6 +489,12 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0489, 0xe0d9), .driver_info = BTUSB_MEDIATEK | { USB_DEVICE(0x0489, 0xe0d9), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH | BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES }, BTUSB_VALID_LE_STATES },
{ USB_DEVICE(0x13d3, 0x3568), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
{ USB_DEVICE(0x0489, 0xe0e2), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
/* Additional Realtek 8723AE Bluetooth devices */ /* Additional Realtek 8723AE Bluetooth devices */
{ USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
...@@ -893,11 +911,21 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count) ...@@ -893,11 +911,21 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
hci_skb_expect(skb) -= len; hci_skb_expect(skb) -= len;
if (skb->len == HCI_ACL_HDR_SIZE) { if (skb->len == HCI_ACL_HDR_SIZE) {
__u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle);
__le16 dlen = hci_acl_hdr(skb)->dlen; __le16 dlen = hci_acl_hdr(skb)->dlen;
__u8 type;
/* Complete ACL header */ /* Complete ACL header */
hci_skb_expect(skb) = __le16_to_cpu(dlen); hci_skb_expect(skb) = __le16_to_cpu(dlen);
/* Detect if ISO packet has been sent over bulk */
if (hci_conn_num(data->hdev, ISO_LINK)) {
type = hci_conn_lookup_type(data->hdev,
hci_handle(handle));
if (type == ISO_LINK)
hci_skb_pkt_type(skb) = HCI_ISODATA_PKT;
}
if (skb_tailroom(skb) < hci_skb_expect(skb)) { if (skb_tailroom(skb) < hci_skb_expect(skb)) {
kfree_skb(skb); kfree_skb(skb);
skb = NULL; skb = NULL;
...@@ -1762,6 +1790,13 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -1762,6 +1790,13 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
hdev->stat.sco_tx++; hdev->stat.sco_tx++;
return submit_tx_urb(hdev, urb); return submit_tx_urb(hdev, urb);
case HCI_ISODATA_PKT:
urb = alloc_bulk_urb(hdev, skb);
if (IS_ERR(urb))
return PTR_ERR(urb);
return submit_or_queue_tx_urb(hdev, urb);
} }
return -EILSEQ; return -EILSEQ;
...@@ -2069,7 +2104,6 @@ static int btusb_setup_csr(struct hci_dev *hdev) ...@@ -2069,7 +2104,6 @@ static int btusb_setup_csr(struct hci_dev *hdev)
* without these the controller will lock up. * without these the controller will lock up.
*/ */
set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks);
set_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks); set_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks);
set_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks); set_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks);
...@@ -2255,6 +2289,13 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2255,6 +2289,13 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
hdev->stat.sco_tx++; hdev->stat.sco_tx++;
return submit_tx_urb(hdev, urb); return submit_tx_urb(hdev, urb);
case HCI_ISODATA_PKT:
urb = alloc_bulk_urb(hdev, skb);
if (IS_ERR(urb))
return PTR_ERR(urb);
return submit_or_queue_tx_urb(hdev, urb);
} }
return -EILSEQ; return -EILSEQ;
...@@ -3352,7 +3393,6 @@ static int btusb_setup_qca(struct hci_dev *hdev) ...@@ -3352,7 +3393,6 @@ static int btusb_setup_qca(struct hci_dev *hdev)
* work with the likes of HSP/HFP mSBC. * work with the likes of HSP/HFP mSBC.
*/ */
set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks); set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks);
set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks);
return 0; return 0;
} }
...@@ -3795,6 +3835,7 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -3795,6 +3835,7 @@ static int btusb_probe(struct usb_interface *intf,
hdev->manufacturer = 70; hdev->manufacturer = 70;
hdev->cmd_timeout = btusb_mtk_cmd_timeout; hdev->cmd_timeout = btusb_mtk_cmd_timeout;
hdev->set_bdaddr = btmtk_set_bdaddr; hdev->set_bdaddr = btmtk_set_bdaddr;
set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks);
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
data->recv_acl = btusb_recv_acl_mtk; data->recv_acl = btusb_recv_acl_mtk;
} }
......
...@@ -53,10 +53,12 @@ ...@@ -53,10 +53,12 @@
* struct bcm_device_data - device specific data * struct bcm_device_data - device specific data
* @no_early_set_baudrate: Disallow set baudrate before driver setup() * @no_early_set_baudrate: Disallow set baudrate before driver setup()
* @drive_rts_on_open: drive RTS signal on ->open() when platform requires it * @drive_rts_on_open: drive RTS signal on ->open() when platform requires it
* @max_autobaud_speed: max baudrate supported by device in autobaud mode
*/ */
struct bcm_device_data { struct bcm_device_data {
bool no_early_set_baudrate; bool no_early_set_baudrate;
bool drive_rts_on_open; bool drive_rts_on_open;
u32 max_autobaud_speed;
}; };
/** /**
...@@ -99,6 +101,8 @@ struct bcm_device_data { ...@@ -99,6 +101,8 @@ struct bcm_device_data {
* @no_early_set_baudrate: don't set_baudrate before setup() * @no_early_set_baudrate: don't set_baudrate before setup()
* @drive_rts_on_open: drive RTS signal on ->open() when platform requires it * @drive_rts_on_open: drive RTS signal on ->open() when platform requires it
* @pcm_int_params: keep the initial PCM configuration * @pcm_int_params: keep the initial PCM configuration
* @use_autobaud_mode: start Bluetooth device in autobaud mode
* @max_autobaud_speed: max baudrate supported by device in autobaud mode
*/ */
struct bcm_device { struct bcm_device {
/* Must be the first member, hci_serdev.c expects this. */ /* Must be the first member, hci_serdev.c expects this. */
...@@ -136,7 +140,9 @@ struct bcm_device { ...@@ -136,7 +140,9 @@ struct bcm_device {
#endif #endif
bool no_early_set_baudrate; bool no_early_set_baudrate;
bool drive_rts_on_open; bool drive_rts_on_open;
bool use_autobaud_mode;
u8 pcm_int_params[5]; u8 pcm_int_params[5];
u32 max_autobaud_speed;
}; };
/* generic bcm uart resources */ /* generic bcm uart resources */
...@@ -472,15 +478,20 @@ static int bcm_open(struct hci_uart *hu) ...@@ -472,15 +478,20 @@ static int bcm_open(struct hci_uart *hu)
out: out:
if (bcm->dev) { if (bcm->dev) {
if (bcm->dev->drive_rts_on_open) if (bcm->dev->use_autobaud_mode)
hci_uart_set_flow_control(hu, false); /* Assert BT_UART_CTS_N */
else if (bcm->dev->drive_rts_on_open)
hci_uart_set_flow_control(hu, true); hci_uart_set_flow_control(hu, true);
hu->init_speed = bcm->dev->init_speed; if (bcm->dev->use_autobaud_mode && bcm->dev->max_autobaud_speed)
hu->init_speed = min(bcm->dev->oper_speed, bcm->dev->max_autobaud_speed);
else
hu->init_speed = bcm->dev->init_speed;
/* If oper_speed is set, ldisc/serdev will set the baudrate /* If oper_speed is set, ldisc/serdev will set the baudrate
* before calling setup() * before calling setup()
*/ */
if (!bcm->dev->no_early_set_baudrate) if (!bcm->dev->no_early_set_baudrate && !bcm->dev->use_autobaud_mode)
hu->oper_speed = bcm->dev->oper_speed; hu->oper_speed = bcm->dev->oper_speed;
err = bcm_gpio_set_power(bcm->dev, true); err = bcm_gpio_set_power(bcm->dev, true);
...@@ -564,6 +575,7 @@ static int bcm_setup(struct hci_uart *hu) ...@@ -564,6 +575,7 @@ static int bcm_setup(struct hci_uart *hu)
{ {
struct bcm_data *bcm = hu->priv; struct bcm_data *bcm = hu->priv;
bool fw_load_done = false; bool fw_load_done = false;
bool use_autobaud_mode = (bcm->dev ? bcm->dev->use_autobaud_mode : 0);
unsigned int speed; unsigned int speed;
int err; int err;
...@@ -572,7 +584,7 @@ static int bcm_setup(struct hci_uart *hu) ...@@ -572,7 +584,7 @@ static int bcm_setup(struct hci_uart *hu)
hu->hdev->set_diag = bcm_set_diag; hu->hdev->set_diag = bcm_set_diag;
hu->hdev->set_bdaddr = btbcm_set_bdaddr; hu->hdev->set_bdaddr = btbcm_set_bdaddr;
err = btbcm_initialize(hu->hdev, &fw_load_done); err = btbcm_initialize(hu->hdev, &fw_load_done, use_autobaud_mode);
if (err) if (err)
return err; return err;
...@@ -580,8 +592,8 @@ static int bcm_setup(struct hci_uart *hu) ...@@ -580,8 +592,8 @@ static int bcm_setup(struct hci_uart *hu)
return 0; return 0;
/* Init speed if any */ /* Init speed if any */
if (hu->init_speed) if (bcm->dev && bcm->dev->init_speed)
speed = hu->init_speed; speed = bcm->dev->init_speed;
else if (hu->proto->init_speed) else if (hu->proto->init_speed)
speed = hu->proto->init_speed; speed = hu->proto->init_speed;
else else
...@@ -616,7 +628,7 @@ static int bcm_setup(struct hci_uart *hu) ...@@ -616,7 +628,7 @@ static int bcm_setup(struct hci_uart *hu)
btbcm_write_pcm_int_params(hu->hdev, &params); btbcm_write_pcm_int_params(hu->hdev, &params);
} }
err = btbcm_finalize(hu->hdev, &fw_load_done); err = btbcm_finalize(hu->hdev, &fw_load_done, use_autobaud_mode);
if (err) if (err)
return err; return err;
...@@ -1197,6 +1209,8 @@ static int bcm_acpi_probe(struct bcm_device *dev) ...@@ -1197,6 +1209,8 @@ static int bcm_acpi_probe(struct bcm_device *dev)
static int bcm_of_probe(struct bcm_device *bdev) static int bcm_of_probe(struct bcm_device *bdev)
{ {
bdev->use_autobaud_mode = device_property_read_bool(bdev->dev,
"brcm,requires-autobaud-mode");
device_property_read_u32(bdev->dev, "max-speed", &bdev->oper_speed); device_property_read_u32(bdev->dev, "max-speed", &bdev->oper_speed);
device_property_read_u8_array(bdev->dev, "brcm,bt-pcm-int-params", device_property_read_u8_array(bdev->dev, "brcm,bt-pcm-int-params",
bdev->pcm_int_params, 5); bdev->pcm_int_params, 5);
...@@ -1512,6 +1526,7 @@ static int bcm_serdev_probe(struct serdev_device *serdev) ...@@ -1512,6 +1526,7 @@ static int bcm_serdev_probe(struct serdev_device *serdev)
data = device_get_match_data(bcmdev->dev); data = device_get_match_data(bcmdev->dev);
if (data) { if (data) {
bcmdev->max_autobaud_speed = data->max_autobaud_speed;
bcmdev->no_early_set_baudrate = data->no_early_set_baudrate; bcmdev->no_early_set_baudrate = data->no_early_set_baudrate;
bcmdev->drive_rts_on_open = data->drive_rts_on_open; bcmdev->drive_rts_on_open = data->drive_rts_on_open;
} }
...@@ -1535,6 +1550,10 @@ static struct bcm_device_data bcm43438_device_data = { ...@@ -1535,6 +1550,10 @@ static struct bcm_device_data bcm43438_device_data = {
.drive_rts_on_open = true, .drive_rts_on_open = true,
}; };
static struct bcm_device_data cyw55572_device_data = {
.max_autobaud_speed = 921600,
};
static const struct of_device_id bcm_bluetooth_of_match[] = { static const struct of_device_id bcm_bluetooth_of_match[] = {
{ .compatible = "brcm,bcm20702a1" }, { .compatible = "brcm,bcm20702a1" },
{ .compatible = "brcm,bcm4329-bt" }, { .compatible = "brcm,bcm4329-bt" },
...@@ -1544,8 +1563,10 @@ static const struct of_device_id bcm_bluetooth_of_match[] = { ...@@ -1544,8 +1563,10 @@ static const struct of_device_id bcm_bluetooth_of_match[] = {
{ .compatible = "brcm,bcm43430a0-bt" }, { .compatible = "brcm,bcm43430a0-bt" },
{ .compatible = "brcm,bcm43430a1-bt" }, { .compatible = "brcm,bcm43430a1-bt" },
{ .compatible = "brcm,bcm43438-bt", .data = &bcm43438_device_data }, { .compatible = "brcm,bcm43438-bt", .data = &bcm43438_device_data },
{ .compatible = "brcm,bcm4349-bt", .data = &bcm43438_device_data },
{ .compatible = "brcm,bcm43540-bt", .data = &bcm4354_device_data }, { .compatible = "brcm,bcm43540-bt", .data = &bcm4354_device_data },
{ .compatible = "brcm,bcm4335a0" }, { .compatible = "brcm,bcm4335a0" },
{ .compatible = "infineon,cyw55572-bt", .data = &cyw55572_device_data },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, bcm_bluetooth_of_match); MODULE_DEVICE_TABLE(of, bcm_bluetooth_of_match);
......
...@@ -1217,7 +1217,11 @@ static struct platform_driver intel_driver = { ...@@ -1217,7 +1217,11 @@ static struct platform_driver intel_driver = {
int __init intel_init(void) int __init intel_init(void)
{ {
platform_driver_register(&intel_driver); int err;
err = platform_driver_register(&intel_driver);
if (err)
return err;
return hci_uart_register_proto(&intel_proto); return hci_uart_register_proto(&intel_proto);
} }
......
...@@ -1588,7 +1588,7 @@ static bool qca_wakeup(struct hci_dev *hdev) ...@@ -1588,7 +1588,7 @@ static bool qca_wakeup(struct hci_dev *hdev)
wakeup = device_may_wakeup(hu->serdev->ctrl->dev.parent); wakeup = device_may_wakeup(hu->serdev->ctrl->dev.parent);
bt_dev_dbg(hu->hdev, "wakeup status : %d", wakeup); bt_dev_dbg(hu->hdev, "wakeup status : %d", wakeup);
return !wakeup; return wakeup;
} }
static int qca_regulator_init(struct hci_uart *hu) static int qca_regulator_init(struct hci_uart *hu)
......
...@@ -231,6 +231,15 @@ static int hci_uart_setup(struct hci_dev *hdev) ...@@ -231,6 +231,15 @@ static int hci_uart_setup(struct hci_dev *hdev)
return 0; return 0;
} }
/* Check if the device is wakeable */
static bool hci_uart_wakeup(struct hci_dev *hdev)
{
/* HCI UART devices are assumed to be wakeable by default.
* Implement wakeup callback to override this behavior.
*/
return true;
}
/** hci_uart_write_wakeup - transmit buffer wakeup /** hci_uart_write_wakeup - transmit buffer wakeup
* @serdev: serial device * @serdev: serial device
* *
...@@ -342,6 +351,8 @@ int hci_uart_register_device(struct hci_uart *hu, ...@@ -342,6 +351,8 @@ int hci_uart_register_device(struct hci_uart *hu,
hdev->flush = hci_uart_flush; hdev->flush = hci_uart_flush;
hdev->send = hci_uart_send_frame; hdev->send = hci_uart_send_frame;
hdev->setup = hci_uart_setup; hdev->setup = hci_uart_setup;
if (!hdev->wakeup)
hdev->wakeup = hci_uart_wakeup;
SET_HCIDEV_DEV(hdev, &hu->serdev->dev); SET_HCIDEV_DEV(hdev, &hu->serdev->dev);
if (test_bit(HCI_UART_NO_SUSPEND_NOTIFIER, &hu->flags)) if (test_bit(HCI_UART_NO_SUSPEND_NOTIFIER, &hu->flags))
......
...@@ -55,6 +55,8 @@ ...@@ -55,6 +55,8 @@
#define BTPROTO_CMTP 5 #define BTPROTO_CMTP 5
#define BTPROTO_HIDP 6 #define BTPROTO_HIDP 6
#define BTPROTO_AVDTP 7 #define BTPROTO_AVDTP 7
#define BTPROTO_ISO 8
#define BTPROTO_LAST BTPROTO_ISO
#define SOL_HCI 0 #define SOL_HCI 0
#define SOL_L2CAP 6 #define SOL_L2CAP 6
...@@ -149,10 +151,51 @@ struct bt_voice { ...@@ -149,10 +151,51 @@ struct bt_voice {
#define BT_MODE_LE_FLOWCTL 0x03 #define BT_MODE_LE_FLOWCTL 0x03
#define BT_MODE_EXT_FLOWCTL 0x04 #define BT_MODE_EXT_FLOWCTL 0x04
#define BT_PKT_STATUS 16 #define BT_PKT_STATUS 16
#define BT_SCM_PKT_STATUS 0x03 #define BT_SCM_PKT_STATUS 0x03
#define BT_ISO_QOS 17
#define BT_ISO_QOS_CIG_UNSET 0xff
#define BT_ISO_QOS_CIS_UNSET 0xff
#define BT_ISO_QOS_BIG_UNSET 0xff
#define BT_ISO_QOS_BIS_UNSET 0xff
struct bt_iso_io_qos {
__u32 interval;
__u16 latency;
__u16 sdu;
__u8 phy;
__u8 rtn;
};
struct bt_iso_qos {
union {
__u8 cig;
__u8 big;
};
union {
__u8 cis;
__u8 bis;
};
union {
__u8 sca;
__u8 sync_interval;
};
__u8 packing;
__u8 framing;
struct bt_iso_io_qos in;
struct bt_iso_io_qos out;
};
#define BT_ISO_PHY_1M 0x01
#define BT_ISO_PHY_2M 0x02
#define BT_ISO_PHY_CODED 0x04
#define BT_ISO_PHY_ANY (BT_ISO_PHY_1M | BT_ISO_PHY_2M | \
BT_ISO_PHY_CODED)
#define BT_CODEC 19 #define BT_CODEC 19
struct bt_codec_caps { struct bt_codec_caps {
...@@ -177,6 +220,8 @@ struct bt_codecs { ...@@ -177,6 +220,8 @@ struct bt_codecs {
#define BT_CODEC_TRANSPARENT 0x03 #define BT_CODEC_TRANSPARENT 0x03
#define BT_CODEC_MSBC 0x05 #define BT_CODEC_MSBC 0x05
#define BT_ISO_BASE 20
__printf(1, 2) __printf(1, 2)
void bt_info(const char *fmt, ...); void bt_info(const char *fmt, ...);
__printf(1, 2) __printf(1, 2)
...@@ -494,7 +539,7 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk, ...@@ -494,7 +539,7 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk,
struct sk_buff *skb, **frag; struct sk_buff *skb, **frag;
skb = bt_skb_sendmsg(sk, msg, len, mtu, headroom, tailroom); skb = bt_skb_sendmsg(sk, msg, len, mtu, headroom, tailroom);
if (IS_ERR_OR_NULL(skb)) if (IS_ERR(skb))
return skb; return skb;
len -= skb->len; len -= skb->len;
...@@ -521,6 +566,7 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk, ...@@ -521,6 +566,7 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk,
} }
int bt_to_errno(u16 code); int bt_to_errno(u16 code);
__u8 bt_status(int err);
void hci_sock_set_flag(struct sock *sk, int nr); void hci_sock_set_flag(struct sock *sk, int nr);
void hci_sock_clear_flag(struct sock *sk, int nr); void hci_sock_clear_flag(struct sock *sk, int nr);
...@@ -558,6 +604,27 @@ static inline void sco_exit(void) ...@@ -558,6 +604,27 @@ static inline void sco_exit(void)
} }
#endif #endif
#if IS_ENABLED(CONFIG_BT_LE)
int iso_init(void);
int iso_exit(void);
bool iso_enabled(void);
#else
static inline int iso_init(void)
{
return 0;
}
static inline int iso_exit(void)
{
return 0;
}
static inline bool iso_enabled(void)
{
return false;
}
#endif
int mgmt_init(void); int mgmt_init(void);
void mgmt_exit(void); void mgmt_exit(void);
......
...@@ -228,17 +228,6 @@ enum { ...@@ -228,17 +228,6 @@ enum {
*/ */
HCI_QUIRK_VALID_LE_STATES, HCI_QUIRK_VALID_LE_STATES,
/* When this quirk is set, then erroneous data reporting
* is ignored. This is mainly due to the fact that the HCI
* Read Default Erroneous Data Reporting command is advertised,
* but not supported; these controllers often reply with unknown
* command and tend to lock up randomly. Needing a hard reset.
*
* This quirk can be set before hci_register_dev is called or
* during the hdev->setup vendor callback.
*/
HCI_QUIRK_BROKEN_ERR_DATA_REPORTING,
/* /*
* When this quirk is set, then the hci_suspend_notifier is not * When this quirk is set, then the hci_suspend_notifier is not
* registered. This is intended for devices which drop completely * registered. This is intended for devices which drop completely
...@@ -327,6 +316,7 @@ enum { ...@@ -327,6 +316,7 @@ enum {
HCI_USER_CHANNEL, HCI_USER_CHANNEL,
HCI_EXT_CONFIGURED, HCI_EXT_CONFIGURED,
HCI_LE_ADV, HCI_LE_ADV,
HCI_LE_PER_ADV,
HCI_LE_SCAN, HCI_LE_SCAN,
HCI_SSP_ENABLED, HCI_SSP_ENABLED,
HCI_SC_ENABLED, HCI_SC_ENABLED,
...@@ -349,6 +339,7 @@ enum { ...@@ -349,6 +339,7 @@ enum {
HCI_LE_SCAN_INTERRUPTED, HCI_LE_SCAN_INTERRUPTED,
HCI_WIDEBAND_SPEECH_ENABLED, HCI_WIDEBAND_SPEECH_ENABLED,
HCI_EVENT_FILTER_CONFIGURED, HCI_EVENT_FILTER_CONFIGURED,
HCI_PA_SYNC,
HCI_DUT_MODE, HCI_DUT_MODE,
HCI_VENDOR_DIAG, HCI_VENDOR_DIAG,
...@@ -361,6 +352,7 @@ enum { ...@@ -361,6 +352,7 @@ enum {
HCI_QUALITY_REPORT, HCI_QUALITY_REPORT,
HCI_OFFLOAD_CODECS_ENABLED, HCI_OFFLOAD_CODECS_ENABLED,
HCI_LE_SIMULTANEOUS_ROLES, HCI_LE_SIMULTANEOUS_ROLES,
HCI_CMD_DRAIN_WORKQUEUE,
__HCI_NUM_FLAGS, __HCI_NUM_FLAGS,
}; };
...@@ -496,6 +488,7 @@ enum { ...@@ -496,6 +488,7 @@ enum {
#define LMP_EXT_INQ 0x01 #define LMP_EXT_INQ 0x01
#define LMP_SIMUL_LE_BR 0x02 #define LMP_SIMUL_LE_BR 0x02
#define LMP_SIMPLE_PAIR 0x08 #define LMP_SIMPLE_PAIR 0x08
#define LMP_ERR_DATA_REPORTING 0x20
#define LMP_NO_FLUSH 0x40 #define LMP_NO_FLUSH 0x40
#define LMP_LSTO 0x01 #define LMP_LSTO 0x01
...@@ -528,9 +521,11 @@ enum { ...@@ -528,9 +521,11 @@ enum {
#define HCI_LE_PHY_2M 0x01 #define HCI_LE_PHY_2M 0x01
#define HCI_LE_PHY_CODED 0x08 #define HCI_LE_PHY_CODED 0x08
#define HCI_LE_EXT_ADV 0x10 #define HCI_LE_EXT_ADV 0x10
#define HCI_LE_PERIODIC_ADV 0x20
#define HCI_LE_CHAN_SEL_ALG2 0x40 #define HCI_LE_CHAN_SEL_ALG2 0x40
#define HCI_LE_CIS_CENTRAL 0x10 #define HCI_LE_CIS_CENTRAL 0x10
#define HCI_LE_CIS_PERIPHERAL 0x20 #define HCI_LE_CIS_PERIPHERAL 0x20
#define HCI_LE_ISO_BROADCASTER 0x40
/* Connection modes */ /* Connection modes */
#define HCI_CM_ACTIVE 0x0000 #define HCI_CM_ACTIVE 0x0000
...@@ -1874,6 +1869,22 @@ struct hci_cp_le_ext_conn_param { ...@@ -1874,6 +1869,22 @@ struct hci_cp_le_ext_conn_param {
__le16 max_ce_len; __le16 max_ce_len;
} __packed; } __packed;
#define HCI_OP_LE_PA_CREATE_SYNC 0x2044
struct hci_cp_le_pa_create_sync {
__u8 options;
__u8 sid;
__u8 addr_type;
bdaddr_t addr;
__le16 skip;
__le16 sync_timeout;
__u8 sync_cte_type;
} __packed;
#define HCI_OP_LE_PA_TERM_SYNC 0x2046
struct hci_cp_le_pa_term_sync {
__le16 handle;
} __packed;
#define HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS 0x203b #define HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS 0x203b
struct hci_rp_le_read_num_supported_adv_sets { struct hci_rp_le_read_num_supported_adv_sets {
__u8 status; __u8 status;
...@@ -1908,13 +1919,6 @@ struct hci_rp_le_set_ext_adv_params { ...@@ -1908,13 +1919,6 @@ struct hci_rp_le_set_ext_adv_params {
__u8 tx_power; __u8 tx_power;
} __packed; } __packed;
#define HCI_OP_LE_SET_EXT_ADV_ENABLE 0x2039
struct hci_cp_le_set_ext_adv_enable {
__u8 enable;
__u8 num_of_sets;
__u8 data[];
} __packed;
struct hci_cp_ext_adv_set { struct hci_cp_ext_adv_set {
__u8 handle; __u8 handle;
__le16 duration; __le16 duration;
...@@ -1941,6 +1945,37 @@ struct hci_cp_le_set_ext_scan_rsp_data { ...@@ -1941,6 +1945,37 @@ struct hci_cp_le_set_ext_scan_rsp_data {
__u8 data[]; __u8 data[];
} __packed; } __packed;
#define HCI_OP_LE_SET_EXT_ADV_ENABLE 0x2039
struct hci_cp_le_set_ext_adv_enable {
__u8 enable;
__u8 num_of_sets;
__u8 data[];
} __packed;
#define HCI_OP_LE_SET_PER_ADV_PARAMS 0x203e
struct hci_cp_le_set_per_adv_params {
__u8 handle;
__le16 min_interval;
__le16 max_interval;
__le16 periodic_properties;
} __packed;
#define HCI_MAX_PER_AD_LENGTH 252
#define HCI_OP_LE_SET_PER_ADV_DATA 0x203f
struct hci_cp_le_set_per_adv_data {
__u8 handle;
__u8 operation;
__u8 length;
__u8 data[];
} __packed;
#define HCI_OP_LE_SET_PER_ADV_ENABLE 0x2040
struct hci_cp_le_set_per_adv_enable {
__u8 enable;
__u8 handle;
} __packed;
#define LE_SET_ADV_DATA_OP_COMPLETE 0x03 #define LE_SET_ADV_DATA_OP_COMPLETE 0x03
#define LE_SET_ADV_DATA_NO_FRAG 0x01 #define LE_SET_ADV_DATA_NO_FRAG 0x01
...@@ -1998,7 +2033,7 @@ struct hci_rp_le_read_iso_tx_sync { ...@@ -1998,7 +2033,7 @@ struct hci_rp_le_read_iso_tx_sync {
struct hci_cis_params { struct hci_cis_params {
__u8 cis_id; __u8 cis_id;
__le16 c_sdu; __le16 c_sdu;
__le16 p_pdu; __le16 p_sdu;
__u8 c_phy; __u8 c_phy;
__u8 p_phy; __u8 p_phy;
__u8 c_rtn; __u8 c_rtn;
...@@ -2009,7 +2044,7 @@ struct hci_cp_le_set_cig_params { ...@@ -2009,7 +2044,7 @@ struct hci_cp_le_set_cig_params {
__u8 cig_id; __u8 cig_id;
__u8 c_interval[3]; __u8 c_interval[3];
__u8 p_interval[3]; __u8 p_interval[3];
__u8 wc_sca; __u8 sca;
__u8 packing; __u8 packing;
__u8 framing; __u8 framing;
__le16 c_latency; __le16 c_latency;
...@@ -2052,6 +2087,73 @@ struct hci_cp_le_reject_cis { ...@@ -2052,6 +2087,73 @@ struct hci_cp_le_reject_cis {
__u8 reason; __u8 reason;
} __packed; } __packed;
#define HCI_OP_LE_CREATE_BIG 0x2068
struct hci_bis {
__u8 sdu_interval[3];
__le16 sdu;
__le16 latency;
__u8 rtn;
__u8 phy;
__u8 packing;
__u8 framing;
__u8 encryption;
__u8 bcode[16];
} __packed;
struct hci_cp_le_create_big {
__u8 handle;
__u8 adv_handle;
__u8 num_bis;
struct hci_bis bis;
} __packed;
#define HCI_OP_LE_TERM_BIG 0x206a
struct hci_cp_le_term_big {
__u8 handle;
__u8 reason;
} __packed;
#define HCI_OP_LE_BIG_CREATE_SYNC 0x206b
struct hci_cp_le_big_create_sync {
__u8 handle;
__le16 sync_handle;
__u8 encryption;
__u8 bcode[16];
__u8 mse;
__le16 timeout;
__u8 num_bis;
__u8 bis[0];
} __packed;
#define HCI_OP_LE_BIG_TERM_SYNC 0x206c
struct hci_cp_le_big_term_sync {
__u8 handle;
} __packed;
#define HCI_OP_LE_SETUP_ISO_PATH 0x206e
struct hci_cp_le_setup_iso_path {
__le16 handle;
__u8 direction;
__u8 path;
__u8 codec;
__le16 codec_cid;
__le16 codec_vid;
__u8 delay[3];
__u8 codec_cfg_len;
__u8 codec_cfg[0];
} __packed;
struct hci_rp_le_setup_iso_path {
__u8 status;
__le16 handle;
} __packed;
#define HCI_OP_LE_SET_HOST_FEATURE 0x2074
struct hci_cp_le_set_host_feature {
__u8 bit_number;
__u8 bit_value;
} __packed;
/* ---- HCI Events ---- */ /* ---- HCI Events ---- */
struct hci_ev_status { struct hci_ev_status {
__u8 status; __u8 status;
...@@ -2580,6 +2682,18 @@ struct hci_ev_le_ext_adv_report { ...@@ -2580,6 +2682,18 @@ struct hci_ev_le_ext_adv_report {
struct hci_ev_le_ext_adv_info info[]; struct hci_ev_le_ext_adv_info info[];
} __packed; } __packed;
#define HCI_EV_LE_PA_SYNC_ESTABLISHED 0x0e
struct hci_ev_le_pa_sync_established {
__u8 status;
__le16 handle;
__u8 sid;
__u8 bdaddr_type;
bdaddr_t bdaddr;
__u8 phy;
__le16 interval;
__u8 clock_accuracy;
} __packed;
#define HCI_EV_LE_ENHANCED_CONN_COMPLETE 0x0a #define HCI_EV_LE_ENHANCED_CONN_COMPLETE 0x0a
struct hci_ev_le_enh_conn_complete { struct hci_ev_le_enh_conn_complete {
__u8 status; __u8 status;
...@@ -2631,6 +2745,55 @@ struct hci_evt_le_cis_req { ...@@ -2631,6 +2745,55 @@ struct hci_evt_le_cis_req {
__u8 cis_id; __u8 cis_id;
} __packed; } __packed;
#define HCI_EVT_LE_CREATE_BIG_COMPLETE 0x1b
struct hci_evt_le_create_big_complete {
__u8 status;
__u8 handle;
__u8 sync_delay[3];
__u8 transport_delay[3];
__u8 phy;
__u8 nse;
__u8 bn;
__u8 pto;
__u8 irc;
__le16 max_pdu;
__le16 interval;
__u8 num_bis;
__le16 bis_handle[];
} __packed;
#define HCI_EVT_LE_BIG_SYNC_ESTABILISHED 0x1d
struct hci_evt_le_big_sync_estabilished {
__u8 status;
__u8 handle;
__u8 latency[3];
__u8 nse;
__u8 bn;
__u8 pto;
__u8 irc;
__le16 max_pdu;
__le16 interval;
__u8 num_bis;
__le16 bis[];
} __packed;
#define HCI_EVT_LE_BIG_INFO_ADV_REPORT 0x22
struct hci_evt_le_big_info_adv_report {
__le16 sync_handle;
__u8 num_bis;
__u8 nse;
__le16 iso_interval;
__u8 bn;
__u8 pto;
__u8 irc;
__le16 max_pdu;
__u8 sdu_interval[3];
__le16 max_sdu;
__u8 phy;
__u8 framing;
__u8 encryption;
} __packed;
#define HCI_EV_VENDOR 0xff #define HCI_EV_VENDOR 0xff
/* Internal events generated by Bluetooth stack */ /* Internal events generated by Bluetooth stack */
......
This diff is collapsed.
...@@ -124,6 +124,8 @@ struct hci_dev_info { ...@@ -124,6 +124,8 @@ struct hci_dev_info {
__u16 acl_pkts; __u16 acl_pkts;
__u16 sco_mtu; __u16 sco_mtu;
__u16 sco_pkts; __u16 sco_pkts;
__u16 iso_mtu;
__u16 iso_pkts;
struct hci_dev_stats stat; struct hci_dev_stats stat;
}; };
......
...@@ -65,6 +65,10 @@ int hci_enable_ext_advertising_sync(struct hci_dev *hdev, u8 instance); ...@@ -65,6 +65,10 @@ int hci_enable_ext_advertising_sync(struct hci_dev *hdev, u8 instance);
int hci_enable_advertising_sync(struct hci_dev *hdev); int hci_enable_advertising_sync(struct hci_dev *hdev);
int hci_enable_advertising(struct hci_dev *hdev); int hci_enable_advertising(struct hci_dev *hdev);
int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len,
u8 *data, u32 flags, u16 min_interval,
u16 max_interval, u16 sync_interval);
int hci_remove_advertising_sync(struct hci_dev *hdev, struct sock *sk, int hci_remove_advertising_sync(struct hci_dev *hdev, struct sock *sk,
u8 instance, bool force); u8 instance, bool force);
int hci_disable_advertising_sync(struct hci_dev *hdev); int hci_disable_advertising_sync(struct hci_dev *hdev);
...@@ -78,10 +82,12 @@ int hci_read_clock_sync(struct hci_dev *hdev, struct hci_cp_read_clock *cp); ...@@ -78,10 +82,12 @@ int hci_read_clock_sync(struct hci_dev *hdev, struct hci_cp_read_clock *cp);
int hci_write_fast_connectable_sync(struct hci_dev *hdev, bool enable); int hci_write_fast_connectable_sync(struct hci_dev *hdev, bool enable);
int hci_update_scan_sync(struct hci_dev *hdev); int hci_update_scan_sync(struct hci_dev *hdev);
int hci_update_scan(struct hci_dev *hdev);
int hci_write_le_host_supported_sync(struct hci_dev *hdev, u8 le, u8 simul); int hci_write_le_host_supported_sync(struct hci_dev *hdev, u8 le, u8 simul);
int hci_remove_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance, int hci_remove_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance,
struct sock *sk); struct sock *sk);
int hci_remove_ext_adv_instance(struct hci_dev *hdev, u8 instance);
struct sk_buff *hci_read_local_oob_data_sync(struct hci_dev *hdev, bool ext, struct sk_buff *hci_read_local_oob_data_sync(struct hci_dev *hdev, bool ext,
struct sock *sk); struct sock *sk);
...@@ -105,4 +111,14 @@ int hci_resume_sync(struct hci_dev *hdev); ...@@ -105,4 +111,14 @@ int hci_resume_sync(struct hci_dev *hdev);
struct hci_conn; struct hci_conn;
int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason);
int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn); int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn);
int hci_le_remove_cig_sync(struct hci_dev *hdev, u8 handle);
int hci_le_terminate_big_sync(struct hci_dev *hdev, u8 handle, u8 reason);
int hci_le_big_terminate_sync(struct hci_dev *hdev, u8 handle);
int hci_le_pa_terminate_sync(struct hci_dev *hdev, u16 handle);
/* SPDX-License-Identifier: GPL-2.0 */
/*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2022 Intel Corporation
*/
#ifndef __ISO_H
#define __ISO_H
/* ISO defaults */
#define ISO_DEFAULT_MTU 251
#define ISO_MAX_NUM_BIS 0x1f
/* ISO socket broadcast address */
struct sockaddr_iso_bc {
bdaddr_t bc_bdaddr;
__u8 bc_bdaddr_type;
__u8 bc_sid;
__u8 bc_num_bis;
__u8 bc_bis[ISO_MAX_NUM_BIS];
};
/* ISO socket address */
struct sockaddr_iso {
sa_family_t iso_family;
bdaddr_t iso_bdaddr;
__u8 iso_bdaddr_type;
struct sockaddr_iso_bc iso_bc[];
};
#endif /* __ISO_H */
...@@ -29,6 +29,7 @@ menuconfig BT ...@@ -29,6 +29,7 @@ menuconfig BT
SCO audio links SCO audio links
L2CAP (Logical Link Control and Adaptation Protocol) L2CAP (Logical Link Control and Adaptation Protocol)
SMP (Security Manager Protocol) on LE (Low Energy) links SMP (Security Manager Protocol) on LE (Low Energy) links
ISO isochronous links
HCI Device drivers (Interface to the hardware) HCI Device drivers (Interface to the hardware)
RFCOMM Module (RFCOMM Protocol) RFCOMM Module (RFCOMM Protocol)
BNEP Module (Bluetooth Network Encapsulation Protocol) BNEP Module (Bluetooth Network Encapsulation Protocol)
......
...@@ -18,6 +18,7 @@ bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ ...@@ -18,6 +18,7 @@ bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
eir.o hci_sync.o eir.o hci_sync.o
bluetooth-$(CONFIG_BT_BREDR) += sco.o bluetooth-$(CONFIG_BT_BREDR) += sco.o
bluetooth-$(CONFIG_BT_LE) += iso.o
bluetooth-$(CONFIG_BT_HS) += a2mp.o amp.o bluetooth-$(CONFIG_BT_HS) += a2mp.o amp.o
bluetooth-$(CONFIG_BT_LEDS) += leds.o bluetooth-$(CONFIG_BT_LEDS) += leds.o
bluetooth-$(CONFIG_BT_MSFTEXT) += msft.o bluetooth-$(CONFIG_BT_MSFTEXT) += msft.o
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#include "selftest.h" #include "selftest.h"
/* Bluetooth sockets */ /* Bluetooth sockets */
#define BT_MAX_PROTO 8 #define BT_MAX_PROTO (BTPROTO_LAST + 1)
static const struct net_proto_family *bt_proto[BT_MAX_PROTO]; static const struct net_proto_family *bt_proto[BT_MAX_PROTO];
static DEFINE_RWLOCK(bt_proto_lock); static DEFINE_RWLOCK(bt_proto_lock);
...@@ -52,6 +52,7 @@ static const char *const bt_key_strings[BT_MAX_PROTO] = { ...@@ -52,6 +52,7 @@ static const char *const bt_key_strings[BT_MAX_PROTO] = {
"sk_lock-AF_BLUETOOTH-BTPROTO_CMTP", "sk_lock-AF_BLUETOOTH-BTPROTO_CMTP",
"sk_lock-AF_BLUETOOTH-BTPROTO_HIDP", "sk_lock-AF_BLUETOOTH-BTPROTO_HIDP",
"sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP", "sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP",
"sk_lock-AF_BLUETOOTH-BTPROTO_ISO",
}; };
static struct lock_class_key bt_slock_key[BT_MAX_PROTO]; static struct lock_class_key bt_slock_key[BT_MAX_PROTO];
...@@ -64,6 +65,7 @@ static const char *const bt_slock_key_strings[BT_MAX_PROTO] = { ...@@ -64,6 +65,7 @@ static const char *const bt_slock_key_strings[BT_MAX_PROTO] = {
"slock-AF_BLUETOOTH-BTPROTO_CMTP", "slock-AF_BLUETOOTH-BTPROTO_CMTP",
"slock-AF_BLUETOOTH-BTPROTO_HIDP", "slock-AF_BLUETOOTH-BTPROTO_HIDP",
"slock-AF_BLUETOOTH-BTPROTO_AVDTP", "slock-AF_BLUETOOTH-BTPROTO_AVDTP",
"slock-AF_BLUETOOTH-BTPROTO_ISO",
}; };
void bt_sock_reclassify_lock(struct sock *sk, int proto) void bt_sock_reclassify_lock(struct sock *sk, int proto)
......
...@@ -13,6 +13,20 @@ ...@@ -13,6 +13,20 @@
#define PNP_INFO_SVCLASS_ID 0x1200 #define PNP_INFO_SVCLASS_ID 0x1200
static u8 eir_append_name(u8 *eir, u16 eir_len, u8 type, u8 *data, u8 data_len)
{
u8 name[HCI_MAX_SHORT_NAME_LENGTH + 1];
/* If data is already NULL terminated just pass it directly */
if (data[data_len - 1] == '\0')
return eir_append_data(eir, eir_len, type, data, data_len);
memcpy(name, data, HCI_MAX_SHORT_NAME_LENGTH);
name[HCI_MAX_SHORT_NAME_LENGTH] = '\0';
return eir_append_data(eir, eir_len, type, name, sizeof(name));
}
u8 eir_append_local_name(struct hci_dev *hdev, u8 *ptr, u8 ad_len) u8 eir_append_local_name(struct hci_dev *hdev, u8 *ptr, u8 ad_len)
{ {
size_t short_len; size_t short_len;
...@@ -23,29 +37,26 @@ u8 eir_append_local_name(struct hci_dev *hdev, u8 *ptr, u8 ad_len) ...@@ -23,29 +37,26 @@ u8 eir_append_local_name(struct hci_dev *hdev, u8 *ptr, u8 ad_len)
return ad_len; return ad_len;
/* use complete name if present and fits */ /* use complete name if present and fits */
complete_len = strlen(hdev->dev_name); complete_len = strnlen(hdev->dev_name, sizeof(hdev->dev_name));
if (complete_len && complete_len <= HCI_MAX_SHORT_NAME_LENGTH) if (complete_len && complete_len <= HCI_MAX_SHORT_NAME_LENGTH)
return eir_append_data(ptr, ad_len, EIR_NAME_COMPLETE, return eir_append_name(ptr, ad_len, EIR_NAME_COMPLETE,
hdev->dev_name, complete_len + 1); hdev->dev_name, complete_len + 1);
/* use short name if present */ /* use short name if present */
short_len = strlen(hdev->short_name); short_len = strnlen(hdev->short_name, sizeof(hdev->short_name));
if (short_len) if (short_len)
return eir_append_data(ptr, ad_len, EIR_NAME_SHORT, return eir_append_name(ptr, ad_len, EIR_NAME_SHORT,
hdev->short_name, short_len + 1); hdev->short_name,
short_len == HCI_MAX_SHORT_NAME_LENGTH ?
short_len : short_len + 1);
/* use shortened full name if present, we already know that name /* use shortened full name if present, we already know that name
* is longer then HCI_MAX_SHORT_NAME_LENGTH * is longer then HCI_MAX_SHORT_NAME_LENGTH
*/ */
if (complete_len) { if (complete_len)
u8 name[HCI_MAX_SHORT_NAME_LENGTH + 1]; return eir_append_name(ptr, ad_len, EIR_NAME_SHORT,
hdev->dev_name,
memcpy(name, hdev->dev_name, HCI_MAX_SHORT_NAME_LENGTH); HCI_MAX_SHORT_NAME_LENGTH);
name[HCI_MAX_SHORT_NAME_LENGTH] = '\0';
return eir_append_data(ptr, ad_len, EIR_NAME_SHORT, name,
sizeof(name));
}
return ad_len; return ad_len;
} }
...@@ -181,7 +192,7 @@ void eir_create(struct hci_dev *hdev, u8 *data) ...@@ -181,7 +192,7 @@ void eir_create(struct hci_dev *hdev, u8 *data)
u8 *ptr = data; u8 *ptr = data;
size_t name_len; size_t name_len;
name_len = strlen(hdev->dev_name); name_len = strnlen(hdev->dev_name, sizeof(hdev->dev_name));
if (name_len > 0) { if (name_len > 0) {
/* EIR Data type */ /* EIR Data type */
...@@ -225,6 +236,27 @@ void eir_create(struct hci_dev *hdev, u8 *data) ...@@ -225,6 +236,27 @@ void eir_create(struct hci_dev *hdev, u8 *data)
ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
} }
u8 eir_create_per_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
{
struct adv_info *adv = NULL;
u8 ad_len = 0;
/* Return 0 when the current instance identifier is invalid. */
if (instance) {
adv = hci_find_adv_instance(hdev, instance);
if (!adv)
return 0;
}
if (adv) {
memcpy(ptr, adv->per_adv_data, adv->per_adv_data_len);
ad_len += adv->per_adv_data_len;
ptr += adv->per_adv_data_len;
}
return ad_len;
}
u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
{ {
struct adv_info *adv = NULL; struct adv_info *adv = NULL;
......
...@@ -11,6 +11,7 @@ void eir_create(struct hci_dev *hdev, u8 *data); ...@@ -11,6 +11,7 @@ void eir_create(struct hci_dev *hdev, u8 *data);
u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr); u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr);
u8 eir_create_scan_rsp(struct hci_dev *hdev, u8 instance, u8 *ptr); u8 eir_create_scan_rsp(struct hci_dev *hdev, u8 instance, u8 *ptr);
u8 eir_create_per_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr);
u8 eir_append_local_name(struct hci_dev *hdev, u8 *eir, u8 ad_len); u8 eir_append_local_name(struct hci_dev *hdev, u8 *eir, u8 ad_len);
u8 eir_append_appearance(struct hci_dev *hdev, u8 *ptr, u8 ad_len); u8 eir_append_appearance(struct hci_dev *hdev, u8 *ptr, u8 ad_len);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -68,8 +68,6 @@ int __hci_req_sync(struct hci_dev *hdev, int (*func)(struct hci_request *req, ...@@ -68,8 +68,6 @@ int __hci_req_sync(struct hci_dev *hdev, int (*func)(struct hci_request *req,
struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen, struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen,
const void *param); const void *param);
int __hci_req_hci_power_on(struct hci_dev *hdev);
void __hci_req_write_fast_connectable(struct hci_request *req, bool enable); void __hci_req_write_fast_connectable(struct hci_request *req, bool enable);
void __hci_req_update_name(struct hci_request *req); void __hci_req_update_name(struct hci_request *req);
void __hci_req_update_eir(struct hci_request *req); void __hci_req_update_eir(struct hci_request *req);
...@@ -85,6 +83,9 @@ void __hci_req_enable_advertising(struct hci_request *req); ...@@ -85,6 +83,9 @@ void __hci_req_enable_advertising(struct hci_request *req);
void __hci_req_disable_advertising(struct hci_request *req); void __hci_req_disable_advertising(struct hci_request *req);
void __hci_req_update_adv_data(struct hci_request *req, u8 instance); void __hci_req_update_adv_data(struct hci_request *req, u8 instance);
int hci_req_update_adv_data(struct hci_dev *hdev, u8 instance); int hci_req_update_adv_data(struct hci_dev *hdev, u8 instance);
int hci_req_start_per_adv(struct hci_dev *hdev, u8 instance, u32 flags,
u16 min_interval, u16 max_interval,
u16 sync_interval);
void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance); void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance);
int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance, int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance,
...@@ -94,8 +95,14 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk, ...@@ -94,8 +95,14 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk,
bool force); bool force);
int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance); int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance);
int __hci_req_setup_per_adv_instance(struct hci_request *req, u8 instance,
u16 min_interval, u16 max_interval);
int __hci_req_start_ext_adv(struct hci_request *req, u8 instance); int __hci_req_start_ext_adv(struct hci_request *req, u8 instance);
int __hci_req_start_per_adv(struct hci_request *req, u8 instance, u32 flags,
u16 min_interval, u16 max_interval,
u16 sync_interval);
int __hci_req_enable_ext_advertising(struct hci_request *req, u8 instance); int __hci_req_enable_ext_advertising(struct hci_request *req, u8 instance);
int __hci_req_enable_per_advertising(struct hci_request *req, u8 instance);
int __hci_req_disable_ext_adv_instance(struct hci_request *req, u8 instance); int __hci_req_disable_ext_adv_instance(struct hci_request *req, u8 instance);
int __hci_req_remove_ext_adv_instance(struct hci_request *req, u8 instance); int __hci_req_remove_ext_adv_instance(struct hci_request *req, u8 instance);
void __hci_req_clear_ext_adv_sets(struct hci_request *req); void __hci_req_clear_ext_adv_sets(struct hci_request *req);
...@@ -110,11 +117,6 @@ bool hci_req_stop_discovery(struct hci_request *req); ...@@ -110,11 +117,6 @@ bool hci_req_stop_discovery(struct hci_request *req);
int hci_req_configure_datapath(struct hci_dev *hdev, struct bt_codec *codec); int hci_req_configure_datapath(struct hci_dev *hdev, struct bt_codec *codec);
static inline void hci_req_update_scan(struct hci_dev *hdev)
{
queue_work(hdev->req_workqueue, &hdev->scan_update);
}
void __hci_req_update_scan(struct hci_request *req); void __hci_req_update_scan(struct hci_request *req);
int hci_update_random_address(struct hci_request *req, bool require_privacy, int hci_update_random_address(struct hci_request *req, bool require_privacy,
......
...@@ -869,7 +869,8 @@ static int hci_sock_release(struct socket *sock) ...@@ -869,7 +869,8 @@ static int hci_sock_release(struct socket *sock)
hdev = hci_pi(sk)->hdev; hdev = hci_pi(sk)->hdev;
if (hdev) { if (hdev) {
if (hci_pi(sk)->channel == HCI_CHANNEL_USER) { if (hci_pi(sk)->channel == HCI_CHANNEL_USER &&
!hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
/* When releasing a user channel exclusive access, /* When releasing a user channel exclusive access,
* call hci_dev_do_close directly instead of calling * call hci_dev_do_close directly instead of calling
* hci_dev_close to ensure the exclusive access will * hci_dev_close to ensure the exclusive access will
...@@ -878,9 +879,15 @@ static int hci_sock_release(struct socket *sock) ...@@ -878,9 +879,15 @@ static int hci_sock_release(struct socket *sock)
* The checking of HCI_AUTO_OFF is not needed in this * The checking of HCI_AUTO_OFF is not needed in this
* case since it will have been cleared already when * case since it will have been cleared already when
* opening the user channel. * opening the user channel.
*
* Make sure to also check that we haven't already
* unregistered since all the cleanup will have already
* been complete and hdev will get released when we put
* below.
*/ */
hci_dev_do_close(hdev); hci_dev_do_close(hdev);
hci_dev_clear_flag(hdev, HCI_USER_CHANNEL); hci_dev_clear_flag(hdev, HCI_USER_CHANNEL);
hci_register_suspend_notifier(hdev);
mgmt_index_added(hdev); mgmt_index_added(hdev);
} }
...@@ -1209,6 +1216,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, ...@@ -1209,6 +1216,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
} }
mgmt_index_removed(hdev); mgmt_index_removed(hdev);
hci_unregister_suspend_notifier(hdev);
err = hci_dev_open(hdev->id); err = hci_dev_open(hdev->id);
if (err) { if (err) {
...@@ -1223,6 +1231,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, ...@@ -1223,6 +1231,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
err = 0; err = 0;
} else { } else {
hci_dev_clear_flag(hdev, HCI_USER_CHANNEL); hci_dev_clear_flag(hdev, HCI_USER_CHANNEL);
hci_register_suspend_notifier(hdev);
mgmt_index_added(hdev); mgmt_index_added(hdev);
hci_dev_put(hdev); hci_dev_put(hdev);
goto done; goto done;
......
This diff is collapsed.
This diff is collapsed.
...@@ -1369,6 +1369,7 @@ static void l2cap_le_connect(struct l2cap_chan *chan) ...@@ -1369,6 +1369,7 @@ static void l2cap_le_connect(struct l2cap_chan *chan)
l2cap_le_flowctl_init(chan, 0); l2cap_le_flowctl_init(chan, 0);
memset(&req, 0, sizeof(req));
req.psm = chan->psm; req.psm = chan->psm;
req.scid = cpu_to_le16(chan->scid); req.scid = cpu_to_le16(chan->scid);
req.mtu = cpu_to_le16(chan->imtu); req.mtu = cpu_to_le16(chan->imtu);
......
...@@ -135,6 +135,77 @@ int bt_to_errno(__u16 code) ...@@ -135,6 +135,77 @@ int bt_to_errno(__u16 code)
} }
EXPORT_SYMBOL(bt_to_errno); EXPORT_SYMBOL(bt_to_errno);
/* Unix errno to Bluetooth error codes mapping */
__u8 bt_status(int err)
{
/* Don't convert if already positive value */
if (err >= 0)
return err;
switch (err) {
case -EBADRQC:
return 0x01;
case -ENOTCONN:
return 0x02;
case -EIO:
return 0x03;
case -EHOSTDOWN:
return 0x04;
case -EACCES:
return 0x05;
case -EBADE:
return 0x06;
case -ENOMEM:
return 0x07;
case -ETIMEDOUT:
return 0x08;
case -EMLINK:
return 0x09;
case EALREADY:
return 0x0b;
case -EBUSY:
return 0x0c;
case -ECONNREFUSED:
return 0x0d;
case -EOPNOTSUPP:
return 0x11;
case -EINVAL:
return 0x12;
case -ECONNRESET:
return 0x13;
case -ECONNABORTED:
return 0x16;
case ELOOP:
return 0x17;
case -EPROTONOSUPPORT:
return 0x1a;
case -EPROTO:
return 0x19;
default:
return 0x1f;
}
}
EXPORT_SYMBOL(bt_status);
void bt_info(const char *format, ...) void bt_info(const char *format, ...)
{ {
struct va_format vaf; struct va_format vaf;
......
This diff is collapsed.
This diff is collapsed.
...@@ -20,8 +20,7 @@ void msft_do_close(struct hci_dev *hdev); ...@@ -20,8 +20,7 @@ void msft_do_close(struct hci_dev *hdev);
void msft_vendor_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb); void msft_vendor_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb);
__u64 msft_get_features(struct hci_dev *hdev); __u64 msft_get_features(struct hci_dev *hdev);
int msft_add_monitor_pattern(struct hci_dev *hdev, struct adv_monitor *monitor); int msft_add_monitor_pattern(struct hci_dev *hdev, struct adv_monitor *monitor);
int msft_remove_monitor(struct hci_dev *hdev, struct adv_monitor *monitor, int msft_remove_monitor(struct hci_dev *hdev, struct adv_monitor *monitor);
u16 handle);
void msft_req_add_set_filter_enable(struct hci_request *req, bool enable); void msft_req_add_set_filter_enable(struct hci_request *req, bool enable);
int msft_set_filter_enable(struct hci_dev *hdev, bool enable); int msft_set_filter_enable(struct hci_dev *hdev, bool enable);
int msft_suspend_sync(struct hci_dev *hdev); int msft_suspend_sync(struct hci_dev *hdev);
...@@ -49,8 +48,7 @@ static inline int msft_add_monitor_pattern(struct hci_dev *hdev, ...@@ -49,8 +48,7 @@ static inline int msft_add_monitor_pattern(struct hci_dev *hdev,
} }
static inline int msft_remove_monitor(struct hci_dev *hdev, static inline int msft_remove_monitor(struct hci_dev *hdev,
struct adv_monitor *monitor, struct adv_monitor *monitor)
u16 handle)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment