irlmp.c

来自「linux操作系统下的红外驱动的测试程序」· C语言 代码 · 共 477 行

C
477
字号
/********************************************************************* *                 * Filename:      irlmp.c * Version:        * Description:    * Status:        Experimental. * Author:        Dag Brattli <dagb@cs.uit.no> * Created at:    Wed Mar 31 15:30:46 1999 * Modified at:   Wed Dec  8 09:46:16 1999 * Modified by:   Dag Brattli <dagb@cs.uit.no> *  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved. *      *     This program is free software; you can redistribute it and/or  *     modify it under the terms of the GNU General Public License as  *     published by the Free Software Foundation; either version 2 of  *     the License, or (at your option) any later version. *  *     This program is distributed in the hope that it will be useful, *     but WITHOUT ANY WARRANTY; without even the implied warranty of *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *     GNU General Public License for more details. *  *     You should have received a copy of the GNU General Public License  *     along with this program; if not, write to the Free Software  *     Foundation, Inc., 59 Temple Place, Suite 330, Boston,  *     MA 02111-1307 USA *      ********************************************************************/#include <sys/socket.h>#include <sys/types.h>#include <string.h>		/* For strstr */#include <stdio.h>		/* For printf */#include <irda.h>#include "irdadump.h"extern struct ias_query last_ias;extern struct lsap_state conn[];/* * Function parse_iriap (buf) * *    Try to parse and print the LM-IAS query * */inline void parse_iriap_command(GNetBuf *buf, GString *str, guint8 slsap_sel){	guint8 opcode;	char name[255];	char attr[255];	int n = 0;	int name_len;	int attr_len;	/* Kill "unused" warning */	slsap_sel = slsap_sel;	opcode = buf->data[n++];	opcode &= ~IAP_LST; /* Mask away LST bit */	switch (opcode) {	case GET_INFO_BASE:	case GET_VALUE_BY_CLASS:		name_len = buf->data[n++];		memcpy( name, buf->data+n, name_len); n+=name_len;		name[name_len] = '\0';				attr_len = buf->data[n++]; 		memcpy( attr, buf->data+n, attr_len); n+=attr_len;		attr[attr_len] = '\0';		g_string_sprintfa(str, "GET_VALUE_BY_CLASS: \"%s\" \"%s\" ",				  name, attr);		/* Check if this is a TinyTP lookup */		if (strstr(attr, "TinyTP"))			last_ias.ttp = 1;		else			last_ias.ttp = 0;		/* Reset to undefined (handle IAS failures properly) */		last_ias.lsap_sel = LSAP_ANY;		/* Check if this is a OBEX lookup */		if (strstr(name, "OBEX"))			last_ias.obex = 1;		else			last_ias.obex = 0;		/* Check if this is a IrCOMM lookup */		if (strstr(name, "IrCOMM") || strstr(name, "IrLPT"))			last_ias.ircomm = 1;		else			last_ias.ircomm = 0;		/* Check if this is a IrNET lookup */		if (strstr(name, "IrNet"))			last_ias.irnet = 1;		else			last_ias.irnet = 0;		break;	default:		break;	}}/* * Function parse_irias_value (buf) * *     * */void parse_irias_value(GNetBuf *buf, GString *str){	char string[255];	int n = 0;	int charset;	guint32 value_len;	guint32 tmp_cpu32;	guint16 tmp_cpu16;	guint16 obj_id;	guint16 len;	guint8  type;	/* Get length, MSB first */	memcpy(&len, buf->data+n, 2); n += 2;	len = GUINT16_FROM_BE(len); 	/* Get object ID, MSB first */	memcpy(&obj_id, buf->data+n, 2); n += 2;	obj_id = GUINT16_FROM_BE(obj_id);	type = buf->data[n++];	switch(type) {	case IAS_INTEGER:		memcpy(&tmp_cpu32, buf->data+n, 4); n += 4;		tmp_cpu32 = GUINT32_FROM_BE(tmp_cpu32);		/*  Legal values restricted to 0x01-0x6f, page 15 irttp */		g_string_sprintfa(str, "Integer: %02x ", tmp_cpu32);		last_ias.lsap_sel = tmp_cpu32;		break;	case IAS_STRING:		charset = buf->data[n++];		switch (charset) {		case CS_ASCII:			break;		case CS_ISO_8859_1:		case CS_ISO_8859_2:		case CS_ISO_8859_3:		case CS_ISO_8859_4:		case CS_ISO_8859_5:		case CS_ISO_8859_6:		case CS_ISO_8859_7:		case CS_ISO_8859_8:		case CS_ISO_8859_9:		case CS_UNICODE:		default:			break;		}		value_len = buf->data[n++];				/* Make sure the string is null-terminated */		memcpy(string, buf->data+n, value_len);		string[value_len] = 0x00;				g_string_sprintfa(str, "String: %s ", string);		break;	case IAS_OCT_SEQ:		memcpy(&tmp_cpu16, buf->data+n, 2);  n += 2;		tmp_cpu16 = GUINT16_FROM_BE(tmp_cpu16);		value_len = tmp_cpu16;				g_netbuf_pull(buf, n);		if (last_ias.ircomm) {			g_string_append(str, "\n\tIrCOMM Parameters ");			parse_ircomm_params(value_len, buf, str);		} else			g_string_append(str, "N/A ");		break;	default:		g_print("%s() Unknown IAS value type! ", __FUNCTION__);		break;	}}/* * Function parse_iriap_response (buf) * *     * */inline void parse_iriap_response(GNetBuf *buf, GString *str, guint8 dlsap_sel){	guint8 opcode, rsp;	/* Kill "unused" warning */	dlsap_sel = dlsap_sel;	opcode = buf->data[0] & ~IAP_LST; /* Mask away LST bit */	rsp = buf->data[1];	g_netbuf_pull(buf, 2);	switch(opcode) {	case GET_INFO_BASE:		g_print("%s() Sorry, GET_INFO_BASE not implemented!\n", __FUNCTION__);		break;	case GET_VALUE_BY_CLASS:		g_string_append(str, "GET_VALUE_BY_CLASS: ");		break;	default:		g_print("%s() Sorry, not implemented!\n", __FUNCTION__);		break;	}	switch(rsp) {	case IAS_SUCCESS:		g_string_append(str, "Success ");		parse_irias_value(buf, str);		break;	case IAS_CLASS_UNKNOWN:		g_string_append(str, "No such class ");		break;	case IAS_ATTRIB_UNKNOWN:		g_string_append(str, "No such attribute ");		break;	default:		g_string_append(str, "Unknown response code ");	}}/* * Function parse_irttp (buf, str) * *    Parse IrTTP data frame * */inline void parse_irnet(GNetBuf *buf, GString *str) {	/* Kill "unused" warning */	buf = buf;	g_string_sprintfa(str, "IrNET ");	/* If you want to hook PPP frame decoding, you can do it here.	 * I don't think it's worth it, PPP has debug capabilities.	 * Jean II */}/* * Function parse_irttp (buf, str) * *    Parse IrTTP data frame * */inline void parse_irttp(GNetBuf *buf, GString *str) {	g_string_sprintfa(str, "TTP credits=%d ", buf->data[0] & 0x7f);	if (buf->data[0] & 0x80)		g_string_append(str, "More ");	/* Remove TTP header */	g_netbuf_pull(buf, 1);}/* * Function parse_irttp_connect (buf, str) * *    Parse IrTTP connect frame * */inline void parse_irttp_connect(GNetBuf *buf, GString *str){	guint8 plen, pi, pl;	guint16 tmp_cpu;	g_string_sprintfa(str, "TTP credits=%d ", buf->data[0] & 0x7f);	if (buf->data[0] & 0x80) {		plen = buf->data[1];		pi   = buf->data[2];		pl   = buf->data[3];		memcpy(&tmp_cpu, buf->data+4, 2); /* Align value */		tmp_cpu = GUINT16_FROM_BE(tmp_cpu); /* Convert to host order */		/* Remove TTP parameters */		g_netbuf_pull(buf, plen);		g_string_sprintfa(str, "MaxSduSize=%d ", tmp_cpu);	}	/* Remove TTP header */	g_netbuf_pull(buf, 1);}/* * Function parse_irlmp (buf) * *    Parse IrLMP frame * */inline void parse_irlmp(GNetBuf *buf, GString *str,			guint8 caddr, int type, int cmd){	guint8 slsap_sel, dlsap_sel;	int ctrl;	int rsvd;	int i;		ctrl = buf->data[0] & CONTROL_BIT;	dlsap_sel = buf->data[0] & LSAP_MASK;	slsap_sel = buf->data[1];		/* Remove IrLMP header */	g_netbuf_pull(buf, 2);	g_string_sprintfa(str, "LM slsap=%02x dlsap=%02x ", slsap_sel, 			  dlsap_sel);		/* Control or data? */	if (ctrl) {		ctrl = buf->data[0];		rsvd = buf->data[1];	/* reason/status/rsvd */		/* Remove IrLMP control header (2 bytes) */		g_netbuf_pull(buf, 2);		switch (ctrl) {		case CONNECT_CMD:			g_string_append(str, "CONN_CMD ");			if (dlsap_sel == last_ias.lsap_sel) {				i = find_free_connection();				if (i == -1) {					printf("No more space for connection!\n");					return;				}				conn[i].valid = 1;				conn[i].caddr = caddr;				if (type) {					conn[i].slsap_sel = slsap_sel;					conn[i].dlsap_sel = dlsap_sel;				} else {					conn[i].slsap_sel = dlsap_sel;					conn[i].dlsap_sel = slsap_sel;				}				conn[i].ttp = last_ias.ttp;				conn[i].obex = last_ias.obex;				conn[i].ircomm = last_ias.ircomm;				conn[i].irnet = last_ias.irnet;				if (conn[i].ttp)					parse_irttp_connect(buf, str);				if (conn[i].ircomm)					parse_ircomm_connect(buf, str);				if (conn[i].irnet)					parse_irnet(buf, str);			} else {				if((config_force_ttp) && (dlsap_sel != 0x00))					parse_irttp_connect(buf, str);			}			break;		case CONNECT_RSP:			g_string_append(str, "CONN_RSP ");			if (type)				i = find_connection(slsap_sel, dlsap_sel);			else				i = find_connection(dlsap_sel, slsap_sel);			if (i != -1) {				if (conn[i].ttp)					parse_irttp_connect(buf, str);				if (conn[i].ircomm)					parse_ircomm_connect(buf, str);				if (conn[i].irnet)					parse_irnet(buf, str);			} else {				if((config_force_ttp) && (slsap_sel != 0x00))					parse_irttp_connect(buf, str);			}			break;		case DISCONNECT:			g_string_append(str, "DISC ");			/* Mark this connection as invalid */			if (type)				i = find_connection(slsap_sel, dlsap_sel);			else				i = find_connection(dlsap_sel, slsap_sel);			if (i != -1) {				conn[i].valid = 0;			}			break;		default:			break;		}	} else {		/* Check if this is a LM-IAS query */		if (dlsap_sel == 0x00)			parse_iriap_command(buf, str, slsap_sel);		else if (slsap_sel == 0x00)			parse_iriap_response(buf, str, dlsap_sel);				/* Find connection */		if (type)			i = find_connection(slsap_sel, dlsap_sel);		else			i = find_connection(dlsap_sel, slsap_sel);		if (i != -1) {			if (conn[i].valid && conn[i].ttp)				parse_irttp(buf, str);			if (conn[i].valid && conn[i].obex)				parse_obex(buf, str, cmd);			if (conn[i].valid && conn[i].ircomm) {				if (conn[i].ttp)					parse_ircomm_ttp(buf, str);				else					parse_ircomm_lmp(buf, str);			}			if (conn[i].valid && conn[i].irnet)				parse_irnet(buf, str);		}		/* Not IAS and unknow connection */		if((dlsap_sel != 0x00) && (slsap_sel != 0x00) && (i == -1)) {			if(config_force_ttp)				parse_irttp(buf, str);		}	}}/* * Function parse_ui_irlmp (buf) * *    Parse IrLMP frame in UI frame * */inline void parse_ui_irlmp(GNetBuf *buf, GString *str, int type){	guint8 slsap_sel, dlsap_sel;	int ctrl;		/* Kill "unused" warning */	type = type;	ctrl = buf->data[0] & CONTROL_BIT;	dlsap_sel = buf->data[0] & LSAP_MASK;	slsap_sel = buf->data[1];		/* Remove IrLMP header */	g_netbuf_pull(buf, 2);	g_string_sprintfa(str, "LM slsap=%02x dlsap=%02x ", slsap_sel, 			  dlsap_sel);	/* Let's see if it's Ultra, and decode it - Jean II */	if((slsap_sel == 0x70) && (dlsap_sel == 0x70))	  {	    int	upid = buf->data[0] & 0x7F;	    g_netbuf_pull(buf, 1);	    g_string_sprintfa(str, " Ultra-PID=%02x ", upid);	    /* Check Obex over Ultra */	    if(upid == 0x01)	      {		/* Remove SAR field */		g_netbuf_pull(buf, 1);		/* Decode Obex stuff - no connection, always a command */		parse_obex(buf, str, 1);	      }	  }}

⌨️ 快捷键说明

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