Blame test/test-hfp

Packit Service 8264ee
#!/usr/bin/python
Packit Service 8264ee
Packit Service 8264ee
from __future__ import absolute_import, print_function, unicode_literals
Packit Service 8264ee
Packit Service 8264ee
from optparse import OptionParser, make_option
Packit Service 8264ee
import os
Packit Service 8264ee
from socket import SOCK_SEQPACKET, socket
Packit Service 8264ee
import sys
Packit Service 8264ee
import dbus
Packit Service 8264ee
import dbus.service
Packit Service 8264ee
import dbus.mainloop.glib
Packit Service 8264ee
import glib
Packit Service 8264ee
try:
Packit Service 8264ee
  from gi.repository import GObject
Packit Service 8264ee
except ImportError:
Packit Service 8264ee
  import gobject as GObject
Packit Service 8264ee
Packit Service 8264ee
mainloop = None
Packit Service 8264ee
audio_supported = True
Packit Service 8264ee
Packit Service 8264ee
try:
Packit Service 8264ee
	from socket import AF_BLUETOOTH, BTPROTO_SCO
Packit Service 8264ee
except:
Packit Service 8264ee
	print("WARNING: python compiled without Bluetooth support"
Packit Service 8264ee
					" - audio will not be available")
Packit Service 8264ee
	audio_supported = False
Packit Service 8264ee
Packit Service 8264ee
BUF_SIZE = 1024
Packit Service 8264ee
Packit Service 8264ee
BDADDR_ANY = '00:00:00:00:00:00'
Packit Service 8264ee
Packit Service 8264ee
HF_NREC			= 0x0001
Packit Service 8264ee
HF_3WAY			= 0x0002
Packit Service 8264ee
HF_CLI			= 0x0004
Packit Service 8264ee
HF_VOICE_RECOGNITION	= 0x0008
Packit Service 8264ee
HF_REMOTE_VOL		= 0x0010
Packit Service 8264ee
HF_ENHANCED_STATUS	= 0x0020
Packit Service 8264ee
HF_ENHANCED_CONTROL	= 0x0040
Packit Service 8264ee
HF_CODEC_NEGOTIATION	= 0x0080
Packit Service 8264ee
Packit Service 8264ee
AG_3WAY			= 0x0001
Packit Service 8264ee
AG_NREC			= 0x0002
Packit Service 8264ee
AG_VOICE_RECOGNITION	= 0x0004
Packit Service 8264ee
AG_INBAND_RING		= 0x0008
Packit Service 8264ee
AG_VOICE_TAG		= 0x0010
Packit Service 8264ee
AG_REJECT_CALL		= 0x0020
Packit Service 8264ee
AG_ENHANCED_STATUS	= 0x0040
Packit Service 8264ee
AG_ENHANCED_CONTROL	= 0x0080
Packit Service 8264ee
AG_EXTENDED_RESULT	= 0x0100
Packit Service 8264ee
AG_CODEC_NEGOTIATION	= 0x0200
Packit Service 8264ee
Packit Service 8264ee
HF_FEATURES = (HF_3WAY | HF_CLI | HF_VOICE_RECOGNITION |
Packit Service 8264ee
			HF_REMOTE_VOL | HF_ENHANCED_STATUS |
Packit Service 8264ee
			HF_ENHANCED_CONTROL | HF_CODEC_NEGOTIATION)
Packit Service 8264ee
Packit Service 8264ee
AVAIL_CODECS = "1,2"
Packit Service 8264ee
Packit Service 8264ee
class HfpConnection:
Packit Service 8264ee
	slc_complete = False
Packit Service 8264ee
	fd = None
Packit Service 8264ee
	io_id = 0
Packit Service 8264ee
	version = 0
Packit Service 8264ee
	features = 0
Packit Service 8264ee
	pending = None
Packit Service 8264ee
Packit Service 8264ee
	def disconnect(self):
Packit Service 8264ee
		if (self.fd >= 0):
Packit Service 8264ee
			os.close(self.fd)
Packit Service 8264ee
			self.fd = -1
Packit Service 8264ee
			glib.source_remove(self.io_id)
Packit Service 8264ee
			self.io_id = 0
Packit Service 8264ee
Packit Service 8264ee
	def slc_completed(self):
Packit Service 8264ee
		print("SLC establisment complete")
Packit Service 8264ee
		self.slc_complete = True
Packit Service 8264ee
Packit Service 8264ee
	def slc_next_cmd(self, cmd):
Packit Service 8264ee
		if not cmd:
Packit Service 8264ee
			self.send_cmd("AT+BRSF=%u" % (HF_FEATURES))
Packit Service 8264ee
		elif (cmd.startswith("AT+BRSF")):
Packit Service 8264ee
			if (self.features & AG_CODEC_NEGOTIATION and
Packit Service 8264ee
					HF_FEATURES & HF_CODEC_NEGOTIATION):
Packit Service 8264ee
				self.send_cmd("AT+BAC=%s" % (AVAIL_CODECS))
Packit Service 8264ee
			else:
Packit Service 8264ee
				self.send_cmd("AT+CIND=?")
Packit Service 8264ee
		elif (cmd.startswith("AT+BAC")):
Packit Service 8264ee
			self.send_cmd("AT+CIND=?")
Packit Service 8264ee
		elif (cmd.startswith("AT+CIND=?")):
Packit Service 8264ee
			self.send_cmd("AT+CIND?")
Packit Service 8264ee
		elif (cmd.startswith("AT+CIND?")):
Packit Service 8264ee
			self.send_cmd("AT+CMER=3,0,0,1")
Packit Service 8264ee
		elif (cmd.startswith("AT+CMER=")):
Packit Service 8264ee
			if (HF_FEATURES & HF_3WAY and self.features & AG_3WAY):
Packit Service 8264ee
				self.send_cmd("AT+CHLD=?")
Packit Service 8264ee
			else:
Packit Service 8264ee
				self.slc_completed()
Packit Service 8264ee
		elif (cmd.startswith("AT+CHLD=?")):
Packit Service 8264ee
			self.slc_completed()
Packit Service 8264ee
		else:
Packit Service 8264ee
			print("Unknown SLC command completed: %s" % (cmd))
Packit Service 8264ee
Packit Service 8264ee
	def io_cb(self, fd, cond):
Packit Service 8264ee
		buf = os.read(fd, BUF_SIZE)
Packit Service 8264ee
		buf = buf.strip()
Packit Service 8264ee
Packit Service 8264ee
		print("Received: %s" % (buf))
Packit Service 8264ee
Packit Service 8264ee
		if (buf == "OK" or buf == "ERROR"):
Packit Service 8264ee
			cmd = self.pending
Packit Service 8264ee
			self.pending = None
Packit Service 8264ee
Packit Service 8264ee
			if (not self.slc_complete):
Packit Service 8264ee
				self.slc_next_cmd(cmd)
Packit Service 8264ee
Packit Service 8264ee
			return True
Packit Service 8264ee
Packit Service 8264ee
		parts = buf.split(':')
Packit Service 8264ee
Packit Service 8264ee
		if (parts[0] == "+BRSF"):
Packit Service 8264ee
			self.features = int(parts[1])
Packit Service 8264ee
Packit Service 8264ee
		return True
Packit Service 8264ee
Packit Service 8264ee
	def send_cmd(self, cmd):
Packit Service 8264ee
		if (self.pending):
Packit Service 8264ee
			print("ERROR: Another command is pending")
Packit Service 8264ee
			return
Packit Service 8264ee
Packit Service 8264ee
		print("Sending: %s" % (cmd))
Packit Service 8264ee
Packit Service 8264ee
		os.write(self.fd, cmd + "\r\n")
Packit Service 8264ee
		self.pending = cmd
Packit Service 8264ee
Packit Service 8264ee
	def __init__(self, fd, version, features):
Packit Service 8264ee
		self.fd = fd
Packit Service 8264ee
		self.version = version
Packit Service 8264ee
		self.features = features
Packit Service 8264ee
Packit Service 8264ee
		print("Version 0x%04x Features 0x%04x" % (version, features))
Packit Service 8264ee
Packit Service 8264ee
		self.io_id = glib.io_add_watch(fd, glib.IO_IN, self.io_cb)
Packit Service 8264ee
Packit Service 8264ee
		self.slc_next_cmd(None)
Packit Service 8264ee
Packit Service 8264ee
class HfpProfile(dbus.service.Object):
Packit Service 8264ee
	sco_socket = None
Packit Service 8264ee
	io_id = 0
Packit Service 8264ee
	conns = {}
Packit Service 8264ee
Packit Service 8264ee
	def sco_cb(self, sock, cond):
Packit Service 8264ee
		(sco, peer) = sock.accept()
Packit Service 8264ee
		print("New SCO connection from %s" % (peer))
Packit Service 8264ee
Packit Service 8264ee
	def init_sco(self, sock):
Packit Service 8264ee
		self.sco_socket = sock
Packit Service 8264ee
		self.io_id = glib.io_add_watch(sock, glib.IO_IN, self.sco_cb)
Packit Service 8264ee
Packit Service 8264ee
	def __init__(self, bus, path, sco):
Packit Service 8264ee
		dbus.service.Object.__init__(self, bus, path)
Packit Service 8264ee
Packit Service 8264ee
		if sco:
Packit Service 8264ee
			self.init_sco(sco)
Packit Service 8264ee
Packit Service 8264ee
	@dbus.service.method("org.bluez.Profile1",
Packit Service 8264ee
					in_signature="", out_signature="")
Packit Service 8264ee
	def Release(self):
Packit Service 8264ee
		print("Release")
Packit Service 8264ee
		mainloop.quit()
Packit Service 8264ee
Packit Service 8264ee
	@dbus.service.method("org.bluez.Profile1",
Packit Service 8264ee
					in_signature="", out_signature="")
Packit Service 8264ee
	def Cancel(self):
Packit Service 8264ee
		print("Cancel")
Packit Service 8264ee
Packit Service 8264ee
	@dbus.service.method("org.bluez.Profile1",
Packit Service 8264ee
				in_signature="o", out_signature="")
Packit Service 8264ee
	def RequestDisconnection(self, path):
Packit Service 8264ee
		conn = self.conns.pop(path)
Packit Service 8264ee
		conn.disconnect()
Packit Service 8264ee
Packit Service 8264ee
	@dbus.service.method("org.bluez.Profile1",
Packit Service 8264ee
				in_signature="oha{sv}", out_signature="")
Packit Service 8264ee
	def NewConnection(self, path, fd, properties):
Packit Service 8264ee
		fd = fd.take()
Packit Service 8264ee
		version = 0x0105
Packit Service 8264ee
		features = 0
Packit Service 8264ee
		print("NewConnection(%s, %d)" % (path, fd))
Packit Service 8264ee
		for key in properties.keys():
Packit Service 8264ee
			if key == "Version":
Packit Service 8264ee
				version = properties[key]
Packit Service 8264ee
			elif key == "Features":
Packit Service 8264ee
				features = properties[key]
Packit Service 8264ee
Packit Service 8264ee
		conn = HfpConnection(fd, version, features)
Packit Service 8264ee
Packit Service 8264ee
		self.conns[path] = conn
Packit Service 8264ee
Packit Service 8264ee
if __name__ == '__main__':
Packit Service 8264ee
	dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
Packit Service 8264ee
Packit Service 8264ee
	bus = dbus.SystemBus()
Packit Service 8264ee
Packit Service 8264ee
	manager = dbus.Interface(bus.get_object("org.bluez",
Packit Service 8264ee
				"/org/bluez"), "org.bluez.ProfileManager1")
Packit Service 8264ee
Packit Service 8264ee
	option_list = [
Packit Service 8264ee
			make_option("-p", "--path", action="store",
Packit Service 8264ee
					type="string", dest="path",
Packit Service 8264ee
					default="/bluez/test/hfp"),
Packit Service 8264ee
			make_option("-n", "--name", action="store",
Packit Service 8264ee
					type="string", dest="name",
Packit Service 8264ee
					default=None),
Packit Service 8264ee
			make_option("-C", "--channel", action="store",
Packit Service 8264ee
					type="int", dest="channel",
Packit Service 8264ee
					default=None),
Packit Service 8264ee
			]
Packit Service 8264ee
Packit Service 8264ee
	parser = OptionParser(option_list=option_list)
Packit Service 8264ee
Packit Service 8264ee
	(options, args) = parser.parse_args()
Packit Service 8264ee
Packit Service 8264ee
	mainloop = GObject.MainLoop()
Packit Service 8264ee
Packit Service 8264ee
	opts = {
Packit Service 8264ee
			"Version" : dbus.UInt16(0x0106),
Packit Service 8264ee
			"Features" : dbus.UInt16(HF_FEATURES),
Packit Service 8264ee
		}
Packit Service 8264ee
Packit Service 8264ee
	if (options.name):
Packit Service 8264ee
		opts["Name"] = options.name
Packit Service 8264ee
Packit Service 8264ee
	if (options.channel is not None):
Packit Service 8264ee
		opts["Channel"] = dbus.UInt16(options.channel)
Packit Service 8264ee
Packit Service 8264ee
	if audio_supported:
Packit Service 8264ee
		sco = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO)
Packit Service 8264ee
		sco.bind(BDADDR_ANY)
Packit Service 8264ee
		sco.listen(1)
Packit Service 8264ee
	else:
Packit Service 8264ee
		sco = None
Packit Service 8264ee
Packit Service 8264ee
	profile = HfpProfile(bus, options.path, sco)
Packit Service 8264ee
Packit Service 8264ee
	manager.RegisterProfile(options.path, "hfp-hf", opts)
Packit Service 8264ee
Packit Service 8264ee
	print("Profile registered - waiting for connections")
Packit Service 8264ee
Packit Service 8264ee
	mainloop.run()