text: /** @file
   *  @brief Bluetooth ISO handling
   */
  
  /*
   * Copyright (c) 2020 Intel Corporation
   *
   * SPDX-License-Identifier: Apache-2.0
   */
  #ifndef ZEPHYR_INCLUDE_BLUETOOTH_ISO_H_
  #define ZEPHYR_INCLUDE_BLUETOOTH_ISO_H_
  
  /**
   * @brief ISO
   * @defgroup bt_iso ISO
   * @ingroup bluetooth
   * @{
   */
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  #include <sys/atomic.h>
  #include <bluetooth/buf.h>
  #include <bluetooth/conn.h>
  #include <bluetooth/hci.h>
  
  /** @def BT_ISO_CHAN_SEND_RESERVE
   *  @brief Headroom needed for outgoing buffers
   */
  #define BT_ISO_CHAN_SEND_RESERVE (CONFIG_BT_HCI_RESERVE + \
  				  BT_HCI_ISO_HDR_SIZE + \
  				  BT_HCI_ISO_DATA_HDR_SIZE)
  
  /** Value to set the ISO data path over HCi. */
  #define BT_ISO_DATA_PATH_HCI     0x00
  
  struct bt_iso_chan;
  
  /** @brief Life-span states of ISO channel. Used only by internal APIs
   *  dealing with setting channel to proper state depending on operational
   *  context.
   */
  enum {
  	/** Channel disconnected */
  	BT_ISO_DISCONNECTED,
  	/** Channel bound to a connection */
  	BT_ISO_BOUND,
  	/** Channel in connecting state */
  	BT_ISO_CONNECT,
  	/** Channel ready for upper layer traffic on it */
  	BT_ISO_CONNECTED,
  	/** Channel in disconnecting state */
  	BT_ISO_DISCONNECT,
  };
  
  /** @brief ISO Channel structure. */
  struct bt_iso_chan {
  	/** Channel connection reference */
  	struct bt_conn			*conn;
  	/** Channel operations reference */
  	struct bt_iso_chan_ops		*ops;
  	/** Channel QoS reference */
  	struct bt_iso_chan_qos		*qos;
  	sys_snode_t			node;
  	uint8_t				state;
  	bt_security_t			required_sec_level;
  };
  
  /** @brief ISO Channel IO QoS structure. */
  struct bt_iso_chan_io_qos {
  	/** Channel interval in us. Value range 0x0000FF - 0x0FFFFFF. */
  	uint32_t			interval;
  	/** Channel Latency in ms. Value range 0x0005 - 0x0FA0. */
  	uint16_t			latency;
  	/** Channel SDU. Value range 0x0000 - 0x0FFF. */
  	uint16_t			sdu;
  	/** Channel PHY - See BT_GAP_LE_PHY for values.
  	 *  Setting BT_GAP_LE_PHY_NONE is invalid.
  	 */
  	uint8_t				phy;
  	/** Channel Retransmission Number. Value range 0x00 - 0x0F. */
  	uint8_t				rtn;
  	/** @brief Channel data path reference
  	 *
  	 *  Setting to NULL default to HCI data path (same as setting path.pid
  	 *  to BT_ISO_DATA_PATH_HCI).
  	 */
  	struct bt_iso_chan_path		*path;
  };
  
  /** @brief ISO Channel QoS structure. */
  struct bt_iso_chan_qos {
  	/** @brief Channel peripherals sleep clock accuracy Only for CIS
  	 *
  	 * Shall be worst case sleep clock accuracy of all the peripherals.
  	 * If unknown for the peripherals, this should be set to BT_GAP_SCA_UNKNOWN.
  	 */
  	uint8_t				sca;
  	/** Channel packing mode. 0 for unpacked, 1 for packed. */
  	uint8_t				packing;
  	/** Channel framing mode. 0 for unframed, 1 for framed. */
  	uint8_t				framing;
  	/** @brief Channel Receiving QoS.
  	 *
  	 *  Setting NULL disables data path BT_HCI_DATAPATH_DIR_CTLR_TO_HOST.
  	 *
  	 *  Can only be set for a connected isochronous channel, or a broadcast
  	 *  isochronous receiver.
  	 */
  	struct bt_iso_chan_io_qos	*rx;
  	/** @brief Channel Transmission QoS
  	 *
  	 *  Setting NULL disables data path BT_HCI_DATAPATH_DIR_HOST_TO_CTRL.
  	 *
  	 *  Can only be set for a connected isochronous channel, or a broadcast
  	 *  isochronous transmitter.
  	 */
  	struct bt_iso_chan_io_qos	*tx;
  };
  
  /** @brief ISO Channel Data Path structure. */
  struct bt_iso_chan_path {
  	/** Default path ID */
  	uint8_t				pid;
  	/** Coding Format */
  	uint8_t				format;
  	/** Company ID */
  	uint16_t			cid;
  	/** Vendor-defined Codec ID */
  	uint16_t			vid;
  	/** Controller Delay */
  	uint32_t			delay;
  	/** Codec Configuration length*/
  	uint8_t				cc_len;
  	/** Codec Configuration */
  	uint8_t				cc[0];
  };
  
  /** Opaque type representing an Broadcast Isochronous Group (BIG). */
  struct bt_iso_big;
  
  struct bt_iso_big_create_param {
  	/** Array of pointers to BIS channels */
  	struct bt_iso_chan **bis_channels;
  
  	/** Number channels in @p bis_channels */
  	uint8_t num_bis;
  
  	/** Whether or not to encrypt the streams. */
  	bool  encryption;
  
  	/** @brief Broadcast code
  	 *
  	 *  The code used to derive the session key that is used to encrypt and
  	 *  decrypt BIS payloads.
  	 */
  	uint8_t  bcode[16];
  };
  
  struct bt_iso_big_sync_param {
  	/** Array of pointers to BIS channels */
  	struct bt_iso_chan **bis_channels;
  
  	/** Number channels in @p bis_channels */
  	uint8_t num_bis;
  
  	/** Bitfield of the BISes to sync to */
  	uint32_t bis_bitfield;
  
  	/** @brief Maximum subevents
  	 *
  	 *  The MSE (Maximum Subevents) parameter is the maximum number of subevents that a
  	 *  Controller should use to receive data payloads in each interval for a BIS
  	 */
  	uint32_t mse;
  
  	/** Synchronization timeout for the BIG (N * 10 MS) */
  	uint16_t sync_timeout;
  
  	/** Whether or not the streams of the BIG are encrypted */
  	bool  encryption;
  
  	/** @brief Broadcast code
  	 *
  	 *  The code used to derive the session key that is used to encrypt and
  	 *  decrypt BIS payloads.
  	 */
  	uint8_t  bcode[16];
  };
  
  struct bt_iso_biginfo {
  	/** Address of the advertiser */
  	const bt_addr_le_t *addr;
  
  	/** Advertiser SID */
  	uint8_t sid;
  
  	/** Number of BISes in the BIG */
  	uint8_t  num_bis;
  
  	/** Maximum number of subevents in each isochronous event */
  	uint8_t  sub_evt_count;
  
  	/** Interval between two BIG anchor point (N * 1.25 ms) */
  	uint16_t iso_interval;
  
  	/** The number of new payloads in each BIS event */
  	uint8_t  burst_number;
  
  	/** Offset used for pre-transmissions */
  	uint8_t  offset;
  
  	/** The number of times a payload is transmitted in a BIS event */
  	uint8_t  rep_count;
  
  	/** Maximum size, in octets, of the payload */
  	uint16_t max_pdu;
  
  	/** The interval, in microseconds, of periodic SDUs. */
  	uint32_t sdu_interval;
  
  	/** Maximum size of an SDU, in octets. */
  	uint16_t max_sdu;
  
  	/** Channel PHY */
  	uint8_t  phy;
  
  	/** Channel framing mode */
  	uint8_t  framing;
  
  	/** Whether or not the BIG is encrypted */
  	bool  encryption;
  };
  
  /** @brief ISO Channel operations structure. */
  struct bt_iso_chan_ops {
  	/** @brief Channel connected callback
  	 *
  	 *  If this callback is provided it will be called whenever the
  	 *  connection completes.
  	 *
  	 *  @param chan The channel that has been connected
  	 */
  	void (*connected)(struct bt_iso_chan *chan);
  
  	/** @brief Channel disconnected callback
  	 *
  	 *  If this callback is provided it will be called whenever the
  	 *  channel is disconnected, including when a connection gets
  	 *  rejected.
  	 *
  	 *  @param chan   The channel that has been Disconnected
  	 *  @param reason HCI reason for the disconnection.
  	 */
  	void (*disconnected)(struct bt_iso_chan *chan, uint8_t reason);
  
  	/** @brief Channel alloc_buf callback
  	 *
  	 *  If this callback is provided the channel will use it to allocate
  	 *  buffers to store incoming data.
  	 *
  	 *  @param chan The channel requesting a buffer.
  	 *
  	 *  @return Allocated buffer.
  	 */
  	struct net_buf *(*alloc_buf)(struct bt_iso_chan *chan);
  
  	/** @brief Channel recv callback
  	 *
  	 *  @param chan The channel receiving data.
  	 *  @param buf Buffer containing incoming data.
  	 */
  	void (*recv)(struct bt_iso_chan *chan, struct net_buf *buf);
  };
  
  /** @brief ISO Server structure. */
  struct bt_iso_server {
  	/** Required minimim security level */
  	bt_security_t		sec_level;
  
  	/** @brief Server accept callback
  	 *
  	 *  This callback is called whenever a new incoming connection requires
  	 *  authorization.
  	 *
  	 *  @param conn The connection that is requesting authorization
  	 *  @param chan Pointer to receive the allocated channel
  	 *
  	 *  @return 0 in case of success or negative value in case of error.
  	 */
  	int (*accept)(struct bt_conn *conn, struct bt_iso_chan **chan);
  };
  
  /** @brief Register ISO server.
   *
   *  Register ISO server, each new connection is authorized using the accept()
   *  callback which in case of success shall allocate the channel structure
   *  to be used by the new connection.
   *
   *  @param server Server structure.
   *
   *  @return 0 in case of success or negative value in case of error.
   */
  int bt_iso_server_register(struct bt_iso_server *server);
  
  /** @brief Bind ISO channels
   *
   *  Bind ISO channels with existing ACL connections, Channel objects passed
   *  (over an address of it) shouldn't be instantiated in application as
   *  standalone.
   *
   *  @param conns Array of ACL connection objects
   *  @param num_conns Number of connection objects
   *  @param chans Array of ISO Channel objects to be created
   *
   *  @return 0 in case of success or negative value in case of error.
   */
  int bt_iso_chan_bind(struct bt_conn **conns, uint8_t num_conns,
  		     struct bt_iso_chan **chans);
  
  /** @brief Unbind ISO channel
   *
   *  Unbind ISO channel from ACL connection, channel must be in BT_ISO_BOUND
   *  state.
   *
   *  Note: Channels which the ACL connection has been disconnected are unbind
   *  automatically.
   *
   *  @param chan Channel object.
   *
   *  @return 0 in case of success or negative value in case of error.
   */
  int bt_iso_chan_unbind(struct bt_iso_chan *chan);
  
  /** @brief Connect ISO channels
   *
   *  Connect ISO channels, once the connection is completed each channel
   *  connected() callback will be called. If the connection is rejected
   *  disconnected() callback is called instead.
   *  Channel object passed (over an address of it) as second parameter shouldn't
   *  be instantiated in application as standalone.
   *
   *  @param chans Array of ISO channel objects
   *  @param num_chans Number of channel objects
   *
   *  @return 0 in case of success or negative value in case of error.
   */
  int bt_iso_chan_connect(struct bt_iso_chan **chans, uint8_t num_chans);
  
  /** @brief Disconnect ISO channel
   *
   *  Disconnect ISO channel, if the connection is pending it will be
   *  canceled and as a result the channel disconnected() callback is called.
   *  Regarding to input parameter, to get details see reference description
   *  to bt_iso_chan_connect() API above.
   *
   *  @param chan Channel object.
   *
   *  @return 0 in case of success or negative value in case of error.
   */
  int bt_iso_chan_disconnect(struct bt_iso_chan *chan);
  
  /** @brief Send data to ISO channel
   *
   *  Send data from buffer to the channel. If credits are not available, buf will
   *  be queued and sent as and when credits are received from peer.
   *  Regarding to first input parameter, to get details see reference description
   *  to bt_iso_chan_connect() API above.
   *
   *  @note Buffer ownership is transferred to the stack in case of success, in
   *  case of an error the caller retains the ownership of the buffer.
   *
   *  @param chan Channel object.
   *  @param buf Buffer containing data to be sent.
   *
   *  @return Bytes sent in case of success or negative value in case of error.
   */
  int bt_iso_chan_send(struct bt_iso_chan *chan, struct net_buf *buf);
  
  /** @brief Creates a BIG as a broadcaster
   *
   *  @param[in] padv      Pointer to the periodic advertising object the BIGInfo shall be sent on.
   *  @param[in] param     The parameters used to create and enable the BIG. The QOS parameters are
   *                       determined by the QOS field of the first BIS in the BIS list of this
   *                       parameter.
   *  @param[out] out_big  Broadcast Isochronous Group object on success.
   *
   *  @return 0 in case of success or negative value in case of error.
   */
  int bt_iso_big_create(struct bt_le_ext_adv *padv, struct bt_iso_big_create_param *param,
  		      struct bt_iso_big **out_big);
  
  /** @brief Terminates a BIG as a broadcaster or receiver
   *
   *  @param big    Pointer to the BIG structure.
   *
   *  @return 0 in case of success or negative value in case of error.
   */
  int bt_iso_big_terminate(struct bt_iso_big *big);
  
  /** @brief Creates a BIG as a receiver
   *
   *  @param[in] sync     Pointer to the periodic advertising sync object the BIGInfo was received on.
   *  @param[in] param    The parameters used to create and enable the BIG sync.
   *  @param[out] out_big Broadcast Isochronous Group object on success.
   *
   *  @return 0 in case of success or negative value in case of error.
   */
  int bt_iso_big_sync(struct bt_le_per_adv_sync *sync, struct bt_iso_big_sync_param *param,
  		    struct bt_iso_big **out_big);
  
  #ifdef __cplusplus
  }
  #endif
  
  /**
   * @}
   */
  
  #endif /* ZEPHYR_INCLUDE_BLUETOOTH_ISO_H_ */
  