/******************************************************************************* ** ** Function hw_config_start ** ** Description Kick off controller initialization process ** ** Returns None ** *******************************************************************************/ void hw_config_start(void) { HC_BT_HDR *p_buf = NULL; uint8_t *p; ALOGI("hw_config_start"); hw_cfg_cb.state = 0; hw_cfg_cb.fw_fd = -1; hw_cfg_cb.f_set_baud_2 = FALSE; strcpy(hw_cfg_cb.local_chip_name, AT_CHIP_NAME); ALOGI("Bluetooth Firmware and smd is initialized"); ALOGI("Atmel: local bd address: %02x:%02x:%02x:%02x:%02x:%02x:", vnd_local_bd_addr[0],vnd_local_bd_addr[1],vnd_local_bd_addr[2], vnd_local_bd_addr[3],vnd_local_bd_addr[4],vnd_local_bd_addr[5]); if(vnd_userial.enable_bdaddress_change != 0) { hw_config_set_bdaddr(vnd_userial.bd_addr); hw_config_reset(); } bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS); }
/******************************************************************************* ** ** Function hw_config_cback ** ** Description Callback function for controller configuration ** ** Returns None ** *******************************************************************************/ void hw_config_cback(void *p_mem) { HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem; char *p_name, *p_tmp; uint8_t *p, status; uint16_t opcode; HC_BT_HDR *p_buf=NULL; uint8_t is_proceeding = FALSE; int i; #if (USE_CONTROLLER_BDADDR == TRUE) const uint8_t null_bdaddr[BD_ADDR_LEN] = {0,0,0,0,0,0}; #endif status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE); p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE; STREAM_TO_UINT16(opcode,p); /* Ask a new buffer big enough to hold any HCI commands sent in here */ if ((status == 0) && bt_vendor_cbacks) p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \ HCI_CMD_MAX_LEN); if (p_buf != NULL) { p_buf->event = MSG_STACK_TO_HC_HCI_CMD; p_buf->offset = 0; p_buf->len = 0; p_buf->layer_specific = 0; p = (uint8_t *) (p_buf + 1); switch (hw_cfg_cb.state) { case HW_CFG_SET_UART_BAUD_1: /* update baud rate of host's UART port */ ALOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE); userial_vendor_set_baud( \ line_speed_to_userial_baud(UART_TARGET_BAUD_RATE) \ ); /* read local name */ UINT16_TO_STREAM(p, HCI_READ_LOCAL_NAME); *p = 0; /* parameter length */ p_buf->len = HCI_CMD_PREAMBLE_SIZE; hw_cfg_cb.state = HW_CFG_READ_LOCAL_NAME; is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_NAME, \ p_buf, hw_config_cback); break; case HW_CFG_READ_LOCAL_NAME: p_tmp = p_name = (char *) (p_evt_buf + 1) + \ HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING; for (i=0; (i < LOCAL_NAME_BUFFER_LEN)||(*(p_name+i) != 0); i++) *(p_name+i) = toupper(*(p_name+i)); if ((p_name = strstr(p_name, "BCM")) != NULL) { strncpy(hw_cfg_cb.local_chip_name, p_name, \ LOCAL_NAME_BUFFER_LEN-1); } else { strncpy(hw_cfg_cb.local_chip_name, "UNKNOWN", \ LOCAL_NAME_BUFFER_LEN-1); p_name = p_tmp; } hw_cfg_cb.local_chip_name[LOCAL_NAME_BUFFER_LEN-1] = 0; BTHWDBG("Chipset %s", hw_cfg_cb.local_chip_name); if ((status = hw_config_findpatch(p_name)) == TRUE) { if ((hw_cfg_cb.fw_fd = open(p_name, O_RDONLY)) == -1) { ALOGE("vendor lib preload failed to open [%s]", p_name); } else { /* vsc_download_minidriver */ UINT16_TO_STREAM(p, HCI_VSC_DOWNLOAD_MINIDRV); *p = 0; /* parameter length */ p_buf->len = HCI_CMD_PREAMBLE_SIZE; hw_cfg_cb.state = HW_CFG_DL_MINIDRIVER; is_proceeding = bt_vendor_cbacks->xmit_cb( \ HCI_VSC_DOWNLOAD_MINIDRV, p_buf, \ hw_config_cback); } } else { ALOGE( \ "vendor lib preload failed to locate firmware patch file" \ ); } if (is_proceeding == FALSE) { is_proceeding = hw_config_set_bdaddr(p_buf); } break; case HW_CFG_DL_MINIDRIVER: /* give time for placing firmware in download mode */ ms_delay(50); hw_cfg_cb.state = HW_CFG_DL_FW_PATCH; /* fall through intentionally */ case HW_CFG_DL_FW_PATCH: p_buf->len = read(hw_cfg_cb.fw_fd, p, HCI_CMD_PREAMBLE_SIZE); if (p_buf->len > 0) { if ((p_buf->len < HCI_CMD_PREAMBLE_SIZE) || \ (opcode == HCI_VSC_LAUNCH_RAM)) { ALOGW("firmware patch file might be altered!"); } else { p_buf->len += read(hw_cfg_cb.fw_fd, \ p+HCI_CMD_PREAMBLE_SIZE,\ *(p+HCD_REC_PAYLOAD_LEN_BYTE)); STREAM_TO_UINT16(opcode,p); is_proceeding = bt_vendor_cbacks->xmit_cb(opcode, \ p_buf, hw_config_cback); break; } } close(hw_cfg_cb.fw_fd); hw_cfg_cb.fw_fd = -1; /* Normally the firmware patch configuration file * sets the new starting baud rate at 115200. * So, we need update host's baud rate accordingly. */ ALOGI("bt vendor lib: set UART baud 115200"); userial_vendor_set_baud(USERIAL_BAUD_115200); /* Next, we would like to boost baud rate up again * to desired working speed. */ hw_cfg_cb.f_set_baud_2 = TRUE; /* Check if we need to pause a few hundred milliseconds * before sending down any HCI command. */ ms_delay(look_up_fw_settlement_delay()); /* fall through intentionally */ case HW_CFG_START: if (UART_TARGET_BAUD_RATE > 3000000) { /* set UART clock to 48MHz */ UINT16_TO_STREAM(p, HCI_VSC_WRITE_UART_CLOCK_SETTING); *p++ = 1; /* parameter length */ *p = 1; /* (1,"UART CLOCK 48 MHz")(2,"UART CLOCK 24 MHz") */ p_buf->len = HCI_CMD_PREAMBLE_SIZE + 1; hw_cfg_cb.state = HW_CFG_SET_UART_CLOCK; is_proceeding = bt_vendor_cbacks->xmit_cb( \ HCI_VSC_WRITE_UART_CLOCK_SETTING, \ p_buf, hw_config_cback); break; } /* fall through intentionally */ case HW_CFG_SET_UART_CLOCK: /* set controller's UART baud rate to 3M */ UINT16_TO_STREAM(p, HCI_VSC_UPDATE_BAUDRATE); *p++ = UPDATE_BAUDRATE_CMD_PARAM_SIZE; /* parameter length */ *p++ = 0; /* encoded baud rate */ *p++ = 0; /* use encoded form */ UINT32_TO_STREAM(p, UART_TARGET_BAUD_RATE); p_buf->len = HCI_CMD_PREAMBLE_SIZE + \ UPDATE_BAUDRATE_CMD_PARAM_SIZE; hw_cfg_cb.state = (hw_cfg_cb.f_set_baud_2) ? \ HW_CFG_SET_UART_BAUD_2 : HW_CFG_SET_UART_BAUD_1; is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_VSC_UPDATE_BAUDRATE, \ p_buf, hw_config_cback); break; case HW_CFG_SET_UART_BAUD_2: /* update baud rate of host's UART port */ ALOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE); userial_vendor_set_baud( \ line_speed_to_userial_baud(UART_TARGET_BAUD_RATE) \ ); #if (USE_CONTROLLER_BDADDR == TRUE) if ((is_proceeding = hw_config_read_bdaddr(p_buf)) == TRUE) break; #else if ((is_proceeding = hw_config_set_bdaddr(p_buf)) == TRUE) break; #endif /* fall through intentionally */ case HW_CFG_SET_BD_ADDR: ALOGI("vendor lib fwcfg completed"); bt_vendor_cbacks->dealloc(p_buf); bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS); hw_cfg_cb.state = 0; if (hw_cfg_cb.fw_fd != -1) { close(hw_cfg_cb.fw_fd); hw_cfg_cb.fw_fd = -1; } is_proceeding = TRUE; break; #if (USE_CONTROLLER_BDADDR == TRUE) case HW_CFG_READ_BD_ADDR: p_tmp = (char *) (p_evt_buf + 1) + \ HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY; if (memcmp(p_tmp, null_bdaddr, BD_ADDR_LEN) == 0) { // Controller does not have a valid OTP BDADDR! // Set the BTIF initial BDADDR instead. if ((is_proceeding = hw_config_set_bdaddr(p_buf)) == TRUE) break; } else { ALOGI("Controller OTP bdaddr %02X:%02X:%02X:%02X:%02X:%02X", *(p_tmp+5), *(p_tmp+4), *(p_tmp+3), *(p_tmp+2), *(p_tmp+1), *p_tmp); } ALOGI("vendor lib fwcfg completed"); bt_vendor_cbacks->dealloc(p_buf); bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS); hw_cfg_cb.state = 0; if (hw_cfg_cb.fw_fd != -1) { close(hw_cfg_cb.fw_fd); hw_cfg_cb.fw_fd = -1; } is_proceeding = TRUE; break; #endif // (USE_CONTROLLER_BDADDR == TRUE) } // switch(hw_cfg_cb.state) } // if (p_buf != NULL) /* Free the RX event buffer */ if (bt_vendor_cbacks) bt_vendor_cbacks->dealloc(p_evt_buf); if (is_proceeding == FALSE) { ALOGE("vendor lib fwcfg aborted!!!"); if (bt_vendor_cbacks) { if (p_buf != NULL) bt_vendor_cbacks->dealloc(p_buf); bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL); } if (hw_cfg_cb.fw_fd != -1) { close(hw_cfg_cb.fw_fd); hw_cfg_cb.fw_fd = -1; } hw_cfg_cb.state = 0; } }