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

📄 unix.c

📁 实现bluez蓝牙profile需要的库
💻 C
📖 第 1 页 / 共 2 页
字号:
	a2dp->stream = NULL;}static void create_stream(struct device *dev, struct unix_client *client){	struct a2dp_data *a2dp;	unsigned int id;	client->type = select_service(dev, client->interface);	switch (client->type) {	case TYPE_SINK:		a2dp = &client->d.a2dp;		if (!a2dp->session)			a2dp->session = avdtp_get(&dev->src, &dev->dst);		if (!a2dp->session) {			error("Unable to get a session");			goto failed;		}		/* FIXME: The provided media_codec breaks bitpool                   selection. So disable it. This needs fixing */		id = a2dp_source_request_stream(a2dp->session,						TRUE, a2dp_setup_complete,						client,						NULL/*client->media_codec*/);		client->cancel_stream = a2dp_source_cancel_stream;		break;	case TYPE_HEADSET:		id = headset_request_stream(dev, headset_setup_complete, client);		client->cancel_stream = headset_cancel_stream;		break;	default:		error("No known services for device");		goto failed;	}	if (id == 0) {		error("request_stream failed");		goto failed;	}	client->req_id = id;	client->dev = dev;	return;failed:	unix_send_cfg(client->sock, NULL, -1);}static void create_cb(struct device *dev, void *user_data){	struct unix_client *client = user_data;	if (!dev)		unix_send_cfg(client->sock, NULL, -1);	else		create_stream(dev, client);}static int cfg_to_caps(struct ipc_data_cfg *cfg, struct sbc_codec_cap *sbc_cap){	struct ipc_codec_sbc *sbc = (void *) cfg->data;	memset(sbc_cap, 0, sizeof(struct sbc_codec_cap));	sbc_cap->cap.media_type = AVDTP_MEDIA_TYPE_AUDIO;	sbc_cap->cap.media_codec_type = A2DP_CODEC_SBC;	switch (cfg->rate) {	case 48000:		sbc_cap->frequency = A2DP_SAMPLING_FREQ_48000;		break;	case 44100:		sbc_cap->frequency = A2DP_SAMPLING_FREQ_44100;		break;	case 32000:		sbc_cap->frequency = A2DP_SAMPLING_FREQ_32000;		break;	case 16000:		sbc_cap->frequency = A2DP_SAMPLING_FREQ_16000;		break;	default:		sbc_cap->frequency = A2DP_SAMPLING_FREQ_44100;		break;	}	switch (cfg->mode) {	case CFG_MODE_MONO:		sbc_cap->channel_mode = A2DP_CHANNEL_MODE_MONO;		break;	case CFG_MODE_DUAL_CHANNEL:		sbc_cap->channel_mode = A2DP_CHANNEL_MODE_DUAL_CHANNEL;		break;	case CFG_MODE_STEREO:		sbc_cap->channel_mode = A2DP_CHANNEL_MODE_STEREO;		break;	case CFG_MODE_JOINT_STEREO:		sbc_cap->channel_mode = A2DP_CHANNEL_MODE_JOINT_STEREO;		break;	default:		sbc_cap->channel_mode = A2DP_CHANNEL_MODE_JOINT_STEREO;		break;	}	switch (sbc->allocation) {	case CFG_ALLOCATION_LOUDNESS:		sbc_cap->allocation_method = A2DP_ALLOCATION_LOUDNESS;		break;	case CFG_ALLOCATION_SNR:		sbc_cap->allocation_method = A2DP_ALLOCATION_LOUDNESS;		break;	default:		sbc_cap->allocation_method = A2DP_ALLOCATION_LOUDNESS;		break;	}	switch (sbc->subbands) {	case 8:		sbc_cap->subbands = A2DP_SUBBANDS_8;		break;	case 4:		sbc_cap->subbands = A2DP_SUBBANDS_4;		break;	default:		sbc_cap->subbands = A2DP_SUBBANDS_8;		break;	}	switch (sbc->blocks) {	case 16:		sbc_cap->block_length = A2DP_BLOCK_LENGTH_16;		break;	case 12:		sbc_cap->block_length = A2DP_BLOCK_LENGTH_12;		break;	case 8:		sbc_cap->block_length = A2DP_BLOCK_LENGTH_8;		break;	case 4:		sbc_cap->block_length = A2DP_BLOCK_LENGTH_4;		break;	default:		sbc_cap->block_length = A2DP_BLOCK_LENGTH_16;		break;	}	if (sbc->bitpool != 0) {		if (sbc->bitpool > 250)			return -EINVAL;		sbc_cap->min_bitpool = sbc->bitpool;		sbc_cap->max_bitpool = sbc->bitpool;	}	return 0;}static void cfg_event(struct unix_client *client, struct ipc_packet *pkt, int len){	struct device *dev;	bdaddr_t bdaddr;	struct ipc_data_cfg *cfg = (void *) pkt->data;	struct sbc_codec_cap sbc_cap;	str2ba(pkt->device, &bdaddr);	client->fd_opt = cfg->fd_opt;	if (client->interface) {		g_free(client->interface);		client->interface = NULL;	}	if (pkt->role == PKT_ROLE_VOICE)		client->interface = g_strdup(AUDIO_HEADSET_INTERFACE);	else if (pkt->role == PKT_ROLE_HIFI)		client->interface = g_strdup(AUDIO_SINK_INTERFACE);	if (cfg_to_caps(cfg, &sbc_cap) < 0)		goto failed;	client->media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC,						&sbc_cap, sizeof(sbc_cap));	if (!manager_find_device(&bdaddr, NULL, FALSE)) {		if (!bacmp(&bdaddr, BDADDR_ANY))			goto failed;		if (!manager_create_device(&bdaddr, create_cb, client))			goto failed;		return;	}	dev = manager_find_device(&bdaddr, client->interface, TRUE);	if (!dev)		dev = manager_find_device(&bdaddr, client->interface, FALSE);	if (!dev)		goto failed;	create_stream(dev, client);	return;failed:	unix_send_cfg(client->sock, NULL, -1);}static void ctl_event(struct unix_client *client,					struct ipc_packet *pkt, int len){}static int reply_state(int sock, struct ipc_packet *pkt){	struct ipc_data_state *state = (struct ipc_data_state *) pkt->data;	int len;	info("status=%u", state->state);	pkt->type = PKT_TYPE_STATE_RSP;	pkt->length = sizeof(struct ipc_data_state);	pkt->error = PKT_ERROR_NONE;	len = sizeof(struct ipc_packet) + sizeof(struct ipc_data_state);	len = send(sock, pkt, len, 0);	if (len < 0)		error("Error %s(%d)", strerror(errno), errno);	debug("%d bytes sent", len);	return 0;}static void state_event(struct unix_client *client,					struct ipc_packet *pkt, int len){#if 0	struct ipc_data_state *state = (struct ipc_data_state *) pkt->data;	struct device *dev = client->dev;	if (len > sizeof(struct ipc_packet))		device_set_state(dev, state->state);	else		state->state = device_get_state(dev);#endif	reply_state(client->sock, pkt);}static gboolean client_cb(GIOChannel *chan, GIOCondition cond, gpointer data){	char buf[IPC_MTU];	struct ipc_packet *pkt = (void *) buf;	struct unix_client *client = data;	int len, len_check;	struct a2dp_data *a2dp = &client->d.a2dp;	struct headset_data *hs = &client->d.hs;	if (cond & G_IO_NVAL)		return FALSE;	if (cond & (G_IO_HUP | G_IO_ERR)) {		debug("Unix client disconnected (fd=%d)", client->sock);		switch (client->type) {		case TYPE_HEADSET:			if (client->dev)				headset_unlock(client->dev, hs->lock);			break;		case TYPE_SOURCE:		case TYPE_SINK:			if (a2dp->sep) {				a2dp_sep_unlock(a2dp->sep, a2dp->session);				a2dp->sep = NULL;			}			break;		default:			break;		}		if (client->cancel_stream && client->req_id > 0)			client->cancel_stream(client->dev, client->req_id);		goto failed;	}	memset(buf, 0, sizeof(buf));	len = recv(client->sock, buf, sizeof(buf), 0);	if (len < 0) {		error("recv: %s (%d)", strerror(errno), errno);		goto failed;	}	len_check = pkt->length + sizeof(struct ipc_packet);	if (len != len_check) {		error("Packet lenght doesn't match");		goto failed;	}	switch (pkt->type) {	case PKT_TYPE_CFG_REQ:		info("Package PKT_TYPE_CFG_REQ:%u", pkt->role);		cfg_event(client, pkt, len);		break;	case PKT_TYPE_STATE_REQ:		info("Package PKT_TYPE_STATE_REQ");		state_event(client, pkt, len);		break;	case PKT_TYPE_CTL_REQ:		info("Package PKT_TYPE_CTL_REQ");		ctl_event(client, pkt, len);		break;	}	return TRUE;failed:	clients = g_slist_remove(clients, client);	client_free(client);	return FALSE;}static gboolean server_cb(GIOChannel *chan, GIOCondition cond, gpointer data){	struct sockaddr_un addr;	socklen_t addrlen;	int sk, cli_sk;	struct unix_client *client;	GIOChannel *io;	if (cond & G_IO_NVAL)		return FALSE;	if (cond & (G_IO_HUP | G_IO_ERR)) {		g_io_channel_close(chan);		return FALSE;	}	sk = g_io_channel_unix_get_fd(chan);	memset(&addr, 0, sizeof(addr));	addrlen = sizeof(addr);	cli_sk = accept(sk, (struct sockaddr *) &addr, &addrlen);	if (cli_sk < 0) {		error("accept: %s (%d)", strerror(errno), errno);		return TRUE;	}	debug("Accepted new client connection on unix socket (fd=%d)", cli_sk);	client = g_new0(struct unix_client, 1);	client->sock = cli_sk;	clients = g_slist_append(clients, client);	io = g_io_channel_unix_new(cli_sk);	g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,							client_cb, client);	g_io_channel_unref(io);	return TRUE;}int unix_init(void){	GIOChannel *io;	struct sockaddr_un addr = {		AF_UNIX, IPC_SOCKET_NAME	};	int sk, err;	sk = socket(PF_LOCAL, SOCK_STREAM, 0);	if (sk < 0) {		err = errno;		error("Can't create unix socket: %s (%d)", strerror(err), err);		return -err;	}	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {		error("Can't bind unix socket: %s (%d)", strerror(errno), errno);		close(sk);		return -1;	}	set_nonblocking(sk);	unix_sock = sk;	listen(sk, 1);	io = g_io_channel_unix_new(sk);	g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,							server_cb, NULL);	g_io_channel_unref(io);	info("Unix socket created: %d", sk);	return 0;}void unix_exit(void){	g_slist_foreach(clients, (GFunc) client_free, NULL);	g_slist_free(clients);	close(unix_sock);	unix_sock = -1;}

⌨️ 快捷键说明

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