📄 btctl-dev.c
字号:
/* Affix - Bluetooth Protocol Stack for Linux Copyright (C) 2001,2002 Nokia Corporation Adopted for Affix by Dmitry Kasatkin Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> BlueZ - Bluetooth protocol stack for Linux Copyright (C) 2000-2001 Qualcomm Incorporated This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//* $Id: btctl-dev.c,v 1.80 2003/12/19 14:35:29 kds Exp $ Utility functions to read and parse the BT server config file. Fixes:*/#include <affix/config.h>#include <sys/fcntl.h>#include <sys/time.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <termios.h>#include <fcntl.h>#include <signal.h>#include <time.h>#include <affix/btcore.h>#include "btctl.h"static int hci = -1;struct affix_tupla uart_flags[] = { {CRTSCTS, "ctl"}, {AFFIX_UART_RI | CRTSCTS, "ring"}, {AFFIX_UART_LOW, "low"}, {PARENB, "pareven"}, {PARENB | PARODD, "parodd"}, {CSTOPB, "stopb"}, {0, NULL}};/* * UART stuff */struct uart_t { char *name; int type; int proto; int speed; int init_speed; int flags; int (*init) (int fd, struct uart_t *u, struct termios *ti);};static int uart_speed(int s){ switch (s) { case 9600: return B9600; case 19200: return B19200; case 38400: return B38400; case 57600: return B57600; case 115200: return B115200; case 230400: return B230400; case 460800: return B460800; case 921600: return B921600; case 1000000: return B1000000; default: return B57600; }}/* * Ericsson specific initialization */struct Ericsson_Set_UART_Speed { HCI_Command_Packet_Header hci; __u8 speed;}__PACK__;#define HCI_C_ERICSSON_SET_UART_SPEED 0xfc09static int ericsson(int fd, struct uart_t *u, struct termios *ti){ struct timespec tm = {0, 50000}; int err; struct Ericsson_Set_UART_Speed cmd; uint8_t buf[HCI_MAX_EVENT_SIZE]; struct Command_Complete_Status *ccs = (void*)buf; switch (u->speed) { case 57600: cmd.speed = 0x03; break; case 115200: cmd.speed = 0x02; break; case 230400: cmd.speed = 0x01; break; case 460800: cmd.speed = 0x00; break; case 921600: cmd.speed = 0x20; break; default: cmd.speed = 0x03; u->speed = 57600; break; }#if 0 err = hci_exec_cmd(fd, HCI_C_ERICSSON_SET_UART_SPEED, &cmd, sizeof(cmd), COMMAND_COMPLETE_MASK, 0, ccs);#else ccs->Status = 0; err = hci_exec_cmd1(fd, HCI_C_ERICSSON_SET_UART_SPEED, &cmd, sizeof(cmd), COMMAND_COMPLETE_MASK, HCI_SKIP_STATUS); nanosleep(&tm, NULL);#endif BTINFO("err: %d, status: %#x\n", err, ccs->Status); if (err) return err; return ccs->Status;}/* * Digianswer specific initialization */struct Digi_Set_UART_Speed { HCI_Command_Packet_Header hci; __u8 speed;}__PACK__;#define HCI_C_DIGI_SET_UART_SPEED 0xfc07static int digi(int fd, struct uart_t *u, struct termios *ti){ struct timespec tm = {0, 50000}; int err; struct Digi_Set_UART_Speed cmd; switch (u->speed) { case 57600: cmd.speed = 0x08; break; case 115200: cmd.speed = 0x09; break; default: cmd.speed = 0x09; u->speed = 115200; break; } err = hci_exec_cmd1(fd, HCI_C_DIGI_SET_UART_SPEED, &cmd, sizeof(cmd), COMMAND_COMPLETE_MASK, HCI_SKIP_STATUS); if (err) return err; nanosleep(&tm, NULL); return 0;}/* * CSR specific initialization * Inspired strongly by code in OpenBT and experimentations with Brainboxes * Pcmcia card. * Jean Tourrilhes <jt@hpl.hp.com> - 14.11.01 * * Adopted to be HCI style - Dmitry Kasatkin * *//* 15 bytes in UART: 1 + 3 + 11 */struct CSR_BCC_Header { /* MSG header */ __u8 channel; /* 0xC2 for BCC */ /* BCC header */ __u16 type; /* getreq - 0x00, getresp - 0x01, setreq - 0x02 */ __u16 len; /* in 16 bits */ __u16 seq_num; __u16 var_id; __u16 status; /* payload data */ __u16 data[0];}__PACK__;#define HCI_C_CSR_COMMAND 0xfc00struct CSR_Get_Build_ID { HCI_Command_Packet_Header hci; struct CSR_BCC_Header bcc; __u16 data[6];}__PACK__;struct CSR_Get_Build_ID_Event { HCI_Event_Packet_Header hci; // 3 bytes struct CSR_BCC_Header bcc; // 11 bytes __u8 data[19];}__PACK__;struct CSR_Set_UART_Speed { HCI_Command_Packet_Header hci; struct CSR_BCC_Header bcc; __u16 speed; __u16 extra[3];}__PACK__;static int csr(int fd, struct uart_t *u, struct termios *ti){ struct timespec tm = {0, 10000000}; /* 10ms - be generous */ static int csr_seq = 0; /* Sequence number of command */ int divisor; int err; struct CSR_Get_Build_ID cmd1; struct CSR_Get_Build_ID_Event cce; struct CSR_Set_UART_Speed cmd2; /* Try to read the build ID of the CSR chip */ cmd1.bcc.channel = 0xc2; /* first+last+channel=BCC */ cmd1.bcc.type = __htob16(0x0000); /* type = GET-REQ */ cmd1.bcc.len = __htob16(5 + 4); /* ??? */ cmd1.bcc.seq_num = __htob16(csr_seq); /* seq num */ csr_seq++; cmd1.bcc.var_id = __htob16(0x2819); /* var_id = CSR_CMD_BUILD_ID */ cmd1.bcc.status = __htob16(0x0000); /* status = STATUS_OK */ /* CSR BCC payload */ memset(cmd1.data, 0, sizeof(cmd1.data)); /* Send command */ err = hci_exec_cmd1(fd, HCI_C_CSR_COMMAND, &cmd1, sizeof(cmd1), ALL_EVENTS_MASK, HCI_SKIP_STATUS); if (err) return err; do {#if 0 // it's here in original code /* Send command */ err = hci_exec_cmd(fd, &cmd1, ALL_EVENTS_MASK, HCI_SKIP_STATUS, NULL); if (err) return err;#endif err = hci_recv_event(fd, &cce, sizeof(cce), 20); if (err < 0) { return err; } } while (cce.hci.EventCode != 0xFF); /* Display that to user */ BTINFO("CSR build ID 0x%02X-0x%02X\n", cce.data[12], cce.data[11]); /* Now, create the command that will set the UART speed */ cmd2.bcc.channel = 0xc2; cmd2.bcc.type = __htob16(0x0002); // SET-REQ cmd2.bcc.len = __htob16(5 + 4); cmd2.bcc.seq_num = __htob16(csr_seq); csr_seq++; cmd2.bcc.var_id = __htob16(0x6802); // CONFIG_UART cmd2.bcc.status = __htob16(0x0000); // STATUS_OK switch (u->speed) { case 9600: divisor = 0x0027; break; /* Various speeds ommited */ case 57600: divisor = 0x00EC; break; case 115200: divisor = 0x01D8; break; /* For Brainbox Pcmcia cards */ case 460800: divisor = 0x075F; break; case 921600: divisor = 0x0EBF; break; default: /* Safe default */ divisor = 0x01D8; u->speed = 115200; break; } /* No parity, one stop bit -> divisor |= 0x0000; */ cmd2.speed = __htob16(divisor); memset(cmd2.extra, 0, sizeof(cmd2.extra)); err = hci_exec_cmd1(fd, HCI_C_CSR_COMMAND, &cmd2, sizeof(cmd2), ALL_EVENTS_MASK, HCI_SKIP_STATUS); if (err) return err;#if 0 // no wait for response in original code do { err = hci_recv_event(fd, &cce, sizeof(cce), 20); if (err < 0) { return err; } } while (cce.hci.EventCode != 0xFF);#endif nanosleep(&tm, NULL); return 0;}/* * Silicon Wave specific initialization * Thomas Moser <Thomas.Moser@tmoser.ch> */struct Swave_Set_UART_Speed { HCI_Command_Packet_Header hci; __u8 subcmd; __u8 tag; __u8 length; /* parameters */ __u8 flow; __u8 type; __u8 speed;}__PACK__;#define HCI_C_SWAVE_COMMAND 0xfc0Bstruct Swave_Event { HCI_Event_Packet_Header hci; __u8 subcmd; __u8 setevent; __u8 tag; __u8 length; /* parameters */ __u8 flow; __u8 type; __u8 speed;}__PACK__;struct Swave_Soft_Reset { HCI_Command_Packet_Header hci; __u8 subcmd;}__PACK__;static int swave(int fd, struct uart_t *u, struct termios *ti){ struct timespec tm = {0, 500000}; int err; struct Swave_Set_UART_Speed cmd; struct Swave_Event cce; struct Swave_Soft_Reset cmd1; // Silicon Wave set baud rate command // see HCI Vendor Specific Interface from Silicon Wave // first send a "param access set" command to set the // appropriate data fields in RAM. Then send a "HCI Reset // Subcommand", e.g. "soft reset" to make the changes effective. cmd.subcmd = 0x01; // param sub command cmd.tag = 0x11; // tag 17 = 0x11 = HCI Transport Params cmd.length = 0x03; // length of the parameter following cmd.flow = 0x01; // HCI Transport flow control enable cmd.type = 0x01; // HCI Transport Type = UART switch (u->speed) { case 19200: cmd.speed = 0x03; break; case 38400: cmd.speed = 0x02; break; case 57600: cmd.speed = 0x01; break; case 115200: cmd.speed = 0x00; break; default: u->speed = 115200; cmd.speed = 0x00; break; } /* Send command */ err = hci_exec_cmd1(fd, HCI_C_SWAVE_COMMAND, &cmd, sizeof(cmd), ALL_EVENTS_MASK, HCI_SKIP_STATUS); if (err) return err; nanosleep(&tm, NULL); do { err = hci_recv_event(fd, &cce, sizeof(cce), 20); if (err < 0) { return err; } } while (cce.hci.EventCode != 0xFF); cmd1.subcmd = 0x03; // param sub command err = hci_exec_cmd1(fd, HCI_C_SWAVE_COMMAND, &cmd1, sizeof(cmd1), ALL_EVENTS_MASK, HCI_SKIP_STATUS); if (err) return err; nanosleep(&tm, NULL); // now the uart baud rate on the silicon wave module is set and effective. // change our own baud rate as well. Then there is a reset event comming in // on the *new* baud rate. This is *undocumented*! The packet looks like this: // 04 FF 01 0B (which would make that a confirmation of 0x0B = "Param // subcommand class". So: change to new baud rate, read with timeout, parse // data, error handling. BTW: all param access in Silicon Wave is done this way. // Maybe this code would belong in a seperate file, or at least code reuse... return 0;}#if 0static int texas(int fd, struct uart_t *u, struct termios *ti){ struct timespec tm = {0, 50000}; char cmd[10]; unsigned char resp[100]; /* Response */ int n;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -