294 lines
6.3 KiB
C
294 lines
6.3 KiB
C
/*
|
|
Copyright (c) 2010-2012 The Linux Foundation. All rights reserved.
|
|
|
|
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
|
|
|
|
/* AMP defaults */
|
|
|
|
#define A2MP_RSP_TIMEOUT (8000) /* 8 seconds */
|
|
|
|
/* A2MP Protocol */
|
|
|
|
/* A2MP command codes */
|
|
#define A2MP_COMMAND_REJ 0x01
|
|
#define A2MP_DISCOVER_REQ 0x02
|
|
#define A2MP_DISCOVER_RSP 0x03
|
|
#define A2MP_CHANGE_NOTIFY 0x04
|
|
#define A2MP_CHANGE_RSP 0x05
|
|
#define A2MP_GETINFO_REQ 0x06
|
|
#define A2MP_GETINFO_RSP 0x07
|
|
#define A2MP_GETAMPASSOC_REQ 0x08
|
|
#define A2MP_GETAMPASSOC_RSP 0x09
|
|
#define A2MP_CREATEPHYSLINK_REQ 0x0A
|
|
#define A2MP_CREATEPHYSLINK_RSP 0x0B
|
|
#define A2MP_DISCONNPHYSLINK_REQ 0x0C
|
|
#define A2MP_DISCONNPHYSLINK_RSP 0x0D
|
|
|
|
struct a2mp_cmd_hdr {
|
|
__u8 code;
|
|
__u8 ident;
|
|
__le16 len;
|
|
} __packed;
|
|
|
|
struct a2mp_cmd_rej {
|
|
__le16 reason;
|
|
} __packed;
|
|
|
|
struct a2mp_discover_req {
|
|
__le16 mtu;
|
|
__le16 ext_feat;
|
|
} __packed;
|
|
|
|
struct a2mp_cl {
|
|
__u8 id;
|
|
__u8 type;
|
|
__u8 status;
|
|
} __packed;
|
|
|
|
struct a2mp_discover_rsp {
|
|
__le16 mtu;
|
|
__le16 ext_feat;
|
|
struct a2mp_cl cl[0];
|
|
} __packed;
|
|
|
|
struct a2mp_getinfo_req {
|
|
__u8 id;
|
|
} __packed;
|
|
|
|
struct a2mp_getinfo_rsp {
|
|
__u8 id;
|
|
__u8 status;
|
|
__le32 total_bw;
|
|
__le32 max_bw;
|
|
__le32 min_latency;
|
|
__le16 pal_cap;
|
|
__le16 assoc_size;
|
|
} __packed;
|
|
|
|
struct a2mp_getampassoc_req {
|
|
__u8 id;
|
|
} __packed;
|
|
|
|
struct a2mp_getampassoc_rsp {
|
|
__u8 id;
|
|
__u8 status;
|
|
__u8 amp_assoc[0];
|
|
} __packed;
|
|
|
|
struct a2mp_createphyslink_req {
|
|
__u8 local_id;
|
|
__u8 remote_id;
|
|
__u8 amp_assoc[0];
|
|
} __packed;
|
|
|
|
struct a2mp_createphyslink_rsp {
|
|
__u8 local_id;
|
|
__u8 remote_id;
|
|
__u8 status;
|
|
} __packed;
|
|
|
|
struct a2mp_disconnphyslink_req {
|
|
__u8 local_id;
|
|
__u8 remote_id;
|
|
} __packed;
|
|
|
|
struct a2mp_disconnphyslink_rsp {
|
|
__u8 local_id;
|
|
__u8 remote_id;
|
|
__u8 status;
|
|
} __packed;
|
|
|
|
|
|
/* L2CAP-AMP module interface */
|
|
int amp_init(void);
|
|
void amp_exit(void);
|
|
|
|
/* L2CAP-AMP fixed channel interface */
|
|
void amp_conn_ind(struct hci_conn *hcon, struct sk_buff *skb);
|
|
|
|
/* L2CAP-AMP link interface */
|
|
void amp_create_physical(struct l2cap_conn *conn, struct sock *sk);
|
|
void amp_accept_physical(struct l2cap_conn *conn, u8 id, struct sock *sk);
|
|
|
|
/* AMP manager internals */
|
|
struct amp_ctrl {
|
|
struct amp_mgr *mgr;
|
|
__u8 id;
|
|
__u8 type;
|
|
__u8 status;
|
|
__u32 total_bw;
|
|
__u32 max_bw;
|
|
__u32 min_latency;
|
|
__u16 pal_cap;
|
|
__u16 max_assoc_size;
|
|
};
|
|
|
|
struct amp_mgr {
|
|
struct list_head list;
|
|
__u8 discovered;
|
|
__u8 next_ident;
|
|
struct l2cap_conn *l2cap_conn;
|
|
struct socket *a2mp_sock;
|
|
struct list_head ctx_list;
|
|
rwlock_t ctx_list_lock;
|
|
struct amp_ctrl *ctrls; /* @@ TODO s.b. list of controllers */
|
|
struct sk_buff *skb;
|
|
__u8 connected;
|
|
};
|
|
|
|
/* AMP Manager signalling contexts */
|
|
#define AMP_GETAMPASSOC 1
|
|
#define AMP_CREATEPHYSLINK 2
|
|
#define AMP_ACCEPTPHYSLINK 3
|
|
#define AMP_CREATELOGLINK 4
|
|
#define AMP_ACCEPTLOGLINK 5
|
|
|
|
/* Get AMP Assoc sequence */
|
|
#define AMP_GAA_INIT 0
|
|
#define AMP_GAA_RLAA_COMPLETE 1
|
|
struct amp_gaa_state {
|
|
__u8 req_ident;
|
|
__u16 len_so_far;
|
|
__u8 *assoc;
|
|
};
|
|
|
|
/* Create Physical Link sequence */
|
|
#define AMP_CPL_INIT 0
|
|
#define AMP_CPL_DISC_RSP 1
|
|
#define AMP_CPL_GETINFO_RSP 2
|
|
#define AMP_CPL_GAA_RSP 3
|
|
#define AMP_CPL_CPL_STATUS 4
|
|
#define AMP_CPL_WRA_COMPLETE 5
|
|
#define AMP_CPL_CHANNEL_SELECT 6
|
|
#define AMP_CPL_RLA_COMPLETE 7
|
|
#define AMP_CPL_PL_COMPLETE 8
|
|
#define AMP_CPL_PL_CANCEL 9
|
|
struct amp_cpl_state {
|
|
__u8 remote_id;
|
|
__u16 max_len;
|
|
__u8 *remote_assoc;
|
|
__u8 *local_assoc;
|
|
__u16 len_so_far;
|
|
__u16 rem_len;
|
|
__u8 phy_handle;
|
|
};
|
|
|
|
/* Accept Physical Link sequence */
|
|
#define AMP_APL_INIT 0
|
|
#define AMP_APL_APL_STATUS 1
|
|
#define AMP_APL_WRA_COMPLETE 2
|
|
#define AMP_APL_PL_COMPLETE 3
|
|
struct amp_apl_state {
|
|
__u8 remote_id;
|
|
__u8 req_ident;
|
|
__u8 *remote_assoc;
|
|
__u16 len_so_far;
|
|
__u16 rem_len;
|
|
__u8 phy_handle;
|
|
};
|
|
|
|
/* Create/Accept Logical Link sequence */
|
|
#define AMP_LOG_INIT 0
|
|
#define AMP_LOG_LL_STATUS 1
|
|
#define AMP_LOG_LL_COMPLETE 2
|
|
struct amp_log_state {
|
|
__u8 remote_id;
|
|
};
|
|
|
|
/* Possible event types a context may wait for */
|
|
#define AMP_INIT 0x01
|
|
#define AMP_HCI_EVENT 0x02
|
|
#define AMP_HCI_CMD_CMPLT 0x04
|
|
#define AMP_HCI_CMD_STATUS 0x08
|
|
#define AMP_A2MP_RSP 0x10
|
|
#define AMP_KILLED 0x20
|
|
#define AMP_CANCEL 0x40
|
|
struct amp_ctx {
|
|
struct list_head list;
|
|
struct amp_mgr *mgr;
|
|
struct hci_dev *hdev;
|
|
__u8 type;
|
|
__u8 state;
|
|
union {
|
|
struct amp_gaa_state gaa;
|
|
struct amp_cpl_state cpl;
|
|
struct amp_apl_state apl;
|
|
} d;
|
|
__u8 evt_type;
|
|
__u8 evt_code;
|
|
__u16 opcode;
|
|
__u8 id;
|
|
__u8 rsp_ident;
|
|
|
|
struct sock *sk;
|
|
struct amp_ctx *deferred;
|
|
struct timer_list timer;
|
|
};
|
|
|
|
/* AMP work */
|
|
struct amp_work_pl_timeout {
|
|
struct work_struct work;
|
|
struct amp_ctrl *ctrl;
|
|
};
|
|
struct amp_work_ctx_timeout {
|
|
struct work_struct work;
|
|
struct amp_ctx *ctx;
|
|
};
|
|
struct amp_work_data_ready {
|
|
struct work_struct work;
|
|
struct sock *sk;
|
|
int bytes;
|
|
};
|
|
struct amp_work_state_change {
|
|
struct work_struct work;
|
|
struct sock *sk;
|
|
};
|
|
struct amp_work_conn_ind {
|
|
struct work_struct work;
|
|
struct hci_conn *hcon;
|
|
struct sk_buff *skb;
|
|
};
|
|
struct amp_work_create_physical {
|
|
struct work_struct work;
|
|
struct l2cap_conn *conn;
|
|
u8 id;
|
|
struct sock *sk;
|
|
};
|
|
struct amp_work_accept_physical {
|
|
struct work_struct work;
|
|
struct l2cap_conn *conn;
|
|
u8 id;
|
|
struct sock *sk;
|
|
};
|
|
struct amp_work_cmd_cmplt {
|
|
struct work_struct work;
|
|
struct hci_dev *hdev;
|
|
u16 opcode;
|
|
struct sk_buff *skb;
|
|
};
|
|
struct amp_work_cmd_status {
|
|
struct work_struct work;
|
|
struct hci_dev *hdev;
|
|
u16 opcode;
|
|
u8 status;
|
|
};
|
|
struct amp_work_event {
|
|
struct work_struct work;
|
|
struct hci_dev *hdev;
|
|
u8 event;
|
|
struct sk_buff *skb;
|
|
};
|
|
|
|
#endif /* __AMP_H */
|