|
From: Peter K. <pk...@us...> - 2001-04-20 11:45:06
|
The following file was modified in linux/drivers/char/bluetooth:
Name Old version New version Comment
---- ----------- ----------- -------
hci_vendor.c 1.26 1.27=20=20=20=20=20=20=20=20=20=20=20=20
The accompanying log:
Added commands for setting BD address and baud rate in CSR
module, and for reading hardware/firmware information.
The diff of the modified file(s):
--- hci_vendor.c 2001/04/18 15:47:13 1.26
+++ hci_vendor.c 2001/04/20 11:45:05 1.27
@@ -412,31 +412,385 @@
=20
#define VENDOR " [CSR]"
=20
+#define CSR_CH_ID_BCCMD 0x02
+#define CSR_CH_ID_HQ 0x03
+
+#define CSR_MSGTYPE_GETREQ 0x0000
+#define CSR_MSGTYPE_GETRESP 0x0001
+#define CSR_MSGTYPE_SETREQ 0x0002
+
+#define CSR_STATUS_OK 0x0000
+#define CSR_STATUS_NO_SUCH_VARID 0x0001
+#define CSR_STATUS_TOO_BIG 0x0002
+#define CSR_STATUS_NO_VALUE 0x0003
+#define CSR_STATUS_BAD_REQ 0x0004
+#define CSR_STATUS_NO_ACCESS 0x0005
+#define CSR_STATUS_READ_ONLY 0x0006
+#define CSR_STATUS_WRITE_ONLY 0x0007
+#define CSR_STATUS_ERROR 0x0008
+#define CSR_STATUS_PERMISSION_DENIED 0x0009
+
+#define CSR_CMD_CONFIG_UART 0x6802
+#define CSR_CMD_BUILD_ID 0x2819
+#define CSR_CMD_CHIP_VER 0x281a
+#define CSR_CMD_CHIP_REV 0x281b
+#define CSR_CMD_PS 0x7003
+
+#define CSR_PS_BDADDR 0x0001
+#define CSR_PS_BAUD_RATE 0x0204
+
+#define CSR_UART_RATE_9K6 0x0027
+#define CSR_UART_RATE_19K2 0x004f
+#define CSR_UART_RATE_38K4 0x009d
+#define CSR_UART_RATE_57K6 0x00ec
+#define CSR_UART_RATE_115K2 0x01d8
+#define CSR_UART_RATE_230K4 0x03b0
+#define CSR_UART_RATE_460K8 0x075f
+#define CSR_UART_RATE_921K6 0x0ebf
+
+#define CSR_UART_ONE_STOP_BIT 0x0000
+#define CSR_UART_TWO_STOP_BITS 0x2000
+
+#define CSR_UART_NO_PARITY 0x0000
+#define CSR_UART_ODD_PARITY 0x4000
+#define CSR_UART_EVEN_PARITY 0xc000
+
+typedef struct payload_descr
+{
+ u8 ch_id:6;
+ u8 first:1;
+ u8 last:1;
+} payload_descr;
+
+typedef struct csr_msg
+{
+ payload_descr p_descr;
+ u8 msg[0];
+} csr_msg;
+
+typedef struct csr_bccmd
+{
+ u16 type;
+ u16 len; /* in 16 bit integers */
+ u16 seq;
+ u16 var_id;
+ u16 status;
+ u16 payload[0];
+} csr_bccmd;
+=20=20
+typedef struct csr_bccmd_ps
+{
+ u16 ps_key;
+ u16 ps_len; /* len of only ps_val */
+ u16 unused; /* always 0x0000 */
+ u16 ps_val[0];
+} csr_bccmd_ps;
+
+static u16 csr_count =3D 0;
+
s32=20
hci_set_bd_addr(u8 bd[6])
{
- D_ERR(__FUNCTION__ VENDOR " not supported.\n");
- return 0;
+ csr_msg *msg;
+ csr_bccmd *cmd;
+ csr_bccmd_ps *ps;
+
+ D_CMD(__FUNCTION__ VENDOR "\n");
+
+ /* HCI Manufacturer specific header */
+ c_pkt.type =3D CMD_PKT;
+ c_pkt.opcode =3D hci_put_opcode(0x00, 0x3f);
+ c_pkt.len =3D 1 + 5*sizeof(u16) + 3*sizeof(u16) + 4*sizeof(u16);
+
+ msg =3D (csr_msg *)c_pkt.data;
+ cmd =3D (csr_bccmd *)msg->msg;
+ ps =3D (csr_bccmd_ps *)cmd->payload;
+
+ /* General msg header */
+ msg->p_descr.last =3D 1; /* first and last segment */
+ msg->p_descr.first =3D 1;
+ msg->p_descr.ch_id =3D CSR_CH_ID_BCCMD;
+
+ /* BCCMD type */
+ cmd->type =3D CSR_MSGTYPE_SETREQ;
+ cmd->len =3D 5 + 3 + 4;
+ cmd->seq =3D csr_count++;
+ cmd->var_id =3D CSR_CMD_PS;
+ cmd->status =3D CSR_STATUS_OK; /* always OK in SETREQ */
+
+ /* Actual PS key request */
+ ps->ps_key =3D CSR_PS_BDADDR;
+ ps->ps_len =3D 4; /* x 16 bits */
+ ps->unused =3D 0x0000;
+
+ ps->ps_val[0] =3D ((u16)bd[3]) & 0x00ff;
+ ps->ps_val[1] =3D ((((u16)bd[4]) << 8) | ((u16)bd[5]));
+ ps->ps_val[2] =3D (u16)bd[2];
+ ps->ps_val[3] =3D (((u16)bd[0] << 8) | ((u16)bd[1]));
+
+ return send_cmd_block((u8*) &c_pkt, c_pkt.len + CMD_HDR_LEN + HCI_HDR_LEN=
);
}
=20
s32
hci_read_firmware_rev_info(void)
{
- D_ERR(__FUNCTION__ VENDOR " not supported.\n");
- return 0;
+ s32 tmp;
+ csr_msg *msg;
+ csr_bccmd *cmd;
+
+ D_CMD(__FUNCTION__ VENDOR "\n");
+=09
+ /* HCI Manufacturer specific header */
+ c_pkt.type =3D CMD_PKT;
+ c_pkt.opcode =3D hci_put_opcode(0x00, 0x3f);
+ c_pkt.len =3D 1 + 5*sizeof(u16) + 6*sizeof(u16);
+
+ msg =3D (csr_msg *)c_pkt.data;
+ cmd =3D (csr_bccmd *)msg->msg;
+
+ /* General msg header */
+ msg->p_descr.last =3D 1; /* first and last segment */
+ msg->p_descr.first =3D 1;
+ msg->p_descr.ch_id =3D CSR_CH_ID_BCCMD;
+
+ /* BCCMD type */
+ cmd->type =3D CSR_MSGTYPE_GETREQ;
+ cmd->len =3D 5 + 6;
+ cmd->seq =3D csr_count++;
+ cmd->var_id =3D CSR_CMD_BUILD_ID;
+ cmd->status =3D CSR_STATUS_OK; /* always OK in GETREQ */
+ memset(cmd->payload, 0, 6*sizeof(u16));
+
+ tmp =3D send_cmd_block((u8*) &c_pkt, c_pkt.len + CMD_HDR_LEN + HCI_HDR_LE=
N);
+ if (tmp < 0)
+ return tmp;
+
+ cmd->seq =3D csr_count++;
+ cmd->var_id =3D CSR_CMD_CHIP_VER;
+ memset(cmd->payload, 0, 6*sizeof(u16));
+ tmp =3D send_cmd_block((u8*) &c_pkt, c_pkt.len + CMD_HDR_LEN + HCI_HDR_LE=
N);
+ if (tmp < 0)
+ return tmp;
+
+ cmd->seq =3D csr_count++;
+ cmd->var_id =3D CSR_CMD_CHIP_REV;
+ memset(cmd->payload, 0, 6*sizeof(u16));
+ tmp =3D send_cmd_block((u8*) &c_pkt, c_pkt.len + CMD_HDR_LEN + HCI_HDR_LE=
N);
+
+ return tmp;
}
=20
+//#define SET_BAUD_RATE_TEMPORARILY
s32=20
hci_set_baudrate(u32 baudrate)
{
- D_ERR(__FUNCTION__ VENDOR " not supported.\n");
- return 0;
+ s32 tmp;
+ csr_msg *msg;
+ csr_bccmd *cmd;
+ csr_bccmd_ps *ps;
+ u16 baud_divider;
+
+ D_CMD(__FUNCTION__ VENDOR " (%u baud)\n", baudrate);
+
+ switch (baudrate) {
+ case 57600:
+ baud_divider =3D CSR_UART_RATE_57K6;
+ break;
+ case 115200:
+ baud_divider =3D CSR_UART_RATE_115K2;
+ break;
+ case 230400:
+ baud_divider =3D CSR_UART_RATE_230K4;
+ break;
+ case 460800:
+ baud_divider =3D CSR_UART_RATE_460K8;
+ break;
+ case 921600:
+ baud_divider =3D 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 =3D CMD_PKT;
+ c_pkt.opcode =3D hci_put_opcode(0x00, 0x3f);
+#ifdef SET_BAUD_RATE_TEMPORARILY
+ c_pkt.len =3D 1 + 5*sizeof(u16) + 6*sizeof(u16);
+#else
+ c_pkt.len =3D 1 + 5*sizeof(u16) + 3*sizeof(u16) + 1*sizeof(u16);
+#endif
+
+ msg =3D (csr_msg *)c_pkt.data;
+ cmd =3D (csr_bccmd *)msg->msg;
+ ps =3D (csr_bccmd_ps *)cmd->payload;
+
+ /* General msg header */
+ msg->p_descr.last =3D 1; /* first and last segment */
+ msg->p_descr.first =3D 1;
+ msg->p_descr.ch_id =3D CSR_CH_ID_BCCMD;
+
+#ifdef SET_BAUD_RATE_TEMPORARILY
+ cmd->type =3D CSR_MSGTYPE_SETREQ;
+ cmd->len =3D 5 + 6;
+ cmd->seq =3D csr_count++;
+ cmd->var_id =3D CSR_CMD_CONFIG_UART;
+ cmd->status =3D CSR_STATUS_OK; /* always OK in SETREQ */
+
+ memset(cmd->payload, 0, 6*sizeof(u16));
+ cmd->payload[0] =3D baud_divider | CSR_UART_NO_PARITY | CSR_UART_ONE_STOP=
_BIT;
+
+ tmp =3D send_cmd_block((u8*) &c_pkt, c_pkt.len + CMD_HDR_LEN + HCI_HDR_LE=
N);
+#else
+ cmd->type =3D CSR_MSGTYPE_SETREQ;
+ cmd->len =3D 5 + 3 + 1;
+ cmd->seq =3D csr_count++;
+ cmd->var_id =3D CSR_CMD_PS;
+ cmd->status =3D CSR_STATUS_OK; /* always OK in SETREQ */
+
+ /* Actual PS key request */
+ ps->ps_key =3D CSR_PS_BAUD_RATE;
+ ps->ps_len =3D 1; /* x 16 bits */
+ ps->unused =3D 0x0000;
+
+ ps->ps_val[0] =3D baud_divider;
+
+ tmp =3D send_cmd_block((u8*) &c_pkt, c_pkt.len + CMD_HDR_LEN + HCI_HDR_LE=
N);
+#endif
+
+ return tmp;
}
=20
+//#define VERBOSE
void
process_vendor_event(u8 *buf, u32 len, u32 event_code)
{
+ csr_msg *msg;
+ csr_bccmd *cmd;
+ csr_bccmd_ps *ps;
+
D_REC(__FUNCTION__ VENDOR "\n");
+=09
+ /* FIXME -- is there only one cmd buffer available ? */
+ hci_ctrl.hc_buf.cmd_num =3D 1;=20=20
+
+ release_cmd_timer();
+
+ msg =3D (struct csr_msg *)buf;
+ cmd =3D (struct csr_bccmd *)msg->msg;
+ ps =3D (struct csr_bccmd_ps *)cmd->payload;
+
+ switch (msg->p_descr.ch_id) {
+ case CSR_CH_ID_BCCMD:
+ if (cmd->type =3D=3D CSR_MSGTYPE_GETRESP &&
+ cmd->status =3D=3D 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:
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ case CSR_CH_ID_HQ:
+ break;
+
+ default:
+ break;
+ }
+
+#ifdef VERBOSE
+ printk("msg: last: %d, first: %d, chID: %d\n",=20
+ msg->p_descr.last, msg->p_descr.first, msg->p_descr.ch_id);
+
+ printk("cmd: type: 0x%04X, msg_len: %d, seq_nbr: %d, varid: 0x%04X, statu=
s: 0x%04X\n",
+ cmd->type, cmd->len, cmd->seq, cmd->var_id, cmd->status);
+
+ switch (msg->p_descr.ch_id) {
+ 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 =3D=3D CSR_STATUS_OK)
+ printk("Command successful\n");
+
+ if (cmd->type =3D=3D CSR_MSGTYPE_GETRESP &&
+ cmd->status =3D=3D 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:
+ if (cmd->len > 2*5)
+ printk("ps: key 0x%x, len %d\n", ps->ps_key, ps->ps_len);
+ 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);=09
}
=20
void
|