Texas Instrument & #39; s Bluetooth Driver For Shared Transport notes, texasinstrument

Source: Internet
Author: User

Texas Instrument's Bluetooth Driver For Shared Transport notes, texasinstrument

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-module operation structure
@ Hdev: The HCI device pointer is bound to the bluetooth module.
@ Reg_status: the Status returned by ST Registration
@ St_write: Write function used by send_frame
@ Wait_reg_completion-end synchronization between 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) count
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);}
The status. ti_st_open () function will wait for the ST_PENDING signal returned by st_register ().

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;}
Called by the Shared Transport layer when receiving data
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 Layer Interface

Struct st_proto_s definition:/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; // maximum size of frames that can be received
Unsigned char hdr_len; // length of the header Structure
Unsigned char offset_len_in_hdr; // provide the length offset in the header structure.
Unsigned char len_size; // 2 bytes or 1 byte
Unsigned char reserve; // number of bytes to be exchanged by the 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;}
Call HCI core to initialize the device

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;}
Disable the device

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 */}
Send Frame

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;}
Device Detection

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;}
Detach a device

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);
Device init and exit
MODULE_AUTHOR("Raja Mani <raja_mani@ti.com>");MODULE_DESCRIPTION("Bluetooth Driver for TI Shared Transport" VERSION);MODULE_VERSION(VERSION);MODULE_LICENSE("GPL");

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.