Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc27d5f1 authored by John W. Linville's avatar John W. Linville
Browse files
parents ddffeb8c f706adfe
Loading
Loading
Loading
Loading
+17 −11
Original line number Diff line number Diff line
@@ -492,7 +492,7 @@ done:
static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
{
	u16 buf_len = 0;
	int ret, buf_block_len, blksz;
	int ret, num_blocks, blksz;
	struct sk_buff *skb = NULL;
	u32 type;
	u8 *payload = NULL;
@@ -514,18 +514,17 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
	}

	blksz = SDIO_BLOCK_SIZE;
	buf_block_len = (buf_len + blksz - 1) / blksz;
	num_blocks = DIV_ROUND_UP(buf_len, blksz);

	if (buf_len <= SDIO_HEADER_LEN
			|| (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
	    || (num_blocks * blksz) > ALLOC_BUF_SIZE) {
		BT_ERR("invalid packet length: %d", buf_len);
		ret = -EINVAL;
		goto exit;
	}

	/* Allocate buffer */
	skb = bt_skb_alloc(buf_block_len * blksz + BTSDIO_DMA_ALIGN,
								GFP_ATOMIC);
	skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC);
	if (skb == NULL) {
		BT_ERR("No free skb");
		goto exit;
@@ -541,7 +540,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
	payload = skb->data;

	ret = sdio_readsb(card->func, payload, card->ioport,
			  buf_block_len * blksz);
			  num_blocks * blksz);
	if (ret < 0) {
		BT_ERR("readsb failed: %d", ret);
		ret = -EIO;
@@ -553,7 +552,16 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
	 */

	buf_len = payload[0];
	buf_len |= (u16) payload[1] << 8;
	buf_len |= payload[1] << 8;
	buf_len |= payload[2] << 16;

	if (buf_len > blksz * num_blocks) {
		BT_ERR("Skip incorrect packet: hdrlen %d buffer %d",
		       buf_len, blksz * num_blocks);
		ret = -EIO;
		goto exit;
	}

	type = payload[3];

	switch (type) {
@@ -589,8 +597,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)

	default:
		BT_ERR("Unknown packet type:%d", type);
		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload,
						blksz * buf_block_len);
		BT_ERR("hex: %*ph", blksz * num_blocks, payload);

		kfree_skb(skb);
		skb = NULL;
@@ -849,8 +856,7 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
		if (ret < 0) {
			i++;
			BT_ERR("i=%d writesb failed: %d", i, ret);
			print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
						payload, nb);
			BT_ERR("hex: %*ph", nb, payload);
			ret = -EIO;
			if (i > MAX_WRITE_IOMEM_RETRY)
				goto exit;
+23 −1
Original line number Diff line number Diff line
@@ -19,13 +19,25 @@

#define A2MP_FEAT_EXT	0x8000

enum amp_mgr_state {
	READ_LOC_AMP_INFO,
	READ_LOC_AMP_ASSOC,
	READ_LOC_AMP_ASSOC_FINAL,
};

struct amp_mgr {
	struct list_head	list;
	struct l2cap_conn	*l2cap_conn;
	struct l2cap_chan	*a2mp_chan;
	struct l2cap_chan	*bredr_chan;
	struct kref		kref;
	__u8			ident;
	__u8			handle;
	enum amp_mgr_state	state;
	unsigned long		flags;

	struct list_head	amp_ctrls;
	struct mutex		amp_ctrls_lock;
};

struct a2mp_cmd {
@@ -118,9 +130,19 @@ struct a2mp_physlink_rsp {
#define A2MP_STATUS_PHYS_LINK_EXISTS		0x05
#define A2MP_STATUS_SECURITY_VIOLATION		0x06

void amp_mgr_get(struct amp_mgr *mgr);
extern struct list_head amp_mgr_list;
extern struct mutex amp_mgr_list_lock;

struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr);
int amp_mgr_put(struct amp_mgr *mgr);
u8 __next_ident(struct amp_mgr *mgr);
struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
				       struct sk_buff *skb);
struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
void a2mp_discover_amp(struct l2cap_chan *chan);
void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status);
void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status);

#endif /* __A2MP_H */
+50 −0
Original line number Diff line number Diff line
/*
   Copyright (c) 2011,2012 Intel Corp.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 2 and
   only version 2 as published by the Free Software Foundation.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
*/

#ifndef __AMP_H
#define __AMP_H

struct amp_ctrl {
	struct list_head	list;
	struct kref		kref;
	__u8			id;
	__u16			assoc_len_so_far;
	__u16			assoc_rem_len;
	__u16			assoc_len;
	__u8			*assoc;
};

int amp_ctrl_put(struct amp_ctrl *ctrl);
void amp_ctrl_get(struct amp_ctrl *ctrl);
struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id);
struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id);
void amp_ctrl_list_flush(struct amp_mgr *mgr);

struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
			     u8 remote_id, bool out);

int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type);

void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr);
void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
				   struct hci_conn *hcon);
void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
			struct hci_conn *hcon);
void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
			struct hci_conn *hcon);
void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle);
void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle);

#endif /* __AMP_H */
+0 −1
Original line number Diff line number Diff line
@@ -180,7 +180,6 @@ static inline void bacpy(bdaddr_t *dst, bdaddr_t *src)
}

void baswap(bdaddr_t *dst, bdaddr_t *src);
char *batostr(bdaddr_t *ba);

/* Common socket structures and functions */

+39 −1
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@
#define HCI_LINK_KEY_SIZE	16
#define HCI_AMP_LINK_KEY_SIZE	(2 * HCI_LINK_KEY_SIZE)

#define HCI_MAX_AMP_ASSOC_SIZE	672

/* HCI dev events */
#define HCI_DEV_REG			1
#define HCI_DEV_UNREG			2
@@ -196,6 +198,7 @@ enum {
#define ACL_START_NO_FLUSH	0x00
#define ACL_CONT		0x01
#define ACL_START		0x02
#define ACL_COMPLETE		0x03
#define ACL_ACTIVE_BCAST	0x04
#define ACL_PICO_BCAST		0x08

@@ -205,6 +208,7 @@ enum {
#define ESCO_LINK	0x02
/* Low Energy links do not have defined link type. Use invented one */
#define LE_LINK		0x80
#define AMP_LINK	0x81

/* LMP features */
#define LMP_3SLOT	0x01
@@ -562,6 +566,40 @@ struct hci_cp_disconn_phy_link {
	__u8     reason;
} __packed;

struct ext_flow_spec {
	__u8       id;
	__u8       stype;
	__le16     msdu;
	__le32     sdu_itime;
	__le32     acc_lat;
	__le32     flush_to;
} __packed;

#define HCI_OP_CREATE_LOGICAL_LINK	0x0438
#define HCI_OP_ACCEPT_LOGICAL_LINK	0x0439
struct hci_cp_create_accept_logical_link {
	__u8                  phy_handle;
	struct ext_flow_spec  tx_flow_spec;
	struct ext_flow_spec  rx_flow_spec;
} __packed;

#define HCI_OP_DISCONN_LOGICAL_LINK	0x043a
struct hci_cp_disconn_logical_link {
	__le16   log_handle;
} __packed;

#define HCI_OP_LOGICAL_LINK_CANCEL	0x043b
struct hci_cp_logical_link_cancel {
	__u8     phy_handle;
	__u8     flow_spec_id;
} __packed;

struct hci_rp_logical_link_cancel {
	__u8     status;
	__u8     phy_handle;
	__u8     flow_spec_id;
} __packed;

#define HCI_OP_SNIFF_MODE		0x0803
struct hci_cp_sniff_mode {
	__le16   handle;
Loading