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

📄 bnep_core.c

📁 蓝牙的各种编程接口和各种按理介绍,还有一些例子和说明
💻 C
📖 第 1 页 / 共 5 页
字号:
	return 0;}/***************************************************************************/static int bnep_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	switch (cmd) {	//Close a connection            	case SIOC_DISCONNECT:{			struct bnep_connect_mgnt_struct bnep_connect_mgnt;			struct bnep_connection *conn = NULL;			copy_from_user(&bnep_connect_mgnt, rq->ifr_data,				       sizeof(struct bnep_connect_mgnt_struct));			conn = bnep_get_conn_by_bdaddr(dev, &bnep_connect_mgnt.destination_address);			if (conn) {				BT_DBG("closing connection to %s",						batostr(&bnep_connect_mgnt.destination_address));				//Kill session thread				stop_kthread(&conn->session);			} else {				BT_DBG("connection to %s not found",						batostr(&bnep_connect_mgnt.destination_address));				return BNEP_ERR_NO_L2CAP;			}			return 0;		}		//Create a BNEP or L2CAP connection             	case SIOC_CONNECT:{			int status = 0;			struct bnep_connect_mgnt_struct bnep_connect_mgnt;			copy_from_user(&bnep_connect_mgnt, rq->ifr_data,				       sizeof(struct bnep_connect_mgnt_struct));			switch (bnep_connect_mgnt.protocol) {			case CONN_L2CAP_LAYER:				status = bnep_l2cap_connect(dev, &bnep_connect_mgnt);				break;			case CONN_BNEP_LAYER:				status = bnep_connect(dev, &bnep_connect_mgnt);				break;			default:				status = BNEP_ERR_CONN_UNKNOWN_LAYER;			}			return status;		}		//Set filter on specific link	case SIOC_SET_FILTER:{			struct filter_request_struct filter_request;			unsigned char *data = NULL;			int status;			copy_from_user(&filter_request, rq->ifr_data,				       sizeof(struct filter_request_struct));			if (filter_request.data_length > 0) {				data =				    (unsigned char *) kmalloc(filter_request.data_length,							      GFP_ATOMIC);				copy_from_user(data, filter_request.data,					       filter_request.data_length);				filter_request.data = data;			}			status = bnep_tx_filter(dev, &filter_request);			kfree(data);			return status;		}		//Change role of device	case SIOC_SET_ROLE:{			int role_uuid;			copy_from_user(&role_uuid, rq->ifr_data, sizeof(int));			return bnep_update_role(dev, role_uuid);		}		//Test case execution	case SIOC_TESTCASE:	/* Execute test case  */  {#ifdef BNEP_TEST			struct bnep_test_ctrl_struct bnep_test_ctrl;			copy_from_user(&bnep_test_ctrl, rq->ifr_data,				       sizeof(struct bnep_test_ctrl_struct));			return test_execute_test(dev, &bnep_test_ctrl);#else			BT_DBG("test mode not available. Recompile with -DBNEP_TEST");			return 1;#endif			break;		}	}	return -EOPNOTSUPP;}/***************************************************************************/static struct net_device_stats *device_get_stats(struct net_device *dev){	struct bnep_private *priv;	priv = (struct bnep_private *) dev->priv;	return &(priv->stats);}/***************************************************************************/static int device_open_dev(struct net_device *dev){	netif_start_queue(dev);	return 0;}/***************************************************************************/static int device_close_dev(struct net_device *dev){	netif_stop_queue(dev);	return 0;}/***************************************************************************/static void device_dev_timeout(struct net_device *dev){	BT_DBG("not implemented");}/***************************************************************************/static int __init bnep_init(struct net_device *dev){	int i;	struct bnep_private *priv = (struct bnep_private *) dev->priv;	//init dev struct	ether_setup(dev);	//net device setup	dev->hard_start_xmit = &device_tx_data;	dev->get_stats = &device_get_stats;	dev->do_ioctl = &bnep_ioctl;	dev->set_multicast_list = &device_set_multicast_list;	dev->open = &device_open_dev;	dev->stop = &device_close_dev;	dev->tx_timeout = &device_dev_timeout;	dev->watchdog_timeo = HZ;#ifdef CONFIG_NET_FASTROUTE	dev->accept_fastpath = device_accept_fastpath;#endif	//Set device source address from private data	BT_DBG("Binding %s <-> %s", batostr(&priv->source_address), dev->name);	for (i = 0; i < 6; i++)		dev->dev_addr[i] = ((unsigned char *) &priv->source_address)[i];	dev->tx_queue_len = 100;	dev->flags &= (IFF_MULTICAST | IFF_BROADCAST);	return 0;}/***************************************************************************/struct socket *bnep_sock_accept(struct socket *sk){	struct socket *nsk;	int err;	nsk = sock_alloc();	if (!nsk)		return NULL;	nsk->type = sk->type;	nsk->ops = sk->ops;	err = sk->ops->accept(sk, nsk, 0);	BT_DBG("result: %d", err);	if (err < 0) {		sock_release(nsk);		return NULL;	}	return nsk;}/***************************************************************************/static void bnep_connect_listener(kthread_t * kthread){	struct sockaddr_l2 addr;	struct l2cap_options opts;	int err, size;	struct net_device *dev = (struct net_device *) kthread->arg;	struct bnep_private *bnep_priv = bnep_get_priv(dev);	BT_DBG("start connect listener");	init_kthread(kthread, "bnep_conn_lsten");	set_fs(KERNEL_DS);	// Create socket	err = sock_create(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP, &bnep_priv->bnep_sk);	if (err < 0) {		BT_DBG("Create socket failed %d", err);		return;	}	// Bind socket 	baswap(&addr.l2_bdaddr, &bnep_priv->source_address);	addr.l2_family = AF_BLUETOOTH;	addr.l2_psm = htobs(PAN_PSM);	err =	    bnep_priv->bnep_sk->ops->bind(bnep_priv->bnep_sk, (struct sockaddr *) &addr,					  sizeof(addr));	if (err < 0) {		BT_DBG("Bind failed %d", err);		return;	}	// Set L2CAP options	size = sizeof(opts);	bnep_priv->bnep_sk->ops->getsockopt(bnep_priv->bnep_sk, SOL_L2CAP, L2CAP_OPTIONS,					    (void *) &opts, &size);	opts.imtu = PAN_IMTU;	opts.imtu = PAN_OMTU;	opts.flush_to = PAN_FLUSH_TO;	bnep_priv->bnep_sk->ops->setsockopt(bnep_priv->bnep_sk, SOL_L2CAP, L2CAP_OPTIONS,					    (void *) &opts, size);	// Start listening on the socket	err = bnep_priv->bnep_sk->ops->listen(bnep_priv->bnep_sk, 10);	if (err) {		BT_DBG("Listen failed %d", err);		sock_release(bnep_priv->bnep_sk);		return;	}	while (1) {		struct socket *nsk;		mb();		if (kthread->terminate) {			BT_DBG("exiting connect listener");			break;		}		nsk = bnep_sock_accept(bnep_priv->bnep_sk);		if (nsk) {			bdaddr_t tmp_addr;			baswap(&tmp_addr, &bluez_pi(nsk->sk)->dst);			//Check for existing bnep connection			if (bnep_get_conn_by_bdaddr(dev, &tmp_addr)) {				BT_DBG("connection to %s exists => close new connection",						batostr(&tmp_addr));				sock_release(nsk);			} else {				//Start new thread for this session				BT_DBG("starting bnep session on sock %p", nsk);				bnep_start_session(nsk, (struct net_device *) kthread->arg);			}		}	}	//Kill thread	exit_kthread(kthread);	return;}/***************************************************************************/static int bnep_read_proc(char *buf, char **start, off_t offset, int count, int *eof, void *priv){	char *ptr = buf;	int len;	struct list_head *list_ptr;	struct bnep_connection *bnep_conn;	struct net_device *net_dev = root_dev;	int counter;	bdaddr_t tmp_addr;	struct bnep_private *bnep_priv;	ptr += sprintf(ptr, "BNEP device status:\n");	if (net_dev == NULL) {		ptr += sprintf(ptr, " No PAN devices loaded\n");	} else {		while (net_dev) {			bnep_priv = bnep_get_priv(net_dev);			ptr += sprintf(ptr, " %s\tBDAddr: %s Role: 0x%.4x\n", net_dev->name,				    batostr(&bnep_priv->source_address), bnep_priv->role_uuid);			for (list_ptr = bnep_priv->bnep_connections.next;			     list_ptr != &bnep_priv->bnep_connections; list_ptr = list_ptr->next) {				bnep_conn = list_entry(list_ptr, struct bnep_connection, list);				baswap(&tmp_addr, &bluez_pi(bnep_conn->sk->sk)->dst);				ptr += sprintf(ptr, "\t  Connection: %s Role 0x%.4x\n",					    batostr(&tmp_addr), bnep_conn->destination_uuid);				if (bnep_conn->filter_info.MulticastFilter) {					for (counter = 0;					     counter <					     bnep_conn->filter_info.multicast_filter_count;					     counter++) {						int byte_counter;						ptr +=						    sprintf(ptr, "\t\tMulticast Filter %d: ",							    counter);						for (byte_counter = 5; byte_counter >= 0;						     byte_counter--) {							ptr +=							    sprintf(ptr, "%.2x%s",								    ((__u8 *) & bnep_conn->								     filter_info.								     MulticastFilter[counter].								     start)[byte_counter],								    byte_counter == 0 ? "" : ":");						}						ptr += sprintf(ptr, " - ");						for (byte_counter = 5; byte_counter >= 0;						     byte_counter--) {							ptr +=							    sprintf(ptr, "%.2x%s",								    ((__u8 *) & bnep_conn->								     filter_info.								     MulticastFilter[counter].								     stop)[byte_counter],								    byte_counter == 0 ? "" : ":");						}						ptr += sprintf(ptr, "\n");					}				} else {					ptr += sprintf(ptr, "\t\tNo Multicast Filter active\n");				}				if (bnep_conn->filter_info.NetFilter) {					for (counter = 0;					     counter < bnep_conn->filter_info.net_filter_count;					     counter++) {						ptr +=						    sprintf(ptr,							    "\t\tProtocol Filter %d: 0x%.4x - 0x%.4x\n",							    counter,							    bnep_conn->filter_info.							    NetFilter[counter].start,							    bnep_conn->filter_info.							    NetFilter[counter].stop);					}				} else {					ptr += sprintf(ptr, "\t\tNo Prototocl Filter active\n");				}			}			net_dev = bnep_priv->next_dev;			ptr += sprintf(ptr, "\n");		}	}	len = ptr - buf;	if (len <= count + offset)		*eof = 1;	*start = buf + offset;	len -= offset;	if (len > count)		len = count;	if (len < 0)		len = 0;	return len;}/******************************************************************************/int bnep_dev_control(struct bnep_dev_ioctl_struct *bnep_dev_ioctl){	int err = 0;	if (bnep_dev_ioctl->net_device_command == NET_DEVICE_REMOVE) {		//Find device in device list		struct net_device *del_dev = NULL;		struct net_device *pre_dev = NULL;		struct net_device *tmp_dev = root_dev;		struct bnep_private *priv = NULL;		int status;		//Remove device from dev list		while (tmp_dev && !del_dev) {			if (strcmp(tmp_dev->name, bnep_dev_ioctl->name) == 0) {				//Check for active connections				if (bnep_get_priv(tmp_dev)->connection_counter != 0) {					BT_DBG("can't remove device with active connections");					return BNEP_ERR_DEVICE_CONNECTED;				}				del_dev = tmp_dev;				if (pre_dev)					bnep_get_priv(pre_dev)->next_dev =					    bnep_get_priv(tmp_dev)->next_dev;				else					root_dev = bnep_get_priv(tmp_dev)->next_dev;			} else {				pre_dev = tmp_dev;				tmp_dev = bnep_get_priv(tmp_dev)->next_dev;			}		}		if (!del_dev) {			BT_DBG("device not loaded");			return BNEP_ERR_DEV_NOT_LOADED;		}		BT_DBG("remove eth net device");		priv = bnep_get_priv(del_dev);		//Stop connection listener thread		stop_kthread(&priv->listener_thread);		//Clean interface to l2cap		if (priv->bnep_sk)			sock_release(priv->bnep_sk);		//Clean interface from kernel		unregister_netdev(del_dev);		status = netdev_finish_unregister(del_dev);		if (status)			BT_DBG("can't free net device mem");		bnep_dev_counter--;		MOD_DEC_USE_COUNT;	} else if (bnep_dev_ioctl->net_device_command == NET_DEVICE_INSERT) {		struct bnep_private *priv;		struct net_device *new_dev;		BT_DBG("insert eth net device");		//Allocate new eth device		if (!(new_dev = alloc_etherdev(sizeof(struct bnep_private))))			return -ENOMEM;		// Find a name for this unit 		if (dev_alloc_name(new_dev, bnep_dev_ioctl->name) < 0) {			kfree(new_dev);			return BNEP_ERR_ALLOC_NAME;		}		//Init device		priv = bnep_get_priv(new_dev);		priv->bnep_sk = NULL;		priv->role_uuid = bnep_dev_ioctl->role_uuid;		new_dev->init = bnep_init;		spin_lock_init(&priv->lock);		bacpy(&priv

⌨️ 快捷键说明

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