bluetooth数据收发

本文深入解析了Linux内核中蓝牙数据的收发流程,从socket创建到 HCI 协议栈的交互,包括hci_sock_create、hci_sock_sendmsg、hci_sock_recvmsg等关键函数,涉及hci_sock_ops、hci_uart_send_frame、tty接收数据的处理等步骤,展示了蓝牙数据如何在内核及协议栈间传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

net/socket.c

SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)->sock_create()->__sock_create()->

pf = rcu_dereference(net_families[family]);

err = pf->create(net, sock, protocol, kern);

bt_init()->

err = sock_register(&bt_sock_family_ops);

static struct net_proto_family bt_sock_family_ops = {

.owner = THIS_MODULE,

.family = PF_BLUETOOTH,

.create = bt_sock_create,

};

bt_sock_create()->

err = bt_proto[proto]->create(net, sock, proto, kern);

bt_proto[proto]注册如下:

bt_init()->hci_sock_init()->bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops)->

bt_proto[proto] = ops;

static const struct net_proto_family hci_sock_family_ops = {

.family = PF_BLUETOOTH,

.owner = THIS_MODULE,

.create = hci_sock_create,

};

hci_sock_create()->sock->ops = &hci_sock_ops

net/bluetooth/hci_sock.c

static const struct proto_ops hci_sock_ops = {

.family = PF_BLUETOOTH,

.owner = THIS_MODULE,

.release = hci_sock_release,

.bind = hci_sock_bind,

.getname = hci_sock_getname,

.sendmsg = hci_sock_sendmsg,

.recvmsg = hci_sock_recvmsg,

.ioctl = hci_sock_ioctl,

.poll = datagram_poll,

.listen = sock_no_listen,

.shutdown = sock_no_shutdown,

.setsockopt = hci_sock_setsockopt,

.getsockopt = hci_sock_getsockopt,

.connect = sock_no_connect,

.socketpair = sock_no_socketpair,

.accept = sock_no_accept,

.mmap = sock_no_mmap

};

发送

hci_sock_sendmsg()->

hdev = hci_pi(sk)->hdev;//bind函数确定的

skb_queue_tail(&hdev->raw_q, skb);

queue_work(hdev->workqueue, &hdev->tx_work);

hci_sock_bind()->

hdev = hci_dev_get(haddr.hci_dev);

hci_pi(sk)->hdev = hdev;

ioctl()--->hci_alloc_dev()->

INIT_WORK(&hdev->rx_work, hci_rx_work);

INIT_WORK(&hdev->cmd_work, hci_cmd_work);

INIT_WORK(&hdev->tx_work, hci_tx_work);

INIT_WORK(&hdev->power_on, hci_power_on);

hci_tx_work()->hci_send_frame()->

hci_send_to_sock(hdev, skb);

return hdev->send(skb);

ioctl()--->hci_uart_register_dev()->

hdev->open  = hci_uart_open;

hdev->close = hci_uart_close;

hdev->flush = hci_uart_flush;

hdev->send  = hci_uart_send_frame;

hdev->send即为hci_uart_send_frame

hci_uart_send_frame()->

hci_set_drvdata(hdev, hu);

hu = hci_get_drvdata(hdev);

hu->proto->enqueue(hu, skb);

hci_uart_tx_wakeup(hu);

注意以后可以从tty->disc_data得到hu

hci_uart_tty_open()->

tty->disc_data = hu;

hu->tty = tty;

hci_uart_tx_wakeup()->

len = tty->ops->write(tty, skb->data, skb->len);

hci_uart_tx_complete(hu, bt_cb(skb)->pkt_type);

uart_write()->uart_start(tty)->__uart_start()->(port->ops->start_tx(port))

平台相关,uart_add_one_port()时注册的。

接收

tty接收到数据,使用tty_insert_flip_char()写入到ttybuffer中,

uart_register_driver()->tty_port_init(port)->tty_buffer_init(port)//buf初始化

tty_buffer_request_room()->//find buffers

/* This is the slow path - looking for new buffers to use */

if ((n = tty_buffer_find(port, size)) != NULL) {

if (b != NULL) {

b->next = n;

b->commit = b->used;

} else

buf->head = n;

buf->tail = n;

}

tty_flip_buffer_push(tport) PUSHhci uart

tty_flip_buffer_push()->tty_flip_buffer_push()->tty_ldisc_ref()->

disc = tty_ldisc_ref(tty);

disc->ops->receive_buf(tty, char_buf,

flag_buf, count);

hci_uart_init()->

memset(&hci_uart_ldisc, 0, sizeof (hci_uart_ldisc));

hci_uart_ldisc.magic = TTY_LDISC_MAGIC;

hci_uart_ldisc.name = "n_hci";

hci_uart_ldisc.open = hci_uart_tty_open;

hci_uart_ldisc.close = hci_uart_tty_close;

hci_uart_ldisc.read = hci_uart_tty_read;

hci_uart_ldisc.write = hci_uart_tty_write;

hci_uart_ldisc.ioctl = hci_uart_tty_ioctl;

hci_uart_ldisc.poll = hci_uart_tty_poll;

hci_uart_ldisc.receive_buf = hci_uart_tty_receive;

hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup;

hci_uart_ldisc.owner = THIS_MODULE;

 

if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) {

BT_ERR("HCI line discipline registration failed. (%d)", err);

return err;

}

#ifdef CONFIG_BT_HCIUART_H4

h4_init();

#endif

#ifdef CONFIG_BT_HCIUART_BCSP

bcsp_init();

#endif

#ifdef CONFIG_BT_HCIUART_LL

ll_init();

#endif

#ifdef CONFIG_BT_HCIUART_ATH3K

ath_init();

#endif

#ifdef CONFIG_BT_HCIUART_3WIRE

h5_init();

#endif

hci_uart_tty_receive()->

hu->proto->recv(hu, (void *) data, count);

h4_init()->hci_uart_register_proto(&h4p)

static struct hci_uart_proto h4p = {

.id = HCI_UART_H4,

.open = h4_open,

.close = h4_close,

.recv = h4_recv,

.enqueue = h4_enqueue,

.dequeue = h4_dequeue,

.flush = h4_flush,

};

协议不同,recv()不同。

h4_recv()->hci_recv_stream_fragment()->hci_reassembly()->hci_recv_frame(skb)->

skb_queue_tail(&hdev->rx_q, skb);

queue_work(hdev->workqueue, &hdev->rx_work);

hci_rx_work()->hci_send_to_sock()->sock_queue_rcv_skb()->__skb_queue_tail(list, skb);

hci_send_to_sock通过已经连接并且正在监听的sockt将数据拷贝发送给HAL,并且根据skb的类型作对应处理

hci_sock_recvmsg()->

err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);

参考博客
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值