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

📄 blue.cpp

📁 blue-usu: (Search, Connect, Playback, Record) with bluetooth devices like headset. Rely on usu dr
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	int ritorno=0;	int optL=hciEvts[index].resL;	unsigned char* ubuf = (unsigned char*)buf;	/* 1) see if msg is our response. */	if ((len-2)==ubuf[1]) {		if (hciEvts[index].evt==ANY_EVT || (buf[0]==hciEvts[index].evt && (optL==ubuf[1]))) {			ritorno=HciReqRes::readRes(buf,ubuf[1]+2);			scanRes(buf,2);			if (hciEvts[index].evt==ANY_EVT)				evtComplete();			/* 2) If interesting verify correctness (status=0).*/			if (log) {				int l;				Dprintf("> %s(%02x)",hciEvts[index].des,buf[0]);				for (l=0; l<ubuf[1]; l++)					Dprintf("%02x",(unsigned char)res[2+l]);				switch (hciEvts[index].evt) {					case DISCONN_COMPLETE:						Dprintf(" reason(%s)",blueErrDes(res[5]));					case CONNECT_COMPLETE:						Dprintf(" status(%s)",blueErrDes(res[2]));						ritorno=res[2]?blue2linuxErr(res[2]):ritorno;					default:						break;				}			}		}	}	return ritorno;}enum L2capCode {	NO_CODE=0,	COMMAND_REJ=1,	CONNECT_REQ,	CONNECT_RES,	CONFIG_REQ,	CONFIG_RES,	DISCONN_REQ,	DISCONN_RES,	ECHO_REQ,	ECHO_RES,	INFO_REQ,	INFO_RES,};struct L2capCmdEvt{	L2capCode code;	int len;};class HciL2cap: public HciReqRes {	static char hciH;	static L2capCmdEvt l2capCmdEvt[11];	static char req_ident;	static char res_ident;		L2capCode code;	int remL;public:	HciL2cap(char cid, L2capCode code, char* opt, int optl=-1);	~HciL2cap();	int readRes(char* des, int len);	int writeReq(char* buf, int len);	void copy(HciL2cap& ing) {memcpy(this,&ing,sizeof(*this));}		static void setHciHandle(char newHhciH);	static void setReqNumber(char reqn);	static char getReqNumber();};char HciL2cap::hciH='\x0';char HciL2cap::req_ident=0;char HciL2cap::res_ident=0;L2capCmdEvt HciL2cap::l2capCmdEvt[]={	{COMMAND_REJ, 	0},	{CONNECT_REQ, 	4},	{CONNECT_RES, 	8},	{CONFIG_REQ,  	8},	{CONFIG_RES,  	6},	{DISCONN_REQ, 	4},	{DISCONN_RES, 	4},	{ECHO_REQ,	0},	{ECHO_RES,	0},	{INFO_REQ,	0},	{INFO_RES,	0},};void HciL2cap::setHciHandle(char newHciH) {	hciH=newHciH;}void HciL2cap::setReqNumber(char number) {	req_ident=number;}char HciL2cap::getReqNumber() {	return req_ident;}HciL2cap::~HciL2cap() {}HciL2cap::HciL2cap(char cid, L2capCode cod, char* opt, int optl): code(cod) {	setProto(L2CAP);	HciReqRes::compileReq(&hciH,1);	HciReqRes::compileReq("\x20",1);	remL=0;	unsigned int l;	int optL=optl;	for (l=0; (l<sizeof(l2capCmdEvt)/sizeof(L2capCmdEvt)) && (optL==-1); l++)		if (l2capCmdEvt[l].code==code)			optL=l2capCmdEvt[l].len;	if (optL!=-1) {		char codechar=(char)code;		char optLc=(char) optL + 4/*len,cid*/ + 4 /*code,ident,len*/;		HciReqRes::compileReq(&optLc, 1);		HciReqRes::compileReq("\x00", 1);		optLc-=4;		HciReqRes::compileReq(&optLc, 1);		HciReqRes::compileReq("\x00", 1);		HciReqRes::compileReq(&cid,1);		HciReqRes::compileReq("\x00",1);		if (codechar!=NO_CODE) {			char ident;			if (codechar%2) {				res_ident++;				ident=res_ident;			} else {				req_ident++;				ident=req_ident;			}			HciReqRes::compileReq(&codechar,1);			HciReqRes::compileReq(&ident,1);			optLc-=4;			HciReqRes::compileReq(&optLc, 1);			HciReqRes::compileReq("\x00", 1);		}		if (opt && optL)			HciReqRes::compileReq(opt, optL);	} else if (code!=NO_CODE)		Dprintf("L2cap::L2cap() code=%d !found.",code);}int HciL2cap::writeReq(char* buf, int len) {	if (log) {		Dprintf("< L2CAP:");		int l;		for (l=0; (l<getReqC()); l++)			Dprintf("%02x",(unsigned char)req[l]);	}	return HciReqRes::writeReq(buf,len);}/*  * L2CAP	  ACL            L2CAP *  ACL		28 20 0C 00	08 00  01 00  ... *		|   |   |	 len	cid *       (handle)   |   | * 		(flag)  | * 		      (len) *  * When >1 packet is generated4anL2CAPmsg, we have this situation: * 	 ACLlen=18  | L2CAPlen=14 * 	28 20 11 00 | 0e 00 41 ... * 	28 10 01 00 | aa * * Same packet sometimes is generated with 1 frame: * 	 ACLlen=18  | L2CAPlen=14 * 	28 20 12 00 | 0e 00 41 ... * * In first case, the second frame can be linked to first only thank to ACL level, so we expect that * every non first frame are related to last frame in same direction. * */ int HciL2cap::readRes(char* buf, int len) {	int ritorno=0;	unsigned char* ubuf=(unsigned char*) buf;	if (buf[0]==hciH) {		/* 		 * If start frame, remain on,		 *    middle frame, remain on,		 *    end frame, turn off.		 */		ritorno=HciReqRes::readRes(buf,len);		if (log) {			int l;			Dprintf("> L2CAP:");			for (l=0; l<len; l++)				Dprintf("%02x",(unsigned char)res[l]);		}		if (remL==0)			remL=ubuf[4]+(ubuf[5]<<8);		remL-=(ritorno-8);		if (remL>0) {			Dprintf("(!complete packet,remain=%d)",remL);			/*requestOn=true*/;		} if (remL<0)			Dprintf("(corrupted packet!remL=%d!)",remL);		if (buf[8]==CONNECT_RES && buf[16]==1 && buf[18]==2) {			Dprintf("(auth pending, reschedule same event)");			setDone(false);		}	}	return ritorno;}HciBus::HciBus() {	memset(this,0,sizeof(*this));#ifdef USE_PROC_FS	fdCommand=open("/proc/USBDo/intr",O_WRONLY,0666);	fdEvent	 =open("/proc/USBDo/intr",O_RDONLY,0666);	fdDataAsync=open("/proc/USBDo/bulk",O_RDWR,0666);/*	fdDataSync =open("/proc/USBDo/isoc",O_RDWR,0666);*/#else	fdCommand=open("/dev/usu_intr",O_WRONLY,0666);	fdEvent	 =open("/dev/usu_intr",O_RDONLY,0666);	fdDataAsync=open("/dev/usu_bulk",O_RDWR,0666);#endif	lastPduL=MAX_PDU_LEN;	lastPduC=0;	lastPdu = new char[MAX_PDU_LEN];}HciBus::~HciBus() {	if (fdCommand>0) close(fdCommand);	if (fdEvent>0) close(fdEvent);	if (fdDataAsync>0) close(fdDataAsync);	if (fdDataSync>0) close(fdDataSync);	int l,ritorno=0;	for (l=0; l<MAX_PENDING_CMD; l++)		if (hcireqres[l]) {			Dprintf("HciBus::clear() found obj!!!\n");			/*hcireqres[l].detach()~HciReqRes()*/;			hcireqres[l]=NULL;			ritorno++;		}	delete lastPdu;}void onMessageDestroy(void* hb, HciReqRes& hcirr) {	((HciBus*)hb)->clear(hcirr);}int HciBus::schedule(HciReqRes& hcirr,char classe) {	int ritorno=-ENOSPC;	int l,la,lb;//	if (hcirr.done()) return -EBADMSG;	la=(classe=='a')?0:MAX_PENDING_CMD_CLASSA;	lb=(classe=='a')?  MAX_PENDING_CMD_CLASSA:MAX_PENDING_CMD;	for (l=la; (l<lb) && (ritorno<0); l++)		if (hcireqres[l]==NULL || hcireqres[l]->done())			ritorno=l;	if (ritorno>=0) {		hcireqres[ritorno]=&hcirr;//		fb=(void (*) (HciReqRes&)) &HciBus::onMessageDestroy;		hcirr.atExit(this,onMessageDestroy);		/*		hcireqres[ritorno].detach();		hcireqres[ritorno].copy(hcirr);		hcireqres[ritorno].attach();		*/		ritorno=hcirr.writeReq(lastPdu, lastPduL);		if (ritorno>0) { /* So event can pass through this function.*/			lastPduC=ritorno;			ritorno=hcirr.getProto()==HciReqRes::HCI?writeHci(fdCommand):writeHci(fdDataAsync);		}	}	if (log && ritorno!=0) Dprintf("\tscheduled(%s=%s)\n",ritorno>=0?"bytes":"err",linuxErrDes(ritorno));	return ritorno;}int HciBus::writeHci(char* cmddata,int cmddataLen) {	if (cmddataLen>lastPduL)		return -ENOSPC;	memcpy(lastPdu,cmddata,cmddataLen);	lastPduC=cmddataLen;	return writeHci(fdCommand);}int HciBus::writeHci(int fd) {	int ritorno=0;	int nVolte=0;	while (ritorno>=0 && lastPduC>0 && nVolte<10 && fd>=0) {		ritorno=write(fd,lastPdu,lastPduC);		if (ritorno>=0) lastPduC-=ritorno;		if (nVolte) {			struct timespec ts;			ts.tv_sec=0;			ts.tv_nsec=1000*100; /* 100 msec.*/			nanosleep(&ts,0);		}		nVolte++;	}	if (nVolte==10 || fd==-1) ritorno=-ENODEV;	return ritorno;}/* In one cycle we read msg & deliver. * * Return 0 if 0 bytes was readed form hciFd, * 	 >0 if wee read a valid msg & is being accepted, without error, by someone. * 	 <0 (msg decode with error -EBADMSG) | (msg !accepted by so -ESRCH) | (msg accepted with error) */int HciBus::hci_readEvt() {	return readHci(HciReqRes::HCI);}int HciBus::l2cap_readEvt() {	return readHci(HciReqRes::L2CAP);}/* readMsg() read {hci,l2cap} pdu (so we found hci,l2cap header) * 	     for l2cap put only header from first packet, so user level can recognize multipacket. */int HciBus::readMsg(HciReqRes::ProtoT proto) {	int ritorno=0;	bool done=false;	int nPacket=0;	int lastPduCkp1=0;	unsigned char* ulastPdu = (unsigned char*)lastPdu;	/* Header & msg.*/	int currFd	=(proto==HciReqRes::HCI)?fdEvent:fdDataAsync;;	int hdrLen	=(proto==HciReqRes::HCI)?2:4;	int pduLen;	/* Overwrite lastPdu.*/	lastPduC=0;	while (ritorno>=0 && !done) {		/* HCI Event:		L2CAP Event:		 * id len		    ACL	    |   L2CAP		 * 13 0B ...		28 20 12 00 | 0e 00 41 ... 		 * 			       len     len		 *  hdrlen=2		hdrlen=4		 *  len@pdu[1]		len@pdu[2:3]		 *		 *  1) Read header,		 */		if (proto==HciReqRes::L2CAP || (proto==HciReqRes::HCI && nPacket==0)) {			ritorno=currFd!=-1?read(currFd,lastPdu+lastPduC,hdrLen):-ENODEV;			if (proto==HciReqRes::HCI || (proto==HciReqRes::L2CAP && nPacket==0))				lastPduCkp1+=hdrLen;			nPacket++;		}		/*  2) Read remaining bytes of protocol {HCI,ACL}. */		if (ritorno==hdrLen) {			pduLen=ulastPdu[hdrLen>>1]; 			/* HCI len.	*/			if (proto==HciReqRes::L2CAP)				pduLen+=ulastPdu[(hdrLen>>1)+1]<<8;	/* ACL len.	*/			while (ritorno>=0 && pduLen>0) {				ritorno=read(currFd,lastPdu+lastPduCkp1,pduLen);				if (ritorno>0) {					pduLen-=ritorno;					lastPduCkp1+=ritorno;				}				if (ritorno==0) {					static int nTime=0;					if (nTime<100) {						struct timespec ts;						ts.tv_sec=0;						ts.tv_nsec=1<<20; /* about 1ms.*/						nanosleep(&ts,0);						nTime++;					} else {						ritorno = -ETIMEDOUT;						if (log)							Dprintf("> msg timedout while reconstruct msg of len(%d/%d)!",lastPduCkp1,pduLen+lastPduCkp1);					}				}			}		} else if (ritorno>0) {			if (log)				Dprintf("(ERR!: can't read atomically header)");			ritorno=-EBADMSG;		}		if (ritorno>=0) {			done = true;			if (ritorno>0 && proto==HciReqRes::L2CAP) {				int l2capLen=ulastPdu[4]+(ulastPdu[5]<<8);				Dprintf("l2cap (desLen,readedLen)=(%d,%d)",l2capLen,lastPduCkp1-8);				if (l2capLen<4) {					if (log)						Dprintf("(ERR!:L2CAP msg have len<4 (len=%d))",l2capLen);				} else if (l2capLen>lastPduCkp1-8) {					done=false;					if (log)						Dprintf("(L2CAP msg have other %d bytes)",l2capLen-(lastPduCkp1-8));				} else if (l2capLen<lastPduCkp1-8) {					if (log)						Dprintf("(ERR!:bad L2CAP msg: ACL len > L2CAP len)");					ritorno = -EBADMSG;					done = false;				}			}		}	}	if (ritorno>0) {		lastPduC=lastPduCkp1;		ritorno =lastPduCkp1;	}	return ritorno;}/* If any pending message, we complete in this routine. * The problem is that if we have: *  <- ReadA *  <- ReadRemoteName *  -> 16 bytes *  -> 16 bytes *  -> N bytes (ReadA) *  -> 16 bytes *  -> 16 bytes * It is difficult to recognize readRemoteName PDU against response (F 4 ...) * For now we serialize. */int HciBus::readHci(HciReqRes::ProtoT proto) {	/* 	 * Read entire msg.  Hci seem to prefere serial beh.

⌨️ 快捷键说明

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