/* bton - tell tapisrv to turn on Bluetooth chip. Copyright (C) Ho Ming Shun cyph at cyph.ath.cx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED. */ /* * Apparently, ezx_bt tells tapisrv to enable the bluetooth chip when it starts up through * some kind of binary RPC protocol. tapisrv will use an AT command (AT+EBTP=1) to powerup * bluetooth!! (what the hell does bluetooth got to do with the GSM module??) * * This program is created by running strace output through a Vim macro :) * * Based on observations of other users, it seems tapisrv returns the BD_ADDR to be programmed * into the bluetooth chip. bton will take this BD_ADDR and write it into /tmp/bd_addr * in the format that dload expects. */ /* * Modificado por Fábio Belavenuto <belavenuto@gmail> para funcionar no A1200 */ //#define DEBUG 1 #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/ioctl.h> #include <asm/ioctls.h> #define END 0 #define WRITE 1 #define READ 2 #define OPENTTY 3 #define BDADDR 4 #define MAX_DATA 12 struct rw_op { char op; unsigned char data[MAX_DATA]; int len; }; struct rw_op tapi_ops_on[] = { { WRITE, {0x02, 0x81, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00}, 8 }, { WRITE, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}, 12 }, { READ, {0x02, 0x81, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, 8 }, { READ, {0x00, 0x00, 0x00, 0x00}, 4 }, { WRITE, {0x11, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 8 }, { READ, {0x11, 0x86, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00}, 8 }, { BDADDR, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 10 }, { WRITE, {0x13, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 8 }, { READ, {0x13, 0x86, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, 8 }, { READ, {0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff}, 8 }, { END }, }; struct rw_op tapi_ops_off[] = { { WRITE, {0x02, 0x81, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00}, 8 }, { WRITE, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 12 }, { READ, {0x02, 0x81, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, 8 }, { READ, {0x00, 0x00, 0x00, 0x00}, 4 }, { END }, }; char bdaddr[13]; void read_write(int fd, struct rw_op ops[]); void read_bdaddr(int fd); void dump(unsigned char *start, int len); int main(int argc, char **argv) { int tapisock; int startchip=1; struct sockaddr_un tapiaddr; unsigned short pid; char cmdline[255]; /* shutdown */ if (argc > 1 && strcmp(argv[1], "-s") == 0) { startchip=0; } if((tapisock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { perror("cannot create socket"); exit(1); } tapiaddr.sun_family = AF_UNIX; strcpy(tapiaddr.sun_path, "/tmp/tapisock"); if(connect(tapisock, (struct sockaddr*)&tapiaddr, sizeof(tapiaddr.sun_family) + strlen(tapiaddr.sun_path))) { perror("cannot connect"); //exit(1); } #ifdef DEBUG printf("Connected. Starting read/write\n"); #endif pid = getpid(); tapi_ops_on[1].data[0] = (char)(pid & 0xFF); tapi_ops_on[1].data[1] = (char)((pid >> 8) & 0xFF); tapi_ops_off[1].data[0] = (char)((pid) & 0xFF); tapi_ops_off[1].data[1] = (char)(((pid) >> 8) & 0xFF); if (startchip) { //read_write(tapisock, tapi_ops_on); unsigned short state; int ret, fd; fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY); ret = ioctl(fd, TIOC_BT_VOLTAGE_OFF, &state); printf("OFF: %d, %d\n",ret, state); usleep(200000); ioctl(fd, TIOC_BT_VOLTAGE_ON, &state); printf("ON: %d, %d\n", ret, state); close(fd); sprintf(cmdline, "/usr/SYSbt/mbtdload /dev/ttyS1 1 921600 0009DD502319 1 0 -1", bdaddr); #ifdef DEBUG printf("Executando %s\n", cmdline); #endif system(cmdline); } else read_write(tapisock, tapi_ops_off); close(tapisock); return 0; } void read_write(int fd, struct rw_op ops[]) { struct rw_op *curr = ops; char buf[MAX_DATA]; int readlen; while(curr->op != END) { switch(curr->op) { case WRITE: #ifdef DEBUG printf("Writing %02d bytes: ", curr->len); dump(curr->data, curr->len); printf("\n"); #endif if(write(fd, curr->data, curr->len) < 0) { perror("write failed"); exit(1); } break; case READ: #ifdef DEBUG printf("Reading %02d bytes: \n", curr->len); #endif readlen = 0; while(readlen != curr->len) { if((readlen += read(fd, buf + readlen, curr->len - readlen)) < 0) { perror("read failed"); } } #ifdef DEBUG printf("Read : "); dump(buf, curr->len); printf("\n"); printf("Expecting : "); dump(curr->data, curr->len); printf("\n"); #endif if(memcmp(curr->data, buf, curr->len)) { perror("read wrong"); } break; case BDADDR: #ifdef DEBUG printf("Reading BD ADDR:\n"); #endif readlen = 0; while(readlen != curr->len) { if((readlen += read(fd, buf + readlen, curr->len - readlen)) < 0) { perror("read failed"); } } #ifdef DEBUG printf("Read : "); dump(buf, curr->len); printf("\n"); #endif sprintf(bdaddr, "%02x%02x%02x%02x%02x%02x", buf[4], buf[5], buf[6], buf[7], buf[8], buf[9]); break; } curr++; } } #ifdef DEBUG void dump(unsigned char *start, int len) { int i; for(i = 0; i < len; i++) { printf("%02x ", (unsigned int)start[i]); } } #endif