hciattach

这个工具的源代码位于 external/bluetooth/bluez/Tools/hciattach.c

编译完会生成 hciattach 工具,

会被install 到 /system/bin/hciattach

1. 先介绍一个数据结构 uart_t :
struct uart_t {
        char *type;   //name,这里为texas
        int m_id;
        int p_id;
        int proto;
        int init_speed;  //波特率
        int speed;
        int flags;    //UART 标志位
        char *bdaddr;
        int (*init) (int fd, struct uart_t *u, struct termios *ti);   //u -> init,这里为texas
        int (*post) (int fd, struct uart_t *u, struct termios *ti);   //u -> post,这里为texas2
    };
2. 各种 BT 模块的 uart 参数配置:
struct uart_t uart[] = {
        { "any", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200, FLOW_CTL, NULL, NULL },
        { "ericsson", 0x0000, 0x0000, HCI_UART_H4, 57600, 115200, FLOW_CTL, NULL, ericsson },
        { "digi", 0x0000, 0x0000, HCI_UART_H4, 9600, 115200, FLOW_CTL, NULL, digi },
        { "bcsp", 0x0000, 0x0000, HCI_UART_BCSP, 115200, 115200, 0, NULL, bcsp },
        /* Xircom PCMCIA cards: Credit Card Adapter and Real Port Adapter */
        { "xircom", 0x0105, 0x080a, HCI_UART_H4, 115200, 115200, FLOW_CTL, NULL, NULL },
        /* CSR Casira serial adapter or BrainBoxes serial dongle (BL642) */
        { "csr", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200, FLOW_CTL, NULL, csr },
        /* BrainBoxes PCMCIA card (BL620) */
        { "bboxes", 0x0160, 0x0002, HCI_UART_H4, 115200, 460800, FLOW_CTL, NULL, csr },
        /* Silicon Wave kits */
        { "swave", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200, FLOW_CTL, NULL, swave },
        /* Texas Instruments Bluelink (BRF) modules */
        { "texas", 0x0000, 0x0000, HCI_UART_LL, 115200, 115200, FLOW_CTL, NULL, texas, texas2 },   //这里就用的这项数据。
        { "texasalt", 0x0000, 0x0000, HCI_UART_LL, 115200, 115200, FLOW_CTL, NULL, texasalt, NULL },
        /* ST Microelectronics minikits based on STLC2410/STLC2415 */
        { "st", 0x0000, 0x0000, HCI_UART_H4, 57600, 115200, FLOW_CTL, NULL, st },
        /* ST Microelectronics minikits based on STLC2500 */
        { "stlc2500", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200, FLOW_CTL, "00:80:E1:00:AB:BA", stlc2500 },
        /* Philips generic Ericsson IP core based */
        { "philips", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200, FLOW_CTL, NULL, NULL },
        /* Philips BGB2xx Module */
        { "bgb2xx", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200, FLOW_CTL, "BD:B2:10:00:AB:BA", bgb2xx },
        /* Sphinx Electronics PICO Card */
        { "picocard", 0x025e, 0x1000, HCI_UART_H4, 115200, 115200, FLOW_CTL, NULL, NULL },
        /* Inventel BlueBird Module */
        { "inventel", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200, FLOW_CTL, NULL, NULL },
        /* COM One Platinium Bluetooth PC Card */
        { "comone", 0xffff, 0x0101, HCI_UART_BCSP, 115200, 115200, 0, NULL, bcsp },
        /* TDK Bluetooth PC Card and IBM Bluetooth PC Card II */
        { "tdk", 0x0105, 0x4254, HCI_UART_BCSP, 115200, 115200, 0, NULL, bcsp },
        /* Socket Bluetooth CF Card (Rev G) */
        { "socket", 0x0104, 0x0096, HCI_UART_BCSP, 230400, 230400, 0, NULL, bcsp },
        /* 3Com Bluetooth Card (Version 3.0) */
        { "3com", 0x0101, 0x0041, HCI_UART_H4, 115200, 115200, FLOW_CTL, NULL, csr },
        /* AmbiCom BT2000C Bluetooth PC/CF Card */
        { "bt2000c", 0x022d, 0x2000, HCI_UART_H4, 57600, 460800, FLOW_CTL, NULL, csr },
        /* Zoom Bluetooth PCMCIA Card */
        { "zoom", 0x0279, 0x950b, HCI_UART_BCSP, 115200, 115200, 0, NULL, bcsp },
        /* Sitecom CN-504 PCMCIA Card */
        { "sitecom", 0x0279, 0x950b, HCI_UART_BCSP, 115200, 115200, 0, NULL, bcsp },
        /* Billionton PCBTC1 PCMCIA Card */
        { "billionton", 0x0279, 0x950b, HCI_UART_BCSP, 115200, 115200, 0, NULL, bcsp },
        /* Broadcom BCM2035 */
        { "bcm2035", 0x0A5C, 0x2035, HCI_UART_H4, 115200, 460800, FLOW_CTL, NULL, bcm2035 },
        { NULL, 0 }
    };
3. main() 函数:
int main(int argc, char *argv[])
    {
        struct uart_t *u = NULL;
        int detach, printpid, raw, opt, i, n, ld, err;
        int to = 10;
        int init_speed = 0;
        int send_break = 0;
        pid_t pid;
        struct sigaction sa;
        struct pollfd p;
        sigset_t sigs;
        char dev[PATH_MAX];
        detach = 1;
        printpid = 0;
        raw = 0;
        while ((opt=getopt(argc, argv, "bnpt:s:lr")) != EOF) {  //解析参数
            switch(opt) {
            case 'b':
                send_break = 1;
                break;
            case 'n':   // 比如 有 -n 参数就会进这里
                detach = 0;
                break;
            case 'p':
                printpid = 1;
                break;
            case 't':
                to = atoi(optarg);
                break;
            case 's':
                init_speed = atoi(optarg);
                break;
            case 'l':
                for (i = 0; uart[i].type; i++) {
                    printf("%-10s0x%04x,0x%04x\n", uart[i].type,
                                uart[i].m_id, uart[i].p_id);
                }
                exit(0);
            case 'r':
                raw = 1;
                break;
            default:
                usage();
                exit(1);
            }
        }
        n = argc - optind;
        if (n < 2) {
            usage();
            exit(1);
        }
        for (n = 0; optind < argc; n++, optind++) {
            char *opt;
            opt = argv[optind];
            switch(n) {
            case 0:
                dev[0] = 0;
                if (!strchr(opt, '/'))     //opt = /dev/ttyO1
                    strcpy(dev, "/dev/");
                strcat(dev, opt);         //strcat之后,dev =/dev/ttyO1
                break;
            case 1:
                if (strchr(argv[optind], ',')) {
                    int m_id, p_id;
                    sscanf(argv[optind], "%x,%x", &m_id, &p_id);
                    u = get_by_id(m_id, p_id);
                } else {
                    u = get_by_type(opt);  //如果参数有/dev/ttyO1,就会这里得到uart_t u 
                }
                if (!u) {
                    fprintf(stderr, "Unknown device type or id\n");
                    exit(1);
                }
                break;
            case 2:
                u->speed = atoi(argv[optind]);  //这里获得波特率参数。
                break;
            case 3:
                if (!strcmp("flow", argv[optind]))
                    u->flags |= FLOW_CTL;    //uart flag 流控制标志
                else
                    u->flags &= ~FLOW_CTL;
                break;
            case 4:
                u->bdaddr = argv[optind];
                break;
            }
        }
        if (!u) {
            fprintf(stderr, "Unknown device type or id\n");
            exit(1);
        }
        /* If user specified a initial speed, use that instead of
         the hardware's default */
        if (init_speed)
            u->init_speed = init_speed;    //波特率
        memset(&sa, 0, sizeof(sa));
        sa.sa_flags = SA_NOCLDSTOP;
        sa.sa_handler = sig_alarm;        //sig_alarm = Initialization time out
        sigaction(SIGALRM, &sa, NULL);     //sigaction 超时后就会 打印出该sa_handler.
        /* 10 seconds should be enough for initialization */
        alarm(to);
        bcsp_max_retries = to;
        n = init_uart(dev, u, send_break, raw);   //这里会进入init_uart,初始化串口。
        if (n < 0) {
            perror("Can't initialize device");
            exit(1);
        }
        printf("Device setup complete\n");
        alarm(0);
        memset(&sa, 0, sizeof(sa));
        sa.sa_flags = SA_NOCLDSTOP;
        sa.sa_handler = SIG_IGN;
        sigaction(SIGCHLD, &sa, NULL);
        sigaction(SIGPIPE, &sa, NULL);
        sa.sa_handler = sig_term;
        sigaction(SIGTERM, &sa, NULL);
        sigaction(SIGINT, &sa, NULL);
        sa.sa_handler = sig_hup;
        sigaction(SIGHUP, &sa, NULL);
        if (detach) {
            if ((pid = fork())) {
                if (printpid)
                    printf("%d\n", pid);
                return 0;
            }
            for (i = 0; i < 20; i++)
                if (i != n)
                    close(i);
        }
        p.fd = n;
        p.events = POLLERR | POLLHUP;
        sigfillset(&sigs);
        sigdelset(&sigs, SIGCHLD);
        sigdelset(&sigs, SIGPIPE);
        sigdelset(&sigs, SIGTERM);
        sigdelset(&sigs, SIGINT);
        sigdelset(&sigs, SIGHUP);
        while (!__io_canceled) {
            p.revents = 0;
            err = ppoll(&p, 1, NULL, &sigs);
            if (err < 0 && errno == EINTR)
                continue;
            if (err)
                break;
        }
        /* Restore TTY line discipline */
        ld = N_TTY;
        if (ioctl(n, TIOCSETD, &ld) < 0) {
            perror("Can't restore line discipline");
            exit(1);
        }
        return 0;
    }
4.get_by_id() / get_by_type():
static struct uart_t * get_by_id(int m_id, int p_id)
    {
        int i;
        for (i = 0; uart[i].type; i++) {
            if (uart[i].m_id == m_id && uart[i].p_id == p_id)
                return &uart[i];
        }
        return NULL;
    }
    static struct uart_t * get_by_type(char *type)
    {
        int i;
        for (i = 0; uart[i].type; i++) {
            if (!strcmp(uart[i].type, type)) //获取/dev/ttyO1
                return &uart[i];
        }
        return NULL;
    }
5.init_uart():
/* Initialize UART driver */
    static int init_uart(char *dev, struct uart_t *u, int send_break, int raw)
    {
        struct termios ti;
        int fd, i;
        unsigned long flags = 0;
        if (raw)
            flags |= 1 << HCI_UART_RAW_DEVICE;
        fd = open(dev, O_RDWR | O_NOCTTY);  //打开 /dev/ttyO1
        if (fd < 0) {
            perror("Can't open serial port");
            return -1;
        }
        tcflush(fd, TCIOFLUSH);     //一系列 UART 口配置
        if (tcgetattr(fd, &ti) < 0) {
            perror("Can't get port settings");
            return -1;
        }
        cfmakeraw(&ti);         
        ti.c_cflag |= CLOCAL;
        if (u->flags & FLOW_CTL)     //添加流控制标志
            ti.c_cflag |= CRTSCTS;
        else
            ti.c_cflag &= ~CRTSCTS;
        if (tcsetattr(fd, TCSANOW, &ti) < 0) {
            perror("Can't set port settings");
            return -1;
        }
        /* Set initial baudrate */
        if (set_speed(fd, &ti, u->init_speed) < 0) {  //初始波特率设置
            perror("Can't set initial baud rate");
            return -1;
        }
        tcflush(fd, TCIOFLUSH);
        if (send_break) {
            tcsendbreak(fd, 0);
            usleep(500000);
        }
        if (u->init && u->init(fd, u, &ti) < 0)   //这里调用texas()函数
            return -1;
        tcflush(fd, TCIOFLUSH);
        /* Set actual baudrate */
        if (set_speed(fd, &ti, u->speed) < 0) {  //实际波特率设置
            perror("Can't set baud rate");
            return -1;
        }
        /* Set TTY to N_HCI line discipline */
        i = N_HCI;
        if (ioctl(fd, TIOCSETD, &i) < 0) {
            perror("Can't set line discipline");
            return -1;
        }
        if (flags && ioctl(fd, HCIUARTSETFLAGS, flags) < 0) {
            perror("Can't set UART flags");
            return -1;
        }
        if (ioctl(fd, HCIUARTSETPROTO, u->proto) < 0) {
            perror("Can't set device");
            return -1;
        }
        if (u->post && u->post(fd, u, &ti) < 0)   //一切正常的话,就运行texas2()
            return -1;
        return fd;
    }
6. texas 相关的一系列函数,这个被定义在 hciattach_ti.c 中:
static int texas(int fd, struct uart_t *u, struct termios *ti)
    {
     return texas_init(fd, ti);
    }
    static int texas2(int fd, struct uart_t *u, struct termios *ti)
    {
     return texas_post(fd, ti);
    }
    static int texasalt(int fd, struct uart_t *u, struct termios *ti)
    {
     return texasalt_init(fd, u->speed, ti);
    }
7. 这个代码中,还有其他公司的一些接口,如爱立信,BCM,st等等
 




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值