⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 headset.c

📁 基于LINUX内核驱动的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
	dbus_message_unref(msg);	return 0;}static int rfcomm_connect(struct device *dev, headset_stream_cb_t cb,				void *user_data, unsigned int *cb_id){	struct headset *hs = dev->headset;	struct sockaddr_rc addr;	GIOChannel *io;	char address[18];	int sk, err;	if (hs->rfcomm_ch < 0)		return get_handles(dev, cb, user_data, cb_id);	ba2str(&dev->dst, address);	debug("%s: Connecting to %s channel %d", dev->path, address,		hs->rfcomm_ch);	sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);	if (sk < 0) {		err = errno;		error("socket(BTPROTO_RFCOMM): %s (%d)", strerror(err), err);		return -err;	}	io = g_io_channel_unix_new(sk);	if (!io) {		close(sk);		return -ENOMEM;	}	memset(&addr, 0, sizeof(addr));	addr.rc_family = AF_BLUETOOTH;	bacpy(&addr.rc_bdaddr, BDADDR_ANY);	addr.rc_channel = 0;	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {		err = errno;		error("bind: %s (%d)", strerror(errno), errno);		goto failed;	}	if (set_nonblocking(sk) < 0) {		err = errno;		goto failed;	}	memset(&addr, 0, sizeof(addr));	addr.rc_family = AF_BLUETOOTH;	bacpy(&addr.rc_bdaddr, &dev->dst);	addr.rc_channel = hs->rfcomm_ch;	err = connect(sk, (struct sockaddr *) &addr, sizeof(addr));	if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) {		err = errno;		error("connect() failed: %s (%d)", strerror(err), err);		goto failed;	}	headset_set_state(dev, HEADSET_STATE_CONNECT_IN_PROGRESS);	pending_connect_init(hs, HEADSET_STATE_CONNECTED);	if (cb) {		unsigned int id = connect_cb_new(hs, HEADSET_STATE_CONNECTED,							cb, user_data);		if (cb_id)			*cb_id = id;	}	g_io_add_watch(io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL,			(GIOFunc) rfcomm_connect_cb, dev);	hs->pending->io = io;	return 0;failed:	g_io_channel_close(io);	g_io_channel_unref(io);	return -err;}static DBusHandlerResult hs_stop(DBusConnection *conn, DBusMessage *msg,					void *data){	struct device *device = data;	struct headset *hs = device->headset;	DBusMessage *reply = NULL;	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	if (hs->state < HEADSET_STATE_PLAY_IN_PROGRESS)		return error_not_connected(conn, msg);	headset_set_state(device, HEADSET_STATE_CONNECTED);	send_message_and_unref(conn, reply);	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult hs_is_playing(DBusConnection *conn, DBusMessage *msg,					void *data){	struct device *device = data;	struct headset *hs = device->headset;	DBusMessage *reply;	dbus_bool_t playing;	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	playing = (hs->state == HEADSET_STATE_PLAYING);	dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &playing,					DBUS_TYPE_INVALID);	send_message_and_unref(conn, reply);	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult hs_disconnect(DBusConnection *conn, DBusMessage *msg,					void *data){	struct device *device = data;	struct headset *hs = device->headset;	DBusMessage *reply = NULL;	char hs_address[18];	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	if (hs->state == HEADSET_STATE_DISCONNECTED)		return error_not_connected(conn, msg);	headset_set_state(device, HEADSET_STATE_DISCONNECTED);	ba2str(&device->dst, hs_address);	info("Disconnected from %s, %s", hs_address, device->path);	send_message_and_unref(conn, reply);	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult hs_is_connected(DBusConnection *conn,						DBusMessage *msg,						void *data){	struct device *device = data;	DBusMessage *reply;	dbus_bool_t connected;	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	connected = (device->headset->state >= HEADSET_STATE_CONNECTED);	dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &connected,					DBUS_TYPE_INVALID);	send_message_and_unref(conn, reply);	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult hs_connect(DBusConnection *conn, DBusMessage *msg,					void *data){	struct device *device = data;	struct headset *hs = device->headset;	int err;	if (hs->state == HEADSET_STATE_CONNECT_IN_PROGRESS)		return error_in_progress(conn, msg, "Connect in progress");	else if (hs->state > HEADSET_STATE_CONNECT_IN_PROGRESS)		return error_already_connected(conn, msg);	err = rfcomm_connect(device, NULL, NULL, NULL);	if (err < 0)		return error_connection_attempt_failed(conn, msg, -err);	hs->auto_dc = FALSE;	hs->pending->msg = dbus_message_ref(msg);	return DBUS_HANDLER_RESULT_HANDLED;}static gboolean ring_timer_cb(gpointer data){	struct device *device = data;	struct headset *hs = device->headset;	int err;	err = headset_send(hs, "\r\nRING\r\n");	if (err < 0)		error("Error while sending RING: %s (%d)",				strerror(-err), -err);	if (hs->cli_active && hs->ph_number) {		err = headset_send(hs, "\r\n+CLIP:\"%s\",%d\r\n",					hs->ph_number, hs->type);		if (err < 0)			error("Error while sending CLIP: %s (%d)",					strerror(-err), -err);	}	return TRUE;}static DBusHandlerResult hs_ring(DBusConnection *conn, DBusMessage *msg,					void *data){	struct device *device = data;	struct headset *hs = device->headset;	DBusMessage *reply = NULL;	int err;	if (hs->state < HEADSET_STATE_CONNECTED)		return error_not_connected(conn, msg);	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	if (hs->ring_timer) {		debug("IndicateCall received when already indicating");		goto done;	}	err = headset_send(hs, "\r\nRING\r\n");	if (err < 0) {		dbus_message_unref(reply);		return error_failed_errno(conn, msg, -err);	}	if (hs->cli_active && hs->ph_number) {		err = headset_send(hs, "\r\n+CLIP:\"%s\",%d\r\n",					hs->ph_number, hs->type);		if (err < 0) {			dbus_message_unref(reply);			return error_failed_errno(conn, msg, -err);		}	}	hs->ring_timer = g_timeout_add(RING_INTERVAL, ring_timer_cb, device);done:	send_message_and_unref(conn, reply);	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult hs_cancel_ringing(DBusConnection *conn,						DBusMessage *msg,						void *data){	struct device *device = data;	struct headset *hs = device->headset;	DBusMessage *reply = NULL;	if (hs->state < HEADSET_STATE_CONNECTED)		return error_not_connected(conn, msg);	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	if (!hs->ring_timer) {		debug("Got CancelRinging method call but ringing is not in progress");		goto done;	}	g_source_remove(hs->ring_timer);	hs->ring_timer = 0;done:	if (hs->hfp_active) {		int err;		/*+CIEV: (callsetup = 0)*/		err = headset_send(hs, "\r\n+CIEV:3,0\r\n");		if (err < 0) {			dbus_message_unref(reply);			return error_failed_errno(conn, msg, -err);		}	}	send_message_and_unref(conn, reply);	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult hs_play(DBusConnection *conn, DBusMessage *msg,					void *data){	struct device *device = data;	struct headset *hs = device->headset;	int err;	if (sco_hci) {		error("Refusing Headset.Play() because SCO HCI routing "				"is enabled");		return error_not_available(conn, msg);	}	switch (hs->state) {	case HEADSET_STATE_DISCONNECTED:	case HEADSET_STATE_CONNECT_IN_PROGRESS:		return error_not_connected(conn, msg);	case HEADSET_STATE_PLAY_IN_PROGRESS:		return error_in_progress(conn, msg, "Play in progress");	case HEADSET_STATE_PLAYING:		return error_already_connected(conn, msg);	case HEADSET_STATE_CONNECTED:	default:		break;	}	err = sco_connect(device, NULL, NULL, NULL);	if (err < 0)		return error_failed(conn, msg, strerror(-err));	hs->pending->msg = dbus_message_ref(msg);	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult hs_get_speaker_gain(DBusConnection *conn,						DBusMessage *msg,						void *data){	struct device *device = data;	struct headset *hs = device->headset;	DBusMessage *reply;	dbus_uint16_t gain;	if (hs->state < HEADSET_STATE_CONNECTED || hs->sp_gain < 0)		return error_not_available(conn, msg);	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	gain = (dbus_uint16_t) hs->sp_gain;	dbus_message_append_args(reply, DBUS_TYPE_UINT16, &gain,					DBUS_TYPE_INVALID);	send_message_and_unref(conn, reply);	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult hs_get_mic_gain(DBusConnection *conn,						DBusMessage *msg,						void *data){	struct device *device = data;	struct headset *hs = device->headset;	DBusMessage *reply;	dbus_uint16_t gain;	if (hs->state < HEADSET_STATE_CONNECTED || hs->mic_gain < 0)		return error_not_available(conn, msg);	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	gain = (dbus_uint16_t) hs->mic_gain;	dbus_message_append_args(reply, DBUS_TYPE_UINT16, &gain,					DBUS_TYPE_INVALID);	send_message_and_unref(conn, reply);	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult hs_set_gain(DBusConnection *conn,					DBusMessage *msg,					void *data, char type){	struct device *device = data;	struct headset *hs = device->headset;	DBusMessage *reply;	DBusError derr;	dbus_uint16_t gain;	int err;	if (hs->state < HEADSET_STATE_CONNECTED)		return error_not_connected(conn, msg);	dbus_error_init(&derr);	dbus_message_get_args(msg, &derr, DBUS_TYPE_UINT16, &gain,				DBUS_TYPE_INVALID);	if (dbus_error_is_set(&derr)) {		error_invalid_arguments(conn, msg, derr.message);		dbus_error_free(&derr);		return DBUS_HANDLER_RESULT_HANDLED;	}	if (gain > 15)		return error_invalid_arguments(conn, msg,					"Must be less than or equal to 15");	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	if (hs->state != HEADSET_STATE_PLAYING)		goto done;	err = headset_send(hs, "\r\n+VG%c=%u\r\n", type, gain);	if (err < 0) {		dbus_message_unref(reply);		return error_failed(conn, msg, "Unable to send to headset");	}done:	if (type == HEADSET_GAIN_SPEAKER) {		hs->sp_gain = gain;		dbus_connection_emit_signal(conn, device->path,						AUDIO_HEADSET_INTERFACE,						"SpeakerGainChanged",						DBUS_TYPE_UINT16, &gain,						DBUS_TYPE_INVALID);	} else {		hs->mic_gain = gain;		dbus_connection_emit_signal(conn, device->path,						AUDIO_HEADSET_INTERFACE,						"MicrophoneGainChanged",						DBUS_TYPE_UINT16, &gain,						DBUS_TYPE_INVALID);	}	send_message_and_unref(conn, reply);	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult hs_set_speaker_gain(DBusConnection *conn,						DBusMessage *msg,						void *data){	return hs_set_gain(conn, msg, data, HEADSET_GAIN_SPEAKER);}static DBusHandlerResult hs_set_mic_gain(DBusConnection *conn,						DBusMessage *msg,						void *data){	return hs_set_gain(conn, msg, data, HEADSET_GAIN_MICROPHONE);}static DBusHandlerResult hf_setup_call(DBusConnection *conn,						DBusMessage *msg,						void *data){	struct device *device = data;	struct headset *hs = device->headset;	DBusMessage *reply;	DBusError derr;	const char *value;	int err;	if (!hs->hfp_active)		return error_not_supported(device->conn, msg);	if (hs->state < HEADSET_STATE_CONNECTED)		return error_not_connected(conn, msg);	dbus_error_init(&derr);	dbus_message_get_args(msg, &derr, DBUS_TYPE_STRING, &value,				DBUS_TYPE_INVALID);	if (dbus_error_is_set(&derr)) {		error_invalid_arguments(conn, msg, derr.message);		dbus_error_free(&derr);		return DBUS_HANDLER_RESULT_HANDLED;	}	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	if (!strncmp(value, "incoming", 8))		err = headset_send(hs, "\r\n+CIEV:3,1\r\n");	else if (!strncmp(value, "outgoing", 8))		err = headset_send(hs, "\r\n+CIEV:3,2\r\n");	else if (!strncmp(value, "remote", 6))		err = headset_send(hs, "\r\n+CIEV:3,3\r\n");	else		err = -EINVAL;	if (err < 0) {		dbus_message_unref(reply);		return error_failed_errno(conn, msg, -err);	}	send_message_and_unref(conn, reply);	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult hf_identify_call(DBusConnection *conn,						DBusMessage *msg,						void *data){	struct device *device = data;	struct headset *hs = device->headset;	DBusMessage *reply;	DBusError derr;	const char *number;	dbus_int32_t type;	if (!hs->hfp_active && !hs->cli_active)		return error_not_supported(device->conn, msg);	if (hs->state < HEADSET_STATE_CONNECTED)		return error_not_connected(conn, msg);	dbus_error_init(&derr);	dbus_message_get_args(msg, &derr, DBUS_TYPE_STRING, &number,			      DBUS_TYPE_INT32, &type, DBUS_TYPE_INVALID);	if (dbus_error_is_set(&derr)) {		error_invalid_arguments(conn, msg, derr.message);		dbus_error_free(&derr);		return DBUS_HANDLER_RESULT_HANDLED;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -