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

📄 blue.cpp

📁 blue-usu: (Search, Connect, Playback, Record) with bluetooth devices like headset. Rely on usu dr
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/* * blue.cpp * * Author : Lionetti Salvatore <salvatorelionetti@yahoo.it> * License: GPL * * 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<stdio.h>#include<stdio.h>#include<fcntl.h>  /* open().*/#include<unistd.h> /* read()/close().*/#if 0#ifdef LITTLE_ENDIAN#undef LITTLE_ENDIAN#include<linux/byteorder/little_endian.h>#elif defined BIG_ENDIAN#undef BIG_ENDIAN#include<linux/byteorder/big_endian.h>#endif#endif#include<string.h>      /* memcpy().*/#include<linux/types.h> /* __u16 */#include<time.h> 	/* nanosleep(), timespec.*/#include<stdarg.h>	/* va_start(), va_end().*/#include<errno.h>#include"blue.h"#include"../config_usu.h" /* To select fs to which interact.*/#undef USE_PROCFSchar* linuxErrDes(int errCode) {	char* ritorno=0;	switch (errCode) {		case -ESRCH: {ritorno="-ESRCH";break;}		case -ENOSPC:{ritorno="-ENOSPC";break;}		case -EPROTO:{ritorno="-EPROTO";break;}		case -ENODEV:{ritorno="-ENODEV";break;}		case -EBADMSG:{ritorno="-EBADMSG";break;}		case -EALREADY:{ritorno="-EALREADY";break;}		case -EINVAL:{ritorno="-EINVAL";break;}		case -ETIMEDOUT:{ritorno="-ETIMEDOUT";break;}		case -EHOSTDOWN:{ritorno="-EHOSTDOWN";break;}		case -EACCES:{ritorno="-EACCES";break;}		case -ENOTCONN:{ritorno="-ENOTCONN";break;}		case -ECONNRESET:{ritorno="-ECONNRESET";break;}		case -EBUSY:{ritorno="-EBUSY";break;}		case -ECONNABORTED:{ritorno="-ECONNABORTED";break;}		default: {			static char defaultErr[10];			snprintf(defaultErr,10,"%d",errCode);			ritorno=defaultErr;			break;		}	}	return ritorno;}int blue2linuxErr(int errCode) {	int ritorno=0;	switch(errCode) {		case '\xb': 	{ritorno=-EALREADY;break;}		case '\x12': 	{ritorno=-EINVAL;break;}		case '\x10': 	{ritorno=-ETIMEDOUT;break;}		case '\x4': 	{ritorno=-EHOSTDOWN;break;}		case '\x18':		case '\x5': 	{ritorno=-EACCES;break;}		case '\x2': 	{ritorno=-ENOTCONN;break;}		case '\x13': 	{ritorno=-ECONNRESET;break;}		case '\xc':	{ritorno=-EBUSY;break;}		case '\x9':		case '\xa':	{ritorno=-EMLINK;break;} /* Many link.*/		case '\x16':	{ritorno=-ECONNABORTED;break;} /* Software cause connection abort.*//*		case '\x22':	{ritorno=-EPROTO;break;}  UNKNOWN.*/		case '\x1f':	{ritorno=-EIO;break;} /* affix report unk err.*/		default:	{ritorno=errCode;break;}	}	return ritorno;}char* blueErrDes(int errCode) {	return linuxErrDes(blue2linuxErr(errCode));}int log=1;FILE* fdlog=NULL;int Dprintf(const char* fmt,...) {	int ritorno;	{		va_list va;		va_start(va,fmt);		ritorno=vfprintf(stdout,fmt,va);		va_end(va);	}	if (fdlog==NULL) {		fdlog=fopen("log.txt","a");		if (fdlog) fprintf(fdlog,"\n=========START PROGRAM============\n");	}	if (fdlog) {		va_list va;		va_start(va,fmt);		int ritorno;		ritorno=vfprintf(fdlog,fmt,va);		va_end(va);	}	return ritorno;}HciReqRes::HciReqRes() {	req=new char[MAX_PDU_LEN*2];	res=req + MAX_PDU_LEN;	reqL=resL=MAX_PDU_LEN; 	/* max len.*/	reqC=resC=0; 		/* cursors.*/	atExitF=NULL;}HciReqRes::~HciReqRes() {	if (atExitF)		atExitF(atExitP,*this);	delete req;}void HciReqRes::atExit(void* ingP,atExitT ing) {	atExitF=ing;	atExitP=ingP;}/* Write only if all requested bytes are now available.*/int HciReqRes::compileReq(char* buf, int len) {	int ritorno=0;	if (len+reqC<=reqL) {		memcpy(req+reqC,buf,len);		ritorno=len;		reqC+=len;	}	return ritorno;}int HciReqRes::scanRes(char* buf, int len) {	int ritorno=len;	if (ritorno>0) {		memcpy(buf,res+resC,ritorno);		resC+=ritorno;		/*if (resC==0) requestOn=false; */	}	return ritorno;}int HciReqRes::writeReq(char* buf, int len) {	int ritorno=-ENOSPC;	if (len>reqC) {		if (reqC>0) memcpy(buf, req, reqC);		ritorno=reqC;		/*reqC=0; so multi read can be done.*/		requestOn=true;	}	return ritorno;}/* Read only if all bytes requested are now available.*/int HciReqRes::readRes(char* buf, int len) {	int ritorno=0;	/*if (len<=resC)*/ {		/*resC-=len;*/		resC=0;		memcpy(res+resC,buf,len);		ritorno=len;		requestOn=false;		/*if (resC==0) requestOn=false; */	}	return ritorno;}bool HciReqRes::done() {return !requestOn;}enum HciReqRes::ProtoT HciReqRes::getProto() {return proto;}void HciReqRes::setProto(enum HciReqRes::ProtoT pro) {proto=pro;}int HciReqRes::getReqC() {return reqC;}int HciReqRes::getResC() {return resC;}void HciReqRes::setDone(bool idone) {requestOn=!idone;}/*void HciReqRes::attach() {if (hcirr) hcirr->usecount++;}void HciReqRes::detach() {if (hcirr) hcirr->usecount--;}void HciReqRes::copy(HciReqRes& ing) {memcpy(this,&ing,sizeof(*this));}*/enum OgfOcfT {	WRITE_VOICE_SETTING=0,	WRITE_SCAN_ENABLE,	WRITE_AUTH_ENABLE,	WRITE_ENCR_MODE,	WRITE_LOCAL_NAME,	CREATE_CONNECTION,	LINKKEY_REPLY,	LINKKEY_NEG_REPLY,	PINCODE_REPLY,	DISCONNECT,	WRITE_CLASS_OF_DEV,	WRITE_LINK_POLICY,	ADD_SCO_CONNECTION,	ACCEPT_CONNECTION,	READ_HOST_MAC, /* HOST mean the special bt device that let us2communicate with HciBus.*/	SEARCH_DEVICE,	READ_REMOTE_NAME,	WRITE_PAGESCAN_TIMEOUT,	WRITE_INCONNECTION_TIMEOUT,	SET_EVENT_FILTER,	EVENT_WAITING,};/* All HCI Command end with EVT command complete: (also if err?) * class HciCmd capture this behavior.*//* Only deal with hci cmd and related response (e..., f...) * * AcceptConnection is only req (really is a response to device) * and have no response at all. Now we only schedule. * If wrong command, we a spurious hciEvent.*/class HciCmd: public HciReqRes {public:	enum OgfT {NULL_OGF=0, LINK_CTL, LINK_POL, HOST_CTL, INFO_PAR, STATUS_PAR, TESTING_CMD=0x3E, VENDOR_CMD};	struct HciCmdT {		char* des;		enum OgfT ogf;		__u16 ocf;		__u8 reqL;		__u8 resL;	};#if 0		char* reqOptTypes;		char* resOptTypes;#endifprivate:	static HciCmdT hciCmds[21];	enum OgfOcfT index;public:	HciCmd(enum OgfOcfT ind, char* reqopt=0);	~HciCmd();	int readRes(char* des, int len);	int writeReq(char* buf, int len);	/* Now we assume that only one parameter is present in req.*/	void setPar(char* reqopt);	int getReqL() {return req[2];}	void copy(HciCmd& ing) {memcpy(this,&ing,sizeof(*this));}};#if 0struct HciCmd::HciCmdT asd[]={	{"wrVoiceSetting",	HciCmd::HOST_CTL, 0x26, 2, 0},		/* WRITE_VOICE_SETTING 	*/	{"wrVoiceSetting",	HciCmd::HOST_CTL, 0x26, 2, 0}		/* WRITE_VOICE_SETTING 	*/};#endifstruct HciCmd::HciCmdT HciCmd::hciCmds[]={	{"wrVoiceSetting",	HOST_CTL, 0x26, 2, 0},		/* WRITE_VOICE_SETTING 	*/	{"wrScanEnable",	HOST_CTL, 0x1a, 1, 0},		/* WRITE_SCAN_ENABLE	*/	{"wrAuthEnable",	HOST_CTL, 0x20, 1, 0},		/* WRITE_AUTH_ENABLE	*/	{"wrEncrMode",		HOST_CTL, 0x22, 1, 0},		/* WRITE_ENCR_MODE	*/	{"wrLocalName",		HOST_CTL, 0x13, 256, 0},	/* WRITE_LOCAL_NAME	*/	{"createConn",		LINK_CTL, 0x05, 13, 0},		/* CREATE_CONNECTION	*/	{"linkKeyReply",	LINK_CTL, 0x0b, 22, 6},		/* LINKKEY_REPLY	*/	{"linkKeyNegReply",	LINK_CTL, 0x0c,  6, 6},		/* LINKKEY_NEG_REPLY	*/	{"pinCodeReply",	LINK_CTL, 0x0d, /*12*/23, 6},		/* PINCODE_REPLY	*/	{"disconnect",		LINK_CTL, 0x06, 3, 0},		/* DISCONNECT		*/	{"wrClassOfDev",	HOST_CTL, 0x24, 3, 0},		/* WRITE_CLASS_OF_DEV	*/	{"wrLinkPolicy",	LINK_POL, 0x0d, 4, 2},		/* WRITE_LINK_POLICY	*/	{"addScoConn",		LINK_CTL, 0x07, 4, 0},		/* ADD_SCO_CONNECTION	*/	{"acceptConn",		LINK_CTL, 0x09, 7, 0},		/* ACCEPT_CONNECTION	*/	{"rdHostMac",		INFO_PAR, 0x09, 0, 6},		/* READ_HOST_MAC	*/	{"searchDev",		LINK_CTL, 0x01, 5, 0},		/* SEARCH_DEVICE	*/	{"readRemoteName",	LINK_CTL, 0x19, 10, 0},		/* READ_REMOTE_NAME	*/	{"wrPageScanTimeout",	HOST_CTL, 0x18, 2, 0},		/* WRITE_PAGESCAN_TIMEOUT*/	{"wrIConnectionTimeout",HOST_CTL, 0x18, 2, 0},		/* WRITE_INCONNECTION_TIMEOUT*/	{"setEventFilter",	HOST_CTL, 0x05, 2, 0},		/* SET_EVENT_FILTER	*/	{"eventWait",		NULL_OGF, 0x00, 0,0}		/* EVENT_WAITING	*/};HciCmd::HciCmd(enum OgfOcfT ind, char* reqopt) {	setProto(HCI);	index=ind;	if (hciCmds[index].ogf!=NULL_OGF) {		char tmp;		tmp = hciCmds[index].ocf;						compileReq(&tmp,1);		tmp = (hciCmds[index].ocf>>8)&3 | hciCmds[index].ogf<<2; 		compileReq(&tmp,1);		tmp = index==WRITE_LOCAL_NAME?strlen(reqopt):hciCmds[index].reqL; 	compileReq(&tmp,1);		if (reqopt)			compileReq(reqopt, index==WRITE_LOCAL_NAME?strlen(reqopt):req[2]);	}}HciCmd::~HciCmd() {}int HciCmd::writeReq(char* buf, int len) {	if (log && index!=EVENT_WAITING) {		Dprintf("< %s(%x,%x) ",hciCmds[index].des, req[0],req[1]);		int l;		for (l=0; (l<hciCmds[index].reqL) && (l<getReqC()-3); l++)			Dprintf(index==WRITE_LOCAL_NAME?"c":"%02x",(unsigned char)req[3+l]);	}	return HciReqRes::writeReq(buf,len);}int HciCmd::readRes(char* buf, int len) {	int ritorno=0;	int expL=6;	/* Parameter correct for 0xf */	int ogfocfC=4;	/* Parameter correct for oxf */	int statusC=2;	/* Parameter correct for 0xf */	/* 1) see if msg is our response:	 * 	(0xe, len, nPendPct, ocf,ogf, status : check ocf,ogf,status,len=expected).	 * 	(0xf, len, status, nPendCmd, ocf, ogf: check ocf,ogf,status,len=expected).	 */	if (buf[0]=='\xe' || buf[0]=='\xf') {		if (buf[0]=='\xe') {			expL+=hciCmds[index].resL;			ogfocfC=3;			statusC=5;		}		if (len>=expL) {			if (expL==(buf[1]+2) && memcmp(req,buf+ogfocfC,2)==0) {		       		ritorno=HciReqRes::readRes(buf,expL);				{					/* skip common header: E len nPendCmd ocf ogf status(?)*/					char tmp[6];					HciReqRes::scanRes(tmp,6);				}			       	/* 2) If interesting verify correctness (status=0).*/			       	if (log) {					int l;					Dprintf("> cmd%s(%02x) (%x,%x) status(%s)",buf[0]=='\xe'?"Compl":"Stat",buf[0],buf[ogfocfC],buf[ogfocfC+1],blueErrDes(buf[statusC]));					for (l=getResC(); l<expL; l++)						Dprintf("%02x",(unsigned char)res[l]);			       	}				ritorno = buf[statusC]?blue2linuxErr(buf[statusC]):ritorno;/*-EPROTO*/;		       	}		}	}	return ritorno;}void HciCmd::setPar(char* reqopt) {	memcpy(req+3,reqopt,hciCmds[index].reqL);	}/* Hci bytes produced, so communication is started by device: * HciCmd < * HciCmd > * HciEvt > */enum EvtT {	ANY_EVT=0,	NUM_COMPL_PACKET=0x13,	PINCODE_REQ=0x16,	LINKKEY_REQ,	LINKKEY_NOTIFY,	CONNECT_COMPLETE=3,	CONNECT_REQUEST,	DISCONN_COMPLETE,	SEARCH_DEVICE_END=1,	SEARCH_DEVICE_FOUND,	DEVICE_NAME=7};class HciEvt: public HciReqRes {public:	struct HciEvtT {		char* des;		enum EvtT evt;		__u8 resL;	};private:	int index;	static HciEvtT hciEvts[11];public:	HciEvt(enum EvtT ind);	~HciEvt();	int readRes(char* des, int len);	int writeReq(char* buf, int len);	virtual void evtComplete();	void copy(HciEvt& ing) {memcpy(this,&ing,sizeof(*this));}};struct HciEvt::HciEvtT HciEvt::hciEvts[]={	{"anyEvt",		ANY_EVT,		 0},	{"numComplPacket", 	NUM_COMPL_PACKET, 	 5},	{"pinCodeRequest", 	PINCODE_REQ, 		 6},	{"linkKeyRequest", 	LINKKEY_REQ, 		 6},	{"linkKeyNotify", 	LINKKEY_NOTIFY,		23},	{"connectComplete", 	CONNECT_COMPLETE, 	11},	{"connectRequest",  	CONNECT_REQUEST, 	10},	{"disconnComplete", 	DISCONN_COMPLETE, 	 4},	{"searchDevEnd",	SEARCH_DEVICE_END,	 1},	{"searchDevFound",	SEARCH_DEVICE_FOUND,	15},	{"remoteDeviceName",	DEVICE_NAME,		255},};HciEvt::HciEvt(enum EvtT ind) {	unsigned int l;	setProto(HCI);	index=-1;	for (l=0; l<sizeof(hciEvts)/sizeof(HciEvtT); l++)		if (hciEvts[l].evt==ind)			index=l;	if (index==-1)		Dprintf("\n INTERNAL ERROR! index %d !exist in hciEvts[].\n",(int)ind);//	resC=hciEvts[index].resL+2;}HciEvt::~HciEvt() {}void HciEvt::evtComplete() {Dprintf("evtComplete!!!\n");}int HciEvt::writeReq(char* buf, int len) {	return HciReqRes::writeReq(buf,len);}/* HciBus ensure that only one event@time is delivered.*/int HciEvt::readRes(char* buf, int len) {

⌨️ 快捷键说明

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