File: _lightbluecommon.py

package info (click to toggle)
pybluez 0.23-5.1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 2,152 kB
  • sloc: ansic: 4,854; python: 4,319; objc: 3,363; cpp: 1,950; makefile: 190
file content (331 lines) | stat: -rwxr-xr-x 10,539 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
# Copyright (c) 2009 Bea Lam. All rights reserved.
#
# This file is part of LightBlue.
#
# LightBlue is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# LightBlue is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with LightBlue.  If not, see <http://www.gnu.org/licenses/>.

# Defines attributes with common implementations across the different
# platforms.


# public attributes
__all__ = ("L2CAP", "RFCOMM", "OBEX", "BluetoothError", "splitclass")


# Protocol/service class types, used for sockets and advertising services
L2CAP, RFCOMM, OBEX = (10, 11, 12)


class BluetoothError(IOError):
    """
    Generic exception raised for Bluetooth errors. This is not raised for
    socket-related errors; socket objects raise the socket.error and
    socket.timeout exceptions from the standard library socket module.

    Note that error codes are currently platform-independent. In particular,
    the Mac OS X implementation returns IOReturn error values from the IOKit
    framework, and OBEXError codes from <IOBluetooth/OBEX.h> for OBEX operations.
    """
    pass


def splitclass(classofdevice):
    """
    Splits the given class of device to return a 3-item tuple with the
    major service class, major device class and minor device class values.

    These values indicate the device's major services and the type of the
    device (e.g. mobile phone, laptop, etc.). If you google for
    "assigned numbers bluetooth baseband" you might find some documents
    that discuss how to extract this information from the class of device.

    Example:
        >>> splitclass(1057036)
        (129, 1, 3)
        >>>
    """
    if not isinstance(classofdevice, int):
        try:
            classofdevice = int(classofdevice)
        except (TypeError, ValueError):
            raise TypeError("Given device class '%s' cannot be split" % \
                str(classofdevice))

    data = classofdevice >> 2   # skip over the 2 "format" bits
    service = data >> 11
    major = (data >> 6) & 0x1F
    minor = data & 0x3F
    return (service, major, minor)


_validbtaddr = None
def _isbtaddr(address):
    """
    Returns whether the given address is a valid bluetooth address.
    For example, "00:0e:6d:7b:a2:0a" is a valid address.

    Returns False if the argument is None or is not a string.
    """
    # Define validity regex. Accept either ":" or "-" as separators.
    global _validbtaddr
    if _validbtaddr is None:
        import re
        _validbtaddr = re.compile("((\d|[a-f]){2}(:|-)){5}(\d|[a-f]){2}",
                re.IGNORECASE)
    import types
    if not isinstance(address, str):
        return False
    return _validbtaddr.match(address) is not None


# --------- other attributes ---------

def _joinclass(codtuple):
    """
    The opposite of splitclass(). Joins a (service, major, minor) class-of-
    device tuple into a whole class of device value.
    """
    if not isinstance(codtuple, tuple):
        raise TypeError("argument must be tuple, was %s" % type(codtuple))
    if len(codtuple) != 3:
        raise ValueError("tuple must have 3 items, has %d" % len(codtuple))

    serviceclass = codtuple[0] << 2 << 11
    majorclass = codtuple[1] << 2 << 6
    minorclass = codtuple[2] << 2
    return (serviceclass | majorclass | minorclass)


# Docstrings for socket objects.
# Based on std lib socket docs.
_socketdocs = {
"accept":
    """
    accept() -> (socket object, address info)

    Wait for an incoming connection. Return a new socket representing the
    connection, and the address of the client. For RFCOMM sockets, the address
    info is a pair (hostaddr, channel).

    The socket must be bound and listening before calling this method.
    """,
"bind":
    """
    bind(address)

    Bind the socket to a local address. For RFCOMM sockets, the address is a
    pair (host, channel); the host must refer to the local host.

    A port value of 0 binds the socket to a dynamically assigned port.
    (Note that on Mac OS X, the port value must always be 0.)

    The socket must not already be bound.
    """,
"close":
    """
    close()

    Close the socket.  It cannot be used after this call.
    """,
"connect":
    """
    connect(address)

    Connect the socket to a remote address. The address should be a
    (host, channel) pair for RFCOMM sockets, and a (host, PSM) pair for L2CAP
    sockets.

    The socket must not be already connected.
    """,
"connect_ex":
    """
    connect_ex(address) -> errno

    This is like connect(address), but returns an error code instead of raising
    an exception when an error occurs.
    """,
"dup":
    """
    dup() -> socket object

    Returns a new socket object connected to the same system resource.
    """,
"fileno":
    """
    fileno() -> integer

    Return the integer file descriptor of the socket.

    Raises NotImplementedError on Mac OS X and Python For Series 60.
    """,
"getpeername":
    """
    getpeername() -> address info

    Return the address of the remote endpoint. The address info is a
    (host, channel) pair for RFCOMM sockets, and a (host, PSM) pair for L2CAP
    sockets.

    If the socket has not been connected, socket.error will be raised.
    """,
"getsockname":
    """
    getsockname() -> address info

    Return the address of the local endpoint. The address info is a
    (host, channel) pair for RFCOMM sockets, and a (host, PSM) pair for L2CAP
    sockets.

    If the socket has not been connected nor bound, this returns the tuple
    ("00:00:00:00:00:00", 0).
    """,
"getsockopt":
    """
    getsockopt(level, option[, bufsize]) -> value

    Get a socket option.  See the Unix manual for level and option.
    If a nonzero buffersize argument is given, the return value is a
    string of that length; otherwise it is an integer.

    Currently support for socket options are platform independent -- i.e.
    depends on the underlying Series 60 or BlueZ socket options support.
    The Mac OS X implementation currently does not support any options at
    all and automatically raises socket.error.
    """,
"gettimeout":
    """
    gettimeout() -> timeout

    Returns the timeout in floating seconds associated with socket
    operations. A timeout of None indicates that timeouts on socket
    operations are disabled.

    Currently not supported on Python For Series 60 implementation, which
    will always return None.
    """,
"listen":
    """
    listen(backlog)

    Enable a server to accept connections. The backlog argument must be at
    least 1; it specifies the number of unaccepted connection that the system
    will allow before refusing new connections.

    The socket must not be already listening.

    Currently not implemented on Mac OS X.
    """,
"makefile":
    """
    makefile([mode[, bufsize]]) -> file object

    Returns a regular file object corresponding to the socket.  The mode
    and bufsize arguments are as for the built-in open() function.
    """,
"recv":
    """
    recv(bufsize[, flags]) -> data

    Receive up to bufsize bytes from the socket.  For the optional flags
    argument, see the Unix manual.  When no data is available, block until
    at least one byte is available or until the remote end is closed.  When
    the remote end is closed and all data is read, return the empty string.

    Currently the flags argument has no effect on Mac OS X.
    """,
"recvfrom":
    """
    recvfrom(bufsize[, flags]) -> (data, address info)

    Like recv(buffersize, flags) but also return the sender's address info.
    """,
"send":
    """
    send(data[, flags]) -> count

    Send a data string to the socket.  For the optional flags
    argument, see the Unix manual.  Return the number of bytes
    sent.

    The socket must be connected to a remote socket.

    Currently the flags argument has no effect on Mac OS X.
    """,
"sendall":
    """
    sendall(data[, flags])

    Send a data string to the socket.  For the optional flags
    argument, see the Unix manual.  This calls send() repeatedly
    until all data is sent.  If an error occurs, it's impossible
    to tell how much data has been sent.
    """,
"sendto":
    """
    sendto(data[, flags], address) -> count

    Like send(data, flags) but allows specifying the destination address.
    For RFCOMM sockets, the address is a pair (hostaddr, channel).
    """,
"setblocking":
    """
    setblocking(flag)

    Set the socket to blocking (flag is true) or non-blocking (false).
    setblocking(True) is equivalent to settimeout(None);
    setblocking(False) is equivalent to settimeout(0.0).

    Initially a socket is in blocking mode. In non-blocking mode, if a
    socket operation cannot be performed immediately, socket.error is raised.

    The underlying implementation on Python for Series 60 only supports
    non-blocking mode for send() and recv(), and ignores it for connect() and
    accept().
    """,
"setsockopt":
    """
    setsockopt(level, option, value)

    Set a socket option.  See the Unix manual for level and option.
    The value argument can either be an integer or a string.

    Currently support for socket options are platform independent -- i.e.
    depends on the underlying Series 60 or BlueZ socket options support.
    The Mac OS X implementation currently does not support any options at
    all and automatically raise socket.error.
    """,
"settimeout":
    """
    settimeout(timeout)

    Set a timeout on socket operations.  'timeout' can be a float,
    giving in seconds, or None.  Setting a timeout of None disables
    the timeout feature and is equivalent to setblocking(1).
    Setting a timeout of zero is the same as setblocking(0).

    If a timeout is set, the connect, accept, send and receive operations will
    raise socket.timeout if a timeout occurs.

    Raises NotImplementedError on Python For Series 60.
    """,
"shutdown":
    """
    shutdown(how)

    Shut down the reading side of the socket (flag == socket.SHUT_RD), the
    writing side of the socket (flag == socket.SHUT_WR), or both ends
    (flag == socket.SHUT_RDWR).
    """
}