SmartAudio/package/utils/bluez/patches/202-add-xradio-hciattach.patch

1547 lines
41 KiB
Diff
Executable File

Index: bluez-5.38/Makefile.in
===================================================================
--- bluez-5.38/Makefile.in
+++ bluez-5.38/Makefile.in
@@ -1235,7 +1235,8 @@ am__tools_hciattach_SOURCES_DIST = tools
tools/hciattach_st.c tools/hciattach_ti.c \
tools/hciattach_tialt.c tools/hciattach_ath3k.c \
tools/hciattach_qualcomm.c tools/hciattach_intel.c \
- tools/hciattach_bcm43xx.c
+ tools/hciattach_bcm43xx.c \
+ tools/hciattach_xradio.c
@TOOLS_TRUE@am_tools_hciattach_OBJECTS = tools/hciattach.$(OBJEXT) \
@TOOLS_TRUE@ tools/hciattach_st.$(OBJEXT) \
@TOOLS_TRUE@ tools/hciattach_ti.$(OBJEXT) \
@@ -1243,7 +1244,8 @@ am__tools_hciattach_SOURCES_DIST = tools
@TOOLS_TRUE@ tools/hciattach_ath3k.$(OBJEXT) \
@TOOLS_TRUE@ tools/hciattach_qualcomm.$(OBJEXT) \
@TOOLS_TRUE@ tools/hciattach_intel.$(OBJEXT) \
-@TOOLS_TRUE@ tools/hciattach_bcm43xx.$(OBJEXT)
+@TOOLS_TRUE@ tools/hciattach_bcm43xx.$(OBJEXT) \
+@TOOLS_TRUE@ tools/hciattach_xradio.$(OBJEXT)
tools_hciattach_OBJECTS = $(am_tools_hciattach_OBJECTS)
@TOOLS_TRUE@tools_hciattach_DEPENDENCIES = \
@TOOLS_TRUE@ lib/libbluetooth-internal.la
@@ -2581,7 +2583,8 @@ unit_tests = $(am__append_35) unit/test-
@TOOLS_TRUE@ tools/hciattach_ath3k.c \
@TOOLS_TRUE@ tools/hciattach_qualcomm.c \
@TOOLS_TRUE@ tools/hciattach_intel.c \
-@TOOLS_TRUE@ tools/hciattach_bcm43xx.c
+@TOOLS_TRUE@ tools/hciattach_bcm43xx.c \
+@TOOLS_TRUE@ tools/hciattach_xradio.c
@TOOLS_TRUE@tools_hciattach_LDADD = lib/libbluetooth-internal.la
@TOOLS_TRUE@tools_hciconfig_SOURCES = tools/hciconfig.c tools/csr.h tools/csr.c
@@ -4702,6 +4705,8 @@ tools/hciattach_intel.$(OBJEXT): tools/$
tools/$(DEPDIR)/$(am__dirstamp)
tools/hciattach_bcm43xx.$(OBJEXT): tools/$(am__dirstamp) \
tools/$(DEPDIR)/$(am__dirstamp)
+tools/hciattach_xradio.$(OBJEXT): tools/$(am__dirstamp) \
+ tools/$(DEPDIR)/$(am__dirstamp)
tools/hciattach$(EXEEXT): $(tools_hciattach_OBJECTS) $(tools_hciattach_DEPENDENCIES) $(EXTRA_tools_hciattach_DEPENDENCIES) tools/$(am__dirstamp)
@rm -f tools/hciattach$(EXEEXT)
@@ -5569,6 +5574,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hciattach.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hciattach_ath3k.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hciattach_bcm43xx.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hciattach_xradio.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hciattach_intel.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hciattach_qualcomm.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/hciattach_st.Po@am__quote@
Index: bluez-5.38/Makefile.tools
===================================================================
--- bluez-5.38/Makefile.tools
+++ bluez-5.38/Makefile.tools
@@ -163,7 +163,8 @@ tools_hciattach_SOURCES = tools/hciattac
tools/hciattach_ath3k.c \
tools/hciattach_qualcomm.c \
tools/hciattach_intel.c \
- tools/hciattach_bcm43xx.c
+ tools/hciattach_bcm43xx.c \
+ tools/hciattach_xradio.c
tools_hciattach_LDADD = lib/libbluetooth-internal.la
tools_hciconfig_SOURCES = tools/hciconfig.c tools/csr.h tools/csr.c
Index: bluez-5.38/tools/hciattach.c
===================================================================
--- bluez-5.38/tools/hciattach.c
+++ bluez-5.38/tools/hciattach.c
@@ -349,6 +349,11 @@ static int bcm43xx(int fd, struct uart_t
return bcm43xx_init(fd, u->init_speed, u->speed, ti, u->bdaddr);
}
+static int xradio(int fd, struct uart_t *u, struct termios *ti)
+{
+ return xradio_init(fd, u->init_speed, u->speed, ti, u->bdaddr);
+}
+
static int read_check(int fd, void *buf, int count)
{
int res;
@@ -1164,6 +1169,10 @@ struct uart_t uart[] = {
{ "bcm43xx-3wire", 0x0000, 0x0000, HCI_UART_3WIRE, 115200, 3000000,
0, DISABLE_PM, NULL, bcm43xx, NULL },
+ /* Xradio XR829 */
+ { "xradio", 0x0000, 0x0000, HCI_UART_H4, 115200, 1500000,
+ 0, DISABLE_PM, NULL, xradio, NULL },
+
{ "ath3k", 0x0000, 0x0000, HCI_UART_ATH3K, 115200, 115200,
FLOW_CTL, DISABLE_PM, NULL, ath3k_ps, ath3k_pm },
@@ -1234,7 +1243,11 @@ static int init_uart(char *dev, struct u
cfmakeraw(&ti);
- ti.c_cflag |= CLOCAL;
+ /* ti.c_cflag |= CLOCAL; */
+ ti.c_cflag |= CS8;
+ ti.c_cflag &= ~(PARENB | PARODD);
+ ti.c_cflag &= ~(CSTOPB);
+
if (u->flags & FLOW_CTL)
ti.c_cflag |= CRTSCTS;
else
@@ -1245,6 +1258,14 @@ static int init_uart(char *dev, struct u
goto fail;
}
+ tcflush(fd, TCIOFLUSH);
+ if (tcsetattr(fd, TCSANOW, &ti) < 0) {
+ perror("Can't set port settings");
+ goto fail;
+ }
+ tcflush(fd, TCIOFLUSH);
+ tcflush(fd, TCIOFLUSH);
+
/* Set initial baudrate */
if (set_speed(fd, &ti, u->init_speed) < 0) {
perror("Can't set initial baud rate");
@@ -1252,15 +1273,16 @@ static int init_uart(char *dev, struct u
}
tcflush(fd, TCIOFLUSH);
-
+#if 0
if (send_break) {
tcsendbreak(fd, 0);
usleep(500000);
}
+#endif
if (u->init && u->init(fd, u, &ti) < 0)
goto fail;
-
+#if 0
tcflush(fd, TCIOFLUSH);
/* Set actual baudrate */
@@ -1288,7 +1310,7 @@ static int init_uart(char *dev, struct u
if (u->post && u->post(fd, u, &ti) < 0)
goto fail;
-
+#endif
return fd;
fail:
Index: bluez-5.38/tools/hciattach.h
===================================================================
--- bluez-5.38/tools/hciattach.h
+++ bluez-5.38/tools/hciattach.h
@@ -66,3 +66,5 @@ int qualcomm_init(int fd, int speed, str
int intel_init(int fd, int init_speed, int *speed, struct termios *ti);
int bcm43xx_init(int fd, int def_speed, int speed, struct termios *ti,
const char *bdaddr);
+int xradio_init(int fd, int def_speed, int speed, struct termios *ti,
+ const char *bdaddr);
===================================================================
--- /dev/null
+++ bluez-5.38.orig/tools/hciattach_xradio.c
@@ -0,0 +1,1383 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2018 Xradio Technology Co., Ltd.. All rights reserved.
+ *
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+#include <time.h>
+#include <limits.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+
+#include "lib/bluetooth.h"
+#include "lib/hci.h"
+#include "lib/hci_lib.h"
+
+#include "hciattach.h"
+
+#ifndef BT_FW_PATH_NAME
+#define BT_FW_PATH_NAME "/lib/firmware/fw_xr829_bt.bin"
+#endif
+
+#define UNUSED(x) (void)(x)
+
+#define SHOW_LOG 0
+#define SAVE_TXRX_DATA 0
+
+#define SWAP16(d) (((d & 0xff) << 8) | ((d & 0xff00) >> 8))
+#define SWAP32(d) (((d & 0xff) << 24) | ((d & 0xff00) << 8) \
+ | ((d & 0xff0000) >> 8) | ((d & 0xff000000) >> 24))
+
+#define FILL_HEADER_MAGIC(h) do { \
+ (h)->magic[0] = 'B'; \
+ (h)->magic[1] = 'R'; \
+ (h)->magic[2] = 'O'; \
+ (h)->magic[3] = 'M'; \
+} while(0)
+
+#define HEADER_MAGIC_VALID(h) ( \
+ (h)->magic[0] == 'B' && \
+ (h)->magic[1] == 'R' && \
+ (h)->magic[2] == 'O' && \
+ (h)->magic[3] == 'M' )
+
+#define FILL_HEADER_CHECKSUM(h, cs) do { \
+ (h)->checksum = cs; \
+ } while(0)
+
+#define UART_BUF_RXCLEAR (1<<0)
+#define UART_BUF_TXCLEAR (1<<1)
+
+#define SZ_512 (0x00000200U )
+#define SZ_1K (0x00000400U )
+#define SZ_2K (0x00000800U )
+#define SZ_4K (0x00001000U )
+#define SZ_8K (0x00002000U )
+#define SZ_16K (0x00004000U )
+#define SZ_32K (0x00008000U )
+#define SZ_64K (0x00010000U )
+#define SZ_128K (0x00020000U )
+#define SZ_256K (0x00040000U )
+#define SZ_512K (0x00080000U )
+#define SZ_1M (0x00100000U )
+#define SZ_2M (0x00200000U )
+#define SZ_4M (0x00400000U )
+#define SZ_8M (0x00800000U )
+#define SZ_16M (0x01000000U )
+#define SZ_32M (0x02000000U )
+#define SZ_64M (0x04000000U )
+#define SZ_128M (0x08000000U )
+#define SZ_256M (0x10000000U )
+#define SZ_512M (0x20000000U )
+#define SZ_1G (0x40000000U )
+#define SZ_2G (0x80000000U )
+#define SZ_4G (0x0100000000ULL)
+#define SZ_8G (0x0200000000ULL)
+#define SZ_16G (0x0400000000ULL)
+#define SZ_32G (0x0800000000ULL)
+#define SZ_64G (0x1000000000ULL)
+
+#define CMD_REVESION 0x0000 /* 0.0.0.0 */
+#define CMD_SYNC_WORD 0x55
+#define CMD_ID(group, key) (((group) << 3) | (key))
+
+/*----------------------------*/
+/* COMMANDS FORM PC TO MCU */
+/*----------------------------*/
+#define CMD_ID_MEMRW 0x00
+#define CMD_ID_SEQRQ 0x01
+#define CMD_ID_SYSCTL 0x02
+#define CMD_ID_FLASH 0x03
+/* memory access commands */
+#define CMD_ID_READ1 CMD_ID(CMD_ID_MEMRW, 0)
+#define CMD_ID_WRITE1 CMD_ID(CMD_ID_MEMRW, 1)
+#define CMD_ID_READ2 CMD_ID(CMD_ID_MEMRW, 2)
+#define CMD_ID_WRITE2 CMD_ID(CMD_ID_MEMRW, 3)
+#define CMD_ID_READ4 CMD_ID(CMD_ID_MEMRW, 4)
+#define CMD_ID_WRITE4 CMD_ID(CMD_ID_MEMRW, 5)
+#define CMD_ID_READ8 CMD_ID(CMD_ID_MEMRW, 6)
+#define CMD_ID_WRITE8 CMD_ID(CMD_ID_MEMRW, 7)
+
+#define CMD_ID_SEQRD CMD_ID(CMD_ID_SEQRQ, 0)
+#define CMD_ID_SEQWR CMD_ID(CMD_ID_SEQRQ, 1)
+/* uart commands */
+#define CMD_ID_SETUART CMD_ID(CMD_ID_SYSCTL, 0)
+#define CMD_ID_SETJTAG CMD_ID(CMD_ID_SYSCTL, 1)
+#define CMD_ID_REBOOT CMD_ID(CMD_ID_SYSCTL, 2)
+#define CMD_ID_SETPC CMD_ID(CMD_ID_SYSCTL, 3)
+#define CMD_ID_SETCKCS CMD_ID(CMD_ID_SYSCTL, 4)
+/* flash operation commands */
+#define CMD_ID_FLASH_GETINFO CMD_ID(CMD_ID_FLASH, 0)
+#define CMD_ID_FLASH_ERASE CMD_ID(CMD_ID_FLASH, 1)
+#define CMD_ID_FLASH_READ CMD_ID(CMD_ID_FLASH, 2)
+#define CMD_ID_FLASH_WRITE CMD_ID(CMD_ID_FLASH, 3)
+
+/*----------------------------*/
+/* COMMANDS FORM MCU TO PC */
+/*----------------------------*/
+/* message output */
+#define CMD_ID_SENDMSG CMD_ID(0, 0)
+
+#pragma pack(1)
+/* command header
+ *
+ * byte 0 byte 1 byte 2 byte 3 byte 4 byte 5 byte 6 -7 byte 8-11
+ * ___________________________________________________________________________________________________
+ * | | | | | | | | |
+ * | 'B' | 'R' | 'O' | 'M' | Flags |Reserved | Checksum | Playload Length |
+ * |_________|_________|_________|_________|_________|_________|__________ ________|___________________|
+ */
+typedef struct {
+ unsigned char magic[4]; /* magic "BROM" */
+ #define CMD_BROM_MAGIC "BROM"
+ unsigned char flags;
+ #define CMD_HFLAG_ERROR (0x1U << 0)
+ #define CMD_HFLAG_ACK (0x1U << 1)
+ #define CMD_HFLAG_CHECK (0x1U << 2)
+ #define CMD_HFLAG_RETRY (0x1U << 3)
+ #define CMD_HFLAG_EXE (0x1U << 4)
+ unsigned char version:4;
+ unsigned char reserved:4;
+ unsigned short checksum;
+ unsigned int payload_len;
+} __attribute__((packed)) cmd_header_t;
+#define MB_CMD_HEADER_SIZE (sizeof(cmd_header_t))
+
+typedef struct {
+ cmd_header_t h;
+ unsigned char cmdid;
+} __attribute__((packed)) cmd_header_id_t;
+#define MB_HEADER_TO_ID(h) (((cmd_header_id_t*)(h))->cmdid)
+
+/* acknownledge structure */
+typedef struct {
+ cmd_header_t h;
+ unsigned char err;
+} __attribute__((packed)) cmd_ack_t;
+
+/* memory read/write command structure */
+#define CMD_RW_DATA_POS (MB_CMD_HEADER_SIZE + 5)
+#define CMD_RW_DATA_LEN(id) (1 << ((id >> 1) & 0x3))
+typedef struct {
+ cmd_header_t h;
+ unsigned char cmdid;
+ unsigned int addr;
+} __attribute__((packed)) cmd_rw_t;
+
+/* sequence read/write command structure */
+#define CMD_SEQRW_DATA_POS (MB_CMD_HEADER_SIZE + 5)
+typedef struct {
+ cmd_header_t h;
+ unsigned char cmdid;
+ unsigned int addr;
+ unsigned int dlen;
+ unsigned short dcs;
+} __attribute__((packed)) cmd_seq_wr_t;
+
+typedef struct {
+ cmd_header_t h;
+ unsigned char cmdid;
+ unsigned int addr;
+ unsigned int dlen;
+} __attribute__((packed)) cmd_seq_rd_t;
+
+/* io change command structure */
+#define CMD_SYS_DATA_POS (MB_CMD_HEADER_SIZE + 1)
+typedef struct {
+ cmd_header_t h;
+ unsigned char cmdid;
+ unsigned int val;
+} __attribute__((packed)) cmd_sys_t;
+
+typedef struct {
+ cmd_header_t h;
+ unsigned char cmdid;
+ unsigned int lcr;
+} __attribute__((packed)) cmd_sys_setuart_t;
+
+typedef struct {
+ cmd_header_t h;
+ unsigned char cmdid;
+ unsigned char mode;
+} __attribute__((packed)) cmd_sys_setjtag_t;
+
+typedef struct {
+ cmd_header_t h;
+ unsigned char cmdid;
+ unsigned char mode;
+} __attribute__((packed)) cmd_sys_setcs_t;
+
+/* flash command structure */
+typedef struct {
+ cmd_header_t h;
+ unsigned char cmdid;
+ unsigned char erase_cmd;
+ unsigned int addr;
+} __attribute__((packed)) cmd_flash_er_t;
+
+typedef struct {
+ cmd_header_t h;
+ unsigned char cmdid;
+ unsigned int sector;
+ unsigned int num;
+ unsigned short dcs;
+} __attribute__((packed)) cmd_flash_wr_t;
+
+typedef struct {
+ cmd_header_t h;
+ unsigned char cmdid;
+ unsigned int sector;
+ unsigned int num;
+} __attribute__((packed)) cmd_flash_rd_t;
+
+#pragma pack()
+
+/* response error type */
+#define MB_ERR_UNKNOWNCMD (1)
+#define MB_ERR_TIMEOUT (2)
+#define MB_ERR_CHECKSUM (3)
+#define MB_ERR_INVALID (4)
+#define MB_ERR_NOMEM (5)
+
+#define UPIO_BT_POWER_OFF 0
+#define UPIO_BT_POWER_ON 1
+
+/* UPIO signals */
+enum {
+ UPIO_BT_WAKE = 0,
+ UPIO_HOST_WAKE,
+ UPIO_LPM_MODE,
+ UPIO_MAX_COUNT
+};
+
+/* UPIO assertion/deassertion */
+enum {
+ UPIO_UNKNOWN = 0,
+ UPIO_DEASSERT,
+ UPIO_ASSERT
+};
+
+#define BT_WAKE_VIA_PROC 1
+
+/* proc fs node for enable/disable lpm mode */
+#ifndef VENDOR_LPM_PROC_NODE
+#define VENDOR_LPM_PROC_NODE "/proc/bluetooth/sleep/lpm"
+#endif
+
+/* proc fs node for sleep bt device */
+#ifndef VENDOR_BTWAKE_PROC_NODE
+#define VENDOR_BTWAKE_PROC_NODE "/proc/bluetooth/sleep/btwrite"
+#endif
+
+/*
+ * Maximum btwrite assertion holding time without consecutive btwrite kicking.
+ * This value is correlative(shorter) to the in-activity timeout period set in
+ * the bluesleep LPM code. The current value used in bluesleep is 10sec.
+ */
+#ifndef PROC_BTWAKE_TIMER_TIMEOUT_MS
+#define PROC_BTWAKE_TIMER_TIMEOUT_MS 10000
+#endif
+
+/* lpm proc control block */
+typedef struct
+{
+ uint8_t btwrite_active;
+ uint8_t timer_created;
+ timer_t timer_id;
+ uint32_t timeout_ms;
+} vnd_lpm_proc_cb_t;
+
+static unsigned char upio_state[UPIO_MAX_COUNT];
+static int rfkill_id = -1;
+static char *rfkill_state_path = NULL;
+static vnd_lpm_proc_cb_t lpm_proc_cb;
+
+/* for friendly debugging outpout string */
+static char *lpm_mode[] = {
+ "UNKNOWN",
+ "disabled",
+ "enabled"
+};
+
+static char *lpm_state[] = {
+ "UNKNOWN",
+ "de-asserted",
+ "asserted"
+};
+
+static unsigned int g_chip_name = 1; /* 1:AW1722 2:AW1732 */
+static unsigned int g_load_addr = 0x0000;
+static unsigned int g_jump_addr = 0x0000;
+static unsigned int g_port_num = 1;
+static unsigned int g_dump_debug = 1;
+static unsigned int g_hciup_flag = 1;
+static unsigned int g_startup_reset_flag =1;
+static unsigned int g_update_hcirate_flag = 1;
+static unsigned int g_bdaddr_flag = 0;
+
+static unsigned char g_trans_buf[1024];
+
+static unsigned char hci_reset[] = { 0x01, 0x03, 0x0c, 0x00 };
+static unsigned char hci_update_baud_rate[] = { 0x01, 0x18, 0xfc, 0x04, 0x60, 0xE3, 0x16, 0x00};
+static unsigned char hci_write_bd_addr[] = { 0x01, 0x32, 0xfc, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static void proc_btwrite_timeout(union sigval arg)
+{
+ UNUSED(arg);
+ printf("%s.\n", __FUNCTION__);
+ lpm_proc_cb.btwrite_active = 0;
+}
+
+static void ms_delay (uint32_t timeout)
+{
+ struct timespec delay;
+ int err;
+
+ if (timeout == 0)
+ return;
+
+ delay.tv_sec = timeout / 1000;
+ delay.tv_nsec = 1000 * 1000 * (timeout%1000);
+
+ /* [u]sleep can't be used because it uses SIGALRM */
+ do {
+ err = nanosleep(&delay, &delay);
+ } while (err < 0 && errno == EINTR);
+}
+
+static unsigned short check_sum16(unsigned char *data, unsigned int len)
+{
+ unsigned short cs = 0;
+ unsigned short *p = (unsigned short*)data;
+
+ while(len > 1) {
+ cs += *p++;
+ len -= 2;
+ }
+ if (len) {
+ cs += *(unsigned char*)p;
+ }
+
+ return cs;
+}
+
+static void debug_dump(unsigned char *out, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ {
+ if (i && !(i % 16))
+ {
+ fprintf(stderr, "\n");
+ }
+
+ fprintf(stderr, "%02x ", out[i]);
+ }
+
+ fprintf(stderr, "\n");
+}
+
+static void debug_dump_data(unsigned char *prompt, unsigned char *buf, unsigned int len)
+{
+#if SHOW_LOG
+ unsigned int i, j;
+ unsigned int head = 0;
+
+ printf("Dump(%s): len %d\n", prompt, len);
+ for (i = 0; i < len;) {
+ printf("0x%02x, ", buf[i]&0xff);
+ if (i % 8 == 7 || i==len-1) {
+ printf("\n");
+ }
+
+ i++;
+ }
+ printf("\n");
+#endif
+}
+
+static void debug_write_txdata(unsigned char *buf, unsigned int len)
+{
+#if SAVE_TXRX_DATA
+ unsigned int i;
+ static unsigned int txidx = 0;
+ static unsigned int txlen = 0;
+ cmd_rw_t *cmd = (cmd_rw_t *)buf;
+ char name[16] = "txdata.hex";
+ FILE *fd;
+
+ txidx ++;
+ txlen = 0;
+
+ txlen += len;
+ sprintf(&name[strlen("txdata.hex")], "%d", txidx);
+ fd = fopen(name, "wb+");
+
+ fprintf(fd, "%02x\n", txlen & 0xff);
+ fprintf(fd, "%02x\n", (txlen>>8) & 0xff);
+ fprintf(fd, "%02x\n", (txlen>>16) & 0xff);
+ fprintf(fd, "%02x\n", (txlen>>24) & 0xff);
+
+ for (i=0; i<len; i++)
+ fprintf(fd, "%02x\n", buf[i]);
+ fclose(fd);
+#endif
+}
+
+static void debug_write_rxdata(unsigned char *buf, unsigned int len)
+{
+#if SAVE_TXRX_DATA
+ unsigned int i;
+ static unsigned int rxidx = 0;
+ static unsigned int rxlen = 0;
+ cmd_rw_t *cmd = (cmd_rw_t *)buf;
+ char name[16] = "rxdata.hex";
+ FILE *fd;
+
+ if (HEADER_MAGIC_VALID(&cmd->h)) {
+ rxidx ++;
+ rxlen = 0;
+ }
+ rxlen += len;
+ sprintf(&name[strlen("rxdata.hex")], "%d", rxidx);
+ if (HEADER_MAGIC_VALID(&cmd->h)) {
+ fd = fopen(name, "wb+");
+ fprintf(fd, "%02x\n", rxlen & 0xff);
+ fprintf(fd, "%02x\n", (rxlen>>8) & 0xff);
+ fprintf(fd, "%02x\n", (rxlen>>16) & 0xff);
+ fprintf(fd, "%02x\n", (rxlen>>24) & 0xff);
+ } else {
+ fd = fopen(name, "ab+");
+ }
+ for (i=0; i<len; i++)
+ fprintf(fd, "%02x\n", buf[i]);
+ if (!HEADER_MAGIC_VALID(&cmd->h)) {
+ fclose(fd);
+ fd = fopen(name, "rb+");
+ fseek(fd, 0, SEEK_SET);
+ fprintf(fd, "%02x\n", rxlen & 0xff);
+ fprintf(fd, "%02x\n", (rxlen>>8) & 0xff);
+ fprintf(fd, "%02x\n", (rxlen>>16) & 0xff);
+ fprintf(fd, "%02x\n", (rxlen>>24) & 0xff);
+ }
+
+ fclose(fd);
+#endif
+}
+
+static int userial_sync(int fd)
+{
+ unsigned char syncbuf[] = {0x55};
+ unsigned char ackbuf[3] = {0};
+ int ret = -1;
+ int flags;
+ int cnt = 0;
+
+ flags = fcntl(fd, F_GETFL);
+ flags |= O_NONBLOCK;
+ if (fcntl(fd, F_SETFL, flags) == -1) {
+ printf("[%s] fcntl NONBLOCK fail.\n", __FUNCTION__);
+ exit(-1);
+ }
+
+
+ /*
+ * sync success or stop by alarm.
+ */
+ do {
+ printf("[%s] uart sync count: %d.\n", __FUNCTION__, ++cnt);
+ write(fd, syncbuf, 1);
+ usleep(20000);
+ ret = read(fd, ackbuf, 2);
+ printf("[%s] read buf: %02x %02x.\n", __FUNCTION__, ackbuf[0], ackbuf[1]);
+ if (ret < 0) {
+ if (errno == EAGAIN)
+ continue;
+ }
+ if (ret == 2 && ((ackbuf[0] == 'O' && ackbuf[1] == 'K')
+ || (ackbuf[0] == 'K' && ackbuf[1] == 'O'))) {
+ printf("[%s] Receive %s, uart sync done.\n", __FUNCTION__, ackbuf);
+ break;
+ }
+ } while (1);
+
+ flags &= ~(O_NONBLOCK);
+ if (fcntl(fd, F_SETFL, flags) == -1) {
+ printf("[%s] fcntl BLOCK fail.\n", __FUNCTION__);
+ exit(-1);
+ }
+
+ return 0;
+}
+
+static void userial_vendor_set_hw_fctrl(int fd, uint8_t hw_fctrl)
+{
+ struct termios ti;
+
+ if (fd == -1)
+ {
+ printf("fd is -1\n");
+ return;
+ }
+
+ if (tcgetattr(fd, &ti) < 0) {
+ perror("Can't get port settings");
+ return;
+ }
+
+ if(hw_fctrl)
+ {
+ printf("Set HW FlowControl On\n");
+ if(ti.c_cflag & CRTSCTS)
+ {
+ printf("userial_vendor_set_hw_fctrl already hw flowcontrol on\n");
+ return;
+ }
+ else
+ {
+ ti.c_cflag |= CRTSCTS;
+ tcsetattr(fd, TCSANOW, &ti);
+ printf("userial_vendor_set_hw_fctrl set hw flowcontrol on\n");
+ }
+ }
+ else
+ {
+ printf("Set HW FlowControl Off\n");
+ if(ti.c_cflag & CRTSCTS)
+ {
+ ti.c_cflag &= ~CRTSCTS;
+ tcsetattr(fd, TCSANOW, &ti);
+ return;
+ }
+ else
+ {
+ printf("userial_vendor_set_hw_fctrl set hw flowcontrol off\n");
+ return;
+ }
+ }
+ tcflush(fd, TCIOFLUSH);
+}
+
+static void userial_clearbuf(int fd, uint8_t flag)
+{
+ if (flag == UART_BUF_RXCLEAR)
+ tcflush(fd, TCIFLUSH);
+ else if (flag == UART_BUF_TXCLEAR)
+ tcflush(fd, TCOFLUSH);
+ else
+ tcflush(fd, TCIOFLUSH);
+}
+
+static uint16_t userial_read(int fd, uint8_t *p_buffer, uint16_t len)
+{
+ int ret = -1;
+ uint16_t total_len = 0;
+
+ do {
+ ret = read(fd, p_buffer + total_len, len);
+ if(ret == -1)
+ {
+ printf("%s error writing to serial port: %s.\n", __func__, strerror(errno));
+ return total_len;
+ }
+ total_len += ret;
+ len -= ret;
+ } while(len);
+
+ return total_len;
+}
+
+static uint16_t userial_write(int fd, const uint8_t *p_data, uint16_t len)
+{
+ uint16_t total = 0;
+ int ret;
+
+ while (len) {
+ ret = write(fd, p_data + total, len);
+ switch (ret) {
+ case -1:
+ printf("%s error writing to serial port: %s.\n", __func__, strerror(errno));
+ return total;
+ case 0:
+ return total;
+ default:
+ total += ret;
+ len -= ret;
+ break;
+ }
+ }
+ return total;
+}
+
+static int userial_vendor_set_baud(int fd, int def_speed)
+{
+ struct termios ti;
+
+ if (tcgetattr(fd, &ti) < 0) {
+ perror("Can't get port settings");
+ return -1;
+ }
+
+ if (set_speed(fd, &ti, def_speed) < 0) {
+ perror("Can't set initial baud rate");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void read_event(int fd, unsigned char *buffer)
+{
+ int i = 0;
+ int len = 3;
+ int count;
+
+ while ((count = read(fd, &buffer[i], len)) < len)
+ {
+ i += count;
+ len -= count;
+ }
+
+ i += count;
+ len = buffer[2];
+
+ while ((count = read(fd, &buffer[i], len)) < len)
+ {
+ i += count;
+ len -= count;
+ }
+
+ if (g_dump_debug)
+ {
+ count += i;
+
+ fprintf(stderr, "received %d\n", count);
+ debug_dump(buffer, count);
+ }
+}
+
+static void xradio_hci_send_cmd(int fd, unsigned char *buf, int len)
+{
+ if (g_dump_debug)
+ {
+ fprintf(stderr, "writing\n");
+ debug_dump(buf, len);
+ }
+
+ write(fd, buf, len);
+}
+
+static void proc_reset(int fd)
+{
+ /* signal(SIGALRM, expired); */
+
+ xradio_hci_send_cmd(fd, hci_reset, sizeof(hci_reset));
+ /* alarm(4); */
+ read_event(fd, g_trans_buf);
+ /* alarm(0); */
+}
+
+static void proc_baudrate(int fd, int speed)
+{
+ xradio_hci_send_cmd(fd, hci_update_baud_rate, sizeof(hci_update_baud_rate));
+
+ read_event(fd, g_trans_buf);
+
+ userial_vendor_set_baud(fd, speed);
+ ms_delay(100);
+
+ if (g_dump_debug)
+ {
+ fprintf(stderr, "Done setting baudrate\n");
+ }
+}
+
+static void proc_bdaddr(int fd)
+{
+ xradio_hci_send_cmd(fd, hci_write_bd_addr, sizeof(hci_write_bd_addr));
+
+ read_event(fd, g_trans_buf);
+}
+
+static void proc_enable_hci(int fd)
+{
+ int i = N_HCI;
+ int proto = HCI_UART_H4;
+ if (ioctl(fd, TIOCSETD, &i) < 0) {
+ fprintf(stderr, "Can't set line discipline\n");
+ return;
+ }
+
+ if (ioctl(fd, HCIUARTSETPROTO, proto) < 0) {
+ fprintf(stderr, "Can't set hci protocol\n");
+ return;
+ }
+ fprintf(stderr, "Done setting line discpline\n");
+ return;
+}
+
+static int init_rfkill(void)
+{
+ char path[64];
+ char buf[16];
+ int fd, sz, id;
+
+ for (id = 0; ; id++)
+ {
+ snprintf(path, sizeof(path), "/sys/class/rfkill/rfkill%d/type", id);
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ {
+ printf("init_rfkill : open(%s) failed: %s (%d).\n", \
+ path, strerror(errno), errno);
+ return -1;
+ }
+
+ sz = read(fd, &buf, sizeof(buf));
+ close(fd);
+
+ if (sz >= 9 && memcmp(buf, "bluetooth", 9) == 0)
+ {
+ rfkill_id = id;
+ break;
+ }
+ }
+
+ asprintf(&rfkill_state_path, "/sys/class/rfkill/rfkill%d/state", rfkill_id);
+ return 0;
+}
+
+static int upio_set_bluetooth_power(int on)
+{
+ int sz;
+ int fd = -1;
+ int ret = -1;
+ char buffer = '0';
+
+ switch(on) {
+ case UPIO_BT_POWER_OFF:
+ buffer = '0';
+ break;
+ case UPIO_BT_POWER_ON:
+ buffer = '1';
+ break;
+ }
+
+ fd = open(rfkill_state_path, O_WRONLY);
+
+ if (fd < 0)
+ {
+ printf("set_bluetooth_power : open(%s) for write failed: %s (%d).\n",
+ rfkill_state_path, strerror(errno), errno);
+ return ret;
+ }
+
+ sz = write(fd, &buffer, 1);
+
+ if (sz < 0)
+ {
+ printf("set_bluetooth_power : write(%s) failed: %s (%d).\n",
+ rfkill_state_path, strerror(errno),errno);
+ }
+ else
+ ret = 0;
+
+ if (fd >= 0)
+ close(fd);
+
+ return ret;
+}
+
+static void upio_init(void)
+{
+ memset(upio_state, UPIO_UNKNOWN, UPIO_MAX_COUNT);
+ memset(&lpm_proc_cb, 0, sizeof(vnd_lpm_proc_cb_t));
+}
+
+static void upio_cleanup(void)
+{
+ if (lpm_proc_cb.timer_created == 1)
+ //timer_delete(lpm_proc_cb.timer_id);
+ ;
+ lpm_proc_cb.timer_created = 0;
+}
+
+static void upio_set(uint8_t pio, uint8_t action, uint8_t polarity)
+{
+ UNUSED(polarity);
+ int rc;
+#if (BT_WAKE_VIA_PROC == 1)
+ int fd = -1;
+ char buffer;
+#endif
+
+ switch (pio)
+ {
+ case UPIO_LPM_MODE:
+ printf("set LPM mode:%s", lpm_mode[action]);
+ if (upio_state[UPIO_LPM_MODE] == action)
+ {
+ printf("LPM is %s already", lpm_mode[action]);
+ return;
+ }
+ upio_state[UPIO_LPM_MODE] = action;
+
+#if (BT_WAKE_VIA_PROC == 1)
+ fd = open(VENDOR_LPM_PROC_NODE, O_WRONLY);
+ if (fd < 0)
+ {
+ printf("upio_set : open(%s) for write failed: %s (%d)",
+ VENDOR_LPM_PROC_NODE, strerror(errno), errno);
+ return;
+ }
+
+ if (action == UPIO_ASSERT)
+ {
+ buffer = '1';
+ }
+ else
+ {
+ buffer = '0';
+ if (lpm_proc_cb.timer_created == 1)
+ {
+ //timer_delete(lpm_proc_cb.timer_id);
+ lpm_proc_cb.timer_created = 0;
+ }
+ }
+
+ if (write(fd, &buffer, 1) < 0)
+ {
+ printf("upio_set : write(%s) failed: %s (%d)",
+ VENDOR_LPM_PROC_NODE, strerror(errno),errno);
+ }
+ else
+ {
+ if (action == UPIO_ASSERT)
+ {
+ // create btwrite assertion holding timer
+ if (lpm_proc_cb.timer_created == 0)
+ {
+#if 0
+ int status;
+ struct sigevent se;
+ se.sigev_notify = SIGEV_THREAD;
+ se.sigev_value.sival_ptr = &lpm_proc_cb.timer_id;
+ se.sigev_notify_function = proc_btwrite_timeout;
+ se.sigev_notify_attributes = NULL;
+ status = timer_create(CLOCK_MONOTONIC, &se,&lpm_proc_cb.timer_id);
+ if (status == 0)
+ lpm_proc_cb.timer_created = 1;
+#endif
+ }
+ }
+ }
+
+ if (fd >= 0)
+ close(fd);
+#endif
+ break;
+ case UPIO_BT_WAKE:
+ printf("upio_set: UPIO_BT_WAKE");
+
+ if (upio_state[UPIO_BT_WAKE] == action)
+ {
+ printf("BT_WAKE is %s already", lpm_state[action]);
+
+#if (BT_WAKE_VIA_PROC == 1)
+ if (lpm_proc_cb.btwrite_active == 1)
+ /*
+ * The proc btwrite node could have not been updated for
+ * certain time already due to heavy downstream path flow.
+ * In this case, we want to explicity touch proc btwrite
+ * node to keep the bt_wake assertion in the LPM kernel
+ * driver. The current kernel bluesleep LPM code starts
+ * a 10sec internal in-activity timeout timer before it
+ * attempts to deassert BT_WAKE line.
+ */
+#endif
+ return;
+ }
+
+ upio_state[UPIO_BT_WAKE] = action;
+
+#if (BT_WAKE_VIA_PROC == 1)
+
+ // Kick proc btwrite node only at UPIO_ASSERT
+ if (action == UPIO_DEASSERT)
+ {
+ buffer = '0';
+ return;
+ }
+ else
+ {
+ buffer = '1';
+ }
+
+ fd = open(VENDOR_BTWAKE_PROC_NODE, O_WRONLY);
+
+ if (fd < 0)
+ {
+ printf("upio_set : open(%s) for write failed: %s (%d)",
+ VENDOR_BTWAKE_PROC_NODE, strerror(errno), errno);
+ return;
+ }
+
+ if (write(fd, &buffer, 1) < 0)
+ {
+ printf("upio_set : write(%s) failed: %s (%d)",
+ VENDOR_BTWAKE_PROC_NODE, strerror(errno),errno);
+ }
+ else
+ {
+ lpm_proc_cb.btwrite_active = 1;
+
+ if (lpm_proc_cb.timer_created == 1)
+ {
+#if 0
+ struct itimerspec ts;
+
+ ts.it_value.tv_sec = PROC_BTWAKE_TIMER_TIMEOUT_MS/1000;
+ ts.it_value.tv_nsec = 1000*(PROC_BTWAKE_TIMER_TIMEOUT_MS%1000);
+ ts.it_interval.tv_sec = 0;
+ ts.it_interval.tv_nsec = 0;
+
+ timer_settime(lpm_proc_cb.timer_id, 0, &ts, 0);
+#endif
+ }
+ }
+
+ printf("proc btwake assertion");
+
+ if (fd >= 0)
+ close(fd);
+#endif
+
+ break;
+ case UPIO_HOST_WAKE:
+ printf("upio_set: UPIO_HOST_WAKE");
+ break;
+ }
+}
+
+static int com_sync_baudrate(int fd, int def_speed, unsigned int lcr);
+static int com_stream_write(int fd, unsigned int addr, unsigned int len, unsigned char* data);
+static int com_write_byte(int fd, unsigned int addr, unsigned int len, unsigned char* data);
+static int com_set_pc(int fd, unsigned int pc);
+
+static int com_sync_baudrate(int fd, int speed, unsigned int lcr)
+{
+ unsigned int payload_len = 5; /* cmdid(1) + lcr(1) + baud(3) */
+ unsigned char cmdbuff[MB_CMD_HEADER_SIZE + 5] = {0};
+ cmd_sys_setuart_t *cmd = (cmd_sys_setuart_t*)cmdbuff;
+ cmd_ack_t *ack = (cmd_ack_t *)cmdbuff;
+
+ /* fill header */
+ FILL_HEADER_MAGIC(&cmd->h);
+ cmd->h.flags = CMD_HFLAG_CHECK;
+ cmd->h.version = 0;
+ cmd->h.checksum = 0;
+ cmd->h.payload_len = payload_len;
+ /* fill command id */
+ cmd->cmdid = CMD_ID_SETUART;
+ cmd->lcr = lcr;
+ cmd->h.checksum = ~check_sum16(cmdbuff, MB_CMD_HEADER_SIZE + payload_len);
+
+ /* convert host byte order to network byte order */
+ cmd->h.payload_len = SWAP32(cmd->h.payload_len);
+ cmd->h.checksum = SWAP16(cmd->h.checksum);
+ cmd->lcr = SWAP32(cmd->lcr);
+
+ userial_clearbuf(fd, UART_BUF_RXCLEAR|UART_BUF_TXCLEAR);
+ /* send command */
+ userial_write(fd, cmdbuff, MB_CMD_HEADER_SIZE + payload_len);
+ memset(cmdbuff, 0, MB_CMD_HEADER_SIZE + 5);
+ userial_read(fd, cmdbuff, MB_CMD_HEADER_SIZE);
+ /* check header */
+ if (!HEADER_MAGIC_VALID(&ack->h)) {
+ printf("invalid response\n");
+ userial_clearbuf(fd, UART_BUF_RXCLEAR);
+ return -1;
+ } else if (ack->h.flags & CMD_HFLAG_ERROR) {
+ userial_read(fd, cmdbuff + MB_CMD_HEADER_SIZE, 1);
+ printf("resp error flag, type %d\n", ack->err);
+ return -ack->err;
+ } else {
+ if (ack->h.flags & CMD_HFLAG_ACK) {
+ /* convert network byte order to host byte order */
+ ack->h.payload_len = SWAP32(ack->h.payload_len);
+ ack->h.checksum = SWAP16(ack->h.checksum);
+ if (ack->h.payload_len != 0) {
+ printf("data payload len %d != 0\n", ack->h.payload_len);
+ userial_clearbuf(fd, UART_BUF_RXCLEAR);
+ return -1;
+ }
+ if ((ack->h.flags & CMD_HFLAG_CHECK) &&
+ (check_sum16(cmdbuff, MB_CMD_HEADER_SIZE)) != 0xffff) {
+ printf("Set uart mode response checksum error\n");
+ return -1;
+ }
+
+ printf("Set uart mode done\n");
+ userial_vendor_set_baud(fd, speed); // low 24 bits
+ return userial_sync(fd);
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static int com_stream_write(int fd, unsigned int addr, unsigned int len, unsigned char *data)
+{
+ unsigned int payload_len = 11; /* cmdid(1) + addr(4) + dlen(4) + dcs(2) */
+ unsigned char cmdbuff[MB_CMD_HEADER_SIZE + 11] = {0};
+ cmd_seq_wr_t *cmd = (cmd_seq_wr_t *)cmdbuff;
+ cmd_ack_t *ack = (cmd_ack_t *)cmdbuff;
+
+ /* fill header */
+ FILL_HEADER_MAGIC(&cmd->h);
+ cmd->h.flags = CMD_HFLAG_CHECK;
+ cmd->h.version = 0;
+ cmd->h.checksum = 0;
+ cmd->h.payload_len = payload_len;
+ /* fill command id */
+ cmd->cmdid = CMD_ID_SEQWR;
+ /* fill command address, data length,
+ data checksum and command checksum */
+ cmd->addr = addr;
+ cmd->dlen = len;
+ cmd->dcs = ~check_sum16(data, len);
+ cmd->h.checksum = ~check_sum16(cmdbuff, MB_CMD_HEADER_SIZE + payload_len);
+
+ /* convert host byte order to network byte order */
+ cmd->h.payload_len = SWAP32(cmd->h.payload_len);
+ cmd->addr = SWAP32(cmd->addr);
+ cmd->dlen = SWAP32(cmd->dlen);
+ cmd->dcs = SWAP16(cmd->dcs);
+ cmd->h.checksum = SWAP16(cmd->h.checksum);
+
+ /* clear rx buffer */
+ userial_clearbuf(fd, UART_BUF_RXCLEAR|UART_BUF_TXCLEAR);
+ /* send cmd */
+ userial_write(fd, cmdbuff, MB_CMD_HEADER_SIZE + payload_len);
+ userial_read(fd, cmdbuff, MB_CMD_HEADER_SIZE);
+ /* check data */
+ if (!HEADER_MAGIC_VALID(&ack->h)) {
+ printf("invalid response\n");
+ userial_clearbuf(fd, UART_BUF_RXCLEAR|UART_BUF_TXCLEAR);
+ return -1;
+ } else if (ack->h.flags & CMD_HFLAG_ERROR) {
+ userial_read(fd, cmdbuff + MB_CMD_HEADER_SIZE, 1);
+ printf("resp error flag, type %d\n", ack->err);
+ } else {
+ if (ack->h.flags & CMD_HFLAG_ACK) {
+ /* convert network byte order to host byte order */
+ ack->h.payload_len = SWAP32(ack->h.payload_len);
+ ack->h.checksum = SWAP16(ack->h.checksum);
+ if (ack->h.payload_len != 0) {
+ printf("data payload len %d != 0\n", ack->h.payload_len);
+ userial_clearbuf(fd, UART_BUF_RXCLEAR|UART_BUF_TXCLEAR);
+ return -1;
+ }
+ /* check response */
+ if ((ack->h.flags & CMD_HFLAG_CHECK) &&
+ (check_sum16(cmdbuff, MB_CMD_HEADER_SIZE) != 0xffff)) {
+ printf("write data response 0 checksum error\n");
+ return -1;
+ }
+ /* send data */
+ userial_write(fd, data, len);
+ userial_read(fd, cmdbuff, MB_CMD_HEADER_SIZE);
+ /* check data */
+ if (ack->h.flags & CMD_HFLAG_ERROR) {
+ userial_read(fd, cmdbuff + MB_CMD_HEADER_SIZE, 1);
+ printf("resp error flag, type %d\n", ack->err);
+ return -ack->err;
+ } else {
+ if (ack->h.flags & CMD_HFLAG_ACK) {
+ /* convert network byte order to host byte order */
+ ack->h.payload_len = SWAP32(ack->h.payload_len);
+ ack->h.checksum = SWAP16(ack->h.checksum);
+ if (ack->h.payload_len != 0) {
+ printf("data payload len %d != 0\n", ack->h.payload_len);
+ userial_clearbuf(fd, UART_BUF_RXCLEAR|UART_BUF_TXCLEAR);
+ return -1;
+ }
+ /* check response */
+ if ((ack->h.flags & CMD_HFLAG_CHECK) &&
+ (check_sum16(cmdbuff, MB_CMD_HEADER_SIZE) != 0xffff)) {
+ printf("write data response 1 checksum error\n");
+ return -1;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static int com_write_byte(int fd, unsigned int addr, unsigned int len, unsigned char *data)
+{
+ unsigned int payload_len = 5 + len;
+ unsigned char cmdbuff[MB_CMD_HEADER_SIZE + 13] = {0}; /* max 8 bytes data */
+ cmd_rw_t *cmd = (cmd_rw_t *)cmdbuff;
+ cmd_ack_t *ack = (cmd_ack_t *)cmdbuff;
+
+ /* fill header */
+ FILL_HEADER_MAGIC(&cmd->h);
+ cmd->h.flags = CMD_HFLAG_CHECK;
+ cmd->h.version = 0;
+ cmd->h.checksum = 0;
+ cmd->h.payload_len = payload_len; // cmdid(1) + addr(4) + data(len)
+ /* fill command id */
+ cmd->cmdid = len == 1 ? CMD_ID_WRITE1 :
+ len == 2 ? CMD_ID_WRITE2 :
+ len == 4 ? CMD_ID_WRITE4 :
+ len == 8 ? CMD_ID_WRITE8 : CMD_ID_WRITE4;
+ /* fill command address, data and checksum */
+ cmd->addr = addr;
+ memcpy(cmdbuff + sizeof(cmd_rw_t), data, len);
+ cmd->h.checksum = ~check_sum16(cmdbuff, MB_CMD_HEADER_SIZE + payload_len);
+
+ /* convert host byte order to network byte order */
+ cmd->h.payload_len = SWAP32(cmd->h.payload_len);
+ cmd->addr = SWAP32(cmd->addr);
+ cmd->h.checksum = SWAP16(cmd->h.checksum);
+
+ /* clear rx buffer */
+ userial_clearbuf(fd, UART_BUF_RXCLEAR|UART_BUF_TXCLEAR);
+ /* send cmd */
+ userial_write(fd, cmdbuff, MB_CMD_HEADER_SIZE + payload_len);
+ userial_read(fd, cmdbuff, MB_CMD_HEADER_SIZE);
+
+ /* check data */
+ if (!HEADER_MAGIC_VALID(&ack->h)) {
+ printf("invalid response\n");
+ userial_clearbuf(fd, UART_BUF_RXCLEAR|UART_BUF_TXCLEAR);
+ return -1;
+ } else if (ack->h.flags & CMD_HFLAG_ERROR) {
+ userial_read(fd, cmdbuff + MB_CMD_HEADER_SIZE, 1);
+ printf("resp error flag, type %d\n", ack->err);
+ return -ack->err;
+ } else {
+ if (ack->h.flags & CMD_HFLAG_ACK) {
+ /* convert network byte order to host byte order */
+ ack->h.payload_len = SWAP32(ack->h.payload_len);
+ ack->h.checksum = SWAP16(ack->h.checksum);
+ if (ack->h.payload_len != 0) {
+ printf("data payload len %d != 0\n", ack->h.payload_len);
+ userial_clearbuf(fd, UART_BUF_RXCLEAR|UART_BUF_TXCLEAR);
+ return -1;
+ }
+ /* check response */
+ if ((ack->h.flags & CMD_HFLAG_CHECK) &&
+ (check_sum16(cmdbuff, MB_CMD_HEADER_SIZE) != 0xffff)) {
+ printf("write data response checksum error\n");
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int com_set_pc(int fd, unsigned int pc)
+{
+ unsigned int payload_len = 5; /* cmdid(1) + PC addr(4) */
+ unsigned char cmdbuff[MB_CMD_HEADER_SIZE + 5] = {0};
+ cmd_sys_t *cmd = (cmd_sys_t*)cmdbuff;
+ cmd_ack_t *ack = (cmd_ack_t *)cmdbuff;
+
+ /* fill header */
+ FILL_HEADER_MAGIC(&cmd->h);
+ cmd->h.flags = CMD_HFLAG_CHECK;
+ cmd->h.version = 0;
+ cmd->h.checksum = 0;
+ cmd->h.payload_len = payload_len;
+ /* fill command id */
+ cmd->cmdid = CMD_ID_SETPC;
+ cmd->val = pc;
+ cmd->h.checksum = ~check_sum16(cmdbuff, MB_CMD_HEADER_SIZE + payload_len);
+ /* convert host byte order to network byte order */
+ cmd->h.payload_len = SWAP32(cmd->h.payload_len);
+ cmd->h.checksum = SWAP16(cmd->h.checksum);
+ cmd->val = SWAP32(cmd->val);
+ printf("set pc %x, val %x\n", pc, cmd->val);
+
+ /* clear rx buffer */
+ userial_clearbuf(fd, UART_BUF_RXCLEAR|UART_BUF_TXCLEAR);
+ /* send command */
+ userial_write(fd, cmdbuff, MB_CMD_HEADER_SIZE + payload_len);
+ userial_read(fd, cmdbuff, MB_CMD_HEADER_SIZE);
+ /* check header */
+ if (!HEADER_MAGIC_VALID(&ack->h)) {
+ printf("invalid response\n");
+ userial_clearbuf(fd, UART_BUF_RXCLEAR|UART_BUF_TXCLEAR);
+ return -1;
+ } else if (ack->h.flags & CMD_HFLAG_ERROR) {
+ userial_read(fd, cmdbuff + MB_CMD_HEADER_SIZE, 1);
+ printf("resp error flag, type %d\n", ack->err);
+ return -ack->err;
+ } else {
+ if (ack->h.flags & CMD_HFLAG_ACK) {
+ /* convert network byte order to host byte order */
+ ack->h.payload_len = SWAP32(ack->h.payload_len);
+ ack->h.checksum = SWAP16(ack->h.checksum);
+ if (ack->h.payload_len != 0) {
+ printf("data payload len %d != 0\n", ack->h.payload_len);
+ userial_clearbuf(fd, UART_BUF_RXCLEAR|UART_BUF_TXCLEAR);
+ return -1;
+ }
+ if ((ack->h.flags & CMD_HFLAG_CHECK) &&
+ (check_sum16(cmdbuff, MB_CMD_HEADER_SIZE)) != 0xffff) {
+ printf("Set PC response checksum error\n");
+ return -1;
+ }
+ printf("Now the system will jump to %08x\n", pc);
+ }
+ }
+ return 0;
+}
+
+static int load_btfirmware(int fd)
+{
+ FILE* fwfile_fd = NULL;
+ unsigned int filesize, len;
+ unsigned char *data = NULL;
+ unsigned int addr = g_load_addr;
+ unsigned char flag_value[4] = {0xFF, 0xFF, 0xFF, 0xFF};
+
+ printf("[%s] start loading firmware...\n", __FUNCTION__);
+
+ fwfile_fd = fopen(BT_FW_PATH_NAME, "rb");
+ if(!fwfile_fd)
+ return -1;
+
+ printf("[%s] open firmware file success.\n", __FUNCTION__);
+
+ fseek(fwfile_fd, 0, SEEK_END);
+ filesize = ftell(fwfile_fd);
+ fseek(fwfile_fd, 0, SEEK_SET);
+ len = filesize;
+ len = len > SZ_1K ? SZ_1K : len;
+ data = (unsigned char*)malloc(len);
+ if (data == NULL) {
+ printf("failed to alloc %d byte memory\n", len);
+ fclose(fwfile_fd);
+ return -1;
+ }
+
+ do {
+ len = filesize;
+ len = (len > SZ_1K) ? SZ_1K : len;
+ fread(data, 1, len, fwfile_fd);
+ com_stream_write(fd, addr, len, data);
+ addr += len;
+ filesize -= len;
+ printf("remain len:\t0x%04X.\n", filesize);
+ } while(filesize);
+ free(data);
+ fclose(fwfile_fd);
+ printf("load firmware done.\n");
+
+ /* jump */
+ printf("jump:\n");
+ com_set_pc(fd, g_jump_addr);
+
+ if(g_chip_name == 2)
+ {
+ printf("\nsecond time sync starting....\n");
+ if(userial_sync(fd) < 0)
+ return -1;
+ com_set_pc(fd, g_jump_addr);
+ }
+ return addr;
+}
+
+int xradio_init(int fd, int def_speed, int speed, struct termios *ti,
+ const char *bdaddr)
+{
+ printf("xradio_init\n");
+
+ if (init_rfkill())
+ return -1;
+
+ if (upio_set_bluetooth_power(UPIO_BT_POWER_OFF))
+ return -1;
+ usleep(500000);
+
+ if (upio_set_bluetooth_power(UPIO_BT_POWER_ON))
+ return -1;
+ usleep(20000);
+
+ upio_init();
+ upio_set(UPIO_LPM_MODE, UPIO_DEASSERT, 0);
+ usleep(50000);
+
+ if (userial_sync(fd))
+ return -1;
+
+ if (com_sync_baudrate(fd, speed, speed | (3 << 24)))
+ return -1;
+
+ if (load_btfirmware(fd) < 0)
+ return -1;
+
+ usleep(50000);
+
+ userial_vendor_set_baud(fd, def_speed);
+ usleep(100000);
+ userial_vendor_set_hw_fctrl(fd, 1);
+ usleep(100000);
+
+ if (g_startup_reset_flag) {
+ printf("[%s] send reset cmd...\n", __FUNCTION__);
+ proc_reset(fd);
+ }
+
+ if (g_update_hcirate_flag) {
+ printf("[%s] update hci baudrate...\n", __FUNCTION__);
+ proc_baudrate(fd, speed);
+ }
+
+ if (g_bdaddr_flag) {
+ printf("[%s] set bdaddr...\n", __FUNCTION__);
+ proc_bdaddr(fd);
+ }
+
+ if (g_hciup_flag) {
+ printf("[%s] bring up hci...\n", __FUNCTION__);
+ proc_enable_hci(fd);
+ }
+
+ return 0;
+}