Android Bletooth Poweron & Enable

Bluetooth服务(以及蓝牙的A2DP服务)都是通过SystemServer启动(frameworks/base/services/java/com/android/server/SystemServer.java)

  1. Frameworks层(frameworks/base/core/java/android/server/BluetoothService.java, function: enable())
  2.              |
  3.              | 给蓝牙状态机一个USER_TURN_ON的命令
  4.              |
  5. jni层(frameworks/base/core/jni/android_server_BluetoothService.cpp, function: enableNative())
  6.              |
  7. HAL层(system/bluetooth/bluedroid/bluetooth.c, function: set_bluetooth_power())
  8.              |
  9.              | write to rfkill
  10.              |
  11. kernel层(net/rfkill/rfkill-gpio.c,或者vendor定制的rfkill driver, function: rfkill_gpio_set_power())
rfkill_id在init.rc和bluetooth.c中已经把bluetooth写定为0,即:/sys/class/rfkill/rfkill0/state。匹配的机制是:
  1.   /sys/class/rfkill/rfkill%d/type
  2.   读取内容,与bluetooth比较,如果相同,则返回id,并且给
  3.   /sys/class/rfkill/rfkill%d/state写值(1或者0)以便开关电
这部分具体实现可以参看rfkill的driver代码

 

  1. HAL层(system/bluetooth/bluedroid/bluetooth.c, function: bt_enable(), property_set("ctl.start", "hciattach"))
  2.                 |
  3.                 | 给电之后,启动注册在init.rc里面的hciattach daemon
  4.                 |           
  5. bluez(external/bluetooth/bluez/tools/hciattach.c)
  6.                 |
  7.                 | 打开制定的tty设备,然后做一些通用的设置,并且通过ioctl发送两个命令
  8.                 | TIOCSETD和HCIUARTSETPROTO
  9.                 | 去将设备注册到hci设备中(h4和bcsp,走的是ldisc机制)
  10.                 |
  11. kernel hci层(net/bluetooth/hci_socket.c,hci_core.c)
  12.                 |
  13.                 | 收到HCIDEVUP指令通过hci_dev_open打开设备,调用hdev->open(hci_uart_open,
  14.                 | hci_uart_register_dev时候指定的方法),并且通过__hci_request调用hci_init_req
  15.                 | 去调用一系列的hci_send_cmd发送各种命令,主要是读各种配置以及设置一些基本参数
  16.                 | __hci_request设置了睡眠,它是一个阻塞函数
  17.                 |
  18. kernel hci层(net/bluetooth/hci_core.c),hci_send_cmd
  19.                 |
  20.                 | 调用tasklet_schedule(&hdev->cmd_task)唤起cmd_task,cmd_task在执行
  21.                 | HCIUARTSETPROTO命令时已经设置好了的
  22.                 |
  23. kernel hci层(net/bluetooth/hci_core.c),hci_cmd_task
  24.                 |
  25.                 | 调用hci_send_frame将命令发送给硬件。hci_send_frame见后面的数据发送流程
  26.                 | 数据收到后会通过中断调起数据接收流程,具体流程也见后面。然后进行一系列的处理
  27.                 | (hci_rx_task->hci_event_packet)最后调起hci_req_complete,用wake_up_interruptible                 | 唤醒前面__hci_request设置的睡眠

一共有3个ioctl命令,TIOCSETD和HCIUARTSETPROTO在hciattach.c里面,通过open命令调用 drivers/tty/tty_io.c以及对应的ioctl,具体见下面描述。 HCIDEVUP在bluetooth.c里面,通过socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)发出,BTPROTO_HCI对应的hci_socket.c的ioctl处理。af_bluetooth.c在初始化的时候就注册了三种proto的socket:hci,l2cap和sco.


TIOCSETD处理流程

  1. tty core(drivers/tty/tty_io.c,function: tty_ioctl调用tiocsetd,传入的参数是hci对应的 discipline id,N_HCI)
  2.                         |
  3. tty ldisc(drivers/tty/tty_ldisc.c,tty_set_ldisc: 1)根据id找ops,ops是在子ldisc初始化时注册到 tty_ldisc.c里面的一个tty_ldisc_ops数组 2) alloc一个ldisc,将前面找到的op设给这个ldisc 3) 通过tty_ldisc_assign将这个ldisc设给tty结构体. 从此,以后对应的函数都是调用子ldisc里面的tty_ldisc_ops函数来处理)
  4.                         |
  5. hci uart(drivers/bluetooth/hci_ldisc.c)


HCIUARTSETPROTO处理流程

  1. tty core(drivers/tty/tty_io.c,function: tty_ioctl调用ld = tty_ldisc_ref_wait(tty); ld->ops->ioctl())
  2.                          |
  3.                          |
  4. hci uart(drivers/bluetooth/hci_ldisc.c,通过init函数注册到tty_ldisc中的, 对应的id是N_HCI.函数hci_uart_tty_ioctl调用hci_uart_set_proto)
  5.                          |
  6.                          | 调用在h4_init或者bcsp_init里面注册的设备的open命令,具体调用哪个open
  7.                          | 取决于hciattach.c里面uart数组对应的定义。
  8.                          | open完了之后通过hci_uart_register_dev alloc一个hci_dev
  9.                          |
  10. hci core(net/bluetooth/hci_core.c,function:hci_register_dev,这里面做的事情比较多,初始化了 3个tasklet(发送,接收以及命令),注册hci设备对应的sysfs,以及注册了该hci设备对应的rfkill,到这一步, 底层的蓝牙虚拟设备hci0就可以通过hciconfig命令看到了


由上面可以看到,一个子uart模块在初始化的时候,应该干这么几件事:

  • 1)通过tty_register_ldisc(id, &tty_ldisc_op)将ops写到tty_ldisc的数组里面,并且子ldisc要实现这么一个hci_uart_proto的数组
  • 2)通过xxx_uart_register_proto(&hci_uart_proto)写到子ldisc的hci_uart_proto数组里面

一旦hci_register_dev完成,也就是hci层加进来以后,HAL层所有的操作都将通过hci-->proto-->ldisc-->tty这么一个流程。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值