|  | /** @file | 
|  | *  @brief Audio Video Control Transport Protocol internal header. | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * Copyright (c) 2015-2016 Intel Corporation | 
|  | * Copyright (C) 2024 Xiaomi Corporation | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | typedef enum __packed { | 
|  | BT_AVCTP_IPID_NONE = 0b0, | 
|  | BT_AVCTP_IPID_INVALID = 0b1, | 
|  | } bt_avctp_ipid_t; | 
|  |  | 
|  | typedef enum __packed { | 
|  | BT_AVCTP_CMD = 0b0, | 
|  | BT_AVCTP_RESPONSE = 0b1, | 
|  | } bt_avctp_cr_t; | 
|  |  | 
|  | typedef enum __packed { | 
|  | BT_AVCTP_PKT_TYPE_SINGLE = 0b00, | 
|  | BT_AVCTP_PKT_TYPE_START = 0b01, | 
|  | BT_AVCTP_PKT_TYPE_CONTINUE = 0b10, | 
|  | BT_AVCTP_PKT_TYPE_END = 0b11, | 
|  | } bt_avctp_pkt_type_t; | 
|  |  | 
|  | struct bt_avctp_header_common { | 
|  | uint8_t byte0;  /** [7:4]: Transaction label, [3:2]: Packet_type, [1]: C/R, [0]: IPID */ | 
|  | } __packed; | 
|  |  | 
|  | struct bt_avctp_header_single { | 
|  | struct bt_avctp_header_common common; | 
|  | uint16_t pid; | 
|  | } __packed; | 
|  |  | 
|  | struct bt_avctp_header_start { | 
|  | struct bt_avctp_header_common common; | 
|  | uint8_t number_packet; | 
|  | uint16_t pid; | 
|  | } __packed; | 
|  |  | 
|  | struct bt_avctp_header_continue_end { | 
|  | struct bt_avctp_header_common common; | 
|  | } __packed; | 
|  |  | 
|  | /** Transaction label provided by the application and is replicated by the sender of the message in | 
|  | *  each packet of the sequence. It isused at the receiver side to identify packets that belong to | 
|  | *  the same message. | 
|  | */ | 
|  | #define BT_AVCTP_HDR_GET_TRANSACTION_LABLE(hdr) FIELD_GET(GENMASK(7, 4), ((hdr)->byte0)) | 
|  | /** Set to zero (00) to indicate that the command/response message is transmitted in a single L2CAP | 
|  | *  packet. Alternatively, set to (01) for start, (10) for continue, or (11) for end packet. | 
|  | */ | 
|  | #define BT_AVCTP_HDR_GET_PACKET_TYPE(hdr)       FIELD_GET(GENMASK(3, 2), ((hdr)->byte0)) | 
|  | /** Indicates whether the messageconveys a command frame (0) or a response frame (1). */ | 
|  | #define BT_AVCTP_HDR_GET_CR(hdr)                FIELD_GET(BIT(1), ((hdr)->byte0)) | 
|  | /** The IPID bit is set in a response message to indicate an invalid Profile Identifier received in | 
|  | *  the command message of the same transaction; otherwise this bit is set to zero. In command | 
|  | *  messages this bit is set to zero. This field is only present in the start packet of the message. | 
|  | */ | 
|  | #define BT_AVCTP_HDR_GET_IPID(hdr)              FIELD_GET(BIT(0), ((hdr)->byte0)) | 
|  |  | 
|  | /** Transaction label provided by the application and is replicated by the sender of the message in | 
|  | *  each packet of the sequence. It isused at the receiver side to identify packets that belong to | 
|  | *  the same message. | 
|  | */ | 
|  | #define BT_AVCTP_HDR_SET_TRANSACTION_LABLE(hdr, tl)                                                \ | 
|  | (hdr)->byte0 = (((hdr)->byte0) & ~GENMASK(7, 4)) | FIELD_PREP(GENMASK(7, 4), (tl)) | 
|  | /** Set to zero (00) to indicate that the command/response message is transmitted in a single L2CAP | 
|  | *  packet. Alternatively, set to (01) for start, (10) for continue, or (11) for end packet. | 
|  | */ | 
|  | #define BT_AVCTP_HDR_SET_PACKET_TYPE(hdr, packet_type)                                             \ | 
|  | (hdr)->byte0 = (((hdr)->byte0) & ~GENMASK(3, 2)) | FIELD_PREP(GENMASK(3, 2), (packet_type)) | 
|  | /** Indicates whether the messageconveys a command frame (0) or a response frame (1). */ | 
|  | #define BT_AVCTP_HDR_SET_CR(hdr, cr)                                                               \ | 
|  | (hdr)->byte0 = (((hdr)->byte0) & ~BIT(1)) | FIELD_PREP(BIT(1), (cr)) | 
|  | /** The IPID bit is set in a response message to indicate an invalid Profile Identifier received in | 
|  | *  the command message of the same transaction; otherwise this bit is set to zero. In command | 
|  | *  messages this bit is set to zero. This field is only present in the start packet of the message. | 
|  | */ | 
|  | #define BT_AVCTP_HDR_SET_IPID(hdr, ipid)                                                           \ | 
|  | (hdr)->byte0 = (((hdr)->byte0) & ~BIT(0)) | FIELD_PREP(BIT(0), (ipid)) | 
|  | /** Set all AVCTP header fields into the first octet. Packs the four fields (IPID, CR, TYPE, TID) | 
|  | *  into a single 8-bit header according to the AVRCP bit layout. | 
|  | */ | 
|  | #define BT_AVCTP_HDR_SET(hdr, ipid, cr, type, tid)                                                 \ | 
|  | (hdr)->byte0 = (FIELD_PREP(BIT(0), (ipid)) | FIELD_PREP(BIT(1), (cr)) |                    \ | 
|  | FIELD_PREP(GENMASK(3, 2), (type)) | FIELD_PREP(GENMASK(7, 4), (tid))) | 
|  |  | 
|  | struct bt_avctp; | 
|  |  | 
|  | struct bt_avctp_ops_cb { | 
|  | void (*connected)(struct bt_avctp *session); | 
|  | void (*disconnected)(struct bt_avctp *session); | 
|  | int (*recv)(struct bt_avctp *session, struct net_buf *buf, bt_avctp_cr_t cr, uint8_t tid); | 
|  | }; | 
|  |  | 
|  | struct bt_avctp { | 
|  | struct bt_l2cap_br_chan br_chan; | 
|  | const struct bt_avctp_ops_cb *ops; | 
|  | uint16_t pid;  /** Profile Identifier */ | 
|  | uint16_t max_tx_payload_size; | 
|  | struct net_buf_pool *tx_pool; | 
|  | struct net_buf_pool *rx_pool; | 
|  | struct net_buf *reassembly_buf; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * @brief AVCTP L2CAP Server structure | 
|  | * | 
|  | * This structure defines the L2CAP server used for AVCTP over L2CAP transport. | 
|  | */ | 
|  | struct bt_avctp_server { | 
|  | /** | 
|  | * @brief L2CAP server parameters | 
|  | * | 
|  | * This field is used to register the L2CAP server. The `psm` field can be set | 
|  | * to a specific value (not recommended), or set to 0 to allow automatic PSM | 
|  | * allocation during registration via @ref bt_avctp_server_register. | 
|  | * | 
|  | * The `sec_level` field specifies the minimum required security level. | 
|  | * | 
|  | * @note The `struct bt_l2cap_server::accept` callback of `l2cap` can not be used | 
|  | * by AVCTP applications. Instead, use the `struct bt_avctp_server::accept` | 
|  | * callback defined in this structure. | 
|  | */ | 
|  | struct bt_l2cap_server l2cap; | 
|  |  | 
|  | /** | 
|  | * @brief Accept callback for incoming AVCTP connections | 
|  | * | 
|  | * This callback is invoked when a new incoming AVCTP connection is received. | 
|  | * The application is responsible for authorizing the connection and allocating | 
|  | * a new AVCTP session object. | 
|  | * | 
|  | * @warning The caller must ensure that the parent object of the AVCTP session | 
|  | * is properly zero-initialized before use. | 
|  | * | 
|  | * @param conn   The Bluetooth connection requesting authorization. | 
|  | * @param session Pointer to receive the allocated AVCTP session object. | 
|  | * | 
|  | * @retval 0        Success. | 
|  | * @retval -ENOMEM  No available space for a new session. | 
|  | * @retval -EACCES  Connection not authorized by the application. | 
|  | * @retval -EPERM   Encryption key size is insufficient. | 
|  | */ | 
|  | int (*accept)(struct bt_conn *conn, struct bt_avctp **session); | 
|  |  | 
|  | /** @brief Internal node for list management */ | 
|  | sys_snode_t node; | 
|  | }; | 
|  |  | 
|  | struct bt_avctp_event_cb { | 
|  | int (*accept)(struct bt_conn *conn, struct bt_avctp **session); | 
|  | }; | 
|  |  | 
|  | /* Initialize AVCTP layer*/ | 
|  | int bt_avctp_init(void); | 
|  |  | 
|  | /* Application register with AVCTP layer */ | 
|  | int bt_avctp_server_register(struct bt_avctp_server *server); | 
|  |  | 
|  | /* AVCTP connect */ | 
|  | int bt_avctp_connect(struct bt_conn *conn, uint16_t psm, struct bt_avctp *session); | 
|  |  | 
|  | /* AVCTP disconnect */ | 
|  | int bt_avctp_disconnect(struct bt_avctp *session); | 
|  |  | 
|  | /* Create AVCTP PDU */ | 
|  | struct net_buf *bt_avctp_create_pdu(struct net_buf_pool *pool); | 
|  |  | 
|  | /* Send AVCTP PDU */ | 
|  | int bt_avctp_send(struct bt_avctp *session, struct net_buf *buf, bt_avctp_cr_t cr, uint8_t tid); |