📄 usb2uart.c
字号:
{
while (!(chunk = get_hci_event (&buf[1])))
Sleep(10);
chunk++;
}
for (len = chunk; len != buf[1] + 2; len = len + chunk)
{
while (!(chunk = get_hci_event (&buf[len])))
Sleep(10);
}
#ifdef PKT_DUMP
printf("Event [%d]: ", len);
for (chunk=0; chunk!=len; chunk++)
printf("%02x ", buf[chunk]);
printf("\n");
#endif
if (buf[0] != 0xFF) /* manuf-specific HCI event */
close_connection_on_error ("invalid packet received");
if (buf[1] != ((buf[5] + (buf[6] << 8)) * 2 + 1))
close_connection_on_error ("invalid length");
if (buf[2] != 0xC2) /* payload descriptor */
close_connection_on_error ("invalid payload descriptor");
if ((buf[3] + (buf[4] << 8)) != BCCMD_GETRESP)
close_connection_on_error ("!= GETRESP");
if ((buf[5] + (buf[6] << 8)) != bccmd_len)
close_connection_on_error ("invalid length");
if ((buf[7] + (buf[8] << 8)) != bccmd_seq)
close_connection_on_error ("invalid sequence number");
if ((buf[9] + (buf[10] << 8)) != bccmd_varid)
close_connection_on_error ("invalid varid");
switch (buf[11] + (buf[12] << 8))
{
case 0x0000:
/* OK status, continue */
break;
case 0x0001:
close_connection_on_error ("status NO_SUCH_VARID");
break;
case 0x0002:
close_connection_on_error ("status TOO_BIG");
break;
case 0x0003:
close_connection_on_error ("status NO_VALUE");
break;
case 0x0004:
close_connection_on_error ("status BAD_REQ");
break;
case 0x0005:
close_connection_on_error ("status NO_ACCESS");
break;
case 0x0006:
close_connection_on_error ("status READ_ONLY");
break;
case 0x0007:
close_connection_on_error ("status WRITE_ONLY");
break;
case 0x0008:
close_connection_on_error ("status ERROR");
break;
case 0x0009:
close_connection_on_error ("status PERMISSION_DENIED");
break;
default:
close_connection_on_error ("invalid status");
break;
}
if ((buf[13] + (buf[14] << 8)) != pfkey)
close_connection_on_error ("incorrect pfkey");
if ((buf[15] + (buf[16] << 8)) != pskey_len)
close_connection_on_error ("incorrect pfkey length");
if ((buf[17] + (buf[18] << 8)) != psstore)
close_connection_on_error ("incorrect psstore");
if (!write)
{
memcpy(data, &buf[19], pskey_len * 2);
return pskey_len * 2;
}
else
return 0;
}
/* read CSR firmware build id/number */
static uint16 buildid(void)
{
uint16 bccmd_req, bccmd_varid, bccmd_len;
unsigned char buf[258];
int len = 0, chunk = 0;
bccmd_req = BCCMD_GETREQ;
bccmd_seq++;
bccmd_varid = 0x2819; /* varid: BUILDID */
bccmd_len = 9; /* minimum possible length, one uint16 is wasted */
memset(&buf, 0, sizeof(buf));
/* need to construct a hand-crafted HCI cmd pkt */
buf[0] = 0x00; buf[1] = 0xFC; /* OGF = 0x3F & OCF = 0x00 */
buf[2] = bccmd_len * 2 + 1; /* pkt len - 3 */
buf[3] = 0xC2; /* payload descriptor: last frag =1;
first frag = 1; channel = 2 */
buf[4] = bccmd_req & 0xFF; buf[5] = bccmd_req >> 8;
buf[6] = bccmd_len & 0xFF; buf[7] = bccmd_len >> 8;
buf[8] = bccmd_seq & 0xFF; buf[9] = bccmd_seq >> 8;
buf[10] = bccmd_varid & 0xFF; buf[11] = bccmd_varid >> 8;
buf[12] = 0x00; buf[13] = 0x00; /* status */
/* FIXME: IOCTL_CSRBC01_SEND_HCI_COMMAND doesn't return the number of bytes written? */
send_hci_command (&buf, buf[2] + 3);
#ifdef PKT_DUMP
printf("HCI cmd[%d]: ", buf[2] + 3);
for (chunk=0; chunk != buf[2] + 3; chunk++)
printf("%02x ", buf[chunk]);
printf("\n");
#endif
/* not really efficient, but who cares? */
while (!(chunk = get_hci_event (&buf)))
Sleep(10);
if (chunk == 1) /* too short to read packet length */
{
while (!(chunk = get_hci_event (&buf[1])))
Sleep(10);
chunk++;
}
for (len = chunk; len != buf[1] + 2; len = len + chunk)
{
while (!(chunk = get_hci_event (&buf[len])))
Sleep(10);
}
#ifdef PKT_DUMP
printf("Event [%d]: ", len);
for (chunk=0; chunk!=len; chunk++)
printf("%02x ", buf[chunk]);
printf("\n");
#endif
if (buf[0] != 0xFF) /* manuf-specific HCI event */
close_connection_on_error ("invalid packet received");
if (buf[1] != 9 * 2 + 1)
close_connection_on_error ("hci event has invalid length");
if (buf[2] != 0xC2) /* payload descriptor */
close_connection_on_error ("invalid payload descriptor");
if ((buf[3] + (buf[4] << 8)) != BCCMD_GETRESP)
close_connection_on_error ("!= GETRESP");
if ((buf[5] + (buf[6] << 8)) != 9)
close_connection_on_error ("invalid length");
if ((buf[7] + (buf[8] << 8)) != bccmd_seq)
close_connection_on_error ("invalid sequence number");
if ((buf[9] + (buf[10] << 8)) != bccmd_varid)
close_connection_on_error ("invalid varid");
switch (buf[11] + (buf[12] << 8))
{
case 0x0000:
/* OK status, continue */
break;
case 0x0001:
close_connection_on_error ("status NO_SUCH_VARID");
break;
case 0x0002:
close_connection_on_error ("status TOO_BIG");
break;
case 0x0003:
close_connection_on_error ("status NO_VALUE");
break;
case 0x0004:
close_connection_on_error ("status BAD_REQ");
break;
case 0x0005:
close_connection_on_error ("status NO_ACCESS");
break;
case 0x0006:
close_connection_on_error ("status READ_ONLY");
break;
case 0x0007:
close_connection_on_error ("status WRITE_ONLY");
break;
case 0x0008:
close_connection_on_error ("status ERROR");
break;
case 0x0009:
close_connection_on_error ("status PERMISSION_DENIED");
break;
default:
close_connection_on_error ("invalid status");
break;
}
return buf[13] + (buf[14] << 8);
}
/* set UART baud rate, stop bit(s), parity
*
* The change happens immediately, most probably the response on this command will be received back
* after the new UART settings took effect.
*
* Parameters:
*
* baud = baud rate, the value is used as a clock divisor, any value can be programmed.
* the common values are: 9600, 19200, ... 115200, 230400, 460800, 921600.
* stop = number of stop bits, either 1 or 2
* parity = parity, 0 - no parity, 1 - even parity, 2 - odd parity
*
*/
static void uart_config(int baud, int stop, int parity)
{
uint16 bccmd_req, bccmd_varid, bccmd_len, divisor;
unsigned char buf[258];
int len = 0, chunk = 0;
bccmd_req = BCCMD_SETREQ;
bccmd_seq++;
bccmd_varid = 0x6802; /* varid: CONFIG_UART */
bccmd_len = 9; /* minimum possible length, one uint16 is wasted */
memset(&buf, 0, sizeof(buf));
/* need to construct a hand-crafted HCI cmd pkt */
buf[0] = 0x00; buf[1] = 0xFC; /* OGF = 0x3F & OCF = 0x00 */
buf[2] = bccmd_len * 2 + 1; /* pkt len - 3 */
buf[3] = 0xC2; /* payload descriptor: last frag =1;
first frag = 1; channel = 2 */
buf[4] = bccmd_req & 0xFF; buf[5] = bccmd_req >> 8;
buf[6] = bccmd_len & 0xFF; buf[7] = bccmd_len >> 8;
buf[8] = bccmd_seq & 0xFF; buf[9] = bccmd_seq >> 8;
buf[10] = bccmd_varid & 0xFF; buf[11] = bccmd_varid >> 8;
buf[12] = 0x00; buf[13] = 0x00; /* status */
divisor = (baud*64+7812)/15625;
if (stop == 1)
divisor |= 0x0000;
else if (stop == 2)
divisor |= 0x2000;
else
close_connection_on_error ("invalid stop bit number");
if (parity == 0)
divisor |= 0x0000;
else if (parity == 1)
divisor |= 0xC000;
else if (parity == 2)
divisor |= 0x4000;
else
close_connection_on_error ("invalid parity bit value");
buf[14] = divisor & 0xFF; buf[15] = divisor >> 8;
/* FIXME: IOCTL_CSRBC01_SEND_HCI_COMMAND doesn't return the number of bytes written? */
send_hci_command (&buf, buf[2] + 3);
#ifdef PKT_DUMP
printf("HCI cmd[%d]: ", buf[2] + 3);
for (chunk=0; chunk != buf[2] + 3; chunk++)
printf("%02x ", buf[chunk]);
printf("\n");
#endif
/* not really efficient, but who cares? */
while (!(chunk = get_hci_event (&buf)))
Sleep(10);
if (chunk == 1) /* too short to read packet length */
{
while (!(chunk = get_hci_event (&buf[1])))
Sleep(10);
chunk++;
}
for (len = chunk; len != buf[1] + 2; len = len + chunk)
{
while (!(chunk = get_hci_event (&buf[len])))
Sleep(10);
}
#ifdef PKT_DUMP
printf("Event [%d]: ", len);
for (chunk=0; chunk!=len; chunk++)
printf("%02x ", buf[chunk]);
printf("\n");
#endif
if (buf[0] != 0xFF) /* manuf-specific HCI event */
close_connection_on_error ("invalid packet received");
if (buf[1] != 9 * 2 + 1)
close_connection_on_error ("hci event has invalid length");
if (buf[2] != 0xC2) /* payload descriptor */
close_connection_on_error ("invalid payload descriptor");
if ((buf[3] + (buf[4] << 8)) != BCCMD_GETRESP)
close_connection_on_error ("!= GETRESP");
if ((buf[5] + (buf[6] << 8)) != 9)
close_connection_on_error ("invalid length");
if ((buf[7] + (buf[8] << 8)) != bccmd_seq)
close_connection_on_error ("invalid sequence number");
if ((buf[9] + (buf[10] << 8)) != bccmd_varid)
close_connection_on_error ("invalid varid");
switch (buf[11] + (buf[12] << 8))
{
case 0x0000:
/* OK status, continue */
break;
case 0x0001:
close_connection_on_error ("status NO_SUCH_VARID");
break;
case 0x0002:
close_connection_on_error ("status TOO_BIG");
break;
case 0x0003:
close_connection_on_error ("status NO_VALUE");
break;
case 0x0004:
close_connection_on_error ("status BAD_REQ");
break;
case 0x0005:
close_connection_on_error ("status NO_ACCESS");
break;
case 0x0006:
close_connection_on_error ("status READ_ONLY");
break;
case 0x0007:
close_connection_on_error ("status WRITE_ONLY");
break;
case 0x0008:
close_connection_on_error ("status ERROR");
break;
case 0x0009:
close_connection_on_error ("status PERMISSION_DENIED");
break;
default:
close_connection_on_error ("invalid status");
break;
}
return;
}
/* enter DEEP_SLEEP mode
*
* The change happens approx. 0.5s after sending event back
*
*/
static void deep_sleep(void)
{
uint16 bccmd_req, bccmd_varid, bccmd_len, testid;
unsigned char buf[258];
int len = 0, chunk = 0;
bccmd_req = BCCMD_SETREQ;
bccmd_seq++;
bccmd_varid = 0x5004; /* varid: RADIOTEST */
bccmd_len = 9; /* minimum possible length, one uint16 is wasted */
memset(&buf, 0, sizeof(buf));
/* need to construct a hand-crafted HCI cmd pkt */
buf[0] = 0x00; buf[1] = 0xFC; /* OGF = 0x3F & OCF = 0x00 */
buf[2] = bccmd_len * 2 + 1; /* pkt len - 3 */
buf[3] = 0xC2; /* payload descriptor: last frag =1;
first frag = 1; channel = 2 */
buf[4] = bccmd_req & 0xFF; buf[5] = bccmd_req >> 8;
buf[6] = bccmd_len & 0xFF; buf[7] = bccmd_len >> 8;
buf[8] = bccmd_seq & 0xFF; buf[9] = bccmd_seq >> 8;
buf[10] = bccmd_varid & 0xFF; buf[11] = bccmd_varid >> 8;
buf[12] = 0x00; buf[13] = 0x00; /* status */
testid = 10; /* DEEP_SLEEP */
buf[14] = testid & 0xFF; buf[15] = testid >> 8;
/* FIXME: IOCTL_CSRBC01_SEND_HCI_COMMAND doesn't return the number of bytes written? */
send_hci_command (&buf, buf[2] + 3);
#ifdef PKT_DUMP
printf("HCI cmd[%d]: ", buf[2] + 3);
for (chunk=0; chunk != buf[2] + 3; chunk++)
printf("%02x ", buf[chunk]);
printf("\n");
#endif
/* not really efficient, but who cares? */
while (!(chunk = get_hci_event (&buf)))
Sleep(10);
if (chunk == 1) /* too short to read packet length */
{
while (!(chunk = get_hci_event (&buf[1])))
Sleep(10);
chunk++;
}
for (len = chunk; len != buf[1] + 2; len = len + chunk)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -