/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2001-2002  Wayne Lee <waynelee@qualcomm.com>
 *  Copyright (C) 2003-2011  Marcel Holtmann <marcel@holtmann.org>
 *
 *
 */

#ifndef __RFCOMM_H
#define __RFCOMM_H

#include <endian.h>

#define RFCOMM_PSM 3

#define TRUE  1
#define FALSE 0

#define RFCOMM_MAX_CONN 10
#define BT_NBR_DATAPORTS RFCOMM_MAX_CONN

#define GET_BIT(pos,bitfield) ((bitfield[(pos)/32]) & (1 << ((pos) % 32)))
#define SET_BIT(pos,bitfield) ((bitfield[(pos)/32]) |= (1 << ((pos) % 32))) 
#define CLR_BIT(pos,bitfield) ((bitfield[(pos)/32]) &= ((1 << ((pos) % 32)) ^ (~0)))

/* Sets the P/F-bit in the control field */
#define SET_PF(ctr) ((ctr) | (1 << 4)) 
/* Clears the P/F-bit in the control field */
#define CLR_PF(ctr) ((ctr) & 0xef)
/* Returns the P/F-bit */
#define GET_PF(ctr) (((ctr) >> 4) & 0x1)

#define MIN(a, b) (((a) < (b)) ? (a) : (b))

/* Endian-swapping macros for structs */
#define swap_long_frame(x) ((x)->h.length.val = le16_to_cpu((x)->h.length.val))
#define swap_mcc_long_frame(x) (swap_long_frame(x))

/* Used for UIH packets */
#define SHORT_CRC_CHECK 2
/* Used for all packet exepts for the UIH packets */
#define LONG_CRC_CHECK 3
/* Short header for short UIH packets */
#define SHORT_HDR 2
/* Long header for long UIH packets */
#define LONG_HDR 3

/* FIXME: Should this one be defined here? */
#define SHORT_PAYLOAD_SIZE 127
/* Used for setting the EA field in different packets, really neccessary? */
#define EA 1
/* Yes the FCS size is only one byte */
#define FCS_SIZE 1

#define RFCOMM_MAX_HDR_SIZE 5

#define MAX_CREDITS   30
#define START_CREDITS 7
#define MIN_CREDITS   6

#define DEF_RFCOMM_MTU 127

/* The values in the control field when sending ordinary rfcomm packets */
#define SABM 0x2f	/* set asynchronous balanced mode */
#define UA   0x63	/* unnumbered acknolodgement */
#define DM   0x0f	/* disconnected mode */
#define DISC 0x43	/* disconnect */
#define UIH  0xef	/* unnumbered information with header check (only) */
#define UI   0x03	/* unnumbered information (with all data check) */

#define SABM_SIZE 4
#define UA_SIZE   4

/* The values in the type field in a multiplexer command packet */
#define PN    (0x80 >> 2)	/* parameter negotiation */
#define PSC   (0x40 >> 2)	/* power saving control */
#define CLD   (0xc0 >> 2)	/* close down */
#define TEST  (0x20 >> 2)	/* test */
#define FCON  (0xa0 >> 2)	/* flow control on */
#define FCOFF (0x60 >> 2)	/* flow control off */
#define MSC   (0xe0 >> 2)	/* modem status command */
#define NSC   (0x10 >> 2)	/* not supported command response */
#define RPN   (0x90 >> 2)	/* remote port negotiation */
#define RLS   (0x50 >> 2)	/* remote line status */
#define SNC   (0xd0 >> 2)	/* service negotiation command */

/* Define of some V.24 signals modem control signals in RFCOMM */
#define DV  0x80	/* data valid */
#define IC  0x40	/* incoming call */
#define RTR 0x08	/* ready to receive */
#define RTC 0x04	/* ready to communicate */
#define FC  0x02	/* flow control (unable to accept frames) */

#define CTRL_CHAN 0	/* The control channel is defined as DLCI 0 in rfcomm */
#define MCC_CMD 1	 /* Multiplexer command */
#define MCC_RSP 0	 /* Multiplexer response */

#if __BYTE_ORDER == __LITTLE_ENDIAN

typedef struct parameter_mask {
	uint8_t bit_rate:1;
	uint8_t data_bits:1;
	uint8_t stop_bit:1;
	uint8_t parity:1;
	uint8_t parity_type:1;
	uint8_t xon:1;
	uint8_t xoff:1;
	uint8_t res1:1;
	uint8_t xon_input:1;
	uint8_t xon_output:1;
	uint8_t rtr_input:1;
	uint8_t rtr_output:1;
	uint8_t rtc_input:1;
	uint8_t rtc_output:1;
	uint8_t res2:2;
} __attribute__ ((packed)) parameter_mask;

typedef struct rpn_values {
	uint8_t bit_rate;
	uint8_t data_bits:2;
	uint8_t stop_bit:1;
	uint8_t parity:1;
	uint8_t parity_type:2;
	uint8_t res1:2;
	uint8_t xon_input:1;
	uint8_t xon_output:1;
	uint8_t rtr_input:1;
	uint8_t rtr_output:1;
	uint8_t rtc_input:1;
	uint8_t rtc_output:1;
	uint8_t res2:2;
	uint8_t xon;
	uint8_t xoff;
	uint16_t pm;
	//parameter_mask pm;
} __attribute__ ((packed)) rpn_values;

#elif __BYTE_ORDER == __BIG_ENDIAN

typedef struct parameter_mask {
	uint8_t res1:1;
	uint8_t xoff:1;
	uint8_t xon:1;
	uint8_t parity_type:1;
	uint8_t parity:1;
	uint8_t stop_bit:1;
	uint8_t data_bits:1;
	uint8_t bit_rate:1;
	uint8_t res2:2;
	uint8_t rtc_output:1;
	uint8_t rtc_input:1;
	uint8_t rtr_output:1;
	uint8_t rtr_input:1;
	uint8_t xon_output:1;
	uint8_t xon_input:1;

} __attribute__ ((packed)) parameter_mask;

typedef struct rpn_values {
	uint8_t bit_rate;
	uint8_t res1:2;
	uint8_t parity_type:2;
	uint8_t parity:1;
	uint8_t stop_bit:1;
	uint8_t data_bits:2;
	uint8_t res2:2;
	uint8_t rtc_output:1;
	uint8_t rtc_input:1;
	uint8_t rtr_output:1;
	uint8_t rtr_input:1;
	uint8_t xon_output:1;
	uint8_t xon_input:1;
	uint8_t xon;
	uint8_t xoff;
	uint16_t pm;
	//parameter_mask pm;
} __attribute__ ((packed)) rpn_values;

#else
#error "Unknown byte order"
#endif

/* Typedefinitions of stuctures used for creating and parsing packets, for a
 * further description of the structures please se the bluetooth core
 * specification part F:1 and the ETSI TS 07.10 specification  */

#if __BYTE_ORDER == __LITTLE_ENDIAN

typedef struct address_field {
	uint8_t ea:1;
	uint8_t cr:1;
	uint8_t d:1;
	uint8_t server_chn:5;
} __attribute__ ((packed)) address_field;

typedef struct short_length {
	uint8_t ea:1;
	uint8_t len:7;
} __attribute__ ((packed)) short_length;

typedef union long_length {
	struct bits {
		uint8_t ea:1;
		unsigned short len:15;
	} __attribute__ ((packed)) bits ;
	uint16_t val ;
} __attribute__ ((packed)) long_length;

typedef struct short_frame_head {
	address_field addr;
	uint8_t control;
	short_length length;
} __attribute__ ((packed)) short_frame_head;

typedef struct short_frame {
	short_frame_head h;
	uint8_t data[0]; 
} __attribute__ ((packed)) short_frame;

typedef struct long_frame_head {
	address_field addr;
	uint8_t control;
	long_length length;
	uint8_t data[0];
} __attribute__ ((packed)) long_frame_head;

typedef struct long_frame {
	long_frame_head h;
	uint8_t data[0];
} __attribute__ ((packed)) long_frame;

/* Typedefinitions for structures used for the multiplexer commands */
typedef struct mcc_type {
	uint8_t ea:1;
	uint8_t cr:1;
	uint8_t type:6;
} __attribute__ ((packed)) mcc_type;

typedef struct mcc_short_frame_head {
	mcc_type type;
	short_length length;
	uint8_t value[0];
} __attribute__ ((packed)) mcc_short_frame_head;

typedef struct mcc_short_frame {
	mcc_short_frame_head h;
	uint8_t value[0];
} __attribute__ ((packed)) mcc_short_frame;

typedef struct mcc_long_frame_head {
	mcc_type type;
	long_length length;
	uint8_t value[0];
} __attribute__ ((packed)) mcc_long_frame_head;

typedef struct mcc_long_frame {
	mcc_long_frame_head h;
	uint8_t value[0];
} __attribute__ ((packed)) mcc_long_frame;

/* MSC-command */
typedef struct v24_signals {
	uint8_t ea:1;
	uint8_t fc:1;
	uint8_t rtc:1;
	uint8_t rtr:1;
	uint8_t reserved:2;
	uint8_t ic:1;
	uint8_t dv:1;
} __attribute__ ((packed)) v24_signals;

typedef struct break_signals {
	uint8_t ea:1;
	uint8_t b1:1;
	uint8_t b2:1;
	uint8_t b3:1;
	uint8_t len:4;
} __attribute__ ((packed)) break_signals;

typedef struct msc_msg {
	short_frame_head s_head;
	mcc_short_frame_head mcc_s_head;
	address_field dlci;
	v24_signals v24_sigs;
	//break_signals break_sigs;
	uint8_t fcs;
} __attribute__ ((packed)) msc_msg;

typedef struct rpn_msg {
	short_frame_head s_head;
	mcc_short_frame_head mcc_s_head;
	address_field dlci;
	rpn_values rpn_val;
	uint8_t fcs;
} __attribute__ ((packed)) rpn_msg;

/* RLS-command */  
typedef struct rls_msg {
	short_frame_head s_head;
	mcc_short_frame_head mcc_s_head;
	address_field dlci;
	uint8_t error:4;
	uint8_t res:4;
	uint8_t fcs;
} __attribute__ ((packed)) rls_msg;

/* PN-command */
typedef struct pn_msg {
	short_frame_head s_head;
	mcc_short_frame_head mcc_s_head;
/* The res1, res2 and res3 values have to be set to 0 by the sender */
	uint8_t dlci:6;
	uint8_t res1:2;
	uint8_t frame_type:4;
	uint8_t credit_flow:4;
	uint8_t prior:6;
	uint8_t res2:2;
	uint8_t ack_timer;
	uint16_t frame_size:16;
	uint8_t max_nbrof_retrans;
	uint8_t credits;
	uint8_t fcs;
} __attribute__ ((packed)) pn_msg;

/* NSC-command */
typedef struct nsc_msg {
	short_frame_head s_head;
	mcc_short_frame_head mcc_s_head;
	mcc_type command_type;
	uint8_t fcs;
} __attribute__ ((packed)) nsc_msg;

#elif __BYTE_ORDER == __BIG_ENDIAN

typedef struct address_field {
	uint8_t server_chn:5;
	uint8_t d:1;
	uint8_t cr:1;
	uint8_t ea:1;
} __attribute__ ((packed)) address_field;

typedef struct short_length {
	uint8_t len:7;
	uint8_t ea:1;
} __attribute__ ((packed)) short_length;

typedef union long_length {
	struct bits {
		unsigned short len:15;
		uint8_t ea:1;
	} __attribute__ ((packed)) bits;
	uint16_t val;
} __attribute__ ((packed)) long_length;

typedef struct short_frame_head {
	address_field addr;
	uint8_t control;
	short_length length;
} __attribute__ ((packed)) short_frame_head;

typedef struct short_frame {
	short_frame_head h;
	uint8_t data[0];
} __attribute__ ((packed)) short_frame;

typedef struct long_frame_head {
	address_field addr;
	uint8_t control;
	long_length length;
	uint8_t data[0];
} __attribute__ ((packed)) long_frame_head;

typedef struct long_frame {
	long_frame_head h;
	uint8_t data[0];
} __attribute__ ((packed)) long_frame;

typedef struct mcc_type {
	uint8_t type:6;
	uint8_t cr:1;
	uint8_t ea:1;
} __attribute__ ((packed)) mcc_type;

typedef struct mcc_short_frame_head {
	mcc_type type;
	short_length length;
	uint8_t value[0];
} __attribute__ ((packed)) mcc_short_frame_head;

typedef struct mcc_short_frame {
	mcc_short_frame_head h;
	uint8_t value[0];
} __attribute__ ((packed)) mcc_short_frame;

typedef struct mcc_long_frame_head {
	mcc_type type;
	long_length length;
	uint8_t value[0];
} __attribute__ ((packed)) mcc_long_frame_head;

typedef struct mcc_long_frame {
	mcc_long_frame_head h;
	uint8_t value[0];
} __attribute__ ((packed)) mcc_long_frame;

typedef struct v24_signals {
	uint8_t dv:1;
	uint8_t ic:1;
	uint8_t reserved:2;
	uint8_t rtr:1;
	uint8_t rtc:1;
	uint8_t fc:1;
	uint8_t ea:1;
} __attribute__ ((packed)) v24_signals;

typedef struct break_signals {
	uint8_t len:4;
	uint8_t b3:1;
	uint8_t b2:1;
	uint8_t b1:1;
	uint8_t ea:1;
} __attribute__ ((packed)) break_signals;

typedef struct msc_msg {
	short_frame_head s_head;
	mcc_short_frame_head mcc_s_head;
	address_field dlci;
	v24_signals v24_sigs;
	//break_signals break_sigs;
	uint8_t fcs;
} __attribute__ ((packed)) msc_msg;

typedef struct rpn_msg {
	short_frame_head s_head;
	mcc_short_frame_head mcc_s_head;
	address_field dlci;
	rpn_values rpn_val;
	uint8_t fcs;
} __attribute__ ((packed)) rpn_msg;

typedef struct rls_msg {
	short_frame_head s_head;
	mcc_short_frame_head mcc_s_head;
	address_field dlci;
	uint8_t res:4;
	uint8_t error:4;
	uint8_t fcs;
} __attribute__ ((packed)) rls_msg;

typedef struct pn_msg {
	short_frame_head s_head;
	mcc_short_frame_head mcc_s_head;
	uint8_t res1:2;
	uint8_t dlci:6;
	uint8_t credit_flow:4;
	uint8_t frame_type:4;
	uint8_t res2:2;
	uint8_t prior:6;
	uint8_t ack_timer;
	uint16_t frame_size:16;
	uint8_t max_nbrof_retrans;
	uint8_t credits;
	uint8_t fcs;
} __attribute__ ((packed)) pn_msg;

typedef struct nsc_msg {
	short_frame_head s_head;
	mcc_short_frame_head mcc_s_head;
	mcc_type command_type;
	uint8_t fcs;
} __attribute__ ((packed)) nsc_msg;

#else
#error "Unknown byte order"
#error Processor endianness unknown!
#endif

#endif /* __RFCOMM_H */
