pax_global_header 0000666 0000000 0000000 00000000064 13346112537 0014517 g ustar 00root root 0000000 0000000 52 comment=857c1b3fadbd7e86ebb7072efbfd084cf7a4c198
pybluez-0.22+really0.22/ 0000775 0000000 0000000 00000000000 13346112537 0014722 5 ustar 00root root 0000000 0000000 pybluez-0.22+really0.22/CHANGELOG 0000664 0000000 0000000 00000023642 13346112537 0016143 0 ustar 00root root 0000000 0000000 PyBluez CHANGELOG file
this file contains a list of changes through the different versions of PyBluez.
changes from 0.21 to 0.22(August 05, 2015)
-------------------------
GNU/Linux:
Features:
- experimental support for Bluetooth Low Energy, based on pygattlib
implementation
Bugs:
- l2cap options issue #88
- When cancelling device discovery, DeviceDiscoverer does not call
inquiry_complete() #85
- No way to select device id for device discovery #77
- _get_available_port() should try to bind() with
a supplied address instead of "" #45
Windows:
Bugs:
- No adapter detected - WP8.1 #72
- Non-blocking sockets and blocking sockets with a timeout
do not work correctly when using WinSock backend #40
- Need to setsockopt in Windows #10
changes from 0.20 to 0.21(Apr 05, 2015)
-------------------------
GNU/Linux:
Bugs:
- No way to select device id for device discovery #77
- RSSI info not passed on by DeviceDiscoverer #74
- Warnings during compilation on linux #73
- python3 UnicodeDecodeError in DeviceDiscoverer find_devices #67
Windows:
Bugs:
- Problem with iqnuiring unicode names on windows8.1 with python3.4 #76
- warnings during build for windows (ms visual studio 2010 express) #60
changes from 0.19 to 0.20(Jan 13, 2014)
-------------------------
GNU/Linux/Windows:
Python 3 is now supported.
Python 3.3 uses Visual C++ 2010 Express Edition for build on windows.
changes from 0.18 to 0.19
-------------------------
Added option to return the class of device in discover_devices()
(Lukas Hetzenecker)
GNU/Linux:
Added setl2capsecurity() method to BluetoothSocket
Fixed get_l2cap_options(), set_l2cap_options(), set_l2cap_mtu()
Added abovementioned functions as socket methods
Added BT_SECURITY_*, L2CAP_MODE_* constants
Added support for the "Extended Inquiry Response" event in the asynchronous
DeviceDiscoverer (Lukas Hetzenecker)
Fixed problems with kernel 3.x
windows:
Allow threads during the initialization of the inquiry in widcomm
(Lukas Hetzenecker)
changes from 0.17 to 0.18 (Nov 25, 2009)
----------------------------------------
windows:
support Visual C++ 2008 Express Edition for Python 2.6 (this should
add support for Windows Vista and Windows 7) (Lukas Hetzenecker)
include widcomm/util.h in source distribution
changes from 0.16 to 0.17 (Oct 15, 2009)
----------------------------------------
GNU/Linux:
bugfix for linux 2.6.30+ zero out struct sockaddr
DeviceDiscoverer may specify bluetooth device_id (roelhuybrechts)
DeviceDiscoverer do not override duration parameter (roelhuybrechts)
changes from 0.15 to 0.16 (Feb 5, 2009)
---------------------------------------
fix variable naming in example/simple/inquiry.py (M. Harris Bhatti)
windows:
only import msbt if widcomm fails
fix memory error in MSBT stack
widcomm comment out debugging statements
GNU/Linux:
fix examples to import bluetooth._bluetooth
changes from 0.14 to 0.15 (Jan 21, 2008)
----------------------------------------
GNU/Linux:
don't hardcode duration in discover_devices() to 8 (Gustavo Chain)
win32:
search for wbtapi.dll before trying to import widcomm
changes from 0.13 to 0.14 (Nov 12, 2007)
----------------------------------------
GNU/Linux:
fix device class parsing bug in inquiry-with-rssi (Pepe Aracil)
changes from 0.12 to 0.13 (August 30, 2007)
-------------------------------------------
GNU/Linux:
Oops, stupid bug introduced from last bugfix
changes from 0.11 to 0.12 (August 29, 2007)
-------------------------------------------
GNU/Linux:
fixed _checkaddr bug (reported by Giovanni)
changes from 0.10 to 0.11 (August 25, 2007)
-------------------------------------------
win32:
fixed bug preventing MSBT stack from loading when Widcomm not present
changes from 0.9.2 to 0.10 (August 10, 2007)
--------------------------------------------
win32:
better searching for Platform SDK path (Ren� M�ller)
proper Py_{BEGIN,END}_ALLOW_THREADS (Ren� M�ller)
added experimental Broadcom/Widcomm support. All the basics should be
supported:
RFCOMM sockets
L2CAP sockets
Device Discovery, Name Lookup
SDP search on remote devices
SDP advertisement (RFCOMM, L2CAP)
Widcomm stack notes:
1. BluetoothSocket.accept () always returns 0 for the port,
as the RFCOMM channel/L2CAP PSM of the client device is not exposed
by the Widcomm API
2. Not all fields of advertise_service are supported. The following
parameters are currently not supported:
description, protocols
3. The following methods of BluetoothSocket are not supported:
gettimeout, dup, makefile, settimeout
4. The following parameters to discover_devices are not supported:
duration, flush_cache (cache always flushes)
5. The timeout parameter of lookup_name is not supported
6. Once a listening socket has accepted a connection, it is not put
back into listening mode. The original listening socket essentially
becomes useless.
7. SDP search/browse operations on the local host are not yet supported
GNU/Linux:
fix segfault on trying to SDP advertise when sdpd not running
(reported by Eric Butler)
changes from 0.9.1 to 0.9.2 (Dec 29, 2006)
------------------------------------------
GNU/Linux:
fixed endian-ness error in L2CAP psm field. only affects big-endian
machines.
changes from 0.9 to 0.9.1 (Sep 14, 2006)
----------------------------------------
GNU/Linux:
fixed missing #include that prevents PyBluez from compiling with
newer version of BlueZ (reported by Priyank Gosalia)
changes from 0.8 to 0.9 (Sep 9, 2006)
----------------------------------------
added protocols optional parameter to advertise_service (bluez: Bea Lam)
refactor: merged bluez/bluetooth.py and msbt/bluetooth.py
GNU/Linux:
added _bluetooth.hci_devid (Mikael Lindqvist)
added _bluetooth.SCO_OPTIONS constant
added Py_{BEGIN,END}_ALLOW_THREADS guards around sdp_connect
(spotted by Rostislav Belov)
win32:
send() now returns the number of bytes sent (spotted by Keith O'Hara)
sdp search no longer raises an exception when no records are found and no
other error occurred.
changes from 0.7.1 to 0.8 (July 31, 2006)
----------------------------------------
win32:
added settimeout, gettimeout, setblocking methods (David Conolly)
GNU/Linux:
fixed DeviceDiscoverer device class byte swap bug (spotted by Bea Lam)
changes from 0.7 to 0.7.1 (May 13, 2006)
---------------------------------------
win32:
discover_devices() no longer raises an IOError when no devices are detected
lookup_name() sort of works (consistently on some machines,
not at all on others)
advertise_service() fully supported
changes from 0.6.1 to 0.7 (May 5, 2006)
---------------------------------------
- fixed some docstring errors
- added lookup_names parameter to discover_devices() If set to True,
discover_devices() returns a list of (address, name) pairs. If set to False
(default), returns a list of addresses
- added constant PORT_ANY. bind to port PORT_ANY for dynamic port
assignment.
get_available_port() is now deprecated.
- added support for Microsoft Windows Bluetooth API. This comes standard on
Windows XP SP1, and Windows Vista. The following features are supported:
RFCOMM sockets (bind, listen, connect, accept, send, recv, close,
getsockname, fileno)
discover_devices()
find_service()
advertise_service() - with limitations. See code for details
The following features are not yet supported in Windows XP:
DeviceDiscoverer class
lookup_name()
changes from 0.6 to 0.6.1 (Feb 24, 2006)
----------------------------------------
fixed UUID parsing again (byte swap error)
added parsing of 32-bit reserved UUIDs
fixed rfcomm-client and rfcomm-server examples to use the same UUID
addded service-id to find_service result
changes from 0.5 to 0.6 (Feb 18, 2006)
--------------------------------------
fixed examples/basic/l2-mtu.py [sock -> client_sock]
fixed hci_send_req [keywords bug]
fixed UUID parsing (Cezar S Espinola)
changes from 0.4 to 0.5 (Dec 16, 2005)
--------------------------------------
added service-classes and profiles keys to find_service result
added service class list and profile list support to
advertise_service (Elvis Pf zenreuter)
fixed do_search response_list (Richard Moore)
BluetoothError now inherits from IOError (Elvis Pf�tzenreuter)
added CHANGELOG
added COPYING
changes from 0.3 to 0.4 (Nov 9, 2005)
-------------------------------------
fixed DeviceDiscoverer name request parsing (Alastair Tre)
fixed set_l2cap_mtu bluetooth module error (simo salminen)
changes from 0.2 to 0.3 (Sep 20, 2005)
--------------------------------------
fixed invalid free() in bt_hci_inquiry (ted wright)
fixed endian error for RFCOMM sockets (Ted Wright)
no longer using SDP_RECORD_PERSIST
changes from 0.1 to 0.2 (Apr 4, 2005)
-------------------------------------
Support for SDP service advertisement and searching added.
Support for easy asynchronous device discovery added (DeviceDiscoverer).
fixed hci_send_req. added a bunch of constants for ioctl on hci sockets
renamed most things from bluez* to bt* or bluetooth*
changed module name from bluez to _bluetooth
changed bluezsocket to btsocket
New API is incompatible with 0.1.
version 0.1 (Dec 16, 2004)
--------------------------
Support for HCI, L2CAP, and RFCOMM sockets.
No support for OBEX or SDP.
pybluez-0.22+really0.22/COPYING 0000664 0000000 0000000 00000043105 13346112537 0015760 0 ustar 00root root 0000000 0000000 GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program 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 2 of the License, or
(at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
pybluez-0.22+really0.22/MANIFEST.in 0000664 0000000 0000000 00000000724 13346112537 0016463 0 ustar 00root root 0000000 0000000 include CHANGELOG
include COPYING
include README
include setup.py
recursive-include bluetooth *.py
recursive-include bluez *.c
recursive-include bluez *.h
recursive-include msbt *.c
recursive-include widcomm *.cpp
recursive-include widcomm *.hpp
recursive-include widcomm *.h
recursive-include osx *.c
recursive-include osx *.h
recursive-include port3 *.h
recursive-include examples *.py
recursive-exclude * *.pyc
recursive-exclude * *.o
recursive-exclude * *.opp
pybluez-0.22+really0.22/README 0000664 0000000 0000000 00000004314 13346112537 0015604 0 ustar 00root root 0000000 0000000 PyBluez
Python extension module allowing access to system Bluetooth resources.
https://github.com/karulis/pybluez
BUILD REQUIREMENTS:
GNU/Linux:
- Python 2.3 or more recent version
- Python distutils (standard in most Python distros, separate package
python-dev in Debian)
- BlueZ libraries and header files
Windows:
- Microsoft Windows XP SP1 or Windows Vista/7/8/8.1
- Visual C++ 2010 Express for build for Python 3.3 or newer
- Visual C++ 2008 Express for build for Python 3.2 or older
- In order to build 64-bit debug and release executables,
Visual Studio 2008/2010 Standard Edition is required
- Widcomm BTW development kit 5.0 or later (Optional)
- Python 2.3 or more recent version
INSTALLATION:
from a command shell:
# python setup.py install
EXAMPLES:
GNU/Linux and Windows XP:
# examples/simple/inquiry.py - Detecting nearby Bluetooth devices
# examples/simple/sdp-browse.py - Browsing SDP services on a Bluetooth device
# examples/simple/rfcomm-server.py - establishing an RFCOMM connection.
# examples/simple/rfcomm-client.py - establishing an RFCOMM connection.
GNU/Linux only:
# exmaples/simple/l2capserver.py
# exmaples/simple/l2capclient.py
# examples/simple/asynchronous-inquiry.py
# examples/bluezchat (requires PyGTK)
# examples/advanced/inquiry-with-rssi.py
# examples/l2-unreliable-server.py
# examples/l2-unreliable-client.py
CONTACT:
Please use the mailing list at http://groups.google.com/group/pybluez/
LICENSE:
PyBluez 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 2 of the License, or (at your option) any later
version.
PyBluez 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
PyBluez; if not, write to the Free Software Foundation, Inc., 51 Franklin St,
Fifth Floor, Boston, MA 02110-1301 USA
pybluez-0.22+really0.22/README.rst 0000664 0000000 0000000 00000012062 13346112537 0016412 0 ustar 00root root 0000000 0000000 ==================
PyBluez
==================
Python extension module allowing access to system Bluetooth resources.
https://github.com/karulis/pybluez
**EXAMPLES:**
.. code-block:: python
# simple inquiry example
import bluetooth
nearby_devices = bluetooth.discover_devices(lookup_names=True)
print("found %d devices" % len(nearby_devices))
for addr, name in nearby_devices:
print(" %s - %s" % (addr, name))
.. code-block:: python
# bluetooth low energy scan
from bluetooth.ble import DiscoveryService
service = DiscoveryService()
devices = service.discover(2)
for address, name in devices.items():
print("name: {}, address: {}".format(name, address))
*GNU/Linux and Windows XP examples:*
- `examples/simple/inquiry.py`_ - Detecting nearby Bluetooth devices
- `examples/simple/sdp-browse.py`_ - Browsing SDP services on a Bluetooth device.
- `examples/simple/rfcomm-server.py`_ - establishing an RFCOMM connection.
- `examples/simple/rfcomm-client.py`_ - establishing an RFCOMM connection.
*GNU/Linux only examples:*
- `examples/simple/l2capserver.py`_
- `examples/simple/l2capclient.py`_
- `examples/simple/asynchronous-inquiry.py`_
- `examples/bluezchat`_
- `examples/advanced/inquiry-with-rssi.py`_
- `examples/advanced/l2-unreliable-server.py`_
- `examples/advanced/l2-unreliable-client.py`_
*GNU/Linux experimental BLE support:*
- `examples/ble/scan.py`_
- `examples/ble/beacon.py`_
- `examples/ble/beacon_scan.py`_
- `examples/ble/read_name.py`_
**CONTACT:**
Please use the mailing list at
http://groups.google.com/group/pybluez/
**INSTALLATION:**
Use pip(there are also binaries for Windows platform on PyPi):
pip install pybluez
For experimental Bluetooth Low Energy support(only for Linux platform - for additional dependencies please take look at: `ble-dependencies`_):
pip install pybluez[ble]
For source installation:
python setup.py install
for Bluetooth Low Energy support:
pip install -e .[ble]
**BUILD REQUIREMENTS:**
*GNU/Linux:*
- Python 2.3 or more recent version
- Python distutils (standard in most Python distros, separate package python-dev in Debian)
- BlueZ libraries and header files
*Windows:*
- Microsoft Windows XP SP1 or Windows Vista/7/8/8.1
- Visual C++ 2010 Express for build for Python 3.3 or newer
- Visual C++ 2008 Express for build for Python 3.2 or older
- In order to build 64-bit debug and release executables, Visual Studio 2008/2010 Standard Edition is required
- Widcomm BTW development kit 5.0 or later (Optional)
- Python 2.3 or more recent version
**LICENSE:**
PyBluez 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 2 of the License, or (at your option) any later
version.
PyBluez 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
PyBluez; if not, write to the Free Software Foundation, Inc., 51 Franklin St,
Fifth Floor, Boston, MA 02110-1301 USA
.. _examples/simple/inquiry.py: https://github.com/karulis/pybluez/blob/master/examples/simple/inquiry.py
.. _examples/simple/sdp-browse.py: https://github.com/karulis/pybluez/blob/master/examples/simple/sdp-browse.py
.. _examples/simple/rfcomm-server.py: https://github.com/karulis/pybluez/blob/master/examples/simple/rfcomm-server.py
.. _examples/simple/rfcomm-client.py: https://github.com/karulis/pybluez/blob/master/examples/simple/rfcomm-client.py
.. _examples/simple/l2capserver.py: https://github.com/karulis/pybluez/blob/master/examples/simple/l2capserver.py
.. _examples/simple/l2capclient.py: https://github.com/karulis/pybluez/blob/master/examples/simple/l2capclient.py
.. _examples/simple/asynchronous-inquiry.py: https://github.com/karulis/pybluez/blob/master/examples/simple/asynchronous-inquiry.py
.. _examples/bluezchat: https://github.com/karulis/pybluez/blob/master/examples/bluezchat
.. _examples/advanced/inquiry-with-rssi.py: https://github.com/karulis/pybluez/blob/master/examples/advanced/inquiry-with-rssi.py
.. _examples/advanced/l2-unreliable-server.py: https://github.com/karulis/pybluez/blob/master/examples/advanced/l2-unreliable-server.py
.. _examples/advanced/l2-unreliable-client.py: https://github.com/karulis/pybluez/blob/master/examples/advanced/l2-unreliable-client.py
.. _examples/ble/scan.py: https://github.com/karulis/pybluez/blob/master/examples/ble/scan.py
.. _examples/ble/beacon.py: https://github.com/karulis/pybluez/blob/master/examples/ble/beacon.py
.. _examples/ble/beacon_scan.py: https://github.com/karulis/pybluez/blob/master/examples/ble/beacon_scan.py
.. _examples/ble/read_name.py: https://github.com/karulis/pybluez/blob/master/examples/ble/read_name.py
.. _ble-dependencies: https://bitbucket.org/OscarAcena/pygattlib/src/45e04060881a20189412681f52d55ff5add9f388/DEPENDS?at=default pybluez-0.22+really0.22/bluetooth/ 0000775 0000000 0000000 00000000000 13346112537 0016727 5 ustar 00root root 0000000 0000000 pybluez-0.22+really0.22/bluetooth/__init__.py 0000664 0000000 0000000 00000013547 13346112537 0021052 0 ustar 00root root 0000000 0000000 import sys
import os
if sys.version < '3':
from .btcommon import *
else:
from bluetooth.btcommon import *
__version__ = 0.22
def _dbg(*args):
return
sys.stderr.write(*args)
sys.stderr.write("\n")
if sys.platform == "win32":
_dbg("trying widcomm")
have_widcomm = False
dll = "wbtapi.dll"
sysroot = os.getenv ("SystemRoot")
if os.path.exists (dll) or \
os.path.exists (os.path.join (sysroot, "system32", dll)) or \
os.path.exists (os.path.join (sysroot, dll)):
try:
from . import widcomm
if widcomm.inquirer.is_device_ready ():
# if the Widcomm stack is active and a Bluetooth device on that
# stack is detected, then use the Widcomm stack
from .widcomm import *
have_widcomm = True
except ImportError:
pass
if not have_widcomm:
# otherwise, fall back to the Microsoft stack
_dbg("Widcomm not ready. falling back to MS stack")
if sys.version < '3':
from .msbt import *
else:
from bluetooth.msbt import *
elif sys.platform.startswith("linux"):
if sys.version < '3':
from .bluez import *
else:
from bluetooth.bluez import *
elif sys.platform == "darwin":
from .osx import *
else:
raise Exception("This platform (%s) is currently not supported by pybluez." % sys.platform)
discover_devices.__doc__ = \
"""
performs a bluetooth device discovery using the first available bluetooth
resource.
if lookup_names is False, returns a list of bluetooth addresses.
if lookup_names is True, returns a list of (address, name) tuples
lookup_names=False
if set to True, then discover_devices also attempts to lookup the
display name of each detected device.
if lookup_class is True, the class of the device is added to the tuple
"""
lookup_name.__doc__ = \
"""
Tries to determine the friendly name (human readable) of the device with
the specified bluetooth address. Returns the name on success, and None
on failure.
"""
advertise_service.__doc__ = \
"""
Advertises a service with the local SDP server. sock must be a bound,
listening socket. name should be the name of the service, and service_id
(if specified) should be a string of the form
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", where each 'X' is a hexadecimal
digit.
service_classes is a list of service classes whose this service belongs to.
Each class service is a 16-bit UUID in the form "XXXX", where each 'X' is a
hexadecimal digit, or a 128-bit UUID in the form
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX". There are some constants for
standard services, e.g. SERIAL_PORT_CLASS that equals to "1101". Some class
constants:
SERIAL_PORT_CLASS LAN_ACCESS_CLASS DIALUP_NET_CLASS
HEADSET_CLASS CORDLESS_TELEPHONY_CLASS AUDIO_SOURCE_CLASS
AUDIO_SINK_CLASS PANU_CLASS NAP_CLASS
GN_CLASS
profiles is a list of service profiles that thie service fulfills. Each
profile is a tuple with ( uuid, version). Most standard profiles use
standard classes as UUIDs. PyBluez offers a list of standard profiles,
for example SERIAL_PORT_PROFILE. All standard profiles have the same
name as the classes, except that _CLASS suffix is replaced by _PROFILE.
provider is a text string specifying the provider of the service
description is a text string describing the service
A note on working with Symbian smartphones:
bt_discover in Python for Series 60 will only detect service records
with service class SERIAL_PORT_CLASS and profile SERIAL_PORT_PROFILE
"""
stop_advertising.__doc__ = \
"""
Instructs the local SDP server to stop advertising the service associated
with sock. You should typically call this right before you close sock.
"""
find_service.__doc__ = \
"""
find_service (name = None, uuid = None, address = None)
Searches for SDP services that match the specified criteria and returns
the search results. If no criteria are specified, then returns a list of
all nearby services detected. If more than one is specified, then
the search results will match all the criteria specified. If uuid is
specified, it must be either a 16-bit UUID in the form "XXXX", where each
'X' is a hexadecimal digit, or as a 128-bit UUID in the form
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX". A special case of address is
"localhost", which will search for services on the local machine.
The search results will be a list of dictionaries. Each dictionary
represents a search match and will have the following key/value pairs:
host - the bluetooth address of the device advertising the
service
name - the name of the service being advertised
description - a description of the service being advertised
provider - the name of the person/organization providing the service
protocol - either 'RFCOMM', 'L2CAP', None if the protocol was not
specified, or 'UNKNOWN' if the protocol was specified but
unrecognized
port - the L2CAP PSM # if the protocol is 'L2CAP', the RFCOMM
channel # if the protocol is 'RFCOMM', or None if it
wasn't specified
service-classes - a list of service class IDs (UUID strings). possibly
empty
profiles - a list of profiles - (UUID, version) pairs - the
service claims to support. possibly empty.
service-id - the Service ID of the service. None if it wasn't set
See the Bluetooth spec for the difference between
Service ID and Service Class ID List
"""
pybluez-0.22+really0.22/bluetooth/ble.py 0000664 0000000 0000000 00000000027 13346112537 0020042 0 ustar 00root root 0000000 0000000 from gattlib import *
pybluez-0.22+really0.22/bluetooth/bluez.py 0000664 0000000 0000000 00000055412 13346112537 0020431 0 ustar 00root root 0000000 0000000 import sys
import struct
if sys.version < '3':
from .btcommon import *
import _bluetooth as _bt
get_byte = ord
else:
from bluetooth.btcommon import *
import bluetooth._bluetooth as _bt
get_byte = int
import array
import fcntl
_constants = [ 'HCI', 'RFCOMM', 'L2CAP', 'SCO', 'SOL_L2CAP', 'SOL_RFCOMM',\
'L2CAP_OPTIONS' ]
for _c in _constants:
command_ = "{C} = _bt.{C1}".format(C=_c, C1=_c)
exec(command_)
del _constants
# ============== SDP service registration and unregistration ============
def discover_devices (duration=8, flush_cache=True, lookup_names=False,
lookup_class=False, device_id=-1):
if device_id == -1:
device_id = _bt.hci_get_route()
sock = _gethcisock (device_id)
try:
results = _bt.hci_inquiry (sock, duration=duration, flush_cache=True,
lookup_class=lookup_class, device_id=device_id)
except _bt.error:
sock.close ()
raise BluetoothError ("error communicating with local "
"bluetooth adapter")
if lookup_names:
pairs = []
for item in results:
if lookup_class:
addr, dev_class = item
else:
addr = item
timeoutms = int (10 * 1000)
try:
name = _bt.hci_read_remote_name (sock, addr, timeoutms)
except _bt.error:
# name lookup failed. either a timeout, or I/O error
continue
pairs.append ((addr, name, dev_class) if lookup_class else (addr, name))
sock.close ()
return pairs
else:
sock.close ()
return results
def lookup_name (address, timeout=10):
if not is_valid_address (address):
raise BluetoothError ("%s is not a valid Bluetooth address" % address)
sock = _gethcisock ()
timeoutms = int (timeout * 1000)
try:
name = _bt.hci_read_remote_name (sock, address, timeoutms)
except _bt.error:
# name lookup failed. either a timeout, or I/O error
name = None
sock.close ()
return name
def set_packet_timeout (address, timeout):
"""
Adjusts the ACL flush timeout for the ACL connection to the specified
device. This means that all L2CAP and RFCOMM data being sent to that
device will be dropped if not acknowledged in timeout milliseconds (maximum
1280). A timeout of 0 means to never drop packets.
Since this affects all Bluetooth connections to that device, and not just
those initiated by this process or PyBluez, a call to this method requires
superuser privileges.
You must have an active connection to the specified device before invoking
this method
"""
n = round (timeout / 0.625)
write_flush_timeout (address, n)
def get_l2cap_options (sock):
"""get_l2cap_options (sock, mtu)
Gets L2CAP options for the specified L2CAP socket.
Options are: omtu, imtu, flush_to, mode, fcs, max_tx, txwin_size.
"""
# TODO this should be in the C module, because it depends
# directly on struct l2cap_options layout.
s = sock.getsockopt (SOL_L2CAP, L2CAP_OPTIONS, 12)
options = list( struct.unpack ("HHHBBBH", s))
return options
def set_l2cap_options (sock, options):
"""set_l2cap_options (sock, options)
Sets L2CAP options for the specified L2CAP socket.
The option list must be in the same format supplied by
get_l2cap_options().
"""
# TODO this should be in the C module, because it depends
# directly on struct l2cap_options layout.
s = struct.pack ("HHHBBBH", *options)
sock.setsockopt (SOL_L2CAP, L2CAP_OPTIONS, s)
def set_l2cap_mtu (sock, mtu):
"""set_l2cap_mtu (sock, mtu)
Adjusts the MTU for the specified L2CAP socket. This method needs to be
invoked on both sides of the connection for it to work! The default mtu
that all L2CAP connections start with is 672 bytes.
mtu must be between 48 and 65535, inclusive.
"""
options = get_l2cap_options (sock)
options[0] = options[1] = mtu
set_l2cap_options (sock, options)
def _get_available_port (protocol, addr=""):
"""
deprecated. bind to PORT_ANY instead.
"""
if protocol == RFCOMM:
for channel in range (1,31):
s = BluetoothSocket (RFCOMM)
try:
s.bind ( (addr, channel))
s.close ()
return channel
except:
s.close ()
elif protocol == L2CAP:
for psm in range (0x1001,0x8000,2):
s = BluetoothSocket (L2CAP)
try:
s.bind ( (addr, psm))
s.close ()
return psm
except:
s.close ()
else:
raise ValueError ("protocol must either RFCOMM or L2CAP")
class BluetoothSocket:
__doc__ = _bt.btsocket.__doc__
def __init__ (self, proto = RFCOMM, _sock=None):
if _sock is None:
_sock = _bt.btsocket (proto)
self._sock = _sock
self._proto = proto
def dup (self):
"""dup () -> socket object
Return a new socket object connected to the same system resource."""
return BluetoothSocket (proto=self._proto, _sock=self._sock)
def accept (self):
try:
client, addr = self._sock.accept ()
except _bt.error as e:
raise BluetoothError (str (e))
newsock = BluetoothSocket (self._proto, client)
return (newsock, addr)
accept.__doc__ = _bt.btsocket.accept.__doc__
def bind (self, addrport):
if self._proto == RFCOMM or self._proto == L2CAP:
addr, port = addrport
if port == 0: addrport = (addr, _get_available_port (self._proto, addr))
return self._sock.bind (addrport)
def get_l2cap_options(self):
"""get_l2cap_options (sock, mtu)
Gets L2CAP options for the specified L2CAP socket.
Options are: omtu, imtu, flush_to, mode, fcs, max_tx, txwin_size.
"""
return get_l2cap_options(self)
def set_l2cap_options(self, options):
"""set_l2cap_options (sock, options)
Sets L2CAP options for the specified L2CAP socket.
The option list must be in the same format supplied by
get_l2cap_options().
"""
return set_l2cap_options(self, options)
def set_l2cap_mtu(self, mtu):
"""set_l2cap_mtu (sock, mtu)
Adjusts the MTU for the specified L2CAP socket. This method needs to be
invoked on both sides of the connection for it to work! The default mtu
that all L2CAP connections start with is 672 bytes.
mtu must be between 48 and 65535, inclusive.
"""
return set_l2cap_mtu(self, mtu)
# import methods from the wraapped socket object
_s = ("""def %s (self, *args, **kwargs):
try:
return self._sock.%s (*args, **kwargs)
except _bt.error as e:
raise BluetoothError (str (e))
%s.__doc__ = _bt.btsocket.%s.__doc__\n""")
for _m in ( 'connect', 'connect_ex', 'close',
'fileno', 'getpeername', 'getsockname', 'gettimeout',
'getsockopt', 'listen', 'makefile', 'recv', 'recvfrom', 'sendall',
'send', 'sendto', 'setblocking', 'setsockopt', 'settimeout',
'shutdown', 'setl2capsecurity'):
exec( _s % (_m, _m, _m, _m))
del _m, _s
def advertise_service (sock, name, service_id = "", service_classes = [], \
profiles = [], provider = "", description = "", protocols = []):
if service_id != "" and not is_valid_uuid (service_id):
raise ValueError ("invalid UUID specified for service_id")
for uuid in service_classes:
if not is_valid_uuid (uuid):
raise ValueError ("invalid UUID specified in service_classes")
for uuid, version in profiles:
if not is_valid_uuid (uuid) or version < 0 or version > 0xFFFF:
raise ValueError ("Invalid Profile Descriptor")
for uuid in protocols:
if not is_valid_uuid (uuid):
raise ValueError ("invalid UUID specified in protocols")
try:
_bt.sdp_advertise_service (sock._sock, name, service_id, \
service_classes, profiles, provider, description, \
protocols)
except _bt.error as e:
raise BluetoothError (str (e))
def stop_advertising (sock):
try:
_bt.sdp_stop_advertising (sock._sock)
except _bt.error as e:
raise BluetoothError (str (e))
def find_service (name = None, uuid = None, address = None):
if not address:
devices = discover_devices ()
else:
devices = [ address ]
results = []
if uuid is not None and not is_valid_uuid (uuid):
raise ValueError ("invalid UUID")
try:
for addr in devices:
try:
s = _bt.SDPSession ()
s.connect (addr)
matches = []
if uuid is not None:
matches = s.search (uuid)
else:
matches = s.browse ()
except _bt.error:
continue
if name is not None:
matches = [s for s in matches if s.get ("name", "") == name]
for m in matches:
m["host"] = addr
results.extend (matches)
except _bt.error as e:
raise BluetoothError (str (e))
return results
# ================ BlueZ internal methods ================
def _gethcisock (device_id = -1):
try:
sock = _bt.hci_open_dev (device_id)
except:
raise BluetoothError ("error accessing bluetooth device")
return sock
def get_acl_conn_handle (hci_sock, addr):
hci_fd = hci_sock.fileno ()
reqstr = struct.pack ("6sB17s", _bt.str2ba (addr),
_bt.ACL_LINK, b"\0" * 17)
request = array.array ("b", reqstr)
try:
fcntl.ioctl (hci_fd, _bt.HCIGETCONNINFO, request, 1)
except IOError:
raise BluetoothError ("There is no ACL connection to %s" % addr)
# XXX should this be "<8xH14x"?
handle = struct.unpack ("8xH14x", request.tostring ())[0]
return handle
def write_flush_timeout (addr, timeout):
hci_sock = _bt.hci_open_dev ()
# get the ACL connection handle to the remote device
handle = get_acl_conn_handle (hci_sock, addr)
# XXX should this be " 127:
return byte_ - 256
else:
return byte_
class DeviceDiscoverer:
"""
Skeleton class for finer control of the device discovery process.
To implement asynchronous device discovery (e.g. if you want to do
something *as soon as* a device is discovered), subclass
DeviceDiscoverer and override device_discovered () and
inquiry_complete ()
"""
def __init__ (self, device_id=-1):
"""
__init__ (device_id=-1)
device_id - The ID of the Bluetooth adapter that will be used
for discovery.
"""
self.sock = None
self.is_inquiring = False
self.lookup_names = False
self.device_id = device_id
self.names_to_find = {}
self.names_found = {}
def find_devices (self, lookup_names=True,
duration=8,
flush_cache=True):
"""
find_devices (lookup_names=True, service_name=None,
duration=8, flush_cache=True)
Call this method to initiate the device discovery process
lookup_names - set to True if you want to lookup the user-friendly
names for each device found.
service_name - set to the name of a service you're looking for.
only devices with a service of this name will be
returned in device_discovered () NOT YET IMPLEMENTED
ADVANCED PARAMETERS: (don't change these unless you know what
you're doing)
duration - the number of 1.2 second units to spend searching for
bluetooth devices. If lookup_names is True, then the
inquiry process can take a lot longer.
flush_cache - return devices discovered in previous inquiries
"""
if self.is_inquiring:
raise BluetoothError ("Already inquiring!")
self.lookup_names = lookup_names
self.sock = _gethcisock (self.device_id)
flt = _bt.hci_filter_new ()
_bt.hci_filter_all_events (flt)
_bt.hci_filter_set_ptype (flt, _bt.HCI_EVENT_PKT)
try:
self.sock.setsockopt (_bt.SOL_HCI, _bt.HCI_FILTER, flt)
except:
raise BluetoothError ("problem with local bluetooth device.")
# send the inquiry command
max_responses = 255
cmd_pkt = struct.pack ("BBBBB", 0x33, 0x8b, 0x9e, \
duration, max_responses)
self.pre_inquiry ()
try:
_bt.hci_send_cmd (self.sock, _bt.OGF_LINK_CTL, \
_bt.OCF_INQUIRY, cmd_pkt)
except:
raise BluetoothError ("problem with local bluetooth device.")
self.is_inquiring = True
self.names_to_find = {}
self.names_found = {}
def cancel_inquiry (self):
"""
Call this method to cancel an inquiry in process. inquiry_complete
will still be called.
"""
self.names_to_find = {}
if self.is_inquiring:
try:
_bt.hci_send_cmd (self.sock, _bt.OGF_LINK_CTL, \
_bt.OCF_INQUIRY_CANCEL)
except:
self.sock.close ()
self.sock = None
raise BluetoothError ("error canceling inquiry")
self.is_inquiring = False
def process_inquiry (self):
"""
Repeatedly calls process_event () until the device inquiry has
completed.
"""
while self.is_inquiring or len (self.names_to_find) > 0:
self.process_event ()
def process_event (self):
"""
Waits for one event to happen, and proceses it. The event will be
either a device discovery, or an inquiry completion.
"""
self._process_hci_event ()
def _process_hci_event (self):
if self.sock is None: return
# voodoo magic!!!
pkt = self.sock.recv (258)
ptype, event, plen = struct.unpack ("BBB", pkt[:3])
pkt = pkt[3:]
if event == _bt.EVT_INQUIRY_RESULT:
nrsp = get_byte(pkt[0])
for i in range (nrsp):
addr = _bt.ba2str (pkt[1+6*i:1+6*i+6])
psrm = pkt[ 1+6*nrsp+i ]
pspm = pkt[ 1+7*nrsp+i ]
devclass_raw = struct.unpack ("BBB",
pkt[1+9*nrsp+3*i:1+9*nrsp+3*i+3])
devclass = (devclass_raw[2] << 16) | \
(devclass_raw[1] << 8) | \
devclass_raw[0]
clockoff = pkt[1+12*nrsp+2*i:1+12*nrsp+2*i+2]
self._device_discovered (addr, devclass,
psrm, pspm, clockoff, None, None)
elif event == _bt.EVT_INQUIRY_RESULT_WITH_RSSI:
nrsp = get_byte(pkt[0])
for i in range (nrsp):
addr = _bt.ba2str (pkt[1+6*i:1+6*i+6])
psrm = pkt[ 1+6*nrsp+i ]
pspm = pkt[ 1+7*nrsp+i ]
# devclass_raw = pkt[1+8*nrsp+3*i:1+8*nrsp+3*i+3]
# devclass = struct.unpack ("I", "%s\0" % devclass_raw)[0]
devclass_raw = struct.unpack ("BBB",
pkt[1+8*nrsp+3*i:1+8*nrsp+3*i+3])
devclass = (devclass_raw[2] << 16) | \
(devclass_raw[1] << 8) | \
devclass_raw[0]
clockoff = pkt[1+11*nrsp+2*i:1+11*nrsp+2*i+2]
rssi = byte_to_signed_int(get_byte(pkt[1+13*nrsp+i]))
self._device_discovered (addr, devclass,
psrm, pspm, clockoff, rssi, None)
elif _bt.HAVE_EVT_EXTENDED_INQUIRY_RESULT and event == _bt.EVT_EXTENDED_INQUIRY_RESULT:
nrsp = get_byte(pkt[0])
for i in range (nrsp):
addr = _bt.ba2str (pkt[1+6*i:1+6*i+6])
psrm = pkt[ 1+6*nrsp+i ]
pspm = pkt[ 1+7*nrsp+i ]
devclass_raw = struct.unpack ("BBB",
pkt[1+8*nrsp+3*i:1+8*nrsp+3*i+3])
devclass = (devclass_raw[2] << 16) | \
(devclass_raw[1] << 8) | \
devclass_raw[0]
clockoff = pkt[1+11*nrsp+2*i:1+11*nrsp+2*i+2]
rssi = byte_to_signed_int(get_byte(pkt[1+13*nrsp+i]))
data_len = _bt.EXTENDED_INQUIRY_INFO_SIZE - _bt.INQUIRY_INFO_WITH_RSSI_SIZE
data = pkt[1+14*nrsp+i:1+14*nrsp+i+data_len]
name = None
pos = 0
while(pos <= len(data)):
struct_len = get_byte(data[pos])
if struct_len == 0:
break
eir_type = get_byte(data[pos+1])
if eir_type == 0x09: # Complete local name
name = data[pos+2:pos+struct_len+1]
pos += struct_len + 2
self._device_discovered (addr, devclass,
psrm, pspm, clockoff, rssi, name)
elif event == _bt.EVT_INQUIRY_COMPLETE or event == _bt.EVT_CMD_COMPLETE:
self.is_inquiring = False
if len (self.names_to_find) == 0:
# print "inquiry complete (evt_inquiry_complete)"
self.sock.close ()
self._inquiry_complete ()
else:
self._send_next_name_req ()
elif event == _bt.EVT_CMD_STATUS:
# XXX shold this be " 0
address = list(self.names_to_find.keys ())[0]
device_class, rssi, psrm, pspm, clockoff = self.names_to_find[address]
bdaddr = _bt.str2ba (address) #TODO not supported in python3
cmd_pkt = "%s%s\0%s" % (bdaddr, psrm, clockoff)
try:
_bt.hci_send_cmd (self.sock, _bt.OGF_LINK_CTL, \
_bt.OCF_REMOTE_NAME_REQ, cmd_pkt)
except Exception as e:
raise BluetoothError ("error request name of %s - %s" %
(address, str (e)))
def fileno (self):
if not self.sock: return None
return self.sock.fileno ()
def pre_inquiry (self):
"""
Called just after find_devices is invoked, but just before the
inquiry is started.
This method exists to be overriden
"""
def device_discovered (self, address, device_class, rssi, name):
"""
Called when a bluetooth device is discovered.
address is the bluetooth address of the device
device_class is the Class of Device, as specified in [1]
passed in as a 3-byte string
name is the user-friendly name of the device if lookup_names was
set when the inquiry was started. otherwise None
This method exists to be overriden.
[1] https://www.bluetooth.org/foundry/assignnumb/document/baseband
"""
if name:
print(("found: %s - %s (class 0x%X, rssi %s)" % \
(address, name, device_class, rssi)))
else:
print(("found: %s (class 0x%X)" % (address, device_class)))
print(("found: %s (class 0x%X, rssi %s)" % \
(address, device_class, rssi)))
def _inquiry_complete (self):
"""
Called when an inquiry started by find_devices has completed.
"""
self.sock.close ()
self.sock = None
self.inquiry_complete()
def inquiry_complete (self):
"""
Called when an inquiry started by find_devices has completed.
"""
print("inquiry complete")
pybluez-0.22+really0.22/bluetooth/btcommon.py 0000664 0000000 0000000 00000032037 13346112537 0021124 0 ustar 00root root 0000000 0000000 import sys
import struct
import binascii
L2CAP=0
RFCOMM=3
PORT_ANY=0
# Service Class IDs
SDP_SERVER_CLASS = "1000"
BROWSE_GRP_DESC_CLASS = "1001"
PUBLIC_BROWSE_GROUP = "1002"
SERIAL_PORT_CLASS = "1101"
LAN_ACCESS_CLASS = "1102"
DIALUP_NET_CLASS = "1103"
IRMC_SYNC_CLASS = "1104"
OBEX_OBJPUSH_CLASS = "1105"
OBEX_FILETRANS_CLASS = "1106"
IRMC_SYNC_CMD_CLASS = "1107"
HEADSET_CLASS = "1108"
CORDLESS_TELEPHONY_CLASS = "1109"
AUDIO_SOURCE_CLASS = "110a"
AUDIO_SINK_CLASS = "110b"
AV_REMOTE_TARGET_CLASS = "110c"
ADVANCED_AUDIO_CLASS = "110d"
AV_REMOTE_CLASS = "110e"
VIDEO_CONF_CLASS = "110f"
INTERCOM_CLASS = "1110"
FAX_CLASS = "1111"
HEADSET_AGW_CLASS = "1112"
WAP_CLASS = "1113"
WAP_CLIENT_CLASS = "1114"
PANU_CLASS = "1115"
NAP_CLASS = "1116"
GN_CLASS = "1117"
DIRECT_PRINTING_CLASS = "1118"
REFERENCE_PRINTING_CLASS = "1119"
IMAGING_CLASS = "111a"
IMAGING_RESPONDER_CLASS = "111b"
IMAGING_ARCHIVE_CLASS = "111c"
IMAGING_REFOBJS_CLASS = "111d"
HANDSFREE_CLASS = "111e"
HANDSFREE_AGW_CLASS = "111f"
DIRECT_PRT_REFOBJS_CLASS = "1120"
REFLECTED_UI_CLASS = "1121"
BASIC_PRINTING_CLASS = "1122"
PRINTING_STATUS_CLASS = "1123"
HID_CLASS = "1124"
HCR_CLASS = "1125"
HCR_PRINT_CLASS = "1126"
HCR_SCAN_CLASS = "1127"
CIP_CLASS = "1128"
VIDEO_CONF_GW_CLASS = "1129"
UDI_MT_CLASS = "112a"
UDI_TA_CLASS = "112b"
AV_CLASS = "112c"
SAP_CLASS = "112d"
PNP_INFO_CLASS = "1200"
GENERIC_NETWORKING_CLASS = "1201"
GENERIC_FILETRANS_CLASS = "1202"
GENERIC_AUDIO_CLASS = "1203"
GENERIC_TELEPHONY_CLASS = "1204"
UPNP_CLASS = "1205"
UPNP_IP_CLASS = "1206"
UPNP_PAN_CLASS = "1300"
UPNP_LAP_CLASS = "1301"
UPNP_L2CAP_CLASS = "1302"
VIDEO_SOURCE_CLASS = "1303"
VIDEO_SINK_CLASS = "1304"
# Bluetooth Profile Descriptors
SDP_SERVER_PROFILE = ( SDP_SERVER_CLASS, 0x0100)
BROWSE_GRP_DESC_PROFILE = ( BROWSE_GRP_DESC_CLASS, 0x0100)
SERIAL_PORT_PROFILE = ( SERIAL_PORT_CLASS, 0x0100)
LAN_ACCESS_PROFILE = ( LAN_ACCESS_CLASS, 0x0100)
DIALUP_NET_PROFILE = ( DIALUP_NET_CLASS, 0x0100)
IRMC_SYNC_PROFILE = ( IRMC_SYNC_CLASS, 0x0100)
OBEX_OBJPUSH_PROFILE = ( OBEX_OBJPUSH_CLASS, 0x0100)
OBEX_FILETRANS_PROFILE = ( OBEX_FILETRANS_CLASS, 0x0100)
IRMC_SYNC_CMD_PROFILE = ( IRMC_SYNC_CMD_CLASS, 0x0100)
HEADSET_PROFILE = ( HEADSET_CLASS, 0x0100)
CORDLESS_TELEPHONY_PROFILE = ( CORDLESS_TELEPHONY_CLASS, 0x0100)
AUDIO_SOURCE_PROFILE = ( AUDIO_SOURCE_CLASS, 0x0100)
AUDIO_SINK_PROFILE = ( AUDIO_SINK_CLASS, 0x0100)
AV_REMOTE_TARGET_PROFILE = ( AV_REMOTE_TARGET_CLASS, 0x0100)
ADVANCED_AUDIO_PROFILE = ( ADVANCED_AUDIO_CLASS, 0x0100)
AV_REMOTE_PROFILE = ( AV_REMOTE_CLASS, 0x0100)
VIDEO_CONF_PROFILE = ( VIDEO_CONF_CLASS, 0x0100)
INTERCOM_PROFILE = ( INTERCOM_CLASS, 0x0100)
FAX_PROFILE = ( FAX_CLASS, 0x0100)
HEADSET_AGW_PROFILE = ( HEADSET_AGW_CLASS, 0x0100)
WAP_PROFILE = ( WAP_CLASS, 0x0100)
WAP_CLIENT_PROFILE = ( WAP_CLIENT_CLASS, 0x0100)
PANU_PROFILE = ( PANU_CLASS, 0x0100)
NAP_PROFILE = ( NAP_CLASS, 0x0100)
GN_PROFILE = ( GN_CLASS, 0x0100)
DIRECT_PRINTING_PROFILE = ( DIRECT_PRINTING_CLASS, 0x0100)
REFERENCE_PRINTING_PROFILE = ( REFERENCE_PRINTING_CLASS, 0x0100)
IMAGING_PROFILE = ( IMAGING_CLASS, 0x0100)
IMAGING_RESPONDER_PROFILE = ( IMAGING_RESPONDER_CLASS, 0x0100)
IMAGING_ARCHIVE_PROFILE = ( IMAGING_ARCHIVE_CLASS, 0x0100)
IMAGING_REFOBJS_PROFILE = ( IMAGING_REFOBJS_CLASS, 0x0100)
HANDSFREE_PROFILE = ( HANDSFREE_CLASS, 0x0100)
HANDSFREE_AGW_PROFILE = ( HANDSFREE_AGW_CLASS, 0x0100)
DIRECT_PRT_REFOBJS_PROFILE = ( DIRECT_PRT_REFOBJS_CLASS, 0x0100)
REFLECTED_UI_PROFILE = ( REFLECTED_UI_CLASS, 0x0100)
BASIC_PRINTING_PROFILE = ( BASIC_PRINTING_CLASS, 0x0100)
PRINTING_STATUS_PROFILE = ( PRINTING_STATUS_CLASS, 0x0100)
HID_PROFILE = ( HID_CLASS, 0x0100)
HCR_PROFILE = ( HCR_SCAN_CLASS, 0x0100)
HCR_PRINT_PROFILE = ( HCR_PRINT_CLASS, 0x0100)
HCR_SCAN_PROFILE = ( HCR_SCAN_CLASS, 0x0100)
CIP_PROFILE = ( CIP_CLASS, 0x0100)
VIDEO_CONF_GW_PROFILE = ( VIDEO_CONF_GW_CLASS, 0x0100)
UDI_MT_PROFILE = ( UDI_MT_CLASS, 0x0100)
UDI_TA_PROFILE = ( UDI_TA_CLASS, 0x0100)
AV_PROFILE = ( AV_CLASS, 0x0100)
SAP_PROFILE = ( SAP_CLASS, 0x0100)
PNP_INFO_PROFILE = ( PNP_INFO_CLASS, 0x0100)
GENERIC_NETWORKING_PROFILE = ( GENERIC_NETWORKING_CLASS, 0x0100)
GENERIC_FILETRANS_PROFILE = ( GENERIC_FILETRANS_CLASS, 0x0100)
GENERIC_AUDIO_PROFILE = ( GENERIC_AUDIO_CLASS, 0x0100)
GENERIC_TELEPHONY_PROFILE = ( GENERIC_TELEPHONY_CLASS, 0x0100)
UPNP_PROFILE = ( UPNP_CLASS, 0x0100)
UPNP_IP_PROFILE = ( UPNP_IP_CLASS, 0x0100)
UPNP_PAN_PROFILE = ( UPNP_PAN_CLASS, 0x0100)
UPNP_LAP_PROFILE = ( UPNP_LAP_CLASS, 0x0100)
UPNP_L2CAP_PROFILE = ( UPNP_L2CAP_CLASS, 0x0100)
VIDEO_SOURCE_PROFILE = ( VIDEO_SOURCE_CLASS, 0x0100)
VIDEO_SINK_PROFILE = ( VIDEO_SINK_CLASS, 0x0100)
# Universal Service Attribute IDs
SERVICE_RECORD_HANDLE_ATTRID = 0x0000
SERVICE_CLASS_ID_LIST_ATTRID = 0x0001
SERVICE_RECORD_STATE_ATTRID = 0x0002
SERVICE_ID_ATTRID = 0x0003
PROTOCOL_DESCRIPTOR_LIST_ATTRID = 0x0004
BROWSE_GROUP_LIST_ATTRID = 0x0005
LANGUAGE_BASE_ATTRID_LIST_ATTRID = 0x0006
SERVICE_INFO_TIME_TO_LIVE_ATTRID = 0x0007
SERVICE_AVAILABILITY_ATTRID = 0x0008
BLUETOOTH_PROFILE_DESCRIPTOR_LIST_ATTRID = 0x0009
DOCUMENTATION_URL_ATTRID = 0x000a
CLIENT_EXECUTABLE_URL_ATTRID = 0x000b
ICON_URL_ATTRID = 0x000c
SERVICE_NAME_ATTRID = 0x0100
SERVICE_DESCRIPTION_ATTRID = 0x0101
PROVIDER_NAME_ATTRID = 0x0102
# Protocol UUIDs
SDP_UUID = "0001"
UDP_UUID = "0002"
RFCOMM_UUID = "0003"
TCP_UUID = "0004"
TCS_BIN_UUID = "0005"
TCS_AT_UUID = "0006"
OBEX_UUID = "0008"
IP_UUID = "0009"
FTP_UUID = "000a"
HTTP_UUID = "000c"
WSP_UUID = "000e"
BNEP_UUID = "000f"
UPNP_UUID = "0010"
HIDP_UUID = "0011"
HCRP_CTRL_UUID = "0012"
HCRP_DATA_UUID = "0014"
HCRP_NOTE_UUID = "0016"
AVCTP_UUID = "0017"
AVDTP_UUID = "0019"
CMTP_UUID = "001b"
UDI_UUID = "001d"
L2CAP_UUID = "0100"
class BluetoothError (IOError):
pass
def is_valid_address (s):
"""
returns True if address is a valid Bluetooth address
valid address are always strings of the form XX:XX:XX:XX:XX:XX
where X is a hexadecimal character. For example,
01:23:45:67:89:AB is a valid address, but
IN:VA:LI:DA:DD:RE is not
"""
try:
pairs = s.split (":")
if len (pairs) != 6: return False
for b in pairs: int (b, 16)
except:
return False
return True
def is_valid_uuid (uuid):
"""
is_valid_uuid (uuid) -> bool
returns True if uuid is a valid 128-bit UUID.
valid UUIDs are always strings taking one of the following forms:
XXXX
XXXXXXXX
XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
where each X is a hexadecimal digit (case insensitive)
"""
try:
if len (uuid) == 4:
if int (uuid, 16) < 0: return False
elif len (uuid) == 8:
if int (uuid, 16) < 0: return False
elif len (uuid) == 36:
pieces = uuid.split ("-")
if len (pieces) != 5 or \
len (pieces[0]) != 8 or \
len (pieces[1]) != 4 or \
len (pieces[2]) != 4 or \
len (pieces[3]) != 4 or \
len (pieces[4]) != 12:
return False
[ int (p, 16) for p in pieces ]
else:
return False
except ValueError:
return False
except TypeError:
return False
return True
def to_full_uuid (uuid):
"""
converts a short 16-bit or 32-bit reserved UUID to a full 128-bit Bluetooth
UUID.
"""
if not is_valid_uuid (uuid): raise ValueError ("invalid UUID")
if len (uuid) == 4:
return "0000%s-0000-1000-8000-00805F9B34FB" % uuid
elif len (uuid) == 8:
return "%s-0000-1000-8000-00805F9B34FB" % uuid
else:
return uuid
# =============== parsing and constructing raw SDP records ============
def sdp_parse_size_desc (data):
dts = struct.unpack ("B", data[0:1])[0]
dtype, dsizedesc = dts >> 3, dts & 0x7
dstart = 1
if dtype == 0: dsize = 0
elif dsizedesc == 0: dsize = 1
elif dsizedesc == 1: dsize = 2
elif dsizedesc == 2: dsize = 4
elif dsizedesc == 3: dsize = 8
elif dsizedesc == 4: dsize = 16
elif dsizedesc == 5:
dsize = struct.unpack ("B", data[1:2])[0]
dstart += 1
elif dsizedesc == 6:
dsize = struct.unpack ("!H", data[1:3])[0]
dstart += 2
elif dsizedesc == 7:
dsize == struct.unpack ("!I", data[1:5])[0]
dstart += 4
if dtype > 8:
raise ValueError ("Invalid TypeSizeDescriptor byte %s %d, %d" \
% (binascii.hexlify (data[0:1]), dtype, dsizedesc))
return dtype, dsize, dstart
def sdp_parse_uuid (data, size):
if size == 2:
return binascii.hexlify (data)
elif size == 4:
return binascii.hexlify (data)
elif size == 16:
return "%08X-%04X-%04X-%04X-%04X%08X" % struct.unpack ("!IHHHHI", data)
else: return ValueError ("invalid UUID size")
def sdp_parse_int (data, size, signed):
fmts = { 1 : "!b" , 2 : "!h" , 4 : "!i" , 8 : "!q" , 16 : "!qq" }
fmt = fmts[size]
if not signed: fmt = fmt.upper ()
if fmt in [ "!qq", "!QQ" ]:
upp, low = struct.unpack ("!QQ", data)
result = ( upp << 64) | low
if signed:
result=- ((~ (result-1))&0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
return result
else:
return struct.unpack (fmt, data)[0]
def sdp_parse_data_elementSequence (data):
result = []
pos = 0
datalen = len (data)
while pos < datalen:
rtype, rval, consumed = sdp_parse_data_element (data[pos:])
pos += consumed
result.append ( (rtype, rval))
return result
def sdp_parse_data_element (data):
dtype, dsize, dstart = sdp_parse_size_desc (data)
elem = data[dstart:dstart+dsize]
if dtype == 0:
rtype, rval = "Nil", None
elif dtype == 1:
rtype, rval = "UInt%d"% (dsize*8), sdp_parse_int (elem, dsize, False)
elif dtype == 2:
rtype, rval = "SInt%d"% (dsize*8), sdp_parse_int (elem, dsize, True)
elif dtype == 3:
rtype, rval = "UUID", sdp_parse_uuid (elem, dsize)
elif dtype == 4:
rtype, rval = "String", elem
elif dtype == 5:
rtype, rval = "Bool", (struct.unpack ("B", elem)[0] != 0)
elif dtype == 6:
rtype, rval = "ElemSeq", sdp_parse_data_elementSequence (elem)
elif dtype == 7:
rtype, rval = "AltElemSeq", sdp_parse_data_elementSequence (elem)
elif dtype == 8:
rtype, rval = "URL", elem
return rtype, rval, dstart+dsize
def sdp_parse_raw_record (data):
dtype, dsize, dstart = sdp_parse_size_desc (data)
assert dtype == 6
pos = dstart
datalen = len (data)
record = {}
while pos < datalen:
type, attrid, consumed = sdp_parse_data_element (data[pos:])
assert type == "UInt16"
pos += consumed
type, attrval, consumed = sdp_parse_data_element (data[pos:])
pos += consumed
record[attrid] = attrval
return record
def sdp_make_data_element (type, value):
def maketsd (tdesc, sdesc):
return struct.pack ("B", (tdesc << 3) | sdesc)
def maketsdl (tdesc, size):
if size < (1<<8): return struct.pack ("!BB", tdesc << 3 | 5, size)
elif size < (1<<16): return struct.pack ("!BH", tdesc << 3 | 6, size)
else: return struct.pack ("!BI", tdesc << 3 | 7, size)
easyinttypes = { "UInt8" : (1, 0, "!B"), "UInt16" : (1, 1, "!H"),
"UInt32" : (1, 2, "!I"), "UInt64" : (1, 3, "!Q"),
"SInt8" : (2, 0, "!b"), "SInt16" : (2, 1, "!h"),
"SInt32" : (2, 2, "!i"), "SInt64" : (2, 3, "!q"),
}
if type == "Nil":
return maketsd (0, 0)
elif type in easyinttypes:
tdesc, sdesc, fmt = easyinttypes[type]
return maketsd (tdesc, sdesc) + struct.pack (fmt, value)
elif type == "UInt128":
ts = maketsd (1, 4)
upper = ts >> 64
lower = (ts & 0xFFFFFFFFFFFFFFFF)
return ts + struct.pack ("!QQ", upper, lower)
elif type == "SInt128":
ts = maketsd (2, 4)
# FIXME
raise NotImplementedException ("128-bit signed int NYI!")
elif type == "UUID":
if len (value) == 4:
return maketsd (3, 1) + binascii.unhexlify (value)
elif len (value) == 8:
return maketsd (3, 2) + binascii.unhexlify (value)
elif len (value) == 36:
return maketsd (3, 4) + binascii.unhexlify (value.replace ("-",""))
elif type == "String":
return maketsdl (4, len (value)) + str.encode(value)
elif type == "Bool":
return maketsd (5,0) + (value and "\x01" or "\x00")
elif type == "ElemSeq":
packedseq = bytes()
for subtype, subval in value:
nextelem = sdp_make_data_element (subtype, subval)
packedseq = packedseq + nextelem
return maketsdl (6, len (packedseq)) + packedseq
elif type == "AltElemSeq":
packedseq = bytes()
for subtype, subval in value:
packedseq = packedseq + sdp_make_data_element (subtype, subval)
return maketsdl (7, len (packedseq)) + packedseq
elif type == "URL":
return maketsdl (8, len (value)) + value
else:
raise ValueError ("invalid type %s" % type)
pybluez-0.22+really0.22/bluetooth/msbt.py 0000664 0000000 0000000 00000021412 13346112537 0020246 0 ustar 00root root 0000000 0000000 from bluetooth import *
import bluetooth._msbt as bt
bt.initwinsock ()
# ============== SDP service registration and unregistration ============
def discover_devices (duration=8, flush_cache=True, lookup_names=False,
lookup_class=False, device_id=-1):
#this is order of items in C-code
btAddresIndex = 0
namesIndex = 1
classIndex = 2
devices = bt.discover_devices(duration=duration, flush_cache=flush_cache)
ret = list()
for device in devices:
item = [device[btAddresIndex],]
if lookup_names:
item.append(device[namesIndex])
if lookup_class:
item.append(device[classIndex])
if len(item) == 1: # in case of address-only we return string not tuple
ret.append(item[0])
else:
ret.append(tuple(i for i in item))
return ret
def lookup_name (address, timeout=10):
if not is_valid_address (address):
raise ValueError ("Invalid Bluetooth address")
return bt.lookup_name (address)
class BluetoothSocket:
def __init__ (self, proto = RFCOMM, sockfd = None):
if proto not in [ RFCOMM ]:
raise ValueError ("invalid protocol")
if sockfd:
self._sockfd = sockfd
else:
self._sockfd = bt.socket (bt.SOCK_STREAM, bt.BTHPROTO_RFCOMM)
self._proto = proto
# used by advertise_service and stop_advertising
self._sdp_handle = None
self._raw_sdp_record = None
# used to track if in blocking or non-blocking mode (FIONBIO appears
# write only)
self._blocking = True
self._timeout = False
def bind (self, addrport):
if self._proto == RFCOMM:
addr, port = addrport
if port == 0: port = bt.BT_PORT_ANY
bt.bind (self._sockfd, addr, port)
def listen (self, backlog):
bt.listen (self._sockfd, backlog)
def accept (self):
clientfd, addr, port = bt.accept (self._sockfd)
client = BluetoothSocket (self._proto, sockfd=clientfd)
return client, (addr, port)
def connect (self, addrport):
addr, port = addrport
bt.connect (self._sockfd, addr, port)
def send (self, data):
return bt.send (self._sockfd, data)
def recv (self, numbytes):
return bt.recv (self._sockfd, numbytes)
def close (self):
return bt.close (self._sockfd)
def getsockname (self):
return bt.getsockname (self._sockfd)
def setblocking (self, blocking):
bt.setblocking (self._sockfd, blocking)
self._blocking = blocking
def settimeout (self, timeout):
if timeout < 0: raise ValueError ("invalid timeout")
if timeout == 0:
self.setblocking (False)
else:
self.setblocking (True)
bt.settimeout (self._sockfd, timeout)
self._timeout = timeout
def gettimeout (self):
if self._blocking and not self._timeout: return None
return bt.gettimeout (self._sockfd)
def fileno (self):
return self._sockfd
def dup (self):
return BluetoothSocket (self._proto, sockfd=bt.dup (self._sockfd))
def makefile (self):
# TODO
raise Exception("Not yet implemented")
def advertise_service (sock, name, service_id = "", service_classes = [], \
profiles = [], provider = "", description = "", protocols = []):
if service_id != "" and not is_valid_uuid (service_id):
raise ValueError ("invalid UUID specified for service_id")
for uuid in service_classes:
if not is_valid_uuid (uuid):
raise ValueError ("invalid UUID specified in service_classes")
for uuid, version in profiles:
if not is_valid_uuid (uuid) or version < 0 or version > 0xFFFF:
raise ValueError ("Invalid Profile Descriptor")
for uuid in protocols:
if not is_valid_uuid (uuid):
raise ValueError ("invalid UUID specified in protocols")
if sock._raw_sdp_record is not None:
raise IOError ("service already advertised")
avpairs = []
# service UUID
if len (service_id) > 0:
avpairs.append (("UInt16", SERVICE_ID_ATTRID))
avpairs.append (("UUID", service_id))
# service class list
if len (service_classes) > 0:
seq = [ ("UUID", svc_class) for svc_class in service_classes ]
avpairs.append (("UInt16", SERVICE_CLASS_ID_LIST_ATTRID))
avpairs.append (("ElemSeq", seq))
# set protocol and port information
assert sock._proto == RFCOMM
addr, port = sock.getsockname ()
avpairs.append (("UInt16", PROTOCOL_DESCRIPTOR_LIST_ATTRID))
l2cap_pd = ("ElemSeq", (("UUID", L2CAP_UUID),))
rfcomm_pd = ("ElemSeq", (("UUID", RFCOMM_UUID), ("UInt8", port)))
proto_list = [ l2cap_pd, rfcomm_pd ]
for proto_uuid in protocols:
proto_list.append (("ElemSeq", (("UUID", proto_uuid),)))
avpairs.append (("ElemSeq", proto_list))
# make the service publicly browseable
avpairs.append (("UInt16", BROWSE_GROUP_LIST_ATTRID))
avpairs.append (("ElemSeq", (("UUID", PUBLIC_BROWSE_GROUP),)))
# profile descriptor list
if len (profiles) > 0:
seq = [ ("ElemSeq", (("UUID",uuid), ("UInt16",version))) \
for uuid, version in profiles ]
avpairs.append (("UInt16",
BLUETOOTH_PROFILE_DESCRIPTOR_LIST_ATTRID))
avpairs.append (("ElemSeq", seq))
# service name
avpairs.append (("UInt16", SERVICE_NAME_ATTRID))
avpairs.append (("String", name))
# service description
if len (description) > 0:
avpairs.append (("UInt16", SERVICE_DESCRIPTION_ATTRID))
avpairs.append (("String", description))
# service provider
if len (provider) > 0:
avpairs.append (("UInt16", PROVIDER_NAME_ATTRID))
avpairs.append (("String", provider))
sock._raw_sdp_record = sdp_make_data_element ("ElemSeq", avpairs)
# pr = sdp_parse_raw_record (sock._raw_sdp_record)
# for attrid, val in pr.items ():
# print "%5s: %s" % (attrid, val)
# print binascii.hexlify (sock._raw_sdp_record)
# print repr (sock._raw_sdp_record)
sock._sdp_handle = bt.set_service_raw (sock._raw_sdp_record, True)
def stop_advertising (sock):
if sock._raw_sdp_record is None:
raise IOError ("service isn't advertised, " \
"but trying to un-advertise")
bt.set_service_raw (sock._raw_sdp_record, False, sock._sdp_handle)
sock._raw_sdp_record = None
sock._sdp_handle = None
def find_service (name = None, uuid = None, address = None):
if address is not None:
addresses = [ address ]
else:
addresses = discover_devices (lookup_names = False)
results = []
for addr in addresses:
uuidstr = uuid or PUBLIC_BROWSE_GROUP
if not is_valid_uuid (uuidstr): raise ValueError ("invalid UUID")
uuidstr = to_full_uuid (uuidstr)
dresults = bt.find_service (addr, uuidstr)
for dict in dresults:
raw = dict["rawrecord"]
record = sdp_parse_raw_record (raw)
if SERVICE_CLASS_ID_LIST_ATTRID in record:
svc_class_id_list = [ t[1] for t in \
record[SERVICE_CLASS_ID_LIST_ATTRID] ]
dict["service-classes"] = svc_class_id_list
else:
dict["services-classes"] = []
if BLUETOOTH_PROFILE_DESCRIPTOR_LIST_ATTRID in record:
pdl = []
for profile_desc in \
record[BLUETOOTH_PROFILE_DESCRIPTOR_LIST_ATTRID]:
uuidpair, versionpair = profile_desc[1]
pdl.append ((uuidpair[1], versionpair[1]))
dict["profiles"] = pdl
else:
dict["profiles"] = []
dict["provider"] = record.get (PROVIDER_NAME_ATTRID, None)
dict["service-id"] = record.get (SERVICE_ID_ATTRID, None)
# XXX the C version is buggy (retrieves an extra byte or two),
# so get the service name here even though it may have already
# been set
dict["name"] = record.get (SERVICE_NAME_ATTRID, None)
dict["handle"] = record.get (SERVICE_RECORD_HANDLE_ATTRID, None)
# if LANGUAGE_BASE_ATTRID_LIST_ATTRID in record:
# for triple in record[LANGUAGE_BASE_ATTRID_LIST_ATTRID]:
# code_ISO639, encoding, base_offset = triple
#
# if SERVICE_DESCRIPTION_ATTRID in record:
# service_description = record[SERVICE_DESCRIPTION_ATTRID]
if name is None:
results.extend (dresults)
else:
results.extend ([ d for d in dresults if d["name"] == name ])
return results
# =============== DeviceDiscoverer ==================
class DeviceDiscoverer:
def __init__ (self):
raise NotImplementedError
pybluez-0.22+really0.22/bluetooth/osx.py 0000664 0000000 0000000 00000000063 13346112537 0020111 0 ustar 00root root 0000000 0000000 from .btcommon import *
raise NotImplementedError
pybluez-0.22+really0.22/bluetooth/widcomm.py 0000664 0000000 0000000 00000071571 13346112537 0020753 0 ustar 00root root 0000000 0000000 from .btcommon import *
import socket
import struct
import threading
import os
import _widcomm
DEFAULT_MTU = 672
def dbg (*args):
return
sys.stdout.write (*args)
sys.stdout.write ("\n")
def BD_ADDR_to_str (bda):
return "%02X:%02X:%02X:%02X:%02X:%02X" % \
(ord(bda[0]), ord(bda[1]), ord(bda[2]),
ord(bda[3]), ord(bda[4]), ord(bda[5]))
def str_to_BD_ADDR (s):
digits = [ int (c, 16) for c in s.split(":") ]
return struct.pack ("6B", *digits)
class WCInquirer:
DEVST_DOWN = 0
DEVST_UP = 1
DEVST_ERROR = 2
DEVST_UNLOADED = 3
DEVST_RELOADED = 4
def __init__ (self):
self._wcinq = _widcomm._WCInquirer ()
port = self._wcinq.get_sockport ()
self.readsock = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
self.readsock.connect (("127.0.0.1", port))
self._wcinq.accept_client ()
self.recently_discovered = []
self.inquiry_in_progress = False
self.sdp_query_in_progress = False
def fileno ():
return self.readsock.fileno ()
def start_inquiry (self):
self.recently_discovered = []
self.inquiry_in_progress = self._wcinq.start_inquiry ()
def read_msg (self):
intsize = struct.calcsize ("=i")
msg_type = struct.unpack ("=i", self.readsock.recv (intsize))[0]
if msg_type == _widcomm.INQ_DEVICE_RESPONDED:
fmt = "=6s3s248si"
data = self.readsock.recv (struct.calcsize (fmt))
bda, devclass, bdname, connected = struct.unpack (fmt, data)
bdaddr = BD_ADDR_to_str (bda)
bdname = bdname.strip ("\0")
self.recently_discovered.append ((bdaddr, devclass, bdname,
connected))
elif msg_type == _widcomm.INQ_INQUIRY_COMPLETE:
fmt = "=ih"
data = self.readsock.recv (struct.calcsize (fmt))
success, num_responses = struct.unpack (fmt, data)
self.inquiry_in_progress = False
elif msg_type == _widcomm.INQ_DISCOVERY_COMPLETE:
self.sdp_query_in_progress = False
elif msg_type == _widcomm.INQ_STACK_STATUS_CHANGE:
fmt = "=i"
data = self.readsock.recv (struct.calcsize (fmt))
new_status = struct.unpack (fmt, data)[0]
def start_discovery (self, addr, uuid = None):
bd_addr = str_to_BD_ADDR (addr)
if uuid is not None:
self.sdp_query_in_progress = \
self._wcinq.start_discovery (bd_addr, to_full_uuid (uuid))
else:
self.sdp_query_in_progress = \
self._wcinq.start_discovery (bd_addr)
self.sdp_query_in_progress = True
def read_discovery_records (self, addr, uuid = None):
if not is_valid_address (addr):
raise ValueError ("invalid Bluetooth address")
bd_addr = str_to_BD_ADDR (addr)
if uuid is not None:
dbg ("read_discovery_records (%s, %s)" % (addr, uuid))
return self._wcinq.read_discovery_records (bd_addr,
to_full_uuid (uuid))
else:
return self._wcinq.read_discovery_records (bd_addr)
def is_device_ready (self):
return self._wcinq.is_device_ready ()
def get_local_device_address (self):
return self._wcinq.get_local_device_address ()
inquirer = WCInquirer ()
def discover_devices (duration=8, flush_cache=True, lookup_names=False, lookup_class=False):
inquirer.start_inquiry ()
while inquirer.inquiry_in_progress:
inquirer.read_msg ()
discovered = inquirer.recently_discovered[:]
if not lookup_names and not lookup_class:
return [ tup[0] for tup in discovered ]
if lookup_names and not lookup_class:
result = []
for bdaddr, devClass, bdName, bConnected in discovered:
if bdName:
result.append ((bdaddr, bdName))
else:
result.append ((bdAddr, None))
return result
if not lookup_names and lookup_class:
result = []
for bdaddr, devClass, bdName, bConnected in discovered:
hex = "%02X%02X%02X" % (ord(devClass[0]), ord(devClass[1]), ord(devClass[2]))
devClass = int(hex, 16)
result.append ((bdAddr, devClass))
return result
if lookup_names and lookup_class:
result = []
for bdaddr, devClass, bdName, bConnected in discovered:
hex = "%02X%02X%02X" % (ord(devClass[0]), ord(devClass[1]), ord(devClass[2]))
devClass = int(hex, 16)
if bdName:
result.append ((bdaddr, bdName, devClass))
else:
result.append ((bdAddr, None, devClass))
return result
def lookup_name (address, timeout=10):
discover_devices ()
for bdaddr, devClass, bdName, bConnected in inquirer.recently_discovered:
if bdaddr == address:
return bdName
def advertise_service (sock, name, service_id = "", service_classes = [], \
profiles = [], provider = "", description = "", protocols = []):
sock._advertise_service (name, service_id, service_classes,
profiles, provider, description, protocols)
def stop_advertising (sock):
sock._stop_advertising ()
def find_service (name = None, uuid = None, address = None):
if address:
if address == "localhost": raise NotImplementedError
if not is_valid_address (address):
raise ValueError ("invalid Bluetooth address")
addresses = [ address ]
else:
addresses = discover_devices ()
if uuid and not is_valid_uuid (uuid):
raise ValueError ("invalid uuid ", uuid)
results = []
for addr in addresses:
inquirer.start_discovery (addr, uuid)
while inquirer.sdp_query_in_progress:
inquirer.read_msg ()
results.extend (inquirer.read_discovery_records (addr, uuid))
return results
def _port_return_code_to_str (code):
k = { _widcomm.RFCOMM_SUCCESS : "Success",
_widcomm.RFCOMM_ALREADY_OPENED : "Port already opened",
_widcomm.RFCOMM_NOT_OPENED : "Connection not open",
_widcomm.RFCOMM_HANDLE_ERROR: "This error should never occur " \
"(HANDLE_ERROR) and is a stack bug",
_widcomm.RFCOMM_LINE_ERR: "Line error",
_widcomm.RFCOMM_START_FAILED: "Connection attempt failed",
_widcomm.RFCOMM_PAR_NEG_FAILED: "Parameter negotion (MTU) failed",
_widcomm.RFCOMM_PORT_NEG_FAILED: "Port negotiation failed",
_widcomm.RFCOMM_PEER_CONNECTION_FAILED: "Connection ended by remote "\
"side",
_widcomm.RFCOMM_PEER_TIMEOUT: "Timeout by remote side",
_widcomm.RFCOMM_INVALID_PARAMETER: "Invalid parameter",
_widcomm.RFCOMM_UNKNOWN_ERROR: "Unknown error" }
if code in k:
return k[code]
else:
return "Invalid RFCOMM error code %s" % str (code)
def _port_ev_code_to_str (code):
d = { _widcomm.PORT_EV_RXFLAG : "Received certain character",
_widcomm.PORT_EV_TXEMPTY : "Transmit Queue Empty",
_widcomm.PORT_EV_CTS : "CTS changed state",
_widcomm.PORT_EV_DSR : "DSR changed state",
_widcomm.PORT_EV_RLSD : "RLSD changed state",
_widcomm.PORT_EV_BREAK : "BREAK received",
_widcomm.PORT_EV_ERR : "Line status error occurred",
_widcomm.PORT_EV_RING : "Ring signal detected",
_widcomm.PORT_EV_CTSS : "CTS state",
_widcomm.PORT_EV_DSRS : "DSR state",
_widcomm.PORT_EV_RLSDS : "RLSD state",
_widcomm.PORT_EV_OVERRUN : "Receiver buffer overrun",
_widcomm.PORT_EV_TXCHAR : "Any character transmitted",
_widcomm.PORT_EV_CONNECTED : "RFCOMM connection established",
_widcomm.PORT_EV_CONNECT_ERR : "Was not able to establish " \
"connection or disconnected",
_widcomm.PORT_EV_FC : "Flow control enabled flag changed by remote",
_widcomm.PORT_EV_FCS : "Flow control status true = enabled" }
result = []
for k, v in list(d.items ()):
if code & k:
result.append (v)
if len (result) == 0:
return "Invalid event code %d" % code
else:
return "\n".join (result)
def _sdp_checkraise (code):
if code == _widcomm.SDP_OK: return
elif code == _widcomm.SDP_COULD_NOT_ADD_RECORD:
raise BluetoothError ("Could not add SDP record")
elif code == _widcomm.SDP_INVALID_RECORD:
raise BluetoothError ("Invalid SDP record")
elif code == _widcomm.SDP_INVALID_PARAMETERS:
raise BluetoothError ("SDP: invalid parameters")
raise RuntimeError ("unknown SDP status code %s" % code)
class BluetoothSocket:
def __init__ (self, proto = RFCOMM, _sockdata = None):
if not proto in [ RFCOMM, L2CAP ]:
raise ValueError ("invalid protocol")
self.proto = proto
if proto == RFCOMM:
self.bind = self.rfcomm_bind
self.listen = self.rfcomm_listen
self.accept = self.rfcomm_accept
self.connect = self.rfcomm_connect
self.send = self.rfcomm_send
self.recv = self.rfcomm_recv
self.close = self.rfcomm_close
self.getsockname = self.rfcomm_getsockname
self.setblocking = self.rfcomm_setblocking
self.settimeout = self.rfcomm_settimeout
self.gettimeout = self.rfcomm_gettimeout
self.dup = self.rfcomm_dup
self.makefile = self.rfcomm_makefile
self.fileno = self.rfcomm_fileno
self.__make_cobjects = self.__rfcomm_make_cobjects
self._advertise_service = self.__rfcomm_advertise_service
if _sockdata:
self._wc, self._if, self.readsock = _sockdata
else:
self.__make_cobjects ()
self.connected = self._wc.is_connected ()
elif proto == L2CAP:
dbg ("creating l2cap socket")
self.bind = self.l2cap_bind
self.listen = self.l2cap_listen
self.accept = self.l2cap_accept
self.connect = self.l2cap_connect
self.send = self.l2cap_send
self.recv = self.l2cap_recv
self.close = self.l2cap_close
self.getsockname = self.l2cap_getsockname
self.setblocking = self.l2cap_setblocking
self.settimeout = self.l2cap_settimeout
self.gettimeout = self.l2cap_gettimeout
self.dup = self.l2cap_dup
self.makefile = self.l2cap_makefile
self.fileno = self.l2cap_fileno
self.__make_cobjects = self.__l2cap_make_cobjects
self._advertise_service = self.__l2cap_advertise_service
if _sockdata:
self._wc, self._if, self.readsock = _sockdata
self.connected = True
else:
self.__make_cobjects ()
self.connected = False
else:
raise NotImplementedError ()
self.nonblocking = False
self.connecting = False
self.listening = False
self.bound = False
self.received_data = []
self.last_event_code = None
self.port = 0
self._sdpservice = None
def _stop_advertising (self):
if not self._sdpservice:
raise BluetoothError ("not advertising any services")
self._sdpservice = None
def __rfcomm_make_cobjects (self):
self._wc = _widcomm._WCRfCommPort ()
self._if = _widcomm._WCRfCommIf ()
self.readsock = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
self.readsock.connect (("127.0.0.1", self._wc.get_sockport ()))
self._wc.accept_client ()
def rfcomm_read_msg (self):
intsize = struct.calcsize ("=i")
msg_type_data = self.readsock.recv (intsize)
msg_type = struct.unpack ("=i", msg_type_data)[0]
if msg_type == _widcomm.RFCOMM_DATA_RECEIVED:
datalen_fmt = "=i"
datalen_data = self.readsock.recv (struct.calcsize (datalen_fmt))
datalen = struct.unpack (datalen_fmt, datalen_data)[0]
self.received_data.append (self.readsock.recv (datalen))
elif msg_type == _widcomm.RFCOMM_EVENT_RECEIVED:
fmt = "=I"
data = self.readsock.recv (struct.calcsize (fmt))
code = struct.unpack (fmt, data)[0]
dbg ("event %X received" % code)
if code & _widcomm.PORT_EV_CONNECTED:
self.connecting = False
self.listening = False
self.connected = True
if code & _widcomm.PORT_EV_CONNECT_ERR:
self.connecting = False
self.listening = False
self.connected = False
raise BluetoothError ("Connection failed")
if code & _widcomm.PORT_EV_RXFLAG:
dbg ("Rx flag")
if code & _widcomm.PORT_EV_TXEMPTY:
dbg ("Tx queue empty")
if code & _widcomm.PORT_EV_CTS:
dbg ("CTS changed state")
if code & _widcomm.PORT_EV_DSR:
dbg ("DSR changed state")
if code & _widcomm.PORT_EV_RLSD:
dbg ("RLSD changed state")
if code & _widcomm.PORT_EV_BREAK:
dbg ("BREAK received")
if code & _widcomm.PORT_EV_ERR:
dbg ("Line status error")
if code & _widcomm.PORT_EV_RING:
dbg ("Ring")
if code & _widcomm.PORT_EV_CTSS:
dbg ("CTS state")
if code & _widcomm.PORT_EV_DSRS:
dbg ("DSR state")
if code & _widcomm.PORT_EV_RLSDS:
dbg ("RLSD state")
if code & _widcomm.PORT_EV_OVERRUN:
dbg ("Receive buffer overrun")
if code & _widcomm.PORT_EV_TXCHAR:
dbg ("Data transmitted")
if code & _widcomm.PORT_EV_FC:
dbg ("Flow control changed by remote")
if code & _widcomm.PORT_EV_FCS:
dbg ("Flow control status true = enabled")
self.last_event_code = code
def rfcomm_bind (self, addrport):
addr, port = addrport
if len (addr):
raise ValueError ("Widcomm stack can't bind to " \
"user-specified adapter")
result = self._if.assign_scn_value (RFCOMM_UUID, port)
if not result:
raise BluetoothError ("unable to bind to port")
self.bound = True
self.port = self._if.get_scn ()
def rfcomm_listen (self, backlog):
if self.connected:
raise BluetoothError ("already connected")
if self.listening:
raise BluetoothError ("already listening/connecting")
if backlog != 1:
raise ValueError ("Widcomm stack requires backlog == 1")
port = self._if.get_scn ()
self._if.set_security_level ("", _widcomm.BTM_SEC_NONE, True)
if not port:
raise BluetoothError ("not bound to a port")
result = self._wc.open_server (port, DEFAULT_MTU)
if result != _widcomm.RFCOMM_SUCCESS:
raise BluetoothError (_port_return_code_to_str (result))
self.listening = True
def rfcomm_accept (self):
if self.connected:
raise BluetoothError ("already connected")
while self.listening and not self.connected:
dbg ("waiting for connection")
self.rfcomm_read_msg ()
if self.connected:
port = self._if.get_scn ()
client_bdaddr = BD_ADDR_to_str (self._wc.is_connected ())
# XXX widcomm API doesn't provide a way to determine the RFCOMM
# channel number of the client
client_port = 0
# create a new socket object and give it ownership of the
# wrapped C++ objects, since those are the ones actually connected
_sockdata = self._wc, self._if, self.readsock
clientsock = BluetoothSocket (RFCOMM, _sockdata)
# now create new C++ objects
self.__rfcomm_make_cobjects ()
# self.bind (("", port))
# self.listen (1)
return clientsock, (client_bdaddr, client_port)
def rfcomm_connect (self, addrport):
addr, port = addrport
dbg ("connecting to %s port %d" % (addr, port))
if not is_valid_address (addr):
raise ValueError ("invalid address %s" % addr)
self._if.assign_scn_value (RFCOMM_UUID, port)
self._if.set_security_level ("", _widcomm.BTM_SEC_NONE, False)
result = self._wc.open_client (port, str_to_BD_ADDR (addr), DEFAULT_MTU)
if result != _widcomm.RFCOMM_SUCCESS:
raise BluetoothError (_port_return_code_to_str (result))
self.connecting = True
while self.connecting:
self.rfcomm_read_msg ()
if not self._wc.is_connected ():
raise BluetoothError ("connection failed")
def rfcomm_send (self, data):
dbg ("sending: [%s]" % data)
status, written = self._wc.write (data)
if status == _widcomm.RFCOMM_SUCCESS:
dbg ("sent okay")
return written
else:
raise BluetoothError (_port_return_code_to_str (status))
def rfcomm_recv (self, numbytes):
if self.nonblocking and not self.received_data:
# XXX are we supposed to raise an exception, or just return None?
return None
while not self.received_data and self._wc.is_connected ():
self.rfcomm_read_msg ()
if self.received_data:
data = self.received_data.pop (0)
if len(data) > numbytes:
self.received_data.insert (0, data[numbytes:])
return data[:numbytes]
else:
return data
def rfcomm_close (self):
self._wc.close ()
self._wc = None
self.bound = False
self.connecting = False
self.listening = False
self.connected = False
# return bt.close (self._sockfd)
def rfcomm_getsockname (self):
if not self.bound:
raise BluetoothError ("Socket not bound")
addr = inquirer.get_local_device_address ()
port = self._if.get_scn ()
return addr, port
def rfcomm_setblocking (self, blocking):
self.nonblocking = not blocking
self.readsock.setblocking (blocking)
def rfcomm_settimeout (self, timeout):
raise NotImplementedError
pass
# if timeout < 0: raise ValueError ("invalid timeout")
#
# if timeout == 0:
# self.setblocking (False)
# else:
# self.setblocking (True)
# # XXX this doesn't look correct
# timeout = 0 # winsock timeout still needs to be set 0
#
# s = bt.settimeout (self._sockfd, timeout)
# self._timeout = timeout
def rfcomm_gettimeout (self):
raise NotImplementedError
# if self._blocking and not self._timeout: return None
# return bt.gettimeout (self._sockfd)
def rfcomm_fileno (self):
return self.readsock.fileno ()
def rfcomm_dup (self):
raise NotImplementedError
def rfcomm_makefile (self):
raise NotImplementedError
def __rfcomm_advertise_service (self, name, service_id,
service_classes, profiles, provider, description,
protocols):
if self._sdpservice is not None:
raise BluetoothError ("Service already advertised")
if not self.listening:
raise BluetoothError ("Socket must be listening before advertised")
if protocols:
raise NotImplementedError ("extra protocols not yet supported in Widcomm stack")
self._sdpservice = _widcomm._WCSdpService ()
if service_classes:
service_classes = [ to_full_uuid (s) for s in service_classes ]
_sdp_checkraise (self._sdpservice.add_service_class_id_list ( \
service_classes))
# self._if.set_security_level (name, _widcomm.BTM_SEC_NONE, True)
_sdp_checkraise (self._sdpservice.add_rfcomm_protocol_descriptor ( \
self.port))
if profiles:
for uuid, version in profiles:
uuid = to_full_uuid (uuid)
_sdp_checkraise (self._sdpservice.add_profile_descriptor_list (\
uuid, version))
_sdp_checkraise (self._sdpservice.add_service_name (name))
_sdp_checkraise (self._sdpservice.make_public_browseable ())
def __l2cap_make_cobjects (self):
dbg ("__l2cap_make_cobjects")
self._wc = _widcomm._WCL2CapConn ()
self._if = _widcomm._WCL2CapIf ()
self.readsock = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
self.readsock.connect (("127.0.0.1", self._wc.get_sockport ()))
self._wc.accept_client ()
def l2cap_read_msg (self):
intsize = struct.calcsize ("=i")
msg_type_data = self.readsock.recv (intsize)
msg_type = struct.unpack ("=i", msg_type_data)[0]
if msg_type == _widcomm.L2CAP_DATA_RECEIVED:
datalen_fmt = "=i"
datalen_data = self.readsock.recv (struct.calcsize (datalen_fmt))
datalen = struct.unpack (datalen_fmt, datalen_data)[0]
self.received_data.append (self.readsock.recv (datalen))
elif msg_type == _widcomm.L2CAP_INCOMING_CONNECTION:
result = self._wc.accept ()
if not result: raise BluetoothError ("accept() failed")
elif msg_type == _widcomm.L2CAP_REMOTE_DISCONNECTED:
dbg ("L2CAP_REMOTE_DISCONNECTED")
self.connecting = False
self.listening = False
self.connected = False
elif msg_type == _widcomm.L2CAP_CONNECTED:
self.connecting = False
self.listening = False
self.connected = True
# elif msg_type == _widcomm.PORT_EV_CONNECT_ERR:
# self.connecting = False
# self.listening = False
# raise BluetoothError ("Connection failed")
def l2cap_bind (self, addrport):
dbg ("l2cap_bind %s" % str(addrport))
addr, port = addrport
if len (addr):
raise ValueError ("Widcomm stack can't bind to " \
"user-specified adapter")
result = self._if.assign_psm_value (L2CAP_UUID, port)
if not result:
raise BluetoothError ("unable to bind to port")
self.bound = True
self.port = self._if.get_psm ()
result = self._if.register ()
if not result:
raise BluetoothError ("register() failed")
def l2cap_listen (self, backlog):
dbg ("l2cap_listen %s" % backlog)
if self.connected:
raise BluetoothError ("already connected")
if self.listening:
raise BluetoothError ("already listening/connecting")
if backlog != 1:
raise ValueError ("Widcomm stack requires backlog == 1")
port = self._if.get_psm ()
self._if.set_security_level ("", _widcomm.BTM_SEC_NONE, True)
if not port:
raise BluetoothError ("not bound to a port")
result = self._wc.listen (self._if)
if not result:
raise BluetoothError ("listen() failed. don't know why")
self.listening = True
def l2cap_accept (self):
dbg ("l2cap_accept")
if self.connected:
raise BluetoothError ("already connected")
while self.listening and not self.connected:
dbg ("waiting for connection")
self.l2cap_read_msg ()
if self.connected:
port = self._if.get_psm ()
client_bdaddr = BD_ADDR_to_str (self._wc.remote_bd_addr ())
# XXX widcomm API doesn't provide a way to determine the L2CAP
# PSM of the client
client_port = 0
# create a new socket object and give it ownership of the
# wrapped C++ objects, since those are the ones actually connected
_sockdata = self._wc, self._if, self.readsock
clientsock = BluetoothSocket (L2CAP, _sockdata)
# now create new C++ objects
self.__l2cap_make_cobjects ()
# self.bind (("", port))
# self.listen (1)
return clientsock, (client_bdaddr, client_port)
def l2cap_connect (self, addrport):
addr, port = addrport
dbg ("connecting to %s port %d" % (addr, port))
if not is_valid_address (addr):
raise ValueError ("invalid address %s" % addr)
if not self._if.assign_psm_value (L2CAP_UUID, port):
raise BluetoothError ("Failed to assign PSM %d" % port)
if not self._if.set_security_level ("", _widcomm.BTM_SEC_NONE, False):
raise BluetoothError ("Failed to set security level")
if not self._if.register ():
raise BluetoothError ("Failed to register PSM")
self.connecting = True
if not self._wc.connect (self._if, str_to_BD_ADDR (addr)):
raise BluetoothError ("Connect failed")
while self.connecting:
self.l2cap_read_msg ()
if not self.connected:
raise BluetoothError ("connection failed")
def l2cap_send (self, data):
dbg ("sending: [%s]" % data)
status, written = self._wc.write (data)
if status:
dbg ("sent okay")
return written
else:
raise BluetoothError (_port_return_code_to_str (status))
def l2cap_recv (self, numbytes):
if self.nonblocking and not self.received_data:
# XXX are we supposed to raise an exception, or just return None?
return None
while not self.received_data and self.connected:
self.l2cap_read_msg ()
if self.received_data:
data = self.received_data.pop (0)
if len(data) > numbytes:
self.received_data.insert (0, data[numbytes:])
return data[:numbytes]
else:
return data
def l2cap_close (self):
self._wc.disconnect ()
self._if.deregister ()
self._wc = None
self.bound = False
self.connecting = False
self.listening = False
self.connected = False
# return bt.close (self._sockfd)
def l2cap_getsockname (self):
if not self.bound:
raise BluetoothError ("Socket not bound")
addr = inquirer.get_local_device_address ()
port = self._if.get_psm ()
return addr, port
def l2cap_setblocking (self, blocking):
self.nonblocking = not blocking
self.readsock.setblocking (blocking)
def l2cap_settimeout (self, timeout):
raise NotImplementedError
# if timeout < 0: raise ValueError ("invalid timeout")
#
# if timeout == 0:
# self.setblocking (False)
# else:
# self.setblocking (True)
# # XXX this doesn't look correct
# timeout = 0 # winsock timeout still needs to be set 0
#
# s = bt.settimeout (self._sockfd, timeout)
# self._timeout = timeout
def l2cap_gettimeout (self):
raise NotImplementedError
# if self._blocking and not self._timeout: return None
# return bt.gettimeout (self._sockfd)
def l2cap_fileno (self):
return self.readsock.fileno ()
def l2cap_dup (self):
raise NotImplementedError
# return BluetoothSocket (self._proto, sockfd=bt.dup (self._sockfd))
def l2cap_makefile (self):
raise NotImplementedError
def __l2cap_advertise_service (self, name, service_id,
service_classes, profiles, provider, description,
protocols):
if self._sdpservice is not None:
raise BluetoothError ("Service already advertised")
if not self.listening:
raise BluetoothError ("Socket must be listening before advertised")
if protocols:
raise NotImplementedError ("extra protocols not yet supported in Widcomm stack")
self._sdpservice = _widcomm._WCSdpService ()
if service_classes:
service_classes = [ to_full_uuid (s) for s in service_classes ]
_sdp_checkraise (self._sdpservice.add_service_class_id_list ( \
service_classes))
_sdp_checkraise (self._sdpservice.add_l2cap_protocol_descriptor ( \
self.port))
if profiles:
for uuid, version in profiles:
uuid = to_full_uuid (uuid)
_sdp_checkraise (self._sdpservice.add_profile_descriptor_list (\
uuid, version))
_sdp_checkraise (self._sdpservice.add_service_name (name))
_sdp_checkraise (self._sdpservice.make_public_browseable ())
class DeviceDiscoverer:
def __init__ (self):
raise NotImplementedError
pybluez-0.22+really0.22/bluez/ 0000775 0000000 0000000 00000000000 13346112537 0016043 5 ustar 00root root 0000000 0000000 pybluez-0.22+really0.22/bluez/btmodule.c 0000664 0000000 0000000 00000270351 13346112537 0020032 0 ustar 00root root 0000000 0000000 /*
This module provides an interface to bluetooth. A great deal of the code is
taken from the pyaffix project.
- there are three kinds of bluetooth addresses used here
HCI address is a single int specifying the device id
L2CAP address is a pair (host, port)
RFCOMM address is a pair (host, channel)
SCO address is just a host
the host part of the address is always a string of the form "XX:XX:XX:XX:XX"
Local naming conventions:
- names starting with sock_ are socket object methods
- names starting with bt_ are module-level functions
*/
#include "btmodule.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "btsdp.h"
/* Socket object documentation */
PyDoc_STRVAR(sock_doc,
"BluetoothSocket(proto=RFCOMM) -> bluetooth socket object\n\
\n\
Open a socket of the given protocol. proto must be one of\n\
HCI, L2CAP, RFCOMM, or SCO. SCO sockets have\n\
not been tested at all yet.\n\
\n\
A BluetoothSocket object represents one endpoint of a bluetooth connection.\n\
\n\
Methods of BluetoothSocket objects (keyword arguments not allowed):\n\
\n\
accept() -- accept a connection, returning new socket and client address\n\
bind(addr) -- bind the socket to a local address\n\
close() -- close the socket\n\
connect(addr) -- connect the socket to a remote address\n\
connect_ex(addr) -- connect, return an error code instead of an exception\n\
dup() -- return a new socket object identical to the current one\n\
fileno() -- return underlying file descriptor\n\
getpeername() -- return remote address\n\
getsockname() -- return local address\n\
getsockopt(level, optname[, buflen]) -- get socket options\n\
gettimeout() -- return timeout or None\n\
listen(n) -- start listening for incoming connections\n\
makefile([mode, [bufsize]]) -- return a file object for the socket\n\
recv(buflen[, flags]) -- receive data\n\
recvfrom(buflen[, flags]) -- receive data and sender's address\n\
sendall(data[, flags]) -- send all data\n\
send(data[, flags]) -- send data, may not send all of it\n\
sendto(data[, flags], addr) -- send data to a given address\n\
setblocking(0 | 1) -- set or clear the blocking I/O flag\n\
setsockopt(level, optname, value) -- set socket options\n\
settimeout(None | float) -- set or clear the timeout\n\
shutdown(how) -- shut down traffic in one or both directions");
/* Global variable holding the exception type for errors detected
by this module (but not argument type or memory errors, etc.). */
PyObject *bluetooth_error;
static PyObject *socket_timeout;
/* A forward reference to the socket type object.
The sock_type variable contains pointers to various functions,
some of which call new_sockobject(), which uses sock_type, so
there has to be a circular reference. */
PyTypeObject sock_type;
/* Convenience function to raise an error according to errno
and return a NULL pointer from a function. */
PyObject *
set_error(void)
{
return PyErr_SetFromErrno(bluetooth_error);
}
/* Function to perform the setting of socket blocking mode
internally. block = (1 | 0). */
static int
internal_setblocking(PySocketSockObject *s, int block)
{
int delay_flag;
Py_BEGIN_ALLOW_THREADS
delay_flag = fcntl(s->sock_fd, F_GETFL, 0);
if (block)
delay_flag &= (~O_NONBLOCK);
else
delay_flag |= O_NONBLOCK;
fcntl(s->sock_fd, F_SETFL, delay_flag);
Py_END_ALLOW_THREADS
/* Since these don't return anything */
return 1;
}
/* Do a select() on the socket, if necessary (sock_timeout > 0).
The argument writing indicates the direction.
This does not raise an exception; we'll let our caller do that
after they've reacquired the interpreter lock.
Returns 1 on timeout, 0 otherwise. */
static int
internal_select(PySocketSockObject *s, int writing)
{
fd_set fds;
struct timeval tv;
int n;
/* Nothing to do unless we're in timeout mode (not non-blocking) */
if (s->sock_timeout <= 0.0)
return 0;
/* Guard against closed socket */
if (s->sock_fd < 0)
return 0;
/* Construct the arguments to select */
tv.tv_sec = (int)s->sock_timeout;
tv.tv_usec = (int)((s->sock_timeout - tv.tv_sec) * 1e6);
FD_ZERO(&fds);
FD_SET(s->sock_fd, &fds);
/* See if the socket is ready */
if (writing)
n = select(s->sock_fd+1, NULL, &fds, NULL, &tv);
else
n = select(s->sock_fd+1, &fds, NULL, NULL, &tv);
if (n == 0)
return 1;
return 0;
}
/* Initialize a new socket object. */
static double defaulttimeout = -1.0; /* Default timeout for new sockets */
static void
init_sockobject(PySocketSockObject *s,
int fd, int family, int type, int proto)
{
s->sock_fd = fd;
s->sock_family = family;
s->sock_type = type;
s->sock_proto = proto;
s->sock_timeout = defaulttimeout;
s->errorhandler = &set_error;
if (defaulttimeout >= 0.0)
internal_setblocking(s, 0);
}
/* Create a new socket object.
This just creates the object and initializes it.
If the creation fails, return NULL and set an exception (implicit
in NEWOBJ()). */
static PySocketSockObject *
new_sockobject(int fd, int family, int type, int proto)
{
PySocketSockObject *s;
s = (PySocketSockObject *)
PyType_GenericNew(&sock_type, NULL, NULL);
if (s != NULL)
init_sockobject(s, fd, family, type, proto);
return s;
}
/* Create an object representing the given socket address,
suitable for passing it back to bind(), connect() etc.
The family field of the sockaddr structure is inspected
to determine what kind of address it really is. */
/*ARGSUSED*/
static PyObject *
makesockaddr(PySocketSockObject *s, struct sockaddr *addr, int addrlen)
{
if (addrlen == 0) {
/* No address -- may be recvfrom() from known socket */
Py_INCREF(Py_None);
return Py_None;
} else {
char ba_name[18];
switch(s->sock_proto) {
case BTPROTO_HCI:
{
return Py_BuildValue("H",
((struct sockaddr_hci*)(addr))->hci_dev );
}
case BTPROTO_L2CAP:
{
struct sockaddr_l2 *a = (struct sockaddr_l2*)addr;
ba2str( &a->l2_bdaddr, ba_name );
return Py_BuildValue("sH", ba_name, btohs(a->l2_psm) );
}
case BTPROTO_RFCOMM:
{
struct sockaddr_rc *a = (struct sockaddr_rc*)addr;
ba2str( &a->rc_bdaddr, ba_name );
return Py_BuildValue("sB", ba_name, a->rc_channel );
}
case BTPROTO_SCO:
{
struct sockaddr_sco *a = (struct sockaddr_sco*)addr;
ba2str( &a->sco_bdaddr, ba_name );
return Py_BuildValue("s", ba_name);
}
default:
PyErr_SetString(bluetooth_error,
"getsockaddrarg: unknown Bluetooth protocol");
return 0;
}
}
}
/* Parse a socket address argument according to the socket object's
address family. Return 1 if the address was in the proper format,
0 of not. The address is returned through addr_ret, its length
through len_ret. */
static int
getsockaddrarg(PySocketSockObject *s, PyObject *args,
struct sockaddr *addr_ret, int *len_ret)
{
memset(addr_ret, 0, sizeof(struct sockaddr));
addr_ret->sa_family = AF_BLUETOOTH;
switch( s->sock_proto )
{
case BTPROTO_HCI:
{
struct sockaddr_hci *addr = (struct sockaddr_hci*) addr_ret;
if ( !PyArg_ParseTuple(args, "H", &addr->hci_dev) ) {
return 0;
}
*len_ret = sizeof(struct sockaddr_hci);
return 1;
}
case BTPROTO_L2CAP:
{
struct sockaddr_l2* addr = (struct sockaddr_l2*) addr_ret;
char *ba_name = 0;
if ( !PyArg_ParseTuple(args, "sH", &ba_name, &addr->l2_psm) )
{
return 0;
}
str2ba( ba_name, &addr->l2_bdaddr );
// check for a valid PSM
if( ! ( 0x1 & addr->l2_psm ) ) {
PyErr_SetString( PyExc_ValueError, "Invalid PSM");
return 0;
}
addr->l2_psm = htobs(addr->l2_psm);
*len_ret = sizeof *addr;
return 1;
}
case BTPROTO_RFCOMM:
{
struct sockaddr_rc *addr = (struct sockaddr_rc*) addr_ret;
char *ba_name = 0;
if( !PyArg_ParseTuple(args, "sB", &ba_name, &addr->rc_channel) )
{
return 0;
}
str2ba( ba_name, &addr->rc_bdaddr );
*len_ret = sizeof *addr;
return 1;
}
case BTPROTO_SCO:
{
struct sockaddr_sco *addr = (struct sockaddr_sco*) addr_ret;
char *ba_name = 0;
if( !PyArg_ParseTuple(args, "s", &ba_name) )
{
return 0;
}
str2ba( ba_name, &addr->sco_bdaddr);
*len_ret = sizeof *addr;
return 1;
}
default:
{
PyErr_SetString(bluetooth_error,
"getsockaddrarg: unknown Bluetooth protocol");
return 0;
}
}
}
/* Get the address length according to the socket object's address family.
Return 1 if the family is known, 0 otherwise. The length is returned
through len_ret. */
int
getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret)
{
switch(s->sock_proto)
{
case BTPROTO_L2CAP:
*len_ret = sizeof (struct sockaddr_l2);
return 1;
case BTPROTO_RFCOMM:
*len_ret = sizeof (struct sockaddr_rc);
return 1;
case BTPROTO_SCO:
*len_ret = sizeof (struct sockaddr_sco);
return 1;
case BTPROTO_HCI:
*len_ret = sizeof (struct sockaddr_hci);
return 1;
default:
PyErr_SetString(bluetooth_error,
"getsockaddrlen: unknown bluetooth protocol");
return 0;
}
}
int str2uuid( const char *uuid_str, uuid_t *uuid )
{
uint32_t uuid_int[4];
char *endptr;
if( strlen( uuid_str ) == 36 ) {
// Parse uuid128 standard format: 12345678-9012-3456-7890-123456789012
char buf[9] = { 0 };
if( uuid_str[8] != '-' && uuid_str[13] != '-' &&
uuid_str[18] != '-' && uuid_str[23] != '-' ) {
return 0;
}
// first 8-bytes
strncpy(buf, uuid_str, 8);
uuid_int[0] = htonl( strtoul( buf, &endptr, 16 ) );
if( endptr != buf + 8 ) return 0;
// second 8-bytes
strncpy(buf, uuid_str+9, 4);
strncpy(buf+4, uuid_str+14, 4);
uuid_int[1] = htonl( strtoul( buf, &endptr, 16 ) );
if( endptr != buf + 8 ) return 0;
// third 8-bytes
strncpy(buf, uuid_str+19, 4);
strncpy(buf+4, uuid_str+24, 4);
uuid_int[2] = htonl( strtoul( buf, &endptr, 16 ) );
if( endptr != buf + 8 ) return 0;
// fourth 8-bytes
strncpy(buf, uuid_str+28, 8);
uuid_int[3] = htonl( strtoul( buf, &endptr, 16 ) );
if( endptr != buf + 8 ) return 0;
if( uuid != NULL ) sdp_uuid128_create( uuid, uuid_int );
} else if ( strlen( uuid_str ) == 8 ) {
// 32-bit reserved UUID
uint32_t i = strtoul( uuid_str, &endptr, 16 );
if( endptr != uuid_str + 8 ) return 0;
if( uuid != NULL ) sdp_uuid32_create( uuid, i );
} else if( strlen( uuid_str ) == 4 ) {
// 16-bit reserved UUID
int i = strtol( uuid_str, &endptr, 16 );
if( endptr != uuid_str + 4 ) return 0;
if( uuid != NULL ) sdp_uuid16_create( uuid, i );
} else {
return 0;
}
return 1;
}
int pyunicode2uuid( PyObject *item, uuid_t *uuid )
{
#if PY_MAJOR_VERSION >= 3
PyObject* ascii = PyUnicode_AsASCIIString( item );
int ret = str2uuid( PyBytes_AsString( ascii ), uuid );
Py_XDECREF( ascii );
return ret;
#else
return str2uuid( PyString_AsString( item ), NULL );
#endif
}
void uuid2str( const uuid_t *uuid, char *dest )
{
if( uuid->type == SDP_UUID16 ) {
sprintf(dest, "%04X", uuid->value.uuid16 );
} else if( uuid->type == SDP_UUID32 ) {
sprintf(dest, "%08X", uuid->value.uuid32 );
} else if( uuid->type == SDP_UUID128 ) {
uint32_t *data = (uint32_t*)(&uuid->value.uuid128);
sprintf(dest, "%08X-%04X-%04X-%04X-%04X%08X",
ntohl(data[0]),
ntohl(data[1])>>16,
(ntohl(data[1])<<16)>>16,
ntohl(data[2])>>16,
(ntohl(data[2])<<16)>>16,
ntohl(data[3]));
}
}
// =================== socket methods ==================== //
/* s.accept() method */
static PyObject *
sock_accept(PySocketSockObject *s)
{
char addrbuf[256];
int newfd;
socklen_t addrlen;
PyObject *sock = NULL;
PyObject *addr = NULL;
PyObject *res = NULL;
int timeout;
if (!getsockaddrlen(s, &addrlen))
return NULL;
memset(addrbuf, 0, addrlen);
newfd = -1;
Py_BEGIN_ALLOW_THREADS
timeout = internal_select(s, 0);
if (!timeout)
newfd = accept(s->sock_fd, (struct sockaddr *) addrbuf,
&addrlen);
Py_END_ALLOW_THREADS
if (timeout) {
PyErr_SetString(socket_timeout, "timed out");
return NULL;
}
if (newfd < 0)
return s->errorhandler();
/* Create the new object with unspecified family,
to avoid calls to bind() etc. on it. */
sock = (PyObject *) new_sockobject(newfd,
s->sock_family,
s->sock_type,
s->sock_proto);
if (sock == NULL) {
close(newfd);
goto finally;
}
addr = makesockaddr(s, (struct sockaddr *)addrbuf, addrlen);
if (addr == NULL)
goto finally;
res = Py_BuildValue("OO", sock, addr);
finally:
Py_XDECREF(sock);
Py_XDECREF(addr);
return res;
}
PyDoc_STRVAR(accept_doc,
"accept() -> (socket object, address info)\n\
\n\
Wait for an incoming connection. Return a new socket representing the\n\
connection, and the address of the client. For L2CAP sockets, the address\n\
is a (host, psm) tuple. For RFCOMM sockets, the address is a (host, channel)\n\
tuple. For SCO sockets, the address is just a host.");
/* s.setblocking(flag) method. Argument:
False -- non-blocking mode; same as settimeout(0)
True -- blocking mode; same as settimeout(None)
*/
static PyObject *
sock_setblocking(PySocketSockObject *s, PyObject *arg)
{
int block;
block = PyInt_AsLong(arg);
if (block == -1 && PyErr_Occurred())
return NULL;
s->sock_timeout = block ? -1.0 : 0.0;
internal_setblocking(s, block);
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(setblocking_doc,
"setblocking(flag)\n\
\n\
Set the socket to blocking (flag is true) or non-blocking (false).\n\
setblocking(True) is equivalent to settimeout(None);\n\
setblocking(False) is equivalent to settimeout(0.0).");
/* s.settimeout(timeout) method. Argument:
None -- no timeout, blocking mode; same as setblocking(True)
0.0 -- non-blocking mode; same as setblocking(False)
> 0 -- timeout mode; operations time out after timeout seconds
< 0 -- illegal; raises an exception
*/
static PyObject *
sock_settimeout(PySocketSockObject *s, PyObject *arg)
{
double timeout;
if (arg == Py_None)
timeout = -1.0;
else {
timeout = PyFloat_AsDouble(arg);
if (timeout < 0.0) {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_ValueError,
"Timeout value out of range");
return NULL;
}
}
s->sock_timeout = timeout;
internal_setblocking(s, timeout < 0.0);
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(settimeout_doc,
"settimeout(timeout)\n\
\n\
Set a timeout on socket operations. 'timeout' can be a float,\n\
giving in seconds, or None. Setting a timeout of None disables\n\
the timeout feature and is equivalent to setblocking(1).\n\
Setting a timeout of zero is the same as setblocking(0).");
/* s.gettimeout() method.
Returns the timeout associated with a socket. */
static PyObject *
sock_gettimeout(PySocketSockObject *s)
{
if (s->sock_timeout < 0.0) {
Py_INCREF(Py_None);
return Py_None;
}
else
return PyFloat_FromDouble(s->sock_timeout);
}
PyDoc_STRVAR(gettimeout_doc,
"gettimeout() -> timeout\n\
\n\
Returns the timeout in floating seconds associated with socket \n\
operations. A timeout of None indicates that timeouts on socket \n\
operations are disabled.");
/* s.setsockopt() method.
With an integer third argument, sets an integer option.
With a string third argument, sets an option from a buffer;
use optional built-in module 'struct' to encode the string. */
static PyObject *
sock_setsockopt(PySocketSockObject *s, PyObject *args)
{
int level;
int optname;
int res;
void *buf;
int buflen;
int flag;
if (PyArg_ParseTuple(args, "iii:setsockopt", &level, &optname, &flag)) {
buf = (void *) &flag;
buflen = sizeof flag;
} else {
PyErr_Clear();
if (!PyArg_ParseTuple(args, "iis#:setsockopt",
&level, &optname, &buf, &buflen)) {
return NULL;
}
}
res = setsockopt(s->sock_fd, level, optname, buf, buflen);
if (res < 0)
return s->errorhandler();
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(setsockopt_doc,
"setsockopt(level, option, value)\n\
\n\
Set a socket option. See the Unix manual for level and option.\n\
The value argument can either be an integer or a string.");
/* s.getsockopt() method.
With two arguments, retrieves an integer option.
With a third integer argument, retrieves a string buffer of that size;
use optional built-in module 'struct' to decode the string. */
static PyObject *
sock_getsockopt(PySocketSockObject *s, PyObject *args)
{
int level;
int optname;
int res;
socklen_t buflen = 0;
if (!PyArg_ParseTuple(args, "ii|i:getsockopt", &level, &optname, &buflen))
return NULL;
if (buflen == 0) {
int flag = 0;
socklen_t flagsize = sizeof flag;
res = getsockopt(s->sock_fd, level, optname, (void *)&flag, &flagsize);
if (res < 0)
return s->errorhandler();
return PyInt_FromLong(flag);
} else if (buflen <= 0 || buflen > 1024) {
PyErr_SetString(bluetooth_error,
"getsockopt buflen out of range");
return NULL;
} else {
PyObject *buf = PyString_FromStringAndSize((char *)NULL, buflen);
if (buf == NULL)
return NULL;
res = getsockopt(s->sock_fd, level, optname,
(void *)PyString_AS_STRING(buf), &buflen);
if (res < 0) {
Py_DECREF(buf);
return s->errorhandler();
}
_PyString_Resize(&buf, buflen);
return buf;
}
return NULL;
}
PyDoc_STRVAR(getsockopt_doc,
"getsockopt(level, option[, buffersize]) -> value\n\
\n\
Get a socket option. See the Unix manual for level and option.\n\
If a nonzero buffersize argument is given, the return value is a\n\
string of that length; otherwise it is an integer.");
static PyObject *
sock_setl2capsecurity(PySocketSockObject *s, PyObject *args)
{
int level;
struct bt_security sec;
if (! PyArg_ParseTuple(args, "i:setsockopt",
&level))
return NULL;
memset(&sec, 0, sizeof(sec));
sec.level = level;
if (setsockopt(s->sock_fd, SOL_BLUETOOTH, BT_SECURITY, &sec,
sizeof(sec)) == 0) {
Py_INCREF(Py_None);
return Py_None;
}
if (errno != ENOPROTOOPT)
return s->errorhandler();
int lm_map[] = {
0,
L2CAP_LM_AUTH,
L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT,
L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE,
}, opt = lm_map[level];
if (setsockopt(s->sock_fd, SOL_L2CAP, L2CAP_LM, &opt, sizeof(opt)) < 0)
return s->errorhandler();
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(setl2capsecurity_doc,
"setl2capsecurity(BT_SECURITY_*) -> value\n\
\n\
Sets socket security. Levels are BT_SECURITY_SDP, LOW, MEDIUM\n\
and HIGH.");
/* s.bind(sockaddr) method */
static PyObject *
sock_bind(PySocketSockObject *s, PyObject *addro)
{
struct sockaddr addr = { 0 };
int addrlen;
int res;
if (!getsockaddrarg(s, addro, &addr, &addrlen))
return NULL;
Py_BEGIN_ALLOW_THREADS
res = bind(s->sock_fd, &addr, addrlen);
Py_END_ALLOW_THREADS
if (res < 0)
return s->errorhandler();
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(bind_doc,
"bind(address)\n\
\n\
Bind the socket to a local address. address must always be a tuple.\n\
HCI sockets: ( device number, )\n\
device number should be 0, 1, 2, etc.\n\
L2CAP sockets: ( host, psm )\n\
host should be an address e.g. \"01:23:45:67:89:ab\"\n\
psm should be an unsigned integer\n\
RFCOMM sockets: ( host, channel )\n\
SCO sockets: ( host )\n\
");
/* s.close() method.
Set the file descriptor to -1 so operations tried subsequently
will surely fail. */
static PyObject *
sock_close(PySocketSockObject *s)
{
int fd;
if ((fd = s->sock_fd) != -1) {
s->sock_fd = -1;
Py_BEGIN_ALLOW_THREADS
(void) close(fd);
Py_END_ALLOW_THREADS
}
if( s->sdp_session ) {
sdp_close( s->sdp_session );
s->sdp_record_handle = 0;
s->sdp_session = NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(close_doc,
"close()\n\
\n\
Close the socket. It cannot be used after this call.");
static int
internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen,
int *timeoutp)
{
int res, timeout;
timeout = 0;
res = connect(s->sock_fd, addr, addrlen);
if (s->sock_timeout > 0.0) {
if (res < 0 && errno == EINPROGRESS) {
timeout = internal_select(s, 1);
res = connect(s->sock_fd, addr, addrlen);
if (res < 0 && errno == EISCONN)
res = 0;
}
}
if (res < 0)
res = errno;
*timeoutp = timeout;
return res;
}
/* s.connect(sockaddr) method */
static PyObject *
sock_connect(PySocketSockObject *s, PyObject *addro)
{
struct sockaddr addr = { 0 };
int addrlen;
int res;
int timeout;
if (!getsockaddrarg(s, addro, &addr, &addrlen))
return NULL;
Py_BEGIN_ALLOW_THREADS
res = internal_connect(s, &addr, addrlen, &timeout);
Py_END_ALLOW_THREADS
if (timeout) {
PyErr_SetString(socket_timeout, "timed out");
return NULL;
}
if (res != 0)
return s->errorhandler();
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(connect_doc,
"connect(address)\n\
\n\
Connect the socket to a remote address. For L2CAP sockets, the address is a \n\
(host,psm) tuple. For RFCOMM sockets, the address is a (host,channel) tuple.\n\
For SCO sockets, the address is just the host.");
/* s.connect_ex(sockaddr) method */
static PyObject *
sock_connect_ex(PySocketSockObject *s, PyObject *addro)
{
struct sockaddr addr = { 0 };
int addrlen;
int res;
int timeout;
if (!getsockaddrarg(s, addro, &addr, &addrlen))
return NULL;
Py_BEGIN_ALLOW_THREADS
res = internal_connect(s, &addr, addrlen, &timeout);
Py_END_ALLOW_THREADS
return PyInt_FromLong((long) res);
}
PyDoc_STRVAR(connect_ex_doc,
"connect_ex(address) -> errno\n\
\n\
This is like connect(address), but returns an error code (the errno value)\n\
instead of raising an exception when an error occurs.");
/* s.fileno() method */
static PyObject *
sock_fileno(PySocketSockObject *s)
{
return PyInt_FromLong((long) s->sock_fd);
}
PyDoc_STRVAR(fileno_doc,
"fileno() -> integer\n\
\n\
Return the integer file descriptor of the socket.");
#ifndef NO_DUP
/* s.dup() method */
static PyObject *
sock_dup(PySocketSockObject *s)
{
int newfd;
PyObject *sock;
newfd = dup(s->sock_fd);
if (newfd < 0)
return s->errorhandler();
sock = (PyObject *) new_sockobject(newfd,
s->sock_family,
s->sock_type,
s->sock_proto);
if (sock == NULL)
close(newfd);
return sock;
}
PyDoc_STRVAR(dup_doc,
"dup() -> socket object\n\
\n\
Return a new socket object connected to the same system resource.");
#endif
/* s.getsockname() method */
static PyObject *
sock_getsockname(PySocketSockObject *s)
{
char addrbuf[256];
int res;
socklen_t addrlen;
if (!getsockaddrlen(s, &addrlen))
return NULL;
memset(addrbuf, 0, addrlen);
Py_BEGIN_ALLOW_THREADS
res = getsockname(s->sock_fd, (struct sockaddr *) addrbuf, &addrlen);
Py_END_ALLOW_THREADS
if (res < 0)
return s->errorhandler();
return makesockaddr(s, (struct sockaddr *) addrbuf, addrlen);
}
PyDoc_STRVAR(getsockname_doc,
"getsockname() -> address info\n\
\n\
Return the address of the local endpoint.");
/* s.getpeername() method */
static PyObject *
sock_getpeername(PySocketSockObject *s)
{
char addrbuf[256];
int res;
socklen_t addrlen;
if (!getsockaddrlen(s, &addrlen))
return NULL;
memset(addrbuf, 0, addrlen);
Py_BEGIN_ALLOW_THREADS
res = getpeername(s->sock_fd, (struct sockaddr *) addrbuf, &addrlen);
Py_END_ALLOW_THREADS
if (res < 0)
return s->errorhandler();
return makesockaddr(s, (struct sockaddr *) addrbuf, addrlen);
}
PyDoc_STRVAR(getpeername_doc,
"getpeername() -> address info\n\
\n\
Return the address of the remote endpoint. For HCI sockets, the address is a\n\
device number (0, 1, 2, etc). For L2CAP sockets, the address is a \n\
(host,psm) tuple. For RFCOMM sockets, the address is a (host,channel) tuple.\n\
For SCO sockets, the address is just the host.");
/* s.listen(n) method */
static PyObject *
sock_listen(PySocketSockObject *s, PyObject *arg)
{
int backlog;
int res;
backlog = PyInt_AsLong(arg);
if (backlog == -1 && PyErr_Occurred())
return NULL;
Py_BEGIN_ALLOW_THREADS
if (backlog < 1)
backlog = 1;
res = listen(s->sock_fd, backlog);
Py_END_ALLOW_THREADS
if (res < 0)
return s->errorhandler();
Py_INCREF(Py_None);
s->is_listening_socket = 1;
return Py_None;
}
PyDoc_STRVAR(listen_doc,
"listen(backlog)\n\
\n\
Enable a server to accept connections. The backlog argument must be at\n\
least 1; it specifies the number of unaccepted connection that the system\n\
will allow before refusing new connections.");
#ifndef NO_DUP
/* s.makefile(mode) method.
Create a new open file object referring to a dupped version of
the socket's file descriptor. (The dup() call is necessary so
that the open file and socket objects may be closed independent
of each other.)
The mode argument specifies 'r' or 'w' passed to fdopen(). */
static PyObject *
sock_makefile(PySocketSockObject *s, PyObject *args)
{
extern int fclose(FILE *);
char *mode = "r";
int bufsize = -1;
int fd;
FILE *fp;
PyObject *f;
if (!PyArg_ParseTuple(args, "|si:makefile", &mode, &bufsize))
return NULL;
if ((fd = dup(s->sock_fd)) < 0 || (fp = fdopen(fd, mode)) == NULL)
{
if (fd >= 0)
close(fd);
return s->errorhandler();
}
#if PY_MAJOR_VERSION >= 3
f = PyFile_FromFd(fd, "", mode, bufsize, NULL, NULL, NULL, 1);
#else
f = PyFile_FromFile(fp, "", mode, fclose);
if (f != NULL)
PyFile_SetBufSize(f, bufsize);
#endif
return f;
}
PyDoc_STRVAR(makefile_doc,
"makefile([mode[, buffersize]]) -> file object\n\
\n\
Return a regular file object corresponding to the socket.\n\
The mode and buffersize arguments are as for the built-in open() function.");
#endif /* NO_DUP */
/* s.recv(nbytes [,flags]) method */
static PyObject *
sock_recv(PySocketSockObject *s, PyObject *args)
{
int len, n = 0, flags = 0, timeout;
PyObject *buf;
if (!PyArg_ParseTuple(args, "i|i:recv", &len, &flags))
return NULL;
if (len < 0) {
PyErr_SetString(PyExc_ValueError,
"negative buffersize in recv");
return NULL;
}
buf = PyString_FromStringAndSize((char *) 0, len);
if (buf == NULL)
return NULL;
Py_BEGIN_ALLOW_THREADS
timeout = internal_select(s, 0);
if (!timeout)
n = recv(s->sock_fd, PyString_AS_STRING(buf), len, flags);
Py_END_ALLOW_THREADS
if (timeout) {
Py_DECREF(buf);
PyErr_SetString(socket_timeout, "timed out");
return NULL;
}
if (n < 0) {
Py_DECREF(buf);
return s->errorhandler();
}
if (n != len)
_PyString_Resize(&buf, n);
return buf;
}
PyDoc_STRVAR(recv_doc,
"recv(buffersize[, flags]) -> data\n\
\n\
Receive up to buffersize bytes from the socket. For the optional flags\n\
argument, see the Unix manual. When no data is available, block until\n\
at least one byte is available or until the remote end is closed. When\n\
the remote end is closed and all data is read, return the empty string.");
/* s.recvfrom(nbytes [,flags]) method */
static PyObject *
sock_recvfrom(PySocketSockObject *s, PyObject *args)
{
char addrbuf[256];
PyObject *buf = NULL;
PyObject *addr = NULL;
PyObject *ret = NULL;
int len, n = 0, flags = 0, timeout;
socklen_t addrlen;
if (!PyArg_ParseTuple(args, "i|i:recvfrom", &len, &flags))
return NULL;
if (!getsockaddrlen(s, &addrlen))
return NULL;
buf = PyString_FromStringAndSize((char *) 0, len);
if (buf == NULL)
return NULL;
Py_BEGIN_ALLOW_THREADS
memset(addrbuf, 0, addrlen);
timeout = internal_select(s, 0);
if (!timeout)
n = recvfrom(s->sock_fd, PyString_AS_STRING(buf), len, flags,
(void *)addrbuf, &addrlen
);
Py_END_ALLOW_THREADS
if (timeout) {
Py_DECREF(buf);
PyErr_SetString(socket_timeout, "timed out");
return NULL;
}
if (n < 0) {
Py_DECREF(buf);
return s->errorhandler();
}
if (n != len && _PyString_Resize(&buf, n) < 0)
return NULL;
if (!(addr = makesockaddr(s, (struct sockaddr *)addrbuf,
addrlen)))
goto finally;
ret = Py_BuildValue("OO", buf, addr);
finally:
Py_XDECREF(addr);
Py_XDECREF(buf);
return ret;
}
PyDoc_STRVAR(recvfrom_doc,
"recvfrom(buffersize[, flags]) -> (data, address info)\n\
\n\
Like recv(buffersize, flags) but also return the sender's address info.");
/* s.send(data [,flags]) method */
static PyObject *
sock_send(PySocketSockObject *s, PyObject *args)
{
char *buf;
int len, n = 0, flags = 0, timeout;
if (!PyArg_ParseTuple(args, "s#|i:send", &buf, &len, &flags))
return NULL;
Py_BEGIN_ALLOW_THREADS
timeout = internal_select(s, 1);
if (!timeout)
n = send(s->sock_fd, buf, len, flags);
Py_END_ALLOW_THREADS
if (timeout) {
PyErr_SetString(socket_timeout, "timed out");
return NULL;
}
if (n < 0)
return s->errorhandler();
return PyInt_FromLong((long)n);
}
PyDoc_STRVAR(send_doc,
"send(data[, flags]) -> count\n\
\n\
Send a data string to the socket. For the optional flags\n\
argument, see the Unix manual. Return the number of bytes\n\
sent; this may be less than len(data) if the network is busy.");
/* s.sendall(data [,flags]) method */
static PyObject *
sock_sendall(PySocketSockObject *s, PyObject *args)
{
char *buf;
int len, n = 0, flags = 0, timeout;
if (!PyArg_ParseTuple(args, "s#|i:sendall", &buf, &len, &flags))
return NULL;
Py_BEGIN_ALLOW_THREADS
do {
timeout = internal_select(s, 1);
if (timeout)
break;
n = send(s->sock_fd, buf, len, flags);
if (n < 0)
break;
buf += n;
len -= n;
} while (len > 0);
Py_END_ALLOW_THREADS
if (timeout) {
PyErr_SetString(socket_timeout, "timed out");
return NULL;
}
if (n < 0)
return s->errorhandler();
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(sendall_doc,
"sendall(data[, flags])\n\
\n\
Send a data string to the socket. For the optional flags\n\
argument, see the Unix manual. This calls send() repeatedly\n\
until all data is sent. If an error occurs, it's impossible\n\
to tell how much data has been sent.");
/* s.sendto(data, [flags,] sockaddr) method */
static PyObject *
sock_sendto(PySocketSockObject *s, PyObject *args)
{
PyObject *addro;
char *buf;
struct sockaddr addr = { 0 };
int addrlen, len, n = 0, flags, timeout;
flags = 0;
if (!PyArg_ParseTuple(args, "s#O:sendto", &buf, &len, &addro)) {
PyErr_Clear();
if (!PyArg_ParseTuple(args, "s#iO:sendto",
&buf, &len, &flags, &addro))
return NULL;
}
if (!getsockaddrarg(s, addro, &addr, &addrlen))
return NULL;
Py_BEGIN_ALLOW_THREADS
timeout = internal_select(s, 1);
if (!timeout)
n = sendto(s->sock_fd, buf, len, flags, &addr, addrlen);
Py_END_ALLOW_THREADS
if (timeout) {
PyErr_SetString(socket_timeout, "timed out");
return NULL;
}
if (n < 0)
return s->errorhandler();
return PyInt_FromLong((long)n);
}
PyDoc_STRVAR(sendto_doc,
"sendto(data[, flags], address) -> count\n\
\n\
Like send(data, flags) but allows specifying the destination address.\n\
For IP sockets, the address is a pair (hostaddr, port).");
/* s.shutdown(how) method */
static PyObject *
sock_shutdown(PySocketSockObject *s, PyObject *arg)
{
int how;
int res;
how = PyInt_AsLong(arg);
if (how == -1 && PyErr_Occurred())
return NULL;
Py_BEGIN_ALLOW_THREADS
res = shutdown(s->sock_fd, how);
Py_END_ALLOW_THREADS
if (res < 0)
return s->errorhandler();
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(shutdown_doc,
"shutdown(flag)\n\
\n\
Shut down the reading side of the socket (flag == 0), the writing side\n\
of the socket (flag == 1), or both ends (flag == 2).");
/* s.getsockid() method */
static PyObject *
sock_getsockid(PySocketSockObject *s, PyObject *arg)
{
int dd;
dd = s->sock_fd;
return Py_BuildValue("i", dd);
}
/* List of methods for socket objects */
static PyMethodDef sock_methods[] = {
{"accept", (PyCFunction)sock_accept, METH_NOARGS,
accept_doc},
{"bind", (PyCFunction)sock_bind, METH_O,
bind_doc},
{"close", (PyCFunction)sock_close, METH_NOARGS,
close_doc},
{"connect", (PyCFunction)sock_connect, METH_O,
connect_doc},
{"connect_ex", (PyCFunction)sock_connect_ex, METH_O,
connect_ex_doc},
#ifndef NO_DUP
{"dup", (PyCFunction)sock_dup, METH_NOARGS,
dup_doc},
#endif
{"fileno", (PyCFunction)sock_fileno, METH_NOARGS,
fileno_doc},
{"getpeername", (PyCFunction)sock_getpeername,
METH_NOARGS, getpeername_doc},
{"getsockid", (PyCFunction)sock_getsockid,
METH_NOARGS, "Gets socket id."},
{"getsockname", (PyCFunction)sock_getsockname,
METH_NOARGS, getsockname_doc},
{"getsockopt", (PyCFunction)sock_getsockopt, METH_VARARGS,
getsockopt_doc},
{"listen", (PyCFunction)sock_listen, METH_O,
listen_doc},
#ifndef NO_DUP
{"makefile", (PyCFunction)sock_makefile, METH_VARARGS,
makefile_doc},
#endif
{"recv", (PyCFunction)sock_recv, METH_VARARGS,
recv_doc},
{"recvfrom", (PyCFunction)sock_recvfrom, METH_VARARGS,
recvfrom_doc},
{"send", (PyCFunction)sock_send, METH_VARARGS,
send_doc},
{"sendall", (PyCFunction)sock_sendall, METH_VARARGS,
sendall_doc},
{"sendto", (PyCFunction)sock_sendto, METH_VARARGS,
sendto_doc},
{"setblocking", (PyCFunction)sock_setblocking, METH_O,
setblocking_doc},
{"settimeout", (PyCFunction)sock_settimeout, METH_O,
settimeout_doc},
{"gettimeout", (PyCFunction)sock_gettimeout, METH_NOARGS,
gettimeout_doc},
{"setsockopt", (PyCFunction)sock_setsockopt, METH_VARARGS,
setsockopt_doc},
{"setl2capsecurity", (PyCFunction)sock_setl2capsecurity, METH_VARARGS,
setl2capsecurity_doc},
{"shutdown", (PyCFunction)sock_shutdown, METH_O,
shutdown_doc},
{NULL, NULL} /* sentinel */
};
/* Deallocate a socket object in response to the last Py_DECREF().
First close the file description. */
static void
sock_dealloc(PySocketSockObject *s)
{
// close the OS file descriptor
if (s->sock_fd != -1) {
Py_BEGIN_ALLOW_THREADS
close(s->sock_fd);
Py_END_ALLOW_THREADS
}
if( s->sdp_session ) {
sdp_close( s->sdp_session );
s->sdp_record_handle = 0;
s->sdp_session = NULL;
}
Py_TYPE(s)->tp_free((PyObject *)s);
}
static PyObject *
sock_repr(PySocketSockObject *s)
{
char buf[512];
#if SIZEOF_SOCKET_T > SIZEOF_LONG
if (s->sock_fd > LONG_MAX) {
/* this can occur on Win64, and actually there is a special
ugly printf formatter for decimal pointer length integer
printing, only bother if necessary*/
PyErr_SetString(PyExc_OverflowError,
"no printf formatter to display "
"the socket descriptor in decimal");
return NULL;
}
#endif
PyOS_snprintf(
buf, sizeof(buf),
"",
(long)s->sock_fd, s->sock_family,
s->sock_type,
s->sock_proto);
return PyString_FromString(buf);
}
/* Create a new, uninitialized socket object. */
static PyObject *
sock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *new;
new = type->tp_alloc(type, 0);
if (new != NULL) {
((PySocketSockObject *)new)->sock_fd = -1;
((PySocketSockObject *)new)->sock_timeout = -1.0;
((PySocketSockObject *)new)->errorhandler = &set_error;
}
return new;
}
/* Initialize a new socket object. */
/*ARGSUSED*/
static int
sock_initobj(PyObject *self, PyObject *args, PyObject *kwds)
{
PySocketSockObject *s = (PySocketSockObject *)self;
int fd;
int family = AF_BLUETOOTH, type = SOCK_STREAM, proto = BTPROTO_RFCOMM;
static char *keywords[] = {"proto", 0};
if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|i:socket", keywords,
&proto))
return -1;
switch(proto) {
case BTPROTO_HCI:
type = SOCK_RAW;
break;
case BTPROTO_L2CAP:
type = SOCK_SEQPACKET;
break;
case BTPROTO_RFCOMM:
type = SOCK_STREAM;
break;
case BTPROTO_SCO:
type = SOCK_SEQPACKET;
break;
}
Py_BEGIN_ALLOW_THREADS
fd = socket(family, type, proto);
Py_END_ALLOW_THREADS
if (fd < 0)
{
set_error();
return -1;
}
init_sockobject(s, fd, family, type, proto);
/* From now on, ignore SIGPIPE and let the error checking
do the work. */
#ifdef SIGPIPE
(void) signal(SIGPIPE, SIG_IGN);
#endif
return 0;
}
/* Type object for socket objects. */
PyTypeObject sock_type = {
#if PY_MAJOR_VERSION < 3
PyObject_HEAD_INIT(0) /* Must fill in type value later */
0, /* ob_size */
#else
PyVarObject_HEAD_INIT(NULL, 0) /* Must fill in type value later */
#endif
"_bluetooth.btsocket", /* tp_name */
sizeof(PySocketSockObject), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)sock_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)sock_repr,/* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
sock_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
sock_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
sock_initobj, /* tp_init */
PyType_GenericAlloc,/* tp_alloc */
sock_new, /* tp_new */
PyObject_Del, /* tp_free */
};
#ifndef NO_DUP
/* Create a socket object from a numeric file description.
Useful e.g. if stdin is a socket.
Additional arguments as for socket(). */
/*ARGSUSED*/
static PyObject *
bt_fromfd(PyObject *self, PyObject *args)
{
PySocketSockObject *s;
int fd;
int family, type, proto = 0;
if (!PyArg_ParseTuple(args, "iii|i:fromfd",
&fd, &family, &type, &proto))
return NULL;
/* Dup the fd so it and the socket can be closed independently */
fd = dup(fd);
if (fd < 0)
return set_error();
s = new_sockobject(fd, family, type, proto);
/* From now on, ignore SIGPIPE and let the error checking
do the work. */
#ifdef SIGPIPE
(void) signal(SIGPIPE, SIG_IGN);
#endif
return (PyObject *) s;
}
PyDoc_STRVAR(bt_fromfd_doc,
"fromfd(fd, family, type[, proto]) -> socket object\n\
\n\
Create a socket object from the given file descriptor.\n\
The remaining arguments are the same as for socket().");
#endif /* NO_DUP */
static PyObject *
bt_btohs(PyObject *self, PyObject *args)
{
int x1, x2;
if (!PyArg_ParseTuple(args, "i:btohs", &x1)) {
return NULL;
}
x2 = (int)btohs((short)x1);
return PyInt_FromLong(x2);
}
PyDoc_STRVAR(bt_btohs_doc,
"btohs(integer) -> integer\n\
\n\
Convert a 16-bit integer from bluetooth to host byte order.");
static PyObject *
bt_btohl(PyObject *self, PyObject *args)
{
unsigned long x;
PyObject *arg;
if (!PyArg_ParseTuple(args, "O:btohl", &arg)) {
return NULL;
}
if (PyInt_Check(arg)) {
x = PyInt_AS_LONG(arg);
if (x == (unsigned long) -1 && PyErr_Occurred())
return NULL;
}
else if (PyLong_Check(arg)) {
x = PyLong_AsUnsignedLong(arg);
if (x == (unsigned long) -1 && PyErr_Occurred())
return NULL;
#if SIZEOF_LONG > 4
{
unsigned long y;
/* only want the trailing 32 bits */
y = x & 0xFFFFFFFFUL;
if (y ^ x)
return PyErr_Format(PyExc_OverflowError,
"long int larger than 32 bits");
x = y;
}
#endif
}
else
return PyErr_Format(PyExc_TypeError,
"expected int/long, %s found",
arg->ob_type->tp_name);
if (x == (unsigned long) -1 && PyErr_Occurred())
return NULL;
return PyInt_FromLong(btohl(x));
}
PyDoc_STRVAR(bt_btohl_doc,
"btohl(integer) -> integer\n\
\n\
Convert a 32-bit integer from bluetooth to host byte order.");
static PyObject *
bt_htobs(PyObject *self, PyObject *args)
{
unsigned long x1, x2;
if (!PyArg_ParseTuple(args, "i:htobs", &x1)) {
return NULL;
}
x2 = (int)htobs((short)x1);
return PyInt_FromLong(x2);
}
PyDoc_STRVAR(bt_htobs_doc,
"htobs(integer) -> integer\n\
\n\
Convert a 16-bit integer from host to bluetooth byte order.");
static PyObject *
bt_htobl(PyObject *self, PyObject *args)
{
unsigned long x;
PyObject *arg;
if (!PyArg_ParseTuple(args, "O:htobl", &arg)) {
return NULL;
}
if (PyInt_Check(arg)) {
x = PyInt_AS_LONG(arg);
if (x == (unsigned long) -1 && PyErr_Occurred())
return NULL;
}
else if (PyLong_Check(arg)) {
x = PyLong_AsUnsignedLong(arg);
if (x == (unsigned long) -1 && PyErr_Occurred())
return NULL;
#if SIZEOF_LONG > 4
{
unsigned long y;
/* only want the trailing 32 bits */
y = x & 0xFFFFFFFFUL;
if (y ^ x)
return PyErr_Format(PyExc_OverflowError,
"long int larger than 32 bits");
x = y;
}
#endif
}
else
return PyErr_Format(PyExc_TypeError,
"expected int/long, %s found",
arg->ob_type->tp_name);
return PyInt_FromLong(htobl(x));
}
//static PyObject *
//bt_get_available_port_number( PyObject *self, PyObject *arg )
//{
// int protocol = -1;
// int s;
//
// protocol = PyInt_AsLong(arg);
//
// if (protocol == -1 && PyErr_Occurred())
// return NULL;
//
// switch(protocol) {
// case BTPROTO_RFCOMM:
// {
// struct sockaddr_rc sockaddr = { 0 };
// int s, psm;
// s = socket( AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM );
//
// sockaddr.rc_family = AF_BLUETOOTH;
// bacppy( &sockaddr.rc_bdaddr, BDADDR_ANY
// }
// break;
// case BTPROTO_L2CAP:
// {
// loc_addr.l2_family = AF_BLUETOOTH;
// bacpy( &loc_addr.l2_bdaddr, BDADDR_ANY );
// loc_addr.l2_psm = htobs(0x1001);
//
// }
// break;
// default:
// {
// PyErr_SetString( PyExc_ValueError,
// "protocol must be either RFCOMM or L2CAP" );
// return 0;
// }
// break;
// }
// Py_INCREF( Py_None );
// return Py_None;
//}
PyDoc_STRVAR(bt_htobl_doc,
"htobl(integer) -> integer\n\
\n\
Convert a 32-bit integer from host to bluetooth byte order.");
/* Python API to getting and setting the default timeout value. */
static PyObject *
bt_getdefaulttimeout(PyObject *self)
{
if (defaulttimeout < 0.0) {
Py_INCREF(Py_None);
return Py_None;
}
else
return PyFloat_FromDouble(defaulttimeout);
}
PyDoc_STRVAR(bt_getdefaulttimeout_doc,
"getdefaulttimeout() -> timeout\n\
\n\
Returns the default timeout in floating seconds for new socket objects.\n\
A value of None indicates that new socket objects have no timeout.\n\
When the socket module is first imported, the default is None.");
static PyObject *
bt_setdefaulttimeout(PyObject *self, PyObject *arg)
{
double timeout;
if (arg == Py_None)
timeout = -1.0;
else {
timeout = PyFloat_AsDouble(arg);
if (timeout < 0.0) {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_ValueError,
"Timeout value out of range");
return NULL;
}
}
defaulttimeout = timeout;
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(bt_setdefaulttimeout_doc,
"setdefaulttimeout(timeout)\n\
\n\
Set the default timeout in floating seconds for new socket objects.\n\
A value of None indicates that new socket objects have no timeout.\n\
When the socket module is first imported, the default is None.");
/*
* ----------------------------------------------------------------------
* HCI Section (Calvin)
*
* This section provides the socket methods for calling HCI commands.
* These commands may be called statically, and implementation is
* independent from the rest of the module (except for bt_methods[]).
*
* ----------------------------------------------------------------------
*
*/
/*
* params: (int) device number
* effect: opens and binds a new HCI socket
* return: a PySocketSockObject, or NULL on failure
*/
static PyObject *
bt_hci_open_dev(PyObject *self, PyObject *args)
{
int dev = -1, fd;
PySocketSockObject *s = NULL;
if ( !PyArg_ParseTuple(args, "|i", &dev) )
{
return NULL;
}
// if the device was not specified, just use the first available bt device
if (dev < 0) {
dev = hci_get_route(NULL);
}
if (dev < 0) {
PyErr_SetString(bluetooth_error, "no available bluetoot devices");
return 0;
}
Py_BEGIN_ALLOW_THREADS
fd = hci_open_dev(dev);
Py_END_ALLOW_THREADS
s = (PySocketSockObject *)PyType_GenericNew(&sock_type, NULL, NULL);
if (s != NULL) init_sockobject(s, fd, AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
return (PyObject*)s;
}
PyDoc_STRVAR(bt_hci_open_dev_doc, "hci_open_dev");
/*
* params: (int) device number
* effect: closes an HCI socket
*/
static PyObject *
bt_hci_close_dev(PyObject *self, PyObject *args)
{
int dev, err;
if ( !PyArg_ParseTuple(args, "i", &dev) )
{
return NULL;
}
Py_BEGIN_ALLOW_THREADS
err = hci_close_dev(dev);
Py_END_ALLOW_THREADS
if( err < 0 ) return set_error();
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(bt_hci_close_dev_doc,
"hci_close_dev(dev_id)\n\
\n\
closes the specified device id. Note: device id is NOT a btoscket.\n\
You can also use btsocket.close() to close a specific socket.");
/*
* params: (int) socket fd, (uint_16) ogf control bits
* (uint_16) ocf control bits, (struct) command params
* effect: executes command described by the OGF and OCF bits
* (see bluetooth/hci.h)
* return: (int) 0 on success, -1 on failure
*/
static PyObject *
bt_hci_send_cmd(PyObject *self, PyObject *args)
{
PySocketSockObject *socko = NULL;
int err, plen = 0;
uint16_t ogf, ocf;
char *param = NULL;
int dd = 0;
if ( !PyArg_ParseTuple(args, "OHH|s#", &socko, &ogf, &ocf, ¶m, &plen)) {
return NULL;
}
dd = socko->sock_fd;
Py_BEGIN_ALLOW_THREADS
err = hci_send_cmd(dd, ogf, ocf, plen, (void*)param);
Py_END_ALLOW_THREADS
if( err ) return socko->errorhandler();
return Py_BuildValue("i", err);
}
PyDoc_STRVAR(bt_hci_send_cmd_doc,
"hci_send_command(sock, ogf, ocf, params)\n\
\n\
Transmits the specified HCI command to the socket.\n\
sock - the btoscket object to use\n\
ogf, pcf - see bluetooth specification\n\
params - packed command parameters (use the struct module to do this)");
static PyObject *
bt_hci_send_req(PyObject *self, PyObject *args, PyObject *kwds)
{
PySocketSockObject *socko = NULL;
int err;
int to=0;
char rparam[256];
struct hci_request req = { 0 };
int dd = 0;
static char *keywords[] = { "sock", "ogf", "ocf", "event", "rlen", "params",
"timeout", 0 };
if( !PyArg_ParseTupleAndKeywords(args, kwds, "OHHii|s#i", keywords,
&socko, &req.ogf, &req.ocf, &req.event, &req.rlen,
&req.cparam, &req.clen, &to) )
return 0;
req.rparam = rparam;
dd = socko->sock_fd;
Py_BEGIN_ALLOW_THREADS
err = hci_send_req( dd, &req, to );
Py_END_ALLOW_THREADS
if( err< 0 ) return socko->errorhandler();
return PyString_FromStringAndSize(rparam, req.rlen);
}
PyDoc_STRVAR(bt_hci_send_req_doc,
"hci_send_req(sock, ogf, ocf, event, rlen, params=None, timeout=0)\n\
\n\
Transmits a HCI cmomand to the socket and waits for the specified event.\n\
sock - the btsocket object\n\
ogf, ocf - see bluetooth specification\n\
event - the event to wait for. Probably one of EVT_*\n\
rlen - the size of the returned packet to expect. This must be\n\
specified since bt won't know how much data to expect\n\
otherwise\n\
params - the command parameters\n\
timeout - timeout, in milliseconds");
static PyObject*
bt_hci_inquiry(PyObject *self, PyObject *args, PyObject *kwds)
{
int i, err;
int dev_id = 0;
int length = 8;
int flush = 1;
int flags = 0;
int lookup_class = 0;
char ba_name[19];
inquiry_info *info = NULL;
PySocketSockObject *socko = NULL;
struct hci_inquiry_req *ir;
char buf[sizeof(*ir) + sizeof(inquiry_info) * 250];
PyObject *rtn_list = (PyObject *)NULL;
static char *keywords[] = {"sock", "duration", "flush_cache", "lookup_class", "device_id", 0};
if( !PyArg_ParseTupleAndKeywords(args, kwds, "O|iiii", keywords,
&socko, &length, &flush, &lookup_class, &dev_id) )
{
return 0;
}
flags |= (flush)?IREQ_CACHE_FLUSH:0;
ir = (struct hci_inquiry_req*)buf;
ir->dev_id = dev_id;
ir->num_rsp = 250;
ir->length = length;
ir->flags = flags;
ir->lap[0] = 0x33;
ir->lap[1] = 0x8b;
ir->lap[2] = 0x9e;
Py_BEGIN_ALLOW_THREADS
err = ioctl(socko->sock_fd, HCIINQUIRY, (unsigned long) buf);
Py_END_ALLOW_THREADS
if( err < 0 ) return socko->errorhandler();
info = (inquiry_info*)(buf + sizeof(*ir));
if( (rtn_list = PyList_New(0)) == NULL ) return 0;
memset( ba_name, 0, sizeof(ba_name) );
// fill in the list with the discovered bluetooth addresses
for(i=0;inum_rsp;i++) {
PyObject * addr_entry = (PyObject *)NULL;
int err;
ba2str( &(info+i)->bdaddr, ba_name );
addr_entry = PyString_FromString( ba_name );
if (lookup_class) {
PyObject *item_tuple = PyTuple_New(2);
int dev_class = (info+i)->dev_class[2] << 16 | (info+i)->dev_class[1] << 8 | (info+i)->dev_class[0];
PyObject *class_entry = PyInt_FromLong( dev_class );
err = PyTuple_SetItem( item_tuple, 0, addr_entry );
if (err) {
Py_XDECREF( item_tuple );
Py_XDECREF( rtn_list );
return NULL;
}
err = PyTuple_SetItem( item_tuple, 1, class_entry );
if (err) {
Py_XDECREF( item_tuple );
Py_XDECREF( rtn_list );
return NULL;
}
err = PyList_Append( rtn_list, item_tuple );
Py_DECREF( item_tuple );
if (err) {
Py_XDECREF( rtn_list );
return NULL;
}
} else {
err = PyList_Append( rtn_list, addr_entry );
Py_DECREF( addr_entry );
if (err) {
Py_XDECREF( rtn_list );
return NULL;
}
}
}
return rtn_list;
}
PyDoc_STRVAR(bt_hci_inquiry_doc,
"hci_inquiry(dev_id=0, duration=8, flush_cache=True\n\
\n\
Performs a device inquiry using the specified device (usually 0 or 1).\n\
The inquiry will last 1.28 * duration seconds. If flush_cache is True, then\n\
previously discovered devices will not be returned in the inquiry.)");
static PyObject*
bt_hci_read_remote_name(PyObject *self, PyObject *args, PyObject *kwds)
{
char *addr = NULL;
bdaddr_t ba;
int timeout = 5192;
static char name[249];
PySocketSockObject *socko = NULL;
int err = 0;
static char *keywords[] = {"dd", "bdaddr", "timeout", 0};
if( !PyArg_ParseTupleAndKeywords(args, kwds, "Os|i", keywords,
&socko, &addr, &timeout) )
{
return 0;
}
str2ba( addr, &ba );
memset( name, 0, sizeof(name) );
Py_BEGIN_ALLOW_THREADS
err = hci_read_remote_name( socko->sock_fd, &ba, sizeof(name)-1,
name, timeout );
Py_END_ALLOW_THREADS
if( err < 0)
return PyErr_SetFromErrno(bluetooth_error);
return PyString_FromString( name );
}
PyDoc_STRVAR(bt_hci_read_remote_name_doc,
"hci_read_remote_name(sock, bdaddr, timeout=5192)\n\
\n\
Performs a remote name request to the specified bluetooth device.\n\
sock - the HCI socket object to use\n\
bdaddr - the bluetooth address of the remote device\n\
timeout - maximum amount of time, in milliseconds, to wait\n\
\n\
Returns the name of the device, or raises an error on failure");
// lot of repetitive code... yay macros!!
#define DECL_HCI_FILTER_OP_1(name, docstring) \
static PyObject * bt_hci_filter_ ## name (PyObject *self, PyObject *args )\
{ \
char *param; \
int len, arg; \
if( !PyArg_ParseTuple(args,"s#i", ¶m, &len, &arg) ) \
return 0; \
if( len != sizeof(struct hci_filter) ) { \
PyErr_SetString(PyExc_ValueError, "bad filter"); \
return 0; \
} \
hci_filter_ ## name ( arg, (struct hci_filter*)param ); \
return PyString_FromStringAndSize(param, len); \
} \
PyDoc_STRVAR(bt_hci_filter_ ## name ## _doc, docstring);
DECL_HCI_FILTER_OP_1(set_ptype, "set ptype!")
DECL_HCI_FILTER_OP_1(clear_ptype, "clear ptype!")
DECL_HCI_FILTER_OP_1(test_ptype, "test ptype!")
DECL_HCI_FILTER_OP_1(set_event, "set event!")
DECL_HCI_FILTER_OP_1(clear_event, "clear event!")
DECL_HCI_FILTER_OP_1(test_event, "test event!")
DECL_HCI_FILTER_OP_1(set_opcode, "set opcode!")
DECL_HCI_FILTER_OP_1(test_opcode, "test opcode!")
#undef DECL_HCI_FILTER_OP_1
#define DECL_HCI_FILTER_OP_2(name, docstring) \
static PyObject * bt_hci_filter_ ## name (PyObject *self, PyObject *args )\
{ \
char *param; \
int len; \
if( !PyArg_ParseTuple(args,"s#", ¶m, &len) ) \
return 0; \
if( len != sizeof(struct hci_filter) ) { \
PyErr_SetString(PyExc_ValueError, "bad filter"); \
return 0; \
} \
hci_filter_ ## name ( (struct hci_filter*)param ); \
return PyString_FromStringAndSize(param, len); \
} \
PyDoc_STRVAR(bt_hci_filter_ ## name ## _doc, docstring);
DECL_HCI_FILTER_OP_2(all_events, "all events!");
DECL_HCI_FILTER_OP_2(clear, "clear filter");
DECL_HCI_FILTER_OP_2(all_ptypes, "all packet types!");
DECL_HCI_FILTER_OP_2(clear_opcode, "clear opcode!")
#undef DECL_HCI_FILTER_OP_2
static PyObject *
bt_cmd_opcode_pack(PyObject *self, PyObject *args )
{
uint16_t opcode, ogf, ocf;
if (!PyArg_ParseTuple(args, "HH", &ogf, &ocf )) return 0;
opcode = cmd_opcode_pack(ogf, ocf);
return Py_BuildValue("H", opcode);
}
PyDoc_STRVAR(bt_cmd_opcode_pack_doc,
"cmd_opcode_pack(ogf, ocf)\n\
\n\
packs an OCF and an OGF value together to form a opcode");
static PyObject *
bt_cmd_opcode_ogf(PyObject *self, PyObject *args )
{
uint16_t opcode;
if (!PyArg_ParseTuple(args, "H", &opcode)) return 0;
return Py_BuildValue("H", cmd_opcode_ogf(opcode));
}
PyDoc_STRVAR(bt_cmd_opcode_ogf_doc,
"cmd_opcode_ogf(opcode)\n\
\n\
Convenience function to extract and return the OGF value from an opcode");
static PyObject *
bt_cmd_opcode_ocf(PyObject *self, PyObject *args )
{
uint16_t opcode;
if (!PyArg_ParseTuple(args, "H", &opcode)) return 0;
return Py_BuildValue("H", cmd_opcode_ocf(opcode));
}
PyDoc_STRVAR(bt_cmd_opcode_ocf_doc,
"cmd_opcode_ocf(opcode)\n\
\n\
Convenience function to extract and return the OCF value from an opcode");
static PyObject *
bt_ba2str(PyObject *self, PyObject *args)
{
char *data=NULL;
int len=0;
char ba_str[19] = {0};
if (!PyArg_ParseTuple(args, "s#", &data, &len)) return 0;
ba2str((bdaddr_t*)data, ba_str);
return PyString_FromString( ba_str );
// return Py_BuildValue("s#", ba_str, 18);
}
PyDoc_STRVAR(bt_ba2str_doc,
"ba2str(data)\n\
\n\
Converts a packed bluetooth address to a human readable string");
static PyObject *
bt_str2ba(PyObject *self, PyObject *args)
{
char *ba_str=NULL;
bdaddr_t ba;
if (!PyArg_ParseTuple(args, "s", &ba_str)) return 0;
str2ba( ba_str, &ba );
return Py_BuildValue(BYTES_FORMAT_CHR, (char*)(&ba), sizeof(ba));
}
PyDoc_STRVAR(bt_str2ba_doc,
"str2ba(string)\n\
\n\
Converts a bluetooth address string into a packed bluetooth address. The\n\
string should be of the form \"XX:XX:XX:XX:XX:XX\"");
/*
* params: (string) device address
* effect: -
* return: Device id
*/
static PyObject *
bt_hci_devid(PyObject *self, PyObject *args)
{
char *devaddr=NULL;
int devid;
if ( !PyArg_ParseTuple(args, "|s", &devaddr) )
{
return NULL;
}
if (devaddr)
devid=hci_devid(devaddr);
else
devid=hci_get_route(NULL);
return Py_BuildValue("i",devid);
}
PyDoc_STRVAR( bt_hci_role_doc,
"hci_devid(address)\n\
\n\
get the device id for the local device with specified address.\n\
");
/*
* params: (string) device address
* effect: -
* return: Device id
*/
static PyObject *
bt_hci_role(PyObject *self, PyObject *args)
{
int devid;
int fd;
int role;
if ( !PyArg_ParseTuple(args, "ii", &fd, &devid) )
return NULL;
struct hci_dev_info di = {dev_id: devid};
if (ioctl(fd, HCIGETDEVINFO, (void *) &di))
return NULL;
role = di.link_mode == HCI_LM_MASTER;
return Py_BuildValue("i", role);
}
PyDoc_STRVAR( bt_hci_devid_doc,
"hci_role(hci_fd, dev_id)\n\
\n\
get the role (master or slave) of the device id.\n\
");
/*
* params: (string) device address
* effect: -
* return: Device id
*/
static PyObject *
bt_hci_read_clock(PyObject *self, PyObject *args)
{
int fd;
int handle;
int which;
int timeout;
uint32_t btclock;
uint16_t accuracy;
int res;
if ( !PyArg_ParseTuple(args, "iiii", &fd, &handle, &which, &timeout) )
return NULL;
res = hci_read_clock(fd, handle, which, &btclock, &accuracy, timeout);
if (res) {
Py_INCREF(Py_None);
return Py_None;
}
return Py_BuildValue("(ii)", btclock, accuracy);
}
PyDoc_STRVAR( bt_hci_read_clock_doc,
"hci_read_clock(hci_fd, acl_handle, which_clock, timeout_ms)\n\
\n\
Get the Bluetooth Clock (native or piconet).\n\
");
/*
* params: (string) device address
* effect: -
* return: Device id
*/
static PyObject *
bt_hci_get_route(PyObject *self, PyObject *args)
{
int dev_id = 0;
char *addr = NULL;
bdaddr_t ba;
if ( !PyArg_ParseTuple(args, "|s", &addr) ) {
return NULL;
}
if(addr && strlen(addr)) {
str2ba( addr, &ba );
dev_id = hci_get_route(&ba);
} else {
dev_id = hci_get_route(NULL);
}
if (dev_id < 0) {
return PyErr_SetFromErrno(PyExc_OSError);
}
return PyInt_FromLong(dev_id);
}
PyDoc_STRVAR( bt_hci_get_route_doc,
"hci_get_route(address)\n\
\n\
get the device id through which remote specified addr can be reached.\n\
");
/*
* params: (string) device address
* effect: -
* return: Device id
*/
static PyObject *
bt_hci_acl_conn_handle(PyObject *self, PyObject *args)
{
int fd;
char *devaddr=NULL;
bdaddr_t binaddr;
struct hci_conn_info_req *cr;
char buf[sizeof(struct hci_conn_info_req) + sizeof(struct hci_conn_info)];
int handle = -1;
if ( !PyArg_ParseTuple(args, "is", &fd, &devaddr) )
return NULL;
if (devaddr)
str2ba(devaddr, &binaddr);
else
str2ba("00:00:00:00:00:00", &binaddr);
cr = (struct hci_conn_info_req*) &buf;
bacpy(&cr->bdaddr, &binaddr);
cr->type = ACL_LINK;
if (ioctl(fd, HCIGETCONNINFO, (unsigned long) cr) == 0)
handle = htobs(cr->conn_info->handle);
return Py_BuildValue("i", handle);
}
PyDoc_STRVAR( bt_hci_acl_conn_handle_doc,
"hci_acl_conn_handle(hci_fd, address)\n\
\n\
get the ACL connection handle for the given remote device addr.\n\
");
static PyObject *
bt_hci_filter_new(PyObject *self, PyObject *args)
{
struct hci_filter flt;
int len = sizeof(flt);
hci_filter_clear( &flt );
return Py_BuildValue("s#", (char*)&flt, len);
}
PyDoc_STRVAR(bt_hci_filter_new_doc,
"hci_filter_new()\n\
\n\
Returns a new HCI filter suitable for operating on with the hci_filter_*\n\
methods, and for passing to getsockopt and setsockopt. The filter is\n\
initially cleared");
/*
* -------------------
* End of HCI section
* -------------------
*/
/* ========= SDP specific bluetooth module methods ========== */
PyObject *
bt_sdp_advertise_service( PyObject *self, PyObject *args )
{
PySocketSockObject *socko = NULL;
char *name = NULL,
*service_id_str = NULL,
*provider = NULL,
*description = NULL;
PyObject *service_classes, *profiles, *protocols;
int namelen = 0, provlen = 0, desclen = 0;
uuid_t svc_uuid = { 0 };
int i;
char addrbuf[256] = { 0 };
int res;
socklen_t addrlen;
struct sockaddr *sockaddr;
uuid_t root_uuid, l2cap_uuid, rfcomm_uuid;
sdp_list_t *l2cap_list = 0,
*rfcomm_list = 0,
*root_list = 0,
*proto_list = 0,
*profile_list = 0,
*svc_class_list = 0,
*access_proto_list = 0;
sdp_data_t *channel = 0, *psm = 0;
sdp_record_t record;
sdp_session_t *session = 0;
int err = 0;
if (!PyArg_ParseTuple(args, "O!s#sOOs#s#O", &sock_type, &socko, &name,
&namelen, &service_id_str, &service_classes,
&profiles, &provider, &provlen, &description, &desclen,
&protocols)) {
return 0;
}
if( provlen == 0 ) provider = NULL;
if( desclen == 0 ) description = NULL;
if( socko->sdp_record_handle != 0 ) {
PyErr_SetString(bluetooth_error,
"SDP service record already registered with this socket!");
return 0;
}
if( namelen == 0 ) {
PyErr_SetString(bluetooth_error, "must specify name!");
return 0;
}
// convert the service ID string into a uuid_t if it was specified
if( strlen(service_id_str) && ! str2uuid( service_id_str, &svc_uuid ) ) {
PyErr_SetString(PyExc_ValueError, "invalid service ID");
return NULL;
}
// service_classes must be a list / sequence
if (! PySequence_Check(service_classes)) {
PyErr_SetString(PyExc_ValueError,
"service_classes must be a sequence");
return 0;
}
// make sure each item in the list is a valid UUID
for(i = 0; i < PySequence_Length(service_classes); ++i) {
PyObject *item = PySequence_GetItem(service_classes, i);
if( ! pyunicode2uuid( item, NULL ) ) {
PyErr_SetString(PyExc_ValueError,
"service_classes must be a list of "
"strings, each either of the form XXXX or "
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
return 0;
}
}
// profiles must be a list / sequence
if (! PySequence_Check(profiles)) {
PyErr_SetString(PyExc_ValueError, "profiles must be a sequence");
return 0;
}
// make sure each item in the list is a valid ( uuid, version ) pair
for(i = 0; i < PySequence_Length(profiles); ++i) {
char *profile_uuid_str = NULL;
uint16_t version;
PyObject *tuple = PySequence_GetItem(profiles, i);
if ( ( ! PySequence_Check(tuple) ) ||
( ! PyArg_ParseTuple(tuple, "sH",
&profile_uuid_str, &version)) ||
( ! str2uuid( profile_uuid_str, NULL ) )
) {
PyErr_SetString(PyExc_ValueError,
"Each profile must be a ('uuid', version) tuple");
return 0;
}
}
// protocols must be a list / sequence
if (! PySequence_Check(protocols)) {
PyErr_SetString(PyExc_ValueError,
"protocols must be a sequence");
return 0;
}
// make sure each item in the list is a valid UUID
for(i = 0; i < PySequence_Length(protocols); ++i) {
PyObject *item = PySequence_GetItem(protocols, i);
if( ! pyunicode2uuid( item, NULL ) ) {
PyErr_SetString(PyExc_ValueError,
"protocols must be a list of "
"strings, each either of the form XXXX or "
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
return 0;
}
}
// verify that the socket is bound and listening
if( ! socko->is_listening_socket ) {
PyErr_SetString(bluetooth_error,
"must have already called socket.listen()");
return 0;
}
// get the socket information
if (!getsockaddrlen(socko, &addrlen)) {
PyErr_SetString(bluetooth_error, "error getting socket information");
return 0;
}
Py_BEGIN_ALLOW_THREADS
res = getsockname(socko->sock_fd, (struct sockaddr *) addrbuf, &addrlen);
Py_END_ALLOW_THREADS
if (res < 0) {
PyErr_SetString(bluetooth_error, "error getting socket information");
return 0;
}
sockaddr = (struct sockaddr *)addrbuf;
// can only deal with L2CAP and RFCOMM sockets
if( socko->sock_proto != BTPROTO_L2CAP &&
socko->sock_proto != BTPROTO_RFCOMM ) {
PyErr_SetString(bluetooth_error,
"Sorry, can only advertise L2CAP and RFCOMM sockets for now");
return 0;
}
// abort if this socket is already advertising a service
if( socko->sdp_record_handle != 0 && socko->sdp_session != NULL ) {
PyErr_SetString(bluetooth_error,
"This socket is already being used to advertise a service!\n"
"Use stop_advertising first!\n");
return 0;
}
// okay, now construct the SDP service record.
memset( &record, 0, sizeof(sdp_record_t) );
record.handle = 0xffffffff;
// make the service record publicly browsable
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
root_list = sdp_list_append(0, &root_uuid);
sdp_set_browse_groups( &record, root_list );
// set l2cap information (this will always go in)
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
l2cap_list = sdp_list_append( 0, &l2cap_uuid );
proto_list = sdp_list_append( 0, l2cap_list );
if( socko->sock_proto == BTPROTO_RFCOMM ) {
// register the RFCOMM channel for RFCOMM sockets
uint8_t rfcomm_channel = ((struct sockaddr_rc*)sockaddr)->rc_channel;
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel);
rfcomm_list = sdp_list_append( 0, &rfcomm_uuid );
sdp_list_append( rfcomm_list, channel );
sdp_list_append( proto_list, rfcomm_list );
} else {
// register the PSM for L2CAP sockets
unsigned short l2cap_psm = ((struct sockaddr_l2*)sockaddr)->l2_psm;
psm = sdp_data_alloc(SDP_UINT16, &l2cap_psm);
sdp_list_append(l2cap_list, psm);
}
// add additional protocols, if any
sdp_list_t *extra_protos_array[PySequence_Length(protocols)];
if (PySequence_Length(protocols) > 0) {
for(i = 0; i < PySequence_Length(protocols); i++) {
uuid_t *proto_uuid = (uuid_t*) malloc( sizeof( uuid_t ) );
PyObject *item = PySequence_GetItem(protocols, i);
pyunicode2uuid( item, proto_uuid );
sdp_list_t *new_list;
new_list = sdp_list_append( 0, proto_uuid );
proto_list = sdp_list_append( proto_list, new_list );
// keep track, to free the list later
extra_protos_array[i] = new_list;
}
}
access_proto_list = sdp_list_append( 0, proto_list );
sdp_set_access_protos( &record, access_proto_list );
// add service classes, if any
for(i = 0; i < PySequence_Length(service_classes); i++) {
uuid_t *svc_class_uuid = (uuid_t*) malloc( sizeof( uuid_t ) );
PyObject *item = PySequence_GetItem(service_classes, i);
pyunicode2uuid( item, svc_class_uuid );
svc_class_list = sdp_list_append(svc_class_list,
svc_class_uuid);
}
sdp_set_service_classes(&record, svc_class_list);
// add profiles, if any
for(i = 0; i < PySequence_Length(profiles); i++) {
char *profile_uuid_str;
sdp_profile_desc_t *profile_desc =
(sdp_profile_desc_t*)malloc(sizeof(sdp_profile_desc_t));
PyObject *tuple = PySequence_GetItem(profiles, i);
PyArg_ParseTuple(tuple, "sH", &profile_uuid_str,
&profile_desc->version);
str2uuid( profile_uuid_str, &profile_desc->uuid );
profile_list = sdp_list_append( profile_list, profile_desc );
}
sdp_set_profile_descs(&record, profile_list);
// set the name, provider and description
sdp_set_info_attr( &record, name, provider, description );
// set the general service ID, if needed
if( strlen(service_id_str) ) sdp_set_service_id( &record, svc_uuid );
// connect to the local SDP server, register the service record, and
// disconnect
Py_BEGIN_ALLOW_THREADS
session = sdp_connect( BDADDR_ANY, BDADDR_LOCAL, 0 );
Py_END_ALLOW_THREADS
if (!session) {
PyErr_SetFromErrno (bluetooth_error);
return 0;
}
socko->sdp_session = session;
Py_BEGIN_ALLOW_THREADS
err = sdp_record_register(session, &record, 0);
Py_END_ALLOW_THREADS
// cleanup
if( psm ) sdp_data_free( psm );
if( channel ) sdp_data_free( channel );
sdp_list_free( l2cap_list, 0 );
sdp_list_free( rfcomm_list, 0 );
for(i = 0; i < PySequence_Length(protocols); i++) {
sdp_list_free( extra_protos_array[i], free );
}
sdp_list_free( root_list, 0 );
sdp_list_free( access_proto_list, 0 );
sdp_list_free( svc_class_list, free );
sdp_list_free( profile_list, free );
if( err ) {
PyErr_SetFromErrno(bluetooth_error);
return 0;
}
socko->sdp_record_handle = record.handle;
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR( bt_sdp_advertise_service_doc,
"sdp_advertise_service( socket, name )\n\
\n\
Registers a service with the local SDP server.\n\
\n\
socket must be a bound, listening socket - you must have already\n\
called socket.listen(). Only L2CAP and RFCOMM sockets are supported.\n\
\n\
name is the name that you want to appear in the SDP record\n\
\n\
Registered services will be automatically unregistered when the socket is\n\
closed.\
");
PyObject *
bt_sdp_stop_advertising( PyObject *self, PyObject *args )
{
PySocketSockObject *socko = NULL;
if ( !PyArg_ParseTuple(args, "O!", &sock_type, &socko ) ) {
return 0;
}
// verify that we got a real socket object
if( ! socko || (Py_TYPE(socko) != &sock_type) ) {
// TODO change this to a more accurate exception type
PyErr_SetString(bluetooth_error,
"must pass in _bluetooth.socket object");
return 0;
}
if( socko->sdp_session != NULL ) {
Py_BEGIN_ALLOW_THREADS
sdp_close( socko->sdp_session );
Py_END_ALLOW_THREADS
socko->sdp_session = NULL;
socko->sdp_record_handle = 0;
} else {
PyErr_SetString( bluetooth_error, "not currently advertising!");
}
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR( bt_sdp_stop_advertising_doc,
"sdp_stop_advertising( socket )\n\
\n\
stop advertising services associated with this socket\n\
");
/* List of functions exported by this module. */
#define DECL_BT_METHOD(name, argtype) \
{ #name, (PyCFunction)bt_ ##name, argtype, bt_ ## name ## _doc }
static PyMethodDef bt_methods[] = {
DECL_BT_METHOD( hci_devid, METH_VARARGS ),
DECL_BT_METHOD( hci_get_route, METH_VARARGS ),
DECL_BT_METHOD( hci_role, METH_VARARGS ),
DECL_BT_METHOD( hci_read_clock, METH_VARARGS ),
DECL_BT_METHOD( hci_acl_conn_handle, METH_VARARGS ),
DECL_BT_METHOD( hci_open_dev, METH_VARARGS ),
DECL_BT_METHOD( hci_close_dev, METH_VARARGS ),
DECL_BT_METHOD( hci_send_cmd, METH_VARARGS ),
DECL_BT_METHOD( hci_send_req, METH_VARARGS | METH_KEYWORDS ),
DECL_BT_METHOD( hci_inquiry, METH_VARARGS | METH_KEYWORDS ),
DECL_BT_METHOD( hci_read_remote_name, METH_VARARGS | METH_KEYWORDS ),
DECL_BT_METHOD( hci_filter_new, METH_VARARGS ),
DECL_BT_METHOD( hci_filter_clear, METH_VARARGS ),
DECL_BT_METHOD( hci_filter_all_events, METH_VARARGS ),
DECL_BT_METHOD( hci_filter_all_ptypes, METH_VARARGS ),
DECL_BT_METHOD( hci_filter_clear_opcode, METH_VARARGS ),
DECL_BT_METHOD( hci_filter_set_ptype, METH_VARARGS ),
DECL_BT_METHOD( hci_filter_clear_ptype, METH_VARARGS ),
DECL_BT_METHOD( hci_filter_test_ptype, METH_VARARGS ),
DECL_BT_METHOD( hci_filter_set_event, METH_VARARGS ),
DECL_BT_METHOD( hci_filter_clear_event, METH_VARARGS ),
DECL_BT_METHOD( hci_filter_test_event, METH_VARARGS ),
DECL_BT_METHOD( hci_filter_set_opcode, METH_VARARGS ),
DECL_BT_METHOD( hci_filter_test_opcode, METH_VARARGS ),
DECL_BT_METHOD( cmd_opcode_pack, METH_VARARGS ),
DECL_BT_METHOD( cmd_opcode_ogf, METH_VARARGS ),
DECL_BT_METHOD( cmd_opcode_ocf, METH_VARARGS ),
DECL_BT_METHOD( ba2str, METH_VARARGS ),
DECL_BT_METHOD( str2ba, METH_VARARGS ),
#ifndef NO_DUP
DECL_BT_METHOD( fromfd, METH_VARARGS ),
#endif
DECL_BT_METHOD( btohs, METH_VARARGS ),
DECL_BT_METHOD( btohl, METH_VARARGS ),
DECL_BT_METHOD( htobs, METH_VARARGS ),
DECL_BT_METHOD( htobl, METH_VARARGS ),
DECL_BT_METHOD( getdefaulttimeout, METH_NOARGS ),
DECL_BT_METHOD( setdefaulttimeout, METH_O ),
DECL_BT_METHOD( sdp_advertise_service, METH_VARARGS ),
DECL_BT_METHOD( sdp_stop_advertising, METH_VARARGS ),
// DECL_BT_METHOD( advertise_service, METH_VARARGS | METH_KEYWORDS ),
{NULL, NULL} /* Sentinel */
};
#undef DECL_BT_METHOD
/* Initialize the bt module.
*/
PyDoc_STRVAR(socket_doc,
"Implementation module for bluetooth operations.\n\
\n\
See the bluetooth module for documentation.");
#if PY_MAJOR_VERSION < 3
PyMODINIT_FUNC
init_bluetooth(void)
{
Py_TYPE(&sock_type) = &PyType_Type;
Py_TYPE(&sdp_session_type) = &PyType_Type;
// Initialization steps for _bluetooth.
PyObject *m = Py_InitModule3("_bluetooth",
bt_methods,
socket_doc);
bluetooth_error = PyErr_NewException("_bluetooth.error", NULL, NULL);
if (bluetooth_error == NULL)
return;
Py_INCREF(bluetooth_error);
PyModule_AddObject(m, "error", bluetooth_error);
socket_timeout = PyErr_NewException("_bluetooth.timeout", bluetooth_error,
NULL);
if (socket_timeout == NULL)
return;
Py_INCREF(socket_timeout);
PyModule_AddObject(m, "timeout", socket_timeout);
Py_INCREF((PyObject *)&sock_type);
if (PyModule_AddObject(m, "btsocket",
(PyObject *)&sock_type) != 0)
return;
Py_INCREF((PyObject *)&sdp_session_type);
if (PyModule_AddObject(m, "SDPSession",
(PyObject *)&sdp_session_type) != 0)
return;
#else
PyMODINIT_FUNC
PyInit__bluetooth(void)
{
Py_TYPE(&sock_type) = &PyType_Type;
Py_TYPE(&sdp_session_type) = &PyType_Type;
// Initialization steps for _bluetooth.
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"_bluetooth",
socket_doc,
-1,
bt_methods,
NULL,
NULL,
NULL,
NULL
};
PyObject *m = PyModule_Create(&moduledef);
bluetooth_error = PyErr_NewException("_bluetooth.error", NULL, NULL);
if (bluetooth_error == NULL)
return NULL;
Py_INCREF(bluetooth_error);
PyModule_AddObject(m, "error", bluetooth_error);
socket_timeout = PyErr_NewException("_bluetooth.timeout", bluetooth_error,
NULL);
if (socket_timeout == NULL)
return NULL;
Py_INCREF(socket_timeout);
PyModule_AddObject(m, "timeout", socket_timeout);
Py_INCREF((PyObject *)&sock_type);
if (PyModule_AddObject(m, "btsocket",
(PyObject *)&sock_type) != 0)
return NULL;
Py_INCREF((PyObject *)&sdp_session_type);
if (PyModule_AddObject(m, "SDPSession",
(PyObject *)&sdp_session_type) != 0)
return NULL;
#endif
// because we're lazy...
#define ADD_INT_CONST(m, a) PyModule_AddIntConstant(m, #a, a)
// Global variables that can be accessible from Python.
// ADD_INT_CONST(m, PF_BLUETOOTH);
// ADD_INT_CONST(m, AF_BLUETOOTH);
ADD_INT_CONST(m, SOL_HCI);
ADD_INT_CONST(m, HCI_DATA_DIR);
ADD_INT_CONST(m, HCI_TIME_STAMP);
ADD_INT_CONST(m, HCI_FILTER);
ADD_INT_CONST(m, HCI_MAX_EVENT_SIZE);
ADD_INT_CONST(m, HCI_EVENT_HDR_SIZE);
PyModule_AddIntConstant(m, "HCI", BTPROTO_HCI);
PyModule_AddIntConstant(m, "L2CAP", BTPROTO_L2CAP);
PyModule_AddIntConstant(m, "RFCOMM", BTPROTO_RFCOMM);
PyModule_AddIntConstant(m, "SCO", BTPROTO_SCO);
// /* Socket types */
// ADD_INT_CONST(m, SOCK_STREAM);
// ADD_INT_CONST(m, SOCK_DGRAM);
// ADD_INT_CONST(m, SOCK_RAW);
// ADD_INT_CONST(m, SOCK_SEQPACKET);
/* HCI Constants */
/* HCI OGF values */
#ifdef OGF_LINK_CTL
ADD_INT_CONST(m, OGF_LINK_CTL);
#endif
#ifdef OGF_LINK_POLICY
ADD_INT_CONST(m, OGF_LINK_POLICY);
#endif
#ifdef OGF_HOST_CTL
ADD_INT_CONST(m, OGF_HOST_CTL);
#endif
#ifdef OGF_INFO_PARAM
ADD_INT_CONST(m, OGF_INFO_PARAM);
#endif
#ifdef OGF_STATUS_PARAM
ADD_INT_CONST(m, OGF_STATUS_PARAM);
#endif
#ifdef OGF_TESTING_CMD
ADD_INT_CONST(m, OGF_TESTING_CMD);
#endif
#ifdef OGF_VENDOR_CMD
ADD_INT_CONST(m, OGF_VENDOR_CMD);
#endif
/* HCI OCF values */
#ifdef OCF_INQUIRY
ADD_INT_CONST(m, OCF_INQUIRY);
#endif
#ifdef OCF_INQUIRY_CANCEL
ADD_INT_CONST(m, OCF_INQUIRY_CANCEL);
#endif
#ifdef OCF_PERIODIC_INQUIRY
ADD_INT_CONST(m, OCF_PERIODIC_INQUIRY);
#endif
#ifdef OCF_EXIT_PERIODIC_INQUIRY
ADD_INT_CONST(m, OCF_EXIT_PERIODIC_INQUIRY);
#endif
#ifdef OCF_CREATE_CONN
ADD_INT_CONST(m, OCF_CREATE_CONN);
#endif
#ifdef OCF_DISCONNECT
ADD_INT_CONST(m, OCF_DISCONNECT);
#endif
#ifdef OCF_ADD_SCO
ADD_INT_CONST(m, OCF_ADD_SCO);
#endif
#ifdef OCF_ACCEPT_CONN_REQ
ADD_INT_CONST(m, OCF_ACCEPT_CONN_REQ);
#endif
#ifdef OCF_REJECT_CONN_REQ
ADD_INT_CONST(m, OCF_REJECT_CONN_REQ);
#endif
#ifdef OCF_LINK_KEY_REPLY
ADD_INT_CONST(m, OCF_LINK_KEY_REPLY);
#endif
#ifdef OCF_LINK_KEY_NEG_REPLY
ADD_INT_CONST(m, OCF_LINK_KEY_NEG_REPLY);
#endif
#ifdef OCF_PIN_CODE_REPLY
ADD_INT_CONST(m, OCF_PIN_CODE_REPLY);
#endif
#ifdef OCF_PIN_CODE_NEG_REPLY
ADD_INT_CONST(m, OCF_PIN_CODE_NEG_REPLY);
#endif
#ifdef OCF_SET_CONN_PTYPE
ADD_INT_CONST(m, OCF_SET_CONN_PTYPE);
#endif
#ifdef OCF_AUTH_REQUESTED
ADD_INT_CONST(m, OCF_AUTH_REQUESTED);
#endif
#ifdef OCF_SET_CONN_ENCRYPT
ADD_INT_CONST(m, OCF_SET_CONN_ENCRYPT);
#endif
#ifdef OCF_REMOTE_NAME_REQ
ADD_INT_CONST(m, OCF_REMOTE_NAME_REQ);
#endif
#ifdef OCF_READ_REMOTE_FEATURES
ADD_INT_CONST(m, OCF_READ_REMOTE_FEATURES);
#endif
#ifdef OCF_READ_REMOTE_VERSION
ADD_INT_CONST(m, OCF_READ_REMOTE_VERSION);
#endif
#ifdef OCF_READ_CLOCK_OFFSET
ADD_INT_CONST(m, OCF_READ_CLOCK_OFFSET);
#endif
#ifdef OCF_READ_CLOCK_OFFSET
ADD_INT_CONST(m, OCF_READ_CLOCK);
#endif
#ifdef OCF_HOLD_MODE
ADD_INT_CONST(m, OCF_HOLD_MODE);
#endif
#ifdef OCF_SNIFF_MODE
ADD_INT_CONST(m, OCF_SNIFF_MODE);
#endif
#ifdef OCF_EXIT_SNIFF_MODE
ADD_INT_CONST(m, OCF_EXIT_SNIFF_MODE);
#endif
#ifdef OCF_PARK_MODE
ADD_INT_CONST(m, OCF_PARK_MODE);
#endif
#ifdef OCF_EXIT_PARK_MODE
ADD_INT_CONST(m, OCF_EXIT_PARK_MODE);
#endif
#ifdef OCF_QOS_SETUP
ADD_INT_CONST(m, OCF_QOS_SETUP);
#endif
#ifdef OCF_ROLE_DISCOVERY
ADD_INT_CONST(m, OCF_ROLE_DISCOVERY);
#endif
#ifdef OCF_SWITCH_ROLE
ADD_INT_CONST(m, OCF_SWITCH_ROLE);
#endif
#ifdef OCF_READ_LINK_POLICY
ADD_INT_CONST(m, OCF_READ_LINK_POLICY);
#endif
#ifdef OCF_WRITE_LINK_POLICY
ADD_INT_CONST(m, OCF_WRITE_LINK_POLICY);
#endif
#ifdef OCF_RESET
ADD_INT_CONST(m, OCF_RESET);
#endif
#ifdef OCF_SET_EVENT_FLT
ADD_INT_CONST(m, OCF_SET_EVENT_FLT);
#endif
#ifdef OCF_CHANGE_LOCAL_NAME
ADD_INT_CONST(m, OCF_CHANGE_LOCAL_NAME);
#endif
#ifdef OCF_READ_LOCAL_NAME
ADD_INT_CONST(m, OCF_READ_LOCAL_NAME);
#endif
#ifdef OCF_WRITE_CA_TIMEOUT
ADD_INT_CONST(m, OCF_WRITE_CA_TIMEOUT);
#endif
#ifdef OCF_WRITE_PG_TIMEOUT
ADD_INT_CONST(m, OCF_WRITE_PG_TIMEOUT);
#endif
#ifdef OCF_READ_PAGE_TIMEOUT
ADD_INT_CONST(m, OCF_READ_PAGE_TIMEOUT);
#endif
#ifdef OCF_WRITE_PAGE_TIMEOUT
ADD_INT_CONST(m, OCF_WRITE_PAGE_TIMEOUT);
#endif
#ifdef OCF_WRITE_SCAN_ENABLE
ADD_INT_CONST(m, OCF_WRITE_SCAN_ENABLE);
#endif
#ifdef OCF_READ_PAGE_ACTIVITY
ADD_INT_CONST(m, OCF_READ_PAGE_ACTIVITY);
#endif
#ifdef OCF_WRITE_PAGE_ACTIVITY
ADD_INT_CONST(m, OCF_WRITE_PAGE_ACTIVITY);
#endif
#ifdef OCF_READ_INQ_ACTIVITY
ADD_INT_CONST(m, OCF_READ_INQ_ACTIVITY);
#endif
#ifdef OCF_WRITE_INQ_ACTIVITY
ADD_INT_CONST(m, OCF_WRITE_INQ_ACTIVITY);
#endif
#ifdef OCF_READ_AUTH_ENABLE
ADD_INT_CONST(m, OCF_READ_AUTH_ENABLE);
#endif
#ifdef OCF_WRITE_AUTH_ENABLE
ADD_INT_CONST(m, OCF_WRITE_AUTH_ENABLE);
#endif
#ifdef OCF_READ_ENCRYPT_MODE
ADD_INT_CONST(m, OCF_READ_ENCRYPT_MODE);
#endif
#ifdef OCF_WRITE_ENCRYPT_MODE
ADD_INT_CONST(m, OCF_WRITE_ENCRYPT_MODE);
#endif
#ifdef OCF_READ_CLASS_OF_DEV
ADD_INT_CONST(m, OCF_READ_CLASS_OF_DEV);
#endif
#ifdef OCF_WRITE_CLASS_OF_DEV
ADD_INT_CONST(m, OCF_WRITE_CLASS_OF_DEV);
#endif
#ifdef OCF_READ_VOICE_SETTING
ADD_INT_CONST(m, OCF_READ_VOICE_SETTING);
#endif
#ifdef OCF_WRITE_VOICE_SETTING
ADD_INT_CONST(m, OCF_WRITE_VOICE_SETTING);
#endif
#ifdef OCF_READ_TRANSMIT_POWER_LEVEL
ADD_INT_CONST(m, OCF_READ_TRANSMIT_POWER_LEVEL);
#endif
#ifdef OCF_HOST_BUFFER_SIZE
ADD_INT_CONST(m, OCF_HOST_BUFFER_SIZE);
#endif
#ifdef OCF_READ_LINK_SUPERVISION_TIMEOUT
ADD_INT_CONST(m, OCF_READ_LINK_SUPERVISION_TIMEOUT);
#endif
#ifdef OCF_WRITE_LINK_SUPERVISION_TIMEOUT
ADD_INT_CONST(m, OCF_WRITE_LINK_SUPERVISION_TIMEOUT);
#endif
#ifdef OCF_READ_CURRENT_IAC_LAP
ADD_INT_CONST(m, OCF_READ_CURRENT_IAC_LAP);
#endif
#ifdef OCF_WRITE_CURRENT_IAC_LAP
ADD_INT_CONST(m, OCF_WRITE_CURRENT_IAC_LAP);
#endif
#ifdef OCF_READ_INQUIRY_MODE
ADD_INT_CONST(m, OCF_READ_INQUIRY_MODE);
#endif
#ifdef OCF_WRITE_INQUIRY_MODE
ADD_INT_CONST(m, OCF_WRITE_INQUIRY_MODE);
#endif
#ifdef OCF_READ_AFH_MODE
ADD_INT_CONST(m, OCF_READ_AFH_MODE);
#endif
#ifdef OCF_WRITE_AFH_MODE
ADD_INT_CONST(m, OCF_WRITE_AFH_MODE);
#endif
#ifdef OCF_READ_LOCAL_VERSION
ADD_INT_CONST(m, OCF_READ_LOCAL_VERSION);
#endif
#ifdef OCF_READ_LOCAL_FEATURES
ADD_INT_CONST(m, OCF_READ_LOCAL_FEATURES);
#endif
#ifdef OCF_READ_BUFFER_SIZE
ADD_INT_CONST(m, OCF_READ_BUFFER_SIZE);
#endif
#ifdef OCF_READ_BD_ADDR
ADD_INT_CONST(m, OCF_READ_BD_ADDR);
#endif
#ifdef OCF_READ_FAILED_CONTACT_COUNTER
ADD_INT_CONST(m, OCF_READ_FAILED_CONTACT_COUNTER);
#endif
#ifdef OCF_RESET_FAILED_CONTACT_COUNTER
ADD_INT_CONST(m, OCF_RESET_FAILED_CONTACT_COUNTER);
#endif
#ifdef OCF_GET_LINK_QUALITY
ADD_INT_CONST(m, OCF_GET_LINK_QUALITY);
#endif
#ifdef OCF_READ_RSSI
ADD_INT_CONST(m, OCF_READ_RSSI);
#endif
#ifdef OCF_READ_AFH_MAP
ADD_INT_CONST(m, OCF_READ_AFH_MAP);
#endif
/* HCI events */
#ifdef EVT_INQUIRY_COMPLETE
ADD_INT_CONST(m, EVT_INQUIRY_COMPLETE);
#endif
#ifdef EVT_INQUIRY_RESULT
ADD_INT_CONST(m, EVT_INQUIRY_RESULT);
#endif
#ifdef EVT_CONN_COMPLETE
ADD_INT_CONST(m, EVT_CONN_COMPLETE);
#endif
#ifdef EVT_CONN_COMPLETE_SIZE
ADD_INT_CONST(m, EVT_CONN_COMPLETE_SIZE);
#endif
#ifdef EVT_CONN_REQUEST
ADD_INT_CONST(m, EVT_CONN_REQUEST);
#endif
#ifdef EVT_CONN_REQUEST_SIZE
ADD_INT_CONST(m, EVT_CONN_REQUEST_SIZE);
#endif
#ifdef EVT_DISCONN_COMPLETE
ADD_INT_CONST(m, EVT_DISCONN_COMPLETE);
#endif
#ifdef EVT_DISCONN_COMPLETE_SIZE
ADD_INT_CONST(m, EVT_DISCONN_COMPLETE_SIZE);
#endif
#ifdef EVT_AUTH_COMPLETE
ADD_INT_CONST(m, EVT_AUTH_COMPLETE);
#endif
#ifdef EVT_AUTH_COMPLETE_SIZE
ADD_INT_CONST(m, EVT_AUTH_COMPLETE_SIZE);
#endif
#ifdef EVT_REMOTE_NAME_REQ_COMPLETE
ADD_INT_CONST(m, EVT_REMOTE_NAME_REQ_COMPLETE);
#endif
#ifdef EVT_REMOTE_NAME_REQ_COMPLETE_SIZE
ADD_INT_CONST(m, EVT_REMOTE_NAME_REQ_COMPLETE_SIZE);
#endif
#ifdef EVT_ENCRYPT_CHANGE
ADD_INT_CONST(m, EVT_ENCRYPT_CHANGE);
#endif
#ifdef EVT_ENCRYPT_CHANGE_SIZE
ADD_INT_CONST(m, EVT_ENCRYPT_CHANGE_SIZE);
#endif
#ifdef EVT_READ_REMOTE_FEATURES_COMPLETE
ADD_INT_CONST(m, EVT_READ_REMOTE_FEATURES_COMPLETE);
#endif
#ifdef EVT_READ_REMOTE_FEATURES_COMPLETE_SIZE
ADD_INT_CONST(m, EVT_READ_REMOTE_FEATURES_COMPLETE_SIZE);
#endif
#ifdef EVT_READ_REMOTE_VERSION_COMPLETE
ADD_INT_CONST(m, EVT_READ_REMOTE_VERSION_COMPLETE);
#endif
#ifdef EVT_READ_REMOTE_VERSION_COMPLETE_SIZE
ADD_INT_CONST(m, EVT_READ_REMOTE_VERSION_COMPLETE_SIZE);
#endif
#ifdef EVT_QOS_SETUP_COMPLETE
ADD_INT_CONST(m, EVT_QOS_SETUP_COMPLETE);
#endif
#ifdef EVT_QOS_SETUP_COMPLETE_SIZE
ADD_INT_CONST(m, EVT_QOS_SETUP_COMPLETE_SIZE);
#endif
#ifdef EVT_CMD_COMPLETE
ADD_INT_CONST(m, EVT_CMD_COMPLETE);
#endif
#ifdef EVT_CMD_COMPLETE_SIZE
ADD_INT_CONST(m, EVT_CMD_COMPLETE_SIZE);
#endif
#ifdef EVT_CMD_STATUS
ADD_INT_CONST(m, EVT_CMD_STATUS);
#endif
#ifdef EVT_CMD_STATUS_SIZE
ADD_INT_CONST(m, EVT_CMD_STATUS_SIZE);
#endif
#ifdef EVT_ROLE_CHANGE
ADD_INT_CONST(m, EVT_ROLE_CHANGE);
#endif
#ifdef EVT_ROLE_CHANGE_SIZE
ADD_INT_CONST(m, EVT_ROLE_CHANGE_SIZE);
#endif
#ifdef EVT_NUM_COMP_PKTS
ADD_INT_CONST(m, EVT_NUM_COMP_PKTS);
#endif
#ifdef EVT_NUM_COMP_PKTS_SIZE
ADD_INT_CONST(m, EVT_NUM_COMP_PKTS_SIZE);
#endif
#ifdef EVT_MODE_CHANGE
ADD_INT_CONST(m, EVT_MODE_CHANGE);
#endif
#ifdef EVT_MODE_CHANGE_SIZE
ADD_INT_CONST(m, EVT_MODE_CHANGE_SIZE);
#endif
#ifdef EVT_PIN_CODE_REQ
ADD_INT_CONST(m, EVT_PIN_CODE_REQ);
#endif
#ifdef EVT_PIN_CODE_REQ_SIZE
ADD_INT_CONST(m, EVT_PIN_CODE_REQ_SIZE);
#endif
#ifdef EVT_LINK_KEY_REQ
ADD_INT_CONST(m, EVT_LINK_KEY_REQ);
#endif
#ifdef EVT_LINK_KEY_REQ_SIZE
ADD_INT_CONST(m, EVT_LINK_KEY_REQ_SIZE);
#endif
#ifdef EVT_LINK_KEY_NOTIFY
ADD_INT_CONST(m, EVT_LINK_KEY_NOTIFY);
#endif
#ifdef EVT_LINK_KEY_NOTIFY_SIZE
ADD_INT_CONST(m, EVT_LINK_KEY_NOTIFY_SIZE);
#endif
#ifdef EVT_READ_CLOCK_OFFSET_COMPLETE
ADD_INT_CONST(m, EVT_READ_CLOCK_OFFSET_COMPLETE);
#endif
#ifdef EVT_READ_CLOCK_OFFSET_COMPLETE_SIZE
ADD_INT_CONST(m, EVT_READ_CLOCK_OFFSET_COMPLETE_SIZE);
#endif
#ifdef EVT_CONN_PTYPE_CHANGED
ADD_INT_CONST(m, EVT_CONN_PTYPE_CHANGED);
#endif
#ifdef EVT_CONN_PTYPE_CHANGED_SIZE
ADD_INT_CONST(m, EVT_CONN_PTYPE_CHANGED_SIZE);
#endif
#ifdef EVT_QOS_VIOLATION
ADD_INT_CONST(m, EVT_QOS_VIOLATION);
#endif
#ifdef EVT_QOS_VIOLATION_SIZE
ADD_INT_CONST(m, EVT_QOS_VIOLATION_SIZE);
#endif
#ifdef EVT_INQUIRY_RESULT_WITH_RSSI
ADD_INT_CONST(m, EVT_INQUIRY_RESULT_WITH_RSSI);
#endif
#ifdef EVT_EXTENDED_INQUIRY_RESULT
ADD_INT_CONST(m, EVT_EXTENDED_INQUIRY_RESULT);
PyModule_AddIntConstant(m, "HAVE_EVT_EXTENDED_INQUIRY_RESULT", 1);
#else
PyModule_AddIntConstant(m, "HAVE_EVT_EXTENDED_INQUIRY_RESULT", 0);
#endif
#ifdef EVT_TESTING
ADD_INT_CONST(m, EVT_TESTING);
#endif
#ifdef EVT_VENDOR
ADD_INT_CONST(m, EVT_VENDOR);
#endif
#ifdef EVT_STACK_INTERNAL
ADD_INT_CONST(m, EVT_STACK_INTERNAL);
#endif
#ifdef EVT_STACK_INTERNAL_SIZE
ADD_INT_CONST(m, EVT_STACK_INTERNAL_SIZE);
#endif
#ifdef EVT_SI_DEVICE
ADD_INT_CONST(m, EVT_SI_DEVICE);
#endif
#ifdef EVT_SI_DEVICE_SIZE
ADD_INT_CONST(m, EVT_SI_DEVICE_SIZE);
#endif
#ifdef EVT_SI_SECURITY
ADD_INT_CONST(m, EVT_SI_SECURITY);
#endif
/* HCI packet types */
#ifdef HCI_COMMAND_PKT
ADD_INT_CONST(m, HCI_COMMAND_PKT);
#endif
#ifdef HCI_ACLDATA_PKT
ADD_INT_CONST(m, HCI_ACLDATA_PKT);
#endif
#ifdef HCI_SCODATA_PKT
ADD_INT_CONST(m, HCI_SCODATA_PKT);
#endif
#ifdef HCI_EVENT_PKT
ADD_INT_CONST(m, HCI_EVENT_PKT);
#endif
#ifdef HCI_UNKNOWN_PKT
ADD_INT_CONST(m, HCI_UNKNOWN_PKT);
#endif
/* socket options */
#ifdef SO_DEBUG
ADD_INT_CONST(m, SO_DEBUG);
#endif
#ifdef SO_ACCEPTCONN
ADD_INT_CONST(m, SO_ACCEPTCONN);
#endif
#ifdef SO_REUSEADDR
ADD_INT_CONST(m, SO_REUSEADDR);
#endif
#ifdef SO_KEEPALIVE
ADD_INT_CONST(m, SO_KEEPALIVE);
#endif
#ifdef SO_DONTROUTE
ADD_INT_CONST(m, SO_DONTROUTE);
#endif
#ifdef SO_BROADCAST
ADD_INT_CONST(m, SO_BROADCAST);
#endif
#ifdef SO_USELOOPBACK
ADD_INT_CONST(m, SO_USELOOPBACK);
#endif
#ifdef SO_LINGER
ADD_INT_CONST(m, SO_LINGER);
#endif
#ifdef SO_OOBINLINE
ADD_INT_CONST(m, SO_OOBINLINE);
#endif
#ifdef SO_REUSEPORT
ADD_INT_CONST(m, SO_REUSEPORT);
#endif
#ifdef SO_SNDBUF
ADD_INT_CONST(m, SO_SNDBUF);
#endif
#ifdef SO_RCVBUF
ADD_INT_CONST(m, SO_RCVBUF);
#endif
#ifdef SO_SNDLOWAT
ADD_INT_CONST(m, SO_SNDLOWAT);
#endif
#ifdef SO_RCVLOWAT
ADD_INT_CONST(m, SO_RCVLOWAT);
#endif
#ifdef SO_SNDTIMEO
ADD_INT_CONST(m, SO_SNDTIMEO);
#endif
#ifdef SO_RCVTIMEO
ADD_INT_CONST(m, SO_RCVTIMEO);
#endif
#ifdef SO_ERROR
ADD_INT_CONST(m, SO_ERROR);
#endif
#ifdef SO_TYPE
ADD_INT_CONST(m, SO_TYPE);
#endif
/* Maximum number of connections for "listen" */
#ifdef SOMAXCONN
ADD_INT_CONST(m, SOMAXCONN);
#else
ADD_INT_CONST(m, SOMAXCONN);
#endif
/* Flags for send, recv */
#ifdef MSG_OOB
ADD_INT_CONST(m, MSG_OOB);
#endif
#ifdef MSG_PEEK
ADD_INT_CONST(m, MSG_PEEK);
#endif
#ifdef MSG_DONTROUTE
ADD_INT_CONST(m, MSG_DONTROUTE);
#endif
#ifdef MSG_DONTWAIT
ADD_INT_CONST(m, MSG_DONTWAIT);
#endif
#ifdef MSG_EOR
ADD_INT_CONST(m, MSG_EOR);
#endif
#ifdef MSG_TRUNC
ADD_INT_CONST(m, MSG_TRUNC);
#endif
#ifdef MSG_CTRUNC
ADD_INT_CONST(m, MSG_CTRUNC);
#endif
#ifdef MSG_WAITALL
ADD_INT_CONST(m, MSG_WAITALL);
#endif
#ifdef MSG_BTAG
ADD_INT_CONST(m, MSG_BTAG);
#endif
#ifdef MSG_ETAG
ADD_INT_CONST(m, MSG_ETAG);
#endif
/* Size of inquiry info */
#ifdef INQUIRY_INFO_WITH_RSSI_SIZE
ADD_INT_CONST(m, INQUIRY_INFO_WITH_RSSI_SIZE);
#endif
#ifdef EXTENDED_INQUIRY_INFO_SIZE
ADD_INT_CONST(m, EXTENDED_INQUIRY_INFO_SIZE);
#endif
/* Protocol level and numbers, usable for [gs]etsockopt */
ADD_INT_CONST(m, SOL_SOCKET);
ADD_INT_CONST(m, SOL_L2CAP);
ADD_INT_CONST(m, SOL_RFCOMM);
ADD_INT_CONST(m, SOL_SCO);
ADD_INT_CONST(m, SCO_OPTIONS);
ADD_INT_CONST(m, L2CAP_OPTIONS);
/* ioctl */
ADD_INT_CONST(m, HCIDEVUP);
ADD_INT_CONST(m, HCIDEVDOWN);
ADD_INT_CONST(m, HCIDEVRESET);
ADD_INT_CONST(m, HCIDEVRESTAT);
ADD_INT_CONST(m, HCIGETDEVLIST);
ADD_INT_CONST(m, HCIGETDEVINFO);
ADD_INT_CONST(m, HCIGETCONNLIST);
ADD_INT_CONST(m, HCIGETCONNINFO);
ADD_INT_CONST(m, HCISETRAW);
ADD_INT_CONST(m, HCISETSCAN);
ADD_INT_CONST(m, HCISETAUTH);
ADD_INT_CONST(m, HCISETENCRYPT);
ADD_INT_CONST(m, HCISETPTYPE);
ADD_INT_CONST(m, HCISETLINKPOL);
ADD_INT_CONST(m, HCISETLINKMODE);
ADD_INT_CONST(m, HCISETACLMTU);
ADD_INT_CONST(m, HCISETSCOMTU);
ADD_INT_CONST(m, HCIINQUIRY);
ADD_INT_CONST(m, ACL_LINK);
ADD_INT_CONST(m, SCO_LINK);
/* RFCOMM */
ADD_INT_CONST(m, RFCOMM_LM);
ADD_INT_CONST(m, RFCOMM_LM_MASTER);
ADD_INT_CONST(m, RFCOMM_LM_AUTH );
ADD_INT_CONST(m, RFCOMM_LM_ENCRYPT);
ADD_INT_CONST(m, RFCOMM_LM_TRUSTED);
ADD_INT_CONST(m, RFCOMM_LM_RELIABLE);
ADD_INT_CONST(m, RFCOMM_LM_SECURE);
/* L2CAP */
ADD_INT_CONST(m, L2CAP_LM);
ADD_INT_CONST(m, L2CAP_LM_MASTER);
ADD_INT_CONST(m, L2CAP_LM_AUTH);
ADD_INT_CONST(m, L2CAP_LM_ENCRYPT);
ADD_INT_CONST(m, L2CAP_LM_TRUSTED);
ADD_INT_CONST(m, L2CAP_LM_RELIABLE);
ADD_INT_CONST(m, L2CAP_LM_SECURE);
ADD_INT_CONST(m, L2CAP_COMMAND_REJ);
ADD_INT_CONST(m, L2CAP_CONN_REQ );
ADD_INT_CONST(m, L2CAP_CONN_RSP );
ADD_INT_CONST(m, L2CAP_CONF_REQ );
ADD_INT_CONST(m, L2CAP_CONF_RSP );
ADD_INT_CONST(m, L2CAP_DISCONN_REQ);
ADD_INT_CONST(m, L2CAP_DISCONN_RSP);
ADD_INT_CONST(m, L2CAP_ECHO_REQ );
ADD_INT_CONST(m, L2CAP_ECHO_RSP );
ADD_INT_CONST(m, L2CAP_INFO_REQ );
ADD_INT_CONST(m, L2CAP_INFO_RSP );
ADD_INT_CONST(m, L2CAP_MODE_BASIC);
ADD_INT_CONST(m, L2CAP_MODE_RETRANS);
ADD_INT_CONST(m, L2CAP_MODE_FLOWCTL);
ADD_INT_CONST(m, L2CAP_MODE_ERTM);
ADD_INT_CONST(m, L2CAP_MODE_STREAMING);
ADD_INT_CONST(m, BT_SECURITY);
ADD_INT_CONST(m, BT_SECURITY_SDP);
ADD_INT_CONST(m, BT_SECURITY_LOW);
ADD_INT_CONST(m, BT_SECURITY_MEDIUM);
ADD_INT_CONST(m, BT_SECURITY_HIGH);
#ifdef BT_DEFER_SETUP
ADD_INT_CONST(m, BT_DEFER_SETUP);
#endif
ADD_INT_CONST(m, SOL_BLUETOOTH);
#undef ADD_INT_CONST
#if PY_MAJOR_VERSION >= 3
return m;
#endif
}
/*
* Affix socket module
* Socket module for python based in the original socket module for python
* This code is a copy from socket.c source code from python2.2 with
* updates/modifications to support affix socket interface *
* AAA FFFFFFF FFFFFFF IIIIIII X X
* A A F F I X X
* A A F F I X X
* AAAAAAA FFFF FFFF I X X
* A A F F I X X
* A A F F IIIIIII X X
*
* Any modifications of this sourcecode must keep this information !!!!!
*
* by Carlos Chinea
* (C) Nokia Research Center, 2004
*/
pybluez-0.22+really0.22/bluez/btmodule.h 0000664 0000000 0000000 00000002362 13346112537 0020032 0 ustar 00root root 0000000 0000000 #ifndef __btmodule_h__
#define __btmodule_h__
#include "Python.h"
#include
#include
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/* The object holding a socket. It holds some extra information,
like the address family, which is used to decode socket address
arguments properly. */
typedef struct {
PyObject_HEAD
int sock_fd; /* Socket file descriptor */
int sock_family; /* Address family, always AF_BLUETOOTH */
int sock_type; /* Socket type, e.g., SOCK_STREAM */
int sock_proto; /* Protocol type, e.g., BTPROTO_L2CAP */
PyObject *(*errorhandler)(void); /* Error handler; checks
errno, returns NULL and
sets a Python exception */
double sock_timeout; /* Operation timeout in seconds;
0.0 means non-blocking */
int is_listening_socket; // XXX this is a hack to make
// sdp_advertise_service easier
uint32_t sdp_record_handle; // if it's a listening socket and advertised
// via SDP, this is the SDP handle
sdp_session_t *sdp_session;
} PySocketSockObject;
#ifdef __cplusplus
}
#endif
extern PyObject *bluetooth_error;
#endif // __btmodule_h__
pybluez-0.22+really0.22/bluez/btsdp.c 0000664 0000000 0000000 00000034044 13346112537 0017330 0 ustar 00root root 0000000 0000000 #include "Python.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "btmodule.h"
#include "btsdp.h"
extern PyTypeObject sock_type;
extern int getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret);
extern PyObject *set_error(void);
extern int str2uuid( const char *uuid_str, uuid_t *uuid );
extern void uuid2str( const uuid_t *uuid, char *dest );
// =================== utility functions =====================
static void
dict_set_str_pyobj(PyObject *dict, const char *key, PyObject *valobj)
{
PyObject *keyobj;
keyobj = PyString_FromString( key );
PyDict_SetItem( dict, keyobj, valobj );
Py_DECREF( keyobj );
}
static void
dict_set_strings(PyObject *dict, const char *key, const char *val)
{
PyObject *keyobj, *valobj;
keyobj = PyString_FromString( key );
valobj = PyString_FromString( val );
PyDict_SetItem( dict, keyobj, valobj );
Py_DECREF( keyobj );
Py_DECREF( valobj );
}
static void
dict_set_str_long(PyObject *dict, const char *key, long val)
{
PyObject *keyobj, *valobj;
keyobj = PyString_FromString( key );
valobj = PyInt_FromLong(val);
PyDict_SetItem( dict, keyobj, valobj );
Py_DECREF( keyobj );
Py_DECREF( valobj );
}
PyDoc_STRVAR(sess_doc,
"SDPSession()\n\
\n\
TODO\n\
");
/*
* utility function to perform an SDP search on a connected session. Builds
* and returns a python list of dictionaries. Each dictionary represents a
* service record match
*/
static PyObject *
do_search( sdp_session_t *sess, uuid_t *uuid )
{
sdp_list_t *response_list = NULL, *attrid_list, *search_list, *r;
uint32_t range = 0x0000ffff;
char buf[1024] = { 0 };
int err = 0;
PyObject *result = 0;
PyObject *rtn_list = PyList_New(0);
if( ! rtn_list ) return 0;
search_list = sdp_list_append( 0, uuid );
attrid_list = sdp_list_append( 0, &range );
// perform the search
Py_BEGIN_ALLOW_THREADS
err = sdp_service_search_attr_req( sess, search_list, \
SDP_ATTR_REQ_RANGE, attrid_list, &response_list);
Py_END_ALLOW_THREADS
if( err ) {
PyErr_SetFromErrno( bluetooth_error );
result = 0;
goto cleanup;
}
// parse the results (ewww....)
// go through each of the service records
for (r = response_list; r; r = r->next ) {
PyObject *dict = PyDict_New();
sdp_record_t *rec = (sdp_record_t*) r->data;
sdp_list_t *proto_list = NULL,
*svc_class_list = NULL,
*profile_list = NULL;
PyObject *py_class_list = NULL, *py_profile_list = NULL;
uuid_t service_id = { 0 };
if( ! dict ) return 0;
// initialize service class list
py_class_list = PyList_New(0);
if( ! py_class_list ) return 0;
dict_set_str_pyobj( dict, "service-classes", py_class_list );
Py_DECREF( py_class_list );
// initialize profile list
py_profile_list = PyList_New(0);
if( ! py_profile_list ) return 0;
dict_set_str_pyobj( dict, "profiles", py_profile_list );
Py_DECREF( py_profile_list );
// set service name
if( ! sdp_get_service_name( rec, buf, sizeof(buf) ) ) {
dict_set_strings( dict, "name", buf );
memset(buf, 0, sizeof( buf ) );
} else {
dict_set_str_pyobj( dict, "name", Py_None );
}
// set service description
if( ! sdp_get_service_desc( rec, buf, sizeof(buf) ) ) {
dict_set_strings( dict, "description", buf );
memset(buf, 0, sizeof( buf ) );
} else {
dict_set_str_pyobj( dict, "description", Py_None );
}
// set service provider name
if( ! sdp_get_provider_name( rec, buf, sizeof(buf) ) ) {
dict_set_strings( dict, "provider", buf );
memset(buf, 0, sizeof( buf ) );
} else {
dict_set_str_pyobj( dict, "provider", Py_None );
}
// set service id
if( ! sdp_get_service_id( rec, &service_id ) ) {
uuid2str( &service_id, buf );
dict_set_strings( dict, "service-id", buf );
memset(buf, 0, sizeof( buf ) );
} else {
dict_set_str_pyobj( dict, "service-id", Py_None );
}
// get a list of the protocol sequences
if( sdp_get_access_protos( rec, &proto_list ) == 0 ) {
sdp_list_t *p = proto_list;
int port;
if( ( port = sdp_get_proto_port( p, RFCOMM_UUID ) ) != 0 ) {
dict_set_strings( dict, "protocol", "RFCOMM" );
dict_set_str_long( dict, "port", port );
} else if ( (port = sdp_get_proto_port( p, L2CAP_UUID ) ) != 0 ) {
dict_set_strings( dict, "protocol", "L2CAP" );
dict_set_str_long( dict, "port", port );
} else {
dict_set_strings( dict, "protocol", "UNKNOWN" );
dict_set_str_pyobj( dict, "port", Py_None );
}
// sdp_get_access_protos allocates data on the heap for the
// protocol list, so we need to free the results...
for( ; p ; p = p->next ) {
sdp_list_free( (sdp_list_t*)p->data, 0 );
}
sdp_list_free( proto_list, 0 );
} else {
dict_set_str_pyobj( dict, "protocol", Py_None );
dict_set_str_pyobj( dict, "port", Py_None );
}
// get a list of the service classes
if( sdp_get_service_classes( rec, &svc_class_list ) == 0 ) {
sdp_list_t *iter;
for( iter = svc_class_list; iter != NULL; iter = iter->next ) {
PyObject *pystr;
char uuid_str[40] = { 0 };
uuid2str( (uuid_t*)iter->data, uuid_str );
pystr = PyString_FromString( uuid_str );
PyList_Append( py_class_list, pystr );
Py_DECREF( pystr );
}
sdp_list_free( svc_class_list, free );
}
// get a list of the profiles
if( sdp_get_profile_descs( rec, &profile_list ) == 0 ) {
sdp_list_t *iter;
for( iter = profile_list; iter != NULL; iter = iter->next ) {
PyObject *tuple, *py_uuid, *py_version;
sdp_profile_desc_t *desc = (sdp_profile_desc_t*)iter->data;
char uuid_str[40] = { 0 };
uuid2str( &desc->uuid, uuid_str );
py_uuid = PyString_FromString( uuid_str );
py_version = PyInt_FromLong( desc->version );
tuple = PyTuple_New( 2 );
PyList_Append( py_profile_list, tuple );
Py_DECREF( tuple );
PyTuple_SetItem( tuple, 0, py_uuid );
PyTuple_SetItem( tuple, 1, py_version );
// Py_DECREF( py_uuid );
// Py_DECREF( py_version );
}
sdp_list_free( profile_list, free );
}
PyList_Append( rtn_list, dict );
Py_DECREF( dict );
sdp_record_free( rec );
}
result = rtn_list;
cleanup:
sdp_list_free( response_list, 0 );
sdp_list_free( search_list, 0 );
sdp_list_free( attrid_list, 0 );
return result;
}
// ==================== SDPSession methods ===========================
// connect
static PyObject *
sess_connect(PySDPSessionObject *s, PyObject *args, PyObject *kwds)
{
bdaddr_t src;
bdaddr_t dst;
char *dst_buf = "localhost";
uint32_t flags = SDP_RETRY_IF_BUSY;
static char *keywords[] = {"target", 0};
bacpy( &src, BDADDR_ANY );
bacpy( &dst, BDADDR_LOCAL );
if( s->session != NULL ) {
sdp_close( s->session );
}
if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|s", keywords,
&dst_buf))
return NULL;
if( strncmp( dst_buf, "localhost", 18 ) != 0 ) {
str2ba( dst_buf, &dst );
} else {
// XXX
}
Py_BEGIN_ALLOW_THREADS
s->session = sdp_connect( &src, &dst, flags );
Py_END_ALLOW_THREADS
if( s->session == NULL )
return PyErr_SetFromErrno( bluetooth_error );
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(sess_connect_doc,
"connect( dest = \"localhost\" )\n\
\n\
Connects the SDP session to the SDP server specified by dest. If the\n\
session was already connected, it's closed first.\n\
\n\
dest specifies the bluetooth address of the server to connect to. Special\n\
case is \"localhost\"\n\
\n\
raises _bluetooth.error if something goes wrong\n\
");
// close
static PyObject *
sess_close(PySDPSessionObject *s)
{
if( s->session != NULL ) {
Py_BEGIN_ALLOW_THREADS
sdp_close( s->session );
Py_END_ALLOW_THREADS
s->session = NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(sess_close_doc,
"close()\n\
\n\
closes the connection with the SDP server. No effect if a session is not open.\n\
");
// fileno
static PyObject *
sess_fileno(PySDPSessionObject *s)
{
return PyInt_FromLong((long) s->session->sock);
}
PyDoc_STRVAR(sess_fileno_doc,
"fileno() -> integer\n\
\n\
Return the integer file descriptor of the socket.\n\
You can use this for direct communication with the SDP server.\n\
");
// search
static PyObject *
sess_search(PySDPSessionObject *s, PyObject *args, PyObject *kwds)
{
char *uuid_str = 0;
uuid_t uuid = { 0 };
PyObject *result = 0;
if (!PyArg_ParseTuple(args, "s", &uuid_str)) return NULL;
// convert the UUID string into a uuid_t
if( ! str2uuid( uuid_str, &uuid ) ) {
PyErr_SetString(PyExc_ValueError, "invalid UUID!");
return NULL;
}
// make sure the SDP session is open
if( ! s->session ) {
PyErr_SetString( bluetooth_error, "SDP session is not active!" );
return 0;
}
// perform the search
result = do_search( s->session, &uuid );
return result;
}
PyDoc_STRVAR(sess_search_doc,
"search( UUID )\n\
\n\
Searches for a service record with the specified UUID. If no match is found,\n\
returns None. Otherwise, returns a dictionary\n\
\n\
UUID must be in the form \"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\", \n\
where each X is a hexadecimal digit.\n\
");
// browse
static PyObject *
sess_browse(PySDPSessionObject *s)
{
uuid_t uuid = { 0 };
PyObject *result = 0;
// convert the UUID string into a uuid_t
sdp_uuid16_create(&uuid, PUBLIC_BROWSE_GROUP);
// make sure the SDP session is open
if( ! s->session ) {
PyErr_SetString( bluetooth_error, "SDP session is not active!" );
return 0;
}
// perform the search
result = do_search( s->session, &uuid );
return result;
}
PyDoc_STRVAR(sess_browse_doc,
"browse()\n\
\n\
Browses all services advertised by connected SDP session\n\
");
static PyMethodDef sess_methods[] = {
{ "search", (PyCFunction) sess_search, METH_VARARGS,
sess_search_doc },
{ "browse", (PyCFunction) sess_browse, METH_NOARGS,
sess_browse_doc },
{ "fileno", (PyCFunction)sess_fileno, METH_NOARGS,
sess_fileno_doc },
{ "connect", (PyCFunction) sess_connect, METH_VARARGS | METH_KEYWORDS,
sess_connect_doc },
{ "close", (PyCFunction)sess_close, METH_NOARGS,
sess_close_doc },
{NULL, NULL}
};
/* =============== object maintenance =============== */
/* Deallocate a socket object in response to the last Py_DECREF().
First close the file description. */
static void
sess_dealloc(PySDPSessionObject *s)
{
if(s->session != NULL) {
sdp_close( s->session );
s->session = NULL;
}
Py_TYPE(s)->tp_free((PyObject *)s);
}
static PyObject *
sess_repr(PySDPSessionObject *s)
{
char buf[512];
if (s->session != NULL) {
PyOS_snprintf( buf, sizeof(buf),
"");
} else {
PyOS_snprintf( buf, sizeof(buf),
"");
}
return PyString_FromString(buf);
}
/* Create a new, uninitialized socket object. */
static PyObject *
sess_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *newsess;
newsess = type->tp_alloc(type, 0);
if (newsess != NULL) {
((PySDPSessionObject *)newsess)->session = NULL;
}
return newsess;
}
/* Initialize a new socket object. */
/*ARGSUSED*/
static int
sess_initobj(PyObject *self, PyObject *args, PyObject *kwds)
{
PySDPSessionObject *s = (PySDPSessionObject *)self;
s->errorhandler = &set_error;
/* From now on, ignore SIGPIPE and let the error checking
do the work. */
#ifdef SIGPIPE
(void) signal(SIGPIPE, SIG_IGN);
#endif
return 0;
}
/* Type object for socket objects. */
PyTypeObject sdp_session_type = {
#if PY_MAJOR_VERSION < 3
PyObject_HEAD_INIT(0) /* Must fill in type value later */
0, /* ob_size */
#else
PyVarObject_HEAD_INIT(NULL, 0) /* Must fill in type value later */
#endif
"_bluetooth.SDPSession", /* tp_name */
sizeof(PySDPSessionObject), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)sess_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)sess_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
sess_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
sess_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
sess_initobj, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
sess_new, /* tp_new */
PyObject_Del, /* tp_free */
};
pybluez-0.22+really0.22/bluez/btsdp.h 0000664 0000000 0000000 00000000565 13346112537 0017336 0 ustar 00root root 0000000 0000000 #ifndef __pybluez_sdp_h__
#define __pybluez_sdp_h__
#include
#include
typedef struct {
PyObject_HEAD
sdp_session_t *session;
PyObject *(*errorhandler)(void); /* Error handler; checks
errno, returns NULL and
sets a Python exception */
} PySDPSessionObject;
extern PyTypeObject sdp_session_type;
#endif
pybluez-0.22+really0.22/docs/ 0000775 0000000 0000000 00000000000 13346112537 0015652 5 ustar 00root root 0000000 0000000 pybluez-0.22+really0.22/docs/epydoc.css 0000664 0000000 0000000 00000010456 13346112537 0017655 0 ustar 00root root 0000000 0000000
/* Body color */
body { background: #ffffff; color: #000000; }
/* Tables */
table.summary, table.details, table.index
{ background: #e8f0f8; color: #000000; }
tr.summary, tr.details, tr.index
{ background: #70b0f0; color: #000000;
text-align: left; font-size: 120%; }
tr.group { background: #c0e0f8; color: #000000;
text-align: left; font-size: 120%;
font-style: italic; }
/* Documentation page titles */
h2.module { margin-top: 0.2em; }
h2.class { margin-top: 0.2em; }
/* Headings */
h1.heading { font-size: +140%; font-style: italic;
font-weight: bold; }
h2.heading { font-size: +125%; font-style: italic;
font-weight: bold; }
h3.heading { font-size: +110%; font-style: italic;
font-weight: normal; }
/* Base tree */
pre.base-tree { font-size: 80%; margin: 0; }
/* Details Sections */
table.func-details { background: #e8f0f8; color: #000000;
border: 2px groove #c0d0d0;
padding: 0 1em 0 1em; margin: 0.4em 0 0 0; }
h3.func-detail { background: transparent; color: #000000;
margin: 0 0 1em 0; }
table.var-details { background: #e8f0f8; color: #000000;
border: 2px groove #c0d0d0;
padding: 0 1em 0 1em; margin: 0.4em 0 0 0; }
h3.var-details { background: transparent; color: #000000;
margin: 0 0 1em 0; }
/* Function signatures */
.sig { background: transparent; color: #000000;
font-weight: bold; }
.sig-name { background: transparent; color: #006080; }
.sig-arg, .sig-kwarg, .sig-vararg
{ background: transparent; color: #008060; }
.sig-default { background: transparent; color: #602000; }
.summary-sig { background: transparent; color: #000000; }
.summary-sig-name { background: transparent; color: #204080; }
.summary-sig-arg, .summary-sig-kwarg, .summary-sig-vararg
{ background: transparent; color: #008060; }
/* Doctest blocks */
.py-src { background: transparent; color: #000000; }
.py-prompt { background: transparent; color: #005050;
font-weight: bold;}
.py-string { background: transparent; color: #006030; }
.py-comment { background: transparent; color: #003060; }
.py-keyword { background: transparent; color: #600000; }
.py-output { background: transparent; color: #404040; }
pre.doctestblock { background: #f4faff; color: #000000;
padding: .5em; margin: 1em;
border: 1px solid #708890; }
table pre.doctestblock
{ background: #dce4ec; color: #000000;
padding: .5em; margin: 1em;
border: 1px solid #708890; }
/* Variable values */
pre.variable { background: #dce4ec; color: #000000;
padding: .5em; margin: 0;
border: 1px solid #708890; }
.variable-linewrap { background: transparent; color: #604000; }
.variable-ellipsis { background: transparent; color: #604000; }
.variable-quote { background: transparent; color: #604000; }
.re { background: transparent; color: #000000; }
.re-char { background: transparent; color: #006030; }
.re-op { background: transparent; color: #600000; }
.re-group { background: transparent; color: #003060; }
.re-ref { background: transparent; color: #404040; }
/* Navigation bar */
table.navbar { background: #a0c0ff; color: #0000ff;
border: 2px groove #c0d0d0; }
th.navbar { background: #a0c0ff; color: #0000ff; }
th.navselect { background: #70b0ff; color: #000000; }
.nomargin { margin: 0; }
/* Links */
a:link { background: transparent; color: #0000ff; }
a:visited { background: transparent; color: #204080; }
a.navbar:link { background: transparent; color: #0000ff;
text-decoration: none; }
a.navbar:visited { background: transparent; color: #204080;
text-decoration: none; }
/* Lists */
ul { margin-top: 0; }
pybluez-0.22+really0.22/docs/index.html 0000664 0000000 0000000 00000000606 13346112537 0017651 0 ustar 00root root 0000000 0000000
API Documentation
pybluez-0.22+really0.22/docs/private/ 0000775 0000000 0000000 00000000000 13346112537 0017324 5 ustar 00root root 0000000 0000000 pybluez-0.22+really0.22/docs/private/bluetooth-module.html 0000664 0000000 0000000 00000367012 13346112537 0023513 0 ustar 00root root 0000000 0000000
bluetooth
advertise_service(sock,
name,
service_id,
service_classes,
profiles,
provider,
description)
Advertises a service with the local SDP server.
discover_devices(duration,
flush_cache,
lookup_names)
discover_devices( duration=8, flush_cache=True, lookup_names=False ) -> results
availability: GNU/Linux, Windows XP
performs a bluetooth device discovery using the first available bluetooth
resource.
find_service(name,
uuid,
address)
find_service( name = None, uuid = None, address = None )
Searches for SDP services that match the specified criteria and returns
the search results.
is_valid_address(address)
is_valid_address(address) -> bool
availability: GNU/Linux, Windows XP
returns True if address is a valid bluetooth address
valid address are always strings of the form XX:XX:XX:XX:XX:XX
where X is a hexadecimal character.
is_valid_uuid(uuid)
is_valid_uuid(uuid) -> bool
availability: GNU/Linux, Windows XP
returns True if uuid is a valid UUID.
lookup_name(address,
timeout)
lookup_name( address, timeout=10 ) -> name
Advertises a service with the local SDP server. sock must be a bound,
listening socket. name should be the name of the service, and service_id
(if specified) should be a string of the form
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", where each 'X' is a hexadecimal digit.
service_classes is a list of service classes whose this service belongs to.
Each class service is a 16-bit UUID in the form "XXXX", where each 'X' is a
hexadecimal digit, or a 128-bit UUID in the form
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX". There are some constants for
standard services, e.g. SERIAL_PORT_CLASS that equals to "1101". Some class
constants:
SERIAL_PORT_CLASS LAN_ACCESS_CLASS DIALUP_NET_CLASS
HEADSET_CLASS CORDLESS_TELEPHONY_CLASS AUDIO_SOURCE_CLASS
AUDIO_SINK_CLASS PANU_CLASS NAP_CLASS
GN_CLASS
profiles is a list of service profiles that thie service fulfills. Each
profile is a tuple with ( uuid, version ). Most standard profiles use
standard classes as UUIDs. PyBluez offers a list of standard profiles,
for example SERIAL_PORT_PROFILE. All standard profiles have the same
name as the classes, except that _CLASS suffix is replaced by _PROFILE.
provider is a text string specifying the provider of the service
description is a text string describing the service
A note on working with Symbian smartphones:
bt_discover in Python for Series 60 will only detect service records
with service class SERIAL_PORT_CLASS and profile SERIAL_PORT_PROFILE
discover_devices( duration=8, flush_cache=True, lookup_names=False ) -> results
availability: GNU/Linux, Windows XP
performs a bluetooth device discovery using the first available bluetooth
resource.
if lookup_names is False, returns a list of bluetooth addresses.
if lookup_names is True, returns a list of (address, name) tuples
duration=8
how long, in units of 1.28 seconds, to search for devices. To find as
many devices as possible, you should set this to at least 8.
This parameter only works with GNU/Linux systems
flush_cache=True
if set to False, then discover_devices may return devices found during
previous discoveries.
lookup_names=False
if set to True, then discover_devices also attempts to lookup the
display name of each detected device.
find_service(name=None,
uuid=None,
address=None)
find_service( name = None, uuid = None, address = None )
Searches for SDP services that match the specified criteria and returns
the search results. If no criteria are specified, then returns a list of
all nearby services detected. If more than one is specified, then
the search results will match all the criteria specified. If uuid is
specified, it must be either a 16-bit UUID in the form "XXXX", where each
'X' is a hexadecimal digit, or as a 128-bit UUID in the form
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX". A special case of address is
"localhost", which will search for services on the local machine.
The search results will be a list of dictionaries. Each dictionary
represents a search match and will have the following key/value pairs:
host - the bluetooth address of the device advertising the
service
name - the name of the service being advertised
description - a description of the service being advertised
provider - the name of the person/organization providing the service
protocol - either 'RFCOMM', 'L2CAP', None if the protocol was not
specified, or 'UNKNOWN' if the protocol was specified but
unrecognized
port - the L2CAP PSM # if the protocol is 'L2CAP', the RFCOMM
channel # if the protocol is 'RFCOMM', or None if it
wasn't specified
service-classes - a list of service class IDs (UUID strings). possibly
empty
profiles - a list of profiles - (UUID, version) pairs - the
service claims to support. possibly empty.
service-id - the Service ID of the service. None if it wasn't set
See the Bluetooth spec for the difference between
Service ID and Service Class ID List
get_available_port(protocol)
deprecated. bind to port zero instead.
is_valid_address(address)
is_valid_address(address) -> bool
availability: GNU/Linux, Windows XP
returns True if address is a valid bluetooth address
valid address are always strings of the form XX:XX:XX:XX:XX:XX
where X is a hexadecimal character. For example,
01:23:45:67:89:AB is a valid address, but
IN:VA:LI:DA:DD:RE is not
is_valid_uuid(uuid)
is_valid_uuid(uuid) -> bool
availability: GNU/Linux, Windows XP
returns True if uuid is a valid UUID.
valid UUIDs are always strings taking one of the following forms:
XXXX
XXXXXXXX
XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
where each X is a hexadecimal digit (case insensitive)
lookup_name(address,
timeout=10)
lookup_name( address, timeout=10 ) -> name
availability: GNU/Linux
Tries to determine the friendly name (human readable) of the device
with the specified bluetooth address. Returns the name on success, and
None on failure.
timeout=10 how many seconds to search before giving up.
set_l2cap_mtu(sock,
mtu)
set_l2cap_mtu( sock, mtu )
availability: GNU/Linux
Adjusts the MTU for the specified L2CAP socket. This method needs to
be invoked on both sides of the connection for it to work! The default
mtu that all L2CAP connections start with is 672 bytes.
mtu must be between 48 and 65535, inclusive.
set_packet_timeout(address,
timeout)
set_packet_timeout( address, timeout )
Availability: GNU/Linux
Adjusts the ACL flush timeout for the ACL connection to the
specified device. This means that all L2CAP and RFCOMM data being sent
to that device will be dropped if not acknowledged in timeout
milliseconds (maximum 1280). A timeout of 0 means to never drop
packets.
Since this affects all Bluetooth connections to that device, and not
just those initiated by this process or PyBluez, a call to this method
requires superuser privileges.
You must have an active connection to the specified device before
invoking this method
stop_advertising(sock)
Instructs the local SDP server to stop advertising the service
associated with sock. You should typically call this right before you
close sock.
Create a new Bluetooth socket that uses the specified transport
protocol.
proto can be one of RFCOMM, L2CAP, HCI, or SCO
HCI, L2CAP, and SCO sockets are only available in GNU/Linux
accept(self)
accept() -> (BluetoothSocket, addrport)
availability: GNU/Linux, Windows XP
Wait for an incoming connection. Return a new socket representing
the connection, and the address/port of the client. For L2CAP sockets,
addport is a (host, psm) tuple. For RFCOMM sockets, addport is a (host,
channel) tuple. For SCO sockets, addrport is just a Bluetooth
address.
bind(self,
addrport)
bind(addrport)
availability: GNU/Linux, Windows XP
Bind the socket to a local adapter and port. addrport must always be a tuple.
HCI sockets: ( device number, )
device number should be 0, 1, 2, etc.
L2CAP sockets: ( host, psm )
host should be an address e.g. "01:23:45:67:89:ab"
psm should be an unsigned integer
RFCOMM sockets: ( host, channel )
SCO sockets: ( host )
close(self)
close()
availability: GNU/Linux, Windows XP
Close the socket. It cannot be used after this call.
connect(self,
addrport)
connect(addrport)
availability: GNU/Linux, Windows XP
Connect the socket to a remote device. For L2CAP sockets, addrport
is a (host,psm) tuple. For RFCOMM sockets, addrport is a (host,channel)
tuple. For SCO sockets, addrport is just the host.
dup(self)
dup() -> socket object
availability: GNU/Linux
Return a new socket object connected to the same system
resource.
fileno(self)
fileno() -> integer
availability: GNU/Linux, Windows XP
Return the integer file descriptor of the socket.
getpeername(self)
getpeername() -> address info
availability: GNU/Linux
Return the address of the remote endpoint. For HCI sockets, the
address is a device number (0, 1, 2, etc). For L2CAP sockets, the
address is a (host,psm) tuple. For RFCOMM sockets, the address is a
(host,channel) tuple. For SCO sockets, the address is just the
host.
getsockname(self)
getsockname() -> address info
availability: GNU/Linux, Windows XP Return the address of the local
endpoint.
getsockopt(self,
level,
option,
buffersize)
getsockopt(level, option[, buffersize]) -> value
availability: GNU/Linux
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.
gettimouet(self,
timeout)
gettimeout() -> timeout
availability: GNU/Linux
Returns the timeout in floating seconds associated with socket
operations. A timeout of None indicates that timeouts on socket
operations are disabled.
listen(self,
backlog)
listen(backlog)
availability: GNU/Linux, Windows XP
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.
makefile(self)
makefile([mode[, buffersize]]) -> file object
availability: GNU/Linux
Return a regular file object corresponding to the socket. The mode
and buffersize arguments are as for the built-in open() function.
recv(self,
buffersize,
flags=None)
recv(buffersize[, flags]) -> data
availability: GNU/Linux, Windows XP
Receive up to buffersize 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.
send(self,
data,
flags=None)
send(data[, flags]) -> count
availability: GNU/Linux, Windows XP
Send a data string to the socket. For the optional flags argument,
see the Unix manual. Return the number of bytes sent; this may be less
than len(data) if the network is busy.
sendall(self,
data,
flags=None)
sendall(data[, flags])
availability: GNU/Linux
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.
setblocking(self,
blocking)
setblocking(flag)
availability: GNU/Linux
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).
setsockopt(self,
level,
option,
value)
setsockopt(level, option, value)
availability: GNU/Linux
Set a socket option. See the Unix manual for level and option. The
value argument can either be an integer or a string.
settimeout(self,
timeout)
settimeout(timeout)
availability: GNU/Linux
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).
shutdown(self,
flag)
shutdown(flag)
availability: GNU/Linux
Shut down the reading side of the socket (flag == 0), the writing
side of the socket (flag == 1), or both ends (flag == 2).
Skeleton class for finer control of the device discovery process.
To implement asynchronous device discovery (e.g. if you want to do
something *as soon as* a device is discovered), subclass DeviceDiscoverer
and override device_discovered() and inquiry_complete()
cancel_inquiry(self)
Call this method to cancel an inquiry in process.
device_discovered(self,
address,
device_class,
name)
Called when a bluetooth device is discovered.
fileno(self)
find_devices(self,
lookup_names,
duration,
flush_cache)
find_devices( lookup_names=True, service_name=None,
duration=8, flush_cache=True )
Call this method to initiate the device discovery process
lookup_names - set to True if you want to lookup the user-friendly
names for each device found.
inquiry_complete(self)
Called when an inquiry started by find_devices has completed.
pre_inquiry(self)
Called just after find_devices is invoked, but just before the inquiry
is started.
process_event(self)
Waits for one event to happen, and proceses it.
process_inquiry(self)
Repeatedly calls process_event() until the device inquiry has
completed.
Method Details
__init__(self) (Constructor)
TODO
cancel_inquiry(self)
Call this method to cancel an inquiry in process. inquiry_complete
will still be called.
Called when a bluetooth device is discovered.
address is the bluetooth address of the device
device_class is the Class of Device, as specified in [1]
passed in as a 3-byte string
name is the user-friendly name of the device if lookup_names was set
when the inquiry was started. otherwise None
This method exists to be overriden.
[1] https://www.bluetooth.org/foundry/assignnumb/document/baseband
find_devices( lookup_names=True, service_name=None,
duration=8, flush_cache=True )
Call this method to initiate the device discovery process
lookup_names - set to True if you want to lookup the user-friendly
names for each device found.
service_name - set to the name of a service you're looking for.
only devices with a service of this name will be
returned in device_discovered() NOT YET IMPLEMENTED
ADVANCED PARAMETERS: (don't change these unless you know what
you're doing)
duration - the number of 1.2 second units to spend searching for
bluetooth devices. If lookup_names is True, then the
inquiry process can take a lot longer.
flush_cache - return devices discovered in previous inquiries
inquiry_complete(self)
Called when an inquiry started by find_devices has completed.
pre_inquiry(self)
Called just after find_devices is invoked, but just before the
inquiry is started.
This method exists to be overriden
process_event(self)
Waits for one event to happen, and proceses it. The event will be
either a device discovery, or an inquiry completion.
process_inquiry(self)
Repeatedly calls process_event() until the device inquiry has
completed.
This document contains the API (Application Programming Interface)
documentation for this project. Documentation for the Python
objects defined by the project is divided into separate pages for each
package, module, and class. The API documentation also includes two
pages containing information about the project as a whole: a trees
page, and an index page.
Object Documentation
Each Package Documentation page contains:
A description of the package.
A list of the modules and sub-packages contained by the
package.
A summary of the classes defined by the package.
A summary of the functions defined by the package.
A summary of the variables defined by the package.
A detailed description of each function defined by the
package.
A detailed description of each variable defined by the
package.
Each Module Documentation page contains:
A description of the module.
A summary of the classes defined by the module.
A summary of the functions defined by the module.
A summary of the variables defined by the module.
A detailed description of each function defined by the
module.
A detailed description of each variable defined by the
module.
Each Class Documentation page contains:
A class inheritance diagram.
A list of known subclasses.
A description of the class.
A summary of the methods defined by the class.
A summary of the instance variables defined by the class.
A summary of the class (static) variables defined by the
class.
A detailed description of each method defined by the
class.
A detailed description of each instance variable defined by the
class.
A detailed description of each class (static) variable defined
by the class.
Project Documentation
The Trees page contains the module and class hierarchies:
The module hierarchy lists every package and module, with
modules grouped into packages. At the top level, and within each
package, modules and sub-packages are listed alphabetically.
The class hierarchy lists every class, grouped by base
class. If a class has more than one base class, then it will be
listed under each base class. At the top level, and under each base
class, classes are listed alphabetically.
The Index page contains indices of terms and
identifiers:
The term index lists every term indexed by any object's
documentation. For each term, the index provides links to each
place where the term is indexed.
The identifier index lists the (short) name of every package,
module, class, method, function, variable, and parameter. For each
identifier, the index provides a short description, and a link to
its documentation.
The Table of Contents
The table of contents occupies the two frames on the left side of
the window. The upper-left frame displays the project
contents, and the lower-left frame displays the module
contents:
Project Contents...
API Documentation Frame
Module Contents ...
The project contents frame contains a list of all packages
and modules that are defined by the project. Clicking on an entry
will display its contents in the module contents frame. Clicking on a
special entry, labeled "Everything," will display the contents of
the entire project.
The module contents frame contains a list of every
submodule, class, type, exception, function, and variable defined by a
module or package. Clicking on an entry will display its
documentation in the API documentation frame. Clicking on the name of
the module, at the top of the frame, will display the documentation
for the module itself.
The "frames" and "no frames" buttons below the top
navigation bar can be used to control whether the table of contents is
displayed or not.
The Navigation Bar
A navigation bar is located at the top and bottom of every page.
It indicates what type of page you are currently viewing, and allows
you to go to related pages. The following table describes the labels
on the navigation bar. Note that not some labels (such as
[Parent]) are not displayed on all pages.
Label
Highlighted when...
Links to...
[Parent]
(never highlighted)
the parent of the current package
[Package]
viewing a package
the package containing the current object
[Module]
viewing a module
the module containing the current object
[Class]
viewing a class
the class containing the current object
[Trees]
viewing the trees page
the trees page
[Index]
viewing the index page
the index page
[Help]
viewing the help page
the help page
The "show private" and "hide private" buttons below
the top navigation bar can be used to control whether documentation
for private objects is displayed. Private objects are usually defined
as objects whose (short) names begin with a single underscore, but do
not end with an underscore. For example, "_x",
"__pprint", and "epydoc.epytext._tokenize"
are private objects; but "re.sub",
"__init__", and "type_" are not. However,
if a module defines the "__all__" variable, then its
contents are used to decide which objects are private.
A timestamp below the bottom navigation bar indicates when each
page was last updated.
advertise_service(sock,
name,
service_id,
service_classes,
profiles,
provider,
description)
Advertises a service with the local SDP server.
discover_devices(duration,
flush_cache,
lookup_names)
discover_devices( duration=8, flush_cache=True, lookup_names=False ) -> results
availability: GNU/Linux, Windows XP
performs a bluetooth device discovery using the first available bluetooth
resource.
find_service(name,
uuid,
address)
find_service( name = None, uuid = None, address = None )
Searches for SDP services that match the specified criteria and returns
the search results.
is_valid_address(address)
is_valid_address(address) -> bool
availability: GNU/Linux, Windows XP
returns True if address is a valid bluetooth address
valid address are always strings of the form XX:XX:XX:XX:XX:XX
where X is a hexadecimal character.
is_valid_uuid(uuid)
is_valid_uuid(uuid) -> bool
availability: GNU/Linux, Windows XP
returns True if uuid is a valid UUID.
lookup_name(address,
timeout)
lookup_name( address, timeout=10 ) -> name
Advertises a service with the local SDP server. sock must be a bound,
listening socket. name should be the name of the service, and service_id
(if specified) should be a string of the form
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", where each 'X' is a hexadecimal digit.
service_classes is a list of service classes whose this service belongs to.
Each class service is a 16-bit UUID in the form "XXXX", where each 'X' is a
hexadecimal digit, or a 128-bit UUID in the form
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX". There are some constants for
standard services, e.g. SERIAL_PORT_CLASS that equals to "1101". Some class
constants:
SERIAL_PORT_CLASS LAN_ACCESS_CLASS DIALUP_NET_CLASS
HEADSET_CLASS CORDLESS_TELEPHONY_CLASS AUDIO_SOURCE_CLASS
AUDIO_SINK_CLASS PANU_CLASS NAP_CLASS
GN_CLASS
profiles is a list of service profiles that thie service fulfills. Each
profile is a tuple with ( uuid, version ). Most standard profiles use
standard classes as UUIDs. PyBluez offers a list of standard profiles,
for example SERIAL_PORT_PROFILE. All standard profiles have the same
name as the classes, except that _CLASS suffix is replaced by _PROFILE.
provider is a text string specifying the provider of the service
description is a text string describing the service
A note on working with Symbian smartphones:
bt_discover in Python for Series 60 will only detect service records
with service class SERIAL_PORT_CLASS and profile SERIAL_PORT_PROFILE
discover_devices( duration=8, flush_cache=True, lookup_names=False ) -> results
availability: GNU/Linux, Windows XP
performs a bluetooth device discovery using the first available bluetooth
resource.
if lookup_names is False, returns a list of bluetooth addresses.
if lookup_names is True, returns a list of (address, name) tuples
duration=8
how long, in units of 1.28 seconds, to search for devices. To find as
many devices as possible, you should set this to at least 8.
This parameter only works with GNU/Linux systems
flush_cache=True
if set to False, then discover_devices may return devices found during
previous discoveries.
lookup_names=False
if set to True, then discover_devices also attempts to lookup the
display name of each detected device.
find_service(name=None,
uuid=None,
address=None)
find_service( name = None, uuid = None, address = None )
Searches for SDP services that match the specified criteria and returns
the search results. If no criteria are specified, then returns a list of
all nearby services detected. If more than one is specified, then
the search results will match all the criteria specified. If uuid is
specified, it must be either a 16-bit UUID in the form "XXXX", where each
'X' is a hexadecimal digit, or as a 128-bit UUID in the form
"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX". A special case of address is
"localhost", which will search for services on the local machine.
The search results will be a list of dictionaries. Each dictionary
represents a search match and will have the following key/value pairs:
host - the bluetooth address of the device advertising the
service
name - the name of the service being advertised
description - a description of the service being advertised
provider - the name of the person/organization providing the service
protocol - either 'RFCOMM', 'L2CAP', None if the protocol was not
specified, or 'UNKNOWN' if the protocol was specified but
unrecognized
port - the L2CAP PSM # if the protocol is 'L2CAP', the RFCOMM
channel # if the protocol is 'RFCOMM', or None if it
wasn't specified
service-classes - a list of service class IDs (UUID strings). possibly
empty
profiles - a list of profiles - (UUID, version) pairs - the
service claims to support. possibly empty.
service-id - the Service ID of the service. None if it wasn't set
See the Bluetooth spec for the difference between
Service ID and Service Class ID List
get_available_port(protocol)
deprecated. bind to port zero instead.
is_valid_address(address)
is_valid_address(address) -> bool
availability: GNU/Linux, Windows XP
returns True if address is a valid bluetooth address
valid address are always strings of the form XX:XX:XX:XX:XX:XX
where X is a hexadecimal character. For example,
01:23:45:67:89:AB is a valid address, but
IN:VA:LI:DA:DD:RE is not
is_valid_uuid(uuid)
is_valid_uuid(uuid) -> bool
availability: GNU/Linux, Windows XP
returns True if uuid is a valid UUID.
valid UUIDs are always strings taking one of the following forms:
XXXX
XXXXXXXX
XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
where each X is a hexadecimal digit (case insensitive)
lookup_name(address,
timeout=10)
lookup_name( address, timeout=10 ) -> name
availability: GNU/Linux
Tries to determine the friendly name (human readable) of the device
with the specified bluetooth address. Returns the name on success, and
None on failure.
timeout=10 how many seconds to search before giving up.
set_l2cap_mtu(sock,
mtu)
set_l2cap_mtu( sock, mtu )
availability: GNU/Linux
Adjusts the MTU for the specified L2CAP socket. This method needs to
be invoked on both sides of the connection for it to work! The default
mtu that all L2CAP connections start with is 672 bytes.
mtu must be between 48 and 65535, inclusive.
set_packet_timeout(address,
timeout)
set_packet_timeout( address, timeout )
Availability: GNU/Linux
Adjusts the ACL flush timeout for the ACL connection to the
specified device. This means that all L2CAP and RFCOMM data being sent
to that device will be dropped if not acknowledged in timeout
milliseconds (maximum 1280). A timeout of 0 means to never drop
packets.
Since this affects all Bluetooth connections to that device, and not
just those initiated by this process or PyBluez, a call to this method
requires superuser privileges.
You must have an active connection to the specified device before
invoking this method
stop_advertising(sock)
Instructs the local SDP server to stop advertising the service
associated with sock. You should typically call this right before you
close sock.
Create a new Bluetooth socket that uses the specified transport
protocol.
proto can be one of RFCOMM, L2CAP, HCI, or SCO
HCI, L2CAP, and SCO sockets are only available in GNU/Linux
accept(self)
accept() -> (BluetoothSocket, addrport)
availability: GNU/Linux, Windows XP
Wait for an incoming connection. Return a new socket representing
the connection, and the address/port of the client. For L2CAP sockets,
addport is a (host, psm) tuple. For RFCOMM sockets, addport is a (host,
channel) tuple. For SCO sockets, addrport is just a Bluetooth
address.
bind(self,
addrport)
bind(addrport)
availability: GNU/Linux, Windows XP
Bind the socket to a local adapter and port. addrport must always be a tuple.
HCI sockets: ( device number, )
device number should be 0, 1, 2, etc.
L2CAP sockets: ( host, psm )
host should be an address e.g. "01:23:45:67:89:ab"
psm should be an unsigned integer
RFCOMM sockets: ( host, channel )
SCO sockets: ( host )
close(self)
close()
availability: GNU/Linux, Windows XP
Close the socket. It cannot be used after this call.
connect(self,
addrport)
connect(addrport)
availability: GNU/Linux, Windows XP
Connect the socket to a remote device. For L2CAP sockets, addrport
is a (host,psm) tuple. For RFCOMM sockets, addrport is a (host,channel)
tuple. For SCO sockets, addrport is just the host.
dup(self)
dup() -> socket object
availability: GNU/Linux
Return a new socket object connected to the same system
resource.
fileno(self)
fileno() -> integer
availability: GNU/Linux, Windows XP
Return the integer file descriptor of the socket.
getpeername(self)
getpeername() -> address info
availability: GNU/Linux
Return the address of the remote endpoint. For HCI sockets, the
address is a device number (0, 1, 2, etc). For L2CAP sockets, the
address is a (host,psm) tuple. For RFCOMM sockets, the address is a
(host,channel) tuple. For SCO sockets, the address is just the
host.
getsockname(self)
getsockname() -> address info
availability: GNU/Linux, Windows XP Return the address of the local
endpoint.
getsockopt(self,
level,
option,
buffersize)
getsockopt(level, option[, buffersize]) -> value
availability: GNU/Linux
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.
gettimouet(self,
timeout)
gettimeout() -> timeout
availability: GNU/Linux
Returns the timeout in floating seconds associated with socket
operations. A timeout of None indicates that timeouts on socket
operations are disabled.
listen(self,
backlog)
listen(backlog)
availability: GNU/Linux, Windows XP
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.
makefile(self)
makefile([mode[, buffersize]]) -> file object
availability: GNU/Linux
Return a regular file object corresponding to the socket. The mode
and buffersize arguments are as for the built-in open() function.
recv(self,
buffersize,
flags=None)
recv(buffersize[, flags]) -> data
availability: GNU/Linux, Windows XP
Receive up to buffersize 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.
send(self,
data,
flags=None)
send(data[, flags]) -> count
availability: GNU/Linux, Windows XP
Send a data string to the socket. For the optional flags argument,
see the Unix manual. Return the number of bytes sent; this may be less
than len(data) if the network is busy.
sendall(self,
data,
flags=None)
sendall(data[, flags])
availability: GNU/Linux
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.
setblocking(self,
blocking)
setblocking(flag)
availability: GNU/Linux
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).
setsockopt(self,
level,
option,
value)
setsockopt(level, option, value)
availability: GNU/Linux
Set a socket option. See the Unix manual for level and option. The
value argument can either be an integer or a string.
settimeout(self,
timeout)
settimeout(timeout)
availability: GNU/Linux
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).
shutdown(self,
flag)
shutdown(flag)
availability: GNU/Linux
Shut down the reading side of the socket (flag == 0), the writing
side of the socket (flag == 1), or both ends (flag == 2).
Skeleton class for finer control of the device discovery process.
To implement asynchronous device discovery (e.g. if you want to do
something *as soon as* a device is discovered), subclass DeviceDiscoverer
and override device_discovered() and inquiry_complete()
cancel_inquiry(self)
Call this method to cancel an inquiry in process.
device_discovered(self,
address,
device_class,
name)
Called when a bluetooth device is discovered.
fileno(self)
find_devices(self,
lookup_names,
duration,
flush_cache)
find_devices( lookup_names=True, service_name=None,
duration=8, flush_cache=True )
Call this method to initiate the device discovery process
lookup_names - set to True if you want to lookup the user-friendly
names for each device found.
inquiry_complete(self)
Called when an inquiry started by find_devices has completed.
pre_inquiry(self)
Called just after find_devices is invoked, but just before the inquiry
is started.
process_event(self)
Waits for one event to happen, and proceses it.
process_inquiry(self)
Repeatedly calls process_event() until the device inquiry has
completed.
Method Details
__init__(self) (Constructor)
TODO
cancel_inquiry(self)
Call this method to cancel an inquiry in process. inquiry_complete
will still be called.
Called when a bluetooth device is discovered.
address is the bluetooth address of the device
device_class is the Class of Device, as specified in [1]
passed in as a 3-byte string
name is the user-friendly name of the device if lookup_names was set
when the inquiry was started. otherwise None
This method exists to be overriden.
[1] https://www.bluetooth.org/foundry/assignnumb/document/baseband
find_devices( lookup_names=True, service_name=None,
duration=8, flush_cache=True )
Call this method to initiate the device discovery process
lookup_names - set to True if you want to lookup the user-friendly
names for each device found.
service_name - set to the name of a service you're looking for.
only devices with a service of this name will be
returned in device_discovered() NOT YET IMPLEMENTED
ADVANCED PARAMETERS: (don't change these unless you know what
you're doing)
duration - the number of 1.2 second units to spend searching for
bluetooth devices. If lookup_names is True, then the
inquiry process can take a lot longer.
flush_cache - return devices discovered in previous inquiries
inquiry_complete(self)
Called when an inquiry started by find_devices has completed.
pre_inquiry(self)
Called just after find_devices is invoked, but just before the
inquiry is started.
This method exists to be overriden
process_event(self)
Waits for one event to happen, and proceses it. The event will be
either a device discovery, or an inquiry completion.
process_inquiry(self)
Repeatedly calls process_event() until the device inquiry has
completed.
This document contains the API (Application Programming Interface)
documentation for this project. Documentation for the Python
objects defined by the project is divided into separate pages for each
package, module, and class. The API documentation also includes two
pages containing information about the project as a whole: a trees
page, and an index page.
Object Documentation
Each Package Documentation page contains:
A description of the package.
A list of the modules and sub-packages contained by the
package.
A summary of the classes defined by the package.
A summary of the functions defined by the package.
A summary of the variables defined by the package.
A detailed description of each function defined by the
package.
A detailed description of each variable defined by the
package.
Each Module Documentation page contains:
A description of the module.
A summary of the classes defined by the module.
A summary of the functions defined by the module.
A summary of the variables defined by the module.
A detailed description of each function defined by the
module.
A detailed description of each variable defined by the
module.
Each Class Documentation page contains:
A class inheritance diagram.
A list of known subclasses.
A description of the class.
A summary of the methods defined by the class.
A summary of the instance variables defined by the class.
A summary of the class (static) variables defined by the
class.
A detailed description of each method defined by the
class.
A detailed description of each instance variable defined by the
class.
A detailed description of each class (static) variable defined
by the class.
Project Documentation
The Trees page contains the module and class hierarchies:
The module hierarchy lists every package and module, with
modules grouped into packages. At the top level, and within each
package, modules and sub-packages are listed alphabetically.
The class hierarchy lists every class, grouped by base
class. If a class has more than one base class, then it will be
listed under each base class. At the top level, and under each base
class, classes are listed alphabetically.
The Index page contains indices of terms and
identifiers:
The term index lists every term indexed by any object's
documentation. For each term, the index provides links to each
place where the term is indexed.
The identifier index lists the (short) name of every package,
module, class, method, function, variable, and parameter. For each
identifier, the index provides a short description, and a link to
its documentation.
The Table of Contents
The table of contents occupies the two frames on the left side of
the window. The upper-left frame displays the project
contents, and the lower-left frame displays the module
contents:
Project Contents...
API Documentation Frame
Module Contents ...
The project contents frame contains a list of all packages
and modules that are defined by the project. Clicking on an entry
will display its contents in the module contents frame. Clicking on a
special entry, labeled "Everything," will display the contents of
the entire project.
The module contents frame contains a list of every
submodule, class, type, exception, function, and variable defined by a
module or package. Clicking on an entry will display its
documentation in the API documentation frame. Clicking on the name of
the module, at the top of the frame, will display the documentation
for the module itself.
The "frames" and "no frames" buttons below the top
navigation bar can be used to control whether the table of contents is
displayed or not.
The Navigation Bar
A navigation bar is located at the top and bottom of every page.
It indicates what type of page you are currently viewing, and allows
you to go to related pages. The following table describes the labels
on the navigation bar. Note that not some labels (such as
[Parent]) are not displayed on all pages.
Label
Highlighted when...
Links to...
[Parent]
(never highlighted)
the parent of the current package
[Package]
viewing a package
the package containing the current object
[Module]
viewing a module
the module containing the current object
[Class]
viewing a class
the class containing the current object
[Trees]
viewing the trees page
the trees page
[Index]
viewing the index page
the index page
[Help]
viewing the help page
the help page
The "show private" and "hide private" buttons below
the top navigation bar can be used to control whether documentation
for private objects is displayed. Private objects are usually defined
as objects whose (short) names begin with a single underscore, but do
not end with an underscore. For example, "_x",
"__pprint", and "epydoc.epytext._tokenize"
are private objects; but "re.sub",
"__init__", and "type_" are not. However,
if a module defines the "__all__" variable, then its
contents are used to decide which objects are private.
A timestamp below the bottom navigation bar indicates when each
page was last updated.