blob: 1cec234c1a9b88919cb2ce0945443100b57f8cfd [file] [log] [blame]
Scott James Remnant96927a42013-07-17 18:27:57 -07001# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6import socket
7
8import _btsocket
Scott James Remnantfc5a3f72013-08-01 14:39:40 -07009import constants
Scott James Remnant96927a42013-07-17 18:27:57 -070010
11class BluetoothSocket(socket._socketobject):
12 """Socket wrapper class for Bluetooth sockets.
13
14 Wraps the Python socket class to implement the necessary pieces to be able
15 to bind to the HCI monitor and control sockets as well as receive messages
16 with ancillary data from them.
17
Scott James Remnantffa6f742013-11-19 12:10:07 -080018 The bind() and connect() functions match the behavior of those of the
19 built-in socket methods and accept a tuple defining the address, the
20 contents of which depend on the protocol of the socket.
21
22 For BTPROTO_HCI this is:
23 @param dev: Device index, or HCI_DEV_NONE.
24 @param channel: Channel, e.g. HCI_CHANNEL_RAW.
25
26 For BTPROTO_L2CAP this is:
27 @param address: Address of device in string format.
28 @param psm: PSM of L2CAP service.
29
30 For BTPROTO_RFCOMM this is:
31 @param address: Address of device in string format.
32 @param cid: Channel ID of RFCOMM service.
33
34 For BTPROTO_SCO this is:
35 @param address: Address of device in string format.
36
Scott James Remnant96927a42013-07-17 18:27:57 -070037 """
38
Scott James Remnantfc5a3f72013-08-01 14:39:40 -070039 def __init__(self,
40 family=constants.AF_BLUETOOTH,
41 type=socket.SOCK_RAW,
42 proto=constants.BTPROTO_HCI):
43 super(BluetoothSocket, self).__init__(family, type, proto)
Scott James Remnant96927a42013-07-17 18:27:57 -070044
45 def bind(self, *args):
Scott James Remnantffa6f742013-11-19 12:10:07 -080046 """Bind the socket to a local address."""
Scott James Remnantfc5a3f72013-08-01 14:39:40 -070047 if self.family == constants.AF_BLUETOOTH:
48 return _btsocket.bind(self, self.proto, *args)
Scott James Remnant96927a42013-07-17 18:27:57 -070049 else:
50 return super(BluetoothSocket, self).bind(*args)
51
Scott James Remnantffa6f742013-11-19 12:10:07 -080052 def connect(self, *args):
53 """Connect the socket to a remote address."""
54 if self.family == constants.AF_BLUETOOTH:
55 return _btsocket.connect(self, self.proto, *args)
56 else:
57 return super(BluetoothSocket, self).connect(*args)
58
Scott James Remnant96927a42013-07-17 18:27:57 -070059 def recvmsg(self, bufsize, ancbufsize=0, flags=0):
60 """Receive normal data and ancillary data from the socket.
61
62 @param bufsize size in bytes of buffer for normal data.
63 @param ancbufsize size in bytes of internal buffer for ancillary data.
64 @param flags same meaning as socket.recv()
65
66 @return tuple of (data, ancdata, msg_flags, address),
67 @ancdata is zero or more tuples of (cmsg_level, cmsg_type, cmsg_data).
68
69 """
70 buffer = bytearray(bufsize)
71 (nbytes, ancdata, msg_flags, address) = \
72 self.recvmsg_into((buffer,), ancbufsize, flags)
73 return (bytes(buffer), ancdata, msg_flags, address)
74
75 def recvmsg_into(self, buffers, ancbufsize=0, flags=0):
76 """Receive normal data and ancillary data from the socket.
77
78 @param buffers iterable of bytearray objects filled with read chunks.
79 @param ancbufsize size in bytes of internal buffer for ancillary data.
80 @param flags same meaning as socket.recv()
81
82 @return tuple of (nbytes, ancdata, msg_flags, address),
83 @ancdata is zero or more tuples of (cmsg_level, cmsg_type, cmsg_data).
84
85 """
86 return _btsocket.recvmsg(self, buffers, ancbufsize, flags)
87
Artem Rakhov1b654492015-01-21 00:40:44 -080088
89def create_le_gatt_server_socket():
90 """Create a socket for incoming BLE connection.
91
92 The function creates an LE socket, then does bind, listen and accept.
93 The accept call blocks until it receives an incoming connection.
94
95 Note, that resulting socket will be standard Python socket,
96 not BluetoothSocket. It is already connected, ready for recv() and
97 send() calls, and there is no need for further setup.
98
99 Before calling this function, the machine must be set up (with appropriate
100 HCI commands) to be advertising, be powered, and have LE turned on.
101
102 @return tuple of (sock, source_address),
103 @sock is standard Python socket object, which is able to receive and send.
104 @source_address is string containing BDADDR of the connected remote.
105
106 """
107 file_descriptor, source_address = _btsocket.listen_and_accept()
108 sock = socket.fromfd(file_descriptor, constants.AF_BLUETOOTH,
109 socket.SOCK_SEQPACKET, constants.BTPROTO_L2CAP)
110 return sock, source_address