Re: [RFC 2/2] btproxy: Add three-wire (h5) protocol initial support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Andrei,

> With H5 support it is possible to create pts and attach to it using
> hciattach ot btattach with 3wire protocol. This is useful for testing
> and developing three-wire protocol.
> Implementation is based on kernel hci_h5.c H5 protocol.
> 
> Simple usage:
> To open virtual pts run:
> $ sudo tools/btproxy -d --pty -3
> Opening pseudoterminal
> New pts created: /dev/pts/2
> Opening user channel for hci0
> 
> Now attach to it using hciattach:
> $ sudo hciattach -n /dev/pts/2 3wire
> Device setup complete
> ---
> tools/btproxy.c | 541 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 535 insertions(+), 6 deletions(-)
> 
> diff --git a/tools/btproxy.c b/tools/btproxy.c
> index 6d78876..c718e48 100644
> --- a/tools/btproxy.c
> +++ b/tools/btproxy.c
> @@ -47,23 +47,22 @@
> #include "src/shared/util.h"
> #include "src/shared/mainloop.h"
> #include "src/shared/ecc.h"
> +#include "src/shared/queue.h"
> +#include "lib/bluetooth.h"
> +#include "lib/hci.h"
> #include "monitor/bt.h"
> 
> #define HCI_BREDR	0x00
> #define HCI_AMP		0x01
> 
> #define BTPROTO_HCI	1
> -struct sockaddr_hci {
> -	sa_family_t	hci_family;
> -	unsigned short	hci_dev;
> -	unsigned short  hci_channel;
> -};
> #define HCI_CHANNEL_USER	1

please do not do this.

> static uint16_t hci_index = 0;
> static bool client_active = false;
> static bool debug_enabled = false;
> static bool emulate_ecc = false;
> +static bool three_wire = false;
> 
> static void hexdump_print(const char *str, void *user_data)
> {
> @@ -287,6 +286,516 @@ static void host_read_destroy(void *user_data)
> 		mainloop_remove_fd(proxy->dev_fd);
> }
> 
> +/* three-wire (H5) packet processing */
> +
> +#define H5_ACK_TIMEOUT		250
> +
> +#define HCI_3WIRE_ACK_PKT	0
> +#define HCI_3WIRE_LINK_PKT	15
> +
> +/*
> + * Maximum Three-wire packet:
> + *     4 byte header + max value for 12-bit length + 2 bytes for CRC
> + */
> +#define H5_MAX_LEN (4 + 0xfff + 2)
> +
> +/* Sliding window size */
> +#define H5_TX_WIN_MAX		4
> +
> +#define SLIP_DELIMITER	0xc0
> +#define SLIP_ESC	0xdb
> +#define SLIP_ESC_DELIM	0xdc
> +#define SLIP_ESC_ESC	0xdd
> +
> +#define H5_RX_ESC	1
> +
> +#define H5_HDR_SEQ(hdr)		((hdr)[0] & 0x07)
> +#define H5_HDR_ACK(hdr)		(((hdr)[0] >> 3) & 0x07)
> +#define H5_HDR_CRC(hdr)		(((hdr)[0] >> 6) & 0x01)
> +#define H5_HDR_RELIABLE(hdr)	(((hdr)[0] >> 7) & 0x01)
> +#define H5_HDR_PKT_TYPE(hdr)	((hdr)[1] & 0x0f)
> +#define H5_HDR_LEN(hdr)		((((hdr)[1] >> 4) & 0x0f) + ((hdr)[2] << 4))
> +
> +#define H5_SET_SEQ(hdr, seq)	((hdr)[0] |= (seq))
> +#define H5_SET_ACK(hdr, ack)	((hdr)[0] |= (ack) << 3)
> +#define H5_SET_RELIABLE(hdr)	((hdr)[0] |= 1 << 7)
> +#define H5_SET_TYPE(hdr, type)	((hdr)[1] |= type)
> +#define H5_SET_LEN(hdr, len)	(((hdr)[1] |= ((len) & 0x0f) << 4), \
> +						((hdr)[2] |= (len) >> 4))
> +
> +static const uint8_t sync_req[] = { 0x01, 0x7e };
> +static const uint8_t sync_rsp[] = { 0x02, 0x7d };
> +static const uint8_t conf_req[] = { 0x03, 0xfc };
> +static const uint8_t wakeup_req[] = { 0x05, 0xfa };
> +static const uint8_t woken_req[] = { 0x06, 0xf9 };
> +static const uint8_t sleep_req[] = { 0x07, 0x78 };
> +
> +static struct h5 {
> +	size_t rx_pending;
> +	uint8_t rx_buf[H5_MAX_LEN];
> +	uint8_t *rx_ptr;
> +	uint8_t flags;
> +
> +	uint8_t rx_ack;		/* Received last ack number */
> +	uint8_t tx_seq;		/* Next seq number to send */
> +	uint8_t tx_ack;		/* Next ack number to send */
> +
> +	uint8_t tx_win;
> +
> +	enum {
> +		H5_UNINITIALIZED,
> +		H5_INITIALIZED,
> +		H5_ACTIVE,
> +	} state;
> +
> +	int timer_id;
> +
> +	struct queue *tx_queue_unack;
> +	struct queue *tx_queue_unrel;
> +	struct queue *tx_queue_rel;
> +
> +	int (*rx_func)(struct proxy *proxy, uint8_t byte);
> +} h5;

No global static variables please. That should be part of struct proxy instead. Global variables will cause problems if you ever try to start two instances.

> +
> +struct h5_pkt {
> +	uint16_t len;
> +	uint8_t data[0];
> +};

I think using get_unaligned_le16 to get the length would be a lot simpler.

> +
> +static void h5_reset_rx(void);
> +
> +static void h5_reset_peer(void)
> +{
> +	h5.state = H5_UNINITIALIZED;
> +
> +	mainloop_remove_timeout(h5.timer_id);
> +	h5.timer_id = -1;
> +	h5_reset_rx();
> +}

With that all said, I think we might want to create a tools/h5.[ch] to abstract this properly into a separate helper library.

Regards

Marcel

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux