/* lock hcill state */
spin_lock_irqsave(&ll->hcill_lock, flags);
switch (ll->hcill_state) { case HCILL_ASLEEP_TO_AWAKE: /* *ThisstatemeansthatboththehostandtheBRFchip *havesimultaneouslysentawake-up-indicationpacket. *Traditionally,inthiscase,receivingawake-up-indication *wasenoughandanadditionalwake-up-ackwasn'tneeded. *ThishaschangedwiththeBRF6350,whichdoesrequirean *explicitwake-up-ack.OtherBRFversions,whichdonot *requireanexplicitackhere,doacceptit,thusitis *perfectlysafetoalwayssendone.
*/
BT_DBG("dual wake-up-indication");
fallthrough; case HCILL_ASLEEP: /* acknowledge device wake up */ if (send_hcill_cmd(HCILL_WAKE_UP_ACK, hu) < 0) {
BT_ERR("cannot acknowledge device wake up"); goto out;
} break; default: /* any other state is illegal */
BT_ERR("received HCILL_WAKE_UP_IND in state %ld",
ll->hcill_state); break;
}
/* send pending packets and change state to HCILL_AWAKE */
__ll_do_awake(ll);
/* lock hcill state */
spin_lock_irqsave(&ll->hcill_lock, flags);
/* sanity check */ if (ll->hcill_state != HCILL_ASLEEP_TO_AWAKE)
BT_ERR("received HCILL_WAKE_UP_ACK in state %ld",
ll->hcill_state);
/* send pending packets and change state to HCILL_AWAKE */
__ll_do_awake(ll);
spin_unlock_irqrestore(&ll->hcill_lock, flags);
/* actually send the packets */
hci_uart_tx_wakeup(hu);
}
/* Enqueue frame for transmission (padding, crc, etc) */ /* may be called from two simultaneous tasklets */ staticint ll_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{ unsignedlong flags = 0; struct ll_struct *ll = hu->priv;
BT_DBG("hu %p skb %p", hu, skb);
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
/* lock hcill state */
spin_lock_irqsave(&ll->hcill_lock, flags);
/* act according to current state */ switch (ll->hcill_state) { case HCILL_AWAKE:
BT_DBG("device awake, sending normally");
skb_queue_tail(&ll->txq, skb); break; case HCILL_ASLEEP:
BT_DBG("device asleep, waking up and queueing packet"); /* save packet for later */
skb_queue_tail(&ll->tx_wait_q, skb); /* awake device */ if (send_hcill_cmd(HCILL_WAKE_UP_IND, hu) < 0) {
BT_ERR("cannot wake up device"); break;
}
ll->hcill_state = HCILL_ASLEEP_TO_AWAKE; break; case HCILL_ASLEEP_TO_AWAKE:
BT_DBG("device waking up, queueing packet"); /* transient state; just keep packet for later */
skb_queue_tail(&ll->tx_wait_q, skb); break; default:
BT_ERR("illegal hcill state: %ld (losing packet)",
ll->hcill_state);
dev_kfree_skb_irq(skb); break;
}
do { /* Reset the Bluetooth device */
gpiod_set_value_cansleep(lldev->enable_gpio, 0);
msleep(5);
gpiod_set_value_cansleep(lldev->enable_gpio, 1);
mdelay(100);
err = serdev_device_wait_for_cts(serdev, true, 200); if (err) {
bt_dev_err(hu->hdev, "Failed to get CTS"); return err;
}
err = download_firmware(lldev); if (!err) break;
/* Toggle BT_EN and retry */
bt_dev_err(hu->hdev, "download firmware failed, retrying...");
} while (retry--);
if (err) return err;
/* Set BD address if one was specified at probe */ if (!bacmp(&lldev->bdaddr, BDADDR_NONE)) { /* This means that there was an error getting the BD address *duringprobe,somarkthedeviceashavingabadaddress.
*/
hci_set_quirk(hu->hdev, HCI_QUIRK_INVALID_BDADDR);
} elseif (bacmp(&lldev->bdaddr, BDADDR_ANY)) {
err = ll_set_bdaddr(hu->hdev, &lldev->bdaddr); if (err)
hci_set_quirk(hu->hdev, HCI_QUIRK_INVALID_BDADDR);
}
/* Operational speed if any */ if (hu->oper_speed)
speed = hu->oper_speed; elseif (hu->proto->oper_speed)
speed = hu->proto->oper_speed; else
speed = 0;
if (speed) {
__le32 speed_le = cpu_to_le32(speed); struct sk_buff *skb;
/* optional BD address from nvram */
bdaddr_cell = nvmem_cell_get(&serdev->dev, "bd-address"); if (IS_ERR(bdaddr_cell)) { int err = PTR_ERR(bdaddr_cell);
if (err == -EPROBE_DEFER) return err;
/* ENOENT means there is no matching nvmem cell and ENOSYS *meansthatnvmemisnotenabledinthekernelconfiguration.
*/ if (err != -ENOENT && err != -ENOSYS) { /* If there was some other error, give userspace a *chancetofixtheprobleminsteadoffailingtoload *thedriver.UsingBDADDR_NONEasaflagthatis *testedlaterinthesetupfunction.
*/
dev_warn(&serdev->dev, "Failed to get \"bd-address\" nvmem cell (%d)\n",
err);
bacpy(&lldev->bdaddr, BDADDR_NONE);
}
} else {
bdaddr_t *bdaddr;
size_t len;
/* As per the device tree bindings, the value from nvmem is *expectedtobeMSBfirst,butinthekernelitisexpected *thatbdaddr_tisLSBfirst.
*/
baswap(&lldev->bdaddr, bdaddr);
kfree(bdaddr);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.