📄 usb2uart.c
字号:
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;
}
/* Forces the module to reboot immediately
*
* Parameters:
*
* warm = 1 (warm reboot, RAM store is preserved) or 0 (cold reboot, the same as
* power-cycling the module)
*
* It's most probable that response will never be able to make it back, so don't bother
*/
static void reboot(int warm)
{
uint16 bccmd_req, bccmd_varid, bccmd_len;
unsigned char buf[258];
int len = 0, chunk = 0;
bccmd_req = BCCMD_SETREQ;
bccmd_seq++;
if (warm == 0)
bccmd_varid = 0x4001; /* varid: COLF_RESET */
else if (warm == 1)
bccmd_varid = 0x4002; /* varid: WARM_RESET */
else
close_connection_on_error ("invalid reset type");
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
return;
}
static void usb_reset(void)
{
unsigned long written;
int status;
status = DeviceIoControl(handle,
IOCTL_CSRBC01_RESET_DEVICE,
0,
0,
0,
0,
&written,
0);
if (!status)
close_connection_on_error ("IOCTL_CSRBC01_RESET_DEVICE");
}
/*
* We only try to open the first CSR device found, if you have multiply
* devices, please unplug all but the last one or change device name from
* CSR0 to CSRn.
*/
int main (int arvc, char* arvgv)
{
unsigned char buf[258];
unsigned long written;
dev_desc desc;
uint16 len;
int baud_rate;
uint16 divisor, uart_conf, retries, host_if;
int status;
/* open device */
handle = CreateFile("\\\\.\\CSR0",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if ( handle == INVALID_HANDLE_VALUE)
close_connection_on_error ("CreateFile");
memset(&desc, 0, sizeof(desc));
status = DeviceIoControl(handle,
IOCTL_CSRBC01_GET_DEVICE_DESCRIPTOR,
0,
0,
&desc,
sizeof(desc), /* must be 18 */
&written,
0);
if (!status)
close_connection_on_error ("IOCTL_CSRBC01_GET_DEVICE_DESCRIPTOR");
printf("Found CSR USB device: VID=%04X, PID=%04X\n", desc.idVendor, desc.idProduct);
/* reset device to known state */
printf("Resetting...\n");
usb_reset();
if (handle != INVALID_HANDLE_VALUE)
CloseHandle (handle);
/* wait for hardware to settle */
Sleep(500);
/* re-open device */
handle = CreateFile("\\\\.\\CSR0",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if ( handle == INVALID_HANDLE_VALUE)
close_connection_on_error ("CreateFile");
printf("CSR firmware build ID: 0x%X\n", buildid());
memset(&buf, 0, sizeof(buf));
len = pfkey(0, PSKEY_BDADDR, buf, 0);
if (len != 8)
close_connection_on_error ("PSKEY_BDADDR");
/* It's hard to make it more akward than that ;) */
printf("read:PSKEY_BDADDR: %02X-%02X-%02X-%02X-%02X-%02X\n\n", 0,
buf[6] + (buf[7] << 8),
buf[4] + (buf[5] << 8),
buf[0] + (buf[1] << 8),
buf[3],
buf[2]);
/*
// printf("read:PSKEY_BDADDR: %02X %02X %02X %02X %02X %02X %02X %02X\n\n",
// buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
buf[0] = 0x1c;
buf[2] = 0x6a;
buf[3] = 0x8d;
buf[4] = 0xc7;
buf[6] = 0x02;
// printf("read:PSKEY_BDADDR: %02X %02X %02X %02X %02X %02X %02X %02X\n\n",
// buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
pfkey(1, PSKEY_BDADDR, buf, 8);
memset(&buf, 0, sizeof(buf));
len = pfkey(0, PSKEY_BDADDR, buf, 0);
if (len != 8)
close_connection_on_error ("PSKEY_BDADDR");
printf("read:PSKEY_BDADDR: %02X-%02X-%02X-%02X-%02X-%02X\n\n", 0,
buf[6] + (buf[7] << 8),
buf[4] + (buf[5] << 8),
buf[0] + (buf[1] << 8),
buf[3],
buf[2]);
goto Exit;
*/
/* Here's the structure of PSKEY_HOSTIO_UART_PS_BLOCK:
PSKEY_HOSTIO_UART_PS_BLOCK (0x191):
0 1 2 3 4 5 6 7 8 9
3B0 A8 FA 14 4 0 4 1E 64 A
0. PSKEY_UART_BAUD_RATE (0x204)
0x3B0 == 230400 bps
=> 0x1D8 == 115200 bps
1. PSKEY_UART_CONFIG (0x205)
0xA8 == hardware flow control, RTS on 1st bit, non-BCSP hardware
=> 6 == one parity bit, even parity (BCSP)
2. PSKEY_UART_SEQ_TIMEOUT (0x405)
0xFA == 250ms
3. PSKEY_UART_SEQ_RETRIES (0x406)
0x14 == 20 retries.
=> 0 == retry indefinitely
4. PSKEY_UART_SEQ_WINSIZE (0x407)
4 == number of unacknowledged packets that can be sent before waiting
for an acknowledgment
5. PSKEY_UART_USE_CRC_ON_TX (0x408)
0 == disabled
6. PSKEY_UART_HOST_INITIAL_STATE (0x409)
4 == host never sleeps
7. PSKEY_UART_HOST_ATTENTION_SPAN (0x40A) ????
0x1E == 30 seconds
8. PSKEY_UART_HOST_WAKEUP_TIME (0x40B) ???
0x64 == 100ms
9. PSKEY_UART_HOST_WAKEUP_WAIT (0x40C) ???
0xA == 10ms
*/
memset(&buf, 0, sizeof(buf));
len = pfkey(0, PSKEY_HOSTIO_UART_PS_BLOCK, buf, 0);
if (len != 20)
close_connection_on_error ("PSKEY_HOST_INTERFACE");
printf("read:PSKEY_HOSTIO_UART_PS_BLOCK: ");
for (len = 0; len < 20; len = len + 2)
printf("%02x ", buf[len] + (buf[len+1] << 8));
printf("\n");
baud_rate = 115200*8;
divisor = (baud_rate * 64 + 7812) / 15625;
buf[0] = divisor & 0xFF ; buf[1] = (divisor >> 8) & 0xFF;
uart_conf = 6; /* one stop bit, even parity, no RTS/CTS flow control,
non-BCSP hardware disabled */
buf[2] = uart_conf & 0xFF ; buf[3] = (uart_conf >> 8) & 0xFF;
retries = 0; /* retry indefinitely on BCSP packet transmission */
buf[6] = retries & 0xFF ; buf[7] = (retries >> 8) & 0xFF;
/* it should look like the following:
buf[0] = 0xD8;
buf[1] = 1;
buf[2] = 6;
buf[3] = 0;
buf[4] = 0xFA;
buf[5] = 0;
buf[6] = 0;
buf[7] = 0;
buf[8] = 4;
buf[9] = 0;
buf[10] = 0;
buf[11] = 0;
buf[12] = 4;
buf[13] = 0;
buf[14] = 0x1E;
buf[15] = 0;
buf[16] = 0x64;
buf[17] = 0;
buf[18] = 0xA;
buf[19] = 0;
*/
printf("write:PSKEY_HOSTIO_UART_PS_BLOCK: ");
for (len = 0; len < 10*2; len = len + 2)
printf("%02x ", buf[len] + (buf[len+1] << 8));
printf("\n");
pfkey(1, PSKEY_HOSTIO_UART_PS_BLOCK, buf, 20);
memset(&buf, 0, sizeof(buf));
len = pfkey(0, PSKEY_HOSTIO_UART_PS_BLOCK, buf, 0);
if (len != 20)
close_connection_on_error ("PSKEY_HOST_INTERFACE");
printf("read:PSKEY_HOSTIO_UART_PS_BLOCK: ");
for (len = 0; len < 20; len = len + 2)
printf("%02x ", buf[len] + (buf[len+1] << 8));
printf("\n");
/* ---------------------------------------------------------------------------- */
/* PSKEY_HOST_INTERFACE should be change at the same time as PSKEY_HOSTIO_UART_PS_BLOCK */
memset(&buf, 0, sizeof(buf));
len = pfkey(0, PSKEY_HOST_INTERFACE, buf, 0);
if (len != 2)
close_connection_on_error ("PSKEY_HOST_INTERFACE");
printf("read:PSKEY_HOST_INTERFACE: %d\n", buf[0] + (buf[1] << 8));
host_if = 1; /* UART in BCSP mode */
buf[0] = host_if & 0xFF ; buf[1] = (host_if >> 8) & 0xFF;
printf("write:PSKEY_HOST_INTERFACE: %d\n", buf[0] + (buf[1] << 8));
pfkey(1, PSKEY_HOST_INTERFACE, buf, 2);
memset(&buf, 0, sizeof(buf));
len = pfkey(0, PSKEY_HOST_INTERFACE, buf, 0);
if (len != 2)
close_connection_on_error ("PSKEY_HOST_INTERFACE");
printf("read:PSKEY_HOST_INTERFACE: %d\n", buf[0] + (buf[1] << 8));
/* ---------------------------------------------------------------------------- */
memset(&buf, 0, sizeof(buf));
len = pfkey(0, PSKEY_DEEP_SLEEP_STATE, buf, 0);
if (len != 2)
close_connection_on_error ("PSKEY_DEEP_SLEEP_STATE");
printf("read:PSKEY_DEEP_SLEEP_STATE: %d\n", buf[0] + (buf[1] << 8));
/* ---------------------------------------------------------------------------- */
memset(&buf, 0, sizeof(buf));
len = pfkey(0, PSKEY_DEEP_SLEEP_WAKE_CTS, buf, 0);
if (len != 2)
close_connection_on_error ("PSKEY_DEEP_SLEEP_WAKE_CTS");
printf("read:PSKEY_DEEP_SLEEP_WAKE_CTS: %d\n", buf[0] + (buf[1] << 8));
/* ---------------------------------------------------------------------------- */
memset(&buf, 0, sizeof(buf));
len = pfkey(0, PSKEY_UART_SLEEP_TIMEOUT, buf, 0);
if (len != 2)
close_connection_on_error ("PSKEY_UART_SLEEP_TIMEOUT");
printf("read:PSKEY_UART_SLEEP_TIMEOUT: %d ms\n", buf[0] + (buf[1] << 8));
/* ---------------------------------------------------------------------------- */
memset(&buf, 0, sizeof(buf));
len = pfkey(0, PSKEY_WD_PERIOD, buf, 0);
if (len != 4)
close_connection_on_error ("PSKEY_WD_PERIOD");
printf("read:PSKEY_WD_PERIOD: %d ms\n", ((buf[0] << 16) + (buf[1] << 24) + buf[2] + (buf[3] << 8))/1000);
/* ---------------------------------------------------------------------------- */
memset(&buf, 0, sizeof(buf));
len = pfkey(0, PSKEY_WD_TIMEOUT, buf, 0);
if (len != 4)
close_connection_on_error ("PSKEY_WD_TIMEOUT");
printf("read:PSKEY_WD_TIMEOUT: %d ms\n", ((buf[0] << 16) + (buf[1] << 24) + buf[2] + (buf[3] << 8))/1000);
/* ---------------------------------------------------------------------------- */
memset(&buf, 0, sizeof(buf));
len = pfkey(0, PSKEY_HOSTIO_UART_RESET_TIMEOUT, buf, 0);
if (len != 4)
close_connection_on_error ("PSKEY_HOSTIO_UART_RESET_TIMEOUT");
printf("read:PSKEY_HOSTIO_UART_RESET_TIMEOUT: %d ms\n", ((buf[0] << 16) + (buf[1] << 24) + buf[2] + (buf[3] << 8))/1000);
/* ---------------------------------------------------------------------------- */
memset(&buf, 0, sizeof(buf));
len = pfkey(0, PSKEY_HOSTIO_BREAK_POLL_PERIOD, buf, 0);
if (len != 4)
close_connection_on_error ("PSKEY_HOSTIO_BREAK_POLL_PERIOD");
printf("read:PSKEY_HOSTIO_BREAK_POLL_PERIOD: %d ms\n", ((buf[0] << 16) + (buf[1] << 24) + buf[2] + (buf[3] << 8))/1000);
printf("\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
printf("!!!! Rebooting device.... It should come up in UART BCSP mode now !!!!\n");
printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
Exit:
/* warm reboot */
reboot(1);
if (handle != INVALID_HANDLE_VALUE)
CloseHandle (handle);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -