PyBluez-0.18/0000755000076400010400000000000011303332711014066 5ustar lukasAdministratorenPyBluez-0.18/bluetooth/0000755000076400010400000000000011303332711016073 5ustar lukasAdministratorenPyBluez-0.18/bluetooth/bluez.py0000644000076400010400000004511311302237264017600 0ustar lukasAdministratorenimport sys import struct import binascii from btcommon import * import _bluetooth as _bt import array import fcntl _constants = [ 'HCI', 'RFCOMM', 'L2CAP', 'SCO', 'SOL_L2CAP', 'SOL_RFCOMM',\ 'L2CAP_OPTIONS' ] for _c in _constants: exec "%s = _bt.%s" % (_c, _c) del _constants # ============== SDP service registration and unregistration ============ def discover_devices (duration=8, flush_cache=True, lookup_names=False): sock = _gethcisock () try: results = _bt.hci_inquiry (sock, duration=duration, flush_cache=True) except _bt.error: sock.close () raise BluetoothError ("error communicating with local " "bluetooth adapter") if lookup_names: pairs = [] for addr in results: timeoutms = int (10 * 1000) try: name = _bt.hci_read_remote_name (sock, addr, timeoutms) except _bt.error, e: # name lookup failed. either a timeout, or I/O error continue pairs.append ((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, e: # 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 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. """ s = sock.getsockopt (SOL_L2CAP, L2CAP_OPTIONS, 7) # XXX should these be " 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, 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)) return self._sock.bind (addrport) # import methods from the wraapped socket object _s = ("""def %s (self, *args, **kwargs): try: return self._sock.%s (*args, **kwargs) except _bt.error, 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'): 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, e: raise BluetoothError (str (e)) def stop_advertising (sock): try: _bt.sdp_stop_advertising (sock._sock) except _bt.error, 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 = filter (lambda s: s.get ("name", "") == name, \ matches) for m in matches: m["host"] = addr results.extend (matches) except _bt.error, 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, "\0" * 17) request = array.array ("c", reqstr) try: fcntl.ioctl (hci_fd, _bt.HCIGETCONNINFO, request, 1) except IOError, e: 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 " 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): import socket if self.sock is None: return # voodoo magic!!! pkt = self.sock.recv (255) ptype, event, plen = struct.unpack ("BBB", pkt[:3]) pkt = pkt[3:] if event == _bt.EVT_INQUIRY_RESULT: nrsp = struct.unpack ("B", pkt[0])[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) elif event == _bt.EVT_INQUIRY_RESULT_WITH_RSSI: nrsp = struct.unpack ("B", pkt[0])[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 = struct.unpack ("b", pkt[1+13*nrsp+i])[0] self._device_discovered (addr, devclass, psrm, pspm, clockoff) elif event == _bt.EVT_INQUIRY_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 = self.names_to_find.keys ()[0] device_class, psrm, pspm, clockoff = self.names_to_find[address] bdaddr = _bt.str2ba (address) 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, 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, 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)" % \ (address, name, device_class) else: print "found: %s (class 0x%X)" % (address, device_class) def inquiry_complete (self): """ Called when an inquiry started by find_devices has completed. """ print "inquiry complete" PyBluez-0.18/bluetooth/btcommon.py0000644000076400010400000003200511302237264020271 0ustar lukasAdministratorenimport 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])[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])[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]), 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))&0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFL) 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 & 0xFFFFFFFFFFFFFFFFL) 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)) + value elif type == "Bool": return maketsd (5,0) + (value and "\x01" or "\x00") elif type == "ElemSeq": packedseq = "" 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 = "" 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.18/bluetooth/msbt.py0000644000076400010400000002045211302237264017423 0ustar lukasAdministratorenfrom btcommon import * import _msbt as bt bt.initwinsock () # ============== SDP service registration and unregistration ============ def discover_devices (duration=8, flush_cache=True, lookup_names=False): return bt.discover_devices (flush_cache, lookup_names) 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 status = 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): s = 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) # 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 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 "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.18/bluetooth/osx.py0000644000076400010400000000006211302237264017262 0ustar lukasAdministratorenfrom btcommon import * raise NotImplementedError PyBluez-0.18/bluetooth/widcomm.py0000644000076400010400000007010111302725060020105 0ustar lukasAdministratorenfrom 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): inquirer.start_inquiry () while inquirer.inquiry_in_progress: inquirer.read_msg () discovered = inquirer.recently_discovered[:] if not lookup_names: return [ tup[0] for tup in discovered ] if lookup_names: result = [] for bdaddr, devClass, bdName, bConnected in discovered: if bdName: result.append ((bdaddr, bdName)) else: result.append ((bdAddr, None)) 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 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.18/bluetooth/__init__.py0000644000076400010400000001264111302715725020221 0ustar lukasAdministratorenimport sys import os from btcommon import * 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: 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") from msbt import * elif sys.platform == "linux2": from bluez import * elif sys.platform == "darwin": from osx import * 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. """ 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.18/bluez/0000755000076400010400000000000011303332711015207 5ustar lukasAdministratorenPyBluez-0.18/bluez/btmodule.c0000644000076400010400000025024511302237264017204 0ustar lukasAdministratoren/* 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 "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 */ PyMODINIT_FUNC 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; } 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; char *buf; int buflen; int flag; if (PyArg_ParseTuple(args, "iii:setsockopt", &level, &optname, &flag)) { buf = (char *) &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, (void *)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; PyObject *buf; 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); } if (buflen <= 0 || buflen > 1024) { PyErr_SetString(bluetooth_error, "getsockopt buflen out of range"); return NULL; } 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; } 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."); /* 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(); } f = PyFile_FromFile(fp, "", mode, fclose); if (f != NULL) PyFile_SetBufSize(f, bufsize); 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}, {"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; } s->ob_type->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 = { PyObject_HEAD_INIT(0) /* Must fill in type value later */ 0, /* ob_size */ "_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 *arg) { unsigned long x; 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 *arg) { unsigned long x; 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 Py_BuildValue("s#", 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; 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", 0}; if( !PyArg_ParseTupleAndKeywords(args, kwds, "O|ii", keywords, &socko, &length, &flush) ) { 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 * list_entry = (PyObject *)NULL; int err; ba2str( &(info+i)->bdaddr, ba_name ); list_entry = PyString_FromString( ba_name ); err = PyList_Append( rtn_list, list_entry ); Py_DECREF( list_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 dd = 0, 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) ); dd = socko->sock_fd; 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"); /* HCI filter operations */ 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"); // 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 ); \ len = sizeof(struct hci_filter); \ return Py_BuildValue("s#", 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 ); \ len = sizeof(struct hci_filter); \ return Py_BuildValue("s#", 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("s#", (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_devid_doc, "hci_devid(address)\n\ \n\ get the device id for the local device with specified address.\n\ "); /* * ------------------- * 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( ! str2uuid( PyString_AsString( 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( ! str2uuid( PyString_AsString( 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); str2uuid( PyString_AsString( 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); str2uuid( PyString_AsString( 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 || (socko->ob_type != &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_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."); PyMODINIT_FUNC init_bluetooth(void) { PyObject *m; sock_type.ob_type = &PyType_Type; sdp_session_type.ob_type = &PyType_Type; // Initialization steps for _bluetooth. 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; // 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_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_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 /* 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 ); #undef ADD_INT_CONST } /* * 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.18/bluez/btmodule.h0000644000076400010400000000236111302237264017203 0ustar lukasAdministratoren#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.18/bluez/btsdp.c0000644000076400010400000003361211302237264016502 0ustar lukasAdministratoren#include "Python.h" #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; } s->ob_type->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 = { PyObject_HEAD_INIT(0) /* Must fill in type value later */ 0, /* ob_size */ "_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.18/bluez/btsdp.h0000644000076400010400000000056511302237264016510 0ustar lukasAdministratoren#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.18/CHANGELOG0000644000076400010400000001742611303332044015311 0ustar lukasAdministratorenPyBluez CHANGELOG file this file contains a list of changes through the different versions of PyBluez. 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.18/COPYING0000644000076400010400000004310511302237266015134 0ustar lukasAdministratoren 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.18/examples/0000755000076400010400000000000011303332711015704 5ustar lukasAdministratorenPyBluez-0.18/examples/advanced/0000755000076400010400000000000011303332711017451 5ustar lukasAdministratorenPyBluez-0.18/examples/advanced/inquiry-with-rssi.py0000644000076400010400000001121711302237265023463 0ustar lukasAdministratoren# performs a simple device inquiry, followed by a remote name request of each # discovered device import os import sys import struct import bluetooth._bluetooth as bluez def printpacket(pkt): for c in pkt: sys.stdout.write("%02x " % struct.unpack("B",c)[0]) print def read_inquiry_mode(sock): """returns the current mode, or -1 on failure""" # save current filter old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) # Setup socket filter to receive only events related to the # read_inquiry_mode command flt = bluez.hci_filter_new() opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, bluez.OCF_READ_INQUIRY_MODE) bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE); bluez.hci_filter_set_opcode(flt, opcode) sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt ) # first read the current inquiry mode. bluez.hci_send_cmd(sock, bluez.OGF_HOST_CTL, bluez.OCF_READ_INQUIRY_MODE ) pkt = sock.recv(255) status,mode = struct.unpack("xxxxxxBB", pkt) if status != 0: mode = -1 # restore old filter sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter ) return mode def write_inquiry_mode(sock, mode): """returns 0 on success, -1 on failure""" # save current filter old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) # Setup socket filter to receive only events related to the # write_inquiry_mode command flt = bluez.hci_filter_new() opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, bluez.OCF_WRITE_INQUIRY_MODE) bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE); bluez.hci_filter_set_opcode(flt, opcode) sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt ) # send the command! bluez.hci_send_cmd(sock, bluez.OGF_HOST_CTL, bluez.OCF_WRITE_INQUIRY_MODE, struct.pack("B", mode) ) pkt = sock.recv(255) status = struct.unpack("xxxxxxB", pkt)[0] # restore old filter sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter ) if status != 0: return -1 return 0 def device_inquiry_with_with_rssi(sock): # save current filter old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) # perform a device inquiry on bluetooth device #0 # The inquiry should last 8 * 1.28 = 10.24 seconds # before the inquiry is performed, bluez should flush its cache of # previously discovered devices flt = bluez.hci_filter_new() bluez.hci_filter_all_events(flt) bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt ) duration = 4 max_responses = 255 cmd_pkt = struct.pack("BBBBB", 0x33, 0x8b, 0x9e, duration, max_responses) bluez.hci_send_cmd(sock, bluez.OGF_LINK_CTL, bluez.OCF_INQUIRY, cmd_pkt) results = [] done = False while not done: pkt = sock.recv(255) ptype, event, plen = struct.unpack("BBB", pkt[:3]) if event == bluez.EVT_INQUIRY_RESULT_WITH_RSSI: pkt = pkt[3:] nrsp = struct.unpack("B", pkt[0])[0] for i in range(nrsp): addr = bluez.ba2str( pkt[1+6*i:1+6*i+6] ) rssi = struct.unpack("b", pkt[1+13*nrsp+i])[0] results.append( ( addr, rssi ) ) print "[%s] RSSI: [%d]" % (addr, rssi) elif event == bluez.EVT_INQUIRY_COMPLETE: done = True elif event == bluez.EVT_CMD_STATUS: status, ncmd, opcode = struct.unpack("BBH", pkt[3:7]) if status != 0: print "uh oh..." printpacket(pkt[3:7]) done = True else: print "unrecognized packet type 0x%02x" % ptype # restore old filter sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter ) return results dev_id = 0 try: sock = bluez.hci_open_dev(dev_id) except: print "error accessing bluetooth device..." sys.exit(1) try: mode = read_inquiry_mode(sock) except Exception, e: print "error reading inquiry mode. " print "Are you sure this a bluetooth 1.2 device?" print e sys.exit(1) print "current inquiry mode is %d" % mode if mode != 1: print "writing inquiry mode..." try: result = write_inquiry_mode(sock, 1) except Exception, e: print "error writing inquiry mode. Are you sure you're root?" print e sys.exit(1) if result != 0: print "error while setting inquiry mode" print "result: %d" % result device_inquiry_with_with_rssi(sock) PyBluez-0.18/examples/advanced/l2-mtu.py0000644000076400010400000000312511302237265021153 0ustar lukasAdministratorenimport sys import struct import bluetooth def usage(): print "usage: l2-mtu < server | client > [options]" print "" print "l2-mtu server to start in server mode" print "l2-mtu client to start in client mode and connect to addr" sys.exit(2) if len(sys.argv) < 2: usage() mode = sys.argv[1] if mode not in [ "client", "server" ]: usage() if mode == "server": server_sock=bluetooth.BluetoothSocket( bluetooth.L2CAP ) server_sock.bind(("",0x1001)) server_sock.listen(1) while True: print "waiting for incoming connection" client_sock,address = server_sock.accept() print "Accepted connection from %s" % str(address) bluetooth.set_l2cap_mtu( client_sock, 65535 ) print "waiting for data" total = 0 while True: try: data = client_sock.recv(65535) except bluetooth.BluetoothError, e: break if len(data) == 0: break print "received packet of size %d" % len(data) client_sock.close() print "connection closed" server_sock.close() else: sock=bluetooth.BluetoothSocket(bluetooth.L2CAP) bt_addr = sys.argv[2] print "trying to connect to %s:1001" % bt_addr port = 0x1001 sock.connect((bt_addr, port)) print "connected. Adjusting link parameters." bluetooth.set_l2cap_mtu( sock, 65535 ) totalsent = 0 for i in range(1, 65535, 100): pkt = "0" * i sent = sock.send(pkt) print "sent packet of size %d (tried %d)" % (sent, len(pkt)) sock.close() PyBluez-0.18/examples/advanced/l2-unreliable-client.py0000644000076400010400000000477711302237265023762 0ustar lukasAdministratorenimport sys import fcntl import struct import array import bluetooth import bluetooth._bluetooth as bt # low level bluetooth wrappers. def __get_acl_conn_handle(sock, addr): hci_fd = sock.fileno() reqstr = struct.pack( "6sB17s", bt.str2ba(addr), bt.ACL_LINK, "\0" * 17) request = array.array( "c", reqstr ) fcntl.ioctl( hci_fd, bt.HCIGETCONNINFO, request, 1 ) 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) pkt = struct.pack("HH", handle, bt.htobs(timeout)) response = bt.hci_send_req(hci_sock, bt.OGF_HOST_CTL, 0x0028, bt.EVT_CMD_COMPLETE, 3, pkt) status = struct.unpack("B", response[0])[0] rhandle = struct.unpack("H", response[1:3])[0] assert rhandle == handle assert status == 0 def read_flush_timeout( addr ): hci_sock = bt.hci_open_dev() # get the ACL connection handle to the remote device handle = __get_acl_conn_handle(hci_sock, addr) pkt = struct.pack("H", handle) response = bt.hci_send_req(hci_sock, bt.OGF_HOST_CTL, 0x0027, bt.EVT_CMD_COMPLETE, 5, pkt) status = struct.unpack("B", response[0])[0] rhandle = struct.unpack("H", response[1:3])[0] assert rhandle == handle assert status == 0 fto = struct.unpack("H", response[3:5])[0] return fto # Create the client socket sock=bluetooth.BluetoothSocket(bluetooth.L2CAP) if len(sys.argv) < 4: print "usage: l2capclient.py " print " address - device that l2-unreliable-server is running on" print " timeout - wait timeout * 0.625ms before dropping unACK'd packets" print " num_packets - number of 627-byte packets to send on connect" sys.exit(2) bt_addr=sys.argv[1] timeout = int(sys.argv[2]) num_packets = int(sys.argv[3]) print "trying to connect to %s:1001" % bt_addr port = 0x1001 sock.connect((bt_addr, port)) print "connected. Adjusting link parameters." print "current flush timeout is %d ms" % read_flush_timeout( bt_addr ) try: write_flush_timeout( bt_addr, timeout ) except bt.error, e: print "error setting flush timeout. are you sure you're superuser?" print e sys.exit(1) print "new flush timeout is %d ms" % read_flush_timeout( bt_addr ) totalsent = 0 for i in range(num_packets): pkt = "0" * 672 totalsent += sock.send(pkt) print "sent %d bytes total" % totalsent sock.close() PyBluez-0.18/examples/advanced/l2-unreliable-server.py0000644000076400010400000000141511302237265023774 0ustar lukasAdministratorenimport sys import bluetooth if len(sys.argv) < 2: print "usage: l2-unreliable-server" sys.exit(2) timeout = int(sys.argv[1]) assert timeout >= 0 server_sock=bluetooth.BluetoothSocket( bluetooth.L2CAP ) server_sock.bind(("",0x1001)) server_sock.listen(1) while True: print "waiting for incoming connection" client_sock,address = server_sock.accept() print "Accepted connection from %s" % str(address) print "waiting for data" total = 0 while True: try: data = client_sock.recv(1024) except bluetooth.BluetoothError, e: break if len(data) == 0: break total += len(data) print "total byte read: %d" % total client_sock.close() print "connection closed" server_sock.close() PyBluez-0.18/examples/advanced/read-local-bdaddr.py0000644000076400010400000000201011302237265023244 0ustar lukasAdministratorenimport os import sys import struct import bluetooth._bluetooth as _bt def read_local_bdaddr(hci_sock): old_filter = hci_sock.getsockopt( _bt.SOL_HCI, _bt.HCI_FILTER, 14) flt = _bt.hci_filter_new() opcode = _bt.cmd_opcode_pack(_bt.OGF_INFO_PARAM, _bt.OCF_READ_BD_ADDR) _bt.hci_filter_set_ptype(flt, _bt.HCI_EVENT_PKT) _bt.hci_filter_set_event(flt, _bt.EVT_CMD_COMPLETE); _bt.hci_filter_set_opcode(flt, opcode) hci_sock.setsockopt( _bt.SOL_HCI, _bt.HCI_FILTER, flt ) _bt.hci_send_cmd(hci_sock, _bt.OGF_INFO_PARAM, _bt.OCF_READ_BD_ADDR ) pkt = hci_sock.recv(255) status,raw_bdaddr = struct.unpack("xxxxxxB6s", pkt) assert status == 0 t = [ "%X" % ord(b) for b in raw_bdaddr ] t.reverse() bdaddr = ":".join(t) # restore old filter hci_sock.setsockopt( _bt.SOL_HCI, _bt.HCI_FILTER, old_filter ) return bdaddr if __name__ == "__main__": dev_id = 0 hci_sock = _bt.hci_open_dev(dev_id) bdaddr = read_local_bdaddr(hci_sock) print bdaddr PyBluez-0.18/examples/advanced/write-inquiry-scan.py0000644000076400010400000000602711302237265023611 0ustar lukasAdministratorenimport os import sys import struct import bluetooth._bluetooth as bluez def read_inquiry_scan_activity(sock): """returns the current inquiry scan interval and window, or -1 on failure""" # save current filter old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) # Setup socket filter to receive only events related to the # read_inquiry_mode command flt = bluez.hci_filter_new() opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, bluez.OCF_READ_INQ_ACTIVITY) bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE); bluez.hci_filter_set_opcode(flt, opcode) sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt ) # first read the current inquiry mode. bluez.hci_send_cmd(sock, bluez.OGF_HOST_CTL, bluez.OCF_READ_INQ_ACTIVITY ) pkt = sock.recv(255) status,interval,window = struct.unpack("!xxxxxxBHH", pkt) interval = bluez.btohs(interval) interval = (interval >> 8) | ( (interval & 0xFF) << 8 ) window = (window >> 8) | ( (window & 0xFF) << 8 ) if status != 0: mode = -1 # restore old filter sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter ) return interval, window def write_inquiry_scan_activity(sock, interval, window): """returns 0 on success, -1 on failure""" # save current filter old_filter = sock.getsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, 14) # Setup socket filter to receive only events related to the # write_inquiry_mode command flt = bluez.hci_filter_new() opcode = bluez.cmd_opcode_pack(bluez.OGF_HOST_CTL, bluez.OCF_WRITE_INQ_ACTIVITY) bluez.hci_filter_set_ptype(flt, bluez.HCI_EVENT_PKT) bluez.hci_filter_set_event(flt, bluez.EVT_CMD_COMPLETE); bluez.hci_filter_set_opcode(flt, opcode) sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, flt ) # send the command! bluez.hci_send_cmd(sock, bluez.OGF_HOST_CTL, bluez.OCF_WRITE_INQ_ACTIVITY, struct.pack("HH", interval, window) ) pkt = sock.recv(255) status = struct.unpack("xxxxxxB", pkt)[0] # restore old filter sock.setsockopt( bluez.SOL_HCI, bluez.HCI_FILTER, old_filter ) if status != 0: return -1 return 0 dev_id = 0 try: sock = bluez.hci_open_dev(dev_id) except: print "error accessing bluetooth device..." sys.exit(1) try: interval, window = read_inquiry_scan_activity(sock) except Exception, e: print "error reading inquiry scan activity. " print e sys.exit(1) print "current inquiry scan interval: %d (0x%X) window: %d (0x%X)" % \ (interval, interval, window, window) if len(sys.argv) == 3: interval = int(sys.argv[1]) window = int(sys.argv[2]) print "target interval: %d window %d" % (interval, window) write_inquiry_scan_activity(sock, interval, window) interval, window = read_inquiry_scan_activity(sock) print "current inquiry scan interval: %d (0x%X) window: %d (0x%X)" % \ (interval, interval, window, window) PyBluez-0.18/examples/bluezchat/0000755000076400010400000000000011303332711017665 5ustar lukasAdministratorenPyBluez-0.18/examples/bluezchat/bluezchat.py0000755000076400010400000001355611302237265022244 0ustar lukasAdministratoren#!/usr/bin/python """ A simple graphical chat client to demonstrate the use of pybluez. Opens a l2cap socket and listens on PSM 0x1001 Provides the ability to scan for nearby bluetooth devices and establish chat sessions with them. """ import os import sys import time import gtk import gobject import gtk.glade import bluetooth GLADEFILE="bluezchat.glade" # ***************** def alert(text, buttons=gtk.BUTTONS_NONE, type=gtk.MESSAGE_INFO): md = gtk.MessageDialog(buttons=buttons, type=type) md.label.set_text(text) md.run() md.destroy() class BluezChatGui: def __init__(self): self.main_window_xml = gtk.glade.XML(GLADEFILE, "bluezchat_window") # connect our signal handlers dic = { "on_quit_button_clicked" : self.quit_button_clicked, "on_send_button_clicked" : self.send_button_clicked, "on_chat_button_clicked" : self.chat_button_clicked, "on_scan_button_clicked" : self.scan_button_clicked, "on_devices_tv_cursor_changed" : self.devices_tv_cursor_changed } self.main_window_xml.signal_autoconnect(dic) # prepare the floor listbox self.devices_tv = self.main_window_xml.get_widget("devices_tv") self.discovered = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) self.devices_tv.set_model(self.discovered) renderer = gtk.CellRendererText() column1=gtk.TreeViewColumn("addr", renderer, text=0) column2=gtk.TreeViewColumn("name", renderer, text=1) self.devices_tv.append_column(column1) self.devices_tv.append_column(column2) self.quit_button = self.main_window_xml.get_widget("quit_button") self.scan_button = self.main_window_xml.get_widget("scan_button") self.chat_button = self.main_window_xml.get_widget("chat_button") self.send_button = self.main_window_xml.get_widget("send_button") self.main_text = self.main_window_xml.get_widget("main_text") self.text_buffer = self.main_text.get_buffer() self.input_tb = self.main_window_xml.get_widget("input_tb") self.listed_devs = [] self.chat_button.set_sensitive(False) self.peers = {} self.sources = {} self.addresses = {} # the listening sockets self.server_sock = None # --- gui signal handlers def quit_button_clicked(self, widget): gtk.main_quit() def scan_button_clicked(self, widget): self.quit_button.set_sensitive(False) self.scan_button.set_sensitive(False) # self.chat_button.set_sensitive(False) self.discovered.clear() for addr, name in bluetooth.discover_devices (lookup_names = True): self.discovered.append ((addr, name)) self.quit_button.set_sensitive(True) self.scan_button.set_sensitive(True) # self.chat_button.set_sensitive(True) def send_button_clicked(self, widget): text = self.input_tb.get_text() if len(text) == 0: return for addr, sock in self.peers.items(): sock.send(text) self.input_tb.set_text("") self.add_text("\nme - %s" % text) def chat_button_clicked(self, widget): (model, iter) = self.devices_tv.get_selection().get_selected() if iter is not None: addr = model.get_value(iter, 0) if addr not in self.peers: self.add_text("\nconnecting to %s" % addr) self.connect(addr) else: self.add_text("\nAlready connected to %s!" % addr) def devices_tv_cursor_changed(self, widget): (model, iter) = self.devices_tv.get_selection().get_selected() if iter is not None: self.chat_button.set_sensitive(True) else: self.chat_button.set_sensitive(False) # --- network events def incoming_connection(self, source, condition): sock, info = self.server_sock.accept() address, psm = info self.add_text("\naccepted connection from %s" % str(address)) # add new connection to list of peers self.peers[address] = sock self.addresses[sock] = address source = gobject.io_add_watch (sock, gobject.IO_IN, self.data_ready) self.sources[address] = source return True def data_ready(self, sock, condition): address = self.addresses[sock] data = sock.recv(1024) if len(data) == 0: self.add_text("\nlost connection with %s" % address) gobject.source_remove(self.sources[address]) del self.sources[address] del self.peers[address] del self.addresses[sock] sock.close() else: self.add_text("\n%s - %s" % (address, str(data))) return True # --- other stuff def cleanup(self): self.hci_sock.close() def connect(self, addr): sock = bluetooth.BluetoothSocket (bluetooth.L2CAP) try: sock.connect((addr, 0x1001)) except bluez.error, e: self.add_text("\n%s" % str(e)) sock.close() return self.peers[addr] = sock source = gobject.io_add_watch (sock, gobject.IO_IN, self.data_ready) self.sources[addr] = source self.addresses[sock] = addr def add_text(self, text): self.text_buffer.insert(self.text_buffer.get_end_iter(), text) def start_server(self): self.server_sock = bluetooth.BluetoothSocket (bluetooth.L2CAP) self.server_sock.bind(("",0x1001)) self.server_sock.listen(1) gobject.io_add_watch(self.server_sock, gobject.IO_IN, self.incoming_connection) def run(self): self.text_buffer.insert(self.text_buffer.get_end_iter(), "loading..") self.start_server() gtk.main() if __name__ == "__main__": gui = BluezChatGui() gui.run() PyBluez-0.18/examples/simple/0000755000076400010400000000000011303332711017175 5ustar lukasAdministratorenPyBluez-0.18/examples/simple/asynchronous-inquiry.py0000644000076400010400000000376111302237266024017 0ustar lukasAdministratoren# file: asynchronous-inquiry.py # auth: Albert Huang # desc: demonstration of how to do asynchronous device discovery by subclassing # the DeviceDiscoverer class # $Id: asynchronous-inquiry.py 405 2006-05-06 00:39:50Z albert $ # # XXX Linux only (5/5/2006) import bluetooth import select class MyDiscoverer(bluetooth.DeviceDiscoverer): def pre_inquiry(self): self.done = False def device_discovered(self, address, device_class, name): print "%s - %s" % (address, name) # get some information out of the device class and display it. # voodoo magic specified at: # # https://www.bluetooth.org/foundry/assignnumb/document/baseband major_classes = ( "Miscellaneous", "Computer", "Phone", "LAN/Network Access point", "Audio/Video", "Peripheral", "Imaging" ) major_class = (device_class >> 8) & 0xf if major_class < 7: print " %s" % major_classes[major_class] else: print " Uncategorized" print " services:" service_classes = ( (16, "positioning"), (17, "networking"), (18, "rendering"), (19, "capturing"), (20, "object transfer"), (21, "audio"), (22, "telephony"), (23, "information")) for bitpos, classname in service_classes: if device_class & (1 << (bitpos-1)): print " %s" % classname def inquiry_complete(self): self.done = True d = MyDiscoverer() d.find_devices(lookup_names = True) readfiles = [ d, ] while True: rfds = select.select( readfiles, [], [] )[0] if d in rfds: d.process_event() if d.done: break PyBluez-0.18/examples/simple/inquiry.py0000644000076400010400000000071511302237266021262 0ustar lukasAdministratoren# file: inquiry.py # auth: Albert Huang # desc: performs a simple device inquiry followed by a remote name request of # each discovered device # $Id: inquiry.py 401 2006-05-05 19:07:48Z albert $ # import bluetooth print "performing inquiry..." 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) PyBluez-0.18/examples/simple/l2capclient.py0000644000076400010400000000104211302237266021754 0ustar lukasAdministratoren# file: l2capclient.py # desc: Demo L2CAP client for bluetooth module. # $Id: l2capclient.py 524 2007-08-15 04:04:52Z albert $ import sys import bluetooth sock=bluetooth.BluetoothSocket(bluetooth.L2CAP) if len(sys.argv) < 2: print "usage: l2capclient.py " sys.exit(2) bt_addr=sys.argv[1] port = 0x1001 print "trying to connect to %s on PSM 0x%X" % (bt_addr, port) sock.connect((bt_addr, port)) print "connected. type stuff" while True: data = raw_input() if(len(data) == 0): break sock.send(data) sock.close() PyBluez-0.18/examples/simple/l2capserver.py0000644000076400010400000000144511302237266022013 0ustar lukasAdministratoren# file: l2capclient.py # desc: Demo L2CAP server for pybluez. # $Id: l2capserver.py 524 2007-08-15 04:04:52Z albert $ import bluetooth server_sock=bluetooth.BluetoothSocket( bluetooth.L2CAP ) port = 0x1001 server_sock.bind(("",port)) server_sock.listen(1) #uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ef" #bluetooth.advertise_service( server_sock, "SampleServerL2CAP", # service_id = uuid, # service_classes = [ uuid ] # ) client_sock,address = server_sock.accept() print "Accepted connection from ",address data = client_sock.recv(1024) print "Data received:", data while data: client_sock.send('Echo =>' + data) data = client_sock.recv(1024) print "Data received:",data client_sock.close() server_sock.close() PyBluez-0.18/examples/simple/rfcomm-client.py0000644000076400010400000000217411302237266022322 0ustar lukasAdministratoren# file: rfcomm-client.py # auth: Albert Huang # desc: simple demonstration of a client application that uses RFCOMM sockets # intended for use with rfcomm-server # # $Id: rfcomm-client.py 424 2006-08-24 03:35:54Z albert $ from bluetooth import * import sys addr = None if len(sys.argv) < 2: print "no device specified. Searching all nearby bluetooth devices for" print "the SampleServer service" else: addr = sys.argv[1] print "Searching for SampleServer on %s" % addr # search for the SampleServer service uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee" service_matches = find_service( uuid = uuid, address = addr ) if len(service_matches) == 0: print "couldn't find the SampleServer service =(" sys.exit(0) first_match = service_matches[0] port = first_match["port"] name = first_match["name"] host = first_match["host"] print "connecting to \"%s\" on %s" % (name, host) # Create the client socket sock=BluetoothSocket( RFCOMM ) sock.connect((host, port)) print "connected. type stuff" while True: data = raw_input() if len(data) == 0: break sock.send(data) sock.close() PyBluez-0.18/examples/simple/rfcomm-server.py0000644000076400010400000000211111302237266022341 0ustar lukasAdministratoren# file: rfcomm-server.py # auth: Albert Huang # desc: simple demonstration of a server application that uses RFCOMM sockets # # $Id: rfcomm-server.py 518 2007-08-10 07:20:07Z albert $ from bluetooth import * server_sock=BluetoothSocket( RFCOMM ) server_sock.bind(("",PORT_ANY)) server_sock.listen(1) port = server_sock.getsockname()[1] uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee" advertise_service( server_sock, "SampleServer", service_id = uuid, service_classes = [ uuid, SERIAL_PORT_CLASS ], profiles = [ SERIAL_PORT_PROFILE ], # protocols = [ OBEX_UUID ] ) print "Waiting for connection on RFCOMM channel %d" % port client_sock, client_info = server_sock.accept() print "Accepted connection from ", client_info try: while True: data = client_sock.recv(1024) if len(data) == 0: break print "received [%s]" % data except IOError: pass print "disconnected" client_sock.close() server_sock.close() print "all done" PyBluez-0.18/examples/simple/sdp-browse.py0000644000076400010400000000211411302237266021642 0ustar lukasAdministratoren# file: sdp-browse.py # auth: Albert Huang # desc: displays services being advertised on a specified bluetooth device # $Id: sdp-browse.py 393 2006-02-24 20:30:15Z albert $ import sys import bluetooth if len(sys.argv) < 2: print "usage: sdp-browse " print " addr can be a bluetooth address, \"localhost\", or \"all\"" sys.exit(2) target = sys.argv[1] if target == "all": target = None services = bluetooth.find_service(address=target) if len(services) > 0: print "found %d services on %s" % (len(services), sys.argv[1]) print else: print "no services found" for svc in services: print "Service Name: %s" % svc["name"] print " Host: %s" % svc["host"] print " Description: %s" % svc["description"] print " Provided By: %s" % svc["provider"] print " Protocol: %s" % svc["protocol"] print " channel/PSM: %s" % svc["port"] print " svc classes: %s "% svc["service-classes"] print " profiles: %s "% svc["profiles"] print " service id: %s "% svc["service-id"] print PyBluez-0.18/msbt/0000755000076400010400000000000011303332711015033 5ustar lukasAdministratorenPyBluez-0.18/msbt/_msbt.c0000644000076400010400000006233311302237264016320 0ustar lukasAdministratoren#include #include #include #include #include #if 1 static void dbg(const char *fmt, ...) { } #else static void dbg(const char *fmt, ...) { va_list ap; va_start (ap, fmt); vprintf (fmt, ap); va_end (ap); } #endif static void Err_SetFromWSALastError(PyObject *exc) { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, WSAGetLastError(), 0, (LPTSTR) &lpMsgBuf, 0, NULL ); PyErr_SetString( exc, lpMsgBuf ); LocalFree(lpMsgBuf); } #define _CHECK_OR_RAISE_WSA(cond) \ if( !(cond) ) { Err_SetFromWSALastError( PyExc_IOError ); return 0; } static void ba2str( BTH_ADDR ba, char *addr ) { int i; unsigned char bytes[6]; for( i=0; i<6; i++ ) { bytes[5-i] = (unsigned char) ((ba >> (i*8)) & 0xff); } sprintf(addr, "%02X:%02X:%02X:%02X:%02X:%02X", bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5] ); } static PyObject * msbt_initwinsock(PyObject *self) { WORD wVersionRequested; WSADATA wsaData; int status; wVersionRequested = MAKEWORD( 2, 0 ); status = WSAStartup( wVersionRequested, &wsaData ); if( 0 != status ) { Err_SetFromWSALastError( PyExc_RuntimeError ); return 0; } Py_INCREF( Py_None ); return Py_None; } PyDoc_STRVAR(msbt_initwinsock_doc, "TODO"); 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 ); } static int str2uuid( const char *uuid_str, GUID *uuid) { // Parse uuid128 standard format: 12345678-9012-3456-7890-123456789012 int i; char buf[20] = { 0 }; strncpy(buf, uuid_str, 8); uuid->Data1 = strtoul( buf, NULL, 16 ); memset(buf, 0, sizeof(buf)); strncpy(buf, uuid_str+9, 4); uuid->Data2 = (unsigned short) strtoul( buf, NULL, 16 ); memset(buf, 0, sizeof(buf)); strncpy(buf, uuid_str+14, 4); uuid->Data3 = (unsigned short) strtoul( buf, NULL, 16 ); memset(buf, 0, sizeof(buf)); strncpy(buf, uuid_str+19, 4); strncpy(buf+4, uuid_str+24, 12); for( i=0; i<8; i++ ) { char buf2[3] = { buf[2*i], buf[2*i+1], 0 }; uuid->Data4[i] = (unsigned char)strtoul( buf2, NULL, 16 ); } return 0; } // ====================== SOCKET FUNCTIONS ======================== static PyObject * msbt_socket(PyObject *self, PyObject *args) { int family = AF_BTH; int type; int proto; int sockfd = -1; if(!PyArg_ParseTuple(args, "ii", &type, &proto)) return 0; Py_BEGIN_ALLOW_THREADS; sockfd = socket( AF_BTH, type, proto ); Py_END_ALLOW_THREADS; _CHECK_OR_RAISE_WSA( SOCKET_ERROR != sockfd ); return PyInt_FromLong( sockfd ); }; PyDoc_STRVAR(msbt_socket_doc, "TODO"); static PyObject * msbt_bind(PyObject *self, PyObject *args) { char *addrstr = NULL; int addrstrlen = -1; int sockfd = -1; int port = -1; char buf[100] = { 0 }; int buf_len = sizeof( buf ); int status; SOCKADDR_BTH sa = { 0 }; int sa_len = sizeof(sa); if(!PyArg_ParseTuple(args, "is#i", &sockfd, &addrstr, &addrstrlen, &port)) return 0; if( addrstrlen == 0 ) { sa.btAddr = 0; } else { _CHECK_OR_RAISE_WSA( NO_ERROR == WSAStringToAddress( addrstr, \ AF_BTH, NULL, (LPSOCKADDR)&sa, &sa_len ) ); } sa.addressFamily = AF_BTH; sa.port = port; Py_BEGIN_ALLOW_THREADS; status = bind( sockfd, (LPSOCKADDR)&sa, sa_len ); Py_END_ALLOW_THREADS; _CHECK_OR_RAISE_WSA( NO_ERROR == status ); Py_INCREF(Py_None); return Py_None; }; PyDoc_STRVAR(msbt_bind_doc, "TODO"); static PyObject * msbt_listen(PyObject *self, PyObject *args) { int sockfd = -1; int backlog = -1; DWORD status; if(!PyArg_ParseTuple(args, "ii", &sockfd, &backlog)) return 0; Py_BEGIN_ALLOW_THREADS; status = listen(sockfd, backlog); Py_END_ALLOW_THREADS; _CHECK_OR_RAISE_WSA( NO_ERROR == status ); Py_INCREF(Py_None); return Py_None; }; PyDoc_STRVAR(msbt_listen_doc, "TODO"); static PyObject * msbt_accept(PyObject *self, PyObject *args) { int sockfd = -1; int clientfd = -1; SOCKADDR_BTH ca = { 0 }; int ca_len = sizeof(ca); PyObject *result = NULL; char buf[100] = { 0 }; int buf_len = sizeof(buf); if(!PyArg_ParseTuple(args, "i", &sockfd)) return 0; Py_BEGIN_ALLOW_THREADS; clientfd = accept(sockfd, (LPSOCKADDR)&ca, &ca_len); Py_END_ALLOW_THREADS; _CHECK_OR_RAISE_WSA( SOCKET_ERROR != clientfd ); ba2str(ca.btAddr, buf); result = Py_BuildValue( "isi", clientfd, buf, ca.port ); return result; }; PyDoc_STRVAR(msbt_accept_doc, "TODO"); static PyObject * msbt_connect(PyObject *self, PyObject *args) { int sockfd = -1; char *addrstr = NULL; int port = -1; SOCKADDR_BTH sa = { 0 }; int sa_len = sizeof(sa); DWORD status; if(!PyArg_ParseTuple(args, "isi", &sockfd, &addrstr, &port)) return 0; if( SOCKET_ERROR == WSAStringToAddress( addrstr, AF_BTH, NULL, (LPSOCKADDR)&sa, &sa_len ) ) { Err_SetFromWSALastError(PyExc_IOError); return 0; } sa.addressFamily = AF_BTH; sa.port = port; Py_BEGIN_ALLOW_THREADS; status = connect(sockfd, (LPSOCKADDR)&sa, sizeof(sa)); Py_END_ALLOW_THREADS; _CHECK_OR_RAISE_WSA( NO_ERROR == status ); Py_INCREF(Py_None); return Py_None; }; PyDoc_STRVAR(msbt_connect_doc, "TODO"); static PyObject * msbt_send(PyObject *self, PyObject *args) { int sockfd = -1; char *data = NULL; int datalen = -1; int flags = 0; int sent = 0; if(!PyArg_ParseTuple(args, "is#|i", &sockfd, &data, &datalen, &flags)) return 0; Py_BEGIN_ALLOW_THREADS; sent = send(sockfd, data, datalen, flags); Py_END_ALLOW_THREADS; if (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAETIMEDOUT ) { return PyInt_FromLong ( 0 ); } _CHECK_OR_RAISE_WSA( SOCKET_ERROR != sent ); return PyInt_FromLong( sent ); }; PyDoc_STRVAR(msbt_send_doc, "TODO"); static PyObject * msbt_recv(PyObject *self, PyObject *args) { int sockfd = -1; PyObject *buf = NULL; int datalen = -1; int flags = 0; int received = 0; if(!PyArg_ParseTuple(args, "ii|i", &sockfd, &datalen, &flags)) return 0; buf = PyString_FromStringAndSize((char*)0, datalen); Py_BEGIN_ALLOW_THREADS; received = recv(sockfd, PyString_AS_STRING(buf), datalen, flags); Py_END_ALLOW_THREADS; if (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAETIMEDOUT ) { _PyString_Resize(&buf, 0); // XXX is this necessary? -albert return buf; } if( SOCKET_ERROR == received ){ Py_DECREF(buf); return 0; } if( received != datalen ) _PyString_Resize(&buf, received); return buf; }; PyDoc_STRVAR(msbt_recv_doc, "TODO"); static PyObject * msbt_close(PyObject *self, PyObject *args) { int sockfd = -1; int status; if(!PyArg_ParseTuple( args, "i", &sockfd )) return 0; Py_BEGIN_ALLOW_THREADS; status = closesocket(sockfd); Py_END_ALLOW_THREADS; Py_INCREF(Py_None); return Py_None; }; PyDoc_STRVAR(msbt_close_doc, "TODO"); static PyObject * msbt_getsockname(PyObject *self, PyObject *args) { int sockfd = -1; SOCKADDR_BTH sa = { 0 }; int sa_len = sizeof(sa); char buf[100] = { 0 }; int buf_len = sizeof(buf); int status; if(!PyArg_ParseTuple( args, "i", &sockfd )) return 0; sa.addressFamily = AF_BTH; Py_BEGIN_ALLOW_THREADS; status = getsockname( sockfd, (LPSOCKADDR)&sa, &sa_len ); Py_END_ALLOW_THREADS; _CHECK_OR_RAISE_WSA( NO_ERROR == status ); ba2str( sa.btAddr, buf ); return Py_BuildValue( "si", buf, sa.port ); }; PyDoc_STRVAR(msbt_getsockname_doc, "TODO"); static PyObject * msbt_dup(PyObject *self, PyObject *args) { int sockfd = -1; int newsockfd = -1; int status; DWORD pid; WSAPROTOCOL_INFO pi = { 0 }; if(!PyArg_ParseTuple( args, "i", &sockfd )) return 0; // prepare to duplicate pid = GetCurrentProcessId(); status = WSADuplicateSocket( sockfd, pid, &pi ); _CHECK_OR_RAISE_WSA( NO_ERROR == status ); // duplicate! newsockfd = WSASocket( FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &pi, 0, 0 ); _CHECK_OR_RAISE_WSA( INVALID_SOCKET != newsockfd ); return PyInt_FromLong( newsockfd ); } PyDoc_STRVAR(msbt_dup_doc, "TODO"); // ==================== static PyObject * msbt_discover_devices(PyObject *self, PyObject *args) { int flushcache = 0; int lookupnames = 0; // inquiry data structure DWORD qs_len = sizeof( WSAQUERYSET ); WSAQUERYSET *qs = (WSAQUERYSET*) malloc( qs_len ); DWORD flags = LUP_CONTAINERS; HANDLE h; int done = 0; PyObject *toreturn = NULL; int status = 0; dbg("msbt_discover_devices\n"); if(!PyArg_ParseTuple(args, "ii", &flushcache, &lookupnames)) { free( qs ); return 0; } if (flushcache) flushcache = LUP_FLUSHCACHE; if (lookupnames) lookupnames = LUP_RETURN_NAME; ZeroMemory( qs, qs_len ); qs->dwSize = sizeof(WSAQUERYSET); qs->dwNameSpace = NS_BTH; flags |= flushcache | lookupnames | LUP_RETURN_ADDR; Py_BEGIN_ALLOW_THREADS; // start the device inquiry status = WSALookupServiceBegin (qs, flags, &h); Py_END_ALLOW_THREADS; if (SOCKET_ERROR == status) { int error = WSAGetLastError(); if( error == WSASERVICE_NOT_FOUND ) { dbg("No devices detected\n"); // no devices detected. WSALookupServiceEnd( h ); free( qs ); PyErr_SetString (PyExc_IOError, "No Bluetooth adapter detected"); return NULL; } else { Err_SetFromWSALastError( PyExc_IOError ); free(qs); return 0; } } toreturn = PyList_New(0); // iterate through the inquiry results while(! done) { Py_BEGIN_ALLOW_THREADS; status = WSALookupServiceNext (h, flags, &qs_len, qs); Py_END_ALLOW_THREADS; if (NO_ERROR == status) { char buf[40] = {0}; PyObject *tup = NULL; BTH_ADDR result = ((SOCKADDR_BTH*)qs->lpcsaBuffer->RemoteAddr.lpSockaddr)->btAddr; ba2str( result, buf ); if( lookupnames ) { tup = Py_BuildValue( "ss", buf, qs->lpszServiceInstanceName ); } else { tup = PyString_FromString (buf); } PyList_Append( toreturn, tup ); Py_DECREF( tup ); } else { int error = WSAGetLastError(); if( error == WSAEFAULT ) { // the qs data structure is too small. allocate a bigger // buffer and try again. free( qs ); qs = (WSAQUERYSET*) malloc( qs_len ); } else if( error == WSA_E_NO_MORE ) { // no more results. done = 1; } else { // unexpected error. raise an exception. Err_SetFromWSALastError( PyExc_IOError ); Py_DECREF( toreturn ); return 0; } } } Py_BEGIN_ALLOW_THREADS; WSALookupServiceEnd( h ); Py_END_ALLOW_THREADS; free( qs ); return toreturn; } PyDoc_STRVAR(msbt_discover_devices_doc, "TODO"); static PyObject * msbt_lookup_name(PyObject *self, PyObject *args) { HANDLE rhandle = NULL; BLUETOOTH_FIND_RADIO_PARAMS p = { sizeof(p) }; HBLUETOOTH_RADIO_FIND fhandle = NULL; BLUETOOTH_DEVICE_INFO dinfo = { 0 }; char *addrstr = NULL; SOCKADDR_BTH sa = { 0 }; int sa_len = sizeof(sa); DWORD status; if(!PyArg_ParseTuple(args,"s",&addrstr)) return 0; _CHECK_OR_RAISE_WSA( NO_ERROR == WSAStringToAddress( addrstr, \ AF_BTH, NULL, (LPSOCKADDR)&sa, &sa_len ) ); // printf("looking for first radio\n"); fhandle = BluetoothFindFirstRadio(&p, &rhandle); _CHECK_OR_RAISE_WSA( NULL != fhandle ); // printf("found radio 0x%p\n", rhandle ); dinfo.dwSize = sizeof( dinfo ); dinfo.Address.ullLong = sa.btAddr; status = BluetoothGetDeviceInfo( rhandle, &dinfo ); _CHECK_OR_RAISE_WSA( status == ERROR_SUCCESS ); // printf("name: %s\n", dinfo.szName ); _CHECK_OR_RAISE_WSA( TRUE == BluetoothFindRadioClose( fhandle ) ); return PyUnicode_FromWideChar( dinfo.szName, wcslen( dinfo.szName ) ); } PyDoc_STRVAR(msbt_lookup_name_doc, "TODO"); // ======================= SDP FUNCTIONS ====================== static PyObject * msbt_find_service(PyObject *self, PyObject *args) { char *addrstr = NULL; char *uuidstr = NULL; // inquiry data structure DWORD qs_len = sizeof( WSAQUERYSET ); WSAQUERYSET *qs = (WSAQUERYSET*) malloc( qs_len ); DWORD flags = LUP_FLUSHCACHE | LUP_RETURN_ALL; HANDLE h; int done = 0; int status = 0; PyObject *record = NULL; PyObject *toreturn = NULL; GUID uuid = { 0 }; char localAddressBuf[20] = { 0 }; if(!PyArg_ParseTuple(args,"ss", &addrstr, &uuidstr)) return 0; ZeroMemory( qs, qs_len ); qs->dwSize = sizeof(WSAQUERYSET); qs->dwNameSpace = NS_BTH; qs->dwNumberOfCsAddrs = 0; qs->lpszContext = (LPSTR) localAddressBuf; if( 0 == strcmp( addrstr, "localhost" ) ) { // find the Bluetooth address of the first local adapter. #if 0 HANDLE rhandle = NULL; BLUETOOTH_RADIO_INFO info; BLUETOOTH_FIND_RADIO_PARAMS p = { sizeof(p) }; HBLUETOOTH_RADIO_FIND fhandle = NULL; printf("looking for first radio\n"); fhandle = BluetoothFindFirstRadio(&p, &rhandle); _CHECK_OR_RAISE_WSA( NULL != fhandle ); printf("first radio: 0x%p\n", rhandle); _CHECK_OR_RAISE_WSA( \ TRUE == BluetoothFindRadioClose( fhandle ) ); printf("retrieving radio info on handle 0x%p\n", rhandle); info.dwSize = sizeof(info); // XXX why doesn't this work??? _CHECK_OR_RAISE_WSA( \ ERROR_SUCCESS != BluetoothGetRadioInfo( rhandle, &info ) ); ba2str( info.address.ullLong, localAddressBuf ); #else // bind a temporary socket and get its Bluetooth address SOCKADDR_BTH sa = { 0 }; int sa_len = sizeof(sa); int tmpfd = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); _CHECK_OR_RAISE_WSA( tmpfd >= 0 ); sa.addressFamily = AF_BTH; sa.port = BT_PORT_ANY; _CHECK_OR_RAISE_WSA(NO_ERROR == bind(tmpfd,(LPSOCKADDR)&sa,sa_len) ); _CHECK_OR_RAISE_WSA(NO_ERROR == getsockname(tmpfd, (LPSOCKADDR)&sa,\ &sa_len ) ); ba2str(sa.btAddr, localAddressBuf ); close(tmpfd); #endif flags |= LUP_RES_SERVICE; } else { strcpy( localAddressBuf, addrstr ); } if( strlen(uuidstr) != 36 || uuidstr[8] != '-' || uuidstr[13] != '-' || uuidstr[18] != '-' || uuidstr[23] != '-' ) { PyErr_SetString( PyExc_ValueError, "Invalid UUID!"); return 0; } str2uuid( uuidstr, &uuid ); qs->lpServiceClassId = &uuid; Py_BEGIN_ALLOW_THREADS; status = WSALookupServiceBegin( qs, flags, &h ); Py_END_ALLOW_THREADS; if( SOCKET_ERROR == status) { int err_code = WSAGetLastError(); if( WSASERVICE_NOT_FOUND == err_code ) { // this device does not advertise any services. return an // empty list free( qs ); return PyList_New(0); } else { // unexpected error. raise an exception Err_SetFromWSALastError( PyExc_IOError ); free(qs); return 0; } } toreturn = PyList_New(0); // iterate through the inquiry results while(! done) { Py_BEGIN_ALLOW_THREADS; status = WSALookupServiceNext( h, flags, &qs_len, qs ); Py_END_ALLOW_THREADS; if (NO_ERROR == status) { int proto; int port; PyObject *rawrecord = NULL; CSADDR_INFO *csinfo = NULL; record = PyDict_New(); // set host name dict_set_strings( record, "host", localAddressBuf ); // set service name dict_set_strings( record, "name", qs->lpszServiceInstanceName ); // set description dict_set_strings( record, "description", qs->lpszComment ); // set protocol and port csinfo = qs->lpcsaBuffer; if( csinfo != NULL ) { proto = csinfo->iProtocol; port = ((SOCKADDR_BTH*)csinfo->RemoteAddr.lpSockaddr)->port; dict_set_str_long(record, "port", port); if( proto == BTHPROTO_RFCOMM ) { dict_set_strings(record, "protocol", "RFCOMM"); } else if( proto == BTHPROTO_L2CAP ) { dict_set_strings(record, "protocol", "L2CAP"); } else { dict_set_strings(record, "protocol", "UNKNOWN"); dict_set_str_pyobj(record, "port", Py_None); } } else { dict_set_str_pyobj(record, "port", Py_None); dict_set_strings(record, "protocol", "UNKNOWN"); } // add the raw service record to be parsed in python rawrecord = PyString_FromStringAndSize( qs->lpBlob->pBlobData, qs->lpBlob->cbSize ); dict_set_str_pyobj(record, "rawrecord", rawrecord); Py_DECREF(rawrecord); PyList_Append( toreturn, record ); Py_DECREF( record ); } else { int error = WSAGetLastError(); if( error == WSAEFAULT ) { // the qs data structure is too small. allocate a bigger // buffer and try again. free( qs ); qs = (WSAQUERYSET*) malloc( qs_len ); } else if( error == WSA_E_NO_MORE ) { // no more results. done = 1; } else { // unexpected error. raise an exception. Err_SetFromWSALastError( PyExc_IOError ); Py_DECREF( toreturn ); return 0; } } } Py_BEGIN_ALLOW_THREADS; WSALookupServiceEnd( h ); Py_END_ALLOW_THREADS; free( qs ); return toreturn; } PyDoc_STRVAR(msbt_find_service_doc, "TODO"); static PyObject * msbt_set_service_raw(PyObject *self, PyObject *args) { int advertise = 0; WSAQUERYSET qs = { 0 }; WSAESETSERVICEOP op; char *record = NULL; int reclen = -1; BTH_SET_SERVICE *si = NULL; int silen = -1; ULONG sdpVersion = BTH_SDP_VERSION; BLOB blob = { 0 }; int status = -1; PyObject *result = NULL; HANDLE rh = 0; if(!PyArg_ParseTuple(args, "s#i|i", &record, &reclen, &advertise, &rh)) return 0; silen = sizeof(BTH_SET_SERVICE) + reclen - 1; si = (BTH_SET_SERVICE*) malloc(silen); ZeroMemory( si, silen ); si->pSdpVersion = &sdpVersion; si->pRecordHandle = &rh; si->fCodService = 0; si->Reserved; si->ulRecordLength = reclen; memcpy( si->pRecord, record, reclen ); op = advertise ? RNRSERVICE_REGISTER : RNRSERVICE_DELETE; qs.dwSize = sizeof(qs); qs.lpBlob = &blob; qs.dwNameSpace = NS_BTH; blob.cbSize = silen; blob.pBlobData = (BYTE*)si; status = WSASetService( &qs, op, 0 ); free( si ); if( SOCKET_ERROR == status ) { Err_SetFromWSALastError( PyExc_IOError ); return 0; } return PyInt_FromLong( (unsigned long) rh ); } PyDoc_STRVAR(msbt_set_service_raw_doc, ""); static PyObject * msbt_set_service(PyObject *self, PyObject *args) { int advertise = 0; WSAQUERYSET qs = { 0 }; WSAESETSERVICEOP op; SOCKADDR_BTH sa = { 0 }; int sa_len = sizeof(sa); char *service_name = NULL; char *service_desc = NULL; char *service_class_id_str = NULL; CSADDR_INFO sockInfo = { 0 }; GUID uuid = { 0 }; int sockfd; if(!PyArg_ParseTuple(args, "iisss", &sockfd, &advertise, &service_name, &service_desc, &service_class_id_str)) return 0; op = advertise ? RNRSERVICE_REGISTER : RNRSERVICE_DELETE; if( SOCKET_ERROR == getsockname( sockfd, (SOCKADDR*) &sa, &sa_len ) ) { Err_SetFromWSALastError( PyExc_IOError ); return 0; } sockInfo.iProtocol = BTHPROTO_RFCOMM; sockInfo.iSocketType = SOCK_STREAM; sockInfo.LocalAddr.lpSockaddr = (LPSOCKADDR) &sa; sockInfo.LocalAddr.iSockaddrLength = sizeof(sa); sockInfo.RemoteAddr.lpSockaddr = (LPSOCKADDR) &sa; sockInfo.RemoteAddr.iSockaddrLength = sizeof(sa); qs.dwSize = sizeof(qs); qs.dwNameSpace = NS_BTH; qs.lpcsaBuffer = &sockInfo; qs.lpszServiceInstanceName = service_name; qs.lpszComment = service_desc; str2uuid( service_class_id_str, &uuid ); qs.lpServiceClassId = (LPGUID) &uuid; qs.dwNumberOfCsAddrs = 1; if( SOCKET_ERROR == WSASetService( &qs, op, 0 ) ) { Err_SetFromWSALastError( PyExc_IOError ); return 0; } Py_INCREF( Py_None ); return Py_None; } PyDoc_STRVAR(msbt_set_service_doc, ""); static PyObject * msbt_setblocking(PyObject *self, PyObject *args) { int sockfd = -1; int block = -1; PyObject* blockingArg; if(!PyArg_ParseTuple(args, "iO", &sockfd, &blockingArg)) return 0; block = PyInt_AsLong(blockingArg); if (block == -1 && PyErr_Occurred()) return NULL; if (block) { block = 0; ioctlsocket( sockfd, FIONBIO, &block); } else { block = 1; ioctlsocket( sockfd, FIONBIO, &block); } Py_INCREF(Py_None); return Py_None; } PyDoc_STRVAR(msbt_setblocking_doc, ""); static PyObject * msbt_settimeout(PyObject *self, PyObject *args) { int sockfd = -1; double secondTimeout = -1; DWORD timeout = -1; int timeoutLen = sizeof(DWORD); if(!PyArg_ParseTuple(args, "id", &sockfd, &secondTimeout)) return 0; timeout = (DWORD) (secondTimeout * 1000); if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, timeoutLen) != 0) { Err_SetFromWSALastError( PyExc_IOError ); return 0; } if(setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, timeoutLen) != 0) { Err_SetFromWSALastError( PyExc_IOError ); return 0; } Py_INCREF(Py_None); return Py_None; } PyDoc_STRVAR(msbt_settimeout_doc, ""); static PyObject * msbt_gettimeout(PyObject *self, PyObject *args) { int sockfd = -1; DWORD recv_timeout = -1; int recv_timeoutLen = sizeof(DWORD); double timeout = -1; if(!PyArg_ParseTuple(args, "i", &sockfd)) return 0; if(getsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char*)&recv_timeout, &recv_timeoutLen) != 0) { Err_SetFromWSALastError( PyExc_IOError ); return 0; } timeout = (double)recv_timeout / 1000; return PyFloat_FromDouble(timeout); } PyDoc_STRVAR(msbt_gettimeout_doc, ""); // ======================= ADMINISTRATIVE ========================= static PyMethodDef msbt_methods[] = { { "initwinsock", (PyCFunction)msbt_initwinsock, METH_NOARGS, msbt_initwinsock_doc }, { "socket", (PyCFunction)msbt_socket, METH_VARARGS, msbt_socket_doc }, { "bind", (PyCFunction)msbt_bind, METH_VARARGS, msbt_bind_doc }, { "listen", (PyCFunction)msbt_listen, METH_VARARGS, msbt_listen_doc }, { "accept", (PyCFunction)msbt_accept, METH_VARARGS, msbt_accept_doc }, { "connect", (PyCFunction)msbt_connect, METH_VARARGS, msbt_connect_doc }, { "send", (PyCFunction)msbt_send, METH_VARARGS, msbt_send_doc }, { "recv", (PyCFunction)msbt_recv, METH_VARARGS, msbt_recv_doc }, { "close", (PyCFunction)msbt_close, METH_VARARGS, msbt_close_doc }, { "getsockname", (PyCFunction)msbt_getsockname, METH_VARARGS, msbt_getsockname_doc }, { "dup", (PyCFunction)msbt_dup, METH_VARARGS, msbt_dup_doc }, { "discover_devices", (PyCFunction)msbt_discover_devices, METH_VARARGS, msbt_discover_devices_doc }, { "lookup_name", (PyCFunction)msbt_lookup_name, METH_VARARGS, msbt_lookup_name_doc }, { "find_service", (PyCFunction)msbt_find_service, METH_VARARGS, msbt_find_service_doc }, { "set_service", (PyCFunction)msbt_set_service, METH_VARARGS, msbt_set_service_doc }, { "set_service_raw", (PyCFunction)msbt_set_service_raw, METH_VARARGS, msbt_set_service_raw_doc }, { "setblocking", (PyCFunction)msbt_setblocking, METH_VARARGS, msbt_setblocking_doc }, { "settimeout", (PyCFunction)msbt_settimeout, METH_VARARGS, msbt_settimeout_doc }, { "gettimeout", (PyCFunction)msbt_gettimeout, METH_VARARGS, msbt_gettimeout_doc }, { NULL, NULL } }; PyDoc_STRVAR(msbt_doc, "TODO\n"); PyMODINIT_FUNC init_msbt(void) { PyObject *m; m = Py_InitModule3("_msbt", msbt_methods, msbt_doc); #define ADD_INT_CONSTANT(m,a) PyModule_AddIntConstant(m, #a, a) ADD_INT_CONSTANT(m, SOCK_STREAM); ADD_INT_CONSTANT(m, BTHPROTO_RFCOMM); ADD_INT_CONSTANT(m, BT_PORT_ANY); } PyBluez-0.18/osx/0000755000076400010400000000000011303332711014677 5ustar lukasAdministratorenPyBluez-0.18/osx/_osxbt.c0000644000076400010400000005247711302237265016367 0ustar lukasAdministratoren#include #include #include //#include //#include //#include //#include //#include #include #include #if 0 // ====================== SOCKET FUNCTIONS ======================== static PyObject * osxbt_socket(PyObject *self, PyObject *args) { int family = AF_BTH; int type; int proto; int sockfd = -1; if(!PyArg_ParseTuple(args, "ii", &type, &proto)) return 0; Py_BEGIN_ALLOW_THREADS; sockfd = socket( AF_BTH, type, proto ); Py_END_ALLOW_THREADS; _CHECK_OR_RAISE_WSA( SOCKET_ERROR != sockfd ); return PyInt_FromLong( sockfd ); }; PyDoc_STRVAR(osxbt_socket_doc, "TODO"); static PyObject * osxbt_bind(PyObject *self, PyObject *args) { char *addrstr = NULL; int addrstrlen = -1; int sockfd = -1; int port = -1; char buf[100] = { 0 }; int buf_len = sizeof( buf ); int status; SOCKADDR_BTH sa = { 0 }; int sa_len = sizeof(sa); if(!PyArg_ParseTuple(args, "is#i", &sockfd, &addrstr, &addrstrlen, &port)) return 0; if( addrstrlen == 0 ) { sa.btAddr = 0; } else { _CHECK_OR_RAISE_WSA( NO_ERROR == WSAStringToAddress( addrstr, \ AF_BTH, NULL, (LPSOCKADDR)&sa, &sa_len ) ); } sa.addressFamily = AF_BTH; sa.port = port; Py_BEGIN_ALLOW_THREADS; status = bind( sockfd, (LPSOCKADDR)&sa, sa_len ); Py_END_ALLOW_THREADS; _CHECK_OR_RAISE_WSA( NO_ERROR == status ); Py_INCREF(Py_None); return Py_None; }; PyDoc_STRVAR(osxbt_bind_doc, "TODO"); static PyObject * osxbt_listen(PyObject *self, PyObject *args) { int sockfd = -1; int backlog = -1; DWORD status; if(!PyArg_ParseTuple(args, "ii", &sockfd, &backlog)) return 0; Py_BEGIN_ALLOW_THREADS; status = listen(sockfd, backlog); Py_END_ALLOW_THREADS; _CHECK_OR_RAISE_WSA( NO_ERROR == status ); Py_INCREF(Py_None); return Py_None; }; PyDoc_STRVAR(osxbt_listen_doc, "TODO"); static PyObject * osxbt_accept(PyObject *self, PyObject *args) { int sockfd = -1; int clientfd = -1; SOCKADDR_BTH ca = { 0 }; int ca_len = sizeof(ca); PyObject *result = NULL; char buf[100] = { 0 }; int buf_len = sizeof(buf); if(!PyArg_ParseTuple(args, "i", &sockfd)) return 0; Py_BEGIN_ALLOW_THREADS; clientfd = accept(sockfd, (LPSOCKADDR)&ca, &ca_len); Py_END_ALLOW_THREADS; _CHECK_OR_RAISE_WSA( SOCKET_ERROR != clientfd ); ba2str(ca.btAddr, buf); result = Py_BuildValue( "isi", clientfd, buf, ca.port ); return result; }; PyDoc_STRVAR(osxbt_accept_doc, "TODO"); static PyObject * osxbt_connect(PyObject *self, PyObject *args) { int sockfd = -1; char *addrstr = NULL; int port = -1; SOCKADDR_BTH sa = { 0 }; int sa_len = sizeof(sa); DWORD status; if(!PyArg_ParseTuple(args, "isi", &sockfd, &addrstr, &port)) return 0; if( SOCKET_ERROR == WSAStringToAddress( addrstr, AF_BTH, NULL, (LPSOCKADDR)&sa, &sa_len ) ) { Err_SetFromWSALastError(PyExc_IOError); return 0; } sa.addressFamily = AF_BTH; sa.port = port; Py_BEGIN_ALLOW_THREADS; status = connect(sockfd, (LPSOCKADDR)&sa, sizeof(sa)); Py_END_ALLOW_THREADS; _CHECK_OR_RAISE_WSA( NO_ERROR == status ); Py_INCREF(Py_None); return Py_None; }; PyDoc_STRVAR(osxbt_connect_doc, "TODO"); static PyObject * osxbt_send(PyObject *self, PyObject *args) { int sockfd = -1; char *data = NULL; int datalen = -1; int flags = 0; int sent = 0; if(!PyArg_ParseTuple(args, "is#|i", &sockfd, &data, &datalen, &flags)) return 0; Py_BEGIN_ALLOW_THREADS; sent = send(sockfd, data, datalen, flags); Py_END_ALLOW_THREADS; if (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAETIMEDOUT ) { return PyInt_FromLong ( 0 ); } _CHECK_OR_RAISE_WSA( SOCKET_ERROR != sent ); return PyInt_FromLong( sent ); }; PyDoc_STRVAR(osxbt_send_doc, "TODO"); static PyObject * osxbt_recv(PyObject *self, PyObject *args) { int sockfd = -1; PyObject *buf = NULL; int datalen = -1; int flags = 0; int received = 0; if(!PyArg_ParseTuple(args, "ii|i", &sockfd, &datalen, &flags)) return 0; buf = PyString_FromStringAndSize((char*)0, datalen); Py_BEGIN_ALLOW_THREADS; received = recv(sockfd, PyString_AS_STRING(buf), datalen, flags); Py_END_ALLOW_THREADS; if (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAETIMEDOUT ) { _PyString_Resize(&buf, 0); // XXX is this necessary? -albert return buf; } if( SOCKET_ERROR == received ){ Py_DECREF(buf); return 0; } if( received != datalen ) _PyString_Resize(&buf, received); return buf; }; PyDoc_STRVAR(osxbt_recv_doc, "TODO"); static PyObject * osxbt_close(PyObject *self, PyObject *args) { int sockfd = -1; int status; if(!PyArg_ParseTuple( args, "i", &sockfd )) return 0; Py_BEGIN_ALLOW_THREADS; status = closesocket(sockfd); Py_END_ALLOW_THREADS; Py_INCREF(Py_None); return Py_None; }; PyDoc_STRVAR(osxbt_close_doc, "TODO"); static PyObject * osxbt_getsockname(PyObject *self, PyObject *args) { int sockfd = -1; SOCKADDR_BTH sa = { 0 }; int sa_len = sizeof(sa); char buf[100] = { 0 }; int buf_len = sizeof(buf); int status; if(!PyArg_ParseTuple( args, "i", &sockfd )) return 0; sa.addressFamily = AF_BTH; Py_BEGIN_ALLOW_THREADS; status = getsockname( sockfd, (LPSOCKADDR)&sa, &sa_len ); Py_END_ALLOW_THREADS; _CHECK_OR_RAISE_WSA( NO_ERROR == status ); ba2str( sa.btAddr, buf ); return Py_BuildValue( "si", buf, sa.port ); }; PyDoc_STRVAR(osxbt_getsockname_doc, "TODO"); static PyObject * osxbt_dup(PyObject *self, PyObject *args) { int sockfd = -1; int newsockfd = -1; int status; DWORD pid; WSAPROTOCOL_INFO pi = { 0 }; if(!PyArg_ParseTuple( args, "i", &sockfd )) return 0; // prepare to duplicate pid = GetCurrentProcessId(); status = WSADuplicateSocket( sockfd, pid, &pi ); _CHECK_OR_RAISE_WSA( NO_ERROR == status ); // duplicate! newsockfd = WSASocket( FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &pi, 0, 0 ); _CHECK_OR_RAISE_WSA( INVALID_SOCKET != newsockfd ); return PyInt_FromLong( newsockfd ); } PyDoc_STRVAR(osxbt_dup_doc, "TODO"); // ==================== static PyObject * osxbt_lookup_name(PyObject *self, PyObject *args) { HANDLE rhandle = NULL; BLUETOOTH_FIND_RADIO_PARAMS p = { sizeof(p) }; HBLUETOOTH_RADIO_FIND fhandle = NULL; BLUETOOTH_DEVICE_INFO dinfo = { 0 }; char *addrstr = NULL; SOCKADDR_BTH sa = { 0 }; int sa_len = sizeof(sa); DWORD status; if(!PyArg_ParseTuple(args,"s",&addrstr)) return 0; _CHECK_OR_RAISE_WSA( NO_ERROR == WSAStringToAddress( addrstr, \ AF_BTH, NULL, (LPSOCKADDR)&sa, &sa_len ) ); // printf("looking for first radio\n"); fhandle = BluetoothFindFirstRadio(&p, &rhandle); _CHECK_OR_RAISE_WSA( NULL != fhandle ); // printf("found radio 0x%p\n", rhandle ); dinfo.dwSize = sizeof( dinfo ); dinfo.Address.ullLong = sa.btAddr; status = BluetoothGetDeviceInfo( rhandle, &dinfo ); _CHECK_OR_RAISE_WSA( status == ERROR_SUCCESS ); // printf("name: %s\n", dinfo.szName ); _CHECK_OR_RAISE_WSA( TRUE == BluetoothFindRadioClose( fhandle ) ); return PyUnicode_FromWideChar( dinfo.szName, wcslen( dinfo.szName ) ); } PyDoc_STRVAR(osxbt_lookup_name_doc, "TODO"); // ======================= SDP FUNCTIONS ====================== static PyObject * osxbt_find_service(PyObject *self, PyObject *args) { char *addrstr = NULL; char *uuidstr = NULL; // inquiry data structure DWORD qs_len = sizeof( WSAQUERYSET ); WSAQUERYSET *qs = (WSAQUERYSET*) malloc( qs_len ); DWORD flags = LUP_FLUSHCACHE | LUP_RETURN_ALL; HANDLE h; int done = 0; PyObject *record = NULL; PyObject *toreturn = NULL; GUID uuid = { 0 }; char localAddressBuf[20] = { 0 }; if(!PyArg_ParseTuple(args,"ss", &addrstr, &uuidstr)) return 0; ZeroMemory( qs, qs_len ); qs->dwSize = sizeof(WSAQUERYSET); qs->dwNameSpace = NS_BTH; qs->dwNumberOfCsAddrs = 0; qs->lpszContext = (LPSTR) localAddressBuf; if( 0 == strcmp( addrstr, "localhost" ) ) { // find the Bluetooth address of the first local adapter. #if 0 HANDLE rhandle = NULL; BLUETOOTH_RADIO_INFO info; BLUETOOTH_FIND_RADIO_PARAMS p = { sizeof(p) }; HBLUETOOTH_RADIO_FIND fhandle = NULL; printf("looking for first radio\n"); fhandle = BluetoothFindFirstRadio(&p, &rhandle); _CHECK_OR_RAISE_WSA( NULL != fhandle ); printf("first radio: 0x%p\n", rhandle); _CHECK_OR_RAISE_WSA( \ TRUE == BluetoothFindRadioClose( fhandle ) ); printf("retrieving radio info on handle 0x%p\n", rhandle); info.dwSize = sizeof(info); // XXX why doesn't this work??? _CHECK_OR_RAISE_WSA( \ ERROR_SUCCESS != BluetoothGetRadioInfo( rhandle, &info ) ); ba2str( info.address.ullLong, localAddressBuf ); #else // bind a temporary socket and get its Bluetooth address SOCKADDR_BTH sa = { 0 }; int sa_len = sizeof(sa); int tmpfd = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); _CHECK_OR_RAISE_WSA( tmpfd >= 0 ); sa.addressFamily = AF_BTH; sa.port = BT_PORT_ANY; _CHECK_OR_RAISE_WSA(NO_ERROR == bind(tmpfd,(LPSOCKADDR)&sa,sa_len) ); _CHECK_OR_RAISE_WSA(NO_ERROR == getsockname(tmpfd, (LPSOCKADDR)&sa,\ &sa_len ) ); ba2str(sa.btAddr, localAddressBuf ); close(tmpfd); #endif flags |= LUP_RES_SERVICE; } else { strcpy( localAddressBuf, addrstr ); } if( strlen(uuidstr) != 36 || uuidstr[8] != '-' || uuidstr[13] != '-' || uuidstr[18] != '-' || uuidstr[23] != '-' ) { PyErr_SetString( PyExc_ValueError, "Invalid UUID!"); return 0; } str2uuid( uuidstr, &uuid ); qs->lpServiceClassId = &uuid; if( SOCKET_ERROR == WSALookupServiceBegin( qs, flags, &h )) { int err_code = WSAGetLastError(); if( WSASERVICE_NOT_FOUND == err_code ) { // this device does not advertise any services. return an // empty list free( qs ); return PyList_New(0); } else { // unexpected error. raise an exception Err_SetFromWSALastError( PyExc_IOError ); free(qs); return 0; } } toreturn = PyList_New(0); // iterate through the inquiry results while(! done) { if( NO_ERROR == WSALookupServiceNext( h, flags, &qs_len, qs )) { int proto; int port; PyObject *rawrecord = NULL; CSADDR_INFO *csinfo = NULL; record = PyDict_New(); // set host name dict_set_strings( record, "host", localAddressBuf ); // set service name dict_set_strings( record, "name", qs->lpszServiceInstanceName ); // set description dict_set_strings( record, "description", qs->lpszComment ); // set protocol and port csinfo = qs->lpcsaBuffer; if( csinfo != NULL ) { proto = csinfo->iProtocol; port = ((SOCKADDR_BTH*)csinfo->RemoteAddr.lpSockaddr)->port; dict_set_str_long(record, "port", port); if( proto == BTHPROTO_RFCOMM ) { dict_set_strings(record, "protocol", "RFCOMM"); } else if( proto == BTHPROTO_L2CAP ) { dict_set_strings(record, "protocol", "L2CAP"); } else { dict_set_strings(record, "protocol", "UNKNOWN"); dict_set_str_pyobj(record, "port", Py_None); } } else { dict_set_str_pyobj(record, "port", Py_None); dict_set_strings(record, "protocol", "UNKNOWN"); } // add the raw service record to be parsed in python rawrecord = PyString_FromStringAndSize( qs->lpBlob->pBlobData, qs->lpBlob->cbSize ); dict_set_str_pyobj(record, "rawrecord", rawrecord); Py_DECREF(rawrecord); PyList_Append( toreturn, record ); Py_DECREF( record ); } else { int error = WSAGetLastError(); if( error == WSAEFAULT ) { // the qs data structure is too small. allocate a bigger // buffer and try again. free( qs ); qs = (WSAQUERYSET*) malloc( qs_len ); } else if( error == WSA_E_NO_MORE ) { // no more results. done = 1; } else { // unexpected error. raise an exception. Err_SetFromWSALastError( PyExc_IOError ); Py_DECREF( toreturn ); return 0; } } } WSALookupServiceEnd( h ); free( qs ); return toreturn; } PyDoc_STRVAR(osxbt_find_service_doc, "TODO"); static PyObject * osxbt_set_service_raw(PyObject *self, PyObject *args) { int advertise = 0; WSAQUERYSET qs = { 0 }; WSAESETSERVICEOP op; char *record = NULL; int reclen = -1; BTH_SET_SERVICE *si = NULL; int silen = -1; ULONG sdpVersion = BTH_SDP_VERSION; BLOB blob = { 0 }; int status = -1; PyObject *result = NULL; HANDLE rh = 0; if(!PyArg_ParseTuple(args, "s#i|i", &record, &reclen, &advertise, &rh)) return 0; silen = sizeof(BTH_SET_SERVICE) + reclen - 1; si = (BTH_SET_SERVICE*) malloc(silen); ZeroMemory( si, silen ); si->pSdpVersion = &sdpVersion; si->pRecordHandle = &rh; si->fCodService = 0; si->Reserved; si->ulRecordLength = reclen; memcpy( si->pRecord, record, reclen ); op = advertise ? RNRSERVICE_REGISTER : RNRSERVICE_DELETE; qs.dwSize = sizeof(qs); qs.lpBlob = &blob; qs.dwNameSpace = NS_BTH; blob.cbSize = silen; blob.pBlobData = (BYTE*)si; status = WSASetService( &qs, op, 0 ); free( si ); if( SOCKET_ERROR == status ) { Err_SetFromWSALastError( PyExc_IOError ); return 0; } return PyInt_FromLong( (unsigned long) rh ); } PyDoc_STRVAR(osxbt_set_service_raw_doc, ""); static PyObject * osxbt_set_service(PyObject *self, PyObject *args) { int advertise = 0; WSAQUERYSET qs = { 0 }; WSAESETSERVICEOP op; SOCKADDR_BTH sa = { 0 }; int sa_len = sizeof(sa); char *service_name = NULL; char *service_desc = NULL; char *service_class_id_str = NULL; CSADDR_INFO sockInfo = { 0 }; GUID uuid = { 0 }; int sockfd; if(!PyArg_ParseTuple(args, "iisss", &sockfd, &advertise, &service_name, &service_desc, &service_class_id_str)) return 0; op = advertise ? RNRSERVICE_REGISTER : RNRSERVICE_DELETE; if( SOCKET_ERROR == getsockname( sockfd, (SOCKADDR*) &sa, &sa_len ) ) { Err_SetFromWSALastError( PyExc_IOError ); return 0; } sockInfo.iProtocol = BTHPROTO_RFCOMM; sockInfo.iSocketType = SOCK_STREAM; sockInfo.LocalAddr.lpSockaddr = (LPSOCKADDR) &sa; sockInfo.LocalAddr.iSockaddrLength = sizeof(sa); sockInfo.RemoteAddr.lpSockaddr = (LPSOCKADDR) &sa; sockInfo.RemoteAddr.iSockaddrLength = sizeof(sa); qs.dwSize = sizeof(qs); qs.dwNameSpace = NS_BTH; qs.lpcsaBuffer = &sockInfo; qs.lpszServiceInstanceName = service_name; qs.lpszComment = service_desc; str2uuid( service_class_id_str, &uuid ); qs.lpServiceClassId = (LPGUID) &uuid; qs.dwNumberOfCsAddrs = 1; if( SOCKET_ERROR == WSASetService( &qs, op, 0 ) ) { Err_SetFromWSALastError( PyExc_IOError ); return 0; } Py_INCREF( Py_None ); return Py_None; } PyDoc_STRVAR(osxbt_set_service_doc, ""); static PyObject * osxbt_setblocking(PyObject *self, PyObject *args) { int sockfd = -1; int block = -1; PyObject* blockingArg; if(!PyArg_ParseTuple(args, "iO", &sockfd, &blockingArg)) return 0; block = PyInt_AsLong(blockingArg); if (block == -1 && PyErr_Occurred()) return NULL; if (block) { block = 0; ioctlsocket( sockfd, FIONBIO, &block); } else { block = 1; ioctlsocket( sockfd, FIONBIO, &block); } Py_INCREF(Py_None); return Py_None; } PyDoc_STRVAR(osxbt_setblocking_doc, ""); static PyObject * osxbt_settimeout(PyObject *self, PyObject *args) { int sockfd = -1; double secondTimeout = -1; DWORD timeout = -1; int timeoutLen = sizeof(DWORD); if(!PyArg_ParseTuple(args, "id", &sockfd, &secondTimeout)) return 0; timeout = (DWORD) (secondTimeout * 1000); if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, timeoutLen) != 0) { Err_SetFromWSALastError( PyExc_IOError ); return 0; } if(setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, timeoutLen) != 0) { Err_SetFromWSALastError( PyExc_IOError ); return 0; } Py_INCREF(Py_None); return Py_None; } PyDoc_STRVAR(osxbt_settimeout_doc, ""); static PyObject * osxbt_gettimeout(PyObject *self, PyObject *args) { int sockfd = -1; DWORD recv_timeout = -1; int recv_timeoutLen = sizeof(DWORD); double timeout = -1; if(!PyArg_ParseTuple(args, "i", &sockfd)) return 0; if(getsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char*)&recv_timeout, &recv_timeoutLen) != 0) { Err_SetFromWSALastError( PyExc_IOError ); return 0; } timeout = (double)recv_timeout / 1000; return PyFloat_FromDouble(timeout); } PyDoc_STRVAR(osxbt_gettimeout_doc, ""); #endif typedef struct _discover_data { PyObject *results; IOBluetoothDeviceInquiryRef inquiry; } discover_data_t; static void timer_test (CFRunLoopTimerRef timer, void *info) { printf ("smack\n"); CFRunLoopRef runloop = CFRunLoopGetCurrent (); CFRunLoopStop (runloop); } static void on_inquiry_complete( void *user_data, IOBluetoothDeviceInquiryRef inquiryRef, IOReturn error, Boolean aborted ) { printf ("inquiry complete\n"); CFRunLoopRef runloop = CFRunLoopGetCurrent (); CFRunLoopStop (runloop); } static void * discover_thread (void *user_data) { printf ("discover thread!\n"); discover_data_t *dd = (discover_data_t*) user_data; dd->inquiry = IOBluetoothDeviceInquiryCreateWithCallbackRefCon (&dd); IOBluetoothDeviceInquirySetCompleteCallback (dd->inquiry, on_inquiry_complete); CFRunLoopRef runloop = CFRunLoopGetCurrent(); CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); CFRunLoopTimerRef timer = CFRunLoopTimerCreate (NULL, now, 20, 0, 0, timer_test, NULL); CFRunLoopAddTimer (runloop, timer, kCFRunLoopCommonModes); IOBluetoothDeviceInquiryStart (dd->inquiry); CFRunLoopRun (); IOBluetoothDeviceInquiryDelete (dd->inquiry); return NULL; } static PyObject * osxbt_discover_devices(PyObject *self, PyObject *args) { PyObject * toreturn = PyList_New(0); discover_data_t dd; dd.results = toreturn; pthread_t tid; pthread_create (&tid, NULL, discover_thread, &dd); void *thread_status = NULL; pthread_join (tid, &thread_status); return toreturn; } PyDoc_STRVAR(osxbt_discover_devices_doc, "TODO"); // ======================= ADMINISTRATIVE ========================= static PyMethodDef osxbt_methods[] = { // { "socket", (PyCFunction)osxbt_socket, METH_VARARGS, osxbt_socket_doc }, // { "bind", (PyCFunction)osxbt_bind, METH_VARARGS, osxbt_bind_doc }, // { "listen", (PyCFunction)osxbt_listen, METH_VARARGS, osxbt_listen_doc }, // { "accept", (PyCFunction)osxbt_accept, METH_VARARGS, osxbt_accept_doc }, // { "connect", (PyCFunction)osxbt_connect, METH_VARARGS, osxbt_connect_doc }, // { "send", (PyCFunction)osxbt_send, METH_VARARGS, osxbt_send_doc }, // { "recv", (PyCFunction)osxbt_recv, METH_VARARGS, osxbt_recv_doc }, // { "close", (PyCFunction)osxbt_close, METH_VARARGS, osxbt_close_doc }, // { "getsockname", (PyCFunction)osxbt_getsockname, METH_VARARGS, // osxbt_getsockname_doc }, // { "dup", (PyCFunction)osxbt_dup, METH_VARARGS, osxbt_dup_doc }, { "discover_devices", (PyCFunction)osxbt_discover_devices, METH_VARARGS, osxbt_discover_devices_doc }, // { "lookup_name", (PyCFunction)osxbt_lookup_name, METH_VARARGS, osxbt_lookup_name_doc }, // { "find_service", (PyCFunction)osxbt_find_service, METH_VARARGS, osxbt_find_service_doc }, // { "set_service", (PyCFunction)osxbt_set_service, METH_VARARGS, osxbt_set_service_doc }, // { "set_service_raw", (PyCFunction)osxbt_set_service_raw, METH_VARARGS, osxbt_set_service_raw_doc }, // { "setblocking", (PyCFunction)osxbt_setblocking, METH_VARARGS, osxbt_setblocking_doc }, // { "settimeout", (PyCFunction)osxbt_settimeout, METH_VARARGS, osxbt_settimeout_doc }, // { "gettimeout", (PyCFunction)osxbt_gettimeout, METH_VARARGS, osxbt_gettimeout_doc }, { NULL, NULL } }; PyDoc_STRVAR(osxbt_doc, "TODO\n"); PyMODINIT_FUNC init_osxbt(void) { PyObject *m; m = Py_InitModule3("_osxbt", osxbt_methods, osxbt_doc); //#define ADD_INT_CONSTANT(m,a) PyModule_AddIntConstant(m, #a, a) // // ADD_INT_CONSTANT(m, SOCK_STREAM); // ADD_INT_CONSTANT(m, BTHPROTO_RFCOMM); // ADD_INT_CONSTANT(m, BT_PORT_ANY); } PyBluez-0.18/PKG-INFO0000644000076400010400000000121011303332734015162 0ustar lukasAdministratorenMetadata-Version: 1.0 Name: PyBluez Version: 0.18 Summary: Bluetooth Python extension module Home-page: http://org.csail.mit.edu/pybluez Author: Albert Huang Author-email: ashuang@alum.mit.edu License: GPL Download-URL: http://org.csail.mit.edu/pybluez/download.html Description: Bluetooth Python extension module to allow Python developers to use system Bluetooth resources. PyBluez works with GNU/Linux and Windows XP. Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: License :: OSI Approved :: GNU General Public License (GPL) Classifier: Programming Language :: Python Classifier: Topic :: Communications PyBluez-0.18/README0000644000076400010400000000346011302237266014761 0ustar lukasAdministratorenPyBluez Python extension module allowing access to system Bluetooth resources. http://org.csail.mit.edu/pybluez BUILD REQUIREMENTS: GNU/Linux: - Python 2.3 or Python 2.4 - Python distutils (standard in most Python distros, separate package python-dev in Debian) - BlueZ libraries and header files Windows XP: - Microsoft Windows XP SP1 - Microsoft Visual Studio - Microsoft Windows Platform SDK - 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 # examples/simple/sdp-browse.py # examples/simple/rfcomm-server.py # examples/simple/rfcomm-client.py 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: Albert Huang 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.18/setup.py0000755000076400010400000000700211303331073015602 0ustar lukasAdministratoren#!/usr/bin/env python from distutils.core import setup, Extension from distutils.debug import DEBUG import sys import os mods = [] if sys.platform == 'win32': XP2_PSDK_PATH = os.path.join(os.getenv('ProgramFiles'), r"Microsoft Platform SDK for Windows XP SP2") S03_PSDK_PATH = os.path.join(os.getenv('ProgramFiles'), r"Microsoft Platform SDK") S08_PSDK_PATH = os.path.join(os.getenv('ProgramFiles'), r"Microsoft SDKs\\Windows\\v6.0A") PSDK_PATH = None for p in [ XP2_PSDK_PATH, S03_PSDK_PATH, S08_PSDK_PATH ]: if os.path.exists(p): PSDK_PATH = p break if PSDK_PATH is None: raise SystemExit ("Can't find the Windows XP Platform SDK") mod1 = Extension ('bluetooth._msbt', include_dirs = ["%s\\Include" % PSDK_PATH], library_dirs = ["%s\\Lib" % PSDK_PATH], libraries = [ "WS2_32", "Irprops" ], sources=['msbt\\_msbt.c'],) mods = [ mod1 ] # widcomm ? WC_BASE = os.path.join(os.getenv('ProgramFiles'), r"Widcomm\BTW DK\SDK") if os.path.exists (WC_BASE): mod2 = Extension ('bluetooth._widcomm', include_dirs = [ "%s\\Inc" % WC_BASE ], define_macros = [ ('_BTWLIB', None) ], library_dirs = [ "%s\\Release" % WC_BASE, "%s\\Lib" % PSDK_PATH, ], libraries = [ "WidcommSdklib", "ws2_32", "version", "user32", "Advapi32", "Winspool", "ole32", "oleaut32" ], sources = [ "widcomm\\_widcomm.cpp", "widcomm\\inquirer.cpp", "widcomm\\rfcommport.cpp", "widcomm\\rfcommif.cpp", "widcomm\\l2capconn.cpp", "widcomm\\l2capif.cpp", "widcomm\\sdpservice.cpp", "widcomm\\util.cpp" ] ) mods.append (mod2) elif sys.platform == 'linux2': mod1 = Extension('bluetooth._bluetooth', libraries = ['bluetooth'], sources = ['bluez/btmodule.c', 'bluez/btsdp.c']) mods = [ mod1 ] elif sys.platform == 'darwin': mod1 = Extension('bluetooth._osxbt', include_dirs = ["/System/Library/Frameworks/IOBluetooth.framework/Headers", "/System/Library/Frameworks/CoreFoundation.framework/Headers"], extra_link_args = ['-framework IOBluetooth -framework CoreFoundation'], sources = ['osx/_osxbt.c'] ) mods = [ mod1 ] setup ( name = 'PyBluez', version = '0.18', description = 'Bluetooth Python extension module', author="Albert Huang", author_email="ashuang@alum.mit.edu", url="http://org.csail.mit.edu/pybluez", ext_modules = mods, packages = [ "bluetooth" ], # for the python cheese shop classifiers = [ 'Development Status :: 4 - Beta', 'License :: OSI Approved :: GNU General Public License (GPL)', 'Programming Language :: Python', 'Topic :: Communications' ], download_url = 'http://org.csail.mit.edu/pybluez/download.html', long_description = 'Bluetooth Python extension module to allow Python developers to use system Bluetooth resources. PyBluez works with GNU/Linux and Windows XP.', maintainer = 'Albert Huang', maintainer_email = 'ashuang@alum.mit.edu', license = 'GPL', ) PyBluez-0.18/widcomm/0000755000076400010400000000000011303332711015525 5ustar lukasAdministratorenPyBluez-0.18/widcomm/inquirer.cpp0000644000076400010400000004112011302237264020073 0ustar lukasAdministratoren#include #include #include #include #include #include "util.h" #include "inquirer.hpp" static inline void dbg (const char *fmt, ...) { return; va_list ap; va_start (ap, fmt); vfprintf (stderr, fmt, ap); va_end (ap); } 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); } WCInquirer::WCInquirer (PyObject *wcinq) { this->wcinq = wcinq; this->serverfd = socket (AF_INET, SOCK_STREAM, 0); this->threadfd = socket (AF_INET, SOCK_STREAM, 0); int status = SOCKET_ERROR; struct sockaddr_in saddr = { 0, }; for (int i=0; i<10; i++) { this->sockport = 3000 + (unsigned short) (20000 * (rand () / (RAND_MAX + 1.0))); saddr.sin_family = AF_INET; saddr.sin_port = htons (this->sockport); saddr.sin_addr.s_addr = inet_addr ("127.0.0.1"); status = bind (this->serverfd, (struct sockaddr*) &saddr, sizeof (saddr)); if (0 == status) break; } assert (0 == status); // instruct server socket to accept one connection status = listen (this->serverfd, 1); // TODO error checking // // connect the client socket to the server socket // status = connect (this->threadfd, (struct sockaddr*) &saddr, // sizeof (saddr)); // // TODO error checking } WCInquirer::~WCInquirer () { closesocket (this->threadfd); } int WCInquirer::AcceptClient () { struct sockaddr_in useless; int useless_sz = sizeof (useless); this->threadfd = accept (this->serverfd, (struct sockaddr*)&useless, &useless_sz); if (this->threadfd >= 0) { // put sockets into nonblocking mode unsigned long nonblocking = 1; ioctlsocket (this->threadfd, FIONBIO, &nonblocking); closesocket (this->serverfd); return 0; } return -1; } #pragma pack(push) #pragma pack(1) typedef struct { int msg_type; unsigned char bda[6]; unsigned char devClass[3]; unsigned char bdName[248]; int bConnected; } device_responded_msg_t; void WCInquirer::OnDeviceResponded (BD_ADDR bda, DEV_CLASS devClass, BD_NAME bdName, BOOL bConnected) { dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); device_responded_msg_t msg; memset (&msg, 0, sizeof (msg)); msg.msg_type = DEVICE_RESPONDED; memcpy (msg.bda, bda, BD_ADDR_LEN); memcpy (msg.devClass, devClass, sizeof (devClass)); memcpy (msg.bdName, bdName, strlen ((char*)bdName)); msg.bConnected = bConnected; send (this->threadfd, reinterpret_cast (&msg), sizeof (msg), 0); } typedef struct { int msg_type; int success; short num_responses; } inquiry_complete_msg_t; void WCInquirer::OnInquiryComplete (BOOL success, short num_responses) { dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); inquiry_complete_msg_t msg; msg.msg_type = INQUIRY_COMPLETE; msg.success = success; msg.num_responses = num_responses; send (this->threadfd, reinterpret_cast (&msg), sizeof (msg), 0); } typedef struct { int msg_type; } discovery_complete_msg_t; void WCInquirer::OnDiscoveryComplete () { dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); discovery_complete_msg_t msg; msg.msg_type = DISCOVERY_COMPLETE; send (this->threadfd, reinterpret_cast (&msg), sizeof (msg), 0); } typedef struct { int msg_type; CBtIf::STACK_STATUS new_status; } stack_status_change_msg_t; void WCInquirer::OnStackStatusChange (STACK_STATUS new_status) { dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); stack_status_change_msg_t msg; msg.msg_type = STACK_STATUS_CHAGE; msg.new_status = new_status; send (this->threadfd, reinterpret_cast (&msg), sizeof (msg), 0); } #pragma pack(pop) // =================== typedef struct _WCInquirerPyObject WCInquirerPyObject; struct _WCInquirerPyObject { PyObject_HEAD WCInquirer *inq; int readfd; int writefd; }; PyDoc_STRVAR(wcinquirer_doc, "CBtIf wrapper"); extern PyTypeObject wcinquirer_type; static PyObject * get_sockport (PyObject *s) { WCInquirerPyObject *self = (WCInquirerPyObject*) s; return PyInt_FromLong (self->inq->GetSockPort ()); } static PyObject * accept_client (PyObject *s) { WCInquirerPyObject *self = (WCInquirerPyObject*) s; return PyInt_FromLong (self->inq->AcceptClient ()); } static PyObject * start_inquiry (PyObject *s) { WCInquirerPyObject *self = (WCInquirerPyObject*) s; if (self->inq->StartInquiry ()) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } static PyObject * start_discovery (PyObject *s, PyObject *args) { WCInquirerPyObject *self = (WCInquirerPyObject*) s; dbg ("%s:%d start_discovery\n", __FILE__, __LINE__); char *bdaddr_in = NULL; int bdaddr_in_len = 0; char *uuid_str = NULL; int uuid_str_len = 0; BD_ADDR bdaddr; if (!PyArg_ParseTuple (args, "s#|s#", &bdaddr_in, &bdaddr_in_len, &uuid_str, &uuid_str_len)) return 0; if (bdaddr_in_len != BD_ADDR_LEN) { PyErr_SetString (PyExc_ValueError, "invalid bdaddr"); return NULL; } memcpy (bdaddr, bdaddr_in, BD_ADDR_LEN); GUID uuid = { 0 }; GUID *puuid = NULL; if (uuid_str) { PyWidcomm::str2uuid (uuid_str, &uuid); puuid = &uuid; } BOOL result; Py_BEGIN_ALLOW_THREADS result = self->inq->StartDiscovery (bdaddr, puuid); Py_END_ALLOW_THREADS if (result) Py_RETURN_TRUE; else Py_RETURN_FALSE; } static PyObject * is_device_ready (PyObject *s) { WCInquirerPyObject *self = (WCInquirerPyObject*) s; dbg ("IsDeviceReady: %d\n", (self->inq->IsDeviceReady ())); if (self->inq->IsDeviceReady ()) Py_RETURN_TRUE; else Py_RETURN_FALSE; } static PyObject * is_stack_server_up (PyObject *s) { WCInquirerPyObject *self = (WCInquirerPyObject*) s; if (self->inq->IsStackServerUp ()) Py_RETURN_TRUE; else Py_RETURN_FALSE; } static PyObject * get_local_device_name (PyObject *s) { WCInquirerPyObject *self = (WCInquirerPyObject*) s; BD_NAME name; if (self->inq->GetLocalDeviceName (&name)) { return PyString_FromString ( (const char *)name); } else { Py_RETURN_NONE; } } static PyObject * get_local_device_version_info (PyObject *s) { WCInquirerPyObject *self = (WCInquirerPyObject*) s; Py_RETURN_NONE; // DEV_VER_INFO info; // BOOL success = self->inq->GetLocalDeviceVersionInfo (&info); // if (success) { // return Py_BuildValue ("s#BHBHH", // info.bd_addr, 6, // info.hci_version, // info.hci_revision, // info.lmp_version, // info.manufacturer, // info.lmp_sub_version); // } else { // Py_RETURN_NONE; // } } #define MAX_SDP_DISCOVERY_RECORDS 2000 static PyObject * read_discovery_records (PyObject *s, PyObject *args) { WCInquirerPyObject *self = (WCInquirerPyObject*) s; UINT8 *bdaddr_in = NULL; int bdaddr_in_len = 0; char *uuid_str = NULL; int uuid_str_len = 0; BD_ADDR bdaddr; if (!PyArg_ParseTuple (args, "s#|s#", &bdaddr_in, &bdaddr_in_len, &uuid_str, &uuid_str_len)) return 0; if (bdaddr_in_len != BD_ADDR_LEN) { PyErr_SetString (PyExc_ValueError, "invalid bdaddr"); return NULL; } memcpy (bdaddr, bdaddr_in, BD_ADDR_LEN); int nrecords = 0; CSdpDiscoveryRec *records = new CSdpDiscoveryRec[MAX_SDP_DISCOVERY_RECORDS]; if (uuid_str) { dbg ("filtering by uuid %s\n", uuid_str); GUID uuid = { 0 }; PyWidcomm::str2uuid (uuid_str, &uuid); nrecords = self->inq->ReadDiscoveryRecords (bdaddr, MAX_SDP_DISCOVERY_RECORDS, records, &uuid); } else { dbg ("no uuid specified.\n"); nrecords = self->inq->ReadDiscoveryRecords (bdaddr, MAX_SDP_DISCOVERY_RECORDS, records); dbg ("nrecords: %d\n", nrecords); } char bdaddr_str[18]; sprintf (bdaddr_str, "%02X:%02X:%02X:%02X:%02X:%02X", bdaddr_in[0], bdaddr_in[1], bdaddr_in[2], bdaddr_in[3], bdaddr_in[4], bdaddr_in[5]); PyObject *result = PyList_New (nrecords); for (int i=0; i 0 && desc.elem[0].type == ATTR_TYPE_ARRAY) { dict_set_strings (dict, "description", (char*)desc.elem[0].val.array); } else { dict_set_strings (dict, "description", ""); } dict_set_strings (dict, "provider", ""); PyObject *profiles_list = PyList_New (0); dict_set_str_pyobj (dict, "profiles", profiles_list); Py_DECREF (profiles_list); dict_set_strings (dict, "service-id", ""); // service class list PyObject *uuid_list = PyList_New (0); // SDP_DISC_ATTTR_VAL service_classes; // if (records[i].FindAttribute (0x0001, &service_classes)) { // // printf ("service-classes: %d\n", desc.num_elem); // for (int j=0; jinq->GetLocalDeviceInfo (); if (result) { return Py_BuildValue ("s", self->inq->m_BdName); } else { Py_RETURN_NONE; } } static PyObject * get_btw_version_info (PyObject *s) { WCInquirerPyObject *self = (WCInquirerPyObject*) s; char buf[MAX_PATH]; BOOL result = self->inq->GetBTWVersionInfo (buf, MAX_PATH); if (result) { return PyString_FromString (buf); } else { Py_RETURN_NONE; } } static PyMethodDef wcinquirer_methods[] = { { "get_sockport", (PyCFunction) get_sockport, METH_NOARGS, "" }, { "accept_client", (PyCFunction) accept_client, METH_NOARGS, "" }, { "start_inquiry", (PyCFunction)start_inquiry, METH_NOARGS, "" }, { "start_discovery", (PyCFunction)start_discovery, METH_VARARGS, "" }, { "is_device_ready", (PyCFunction)is_device_ready, METH_NOARGS, "" }, { "is_stack_server_up", (PyCFunction)is_stack_server_up, METH_NOARGS, "" }, { "get_local_device_name", (PyCFunction)get_local_device_name, METH_NOARGS, "" }, { "get_local_device_version_info", (PyCFunction)get_local_device_version_info, METH_NOARGS, ""}, { "read_discovery_records", (PyCFunction)read_discovery_records, METH_VARARGS, "" }, { "get_remote_device_info", (PyCFunction)get_remote_device_info, METH_VARARGS, "" }, { "get_next_remote_device_info", (PyCFunction)get_next_remote_device_info, METH_VARARGS, "" }, { "get_local_device_address", (PyCFunction)get_local_device_address, METH_NOARGS, "" }, { "get_btw_version_info", (PyCFunction)get_btw_version_info, METH_NOARGS, "" }, { NULL, NULL } }; static PyObject * wcinquirer_repr(WCInquirerPyObject *s) { return PyString_FromString("_WCInquirer object"); } static PyObject * wcinquirer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *newobj; newobj = type->tp_alloc(type, 0); if (newobj != NULL) { WCInquirerPyObject *self = (WCInquirerPyObject *)newobj; self->inq = NULL; } return newobj; } static void wcinquirer_dealloc(WCInquirerPyObject *self) { if (self->inq) { delete self->inq; self->inq = NULL; } self->ob_type->tp_free((PyObject*)self); } int wcinquirer_initobj(PyObject *s, PyObject *args, PyObject *kwds) { WCInquirerPyObject *self = (WCInquirerPyObject *)s; self->inq = new WCInquirer (s); return 0; } /* Type object for socket objects. */ PyTypeObject wcinquirer_type = { PyObject_HEAD_INIT(0) /* Must fill in type value later */ 0, /* ob_size */ "_widcomm._WCInquirer", /* tp_name */ sizeof(WCInquirerPyObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)wcinquirer_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)wcinquirer_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 */ wcinquirer_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ wcinquirer_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 */ wcinquirer_initobj, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ wcinquirer_new, /* tp_new */ PyObject_Del, /* tp_free */ }; PyBluez-0.18/widcomm/inquirer.hpp0000644000076400010400000000146011302237264020103 0ustar lukasAdministratoren#pragma once class WCInquirer : public CBtIf { public: enum { DEVICE_RESPONDED, INQUIRY_COMPLETE, DISCOVERY_COMPLETE, STACK_STATUS_CHAGE }; WCInquirer::WCInquirer (PyObject *wcinq); virtual ~WCInquirer (); int AcceptClient (); inline unsigned short GetSockPort () { return sockport; } private: void OnDeviceResponded (BD_ADDR bda, DEV_CLASS devClass, BD_NAME bdName, BOOL bConnected); void OnInquiryComplete (BOOL success, short num_responses); void OnDiscoveryComplete (); void OnStackStatusChange (STACK_STATUS new_status); PyObject * wcinq; SOCKET threadfd; SOCKET serverfd; unsigned short sockport; }; PyBluez-0.18/widcomm/l2capconn.cpp0000644000076400010400000002663211302237264020127 0ustar lukasAdministratoren#include #include #include #include #include #include "l2capconn.hpp" #include "l2capif.hpp" static inline void dbg (const char *fmt, ...) { return; va_list ap; va_start (ap, fmt); vfprintf (stderr, fmt, ap); va_end (ap); } WCL2CapConn::WCL2CapConn (PyObject *pyobj) : CL2CapConn () { this->pyobj = pyobj; this->serverfd = socket (AF_INET, SOCK_STREAM, 0); this->threadfd = socket (AF_INET, SOCK_STREAM, 0); int status = SOCKET_ERROR; struct sockaddr_in saddr = { 0, }; for (int i=0; i<10; i++) { this->sockport = 3000 + (unsigned short) (20000 * (rand () / (RAND_MAX + 1.0))); saddr.sin_family = AF_INET; saddr.sin_port = htons (this->sockport); saddr.sin_addr.s_addr = inet_addr ("127.0.0.1"); status = bind (this->serverfd, (struct sockaddr*) &saddr, sizeof (saddr)); if (0 == status) break; } assert (0 == status); // instruct server socket to accept one connection status = listen (this->serverfd, 1); } WCL2CapConn::~WCL2CapConn () { closesocket (this->threadfd); } int WCL2CapConn::AcceptClient () { dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); struct sockaddr_in useless; int useless_sz = sizeof (useless); this->threadfd = accept (this->serverfd, (struct sockaddr*)&useless, &useless_sz); if (this->threadfd >= 0) { // put sockets into nonblocking mode unsigned long nonblocking = 1; ioctlsocket (this->threadfd, FIONBIO, &nonblocking); closesocket (this->serverfd); return 0; } return -1; } #pragma pack(push) #pragma pack(1) typedef struct { int msg_type; int len; } data_received_t; void WCL2CapConn::OnDataReceived (void *p_data, UINT16 len) { dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); data_received_t msg; msg.msg_type = DATA_RECEIVED; msg.len = len; send (this->threadfd, reinterpret_cast (&msg), sizeof (msg), 0); send (this->threadfd, reinterpret_cast (p_data), len, 0); } void WCL2CapConn::OnIncomingConnection () { dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); int msg = INCOMING_CONNECTION; send (this->threadfd, reinterpret_cast (&msg), sizeof (msg), 0); } void WCL2CapConn::OnConnectPendingReceived () { dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); // TODO } void WCL2CapConn::OnConnected () { dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); int msg = CONNECTED; send (this->threadfd, reinterpret_cast (&msg), sizeof (msg), 0); } void WCL2CapConn::OnCongestionStatus (BOOL is_congested) { dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); // TODO } void WCL2CapConn::OnRemoteDisconnected (UINT16 reason) { dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); int msg = REMOTE_DISCONNECTED; send (this->threadfd, reinterpret_cast (&msg), sizeof (msg), 0); } #pragma pack(pop) // =================== typedef struct _WCL2CapConnPyObject WCL2CapConnPyObject; struct _WCL2CapConnPyObject { PyObject_HEAD WCL2CapConn *l2cap; }; PyDoc_STRVAR(wcl2capconn_doc, "CL2CapConn wrapper"); extern PyTypeObject wcl2capconn_type; static PyObject * get_sockport (PyObject *s) { WCL2CapConnPyObject *self = (WCL2CapConnPyObject*) s; return PyInt_FromLong (self->l2cap->GetSockPort ()); } static PyObject * accept_client (PyObject *s) { WCL2CapConnPyObject *self = (WCL2CapConnPyObject*) s; return PyInt_FromLong (self->l2cap->AcceptClient ()); } static PyObject * wc_listen (PyObject *s, PyObject *a) { WCL2CapConnPyObject *self = (WCL2CapConnPyObject*) s; dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); if (! PyObject_IsInstance (a, (PyObject*)&wcl2capif_type)) { return NULL; } WCL2CapIfPyObject *l2cap_if = (WCL2CapIfPyObject*) a; BOOL result; Py_BEGIN_ALLOW_THREADS; result = self->l2cap->Listen (l2cap_if->l2capif); Py_END_ALLOW_THREADS; dbg (" listen: %d\n", result); if (result) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } static PyObject * wc_accept (PyObject *s, PyObject *args) { WCL2CapConnPyObject *self = (WCL2CapConnPyObject*) s; dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); UINT16 desired_mtu = L2CAP_DEFAULT_MTU; if (!PyArg_ParseTuple (args, "|H", &desired_mtu)) return NULL; BOOL result; Py_BEGIN_ALLOW_THREADS; dbg (" calling accept (%p)\n", self->l2cap); result = self->l2cap->Accept (); dbg (" accept: %d\n", result); Py_END_ALLOW_THREADS; if (result) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } static PyObject * wc_connect (PyObject *s, PyObject *args) { WCL2CapConnPyObject *self = (WCL2CapConnPyObject*) s; WCL2CapIfPyObject *l2cap_if = NULL; char *bdaddr_in = NULL; int bdaddr_in_len; UINT16 desired_mtu = L2CAP_DEFAULT_MTU;; if(!PyArg_ParseTuple (args, "O!s#|H", &wcl2capif_type, &l2cap_if, &bdaddr_in, &bdaddr_in_len, &desired_mtu)) return NULL; if (bdaddr_in_len != BD_ADDR_LEN) { PyErr_SetString (PyExc_ValueError, "invalid bdaddr"); return NULL; } BD_ADDR bdaddr; memcpy (bdaddr, bdaddr_in, BD_ADDR_LEN); BOOL result; Py_BEGIN_ALLOW_THREADS; result = self->l2cap->Connect (l2cap_if->l2capif, bdaddr, desired_mtu); Py_END_ALLOW_THREADS; return PyInt_FromLong (result); } static PyObject * wc_disconnect (PyObject *s) { WCL2CapConnPyObject *self = (WCL2CapConnPyObject*) s; dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); Py_BEGIN_ALLOW_THREADS; self->l2cap->Disconnect (); Py_END_ALLOW_THREADS; Py_RETURN_NONE; } static PyObject * wc_remote_bd_addr (PyObject *s) { WCL2CapConnPyObject *self = (WCL2CapConnPyObject*) s; dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); tBT_CONN_STATS connstats; if (!self->l2cap->GetConnectionStats (&connstats)) { Py_RETURN_NONE; } if (!connstats.bIsConnected) Py_RETURN_NONE; return Py_BuildValue ("s#", &self->l2cap->m_RemoteBdAddr, BD_ADDR_LEN); } static PyObject * wc_write (PyObject *s, PyObject *args) { _WCL2CapConnPyObject *self = (_WCL2CapConnPyObject*) s; dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); char *data = NULL; int datalen; if (!PyArg_ParseTuple (args, "s#", &data, &datalen)) return NULL; UINT16 written = 0; BOOL result; Py_BEGIN_ALLOW_THREADS; result = self->l2cap->Write (data, datalen, &written); Py_END_ALLOW_THREADS; return Py_BuildValue ("II", result, written); } static PyObject * wc_get_connection_stats (PyObject *s) { _WCL2CapConnPyObject *self = (_WCL2CapConnPyObject*) s; dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); tBT_CONN_STATS stats; memset (&stats, 0, sizeof (stats)); BOOL result; Py_BEGIN_ALLOW_THREADS; result = self->l2cap->GetConnectionStats (&stats); Py_END_ALLOW_THREADS; return Py_BuildValue ("iIiIII", result, stats.bIsConnected, stats.Rssi, stats.BytesSent, stats.BytesRcvd, stats.Duration); } static PyObject * wc_switch_role (PyObject *s, PyObject *arg) { _WCL2CapConnPyObject *self = (_WCL2CapConnPyObject*) s; dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); MASTER_SLAVE_ROLE new_role = static_cast (PyInt_AsLong (arg)); BOOL result = self->l2cap->SwitchRole (new_role); return PyInt_FromLong (result); } static PyObject * wc_set_link_supervision_timeout (PyObject *s, PyObject *arg) { _WCL2CapConnPyObject *self = (_WCL2CapConnPyObject*) s; dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); UINT16 timeoutSlot = static_cast (PyInt_AsLong (arg)); BOOL result = self->l2cap->SetLinkSupervisionTimeOut (timeoutSlot); return PyInt_FromLong (result); } static PyMethodDef wcl2capconn_methods[] = { { "get_sockport", (PyCFunction) get_sockport, METH_NOARGS, "" }, { "accept_client", (PyCFunction) accept_client, METH_NOARGS, "" }, { "listen", (PyCFunction) wc_listen, METH_O, "" }, { "accept", (PyCFunction) wc_accept, METH_VARARGS, "" }, { "connect", (PyCFunction) wc_connect, METH_VARARGS, "" }, { "disconnect", (PyCFunction) wc_disconnect, METH_NOARGS, "" }, { "remote_bd_addr", (PyCFunction) wc_remote_bd_addr, METH_NOARGS, "" }, { "write", (PyCFunction)wc_write, METH_VARARGS, "" }, { "get_connection_stats", (PyCFunction)wc_get_connection_stats, METH_NOARGS, "" }, { "switch_role", (PyCFunction)wc_switch_role, METH_O, "" }, { "set_link_supervision_timeout", (PyCFunction)wc_set_link_supervision_timeout, METH_O, "" }, { NULL, NULL } }; static PyObject * wcl2capconn_repr(WCL2CapConnPyObject *s) { return PyString_FromString("_WCL2CapConn object"); } static PyObject * wcl2capconn_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *newobj; newobj = type->tp_alloc(type, 0); if (newobj != NULL) { WCL2CapConnPyObject *self = (WCL2CapConnPyObject *)newobj; self->l2cap = NULL; } return newobj; } static void wcl2capconn_dealloc(WCL2CapConnPyObject *self) { if (self->l2cap) { delete self->l2cap; self->l2cap = NULL; } self->ob_type->tp_free((PyObject*)self); } int wcl2capconn_initobj(PyObject *s, PyObject *args, PyObject *kwds) { WCL2CapConnPyObject *self = (WCL2CapConnPyObject *)s; self->l2cap = new WCL2CapConn (s); return 0; } /* Type object for socket objects. */ PyTypeObject wcl2capconn_type = { PyObject_HEAD_INIT(0) /* Must fill in type value later */ 0, /* ob_size */ "_widcomm._WCL2CapConn", /* tp_name */ sizeof(WCL2CapConnPyObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)wcl2capconn_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)wcl2capconn_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 */ wcl2capconn_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ wcl2capconn_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 */ wcl2capconn_initobj, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ wcl2capconn_new, /* tp_new */ PyObject_Del, /* tp_free */ }; PyBluez-0.18/widcomm/l2capconn.hpp0000644000076400010400000000145011302237264020123 0ustar lukasAdministratoren#pragma once class WCL2CapConn : public CL2CapConn { public: enum { DATA_RECEIVED, INCOMING_CONNECTION, REMOTE_DISCONNECTED, CONNECTED }; WCL2CapConn (PyObject *pyobj); virtual ~WCL2CapConn (); int AcceptClient (); inline unsigned short GetSockPort () { return sockport; } private: CL2CapIf rfcommif; void OnIncomingConnection (); void OnConnectPendingReceived (); void OnConnected (); void OnDataReceived (void *p_data, UINT16 len); void OnCongestionStatus (BOOL is_congested); void OnRemoteDisconnected (UINT16 reason); PyObject * pyobj; SOCKET threadfd; SOCKET serverfd; unsigned short sockport; }; PyBluez-0.18/widcomm/l2capif.cpp0000644000076400010400000001230711302237264017562 0ustar lukasAdministratoren#include #include #include #include #include #include #include "util.h" #include "l2capif.hpp" // =================== static inline void dbg (const char *fmt, ...) { return; va_list ap; va_start (ap, fmt); vfprintf (stderr, fmt, ap); va_end (ap); } PyDoc_STRVAR(wcl2capif_doc, "CL2CapIf wrapper"); static PyObject * assign_psm_value (PyObject *s, PyObject *args) { // dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); WCL2CapIfPyObject *self = (WCL2CapIfPyObject*) s; char *uuid_str = NULL; int uuid_str_len = 0; UINT16 psm = 0; char *service_name = _T(""); if(!PyArg_ParseTuple (args, "s#|H", &uuid_str, &uuid_str_len, &psm)) return NULL; GUID uuid = { 0 }; PyWidcomm::str2uuid (uuid_str, &uuid); BOOL result = self->l2capif->AssignPsmValue (&uuid, psm); dbg ("%s:%d:%s (%d)\n", __FILE__, __LINE__, __FUNCTION__, self->l2capif->GetPsm()); if (result) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } static PyObject * wc_register (PyObject *s) { WCL2CapIfPyObject *self = (WCL2CapIfPyObject*) s; return PyInt_FromLong (self->l2capif->Register ()); } static PyObject * wc_deregister (PyObject *s) { WCL2CapIfPyObject *self = (WCL2CapIfPyObject*) s; self->l2capif->Deregister (); Py_RETURN_NONE; } static PyObject * get_psm (PyObject *s) { WCL2CapIfPyObject *self = (WCL2CapIfPyObject*) s; return PyInt_FromLong (self->l2capif->GetPsm ()); } static PyObject * set_security_level (PyObject *s, PyObject *args) { char *service_name = NULL; UINT8 security_level = BTM_SEC_NONE; int is_server; if(!PyArg_ParseTuple (args, "sBi", &service_name, &security_level, &is_server)) return NULL; dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); WCL2CapIfPyObject *self = (WCL2CapIfPyObject*) s; BOOL result = self->l2capif->SetSecurityLevel (service_name, security_level, (BOOL) is_server); // dbg ("%s:%d:%s %d\n", __FILE__, __LINE__, __FUNCTION__, result); if (result) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } static PyMethodDef wcl2capif_methods[] = { { "assign_psm_value", (PyCFunction)assign_psm_value, METH_VARARGS, "" }, { "register", (PyCFunction)wc_register, METH_NOARGS, "" }, { "deregister", (PyCFunction)wc_deregister, METH_NOARGS, "" }, { "get_psm", (PyCFunction)get_psm, METH_NOARGS, "" }, { "set_security_level", (PyCFunction)set_security_level, METH_VARARGS, "" }, { NULL, NULL } }; static PyObject * wcl2capif_repr(WCL2CapIfPyObject *s) { return PyString_FromString("_WCL2CapIf object"); } static PyObject * wcl2capif_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *newobj; newobj = type->tp_alloc(type, 0); if (newobj != NULL) { WCL2CapIfPyObject *self = (WCL2CapIfPyObject *)newobj; self->l2capif = NULL; } return newobj; } static void wcl2capif_dealloc(WCL2CapIfPyObject *self) { if (self->l2capif) { delete self->l2capif; self->l2capif = NULL; } self->ob_type->tp_free((PyObject*)self); } int wcl2capif_initobj(PyObject *s, PyObject *args, PyObject *kwds) { WCL2CapIfPyObject *self = (WCL2CapIfPyObject *)s; self->l2capif = new CL2CapIf (); return 0; } /* Type object for socket objects. */ PyTypeObject wcl2capif_type = { PyObject_HEAD_INIT(0) /* Must fill in type value later */ 0, /* ob_size */ "_widcomm._WCL2CapIf", /* tp_name */ sizeof(WCL2CapIfPyObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)wcl2capif_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)wcl2capif_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 */ wcl2capif_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ wcl2capif_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 */ wcl2capif_initobj, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ wcl2capif_new, /* tp_new */ PyObject_Del, /* tp_free */ }; PyBluez-0.18/widcomm/l2capif.hpp0000644000076400010400000000026411302237264017566 0ustar lukasAdministratoren#pragma once typedef struct _WCL2CapIfPyObject WCL2CapIfPyObject; struct _WCL2CapIfPyObject { PyObject_HEAD CL2CapIf * l2capif; }; extern PyTypeObject wcl2capif_type; PyBluez-0.18/widcomm/rfcommif.cpp0000644000076400010400000001112511302237264020041 0ustar lukasAdministratoren#include #include #include #include #include #include #include "util.h" // =================== typedef struct _WCRfCommIfPyObject WCRfCommIfPyObject; struct _WCRfCommIfPyObject { PyObject_HEAD CRfCommIf * rfcommif; }; PyDoc_STRVAR(wcrfcommif_doc, "CRfCommIf wrapper"); extern PyTypeObject wcrfcommif_type; static PyObject * assign_scn_value (PyObject *s, PyObject *args) { WCRfCommIfPyObject *self = (WCRfCommIfPyObject*) s; char *uuid_str = NULL; int uuid_str_len = 0; UINT8 scn = 0; char *service_name = _T(""); if(!PyArg_ParseTuple (args, "s#|Bs", &uuid_str, &uuid_str_len, &scn, &service_name)) return NULL; GUID uuid = { 0 }; PyWidcomm::str2uuid (uuid_str, &uuid); // printf ("AssignScnValue\n"); BOOL result = self->rfcommif->AssignScnValue (&uuid, scn, service_name); if (result) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } static PyObject * get_scn (PyObject *s) { WCRfCommIfPyObject *self = (WCRfCommIfPyObject*) s; return PyInt_FromLong (self->rfcommif->GetScn ()); } static PyObject * set_security_level (PyObject *s, PyObject *args) { char *service_name = NULL; UINT8 security_level = BTM_SEC_NONE; int is_server; if(!PyArg_ParseTuple (args, "sBi", &service_name, &security_level, &is_server)) return NULL; WCRfCommIfPyObject *self = (WCRfCommIfPyObject*) s; BOOL result = self->rfcommif->SetSecurityLevel (service_name, security_level, (BOOL) is_server); if (result) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } static PyMethodDef wcrfcommif_methods[] = { { "assign_scn_value", (PyCFunction)assign_scn_value, METH_VARARGS, "" }, { "get_scn", (PyCFunction)get_scn, METH_NOARGS, "" }, { "set_security_level", (PyCFunction)set_security_level, METH_VARARGS, "" }, { NULL, NULL } }; static PyObject * wcrfcommif_repr(WCRfCommIfPyObject *s) { return PyString_FromString("_WCRfCommIf object"); } static PyObject * wcrfcommif_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *newobj; newobj = type->tp_alloc(type, 0); if (newobj != NULL) { WCRfCommIfPyObject *self = (WCRfCommIfPyObject *)newobj; self->rfcommif = NULL; } return newobj; } static void wcrfcommif_dealloc(WCRfCommIfPyObject *self) { if (self->rfcommif) { delete self->rfcommif; self->rfcommif = NULL; } self->ob_type->tp_free((PyObject*)self); } int wcrfcommif_initobj(PyObject *s, PyObject *args, PyObject *kwds) { WCRfCommIfPyObject *self = (WCRfCommIfPyObject *)s; self->rfcommif = new CRfCommIf (); return 0; } /* Type object for socket objects. */ PyTypeObject wcrfcommif_type = { PyObject_HEAD_INIT(0) /* Must fill in type value later */ 0, /* ob_size */ "_widcomm._WCRfCommIf", /* tp_name */ sizeof(WCRfCommIfPyObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)wcrfcommif_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)wcrfcommif_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 */ wcrfcommif_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ wcrfcommif_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 */ wcrfcommif_initobj, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ wcrfcommif_new, /* tp_new */ PyObject_Del, /* tp_free */ }; PyBluez-0.18/widcomm/rfcommport.cpp0000644000076400010400000002706011302237264020434 0ustar lukasAdministratoren#include #include #include #include #include #include "rfcommport.hpp" static inline void dbg (const char *fmt, ...) { return; va_list ap; va_start (ap, fmt); vfprintf (stderr, fmt, ap); va_end (ap); } WCRfCommPort::WCRfCommPort (PyObject *pyobj) : CRfCommPort () { this->pyobj = pyobj; this->serverfd = socket (AF_INET, SOCK_STREAM, 0); this->threadfd = socket (AF_INET, SOCK_STREAM, 0); int status = SOCKET_ERROR; struct sockaddr_in saddr = { 0, }; for (int i=0; i<10; i++) { this->sockport = 3000 + (unsigned short) (20000 * (rand () / (RAND_MAX + 1.0))); saddr.sin_family = AF_INET; saddr.sin_port = htons (this->sockport); saddr.sin_addr.s_addr = inet_addr ("127.0.0.1"); status = bind (this->serverfd, (struct sockaddr*) &saddr, sizeof (saddr)); if (0 == status) break; } assert (0 == status); // instruct server socket to accept one connection status = listen (this->serverfd, 1); } WCRfCommPort::~WCRfCommPort () { dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); closesocket (this->threadfd); } int WCRfCommPort::AcceptClient () { struct sockaddr_in useless; int useless_sz = sizeof (useless); this->threadfd = accept (this->serverfd, (struct sockaddr*)&useless, &useless_sz); if (this->threadfd >= 0) { // put sockets into nonblocking mode unsigned long nonblocking = 1; ioctlsocket (this->threadfd, FIONBIO, &nonblocking); closesocket (this->serverfd); return 0; } return -1; } #pragma pack(push) #pragma pack(1) typedef struct { int msg_type; int len; } data_received_t; void WCRfCommPort::OnDataReceived (void *p_data, UINT16 len) { dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); data_received_t msg; msg.msg_type = DATA_RECEIVED; msg.len = len; send (this->threadfd, reinterpret_cast (&msg), sizeof (msg), 0); send (this->threadfd, reinterpret_cast (p_data), len, 0); } typedef struct { int msg_type; unsigned int event_code; } event_received_msg_t; void WCRfCommPort::OnEventReceived (UINT32 event_code) { dbg ("%s:%d event %u received\n", __FILE__, __LINE__, event_code); event_received_msg_t msg; msg.msg_type = EVENT_RECEIVED; msg.event_code = event_code; send (this->threadfd, reinterpret_cast (&msg), sizeof (msg), 0); } #pragma pack(pop) // =================== typedef struct _WCRfCommPortPyObject WCRfCommPortPyObject; struct _WCRfCommPortPyObject { PyObject_HEAD WCRfCommPort *rfcp; }; PyDoc_STRVAR(wcrfcommport_doc, "CRfCommPort wrapper"); extern PyTypeObject wcrfcommport_type; static PyObject * get_sockport (PyObject *s) { WCRfCommPortPyObject *self = (WCRfCommPortPyObject*) s; return PyInt_FromLong (self->rfcp->GetSockPort ()); } static PyObject * accept_client (PyObject *s) { WCRfCommPortPyObject *self = (WCRfCommPortPyObject*) s; return PyInt_FromLong (self->rfcp->AcceptClient ()); } static PyObject * wc_open_server (PyObject *s, PyObject *args) { WCRfCommPortPyObject *self = (WCRfCommPortPyObject*) s; UINT8 scn; UINT16 desired_mtu = RFCOMM_DEFAULT_MTU; if (!PyArg_ParseTuple (args, "B|H", &scn, &desired_mtu)) return NULL; CRfCommPort::PORT_RETURN_CODE result = self->rfcp->OpenServer (scn, desired_mtu); return PyInt_FromLong (result); } static PyObject * wc_open_client (PyObject *s, PyObject *args) { UINT8 scn; char *bdaddr_in = NULL; int bdaddr_in_len; UINT16 desired_mtu = RFCOMM_DEFAULT_MTU; if(!PyArg_ParseTuple (args, "Bs#|H", &scn, &bdaddr_in, &bdaddr_in_len, &desired_mtu)) return NULL; if (bdaddr_in_len != BD_ADDR_LEN) { PyErr_SetString (PyExc_ValueError, "invalid bdaddr"); return NULL; } BD_ADDR bdaddr; memcpy (bdaddr, bdaddr_in, BD_ADDR_LEN); _WCRfCommPortPyObject *self = (_WCRfCommPortPyObject*) s; CRfCommPort::PORT_RETURN_CODE result; Py_BEGIN_ALLOW_THREADS; result = self->rfcp->OpenClient (scn, bdaddr, desired_mtu); Py_END_ALLOW_THREADS; return PyInt_FromLong (result); } static PyObject * wc_is_connected (PyObject *s) { _WCRfCommPortPyObject *self = (_WCRfCommPortPyObject*) s; BD_ADDR remote_addr; if (self->rfcp->IsConnected (&remote_addr)) { return Py_BuildValue ("s#", &remote_addr, BD_ADDR_LEN); } else { Py_RETURN_NONE; } } static PyObject * wc_close (PyObject *s) { dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); _WCRfCommPortPyObject *self = (_WCRfCommPortPyObject*) s; self->rfcp->Close (); Py_RETURN_NONE; } static PyObject * wc_set_flow_enabled (PyObject *s, PyObject *arg) { _WCRfCommPortPyObject *self = (_WCRfCommPortPyObject*) s; int enable = PyInt_AsLong (arg); CRfCommPort::PORT_RETURN_CODE result = self->rfcp->SetFlowEnabled (enable); return PyInt_FromLong (result); } static PyObject * wc_set_modem_signal (PyObject *s, PyObject *arg) { _WCRfCommPortPyObject *self = (_WCRfCommPortPyObject*) s; UINT8 signal = static_cast (PyInt_AsLong (arg)); CRfCommPort::PORT_RETURN_CODE result = self->rfcp->SetModemSignal (signal); return PyInt_FromLong (result); } static PyObject * wc_get_modem_status (PyObject *s) { _WCRfCommPortPyObject *self = (_WCRfCommPortPyObject*) s; UINT8 signal; CRfCommPort::PORT_RETURN_CODE result = self->rfcp->GetModemStatus (&signal); return Py_BuildValue ("ii", result, signal); } static PyObject * wc_send_error (PyObject *s, PyObject *arg) { _WCRfCommPortPyObject *self = (_WCRfCommPortPyObject*) s; UINT8 errors = static_cast (PyInt_AsLong (arg)); CRfCommPort::PORT_RETURN_CODE result = self->rfcp->SendError (errors); return PyInt_FromLong (result); } static PyObject * wc_purge (PyObject *s, PyObject *arg) { _WCRfCommPortPyObject *self = (_WCRfCommPortPyObject*) s; UINT8 purge_flags = static_cast (PyInt_AsLong (arg)); CRfCommPort::PORT_RETURN_CODE result = self->rfcp->Purge (purge_flags); return PyInt_FromLong (result); } static PyObject * wc_write (PyObject *s, PyObject *args) { _WCRfCommPortPyObject *self = (_WCRfCommPortPyObject*) s; char *data = NULL; int datalen; if (!PyArg_ParseTuple (args, "s#", &data, &datalen)) return NULL; UINT16 written = 0; CRfCommPort::PORT_RETURN_CODE status; Py_BEGIN_ALLOW_THREADS; status = self->rfcp->Write (data, datalen, &written); Py_END_ALLOW_THREADS; return Py_BuildValue ("II", status, written); } static PyObject * wc_get_connection_stats (PyObject *s) { _WCRfCommPortPyObject *self = (_WCRfCommPortPyObject*) s; tBT_CONN_STATS stats; memset (&stats, 0, sizeof (stats)); CRfCommPort::PORT_RETURN_CODE result = self->rfcp->GetConnectionStats (&stats); return Py_BuildValue ("iIiIII", result, stats.bIsConnected, stats.Rssi, stats.BytesSent, stats.BytesRcvd, stats.Duration); } static PyObject * wc_switch_role (PyObject *s, PyObject *arg) { _WCRfCommPortPyObject *self = (_WCRfCommPortPyObject*) s; MASTER_SLAVE_ROLE new_role = static_cast (PyInt_AsLong (arg)); BOOL result = self->rfcp->SwitchRole (new_role); return PyInt_FromLong (result); } static PyObject * wc_set_link_supervision_timeout (PyObject *s, PyObject *arg) { _WCRfCommPortPyObject *self = (_WCRfCommPortPyObject*) s; UINT16 timeoutSlot = static_cast (PyInt_AsLong (arg)); CRfCommPort::PORT_RETURN_CODE result = self->rfcp->SetLinkSupervisionTimeOut (timeoutSlot); return PyInt_FromLong (result); } static PyMethodDef wcrfcommport_methods[] = { { "get_sockport", (PyCFunction) get_sockport, METH_NOARGS, "" }, { "accept_client", (PyCFunction) accept_client, METH_NOARGS, "" }, { "open_server", (PyCFunction)wc_open_server, METH_VARARGS, "" }, { "open_client", (PyCFunction)wc_open_client, METH_VARARGS, "" }, { "close", (PyCFunction)wc_close, METH_NOARGS, "" }, { "is_connected", (PyCFunction)wc_is_connected, METH_NOARGS, "" }, { "set_flow_enabled", (PyCFunction)wc_set_flow_enabled, METH_O, "" }, { "set_modem_signal", (PyCFunction)wc_set_modem_signal, METH_O, "" }, { "get_modem_status", (PyCFunction)wc_get_modem_status, METH_NOARGS, "" }, { "send_error", (PyCFunction)wc_send_error, METH_O, "" }, { "purge", (PyCFunction)wc_purge, METH_O, "" }, { "write", (PyCFunction)wc_write, METH_VARARGS, "" }, { "get_connection_stats", (PyCFunction)wc_get_connection_stats, METH_NOARGS, "" }, { "switch_role", (PyCFunction)wc_switch_role, METH_O, "" }, { "set_link_supervision_timeout", (PyCFunction)wc_set_link_supervision_timeout, METH_O, "" }, { NULL, NULL } }; static PyObject * wcrfcommport_repr(WCRfCommPortPyObject *s) { return PyString_FromString("_WCRfCommPort object"); } static PyObject * wcrfcommport_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *newobj; newobj = type->tp_alloc(type, 0); if (newobj != NULL) { WCRfCommPortPyObject *self = (WCRfCommPortPyObject *)newobj; self->rfcp = NULL; } return newobj; } static void wcrfcommport_dealloc(WCRfCommPortPyObject *self) { dbg ("%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); if (self->rfcp) { delete self->rfcp; self->rfcp = NULL; } self->ob_type->tp_free((PyObject*)self); } int wcrfcommport_initobj(PyObject *s, PyObject *args, PyObject *kwds) { WCRfCommPortPyObject *self = (WCRfCommPortPyObject *)s; self->rfcp = new WCRfCommPort (s); return 0; } /* Type object for socket objects. */ PyTypeObject wcrfcommport_type = { PyObject_HEAD_INIT(0) /* Must fill in type value later */ 0, /* ob_size */ "_widcomm._WCRfCommPort", /* tp_name */ sizeof(WCRfCommPortPyObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)wcrfcommport_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)wcrfcommport_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 */ wcrfcommport_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ wcrfcommport_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 */ wcrfcommport_initobj, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ wcrfcommport_new, /* tp_new */ PyObject_Del, /* tp_free */ }; PyBluez-0.18/widcomm/rfcommport.hpp0000644000076400010400000000111511302237264020432 0ustar lukasAdministratoren#pragma once class WCRfCommPort : public CRfCommPort { public: enum { DATA_RECEIVED, EVENT_RECEIVED }; WCRfCommPort (PyObject *pyobj); virtual ~WCRfCommPort (); int AcceptClient (); inline unsigned short GetSockPort () { return sockport; } private: CRfCommIf rfcommif; void OnDataReceived (void *p_data, UINT16 len); void OnEventReceived (UINT32 event_code); PyObject * pyobj; SOCKET threadfd; SOCKET serverfd; unsigned short sockport; }; PyBluez-0.18/widcomm/sdpservice.cpp0000644000076400010400000001501311302237264020406 0ustar lukasAdministratoren#include #include #include #include #include #include "util.h" // =================== typedef struct _WCSdpServicePyObject WCSdpServicePyObject; struct _WCSdpServicePyObject { PyObject_HEAD CSdpService * sdpservice; }; PyDoc_STRVAR(wcsdpservice_doc, "CSdpService wrapper"); extern PyTypeObject wcsdpservice_type; static PyObject * add_service_class_id_list (WCSdpServicePyObject *self, PyObject *arg) { int nuids = PySequence_Size (arg); if (nuids < 0) { return NULL; } GUID *uuids = (GUID*) malloc (nuids * sizeof (GUID)); for (int i=0; isdpservice->AddServiceClassIdList (nuids, uuids); free (uuids); return PyInt_FromLong (result); fail: free (uuids); return NULL; } static PyObject * add_profile_descriptor_list (WCSdpServicePyObject *self, PyObject *args) { char *uuid_str = NULL; int uuid_str_len = 0; UINT16 version = 0; GUID uuid; if (!PyArg_ParseTuple (args, "s#H", &uuid_str, &uuid_str_len, &version)) return NULL; PyWidcomm::str2uuid (uuid_str, &uuid); SDP_RETURN_CODE result = self->sdpservice->AddProfileDescriptorList (&uuid, version); return PyInt_FromLong (result); } static PyObject * add_service_name (WCSdpServicePyObject *self, PyObject *arg) { char *name = PyString_AsString (arg); if (!name) return NULL; SDP_RETURN_CODE result = self->sdpservice->AddServiceName (name); return PyInt_FromLong (result); } static PyObject * add_rfcomm_protocol_descriptor (WCSdpServicePyObject *self, PyObject *arg) { int port = PyInt_AsLong (arg); if (PyErr_Occurred ()) return NULL; UINT8 scn = static_cast (port); SDP_RETURN_CODE result = self->sdpservice->AddRFCommProtocolDescriptor (scn); return PyInt_FromLong (result); } static PyObject * add_l2cap_protocol_descriptor (WCSdpServicePyObject *self, PyObject *arg) { int port = PyInt_AsLong (arg); if (PyErr_Occurred ()) return NULL; UINT16 psm = static_cast (port); SDP_RETURN_CODE result = self->sdpservice->AddL2CapProtocolDescriptor (psm); return PyInt_FromLong (result); } static PyObject * make_public_browseable (WCSdpServicePyObject *self) { SDP_RETURN_CODE result = self->sdpservice->MakePublicBrowseable (); return PyInt_FromLong (result); } static PyObject * set_availability (WCSdpServicePyObject *self, PyObject *arg) { UINT8 available = static_cast (PyInt_AsLong (arg)); if (PyErr_Occurred ()) return NULL; SDP_RETURN_CODE result = self->sdpservice->SetAvailability (available); return PyInt_FromLong (result); } static PyMethodDef wcsdpservice_methods[] = { { "add_service_class_id_list", (PyCFunction)add_service_class_id_list, METH_O, "" }, { "add_profile_descriptor_list", (PyCFunction)add_profile_descriptor_list, METH_VARARGS, "" }, { "add_service_name", (PyCFunction)add_service_name, METH_O, "" }, { "add_rfcomm_protocol_descriptor", (PyCFunction)add_rfcomm_protocol_descriptor, METH_O, "" }, { "add_l2cap_protocol_descriptor", (PyCFunction)add_l2cap_protocol_descriptor, METH_O, "" }, { "make_public_browseable", (PyCFunction)make_public_browseable, METH_NOARGS, "" }, { "set_availability", (PyCFunction)set_availability, METH_O, "" }, { NULL, NULL } }; static PyObject * wcsdpservice_repr(WCSdpServicePyObject *s) { return PyString_FromString("_WCSdpService object"); } static PyObject * wcsdpservice_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *newobj; newobj = type->tp_alloc(type, 0); if (newobj != NULL) { WCSdpServicePyObject *self = (WCSdpServicePyObject *)newobj; self->sdpservice = NULL; } return newobj; } static void wcsdpservice_dealloc(WCSdpServicePyObject *self) { if (self->sdpservice) { delete self->sdpservice; self->sdpservice = NULL; } self->ob_type->tp_free((PyObject*)self); } int wcsdpservice_initobj(PyObject *s, PyObject *args, PyObject *kwds) { WCSdpServicePyObject *self = (WCSdpServicePyObject *)s; self->sdpservice = new CSdpService (); return 0; } /* Type object for socket objects. */ PyTypeObject wcsdpservice_type = { PyObject_HEAD_INIT(0) /* Must fill in type value later */ 0, /* ob_size */ "_widcomm._WCSdpService", /* tp_name */ sizeof(WCSdpServicePyObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)wcsdpservice_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)wcsdpservice_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 */ wcsdpservice_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ wcsdpservice_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 */ wcsdpservice_initobj, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ wcsdpservice_new, /* tp_new */ PyObject_Del, /* tp_free */ }; PyBluez-0.18/widcomm/util.cpp0000644000076400010400000000151211302237264017213 0ustar lukasAdministratoren#include #include "util.h" namespace PyWidcomm { int str2uuid( const char *uuid_str, GUID *uuid) { // Parse uuid128 standard format: 12345678-9012-3456-7890-123456789012 int i; char buf[20] = { 0 }; strncpy(buf, uuid_str, 8); uuid->Data1 = strtoul( buf, NULL, 16 ); memset(buf, 0, sizeof(buf)); strncpy(buf, uuid_str+9, 4); uuid->Data2 = (unsigned short) strtoul( buf, NULL, 16 ); memset(buf, 0, sizeof(buf)); strncpy(buf, uuid_str+14, 4); uuid->Data3 = (unsigned short) strtoul( buf, NULL, 16 ); memset(buf, 0, sizeof(buf)); strncpy(buf, uuid_str+19, 4); strncpy(buf+4, uuid_str+24, 12); for( i=0; i<8; i++ ) { char buf2[3] = { buf[2*i], buf[2*i+1], 0 }; uuid->Data4[i] = (unsigned char)strtoul( buf2, NULL, 16 ); } return 0; } } PyBluez-0.18/widcomm/util.h0000644000076400010400000000016011302237264016656 0ustar lukasAdministratoren#pragma once #include namespace PyWidcomm { int str2uuid( const char *uuid_str, GUID *uuid); }; PyBluez-0.18/widcomm/_widcomm.cpp0000644000076400010400000001247111302237264020042 0ustar lukasAdministratoren#include #ifndef _BTWLIB #error "_BTWLIB is not defined" #endif #include #include #include #include #include "inquirer.hpp" #include "rfcommport.hpp" #include "l2capconn.hpp" extern PyTypeObject wcinquirer_type; extern PyTypeObject wcrfcommport_type; extern PyTypeObject wcrfcommif_type; extern PyTypeObject wcl2capif_type; extern PyTypeObject wcl2capconn_type; extern PyTypeObject wcsdpservice_type; static PyMethodDef widcomm_methods[] = { { NULL, NULL } }; extern "C" { PyMODINIT_FUNC init_widcomm(void) { PyObject *m; wcinquirer_type.ob_type = &PyType_Type; wcrfcommport_type.ob_type = &PyType_Type; wcrfcommif_type.ob_type = &PyType_Type; wcl2capif_type.ob_type = &PyType_Type; wcl2capconn_type.ob_type = &PyType_Type; wcsdpservice_type.ob_type = &PyType_Type; m = Py_InitModule("_widcomm", widcomm_methods); // inquirer Py_INCREF((PyObject *)&wcinquirer_type); if (PyModule_AddObject(m, "_WCInquirer", (PyObject *)&wcinquirer_type) != 0) { return; } // rfcomm port Py_INCREF((PyObject *)&wcrfcommport_type); if (PyModule_AddObject(m, "_WCRfCommPort", (PyObject *)&wcrfcommport_type) != 0) { return; } // rfcomm if Py_INCREF((PyObject *)&wcrfcommif_type); if (PyModule_AddObject(m, "_WCRfCommIf", (PyObject *)&wcrfcommif_type) != 0) { return; } // l2cap if Py_INCREF((PyObject *)&wcl2capif_type); if (PyModule_AddObject(m, "_WCL2CapIf", (PyObject *)&wcl2capif_type) != 0) { return; } // l2cap conn Py_INCREF((PyObject *)&wcl2capconn_type); if (PyModule_AddObject(m, "_WCL2CapConn", (PyObject *)&wcl2capconn_type) != 0) { return; } // sdp service advertisement Py_INCREF((PyObject *)&wcsdpservice_type); if (PyModule_AddObject(m, "_WCSdpService", (PyObject *)&wcsdpservice_type) != 0) { return; } #define ADD_INT_CONST(m, a) PyModule_AddIntConstant(m, #a, a) ADD_INT_CONST(m, RFCOMM_DEFAULT_MTU); // CRfCommPort::PORT_RETURN_CODE enum PyModule_AddIntConstant(m, "RFCOMM_SUCCESS", CRfCommPort::SUCCESS); PyModule_AddIntConstant(m, "RFCOMM_ALREADY_OPENED", CRfCommPort::ALREADY_OPENED); PyModule_AddIntConstant(m, "RFCOMM_NOT_OPENED", CRfCommPort::NOT_OPENED); PyModule_AddIntConstant(m, "RFCOMM_HANDLE_ERROR", CRfCommPort::HANDLE_ERROR); PyModule_AddIntConstant(m, "RFCOMM_LINE_ERR", CRfCommPort::LINE_ERR); PyModule_AddIntConstant(m, "RFCOMM_START_FAILED", CRfCommPort::START_FAILED); PyModule_AddIntConstant(m, "RFCOMM_PAR_NEG_FAILED", CRfCommPort::PAR_NEG_FAILED); PyModule_AddIntConstant(m, "RFCOMM_PORT_NEG_FAILED", CRfCommPort::PORT_NEG_FAILED); PyModule_AddIntConstant(m, "RFCOMM_PEER_CONNECTION_FAILED", CRfCommPort::PEER_CONNECTION_FAILED); PyModule_AddIntConstant(m, "RFCOMM_PEER_TIMEOUT", CRfCommPort::PEER_TIMEOUT); PyModule_AddIntConstant(m, "RFCOMM_INVALID_PARAMETER", CRfCommPort::INVALID_PARAMETER); PyModule_AddIntConstant(m, "RFCOMM_UNKNOWN_ERROR", CRfCommPort::UNKNOWN_ERROR); ADD_INT_CONST (m, PORT_EV_RXFLAG); ADD_INT_CONST (m, PORT_EV_TXEMPTY); ADD_INT_CONST (m, PORT_EV_CTS); ADD_INT_CONST (m, PORT_EV_DSR); ADD_INT_CONST (m, PORT_EV_RLSD); ADD_INT_CONST (m, PORT_EV_BREAK); ADD_INT_CONST (m, PORT_EV_ERR); ADD_INT_CONST (m, PORT_EV_RING); ADD_INT_CONST (m, PORT_EV_CTSS); ADD_INT_CONST (m, PORT_EV_DSRS); ADD_INT_CONST (m, PORT_EV_RLSDS); ADD_INT_CONST (m, PORT_EV_OVERRUN); ADD_INT_CONST (m, PORT_EV_TXCHAR); ADD_INT_CONST (m, PORT_EV_CONNECTED); ADD_INT_CONST (m, PORT_EV_CONNECT_ERR); ADD_INT_CONST (m, PORT_EV_FC); ADD_INT_CONST (m, PORT_EV_FCS); ADD_INT_CONST (m, BTM_SEC_NONE); ADD_INT_CONST (m, BTM_SEC_IN_AUTHORIZE); ADD_INT_CONST (m, BTM_SEC_IN_AUTHENTICATE); ADD_INT_CONST (m, BTM_SEC_IN_ENCRYPT); ADD_INT_CONST (m, BTM_SEC_OUT_AUTHORIZE); ADD_INT_CONST (m, BTM_SEC_OUT_AUTHENTICATE); ADD_INT_CONST (m, BTM_SEC_OUT_ENCRYPT); ADD_INT_CONST (m, BTM_SEC_BOND); PyModule_AddIntConstant(m, "INQ_DEVICE_RESPONDED", WCInquirer::DEVICE_RESPONDED); PyModule_AddIntConstant(m, "INQ_INQUIRY_COMPLETE", WCInquirer::INQUIRY_COMPLETE); PyModule_AddIntConstant(m, "INQ_DISCOVERY_COMPLETE", WCInquirer::DISCOVERY_COMPLETE); PyModule_AddIntConstant(m, "INQ_STACK_STATUS_CHANGE", WCInquirer::STACK_STATUS_CHAGE); PyModule_AddIntConstant(m, "RFCOMM_DATA_RECEIVED", WCRfCommPort::DATA_RECEIVED); PyModule_AddIntConstant(m, "RFCOMM_EVENT_RECEIVED", WCRfCommPort::EVENT_RECEIVED); PyModule_AddIntConstant(m, "L2CAP_DATA_RECEIVED", WCL2CapConn::DATA_RECEIVED); PyModule_AddIntConstant(m, "L2CAP_INCOMING_CONNECTION", WCL2CapConn::INCOMING_CONNECTION); PyModule_AddIntConstant(m, "L2CAP_REMOTE_DISCONNECTED", WCL2CapConn::REMOTE_DISCONNECTED); PyModule_AddIntConstant(m, "L2CAP_CONNECTED", WCL2CapConn::CONNECTED); ADD_INT_CONST (m, SDP_OK); ADD_INT_CONST (m, SDP_COULD_NOT_ADD_RECORD); ADD_INT_CONST (m, SDP_INVALID_RECORD); ADD_INT_CONST (m, SDP_INVALID_PARAMETERS); } } // extern "C"