mirror of
https://git.kernel.org/pub/scm/bluetooth/bluez.git
synced 2024-12-12 21:44:12 +08:00
495 lines
12 KiB
C
495 lines
12 KiB
C
/*
|
|
*
|
|
* BlueZ - Bluetooth protocol stack for Linux
|
|
*
|
|
* Copyright (C) 2001-2002 Wayne Lee <waynelee@qualcomm.com>
|
|
* Copyright (C) 2003-2007 Marcel Holtmann <marcel@holtmann.org>
|
|
*
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*/
|
|
|
|
#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 */
|