--- bluez-utils-2.24/tools/hciattach.c +++ bluez-utils-2.24/tools/hciattach.c @@ -95,7 +95,7 @@ case 921600: return B921600; default: - return B57600; + return B115200; } } @@ -118,6 +118,11 @@ { int remain, r; int count = 0; + struct timeval tv = { 0, 100000 }; + fd_set watch; + + FD_ZERO(&watch); + FD_SET(fd,&watch); if (size <= 0) return -1; @@ -125,9 +130,13 @@ /* The first byte identifies the packet type. For HCI event packets, it * should be 0x04, so we read until we get to the 0x04. */ while (1) { + tv.tv_sec = 1; tv.tv_usec = 100000; + if(select(fd+1, &watch, NULL, NULL, &tv) == 0) return -1; // timeout r = read(fd, buf, 1); if (r <= 0) + { return -1; + } if (buf[0] == 0x04) break; } @@ -135,9 +144,13 @@ /* The next two bytes are the event code and parameter total length. */ while (count < 3) { + tv.tv_sec = 1; tv.tv_usec = 100000; + if(select(fd+1, &watch, NULL, NULL, &tv) == 0) return -1; // timeout r = read(fd, buf + count, 3 - count); if (r <= 0) + { return -1; + } count += r; } @@ -148,6 +161,8 @@ remain = size - 3; while ((count - 3) < remain) { + tv.tv_sec = 1; tv.tv_usec = 100000; + if(select(fd+1, &watch, NULL, NULL, &tv) == 0) return -1; // timeout r = read(fd, buf + count, remain - (count - 3)); if (r <= 0) return -1; @@ -203,12 +218,273 @@ /* * Infineon specific initialization */ + +static int infineon_manufacturer_mode(int fd, unsigned char enable) +{ + unsigned char cmd[10], resp[HCI_MAX_EVENT_SIZE]; + struct timeval tv = { 1, 0 }; + fd_set watch; + int retval, j; + + cmd[0] = HCI_COMMAND_PKT; + cmd[1] = 0x11; + cmd[2] = 0xfc; + cmd[3] = 0x02; + cmd[4] = enable; // Enable + cmd[5] = 0x00; // No reset + if(write(fd, cmd, 6) != 6) { + perror("Failed to write command to enter manufacturer mode"); + return -1; + } + + FD_ZERO(&watch); + FD_SET(fd,&watch); + tv.tv_sec = 1; tv.tv_usec = 0; + retval = select(fd+1, &watch, NULL, NULL, &tv); + + if(retval == -1) + { + perror("select() failed"); + return -1; + } else if(retval == 0) { + printf("No response from BT module\n"); + return -1; + } else { + retval = read_hci_event(fd, resp, HCI_MAX_EVENT_SIZE); + if (retval < 0) { + perror("Error reading response"); + return -1; + } else if(retval == (1+6)) { + if(resp[1] = 0x0e && resp[4] == cmd[1] && resp[5] == cmd[2] && resp[6] == 0x0) // Command completed OK + { + return 0; + } else { + perror("Manufacturer mode change failed"); + for(j=0; jspeed) { + case 9600: + cmd[4] = 0x00; + break; + case 19200: + cmd[4] = 0x01; + break; + case 38400: + cmd[4] = 0x02; + break; + case 57600: + cmd[4] = 0x03; + break; + case 115200: + cmd[4] = 0x04; + break; + case 230400: + cmd[4] = 0x05; + break; + case 460800: + cmd[4] = 0x06; + break; + case 921600: + cmd[4] = 0x07; + break; + case 1843200: + cmd[4] = 0x08; // not possible on gumstix + printf("Speed too high: setting to 115200 instead\n"); + default: + cmd[4] = 0x04; + u->speed = 115200; + break; + } + + /* Send initialization command */ + if(write(fd, cmd, 5) != 5) { + perror("Failed to write init command"); + return -1; + } + + FD_ZERO(&watch); + FD_SET(fd,&watch); + tv.tv_sec = 1; tv.tv_usec = 0; + retval = select(fd+1, &watch, NULL, NULL, &tv); + + if(retval == -1) + { + perror("select() failed"); + return -1; + } else if(retval == 0) { + printf("No response from BT module\n"); + return -1; + } else { + retval = read_hci_event(fd, resp, HCI_MAX_EVENT_SIZE); + if (retval < 0) { + perror("Error reading response"); + return -1; + } else if(retval == (1+6)) { + if(resp[1] == 0x0f && resp[3] == 0x00 & resp[5] == cmd[1] && resp[6] == cmd[2]) // Command status OK + { + printf("Set_UART_Baudrate accepted\n"); + } else { + printf("Set_UART_Baudrate rejected\n"); + for(j=0; jspeed) < 0) + { + perror("Can't change baud rate"); + return -1; + } + + FD_ZERO(&watch); + FD_SET(fd,&watch); + tv.tv_sec = 1; tv.tv_usec = 0; + retval = select(fd+1, &watch, NULL, NULL, &tv); + + if(retval == -1) + { + perror("select() failed"); + return -1; + } else if(retval == 0) { + printf("No response from BT module\n"); + return -1; + } else { + retval = read_hci_event(fd, resp, HCI_MAX_EVENT_SIZE); + if (retval < 0) { + perror("Error reading response"); + return -1; + } else if(retval == 5) { + if(resp[1] = 0xff && resp[3] == 0x12 && resp[4] == 0x0) // Command completed OK + { + printf("Set_UART_Baudrate completed\n"); + } else { + perror("Set_UART_Baudrate failed"); + for(j=0; jspeed != u->init_speed) { - printf("Can't yet change speed for infineon module. Will stay at %d baud\n", u->init_speed); + // First need to detect which kind of infineon module we're dealing with here... + // PBA31307 and PBA31308 both have a command OGF=0x3f,OCF=0x0005 which returns version info + // PBA31307 returns: PBA31308 retunrs: + // Status 0x00 1 byte Status 0x00 + // LM-FW-Version 0x5nnn 2 bytes HW-Platform, HW-Variant 0x37,0x03 + // BB-FW-Version 0x05nn 2 bytes Hw-Revision, FW-Variant 0xnn,0x03 + // 1 byte FW-Revision 0xnn + // 3 bytes FW-Build 0xYMDDnn + // 1 byte FW-Patch 0xnn + // + // So the PBA31308 returns 10 bytes, PBA31307 returns only 5 bytes. We can distinguish at byte #2 though, + // but need to continue reading to empty the buffer. + + cmd[0] = HCI_COMMAND_PKT; + cmd[1] = 0x05; // Infineon_Read_Version(PBA31308) or Infineon_Read_SW_Version(PBA31307) + cmd[2] = 0xfc; + cmd[3] = 0x00; + + if(write(fd, cmd, 4) != 4) { + perror("Failed to write Infineon_Read(_SW)_Version command"); + return -1; + } + + FD_ZERO(&watch); + FD_SET(fd,&watch); + tv.tv_sec = 1; tv.tv_usec = 0; + retval = select(fd+1, &watch, NULL, NULL, &tv); + + if(retval == -1) + { + perror("select() failed"); + return -1; + } else if(retval == 0) { + printf("No response from BT module\n"); + return -1; + } else { + retval = read_hci_event(fd, resp, HCI_MAX_EVENT_SIZE); + if (retval < 0) { + printf("Error (or timeout) reading response\n"); + return -1; + } else if(retval == (10+6)) { // Possiby PBA31308 + if(resp[6] == 0x0 && resp[7] == 0x37 && resp[8] == 0x03) // PBA31308 confirmed + { + // Now we can change baudrate + return pba31308(fd, u, ti); + } else { + printf("Not a PBA31308\n"); + for(j=0; jinit_speed); u->speed = u->init_speed; + } else { + printf("Not a PBA31307\n"); + for(j=0; j /proc/gpio/GPIO7"); @@ -785,8 +1062,9 @@ { fd_set watch; struct timeval tv = { 1, 0 }; + unsigned char cmd[10], resp[HCI_MAX_EVENT_SIZE]; - int baudrates[] = { 57600, 115200, 921600 }; + int baudrates[] = { u->init_speed, 921600, 115200, 57600 }; int old_alarm = alarm(20); // Extend timeout int i, j, retval;