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

📄 irlan_common.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	IRDA_DEBUG(0, "%s(), reason=%d\n", __FUNCTION__ , reason);	self = (struct irlan_cb *) instance;	tsap = (struct tsap_cb *) sap;	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	IRDA_ASSERT(tsap != NULL, return;);	IRDA_ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);	IRDA_ASSERT(tsap == self->tsap_data, return;);	IRDA_DEBUG(2, "IrLAN, data channel disconnected by peer!\n");	/* Save reason so we know if we should try to reconnect or not */	self->disconnect_reason = reason;	switch (reason) {	case LM_USER_REQUEST: /* User request */		IRDA_DEBUG(2, "%s(), User requested\n", __FUNCTION__ );		break;	case LM_LAP_DISCONNECT: /* Unexpected IrLAP disconnect */		IRDA_DEBUG(2, "%s(), Unexpected IrLAP disconnect\n", __FUNCTION__ );		break;	case LM_CONNECT_FAILURE: /* Failed to establish IrLAP connection */		IRDA_DEBUG(2, "%s(), IrLAP connect failed\n", __FUNCTION__ );		break;	case LM_LAP_RESET:  /* IrLAP reset */		IRDA_DEBUG(2, "%s(), IrLAP reset\n", __FUNCTION__ );		break;	case LM_INIT_DISCONNECT:		IRDA_DEBUG(2, "%s(), IrLMP connect failed\n", __FUNCTION__ );		break;	default:		IRDA_ERROR("%s(), Unknown disconnect reason\n", __FUNCTION__);		break;	}	/* If you want to pass the skb to *both* state machines, you will	 * need to skb_clone() it, so that you don't free it twice.	 * As the state machines don't need it, git rid of it here...	 * Jean II */	if (userdata)		dev_kfree_skb(userdata);	irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);	irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);	wake_up_interruptible(&self->open_wait);}void irlan_open_data_tsap(struct irlan_cb *self){	struct tsap_cb *tsap;	notify_t notify;	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	/* Check if already open */	if (self->tsap_data)		return;	irda_notify_init(&notify);	notify.data_indication       = irlan_eth_receive;	notify.udata_indication      = irlan_eth_receive;	notify.connect_indication    = irlan_connect_indication;	notify.connect_confirm       = irlan_connect_confirm;	notify.flow_indication       = irlan_eth_flow_indication;	notify.disconnect_indication = irlan_disconnect_indication;	notify.instance              = self;	strlcpy(notify.name, "IrLAN data", sizeof(notify.name));	tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);	if (!tsap) {		IRDA_DEBUG(2, "%s(), Got no tsap!\n", __FUNCTION__ );		return;	}	self->tsap_data = tsap;	/*	 *  This is the data TSAP selector which we will pass to the client	 *  when the client ask for it.	 */	self->stsap_sel_data = self->tsap_data->stsap_sel;}void irlan_close_tsaps(struct irlan_cb *self){	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	/* Disconnect and close all open TSAP connections */	if (self->tsap_data) {		irttp_disconnect_request(self->tsap_data, NULL, P_NORMAL);		irttp_close_tsap(self->tsap_data);		self->tsap_data = NULL;	}	if (self->client.tsap_ctrl) {		irttp_disconnect_request(self->client.tsap_ctrl, NULL,					 P_NORMAL);		irttp_close_tsap(self->client.tsap_ctrl);		self->client.tsap_ctrl = NULL;	}	if (self->provider.tsap_ctrl) {		irttp_disconnect_request(self->provider.tsap_ctrl, NULL,					 P_NORMAL);		irttp_close_tsap(self->provider.tsap_ctrl);		self->provider.tsap_ctrl = NULL;	}	self->disconnect_reason = LM_USER_REQUEST;}/* * Function irlan_ias_register (self, tsap_sel) * *    Register with LM-IAS * */void irlan_ias_register(struct irlan_cb *self, __u8 tsap_sel){	struct ias_object *obj;	struct ias_value *new_value;	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	/*	 * Check if object has already been registered by a previous provider.	 * If that is the case, we just change the value of the attribute	 */	if (!irias_find_object("IrLAN")) {		obj = irias_new_object("IrLAN", IAS_IRLAN_ID);		irias_add_integer_attrib(obj, "IrDA:TinyTP:LsapSel", tsap_sel,					 IAS_KERNEL_ATTR);		irias_insert_object(obj);	} else {		new_value = irias_new_integer_value(tsap_sel);		irias_object_change_attribute("IrLAN", "IrDA:TinyTP:LsapSel",					      new_value);	}	/* Register PnP object only if not registered before */	if (!irias_find_object("PnP")) {		obj = irias_new_object("PnP", IAS_PNP_ID);#if 0		irias_add_string_attrib(obj, "Name", sysctl_devname,					IAS_KERNEL_ATTR);#else		irias_add_string_attrib(obj, "Name", "Linux", IAS_KERNEL_ATTR);#endif		irias_add_string_attrib(obj, "DeviceID", "HWP19F0",					IAS_KERNEL_ATTR);		irias_add_integer_attrib(obj, "CompCnt", 1, IAS_KERNEL_ATTR);		if (self->provider.access_type == ACCESS_PEER)			irias_add_string_attrib(obj, "Comp#01", "PNP8389",						IAS_KERNEL_ATTR);		else			irias_add_string_attrib(obj, "Comp#01", "PNP8294",						IAS_KERNEL_ATTR);		irias_add_string_attrib(obj, "Manufacturer",					"Linux-IrDA Project", IAS_KERNEL_ATTR);		irias_insert_object(obj);	}}/* * Function irlan_run_ctrl_tx_queue (self) * *    Try to send the next command in the control transmit queue * */int irlan_run_ctrl_tx_queue(struct irlan_cb *self){	struct sk_buff *skb;	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );	if (irda_lock(&self->client.tx_busy) == FALSE)		return -EBUSY;	skb = skb_dequeue(&self->client.txq);	if (!skb) {		self->client.tx_busy = FALSE;		return 0;	}	/* Check that it's really possible to send commands */	if ((self->client.tsap_ctrl == NULL) ||	    (self->client.state == IRLAN_IDLE))	{		self->client.tx_busy = FALSE;		dev_kfree_skb(skb);		return -1;	}	IRDA_DEBUG(2, "%s(), sending ...\n", __FUNCTION__ );	return irttp_data_request(self->client.tsap_ctrl, skb);}/* * Function irlan_ctrl_data_request (self, skb) * *    This function makes sure that commands on the control channel is being *    sent in a command/response fashion */static void irlan_ctrl_data_request(struct irlan_cb *self, struct sk_buff *skb){	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );	/* Queue command */	skb_queue_tail(&self->client.txq, skb);	/* Try to send command */	irlan_run_ctrl_tx_queue(self);}/* * Function irlan_get_provider_info (self) * *    Send Get Provider Information command to peer IrLAN layer * */void irlan_get_provider_info(struct irlan_cb *self){	struct sk_buff *skb;	__u8 *frame;	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER,			GFP_ATOMIC);	if (!skb)		return;	/* Reserve space for TTP, LMP, and LAP header */	skb_reserve(skb, self->client.max_header_size);	skb_put(skb, 2);	frame = skb->data;	frame[0] = CMD_GET_PROVIDER_INFO;	frame[1] = 0x00;                 /* Zero parameters */	irlan_ctrl_data_request(self, skb);}/* * Function irlan_open_data_channel (self) * *    Send an Open Data Command to provider * */void irlan_open_data_channel(struct irlan_cb *self){	struct sk_buff *skb;	__u8 *frame;	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +			IRLAN_STRING_PARAMETER_LEN("MEDIA", "802.3") +			IRLAN_STRING_PARAMETER_LEN("ACCESS_TYPE", "DIRECT"),			GFP_ATOMIC);	if (!skb)		return;	skb_reserve(skb, self->client.max_header_size);	skb_put(skb, 2);	frame = skb->data;	/* Build frame */	frame[0] = CMD_OPEN_DATA_CHANNEL;	frame[1] = 0x02; /* Two parameters */	irlan_insert_string_param(skb, "MEDIA", "802.3");	irlan_insert_string_param(skb, "ACCESS_TYPE", "DIRECT");	/* irlan_insert_string_param(skb, "MODE", "UNRELIABLE"); *//* 	self->use_udata = TRUE; */	irlan_ctrl_data_request(self, skb);}void irlan_close_data_channel(struct irlan_cb *self){	struct sk_buff *skb;	__u8 *frame;	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	/* Check if the TSAP is still there */	if (self->client.tsap_ctrl == NULL)		return;	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +			IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN"),			GFP_ATOMIC);	if (!skb)		return;	skb_reserve(skb, self->client.max_header_size);	skb_put(skb, 2);	frame = skb->data;	/* Build frame */	frame[0] = CMD_CLOSE_DATA_CHAN;	frame[1] = 0x01; /* One parameter */	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);	irlan_ctrl_data_request(self, skb);}/* * Function irlan_open_unicast_addr (self) * *    Make IrLAN provider accept ethernet frames addressed to the unicast *    address. * */static void irlan_open_unicast_addr(struct irlan_cb *self){	struct sk_buff *skb;	__u8 *frame;	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +			IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +			IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "DIRECTED") +			IRLAN_STRING_PARAMETER_LEN("FILTER_MODE", "FILTER"),			GFP_ATOMIC);	if (!skb)		return;	/* Reserve space for TTP, LMP, and LAP header */	skb_reserve(skb, self->max_header_size);	skb_put(skb, 2);	frame = skb->data;	frame[0] = CMD_FILTER_OPERATION;	frame[1] = 0x03;                 /* Three parameters */	irlan_insert_byte_param(skb, "DATA_CHAN" , self->dtsap_sel_data);	irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");	irlan_insert_string_param(skb, "FILTER_MODE", "FILTER");	irlan_ctrl_data_request(self, skb);}/* * Function irlan_set_broadcast_filter (self, status) * *    Make IrLAN provider accept ethernet frames addressed to the broadcast *    address. Be careful with the use of this one, since there may be a lot *    of broadcast traffic out there. We can still function without this *    one but then _we_ have to initiate all communication with other *    hosts, since ARP request for this host will not be answered. */void irlan_set_broadcast_filter(struct irlan_cb *self, int status){	struct sk_buff *skb;	__u8 *frame;	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	skb = alloc_skb(IRLAN_MAX_HEADER + IRLAN_CMD_HEADER +			IRLAN_BYTE_PARAMETER_LEN("DATA_CHAN") +			IRLAN_STRING_PARAMETER_LEN("FILTER_TYPE", "BROADCAST") +			/* We may waste one byte here...*/			IRLAN_STRING_PARAMETER_LEN("FILTER_MODE", "FILTER"),			GFP_ATOMIC);	if (!skb)		return;	/* Reserve space for TTP, LMP, and LAP header */	skb_reserve(skb, self->client.max_header_size);	skb_put(skb, 2);	frame = skb->data;	frame[0] = CMD_FILTER_OPERATION;	frame[1] = 0x03;                 /* Three parameters */	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);	irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST");	if (status)		irlan_insert_string_param(skb, "FILTER_MODE", "FILTER");	else		irlan_insert_string_param(skb, "FILTER_MODE", "NONE");

⌨️ 快捷键说明

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