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

📄 hciattach.c

📁 基于LINUX内核驱动的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
		}		if (!memcmp(bcspp, bcspsync, 4)) {			len = write(fd, &bcsp_sync_resp_pkt,10);		} else if (!memcmp(bcspp, bcspsyncresp, 4))			break;	}	/* State = curious */	alarm(0);	sa.sa_handler = bcsp_tconf_sig_alarm;	sigaction(SIGALRM, &sa, NULL);	alarm(1);	while (1) {		do {			if (read_check(fd, &byte, 1) == -1){				perror("Failed to read");				return -1;			}		} while (byte != 0xC0);		do {			if (read_check(fd, &bcsph[0], 1) == -1){				perror("Failed to read");				return -1;			}		} while (bcsph[0] == 0xC0);		if (read_check(fd, &bcsph[1], 3) == -1){			perror("Failed to read");			return -1;		}		if (((bcsph[0] + bcsph[1] + bcsph[2]) & 0xFF) != (unsigned char)~bcsph[3])			continue;		if (bcsph[1] != 0x41 || bcsph[2] != 0x00)			continue;		if (read_check(fd, &bcspp, 4) == -1){			perror("Failed to read");			return -1;		}		if (!memcmp(bcspp, bcspsync, 4))			len = write(fd, &bcsp_sync_resp_pkt, 10);		else if (!memcmp(bcspp, bcspconf, 4))			len = write(fd, &bcsp_conf_resp_pkt, 10);		else if (!memcmp(bcspp, bcspconfresp,  4))			break;	}	/* State = garrulous */	return 0;}/*  * CSR specific initialization  * Inspired strongly by code in OpenBT and experimentations with Brainboxes * Pcmcia card. * Jean Tourrilhes <jt@hpl.hp.com> - 14.11.01 */static int csr(int fd, struct uart_t *u, struct termios *ti){	struct timespec tm = {0, 10000000};	/* 10ms - be generous */	unsigned char cmd[30];		/* Command */	unsigned char resp[30];		/* Response */	int  clen = 0;		/* Command len */	static int csr_seq = 0;	/* Sequence number of command */	int  divisor;	/* It seems that if we set the CSR UART speed straight away, it	 * won't work, the CSR UART gets into a state where we can't talk	 * to it anymore.	 * On the other hand, doing a read before setting the CSR speed	 * seems to be ok.	 * Therefore, the strategy is to read the build ID (useful for	 * debugging) and only then set the CSR UART speed. Doing like	 * this is more complex but at least it works ;-)	 * The CSR UART control may be slow to wake up or something because	 * every time I read its speed, its bogus...	 * Jean II */	/* Try to read the build ID of the CSR chip */	clen = 5 + (5 + 6) * 2;	/* HCI header */	cmd[0] = HCI_COMMAND_PKT;	cmd[1] = 0x00;		/* CSR command */	cmd[2] = 0xfc;		/* MANUFACTURER_SPEC */	cmd[3] = 1 + (5 + 6) * 2;	/* len */	/* CSR MSG header */	cmd[4] = 0xC2;		/* first+last+channel=BCC */	/* CSR BCC header */	cmd[5] = 0x00;		/* type = GET-REQ */	cmd[6] = 0x00;		/* - msB */	cmd[7] = 5 + 4;		/* len */	cmd[8] = 0x00;		/* - msB */	cmd[9] = csr_seq & 0xFF;/* seq num */	cmd[10] = (csr_seq >> 8) & 0xFF;	/* - msB */	csr_seq++;	cmd[11] = 0x19;		/* var_id = CSR_CMD_BUILD_ID */	cmd[12] = 0x28;		/* - msB */	cmd[13] = 0x00;		/* status = STATUS_OK */	cmd[14] = 0x00;		/* - msB */	/* CSR BCC payload */	memset(cmd + 15, 0, 6 * 2);	/* Send command */	do {		if (write(fd, cmd, clen) != clen) {			perror("Failed to write init command (GET_BUILD_ID)");			return -1;		}		/* Read reply. */		if (read_hci_event(fd, resp, 100) < 0) {			perror("Failed to read init response (GET_BUILD_ID)");			return -1;		}	/* Event code 0xFF is for vendor-specific events, which is 	 * what we're looking for. */	} while (resp[1] != 0xFF);#ifdef CSR_DEBUG	{	char temp[512];	int i;	for (i=0; i < rlen; i++)		sprintf(temp + (i*3), "-%02X", resp[i]);	fprintf(stderr, "Reading CSR build ID %d [%s]\n", rlen, temp + 1);	// In theory, it should look like :	// 04-FF-13-FF-01-00-09-00-00-00-19-28-00-00-73-00-00-00-00-00-00-00	}#endif	/* Display that to user */	fprintf(stderr, "CSR build ID 0x%02X-0x%02X\n", 		resp[15] & 0xFF, resp[14] & 0xFF);	/* Try to read the current speed of the CSR chip */	clen = 5 + (5 + 4)*2;	/* -- HCI header */	cmd[3] = 1 + (5 + 4)*2;	/* len */	/* -- CSR BCC header -- */	cmd[9] = csr_seq & 0xFF;	/* seq num */	cmd[10] = (csr_seq >> 8) & 0xFF;	/* - msB */	csr_seq++;	cmd[11] = 0x02;		/* var_id = CONFIG_UART */	cmd[12] = 0x68;		/* - msB */#ifdef CSR_DEBUG	/* Send command */	do {		if (write(fd, cmd, clen) != clen) {			perror("Failed to write init command (GET_BUILD_ID)");			return -1;		}		/* Read reply. */		if (read_hci_event(fd, resp, 100) < 0) {			perror("Failed to read init response (GET_BUILD_ID)");			return -1;		}	/* Event code 0xFF is for vendor-specific events, which is 	 * what we're looking for. */	} while (resp[1] != 0xFF);	{	char temp[512];	int i;	for (i=0; i < rlen; i++)		sprintf(temp + (i*3), "-%02X", resp[i]);	fprintf(stderr, "Reading CSR UART speed %d [%s]\n", rlen, temp+1);	}#endif	if (u->speed > 1500000) {		fprintf(stderr, "Speed %d too high. Remaining at %d baud\n", 			u->speed, u->init_speed);		u->speed = u->init_speed;	} else if (u->speed != 57600 && uart_speed(u->speed) == B57600) {		/* Unknown speed. Why oh why can't we just pass an int to the kernel? */		fprintf(stderr, "Speed %d unrecognised. Remaining at %d baud\n",			u->speed, u->init_speed);		u->speed = u->init_speed;	}	if (u->speed == u->init_speed)		return 0;	/* Now, create the command that will set the UART speed */	/* CSR BCC header */	cmd[5] = 0x02;			/* type = SET-REQ */	cmd[6] = 0x00;			/* - msB */	cmd[9] = csr_seq & 0xFF;	/* seq num */	cmd[10] = (csr_seq >> 8) & 0xFF;/* - msB */	csr_seq++;	divisor = (u->speed*64+7812)/15625;	/* No parity, one stop bit -> divisor |= 0x0000; */	cmd[15] = (divisor) & 0xFF;		/* divider */	cmd[16] = (divisor >> 8) & 0xFF;	/* - msB */	/* The rest of the payload will be 0x00 */#ifdef CSR_DEBUG	{	char temp[512];	int i;	for(i = 0; i < clen; i++)		sprintf(temp + (i*3), "-%02X", cmd[i]);	fprintf(stderr, "Writing CSR UART speed %d [%s]\n", clen, temp + 1);	// In theory, it should look like :	// 01-00-FC-13-C2-02-00-09-00-03-00-02-68-00-00-BF-0E-00-00-00-00-00-00	// 01-00-FC-13-C2-02-00-09-00-01-00-02-68-00-00-D8-01-00-00-00-00-00-00	}#endif	/* Send the command to set the CSR UART speed */	if (write(fd, cmd, clen) != clen) {		perror("Failed to write init command (SET_UART_SPEED)");		return -1;	}	nanosleep(&tm, NULL);	return 0;}/*  * Silicon Wave specific initialization  * Thomas Moser <thomas.moser@tmoser.ch> */static int swave(int fd, struct uart_t *u, struct termios *ti){	struct timespec tm = { 0, 500000 };	char cmd[10], rsp[100];	int r;	// Silicon Wave set baud rate command	// see HCI Vendor Specific Interface from Silicon Wave	// first send a "param access set" command to set the	// appropriate data fields in RAM. Then send a "HCI Reset	// Subcommand", e.g. "soft reset" to make the changes effective.	cmd[0] = HCI_COMMAND_PKT;	// it's a command packet	cmd[1] = 0x0B;			// OCF 0x0B	= param access set		cmd[2] = 0xfc;			// OGF bx111111 = vendor specific	cmd[3] = 0x06;			// 6 bytes of data following	cmd[4] = 0x01;			// param sub command	cmd[5] = 0x11;			// tag 17 = 0x11 = HCI Transport Params	cmd[6] = 0x03;			// length of the parameter following	cmd[7] = 0x01;			// HCI Transport flow control enable	cmd[8] = 0x01;			// HCI Transport Type = UART	switch (u->speed) {	case 19200:		cmd[9] = 0x03;		break;	case 38400:		cmd[9] = 0x02;		break;	case 57600:		cmd[9] = 0x01;		break;	case 115200:		cmd[9] = 0x00;		break;	default:		u->speed = 115200;		cmd[9] = 0x00;		break;	}	/* Send initialization command */	if (write(fd, cmd, 10) != 10) {		perror("Failed to write init command");		return -1;	}	// We should wait for a "GET Event" to confirm the success of 	// the baud rate setting. Wait some time before reading. Better:  	// read with timeout, parse data 	// until correct answer, else error handling ... todo ...	nanosleep(&tm, NULL);	r = read(fd, rsp, sizeof(rsp));	if (r > 0) {		// guess it's okay, but we should parse the reply. But since		// I don't react on an error anyway ... todo		// Response packet format:		//  04	Event		//  FF	Vendor specific		//  07	Parameter length		//  0B	Subcommand		//  01	Setevent		//  11	Tag specifying HCI Transport Layer Parameter		//  03	length		//  01	flow on		//  01 	Hci Transport type = Uart		//  xx	Baud rate set (see above)	} else {		// ups, got error.		return -1;	}	// we probably got the reply. Now we must send the "soft reset"	// which is standard HCI RESET.	cmd[0] = HCI_COMMAND_PKT;	// it's a command packet	cmd[1] = 0x03;	cmd[2] = 0x0c;	cmd[3] = 0x00;	/* Send reset command */	if (write(fd, cmd, 4) != 4) {		perror("Can't write Silicon Wave reset cmd.");		return -1;	}	nanosleep(&tm, NULL);	// now the uart baud rate on the silicon wave module is set and effective.	// change our own baud rate as well. Then there is a reset event comming in 	// on the *new* baud rate. This is *undocumented*! The packet looks like this:	// 04 FF 01 0B (which would make that a confirmation of 0x0B = "Param 	// subcommand class". So: change to new baud rate, read with timeout, parse	// data, error handling. BTW: all param access in Silicon Wave is done this way.	// Maybe this code would belong in a seperate file, or at least code reuse...	return 0;}/* * ST Microelectronics specific initialization * Marcel Holtmann <marcel@holtmann.org> */static int st(int fd, struct uart_t *u, struct termios *ti){	struct timespec tm = {0, 50000};	char cmd[5];	/* ST Microelectronics set baud rate command */	cmd[0] = HCI_COMMAND_PKT;	cmd[1] = 0x46;			// OCF = Hci_Cmd_ST_Set_Uart_Baud_Rate	cmd[2] = 0xfc;			// OGF = Vendor specific	cmd[3] = 0x01;	switch (u->speed) {	case 9600:		cmd[4] = 0x09;		break;	case 19200:		cmd[4] = 0x0b;		break;	case 38400:		cmd[4] = 0x0d;		break;	case 57600:		cmd[4] = 0x0e;		break;	case 115200:		cmd[4] = 0x10;		break;	case 230400:		cmd[4] = 0x12;		break;	case 460800:		cmd[4] = 0x13;		break;	case 921600:		cmd[4] = 0x14;		break;	default:		cmd[4] = 0x10;		u->speed = 115200;		break;	}	/* Send initialization command */	if (write(fd, cmd, 5) != 5) {		perror("Failed to write init command");		return -1;	}	nanosleep(&tm, NULL);	return 0;}extern int stlc2500_init(int fd, bdaddr_t *bdaddr);static int stlc2500(int fd, struct uart_t *u, struct termios *ti){	bdaddr_t bdaddr;	unsigned char resp[10];	int n;	int rvalue;	/* STLC2500 has an ericsson core */	rvalue = ericsson(fd, u, ti);	if (rvalue != 0)		return rvalue;#ifdef STLC2500_DEBUG	fprintf(stderr, "Setting speed\n");#endif	if (set_speed(fd, ti, u->speed) < 0) {		perror("Can't set baud rate");		return -1;	}#ifdef STLC2500_DEBUG	fprintf(stderr, "Speed set...\n");#endif	/* Read reply */	if ((n = read_hci_event(fd, resp, 10)) < 0) {		fprintf(stderr, "Failed to set baud rate on chip\n");		return -1;	}#ifdef STLC2500_DEBUG	for (i = 0; i < n; i++) {		fprintf(stderr, "resp[%d] = %02x\n", i, resp[i]);	}#endif	str2ba(u->bdaddr, &bdaddr);	return stlc2500_init(fd, &bdaddr);}extern int bgb2xx_init(int fd, bdaddr_t *bdaddr);static int bgb2xx(int fd, struct uart_t *u, struct termios *ti){	bdaddr_t bdaddr;	str2ba(u->bdaddr, &bdaddr);	return bgb2xx_init(fd, &bdaddr);}/* * Broadcom specific initialization * Extracted from Jungo openrg */static int bcm2035(int fd, struct uart_t *u, struct termios *ti){	int n;	unsigned char cmd[30], resp[30];	/* Reset the BT Chip */	memset(cmd, 0, sizeof(cmd));	memset(resp, 0, sizeof(resp));	cmd[0] = HCI_COMMAND_PKT;	cmd[1] = 0x03;	cmd[2] = 0x0c;	cmd[3] = 0x00;	/* Send command */	if (write(fd, cmd, 4) != 4) {		fprintf(stderr, "Failed to write reset command\n");

⌨️ 快捷键说明

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