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

📄 irlmp.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);	IRDA_ASSERT(log != NULL, return;);	if (!(HASHBIN_GET_SIZE(log)))		return;	/* For each client - notify callback may touch client list */	client = (irlmp_client_t *) hashbin_get_first(irlmp->clients);	while (NULL != hashbin_find_next(irlmp->clients, (long) client, NULL,					 (void *) &client_next) ) {		/* Check if we should notify client */		irlmp_notify_client(client, log, mode);		client = client_next;	}}/* * Function irlmp_discovery_expiry (expiry) * *	This device is no longer been discovered, and therefore it is being *	purged from the discovery log. Inform all clients who have *	registered for this event... * *	Note : called exclusively from discovery.c *	Note : this is no longer called under discovery spinlock, so the *		client can do whatever he wants in the callback. */void irlmp_discovery_expiry(discinfo_t *expiries, int number){	irlmp_client_t *client;	irlmp_client_t *client_next;	int		i;	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);	IRDA_ASSERT(expiries != NULL, return;);	/* For each client - notify callback may touch client list */	client = (irlmp_client_t *) hashbin_get_first(irlmp->clients);	while (NULL != hashbin_find_next(irlmp->clients, (long) client, NULL,					 (void *) &client_next) ) {		/* Pass all entries to the listener */		for(i = 0; i < number; i++) {			/* Check if we should notify client */			if ((client->expir_callback) &&			    (client->hint_mask.word & u16ho(expiries[i].hints)			     & 0x7f7f) )				client->expir_callback(&(expiries[i]),						       EXPIRY_TIMEOUT,						       client->priv);		}		/* Next client */		client = client_next;	}}/* * Function irlmp_get_discovery_response () * *    Used by IrLAP to get the discovery info it needs when answering *    discovery requests by other devices. */discovery_t *irlmp_get_discovery_response(void){	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);	IRDA_ASSERT(irlmp != NULL, return NULL;);	u16ho(irlmp->discovery_rsp.data.hints) = irlmp->hints.word;	/*	 *  Set character set for device name (we use ASCII), and	 *  copy device name. Remember to make room for a \0 at the	 *  end	 */	irlmp->discovery_rsp.data.charset = CS_ASCII;	strncpy(irlmp->discovery_rsp.data.info, sysctl_devname,		NICKNAME_MAX_LEN);	irlmp->discovery_rsp.name_len = strlen(irlmp->discovery_rsp.data.info);	return &irlmp->discovery_rsp;}/* * Function irlmp_data_request (self, skb) * *    Send some data to peer device * * Note on skb management : * After calling the lower layers of the IrDA stack, we always * kfree() the skb, which drop the reference count (and potentially * destroy it). * IrLMP and IrLAP may queue the packet, and in those cases will need * to use skb_get() to keep it around. * Jean II */int irlmp_data_request(struct lsap_cb *self, struct sk_buff *userdata){	int	ret;	IRDA_ASSERT(self != NULL, return -1;);	IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);	/* Make room for MUX header */	IRDA_ASSERT(skb_headroom(userdata) >= LMP_HEADER, return -1;);	skb_push(userdata, LMP_HEADER);	ret = irlmp_do_lsap_event(self, LM_DATA_REQUEST, userdata);	/* Drop reference count - see irlap_data_request(). */	dev_kfree_skb(userdata);	return ret;}EXPORT_SYMBOL(irlmp_data_request);/* * Function irlmp_data_indication (handle, skb) * *    Got data from LAP layer so pass it up to upper layer * */void irlmp_data_indication(struct lsap_cb *self, struct sk_buff *skb){	/* Hide LMP header from layer above */	skb_pull(skb, LMP_HEADER);	if (self->notify.data_indication) {		/* Don't forget to refcount it - see irlap_driver_rcv(). */		skb_get(skb);		self->notify.data_indication(self->notify.instance, self, skb);	}}/* * Function irlmp_udata_request (self, skb) */int irlmp_udata_request(struct lsap_cb *self, struct sk_buff *userdata){	int	ret;	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);	IRDA_ASSERT(userdata != NULL, return -1;);	/* Make room for MUX header */	IRDA_ASSERT(skb_headroom(userdata) >= LMP_HEADER, return -1;);	skb_push(userdata, LMP_HEADER);	ret = irlmp_do_lsap_event(self, LM_UDATA_REQUEST, userdata);	/* Drop reference count - see irlap_data_request(). */	dev_kfree_skb(userdata);	return ret;}/* * Function irlmp_udata_indication (self, skb) * *    Send unreliable data (but still within the connection) * */void irlmp_udata_indication(struct lsap_cb *self, struct sk_buff *skb){	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);	IRDA_ASSERT(skb != NULL, return;);	/* Hide LMP header from layer above */	skb_pull(skb, LMP_HEADER);	if (self->notify.udata_indication) {		/* Don't forget to refcount it - see irlap_driver_rcv(). */		skb_get(skb);		self->notify.udata_indication(self->notify.instance, self,					      skb);	}}/* * Function irlmp_connless_data_request (self, skb) */#ifdef CONFIG_IRDA_ULTRAint irlmp_connless_data_request(struct lsap_cb *self, struct sk_buff *userdata,				__u8 pid){	struct sk_buff *clone_skb;	struct lap_cb *lap;	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);	IRDA_ASSERT(userdata != NULL, return -1;);	/* Make room for MUX and PID header */	IRDA_ASSERT(skb_headroom(userdata) >= LMP_HEADER+LMP_PID_HEADER,		    return -1;);	/* Insert protocol identifier */	skb_push(userdata, LMP_PID_HEADER);	if(self != NULL)	  userdata->data[0] = self->pid;	else	  userdata->data[0] = pid;	/* Connectionless sockets must use 0x70 */	skb_push(userdata, LMP_HEADER);	userdata->data[0] = userdata->data[1] = LSAP_CONNLESS;	/* Try to send Connectionless  packets out on all links */	lap = (struct lap_cb *) hashbin_get_first(irlmp->links);	while (lap != NULL) {		IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, return -1;);		clone_skb = skb_clone(userdata, GFP_ATOMIC);		if (!clone_skb) {			dev_kfree_skb(userdata);			return -ENOMEM;		}		irlap_unitdata_request(lap->irlap, clone_skb);		/* irlap_unitdata_request() don't increase refcount,		 * so no dev_kfree_skb() - Jean II */		lap = (struct lap_cb *) hashbin_get_next(irlmp->links);	}	dev_kfree_skb(userdata);	return 0;}#endif /* CONFIG_IRDA_ULTRA *//* * Function irlmp_connless_data_indication (self, skb) * *    Receive unreliable data outside any connection. Mostly used by Ultra * */#ifdef CONFIG_IRDA_ULTRAvoid irlmp_connless_data_indication(struct lsap_cb *self, struct sk_buff *skb){	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);	IRDA_ASSERT(skb != NULL, return;);	/* Hide LMP and PID header from layer above */	skb_pull(skb, LMP_HEADER+LMP_PID_HEADER);	if (self->notify.udata_indication) {		/* Don't forget to refcount it - see irlap_driver_rcv(). */		skb_get(skb);		self->notify.udata_indication(self->notify.instance, self,					      skb);	}}#endif /* CONFIG_IRDA_ULTRA *//* * Propagate status indication from LAP to LSAPs (via LMP) * This don't trigger any change of state in lap_cb, lmp_cb or lsap_cb, * and the event is stateless, therefore we can bypass both state machines * and send the event direct to the LSAP user. * Jean II */void irlmp_status_indication(struct lap_cb *self,			     LINK_STATUS link, LOCK_STATUS lock){	struct lsap_cb *next;	struct lsap_cb *curr;	/* Send status_indication to all LSAPs using this link */	curr = (struct lsap_cb *) hashbin_get_first( self->lsaps);	while (NULL != hashbin_find_next(self->lsaps, (long) curr, NULL,					 (void *) &next) ) {		IRDA_ASSERT(curr->magic == LMP_LSAP_MAGIC, return;);		/*		 *  Inform service user if he has requested it		 */		if (curr->notify.status_indication != NULL)			curr->notify.status_indication(curr->notify.instance,						       link, lock);		else			IRDA_DEBUG(2, "%s(), no handler\n", __FUNCTION__);		curr = next;	}}/* * Receive flow control indication from LAP. * LAP want us to send it one more frame. We implement a simple round * robin scheduler between the active sockets so that we get a bit of * fairness. Note that the round robin is far from perfect, but it's * better than nothing. * We then poll the selected socket so that we can do synchronous * refilling of IrLAP (which allow to minimise the number of buffers). * Jean II */void irlmp_flow_indication(struct lap_cb *self, LOCAL_FLOW flow){	struct lsap_cb *next;	struct lsap_cb *curr;	int	lsap_todo;	IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);	IRDA_ASSERT(flow == FLOW_START, return;);	/* Get the number of lsap. That's the only safe way to know	 * that we have looped around... - Jean II */	lsap_todo = HASHBIN_GET_SIZE(self->lsaps);	IRDA_DEBUG(4, "%s() : %d lsaps to scan\n", __FUNCTION__, lsap_todo);	/* Poll lsap in order until the queue is full or until we	 * tried them all.	 * Most often, the current LSAP will have something to send,	 * so we will go through this loop only once. - Jean II */	while((lsap_todo--) &&	      (IRLAP_GET_TX_QUEUE_LEN(self->irlap) < LAP_HIGH_THRESHOLD)) {		/* Try to find the next lsap we should poll. */		next = self->flow_next;		/* If we have no lsap, restart from first one */		if(next == NULL)			next = (struct lsap_cb *) hashbin_get_first(self->lsaps);		/* Verify current one and find the next one */		curr = hashbin_find_next(self->lsaps, (long) next, NULL,					 (void *) &self->flow_next);		/* Uh-oh... Paranoia */		if(curr == NULL)			break;		IRDA_DEBUG(4, "%s() : curr is %p, next was %p and is now %p, still %d to go - queue len = %d\n", __FUNCTION__, curr, next, self->flow_next, lsap_todo, IRLAP_GET_TX_QUEUE_LEN(self->irlap));		/* Inform lsap user that it can send one more packet. */		if (curr->notify.flow_indication != NULL)			curr->notify.flow_indication(curr->notify.instance,						     curr, flow);		else			IRDA_DEBUG(1, "%s(), no handler\n", __FUNCTION__);	}}#if 0/* * Function irlmp_hint_to_service (hint) * *    Returns a list of all servics contained in the given hint bits. This *    function assumes that the hint bits have the size of two bytes only */__u8 *irlmp_hint_to_service(__u8 *hint){	__u8 *service;	int i = 0;	/*	 * Allocate array to store services in. 16 entries should be safe	 * since we currently only support 2 hint bytes	 */	service = kmalloc(16, GFP_ATOMIC);	if (!service) {		IRDA_DEBUG(1, "%s(), Unable to kmalloc!\n", __FUNCTION__);		return NULL;	}	if (!hint[0]) {		IRDA_DEBUG(1, "<None>\n");		kfree(service);		return NULL;	}	if (hint[0] & HINT_PNP)		IRDA_DEBUG(1, "PnP Compatible ");	if (hint[0] & HINT_PDA)		IRDA_DEBUG(1, "PDA/Palmtop ");	if (hint[0] & HINT_COMPUTER)		IRDA_DEBUG(1, "Computer ");	if (hint[0] & HINT_PRINTER) {		IRDA_DEBUG(1, "Printer ");		service[i++] = S_PRINTER;	}	if (hint[0] & HINT_MODEM)		IRDA_DEBUG(1, "Modem ");	if (hint[0] & HINT_FAX)		IRDA_DEBUG(1, "Fax ");	if (hint[0] & HINT_LAN) {		IRDA_DEBUG(1, "LAN Access ");		service[i++] = S_LAN;	}	/*	 *  Test if extension byte exists. This byte will usually be	 *  there, but this is not really required by the standard.	 *  (IrLMP p. 29)	 */	if (hint[0] & HINT_EXTENSION) {		if (hint[1] & HINT_TELEPHONY) {			IRDA_DEBUG(1, "Telephony ");			service[i++] = S_TELEPHONY;		} if (hint[1] & HINT_FILE_SERVER)			IRDA_DEBUG(1, "File Server ");		if (hint[1] & HINT_COMM) {			IRDA_DEBUG(1, "IrCOMM ");			service[i++] = S_COMM;		}		if (hint[1] & HINT_OBEX) {			IRDA_DEBUG(1, "IrOBEX ");			service[i++] = S_OBEX;		}	}	IRDA_DEBUG(1, "\n");	/* So that client can be notified about any discovery */	service[i++] = S_ANY;	service[i] = S_END;	return service;}#endifstatic const __u16 service_hint_mapping[S_END][2] = {	{ HINT_PNP,		0 },			/* S_PNP */	{ HINT_PDA,		0 },			/* S_PDA */	{ HINT_COMPUTER,	0 },			/* S_COMPUTER */	{ HINT_PRINTER,		0 },			/* S_PRINTER */	{ HINT_MODEM,		0 },			/* S_MODEM */	{ HINT_FAX,		0 },			/* S_FAX */	{ HINT_LAN,		0 },			/* S_LAN */	{ HINT_EXTENSION,	HINT_TELEPHONY },	/* S_TELEPHONY */	{ HINT_EXTENSION,	HINT_COMM },		/* S_COMM */	{ HINT_EXTENSION,	HINT_OBEX },		/* S_OBEX */	{ 0xFF,			0xFF },			/* S_ANY */};/* * Function irlmp_service_to_hint (service) * *    Converts a service type, to a hint bit * *    Returns: a 16 bit hint value, with the service bit set */__u16 irlmp_service_to_hint(int service){	__u16_host_order hint;	hint.byte[0] = service_hint_mapping[service][0];	hint.byte[1] = service_hint_mapping[service][1];	return hint.word;}EXPORT_SYMBOL(irlmp_service_to_hint);/* * Function irlmp_register_service (service) * *    Register local service with IrLMP * */void *irlmp_register_service(__u16 hints){	irlmp_service_t *service;	IRDA_DEBUG(4, "%s(), hints = %04x\n", __FUNCTION__, hints);	/* Make a new registration */	service = kmalloc(sizeof(irlmp_service_t), GFP_ATOMIC);	if (!service) {		IRDA_DEBUG(1, "%s(), Unable to kmalloc!\n", __FUNCTION__);		return NULL;	}	service->hints.word = hints;	hashbin_insert(irlmp->services, (irda_queue_t *) service,		       (long) service, NULL);	irlmp->hints.word |= hints;	return (void *)service;}EXPORT_SYMBOL(irlmp_register_service);/* * Function irlmp_unregister_service (handle) * *    Unregister service with IrLMP. * *    Returns: 0 on success, -1 on error */int irlmp_unregister_service(void *handle){	irlmp_service_t *service;	unsigned long flags;	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);	if (!handle)		return -1;	/* Caller may call with invalid handle (it's legal) - Jean II */	service = hashbin_lock_find(irlmp->services, (long) handle, NULL);

⌨️ 快捷键说明

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