Exemple #1
0
static int hci_uart_setup(struct hci_dev *hdev)
{
	struct hci_uart *hu = hci_get_drvdata(hdev);
	struct hci_rp_read_local_version *ver;
	struct sk_buff *skb;
	unsigned int speed;
	int err;

	/* Init speed if any */
	if (hu->init_speed)
		speed = hu->init_speed;
	else if (hu->proto->init_speed)
		speed = hu->proto->init_speed;
	else
		speed = 0;

	if (speed)
		serdev_device_set_baudrate(hu->serdev, speed);

	/* Operational speed if any */
	if (hu->oper_speed)
		speed = hu->oper_speed;
	else if (hu->proto->oper_speed)
		speed = hu->proto->oper_speed;
	else
		speed = 0;

	if (hu->proto->set_baudrate && speed) {
		err = hu->proto->set_baudrate(hu, speed);
		if (err)
			BT_ERR("%s: failed to set baudrate", hdev->name);
		else
			serdev_device_set_baudrate(hu->serdev, speed);
	}

	if (hu->proto->setup)
		return hu->proto->setup(hu);

	if (!test_bit(HCI_UART_VND_DETECT, &hu->hdev_flags))
		return 0;

	skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
			     HCI_INIT_TIMEOUT);
	if (IS_ERR(skb)) {
		BT_ERR("%s: Reading local version information failed (%ld)",
		       hdev->name, PTR_ERR(skb));
		return 0;
	}

	if (skb->len != sizeof(*ver)) {
		BT_ERR("%s: Event length mismatch for version information",
		       hdev->name);
	}

	kfree_skb(skb);
	return 0;
}
Exemple #2
0
static int sirf_open(struct gnss_device *gdev)
{
	struct sirf_data *data = gnss_get_drvdata(gdev);
	struct serdev_device *serdev = data->serdev;
	int ret;

	ret = serdev_device_open(serdev);
	if (ret)
		return ret;

	serdev_device_set_baudrate(serdev, data->speed);
	serdev_device_set_flow_control(serdev, false);

	ret = pm_runtime_get_sync(&serdev->dev);
	if (ret < 0) {
		dev_err(&gdev->dev, "failed to runtime resume: %d\n", ret);
		pm_runtime_put_noidle(&serdev->dev);
		goto err_close;
	}

	return 0;

err_close:
	serdev_device_close(serdev);

	return ret;
}
Exemple #3
0
static inline void host_set_baudrate(struct hci_uart *hu, unsigned int speed)
{
	if (hu->serdev)
		serdev_device_set_baudrate(hu->serdev, speed);
	else
		hci_uart_set_baudrate(hu, speed);
}
Exemple #4
0
static int nokia_reset(struct hci_uart *hu)
{
	struct nokia_bt_dev *btdev = hu->priv;
	struct device *dev = &btdev->serdev->dev;
	int err;

	/* reset routine */
	gpiod_set_value_cansleep(btdev->reset, 1);
	gpiod_set_value_cansleep(btdev->wakeup_bt, 1);

	msleep(100);

	/* safety check */
	err = gpiod_get_value_cansleep(btdev->wakeup_host);
	if (err == 1) {
		dev_err(dev, "reset: host wakeup not low!");
		return -EPROTO;
	}

	/* flush queue */
	serdev_device_write_flush(btdev->serdev);

	/* init uart */
	nokia_flow_control(btdev->serdev, false);
	serdev_device_set_baudrate(btdev->serdev, INIT_BAUD_RATE);

	gpiod_set_value_cansleep(btdev->reset, 0);

	/* wait for cts */
	err = serdev_device_wait_for_cts(btdev->serdev, true, 200);
	if (err < 0) {
		dev_err(dev, "CTS not received: %d", err);
		return err;
	}

	nokia_flow_control(btdev->serdev, true);

	return 0;
}
Exemple #5
0
static int nokia_setup(struct hci_uart *hu)
{
	struct nokia_bt_dev *btdev = hu->priv;
	struct device *dev = &btdev->serdev->dev;
	int err;

	btdev->initialized = false;

	nokia_flow_control(btdev->serdev, false);

	pm_runtime_get_sync(dev);

	if (btdev->tx_enabled) {
		gpiod_set_value_cansleep(btdev->wakeup_bt, 0);
		pm_runtime_put(&btdev->serdev->dev);
		btdev->tx_enabled = false;
	}

	dev_dbg(dev, "protocol setup");

	/* 0. reset connection */
	err = nokia_reset(hu);
	if (err < 0) {
		dev_err(dev, "Reset failed: %d", err);
		goto out;
	}

	/* 1. negotiate speed etc */
	err = nokia_send_negotiation(hu);
	if (err < 0) {
		dev_err(dev, "Negotiation failed: %d", err);
		goto out;
	}

	/* 2. verify correct setup using alive packet */
	err = nokia_send_alive_packet(hu);
	if (err < 0) {
		dev_err(dev, "Alive check failed: %d", err);
		goto out;
	}

	/* 3. send firmware */
	err = nokia_setup_fw(hu);
	if (err < 0) {
		dev_err(dev, "Could not setup FW: %d", err);
		goto out;
	}

	nokia_flow_control(btdev->serdev, false);
	serdev_device_set_baudrate(btdev->serdev, MAX_BAUD_RATE);
	nokia_flow_control(btdev->serdev, true);

	if (btdev->man_id == NOKIA_ID_BCM2048) {
		hu->hdev->set_bdaddr = btbcm_set_bdaddr;
		set_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks);
		dev_dbg(dev, "bcm2048 has invalid bluetooth address!");
	}

	dev_dbg(dev, "protocol setup done!");

	gpiod_set_value_cansleep(btdev->wakeup_bt, 0);
	pm_runtime_put(dev);
	btdev->tx_enabled = false;
	btdev->initialized = true;

	return 0;
out:
	pm_runtime_put(dev);

	return err;
}
Exemple #6
0
static int nokia_send_negotiation(struct hci_uart *hu)
{
	struct nokia_bt_dev *btdev = hu->priv;
	struct device *dev = &btdev->serdev->dev;
	struct hci_nokia_neg_cmd *neg_cmd;
	struct hci_nokia_neg_hdr *neg_hdr;
	struct sk_buff *skb;
	int len, err;
	u16 baud = DIV_ROUND_CLOSEST(btdev->sysclk_speed * 10, SETUP_BAUD_RATE);
	int sysclk = btdev->sysclk_speed / 1000;

	len = H4_TYPE_SIZE + sizeof(*neg_hdr) + sizeof(*neg_cmd);
	skb = bt_skb_alloc(len, GFP_KERNEL);
	if (!skb)
		return -ENOMEM;

	hci_skb_pkt_type(skb) = HCI_NOKIA_NEG_PKT;

	neg_hdr = skb_put(skb, sizeof(*neg_hdr));
	neg_hdr->dlen = sizeof(*neg_cmd);

	neg_cmd = skb_put(skb, sizeof(*neg_cmd));
	neg_cmd->ack = NOKIA_NEG_REQ;
	neg_cmd->baud = cpu_to_le16(baud);
	neg_cmd->unused1 = 0x0000;
	neg_cmd->proto = NOKIA_PROTO_BYTE;
	neg_cmd->sys_clk = cpu_to_le16(sysclk);
	neg_cmd->unused2 = 0x0000;

	btdev->init_error = 0;
	init_completion(&btdev->init_completion);

	nokia_enqueue(hu, skb);
	hci_uart_tx_wakeup(hu);

	dev_dbg(dev, "Negotiation sent");

	if (!wait_for_completion_interruptible_timeout(&btdev->init_completion,
		msecs_to_jiffies(10000))) {
		return -ETIMEDOUT;
	}

	if (btdev->init_error < 0)
		return btdev->init_error;

	/* Change to previously negotiated speed. Flow Control
	 * is disabled until bluetooth adapter is ready to avoid
	 * broken bytes being received.
	 */
	nokia_flow_control(btdev->serdev, false);
	serdev_device_set_baudrate(btdev->serdev, SETUP_BAUD_RATE);
	err = serdev_device_wait_for_cts(btdev->serdev, true, 200);
	if (err < 0) {
		dev_err(dev, "CTS not received: %d", err);
		return err;
	}
	nokia_flow_control(btdev->serdev, true);

	dev_dbg(dev, "Negotiation successful");

	return 0;
}