Texas Instrument's Bluetooth Driver For Shared Transport 笔记
来源:互联网 发布:会计试题软件 编辑:程序博客网 时间:2024/06/05 21:02
Bluetooth Driver acts as interface between HCI core and TI Shared Transport Layer.
/drivers/bluetooth/Btwilink.c:
#include <linux/platform_device.h>#include <net/bluetooth/bluetooth.h>#include <net/bluetooth/hci_core.h>#include <net/bluetooth/hci.h>#include <linux/ti_wilink_st.h>#include <linux/module.h>#define DEBUG#define VERSION "1.0"#define MAX_BT_CHNL_IDS3#define BT_REGISTER_TIMEOUT 6000
struct ti_st {struct hci_dev *hdev;char reg_status;long (*st_write) (struct sk_buff *);struct completion wait_reg_completion;};struct ti_st - 模块操作结构体
@hdev: HCI 设备指针绑定到了蓝牙模块
@reg_status: ST 注册返回状态
@st_write: send_frame 用到的写函数
@wait_reg_completion - ti_st_open and st_reg_completion_cb之间的结束同步
static inline void ti_st_tx_complete(struct ti_st *hst, int pkt_type){struct hci_dev *hdev = hst->hdev;/* Update HCI stat counters */switch (pkt_type) {case HCI_COMMAND_PKT:hdev->stat.cmd_tx++;break;case HCI_ACLDATA_PKT:hdev->stat.acl_tx++;break;case HCI_SCODATA_PKT:hdev->stat.sco_tx++;break;}}pocket ID (cmd,acl,sco)计数
static void st_reg_completion_cb(void *priv_data, char data){struct ti_st *lhst = priv_data;/* Save registration status for use in ti_st_open() */lhst->reg_status = data;/* complete the wait in ti_st_open() */complete(&lhst->wait_reg_completion);}status.ti_st_open() 函数 会等待st_register() 返回的ST_PENDING信号
static long st_receive(void *priv_data, struct sk_buff *skb){struct ti_st *lhst = priv_data;int err;if (!skb)return -EFAULT;if (!lhst) {kfree_skb(skb);return -EFAULT;}skb->dev = (void *) lhst->hdev;/* Forward skb to HCI core layer */err = hci_recv_frame(skb);if (err < 0) {BT_ERR("Unable to push skb to HCI core(%d)", err);return err;}lhst->hdev->stat.byte_rx += skb->len;return 0;}接收到数据时被Shared Transport层调用
static struct st_proto_s ti_st_proto[MAX_BT_CHNL_IDS] = {{.chnl_id = HCI_EVENT_PKT, /* HCI Events */.hdr_len = sizeof(struct hci_event_hdr),.offset_len_in_hdr = offsetof(struct hci_event_hdr, plen),.len_size = 1, /* sizeof(plen) in struct hci_event_hdr */.reserve = 8,},{.chnl_id = HCI_ACLDATA_PKT, /* ACL */.hdr_len = sizeof(struct hci_acl_hdr),.offset_len_in_hdr = offsetof(struct hci_acl_hdr, dlen),.len_size = 2,/* sizeof(dlen) in struct hci_acl_hdr */.reserve = 8,},{.chnl_id = HCI_SCODATA_PKT, /* SCO */.hdr_len = sizeof(struct hci_sco_hdr),.offset_len_in_hdr = offsetof(struct hci_sco_hdr, dlen),.len_size = 1, /* sizeof(dlen) in struct hci_sco_hdr */.reserve = 8,},};HCI 层的接口
struct st_proto_s的定义:/include/linux/ti_wilink_st.h:
struct st_proto_s {
enum proto_type type;
long (*recv) (void *, struct sk_buff *);
unsigned char (*match_packet) (const unsigned char *data);
void (*reg_complete_cb) (void *, char data);
long (*write) (struct sk_buff *skb);
void *priv_data;
unsigned char chnl_id;
unsigned short max_frame_size; //能接收的最大帧的大小
unsigned char hdr_len; //头结构的长度
unsigned char offset_len_in_hdr; //提供头结构中的长度偏移
unsigned char len_size; //2字节或1字节
unsigned char reserve; //ST 需要交换的字节数 };
static int ti_st_open(struct hci_dev *hdev){unsigned long timeleft;struct ti_st *hst;int err, i;BT_DBG("%s %p", hdev->name, hdev);if (test_and_set_bit(HCI_RUNNING, &hdev->flags))return -EBUSY;/* provide contexts for callbacks from ST */hst = hdev->driver_data;for (i = 0; i < MAX_BT_CHNL_IDS; i++) {ti_st_proto[i].priv_data = hst;ti_st_proto[i].max_frame_size = HCI_MAX_FRAME_SIZE;ti_st_proto[i].recv = st_receive;ti_st_proto[i].reg_complete_cb = st_reg_completion_cb;/* Prepare wait-for-completion handler */init_completion(&hst->wait_reg_completion);/* Reset ST registration callback status flag, * this value will be updated in * st_reg_completion_cb() * function whenever it called from ST driver. */hst->reg_status = -EINPROGRESS;err = st_register(&ti_st_proto[i]);if (!err)goto done;if (err != -EINPROGRESS) {clear_bit(HCI_RUNNING, &hdev->flags);BT_ERR("st_register failed %d", err);return err;}/* ST is busy with either protocol * registration or firmware download. */BT_DBG("waiting for registration ""completion signal from ST");timeleft = wait_for_completion_timeout(&hst->wait_reg_completion, msecs_to_jiffies(BT_REGISTER_TIMEOUT));if (!timeleft) {clear_bit(HCI_RUNNING, &hdev->flags);BT_ERR("Timeout(%d sec),didn't get reg ""completion signal from ST",BT_REGISTER_TIMEOUT / 1000);return -ETIMEDOUT;}/* Is ST registration callback * called with ERROR status? */if (hst->reg_status != 0) {clear_bit(HCI_RUNNING, &hdev->flags);BT_ERR("ST registration completed with invalid ""status %d", hst->reg_status);return -EAGAIN;}done:hst->st_write = ti_st_proto[i].write;if (!hst->st_write) {BT_ERR("undefined ST write function");clear_bit(HCI_RUNNING, &hdev->flags);for (i = 0; i < MAX_BT_CHNL_IDS; i++) {/* Undo registration with ST */err = st_unregister(&ti_st_proto[i]);if (err)BT_ERR("st_unregister() failed with ""error %d", err);hst->st_write = NULL;}return -EIO;}}return 0;}HCI core调用,初始化设备
static int ti_st_close(struct hci_dev *hdev){int err, i;struct ti_st *hst = hdev->driver_data;if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))return 0;for (i = MAX_BT_CHNL_IDS-1; i >= 0; i--) {err = st_unregister(&ti_st_proto[i]);if (err)BT_ERR("st_unregister(%d) failed with error %d",ti_st_proto[i].chnl_id, err);}hst->st_write = NULL;return err;}关闭设备
static int ti_st_send_frame(struct sk_buff *skb){struct hci_dev *hdev;struct ti_st *hst;long len;hdev = (struct hci_dev *)skb->dev;if (!test_bit(HCI_RUNNING, &hdev->flags))return -EBUSY;hst = hdev->driver_data;/* Prepend skb with frame type */memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type,skb->len);/* Insert skb to shared transport layer's transmit queue. * Freeing skb memory is taken care in shared transport layer, * so don't free skb memory here. */len = hst->st_write(skb);if (len < 0) {kfree_skb(skb);BT_ERR("ST write failed (%ld)", len);/* Try Again, would only fail if UART has gone bad */return -EAGAIN;}/* ST accepted our skb. So, Go ahead and do rest */hdev->stat.byte_tx += len;ti_st_tx_complete(hst, bt_cb(skb)->pkt_type);return 0;}static void ti_st_destruct(struct hci_dev *hdev){BT_DBG("%s", hdev->name);/* do nothing here, since platform remove * would free the hdev->driver_data */}发送帧
static int bt_ti_probe(struct platform_device *pdev){static struct ti_st *hst;struct hci_dev *hdev;int err;hst = kzalloc(sizeof(struct ti_st), GFP_KERNEL);if (!hst)return -ENOMEM;/* Expose "hciX" device to user space */hdev = hci_alloc_dev();if (!hdev) {kfree(hst);return -ENOMEM;}BT_DBG("hdev %p", hdev);hst->hdev = hdev;hdev->bus = HCI_UART;hdev->driver_data = hst;hdev->open = ti_st_open;hdev->close = ti_st_close;hdev->flush = NULL;hdev->send = ti_st_send_frame;hdev->destruct = ti_st_destruct;hdev->owner = THIS_MODULE;err = hci_register_dev(hdev);if (err < 0) {BT_ERR("Can't register HCI device error %d", err);kfree(hst);hci_free_dev(hdev);return err;}BT_DBG("HCI device registered (hdev %p)", hdev);dev_set_drvdata(&pdev->dev, hst);return err;}设备探测
static int bt_ti_remove(struct platform_device *pdev){struct hci_dev *hdev;struct ti_st *hst = dev_get_drvdata(&pdev->dev);if (!hst)return -EFAULT;BT_DBG("%s", hst->hdev->name);hdev = hst->hdev;ti_st_close(hdev);hci_unregister_dev(hdev);hci_free_dev(hdev);kfree(hst);dev_set_drvdata(&pdev->dev, NULL);return 0;}设备卸载
static struct platform_driver btwilink_driver = {.probe = bt_ti_probe,.remove = bt_ti_remove,.driver = {.name = "btwilink",.owner = THIS_MODULE,},};platform driver
static int __init btwilink_init(void){BT_INFO("Bluetooth Driver for TI WiLink - Version %s", VERSION);return platform_driver_register(&btwilink_driver);}static void __exit btwilink_exit(void){platform_driver_unregister(&btwilink_driver);}module_init(btwilink_init);module_exit(btwilink_exit);设备 init 与 exit
MODULE_AUTHOR("Raja Mani <raja_mani@ti.com>");MODULE_DESCRIPTION("Bluetooth Driver for TI Shared Transport" VERSION);MODULE_VERSION(VERSION);MODULE_LICENSE("GPL");
2 0
- Texas Instrument's Bluetooth Driver For Shared Transport 笔记
- Bluetooth driver
- Bluetooth Driver Stack
- Texas
- Instrument Driver (iOS下的自动化测试)
- shared memory driver(1)
- shared memory driver(2)
- oslo Transport Driver实现指南
- Bluetooth MESH探究 --- (9) Lower Transport Layer
- ATI 's driver for Linux isn't better.
- [PATCH] input: add driver for Bosch Sensortec's BMA150 accelerometer
- Oracle Data Integrator Driver for XML - User's Manual
- How to install Microsoft's SQL Server Driver for PHP
- Instrument
- Kaggle笔记:Porto Seguro’s Safe Driver Prediction(1)
- Kaggle笔记:Porto Seguro’s Safe Driver Prediction(2)
- Bluetooth For .NET
- javaTM API for Bluetooth
- OUYA——JDK的下载与安装(开发环境配置1)
- Android 项目中文件夹的作用
- 轻量级HTTP服务器Nginx(配置与调试Nginx)
- Android 第三方登录
- 【POJ】3294 Life Forms 【后缀数组——求在超过一半串中出现的最长串】
- Texas Instrument's Bluetooth Driver For Shared Transport 笔记
- HDOJ 题目 1385 Minimum Transport Cost(最短路输出路径)
- JavaScript中的线程和CPU的调度
- Node.js npm编译打包自定义的zepto模块
- SQL
- 移动应用开发系列-2-mysql
- 区县政府网站建设要点总结
- appfuse - hibernate search 2 - 常用注解
- Win8快捷键