📄 hci_vendor.c
字号:
break; case 460800: baud_divider = CSR_UART_RATE_460K8; break; case 921600: baud_divider = CSR_UART_RATE_921K6; break; default: D_ERR(__FUNCTION__ VENDOR ": Baudrate %u not supported\n", baudrate); return -EINVAL; } /* HCI Manufacturer specific header */ c_pkt.type = CMD_PKT; c_pkt.opcode = hci_put_opcode(0x00, MANUFACTURER_SPEC); c_pkt.len = 1 + 5*sizeof(u16) + 4*sizeof(u16); msg = (csr_msg *)c_pkt.data; cmd = (csr_bccmd *)msg->msg; ps = (csr_bccmd_ps *)cmd->payload; /* General msg header */ CSR_SET_LAST(msg, 1); /* first and last segment */ CSR_SET_FIRST(msg, 1); CSR_SET_CH_ID(msg, CSR_CH_ID_BCCMD); cmd->type = CSR_MSGTYPE_SETREQ; cmd->len = 5 + 4; cmd->seq = csr_count++; cmd->var_id = CSR_CMD_CONFIG_UART; cmd->status = CSR_STATUS_OK; /* always OK in SETREQ */ memset(cmd->payload, 0, 4*sizeof(u16)); if (bt_use_bcsp(-1)) { cmd->payload[0] = baud_divider | CSR_UART_EVEN_PARITY | CSR_UART_ONE_STOP_BIT; } else { cmd->payload[0] = baud_divider | CSR_UART_NO_PARITY | CSR_UART_ONE_STOP_BIT; } if (hci_ctrl.hc_buf.cmd_num < 1) { DSYS(__FUNCTION__ VENDOR ": sleeping\n"); interruptible_sleep_on(&set_baudrate_wq); } tmp = bt_write_lower_driver((u8*) &c_pkt, c_pkt.len + CMD_HDR_LEN + HCI_HDR_LEN);#ifdef __KERNEL__ bt_wait_tx(2000); /* wait until DMA empty + 2 ms */#endif hci_ctrl.hc_buf.cmd_num--; return tmp;}//#define VERBOSEvoidprocess_vendor_event(u8 *buf, u32 len, u32 event_code){ csr_msg *msg; csr_bccmd *cmd; csr_bccmd_ps *ps; D_REC(__FUNCTION__ VENDOR "\n"); /* FIXME -- is there only one cmd buffer available ? */ hci_ctrl.hc_buf.cmd_num = 1; release_cmd_timer(); msg = (struct csr_msg *)buf; cmd = (struct csr_bccmd *)msg->msg; ps = (struct csr_bccmd_ps *)cmd->payload; switch (CSR_GET_CH_ID(msg)) { case CSR_CH_ID_BCCMD: if (cmd->type == CSR_MSGTYPE_GETRESP && cmd->status == CSR_STATUS_OK) { switch (cmd->var_id) { case CSR_CMD_CONFIG_UART: break; case CSR_CMD_BUILD_ID: /* Store this for later retrieval */ sprintf(bt_hw_firmware_info, "\n Firmware version: %d", cmd->payload[0]); break; case CSR_CMD_CHIP_VER: break; case CSR_CMD_CHIP_REV: break; case CSR_CMD_PS: D_CMD(__FUNCTION__": ps key[0x%x]\n", ps->ps_key); PRINTPKT("", (u8*)ps->ps_val, ps->ps_len*sizeof(u16)); /* Now copy this data to return buf */ memcpy(ps_retbuf, ps->ps_val, ps->ps_len*sizeof(u16)); break; default: break; } } break; case CSR_CH_ID_HQ: switch (cmd->var_id) { case CSR_VARID_RSSI_REPORT: { csr_rssi_rep *rep; rep = (csr_rssi_rep *)cmd->payload; DSYS("RSSI report, rssi : %d\n", rep->rssi); break; } case CSR_VARID_PACKET_STAT_REPORT: { csr_packstat_rep *rep; rep = (struct csr_packstat_rep*)cmd->payload; DSYS("Packet status report : n_pkts %d, n_good %d, n_corr %d, rssi %d, rssi_valid %d\n", rep->n_pkts, rep->n_good, rep->n_corr, rep->rssi, rep->rssi_valid); break; } case CSR_VARID_BITERR_REPORT: { csr_biterr_rep *rep; rep = (struct csr_biterr_rep*)cmd->payload; DSYS("Biterror report : index %d, val_last %d, val_tot %d\n", rep->index, rep->val_last, rep->val_tot); break; } } break; default: D_ERR("Unknown varid [0x%x]!\n", cmd->var_id); break; } #ifdef VERBOSE printk("msg: last: %d, first: %d, chID: %d\n", CSR_GET_LAST(msg), CSR_GET_FIRST(msg), CSR_GET_CH_ID(msg)); printk("cmd: type: 0x%04X, msg_len: %d, seq_nbr: %d, varid: 0x%04X, status: 0x%04X\n", cmd->type, cmd->len, cmd->seq, cmd->var_id, cmd->status); switch (CSR_GET_CH_ID(msg)) { case CSR_CH_ID_BCCMD: printk("BCCMD MSG\n"); switch (cmd->type) { case CSR_MSGTYPE_GETREQ: printk("GETREQ\n"); break; case CSR_MSGTYPE_GETRESP: printk("GETRESP\n"); break; case CSR_MSGTYPE_SETREQ: printk("SETREQ\n"); break; default: break; } if (cmd->status == CSR_STATUS_OK) printk("Command successful\n"); if (cmd->type == CSR_MSGTYPE_GETRESP && cmd->status == CSR_STATUS_OK) { switch (cmd->var_id) { case CSR_CMD_CONFIG_UART: printk("UART config: 0x%04X\n", cmd->payload[0]); break; case CSR_CMD_BUILD_ID: printk("Firmware version: %d\n", cmd->payload[0]); break; case CSR_CMD_CHIP_VER: printk("Chip Version: %d\n", cmd->payload[0]); break; case CSR_CMD_CHIP_REV: printk("Chip Revision: %d\n", cmd->payload[0]); break; case CSR_CMD_PS: break; default: break; } } break; case CSR_CH_ID_HQ: printk("HQ MSG\n"); break; default: printk("Unknown MSG type\n"); break; }#endif /* VERBOSE */ /* FIXME -- if using raw interface we haven't slept */ wake_up_interruptible(&hci_wq); }voidprocess_vendor_return_param(u32 ocf, u8* r_val){ D_ERR(__FUNCTION__ VENDOR " Manufacturer specific: Invalid reply (0x%x)\n", ocf);}char*bt_hw_vendor(void){ return "CSR";}#elif defined(CONFIG_BLUETOOTH_INFINEON_BMI)/*****************************************************************************//***************** Functions for Infineon BlueMoon I chips *******************//*****************************************************************************/#define VENDOR " [Infineon]"s32hci_set_bd_addr(u8 bd[6]){ D_ERR(__FUNCTION__ VENDOR " not supported.\n"); return 0;}s32hci_read_firmware_rev_info(void){ D_CMD(__FUNCTION__ VENDOR "\n"); c_pkt.type = CMD_PKT; c_pkt.opcode = hci_put_opcode(0x05, MANUFACTURER_SPEC); c_pkt.len = 0; return send_cmd_block((u8*) &c_pkt, c_pkt.len + CMD_HDR_LEN + HCI_HDR_LEN, DEFAULT_TIMEOUT);}s32hci_set_baudrate(u32 baudrate){ u8 pkt[6]; s32 tmp; D_CMD(__FUNCTION__ VENDOR " (%d baud)\n", baudrate); pkt[0] = CMD_PKT; pkt[1] = 0x06; pkt[2] = 0xfc; pkt[3] = 0x02; switch (baudrate) { case 9600: pkt[4] = 3; pkt[5] = 168; break; case 19200: pkt[4] = 2; pkt[5] = 168; break; case 38400: pkt[4] = 1; pkt[5] = 168; break; case 57600: pkt[4] = 0; pkt[5] = 225; break; case 115200: pkt[4] = 0; pkt[5] = 112; break; case 230400: pkt[4] = 0; pkt[5] = 55; break; case 460800: pkt[4] = 0; pkt[5] = 27; break; default: D_ERR(__FUNCTION__ VENDOR ": Baudrate not supported\n"); } tmp = send_cmd(pkt, 6); /* the chip answers with two command complete events, the first using the old baudrate, the second using the new baudrate. The second event is send at least 0.125 seconds after the first to let the host change its baudrate too. */ start_cmd_timer(); interruptible_sleep_on(&hci_wq); return tmp;}voidprocess_vendor_event(u8 *buf, u32 len, u32 event_code){ D_REC(__FUNCTION__ VENDOR "\n"); if (len >= 1) { switch (buf[0]) { case 0x00: printk("Infineon event: Hardware Startup complete.\n"); break; case 0x04: printk("Infineon event: invalid packet length.\n"); break; case 0x05: printk("Infineon event: BD-Data invalid (check EEPROM).\n"); break; case 0x07: printk("Infineon event: invalid packet type.\n"); break; case 0x09: printk("Infineon event: invalid ACL_BC_PB_Flag.\n"); break; case 0x0A: printk("Infineon event: invalid ACL_CNC_Handle.\n"); break; case 0x0B: printk("Infineon event: invalid SCO_CNC_Handle.\n"); break; case 0x0C: printk("Infineon event: low power mode start.\n"); break; case 0x0D: printk("Infineon event: low power mode end.\n"); break; default: D_ERR(__FUNCTION__ VENDOR ": Unknown event\n"); } /* end of switch */ } else { D_ERR(__FUNCTION__ VENDOR ": Invalid event\n"); }}voidprocess_vendor_return_param(u32 ocf, u8* r_val){ static int second = 0; switch (ocf) { case 0x0005: /* read software version */ D_CMD(__FUNCTION__ VENDOR ": Software version\n"); if (r_val[0] != 0) { D_ERR(__FUNCTION__ VENDOR ": Software version read failure\n"); } else { printk("Infineon LM-FW version is: %x.%x%x\n", r_val[2] & 0x0F, r_val[1] >> 4, r_val[1] & 0x0F); printk("Infineon BB-FW version is: %02x%02x\n", r_val[4], r_val[3]); } release_cmd_timer(); wake_up_interruptible(&hci_wq); break; case 0x0006: /* set baudrate */ D_CMD(__FUNCTION__ VENDOR ": Baudrate set\n"); if ((r_val[0] == 0x00) && (second == 0)) { printk("Infineon baudrate changes after this message\n"); second = 1; } else if ((r_val[0] == 0x00) && second) { printk("Infineon baudrate has changed to new value\n"); second = 0; } else { D_ERR(__FUNCTION__ VENDOR ": Baudrate set failure %x\n",r_val[0]); } release_cmd_timer(); wake_up_interruptible(&hci_wq); break; default: release_cmd_timer(); D_ERR(__FUNCTION__ VENDOR " Manufacturer specific: Invalid reply (0x%x)\n", ocf); wake_up_interruptible(&hci_wq); break; } /* end of switch */}char*bt_hw_vendor(void){ return "Infineon";}#else/*****************************************************************************//************************* HW_NOINIT and HW_GENERIC **************************//*****************************************************************************/#define VENDOR " [Generic]"s32 hci_set_bd_addr(u8 bd[6]){ D_ERR(__FUNCTION__ VENDOR " not supported.\n"); return 0;}s32hci_read_firmware_rev_info(void){ D_ERR(__FUNCTION__ VENDOR " not supported.\n"); return 0;}s32 hci_set_baudrate(u32 baudrate){ D_ERR(__FUNCTION__ VENDOR " not supported.\n"); return 0;}voidprocess_vendor_event(u8 *buf, u32 len, u32 event_code){ D_REC(__FUNCTION__ VENDOR " Manufacturer specific: Unknown event.\n");}voidprocess_vendor_return_param(u32 ocf, u8* r_val){ D_ERR(__FUNCTION__ VENDOR " Manufacturer specific: Invalid reply (0x%x)\n", ocf);}char*bt_hw_vendor(void){#if defined(CONFIG_BLUETOOTH_USBMODULE) return "USB";#elif defined(CONFIG_BLUETOOTH_GENERIC) return "Generic";#elif defined(CONFIG_BLUETOOTH_NOINIT) return "No Init";#else return "Unknown";#endif}#endif/*****************************************************************************/char*bt_hw_firmware(void){ return bt_hw_firmware_info;}/********************* END OF FILE hci_vendor.c ******************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -