Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/next/external/cache/sources/hcitools/hciattach.c
Views: 3959
/*1*2* BlueZ - Bluetooth protocol stack for Linux3*4* Copyright (C) 2000-2001 Qualcomm Incorporated5* Copyright (C) 2002-2003 Maxim Krasnyansky <[email protected]>6* Copyright (C) 2002-2010 Marcel Holtmann <[email protected]>7*8*9* This program is free software; you can redistribute it and/or modify10* it under the terms of the GNU General Public License as published by11* the Free Software Foundation; either version 2 of the License, or12* (at your option) any later version.13*14* This program is distributed in the hope that it will be useful,15* but WITHOUT ANY WARRANTY; without even the implied warranty of16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the17* GNU General Public License for more details.18*19* You should have received a copy of the GNU General Public License20* along with this program; if not, write to the Free Software21* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA22*23*/2425#ifdef HAVE_CONFIG_H26#include <config.h>27#endif2829#include <stdio.h>30#include <errno.h>31#include <fcntl.h>32#include <unistd.h>33#include <stdlib.h>34#include <string.h>35#include <signal.h>36#include <syslog.h>37#include <termios.h>38#include <time.h>39#include <sys/time.h>40#include <sys/poll.h>41#include <sys/param.h>42#include <sys/ioctl.h>4344#include <bluetooth/bluetooth.h>45#include <bluetooth/hci.h>46#include <bluetooth/hci_lib.h>4748#include "hciattach.h"4950static volatile sig_atomic_t __io_canceled = 0;5152static void sig_hup(int sig)53{54}5556static void sig_term(int sig)57{58__io_canceled = 1;59}6061static void sig_alarm(int sig)62{63fprintf(stderr, "Initialization timed out.\n");64exit(1);65}6667int uart_speed(int s)68{69switch (s) {70case 9600:71return B9600;72case 19200:73return B19200;74case 38400:75return B38400;76case 57600:77return B57600;78case 115200:79return B115200;80case 230400:81return B230400;82case 460800:83return B460800;84case 500000:85return B500000;86case 576000:87return B576000;88case 921600:89return B921600;90case 1000000:91return B1000000;92case 1152000:93return B1152000;94case 1500000:95return B1500000;96case 2000000:97return B2000000;98#ifdef B250000099case 2500000:100return B2500000;101#endif102#ifdef B3000000103case 3000000:104return B3000000;105#endif106#ifdef B3500000107case 3500000:108return B3500000;109#endif110#ifdef B3710000111case 3710000112return B3710000;113#endif114#ifdef B4000000115case 4000000:116return B4000000;117#endif118default:119return B57600;120}121}122123int set_speed(int fd, struct termios *ti, int speed)124{125if (cfsetospeed(ti, uart_speed(speed)) < 0)126return -errno;127128if (cfsetispeed(ti, uart_speed(speed)) < 0)129return -errno;130131if (tcsetattr(fd, TCSANOW, ti) < 0)132return -errno;133134return 0;135}136137/*138* Read an HCI event from the given file descriptor.139*/140int read_hci_event(int fd, unsigned char* buf, int size)141{142int remain, r;143int count = 0;144145if (size <= 0)146return -1;147148/* The first byte identifies the packet type. For HCI event packets, it149* should be 0x04, so we read until we get to the 0x04. */150while (1) {151r = read(fd, buf, 1);152if (r <= 0)153return -1;154if (buf[0] == 0x04)155break;156}157count++;158159/* The next two bytes are the event code and parameter total length. */160while (count < 3) {161r = read(fd, buf + count, 3 - count);162if (r <= 0)163return -1;164count += r;165}166167/* Now we read the parameters. */168if (buf[2] < (size - 3))169remain = buf[2];170else171remain = size - 3;172173while ((count - 3) < remain) {174r = read(fd, buf + count, remain - (count - 3));175if (r <= 0)176return -1;177count += r;178}179180return count;181}182183/*184* Ericsson specific initialization185*/186static int ericsson(int fd, struct uart_t *u, struct termios *ti)187{188struct timespec tm = {0, 50000};189char cmd[5];190191cmd[0] = HCI_COMMAND_PKT;192cmd[1] = 0x09;193cmd[2] = 0xfc;194cmd[3] = 0x01;195196switch (u->speed) {197case 57600:198cmd[4] = 0x03;199break;200case 115200:201cmd[4] = 0x02;202break;203case 230400:204cmd[4] = 0x01;205break;206case 460800:207cmd[4] = 0x00;208break;209case 921600:210cmd[4] = 0x20;211break;212case 2000000:213cmd[4] = 0x25;214break;215case 3000000:216cmd[4] = 0x27;217break;218case 4000000:219cmd[4] = 0x2B;220break;221default:222cmd[4] = 0x03;223u->speed = 57600;224fprintf(stderr, "Invalid speed requested, using %d bps instead\n", u->speed);225break;226}227228/* Send initialization command */229if (write(fd, cmd, 5) != 5) {230perror("Failed to write init command");231return -1;232}233234nanosleep(&tm, NULL);235return 0;236}237238/*239* Digianswer specific initialization240*/241static int digi(int fd, struct uart_t *u, struct termios *ti)242{243struct timespec tm = {0, 50000};244char cmd[5];245246/* DigiAnswer set baud rate command */247cmd[0] = HCI_COMMAND_PKT;248cmd[1] = 0x07;249cmd[2] = 0xfc;250cmd[3] = 0x01;251252switch (u->speed) {253case 57600:254cmd[4] = 0x08;255break;256case 115200:257cmd[4] = 0x09;258break;259default:260cmd[4] = 0x09;261u->speed = 115200;262break;263}264265/* Send initialization command */266if (write(fd, cmd, 5) != 5) {267perror("Failed to write init command");268return -1;269}270271nanosleep(&tm, NULL);272return 0;273}274275static int texas(int fd, struct uart_t *u, struct termios *ti)276{277return texas_init(fd, &u->speed, ti);278}279280static int texas2(int fd, struct uart_t *u, struct termios *ti)281{282return texas_post(fd, ti);283}284285static int texasalt(int fd, struct uart_t *u, struct termios *ti)286{287return texasalt_init(fd, u->speed, ti);288}289290static int ath3k_ps(int fd, struct uart_t *u, struct termios *ti)291{292return ath3k_init(fd, u->speed, u->init_speed, u->bdaddr, ti);293}294295static int ath3k_pm(int fd, struct uart_t *u, struct termios *ti)296{297return ath3k_post(fd, u->pm);298}299300static int qualcomm(int fd, struct uart_t *u, struct termios *ti)301{302return qualcomm_init(fd, u->speed, ti, u->bdaddr);303}304305static int intel(int fd, struct uart_t *u, struct termios *ti)306{307return intel_init(fd, u->init_speed, &u->speed, ti);308}309310static int bcm43xx(int fd, struct uart_t *u, struct termios *ti)311{312return bcm43xx_init(fd, u->speed, ti, u->bdaddr);313}314315//Realtek_add_start316//add realtek Bluetooth init and post function.317static int realtek_init(int fd, struct uart_t *u, struct termios *ti)318{319fprintf(stderr, "Realtek Bluetooth init uart with init speed:%d, final_speed:%d, type:HCI UART %s\n", u->init_speed, u->speed, (u->proto == HCI_UART_H4)? "H4":"H5" );320return rtk_init(fd, u->proto, u->speed, ti);321}322323static int realtek_post(int fd, struct uart_t *u, struct termios *ti)324{325fprintf(stderr, "Realtek Bluetooth post process\n");326return rtk_post(fd, u->proto, ti);327}328329// add xradio Bluetooth init and post function.330static int xradio_init(int fd, struct uart_t *u, struct termios *ti)331{332fprintf(stderr, "XRADIO Bluetooth init uart with init speed:%d, final_speed:%d, type:HCI UART %s\n", u->init_speed, u->speed, (u->proto == HCI_UART_H4)? "H4":"H5" );333return xr_init(fd, u, ti);334}335336static int xradio_post(int fd, struct uart_t *u, struct termios *ti)337{338fprintf(stderr, "XRADIO Bluetooth post process\n");339return xr_post(fd, u, ti);340}341342// add sprd Bluetooth init and post function.343static int sprd_init(int fd, struct uart_t *u, struct termios *ti)344{345fprintf(stderr, "SPRD Bluetooth init uart with init speed:%d, final_speed:%d, type:HCI UART %s\n", u->init_speed, u->speed, (u->proto == HCI_UART_H4)? "H4":"H5" );346return sprd_config_init(fd, u, ti);347}348349static int sprd_post(int fd, struct uart_t *u, struct termios *ti)350{351fprintf(stderr, "SPRD Bluetooth post process\n");352return sprd_config_post(fd, u, ti);353}354355static int read_check(int fd, void *buf, int count)356{357int res;358359do {360res = read(fd, buf, count);361if (res != -1) {362buf += res;363count -= res;364}365} while (count && (errno == 0 || errno == EINTR));366367if (count)368return -1;369370return 0;371}372373/*374* BCSP specific initialization375*/376static int serial_fd;377static int bcsp_max_retries = 10;378379static void bcsp_tshy_sig_alarm(int sig)380{381unsigned char bcsp_sync_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xda,0xdc,0xed,0xed,0xc0};382static int retries = 0;383384if (retries < bcsp_max_retries) {385retries++;386if (write(serial_fd, &bcsp_sync_pkt, 10) < 0)387return;388alarm(1);389return;390}391392tcflush(serial_fd, TCIOFLUSH);393fprintf(stderr, "BCSP initialization timed out\n");394exit(1);395}396397static void bcsp_tconf_sig_alarm(int sig)398{399unsigned char bcsp_conf_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xad,0xef,0xac,0xed,0xc0};400static int retries = 0;401402if (retries < bcsp_max_retries){403retries++;404if (write(serial_fd, &bcsp_conf_pkt, 10) < 0)405return;406alarm(1);407return;408}409410tcflush(serial_fd, TCIOFLUSH);411fprintf(stderr, "BCSP initialization timed out\n");412exit(1);413}414415static int bcsp(int fd, struct uart_t *u, struct termios *ti)416{417unsigned char byte, bcsph[4], bcspp[4],418bcsp_sync_resp_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xac,0xaf,0xef,0xee,0xc0},419bcsp_conf_resp_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xde,0xad,0xd0,0xd0,0xc0},420bcspsync[4] = {0xda, 0xdc, 0xed, 0xed},421bcspsyncresp[4] = {0xac,0xaf,0xef,0xee},422bcspconf[4] = {0xad,0xef,0xac,0xed},423bcspconfresp[4] = {0xde,0xad,0xd0,0xd0};424struct sigaction sa;425int len;426427if (set_speed(fd, ti, u->speed) < 0) {428perror("Can't set default baud rate");429return -1;430}431432ti->c_cflag |= PARENB;433ti->c_cflag &= ~(PARODD);434435if (tcsetattr(fd, TCSANOW, ti) < 0) {436perror("Can't set port settings");437return -1;438}439440alarm(0);441442serial_fd = fd;443memset(&sa, 0, sizeof(sa));444sa.sa_flags = SA_NOCLDSTOP;445sa.sa_handler = bcsp_tshy_sig_alarm;446sigaction(SIGALRM, &sa, NULL);447448/* State = shy */449450bcsp_tshy_sig_alarm(0);451while (1) {452do {453if (read_check(fd, &byte, 1) == -1){454perror("Failed to read");455return -1;456}457} while (byte != 0xC0);458459do {460if ( read_check(fd, &bcsph[0], 1) == -1){461perror("Failed to read");462return -1;463}464} while (bcsph[0] == 0xC0);465466if ( read_check(fd, &bcsph[1], 3) == -1){467perror("Failed to read");468return -1;469}470471if (((bcsph[0] + bcsph[1] + bcsph[2]) & 0xFF) != (unsigned char)~bcsph[3])472continue;473if (bcsph[1] != 0x41 || bcsph[2] != 0x00)474continue;475476if (read_check(fd, &bcspp, 4) == -1){477perror("Failed to read");478return -1;479}480481if (!memcmp(bcspp, bcspsync, 4)) {482if (write(fd, &bcsp_sync_resp_pkt,10) < 0)483return -1;484} else if (!memcmp(bcspp, bcspsyncresp, 4))485break;486}487488/* State = curious */489490alarm(0);491sa.sa_handler = bcsp_tconf_sig_alarm;492sigaction(SIGALRM, &sa, NULL);493alarm(1);494495while (1) {496do {497if (read_check(fd, &byte, 1) == -1){498perror("Failed to read");499return -1;500}501} while (byte != 0xC0);502503do {504if (read_check(fd, &bcsph[0], 1) == -1){505perror("Failed to read");506return -1;507}508} while (bcsph[0] == 0xC0);509510if (read_check(fd, &bcsph[1], 3) == -1){511perror("Failed to read");512return -1;513}514515if (((bcsph[0] + bcsph[1] + bcsph[2]) & 0xFF) != (unsigned char)~bcsph[3])516continue;517518if (bcsph[1] != 0x41 || bcsph[2] != 0x00)519continue;520521if (read_check(fd, &bcspp, 4) == -1){522perror("Failed to read");523return -1;524}525526if (!memcmp(bcspp, bcspsync, 4))527len = write(fd, &bcsp_sync_resp_pkt, 10);528else if (!memcmp(bcspp, bcspconf, 4))529len = write(fd, &bcsp_conf_resp_pkt, 10);530else if (!memcmp(bcspp, bcspconfresp, 4))531break;532else533continue;534535if (len < 0)536return -errno;537}538539/* State = garrulous */540541return 0;542}543544/*545* CSR specific initialization546* Inspired strongly by code in OpenBT and experimentations with Brainboxes547* Pcmcia card.548* Jean Tourrilhes <[email protected]> - 14.11.01549*/550static int csr(int fd, struct uart_t *u, struct termios *ti)551{552struct timespec tm = {0, 10000000}; /* 10ms - be generous */553unsigned char cmd[30]; /* Command */554unsigned char resp[30]; /* Response */555int clen = 0; /* Command len */556static int csr_seq = 0; /* Sequence number of command */557int divisor;558559/* It seems that if we set the CSR UART speed straight away, it560* won't work, the CSR UART gets into a state where we can't talk561* to it anymore.562* On the other hand, doing a read before setting the CSR speed563* seems to be ok.564* Therefore, the strategy is to read the build ID (useful for565* debugging) and only then set the CSR UART speed. Doing like566* this is more complex but at least it works ;-)567* The CSR UART control may be slow to wake up or something because568* every time I read its speed, its bogus...569* Jean II */570571/* Try to read the build ID of the CSR chip */572clen = 5 + (5 + 6) * 2;573/* HCI header */574cmd[0] = HCI_COMMAND_PKT;575cmd[1] = 0x00; /* CSR command */576cmd[2] = 0xfc; /* MANUFACTURER_SPEC */577cmd[3] = 1 + (5 + 6) * 2; /* len */578/* CSR MSG header */579cmd[4] = 0xC2; /* first+last+channel=BCC */580/* CSR BCC header */581cmd[5] = 0x00; /* type = GET-REQ */582cmd[6] = 0x00; /* - msB */583cmd[7] = 5 + 4; /* len */584cmd[8] = 0x00; /* - msB */585cmd[9] = csr_seq & 0xFF;/* seq num */586cmd[10] = (csr_seq >> 8) & 0xFF; /* - msB */587csr_seq++;588cmd[11] = 0x19; /* var_id = CSR_CMD_BUILD_ID */589cmd[12] = 0x28; /* - msB */590cmd[13] = 0x00; /* status = STATUS_OK */591cmd[14] = 0x00; /* - msB */592/* CSR BCC payload */593memset(cmd + 15, 0, 6 * 2);594595/* Send command */596do {597if (write(fd, cmd, clen) != clen) {598perror("Failed to write init command (GET_BUILD_ID)");599return -1;600}601602/* Read reply. */603if (read_hci_event(fd, resp, 100) < 0) {604perror("Failed to read init response (GET_BUILD_ID)");605return -1;606}607608/* Event code 0xFF is for vendor-specific events, which is609* what we're looking for. */610} while (resp[1] != 0xFF);611612#ifdef CSR_DEBUG613{614char temp[512];615int i;616for (i=0; i < rlen; i++)617sprintf(temp + (i*3), "-%02X", resp[i]);618fprintf(stderr, "Reading CSR build ID %d [%s]\n", rlen, temp + 1);619// In theory, it should look like :620// 04-FF-13-FF-01-00-09-00-00-00-19-28-00-00-73-00-00-00-00-00-00-00621}622#endif623/* Display that to user */624fprintf(stderr, "CSR build ID 0x%02X-0x%02X\n",625resp[15] & 0xFF, resp[14] & 0xFF);626627/* Try to read the current speed of the CSR chip */628clen = 5 + (5 + 4)*2;629/* -- HCI header */630cmd[3] = 1 + (5 + 4)*2; /* len */631/* -- CSR BCC header -- */632cmd[9] = csr_seq & 0xFF; /* seq num */633cmd[10] = (csr_seq >> 8) & 0xFF; /* - msB */634csr_seq++;635cmd[11] = 0x02; /* var_id = CONFIG_UART */636cmd[12] = 0x68; /* - msB */637638#ifdef CSR_DEBUG639/* Send command */640do {641if (write(fd, cmd, clen) != clen) {642perror("Failed to write init command (GET_BUILD_ID)");643return -1;644}645646/* Read reply. */647if (read_hci_event(fd, resp, 100) < 0) {648perror("Failed to read init response (GET_BUILD_ID)");649return -1;650}651652/* Event code 0xFF is for vendor-specific events, which is653* what we're looking for. */654} while (resp[1] != 0xFF);655656{657char temp[512];658int i;659for (i=0; i < rlen; i++)660sprintf(temp + (i*3), "-%02X", resp[i]);661fprintf(stderr, "Reading CSR UART speed %d [%s]\n", rlen, temp+1);662}663#endif664665if (u->speed > 1500000) {666fprintf(stderr, "Speed %d too high. Remaining at %d baud\n",667u->speed, u->init_speed);668u->speed = u->init_speed;669} else if (u->speed != 57600 && uart_speed(u->speed) == B57600) {670/* Unknown speed. Why oh why can't we just pass an int to the kernel? */671fprintf(stderr, "Speed %d unrecognised. Remaining at %d baud\n",672u->speed, u->init_speed);673u->speed = u->init_speed;674}675if (u->speed == u->init_speed)676return 0;677678/* Now, create the command that will set the UART speed */679/* CSR BCC header */680cmd[5] = 0x02; /* type = SET-REQ */681cmd[6] = 0x00; /* - msB */682cmd[9] = csr_seq & 0xFF; /* seq num */683cmd[10] = (csr_seq >> 8) & 0xFF;/* - msB */684csr_seq++;685686divisor = (u->speed*64+7812)/15625;687688/* No parity, one stop bit -> divisor |= 0x0000; */689cmd[15] = (divisor) & 0xFF; /* divider */690cmd[16] = (divisor >> 8) & 0xFF; /* - msB */691/* The rest of the payload will be 0x00 */692693#ifdef CSR_DEBUG694{695char temp[512];696int i;697for(i = 0; i < clen; i++)698sprintf(temp + (i*3), "-%02X", cmd[i]);699fprintf(stderr, "Writing CSR UART speed %d [%s]\n", clen, temp + 1);700// In theory, it should look like :701// 01-00-FC-13-C2-02-00-09-00-03-00-02-68-00-00-BF-0E-00-00-00-00-00-00702// 01-00-FC-13-C2-02-00-09-00-01-00-02-68-00-00-D8-01-00-00-00-00-00-00703}704#endif705706/* Send the command to set the CSR UART speed */707if (write(fd, cmd, clen) != clen) {708perror("Failed to write init command (SET_UART_SPEED)");709return -1;710}711712nanosleep(&tm, NULL);713return 0;714}715716/*717* Silicon Wave specific initialization718* Thomas Moser <[email protected]>719*/720static int swave(int fd, struct uart_t *u, struct termios *ti)721{722struct timespec tm = { 0, 500000 };723char cmd[10], rsp[100];724int r;725726// Silicon Wave set baud rate command727// see HCI Vendor Specific Interface from Silicon Wave728// first send a "param access set" command to set the729// appropriate data fields in RAM. Then send a "HCI Reset730// Subcommand", e.g. "soft reset" to make the changes effective.731732cmd[0] = HCI_COMMAND_PKT; // it's a command packet733cmd[1] = 0x0B; // OCF 0x0B = param access set734cmd[2] = 0xfc; // OGF bx111111 = vendor specific735cmd[3] = 0x06; // 6 bytes of data following736cmd[4] = 0x01; // param sub command737cmd[5] = 0x11; // tag 17 = 0x11 = HCI Transport Params738cmd[6] = 0x03; // length of the parameter following739cmd[7] = 0x01; // HCI Transport flow control enable740cmd[8] = 0x01; // HCI Transport Type = UART741742switch (u->speed) {743case 19200:744cmd[9] = 0x03;745break;746case 38400:747cmd[9] = 0x02;748break;749case 57600:750cmd[9] = 0x01;751break;752case 115200:753cmd[9] = 0x00;754break;755default:756u->speed = 115200;757cmd[9] = 0x00;758break;759}760761/* Send initialization command */762if (write(fd, cmd, 10) != 10) {763perror("Failed to write init command");764return -1;765}766767// We should wait for a "GET Event" to confirm the success of768// the baud rate setting. Wait some time before reading. Better:769// read with timeout, parse data770// until correct answer, else error handling ... todo ...771772nanosleep(&tm, NULL);773774r = read(fd, rsp, sizeof(rsp));775if (r > 0) {776// guess it's okay, but we should parse the reply. But since777// I don't react on an error anyway ... todo778// Response packet format:779// 04 Event780// FF Vendor specific781// 07 Parameter length782// 0B Subcommand783// 01 Setevent784// 11 Tag specifying HCI Transport Layer Parameter785// 03 length786// 01 flow on787// 01 Hci Transport type = Uart788// xx Baud rate set (see above)789} else {790// ups, got error.791return -1;792}793794// we probably got the reply. Now we must send the "soft reset"795// which is standard HCI RESET.796797cmd[0] = HCI_COMMAND_PKT; // it's a command packet798cmd[1] = 0x03;799cmd[2] = 0x0c;800cmd[3] = 0x00;801802/* Send reset command */803if (write(fd, cmd, 4) != 4) {804perror("Can't write Silicon Wave reset cmd.");805return -1;806}807808nanosleep(&tm, NULL);809810// now the uart baud rate on the silicon wave module is set and effective.811// change our own baud rate as well. Then there is a reset event coming in812// on the *new* baud rate. This is *undocumented*! The packet looks like this:813// 04 FF 01 0B (which would make that a confirmation of 0x0B = "Param814// subcommand class". So: change to new baud rate, read with timeout, parse815// data, error handling. BTW: all param access in Silicon Wave is done this way.816// Maybe this code would belong in a separate file, or at least code reuse...817818return 0;819}820821/*822* ST Microelectronics specific initialization823* Marcel Holtmann <[email protected]>824*/825static int st(int fd, struct uart_t *u, struct termios *ti)826{827struct timespec tm = {0, 50000};828char cmd[5];829830/* ST Microelectronics set baud rate command */831cmd[0] = HCI_COMMAND_PKT;832cmd[1] = 0x46; // OCF = Hci_Cmd_ST_Set_Uart_Baud_Rate833cmd[2] = 0xfc; // OGF = Vendor specific834cmd[3] = 0x01;835836switch (u->speed) {837case 9600:838cmd[4] = 0x09;839break;840case 19200:841cmd[4] = 0x0b;842break;843case 38400:844cmd[4] = 0x0d;845break;846case 57600:847cmd[4] = 0x0e;848break;849case 115200:850cmd[4] = 0x10;851break;852case 230400:853cmd[4] = 0x12;854break;855case 460800:856cmd[4] = 0x13;857break;858case 921600:859cmd[4] = 0x14;860break;861default:862cmd[4] = 0x10;863u->speed = 115200;864break;865}866867/* Send initialization command */868if (write(fd, cmd, 5) != 5) {869perror("Failed to write init command");870return -1;871}872873nanosleep(&tm, NULL);874return 0;875}876877static int stlc2500(int fd, struct uart_t *u, struct termios *ti)878{879bdaddr_t bdaddr;880unsigned char resp[10];881int n;882int rvalue;883884/* STLC2500 has an ericsson core */885rvalue = ericsson(fd, u, ti);886if (rvalue != 0)887return rvalue;888889#ifdef STLC2500_DEBUG890fprintf(stderr, "Setting speed\n");891#endif892if (set_speed(fd, ti, u->speed) < 0) {893perror("Can't set baud rate");894return -1;895}896897#ifdef STLC2500_DEBUG898fprintf(stderr, "Speed set...\n");899#endif900901/* Read reply */902if ((n = read_hci_event(fd, resp, 10)) < 0) {903fprintf(stderr, "Failed to set baud rate on chip\n");904return -1;905}906907#ifdef STLC2500_DEBUG908for (i = 0; i < n; i++) {909fprintf(stderr, "resp[%d] = %02x\n", i, resp[i]);910}911#endif912913str2ba(u->bdaddr, &bdaddr);914return stlc2500_init(fd, &bdaddr);915}916917static int bgb2xx(int fd, struct uart_t *u, struct termios *ti)918{919bdaddr_t bdaddr;920921str2ba(u->bdaddr, &bdaddr);922923return bgb2xx_init(fd, &bdaddr);924}925926/*927* Broadcom specific initialization928* Extracted from Jungo openrg929*/930static int bcm2035(int fd, struct uart_t *u, struct termios *ti)931{932int n;933unsigned char cmd[30], resp[30];934935/* Reset the BT Chip */936memset(cmd, 0, sizeof(cmd));937memset(resp, 0, sizeof(resp));938cmd[0] = HCI_COMMAND_PKT;939cmd[1] = 0x03;940cmd[2] = 0x0c;941cmd[3] = 0x00;942943/* Send command */944if (write(fd, cmd, 4) != 4) {945fprintf(stderr, "Failed to write reset command\n");946return -1;947}948949/* Read reply */950if ((n = read_hci_event(fd, resp, 4)) < 0) {951fprintf(stderr, "Failed to reset chip\n");952return -1;953}954955if (u->bdaddr != NULL) {956/* Set BD_ADDR */957memset(cmd, 0, sizeof(cmd));958memset(resp, 0, sizeof(resp));959cmd[0] = HCI_COMMAND_PKT;960cmd[1] = 0x01;961cmd[2] = 0xfc;962cmd[3] = 0x06;963str2ba(u->bdaddr, (bdaddr_t *) (cmd + 4));964965/* Send command */966if (write(fd, cmd, 10) != 10) {967fprintf(stderr, "Failed to write BD_ADDR command\n");968return -1;969}970971/* Read reply */972if ((n = read_hci_event(fd, resp, 10)) < 0) {973fprintf(stderr, "Failed to set BD_ADDR\n");974return -1;975}976}977978/* Read the local version info */979memset(cmd, 0, sizeof(cmd));980memset(resp, 0, sizeof(resp));981cmd[0] = HCI_COMMAND_PKT;982cmd[1] = 0x01;983cmd[2] = 0x10;984cmd[3] = 0x00;985986/* Send command */987if (write(fd, cmd, 4) != 4) {988fprintf(stderr, "Failed to write \"read local version\" "989"command\n");990return -1;991}992993/* Read reply */994if ((n = read_hci_event(fd, resp, 4)) < 0) {995fprintf(stderr, "Failed to read local version\n");996return -1;997}998999/* Read the local supported commands info */1000memset(cmd, 0, sizeof(cmd));1001memset(resp, 0, sizeof(resp));1002cmd[0] = HCI_COMMAND_PKT;1003cmd[1] = 0x02;1004cmd[2] = 0x10;1005cmd[3] = 0x00;10061007/* Send command */1008if (write(fd, cmd, 4) != 4) {1009fprintf(stderr, "Failed to write \"read local supported "1010"commands\" command\n");1011return -1;1012}10131014/* Read reply */1015if ((n = read_hci_event(fd, resp, 4)) < 0) {1016fprintf(stderr, "Failed to read local supported commands\n");1017return -1;1018}10191020/* Set the baud rate */1021memset(cmd, 0, sizeof(cmd));1022memset(resp, 0, sizeof(resp));1023cmd[0] = HCI_COMMAND_PKT;1024cmd[1] = 0x18;1025cmd[2] = 0xfc;1026cmd[3] = 0x02;1027switch (u->speed) {1028case 57600:1029cmd[4] = 0x00;1030cmd[5] = 0xe6;1031break;1032case 230400:1033cmd[4] = 0x22;1034cmd[5] = 0xfa;1035break;1036case 460800:1037cmd[4] = 0x22;1038cmd[5] = 0xfd;1039break;1040case 921600:1041cmd[4] = 0x55;1042cmd[5] = 0xff;1043break;1044default:1045/* Default is 115200 */1046cmd[4] = 0x00;1047cmd[5] = 0xf3;1048break;1049}1050fprintf(stderr, "Baud rate parameters: DHBR=0x%2x,DLBR=0x%2x\n",1051cmd[4], cmd[5]);10521053/* Send command */1054if (write(fd, cmd, 6) != 6) {1055fprintf(stderr, "Failed to write \"set baud rate\" command\n");1056return -1;1057}10581059if ((n = read_hci_event(fd, resp, 6)) < 0) {1060fprintf(stderr, "Failed to set baud rate\n");1061return -1;1062}10631064return 0;1065}10661067struct uart_t uart[] = {1068{ "any", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,1069FLOW_CTL, DISABLE_PM, NULL, NULL, NULL },10701071{ "ericsson", 0x0000, 0x0000, HCI_UART_H4, 57600, 115200,1072FLOW_CTL, DISABLE_PM, NULL, ericsson, NULL },10731074{ "digi", 0x0000, 0x0000, HCI_UART_H4, 9600, 115200,1075FLOW_CTL, DISABLE_PM, NULL, digi, NULL },10761077{ "bcsp", 0x0000, 0x0000, HCI_UART_BCSP, 115200, 115200,10780, DISABLE_PM, NULL, bcsp, NULL },10791080/* Xircom PCMCIA cards: Credit Card Adapter and Real Port Adapter */1081{ "xircom", 0x0105, 0x080a, HCI_UART_H4, 115200, 115200,1082FLOW_CTL, DISABLE_PM, NULL, NULL, NULL },10831084/* CSR Casira serial adapter or BrainBoxes serial dongle (BL642) */1085{ "csr", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,1086FLOW_CTL, DISABLE_PM, NULL, csr, NULL },10871088/* BrainBoxes PCMCIA card (BL620) */1089{ "bboxes", 0x0160, 0x0002, HCI_UART_H4, 115200, 460800,1090FLOW_CTL, DISABLE_PM, NULL, csr, NULL },10911092/* Silicon Wave kits */1093{ "swave", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,1094FLOW_CTL, DISABLE_PM, NULL, swave, NULL },10951096/* Texas Instruments Bluelink (BRF) modules */1097{ "texas", 0x0000, 0x0000, HCI_UART_LL, 115200, 115200,1098FLOW_CTL, DISABLE_PM, NULL, texas, texas2 },10991100{ "texasalt", 0x0000, 0x0000, HCI_UART_LL, 115200, 115200,1101FLOW_CTL, DISABLE_PM, NULL, texasalt, NULL },11021103/* ST Microelectronics minikits based on STLC2410/STLC2415 */1104{ "st", 0x0000, 0x0000, HCI_UART_H4, 57600, 115200,1105FLOW_CTL, DISABLE_PM, NULL, st, NULL },11061107/* ST Microelectronics minikits based on STLC2500 */1108{ "stlc2500", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,1109FLOW_CTL, DISABLE_PM, "00:80:E1:00:AB:BA", stlc2500, NULL },11101111/* Philips generic Ericsson IP core based */1112{ "philips", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,1113FLOW_CTL, DISABLE_PM, NULL, NULL, NULL },11141115/* Philips BGB2xx Module */1116{ "bgb2xx", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,1117FLOW_CTL, DISABLE_PM, "BD:B2:10:00:AB:BA", bgb2xx, NULL },11181119/* Sphinx Electronics PICO Card */1120{ "picocard", 0x025e, 0x1000, HCI_UART_H4, 115200, 115200,1121FLOW_CTL, DISABLE_PM, NULL, NULL, NULL },11221123/* Inventel BlueBird Module */1124{ "inventel", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,1125FLOW_CTL, DISABLE_PM, NULL, NULL, NULL },11261127/* COM One Platinium Bluetooth PC Card */1128{ "comone", 0xffff, 0x0101, HCI_UART_BCSP, 115200, 115200,11290, DISABLE_PM, NULL, bcsp, NULL },11301131/* TDK Bluetooth PC Card and IBM Bluetooth PC Card II */1132{ "tdk", 0x0105, 0x4254, HCI_UART_BCSP, 115200, 115200,11330, DISABLE_PM, NULL, bcsp, NULL },11341135/* Socket Bluetooth CF Card (Rev G) */1136{ "socket", 0x0104, 0x0096, HCI_UART_BCSP, 230400, 230400,11370, DISABLE_PM, NULL, bcsp, NULL },11381139/* 3Com Bluetooth Card (Version 3.0) */1140{ "3com", 0x0101, 0x0041, HCI_UART_H4, 115200, 115200,1141FLOW_CTL, DISABLE_PM, NULL, csr, NULL },11421143/* AmbiCom BT2000C Bluetooth PC/CF Card */1144{ "bt2000c", 0x022d, 0x2000, HCI_UART_H4, 57600, 460800,1145FLOW_CTL, DISABLE_PM, NULL, csr, NULL },11461147/* Zoom Bluetooth PCMCIA Card */1148{ "zoom", 0x0279, 0x950b, HCI_UART_BCSP, 115200, 115200,11490, DISABLE_PM, NULL, bcsp, NULL },11501151/* Sitecom CN-504 PCMCIA Card */1152{ "sitecom", 0x0279, 0x950b, HCI_UART_BCSP, 115200, 115200,11530, DISABLE_PM, NULL, bcsp, NULL },11541155/* Billionton PCBTC1 PCMCIA Card */1156{ "billionton", 0x0279, 0x950b, HCI_UART_BCSP, 115200, 115200,11570, DISABLE_PM, NULL, bcsp, NULL },11581159/* Broadcom BCM2035 */1160{ "bcm2035", 0x0A5C, 0x2035, HCI_UART_H4, 115200, 460800,1161FLOW_CTL, DISABLE_PM, NULL, bcm2035, NULL },11621163/* Broadcom BCM43XX */1164{ "bcm43xx", 0x0000, 0x0000, HCI_UART_H4, 115200, 3000000,1165FLOW_CTL, DISABLE_PM, NULL, bcm43xx, NULL },11661167{ "ath3k", 0x0000, 0x0000, HCI_UART_ATH3K, 115200, 115200,1168FLOW_CTL, DISABLE_PM, NULL, ath3k_ps, ath3k_pm },11691170/* QUALCOMM BTS */1171{ "qualcomm", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,1172FLOW_CTL, DISABLE_PM, NULL, qualcomm, NULL },11731174/* Intel Bluetooth Module */1175{ "intel", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,1176FLOW_CTL, DISABLE_PM, NULL, intel, NULL },11771178/* Three-wire UART */1179{ "3wire", 0x0000, 0x0000, HCI_UART_3WIRE, 115200, 115200,11800, DISABLE_PM, NULL, NULL, NULL },11811182/* AMP controller UART */1183{ "amp", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200,1184AMP_DEV, DISABLE_PM, NULL, NULL, NULL },11851186//Realtek_add_start1187/* Realtek Bluetooth H4*/1188/* H4 will set 115200 baudrate and flow control enable by default*/1189{ "rtk_h4", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200, FLOW_CTL, DISABLE_PM, NULL, realtek_init, realtek_post},1190/* Realtek Bluetooth H5*/1191/* H5 will set 921600 baudrate and flow control disable by default */1192/* H5 will be realtek's recommanded protocol */1193{ "rtk_h5", 0x0000, 0x0000, HCI_UART_3WIRE, 115200,115200, 0, DISABLE_PM, NULL, realtek_init, realtek_post},1194//Realtek_add_end11951196{ "xradio", 0x0000, 0x0000, HCI_UART_H4, 115200, 1500000, 0, DISABLE_PM, NULL, xradio_init, xradio_post},1197{ "sprd", 0x0000, 0x0000, NULL, 115200, 1500000, FLOW_CTL, DISABLE_PM, NULL, sprd_init, sprd_post},11981199{ NULL, 0 }1200};12011202static struct uart_t * get_by_id(int m_id, int p_id)1203{1204int i;1205for (i = 0; uart[i].type; i++) {1206if (uart[i].m_id == m_id && uart[i].p_id == p_id)1207return &uart[i];1208}1209return NULL;1210}12111212static struct uart_t * get_by_type(char *type)1213{1214int i;1215for (i = 0; uart[i].type; i++) {1216if (!strcmp(uart[i].type, type))1217return &uart[i];1218}1219return NULL;1220}12211222/* Initialize UART driver */1223static int init_uart(char *dev, struct uart_t *u, int send_break, int raw)1224{1225struct termios ti;1226int fd, i;1227unsigned long flags = 0;12281229if (raw)1230flags |= 1 << HCI_UART_RAW_DEVICE;12311232if (u->flags & AMP_DEV)1233flags |= 1 << HCI_UART_CREATE_AMP;12341235fd = open(dev, O_RDWR | O_NOCTTY);1236if (fd < 0) {1237perror("Can't open serial port");1238return -1;1239}12401241tcflush(fd, TCIOFLUSH);12421243if (tcgetattr(fd, &ti) < 0) {1244perror("Can't get port settings");1245return -1;1246}12471248cfmakeraw(&ti);12491250ti.c_cflag |= CLOCAL;1251if (u->flags & FLOW_CTL)1252ti.c_cflag |= CRTSCTS;1253else1254ti.c_cflag &= ~CRTSCTS;12551256if (tcsetattr(fd, TCSANOW, &ti) < 0) {1257perror("Can't set port settings");1258return -1;1259}12601261/* Set initial baudrate */1262if (set_speed(fd, &ti, u->init_speed) < 0) {1263perror("Can't set initial baud rate");1264return -1;1265}12661267tcflush(fd, TCIOFLUSH);12681269if (send_break) {1270tcsendbreak(fd, 0);1271usleep(500000);1272}12731274if (u->init && u->init(fd, u, &ti) < 0)1275return -1;12761277tcflush(fd, TCIOFLUSH);12781279/* Set actual baudrate */1280if (set_speed(fd, &ti, u->speed) < 0) {1281perror("Can't set baud rate");1282return -1;1283}12841285/* Set TTY to N_HCI line discipline */1286i = N_HCI;1287if (ioctl(fd, TIOCSETD, &i) < 0) {1288perror("Can't set line discipline");1289return -1;1290}12911292if (flags && ioctl(fd, HCIUARTSETFLAGS, flags) < 0) {1293perror("Can't set UART flags");1294return -1;1295}12961297if (ioctl(fd, HCIUARTSETPROTO, u->proto) < 0) {1298perror("Can't set device");1299return -1;1300}13011302if (u->post && u->post(fd, u, &ti) < 0)1303return -1;13041305return fd;1306}13071308static void usage(void)1309{1310printf("hciattach - HCI UART driver initialization utility\n");1311printf("Usage:\n");1312printf("\thciattach [-n] [-p] [-b] [-r] [-t timeout] [-s initial_speed] <tty> <type | id> [speed] [flow|noflow] [bdaddr]\n");1313printf("\thciattach -l\n");1314}13151316int main(int argc, char *argv[])1317{1318struct uart_t *u = NULL;1319int detach, printpid, raw, opt, i, n, ld, err;1320int to = 10;1321int init_speed = 0;1322int send_break = 0;1323pid_t pid;1324struct sigaction sa;1325struct pollfd p;1326sigset_t sigs;1327char dev[PATH_MAX];13281329detach = 1;1330printpid = 0;1331raw = 0;13321333while ((opt=getopt(argc, argv, "bnpt:s:lr")) != EOF) {1334switch(opt) {1335case 'b':1336send_break = 1;1337break;13381339case 'n':1340detach = 0;1341break;13421343case 'p':1344printpid = 1;1345break;13461347case 't':1348to = atoi(optarg);1349break;13501351case 's':1352init_speed = atoi(optarg);1353break;13541355case 'l':1356for (i = 0; uart[i].type; i++) {1357printf("%-10s0x%04x,0x%04x\n", uart[i].type,1358uart[i].m_id, uart[i].p_id);1359}1360exit(0);13611362case 'r':1363raw = 1;1364break;13651366default:1367usage();1368exit(1);1369}1370}13711372n = argc - optind;1373if (n < 2) {1374usage();1375exit(1);1376}13771378for (n = 0; optind < argc; n++, optind++) {1379char *opt;13801381opt = argv[optind];13821383switch(n) {1384case 0:1385dev[0] = 0;1386if (!strchr(opt, '/'))1387strcpy(dev, "/dev/");1388strcat(dev, opt);1389break;13901391case 1:1392if (strchr(argv[optind], ',')) {1393uint32_t m_id, p_id;1394sscanf(argv[optind], "%x,%x", &m_id, &p_id);1395u = get_by_id(m_id, p_id);1396} else {1397u = get_by_type(opt);1398}13991400if (!u) {1401fprintf(stderr, "Unknown device type or id\n");1402exit(1);1403}14041405break;14061407case 2:1408u->speed = atoi(argv[optind]);1409break;14101411case 3:1412if (!strcmp("flow", argv[optind]))1413u->flags |= FLOW_CTL;1414else1415u->flags &= ~FLOW_CTL;1416break;14171418case 4:1419if (!strcmp("sleep", argv[optind]))1420u->pm = ENABLE_PM;1421else1422u->pm = DISABLE_PM;1423break;14241425case 5:1426u->bdaddr = argv[optind];1427break;1428}1429}14301431if (!u) {1432fprintf(stderr, "Unknown device type or id\n");1433exit(1);1434}14351436/* If user specified a initial speed, use that instead of1437the hardware's default */1438if (init_speed)1439u->init_speed = init_speed;14401441memset(&sa, 0, sizeof(sa));1442sa.sa_flags = SA_NOCLDSTOP;1443sa.sa_handler = sig_alarm;1444sigaction(SIGALRM, &sa, NULL);14451446/* 10 seconds should be enough for initialization */1447alarm(to);1448bcsp_max_retries = to;14491450n = init_uart(dev, u, send_break, raw);1451if (n < 0) {1452perror("Can't initialize device");1453exit(1);1454}14551456printf("Device setup complete\n");14571458alarm(0);14591460memset(&sa, 0, sizeof(sa));1461sa.sa_flags = SA_NOCLDSTOP;1462sa.sa_handler = SIG_IGN;1463sigaction(SIGCHLD, &sa, NULL);1464sigaction(SIGPIPE, &sa, NULL);14651466sa.sa_handler = sig_term;1467sigaction(SIGTERM, &sa, NULL);1468sigaction(SIGINT, &sa, NULL);14691470sa.sa_handler = sig_hup;1471sigaction(SIGHUP, &sa, NULL);14721473if (detach) {1474if ((pid = fork())) {1475if (printpid)1476printf("%d\n", pid);1477return 0;1478}14791480for (i = 0; i < 20; i++)1481if (i != n)1482close(i);1483}14841485p.fd = n;1486p.events = POLLERR | POLLHUP;14871488sigfillset(&sigs);1489sigdelset(&sigs, SIGCHLD);1490sigdelset(&sigs, SIGPIPE);1491sigdelset(&sigs, SIGTERM);1492sigdelset(&sigs, SIGINT);1493sigdelset(&sigs, SIGHUP);14941495while (!__io_canceled) {1496p.revents = 0;1497err = ppoll(&p, 1, NULL, &sigs);1498if (err < 0 && errno == EINTR)1499continue;1500if (err)1501break;1502}15031504/* Restore TTY line discipline */1505ld = N_TTY;1506if (ioctl(n, TIOCSETD, &ld) < 0) {1507perror("Can't restore line discipline");1508exit(1);1509}15101511return 0;1512}151315141515