主要分析一下蓝牙USB Adapter使用USB接口传输HCI包的实现及过程。

参照上面的Bluetooth core system architecture图, 蓝牙USB Adapter作为Bluetooth controller以USB的物理形式连接到Linux host processor上,通过HCI protocol和Host通信。

bluetooth in Linux kernel

Linux kernel side主要包括:

  • Bluetooth Core: (net\bluetooth\*)

    • HCI (Host Controller Interface) device and connection manager, schedule
    • SCO (Synchronous Connection Oriented) audio links
    • L2CAP (Logical Link Control and Adaptation Protocol)
    • SMP (Security Manager Protocol) on LE (Low Energy) links
  • HCI Device drivers (Interface to the hardware)
    • USB (btusb)
    • UART (hciuart)
    • SDIO
  • RFCOMM (RFCOMM Protocol for serial communication) Module (creates /dev/rfcomm serial devices)
  • BNEP (Bluetooth Network Encapsulation Protocol) Module (creates /sys/class/net/bnep network interfaces)
  • CMTP (CAPI Message Transport Protocol) Module
  • HIDP (Human Interface Device Protocol) Module (creates /sys/class/input devices)

HCI device driver

HCI:Host Controller Interface

HCI提供了访问Controller的统一接口

Controller主要包含下面几种类型

  • BR/EDR Controller
  • BD/EDR/LE Controller
  • LE Controller
  • AMP Controller (Alternate MAC/PHY)

include/net/bluetooth/hci.h 中定义的HCI bus 接口类型包括:

/* HCI bus types */
#define HCI_VIRTUAL 0
#define HCI_USB 1
#define HCI_PCCARD 2
#define HCI_UART 3
#define HCI_RS232 4
#define HCI_PCI 5
#define HCI_SDIO 6
#define HCI_SPI 7
#define HCI_I2C 8
#define HCI_SMD 9

btusb

bluetooth USB adapter是作为usb device挂载到USB总线上的。因此是通过usb_driver提供的机制去probe,而不是直接通过platform_driver.

这点和i2c, SPI 等设备驱动都是类似的。

static struct usb_driver btusb_driver = {
.name = "btusb",
.probe = btusb_probe,
.disconnect = btusb_disconnect,
#ifdef CONFIG_PM
.suspend = btusb_suspend,
.resume = btusb_resume,
#endif
.id_table = btusb_table,
.supports_autosuspend = 1,
.disable_hub_initiated_lpm = 1,
};

probe

在probe函数中, hci device的operators函数指针被赋值

static int btusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
//...
hdev->open = btusb_open;
hdev->close = btusb_close;
hdev->flush = btusb_flush;
hdev->send = btusb_send_frame;
hdev->notify = btusb_notify;
//...
}

其中HCI Device数据结构定义, include/net/bluetooth/hci_core.h

struct hci_dev {
struct list_head list;
struct mutex lock;
char name[8];
unsigned long flags;
__u16 id;
__u8 bus;
__u8 dev_type; //... int (*open)(struct hci_dev *hdev);
int (*close)(struct hci_dev *hdev);
int (*flush)(struct hci_dev *hdev);
int (*setup)(struct hci_dev *hdev);
int (*shutdown)(struct hci_dev *hdev);
int (*send)(struct hci_dev *hdev, struct sk_buff *skb);
void (*notify)(struct hci_dev *hdev, unsigned int evt); //...
}

接收发送数据

Bluetooth USB设备定义了不同的pipe用于不同类型的数据传输

- Control pipes are used to transport HCI commands.

- Interrupt pipes are responsible for carrying HCI events.

- Bulk pipes transfer asynchronous connectionless (ACL) Bluetooth data.

- Isochronous pipes carry SCO audio data.

static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{
struct urb *urb;
BT_DBG("%s", hdev->name);
switch (hci_skb_pkt_type(skb)) {
case HCI_COMMAND_PKT:
urb = alloc_ctrl_urb(hdev, skb);
if (IS_ERR(urb))
return PTR_ERR(urb);
hdev->stat.cmd_tx++;
return submit_or_queue_tx_urb(hdev, urb);
case HCI_ACLDATA_PKT:
urb = alloc_bulk_urb(hdev, skb);
if (IS_ERR(urb))
return PTR_ERR(urb);
hdev->stat.acl_tx++;
return submit_or_queue_tx_urb(hdev, urb);
case HCI_SCODATA_PKT:
if (hci_conn_num(hdev, SCO_LINK) < 1)
return -ENODEV;
urb = alloc_isoc_urb(hdev, skb);
if (IS_ERR(urb))
return PTR_ERR(urb);
hdev->stat.sco_tx++;
return submit_tx_urb(hdev, urb);
}
return -EILSEQ;
}

接收中断处理:

注册

btusb_open -->
btusb_submit_intr_urb-->
//initialize a interrupt urb
usb_fill_int_urb(urb, data->udev, pipe, buf, size,
btusb_intr_complete, hdev, data->intr_ep->bInterval);

usb_complete_t 回调函数btusb_intr_complete被注册

    if (btusb_recv_intr(data, urb->transfer_buffer,
urb->actual_length) < 0) {
bt_dev_err(hdev, "corrupted event packet");
hdev->stat.err_rx++;
}

btusb_recv_intr函数中,数据被copy到skb. 内核中所有network相关的queue, buffer都用这个通用的结构体。

Reference

https://iotbreaks.com/base-knowledge-about-bluetooth/

http://www.embeddedlinux.org.cn/essentiallinuxdevicedrivers/final/ch16lev1sec1.html#ch16lev1sec1

https://wiki.linuxfoundation.org/networking/sk_buff

蓝牙学习(2)USB Adapter的更多相关文章

  1. Android 蓝牙学习

    Android 蓝牙学习 学习缘由 上个礼拜公司要开发个简单的五子棋游戏!其中一个需求就是支持蓝牙对战!所以苦逼的我学习蓝牙方面的知识了! 简介 Bluetooth是目前使用最广泛的无线通讯协议,近距 ...

  2. 蓝牙学习(3) Linux kernel部分Bluetooth HCI分析

    在上文,https://blog.csdn.net/feiwatson/article/details/81712933中主要理解了在Kernel中USB adapter是如何实现USB设备驱动,以及 ...

  3. Android蓝牙学习笔记

    一 Bluetooth基本概念 蓝牙是无线数据和语音传输的开放式标准,它将各种通信设备.计算机及其终端设备.各种数字数据系统.甚至家用电器采用无线方式联接起来.它的传输距离为10cm-10m,如果增加 ...

  4. nRF51800 蓝牙学习 进程记录 1:感想

    一直想开一个高大上点的博客,觉得博客园不错,便申请了.一直没时间看,都快忘了,无意间登上提示申请到了.便写个东西看看. 正在学习nRF51822的蓝牙开发板,为了做毕设准备.备考中,一直没时间学,但今 ...

  5. android蓝牙学习

    学习路线 1 蓝牙权限 <uses-permission android:name="android.permission.BLUETOOTH" /> <uses ...

  6. 树莓派学习笔记——USB wifi配置指南

    0 前言     树莓派既能够使用有线网络又能够无线网络,假设使用有线网络不方便的话能够借助USB wifi无线网卡让树莓派也插上无线"翅膀". 可是和使用有线网络即插即用的方式不 ...

  7. 蓝牙学习笔记三(Android Debug)

    android 端可以通过两种方式去Debug: 一.在手机的设置功能里,开发者模式 Enable,如下图:   http://blog.bluetooth.com/debugging-bluetoo ...

  8. USB2.0协议学习笔记---USB工作过程(类的方法)

    前面学习了那么多的概念,这里需要记住一点分层概念即设备 ---> 配置 ---> 接口 ---> 端点,这种分层的概念结构 . 也可以理解为端点构成接口,接口组成配置,配置组成设备. ...

  9. Android学习之在Adapter中调用Fragment

    •前言 在学习<第一行代码>,4.5 小节--一个简易版的新闻应用的时候: 在为 RecyclerView 创建适配器的时候: 作者直接在 NewsTitleFragment.java 中 ...

随机推荐

  1. 构建使用SQL服务器的ASP.net Core2.0 API

    web api的教程非常少,使用 core2.0的更少,微软提供了一个aspnet core2的教程,也提供了EF core中访问SQL服务器的教程,参考这些教程可以做出使用sql server的as ...

  2. HDU1087(树状数组求LIS)

    题是水题,学习一下用树状数组求LIS. 先离散化一下,注意去重:然后就把a[i]作为下标,dp[i]作为值,max作为维护的运算插进树状数组即可. 如果是上升子序列,询问(a[i] - 1):如果是不 ...

  3. 在 Linux 环境直接复移动硬盘上的 GRUB

    手头有一块用了 10 年的旧移动硬盘,其中安装了 Debian 系统,从低版本一直升级到现在的 9 已经用了很长时间.前不久正连着那块硬盘跑着 Debian 修改文件的时候,由于一个本可避免的意外震动 ...

  4. 利用HttpClient4访问网页

    一.HttpClient介绍 虽然在 JDK 的 java.net 包中已经提供了访问 HTTP 协议的基本功能,但是它没有提供足够的灵活性和其他应用程序需要的功能.HttpClient 是 Apac ...

  5. 牛客网Java刷题知识点之什么是死锁、死锁产生的4个必要条件、死锁的解除与预防

    不多说,直接上干货! https://www.nowcoder.com/ta/review-java/review?query=&asc=true&order=&page=16 ...

  6. IE如何实现text-shadow文字阴影效果呢?

    让我们头痛的是IE是不支持text-shadow效果,但为了在兼容这一问题,我们只好使用滤镜filter:shadow来处理(本人不提倡使用滤镜).filter:shadow滤镜作用与dropshad ...

  7. React-redux及异步获取数据20分钟快速入门

    一, 写在前面 1. 前面我写过一个vuex10分钟入门 传送门 2. React-redux网上有好多文档,又臭又长,明明很简单的问题,硬是让新人更晕了~, 我写这个文章的目的是让新人在20分钟之内 ...

  8. Java编程基础-面向对象(中)

    本章承接Java编程基础-面向对象(上)一文. 一.static关键字 在java中,定义了一个static关键字,它用于修饰类的成员,如成员变量.成员方法以及代码块等,被static修饰的成员具备一 ...

  9. vue-cli脚手架(框架)

    一.创建vue项目 npm install vue-cli -g #-g全局 (sudo)npm install vue-cli -g #mac笔记本 vue-init webpack myvue # ...

  10. 洛谷 P1201 [USACO1.1]贪婪的送礼者Greedy Gift Givers

    贪婪的送礼者Greedy Gift Givers 难度:☆ Code: #include <iostream> #include <cstdio> #include <c ...