/**
 *    @brief BT process calibration data
 *
 *    @param priv    a pointer to bt_private structure
 *    @param data    a pointer to cal data
 *    @param size    cal data size
 *    @param mac     mac address buf
 *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
 */
int
bt_process_cal_cfg(bt_private * priv, u8 * data, u32 size, char *mac)
{
	u8 bt_mac[ETH_ALEN];
	u8 cal_data[32];
	u8 *mac_data = NULL;
	u32 cal_data_len;
	int ret = BT_STATUS_FAILURE;

	memset(bt_mac, 0, sizeof(bt_mac));
	cal_data_len = sizeof(cal_data);
	if (BT_STATUS_SUCCESS !=
	    bt_parse_cal_cfg(data, size, cal_data, &cal_data_len)) {
		goto done;
	}
	if (mac != NULL) {
		/* Convert MAC format */
		bt_mac2u8(bt_mac, mac);
		PRINTM(CMD, "HCI: new BT Address " MACSTR "\n",
		       MAC2STR(bt_mac));
		mac_data = bt_mac;
	}
	if (BT_STATUS_SUCCESS != bt_load_cal_data(priv, cal_data, mac_data)) {
		PRINTM(FATAL, "BT: Fail to load calibrate data\n");
		goto done;
	}
	ret = BT_STATUS_SUCCESS;

done:
	LEAVE();
	return ret;
}
/**
 *    @brief BT process calibration data
 *
 *    @param priv    a pointer to bt_private structure
 *    @param data    a pointer to cal data
 *    @param size    cal data size
 *    @param mac     mac address buf
 *    @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
 */
int
bt_process_cal_cfg(bt_private * priv, u8 * data, u32 size, char *mac)
{
	u8 bt_mac[ETH_ALEN];
	u8 cal_data[32];
	int ret = BT_STATUS_FAILURE;

	memset(bt_mac, 0, sizeof(bt_mac));
	bt_parse_cal_cfg(data, size, cal_data, sizeof(cal_data));
	if (mac != NULL) {
		/* Convert MAC format */
		bt_mac2u8(bt_mac, mac);
		PRINTM(CMD,
		       "HCI: new BT Address %02x:%02x:%02x:%02x:%02x:%02x\n",
		       bt_mac[0], bt_mac[1], bt_mac[2], bt_mac[3], bt_mac[4],
		       bt_mac[5]);
		if (BT_STATUS_SUCCESS !=
		    bt_load_cal_data(priv, cal_data, bt_mac)) {
			PRINTM(FATAL, "BT: Fail to load calibrate data\n");
			goto done;
		}
	} else {
		if (BT_STATUS_SUCCESS != bt_load_cal_data(priv, cal_data, NULL)) {
			PRINTM(FATAL, "BT: Fail to load calibrate data\n");
			goto done;
		}
	}

	ret = BT_STATUS_SUCCESS;

done:
	LEAVE();
	return ret;
}
/**
 *    @brief BT init mac address from bt_mac parametre when insmod
 *
 *    @param priv    a pointer to bt_private structure
 *    @param bt_mac  mac address buf
 *    @return        BT_STATUS_SUCCESS or BT_STATUS_FAILURE
 */
int
bt_init_mac_address(bt_private * priv, char *mac)
{
	u8 bt_mac[ETH_ALEN];
	int ret = BT_STATUS_FAILURE;

	ENTER();
	memset(bt_mac, 0, sizeof(bt_mac));
	bt_mac2u8(bt_mac, mac);
	PRINTM(CMD, "HCI: New BT Address " MACSTR "\n", MAC2STR(bt_mac));
	ret = bt_set_mac_address(priv, bt_mac);
	if (ret != BT_STATUS_SUCCESS)
		PRINTM(FATAL,
		       "BT: Fail to set mac address from insmod parametre.\n");

	LEAVE();
	return ret;
}
/**
 *    @brief BT parse ASCII format data to MAC address
 *
 *    @param priv          BT private handle
 *    @param data          Source data
 *    @param size          data length
 *    @return              BT_STATUS_SUCCESS or BT_STATUS_FAILURE
 */
int
bt_process_init_cfg(bt_private * priv, u8 * data, u32 size)
{
	u8 *pos;
	u8 *intf_s, *intf_e;
	u8 s[MAX_LINE_LEN];	/* 1 line data */
	u32 line_len;
	char dev_name[MAX_PARAM_LEN];
	u8 buf[MAX_PARAM_LEN];
	u8 bt_addr[MAX_MAC_ADDR_LEN];
	u8 bt_mac[ETH_ALEN];
	int setting = 0;
	u8 type = 0;
	u16 value = 0;
	u32 offset = 0;
	int ret = BT_STATUS_FAILURE;

	memset(dev_name, 0, sizeof(dev_name));
	memset(bt_addr, 0, sizeof(bt_addr));
	memset(bt_mac, 0, sizeof(bt_mac));

	while ((line_len = parse_cfg_get_line(data, size, s)) != -1) {
		pos = s;
		while (*pos == ' ' || *pos == '\t')
			pos++;

		if (*pos == '#' || (*pos == '\r' && *(pos + 1) == '\n') ||
		    *pos == '\n' || *pos == '\0')
			continue;	/* Need n't process this line */

		/* Process MAC addr */
		if (strncmp(pos, "mac_addr", 8) == 0) {
			intf_s = strchr(pos, '=');
			if (intf_s != NULL)
				intf_e = strchr(intf_s, ':');
			else
				intf_e = NULL;
			if (intf_s != NULL && intf_e != NULL) {
				if ((intf_e - intf_s) > MAX_PARAM_LEN) {
					PRINTM(ERROR,
					       "BT: Too long interface name %d\n",
					       __LINE__);
					goto done;
				}
				strncpy(dev_name, intf_s + 1,
					intf_e - intf_s - 1);
				dev_name[intf_e - intf_s - 1] = '\0';
				if (strcmp
				    (dev_name,
				     priv->bt_dev.m_dev[BT_SEQ].name) == 0) {
					/* found hci device */
					strncpy(bt_addr, intf_e + 1,
						MAX_MAC_ADDR_LEN - 1);
					bt_addr[MAX_MAC_ADDR_LEN - 1] = '\0';
					/* Convert MAC format */
					bt_mac2u8(bt_mac, bt_addr);
					PRINTM(CMD,
					       "HCI: %s new BT Address " MACSTR
					       "\n", dev_name, MAC2STR(bt_mac));
					if (BT_STATUS_SUCCESS !=
					    bt_set_mac_address(priv, bt_mac)) {
						PRINTM(FATAL,
						       "BT: Fail to set mac address\n");
						goto done;
					}
				}
			} else {
				PRINTM(ERROR,
				       "BT: Wrong config file format %d\n",
				       __LINE__);
				goto done;
			}
		}
		/* Process REG value */
		else if (strncmp(pos, "bt_reg", 6) == 0) {
			intf_s = strchr(pos, '=');
			if (intf_s != NULL)
				intf_e = strchr(intf_s, ',');
			else
				intf_e = NULL;
			if (intf_s != NULL && intf_e != NULL) {
				/* Copy type */
				memset(buf, 0, sizeof(buf));
				strncpy(buf, intf_s + 1, 1);
				buf[1] = '\0';
				if (0 == bt_atoi(&setting, buf))
					type = (u8) setting;
				else {
					PRINTM(ERROR,
					       "BT: Fail to parse reg type\n");
					goto done;
				}
			} else {
				PRINTM(ERROR,
				       "BT: Wrong config file format %d\n",
				       __LINE__);
				goto done;
			}
			intf_s = intf_e + 1;
				intf_e = strchr(intf_s, ',');
			if (intf_e != NULL) {
				if ((intf_e - intf_s) >= MAX_PARAM_LEN) {
					PRINTM(ERROR,
					       "BT: Regsier offset is too long %d\n",
					       __LINE__);
					goto done;
				}
				/* Copy offset */
				memset(buf, 0, sizeof(buf));
				strncpy(buf, intf_s, intf_e - intf_s);
				buf[intf_e - intf_s] = '\0';
				if (0 == bt_atoi(&setting, buf))
					offset = (u32) setting;
				else {
					PRINTM(ERROR,
					       "BT: Fail to parse reg offset\n");
					goto done;
				}
			} else {
				PRINTM(ERROR,
				       "BT: Wrong config file format %d\n",
				       __LINE__);
				goto done;
			}
			intf_s = intf_e + 1;
				if ((strlen(intf_s) >= MAX_PARAM_LEN)) {
					PRINTM(ERROR,
					       "BT: Regsier value is too long %d\n",
					       __LINE__);
					goto done;
				}
				/* Copy value */
				memset(buf, 0, sizeof(buf));
			strncpy(buf, intf_s, sizeof(buf));
				if (0 == bt_atoi(&setting, buf))
					value = (u16) setting;
				else {
				PRINTM(ERROR, "BT: Fail to parse reg value\n");
				goto done;
			}

			PRINTM(CMD,
			       "BT: Write reg type: %d offset: 0x%x value: 0x%x\n",
			       type, offset, value);
			if (BT_STATUS_SUCCESS !=
			    bt_write_reg(priv, type, offset, value)) {
				PRINTM(FATAL,
				       "BT: Write reg failed. type: %d offset: 0x%x value: 0x%x\n",
				       type, offset, value);
				goto done;
			}
		}
	}
	ret = BT_STATUS_SUCCESS;

done:
	LEAVE();
	return ret;
}