📄 obex_test_cable.c
字号:
/********************************************************************* * * Filename: obex_test_cable.c * Version: 0.6 * Description: OBEX over a serial port in Linux. * Can be used with an Ericsson R320s phone. * Status: Experimental. * Author: Pontus Fuchs <pontus.fuchs@tactel.se> * Created at: Wed Nov 17 22:05:16 1999 * CVS ID: $Id: obex_test_cable.c,v 1.21 2006/01/18 13:02:14 holtmann Exp $ * * Copyright (c) 1999, 2000 Pontus Fuchs, All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * ********************************************************************/#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <stdlib.h>#include <sys/time.h>#include <sys/ioctl.h>#include <fcntl.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <termios.h>#include <openobex/obex.h>#include "obex_test_cable.h"#define TRUE 1#define FALSE 0static void cobex_cleanup(struct cobex_context *gt, int force);/*#define TTBT "AT*TTBT=0001EC4AF6E7\r"*///// Send an AT-command and return back one line of answer if any.// To read a line without sending anything set cmd as NULL// (this function should be rewritten!)//int cobex_do_at_cmd(struct cobex_context *gt, char *cmd, char *rspbuf, int rspbuflen, int timeout){ fd_set ttyset; struct timeval tv; int fd; char *answer = NULL; char *answer_end = NULL; unsigned int answer_size; char tmpbuf[100] = {0,}; int actual; int total = 0; int done = 0; CDEBUG("\n"); fd = gt->ttyfd; rspbuf[0] = 0; if(fd < 0) return -1; if(cmd != NULL) { // Write command int cmdlen; cmdlen = strlen(cmd); CDEBUG("Sending command %s\n", cmd); if(write(fd, cmd, cmdlen) < cmdlen) { perror("Error writing to port"); return -1; } } while(!done) { FD_ZERO(&ttyset); FD_SET(fd, &ttyset); tv.tv_sec = timeout; tv.tv_usec = 0; if(select(fd+1, &ttyset, NULL, NULL, &tv)) { actual = read(fd, &tmpbuf[total], sizeof(tmpbuf) - total); if(actual < 0) return actual; total += actual;// printf("tmpbuf=%d: %s\n", total, tmpbuf); /* Answer didn't come within the length of the buffer. Cancel! */ if(total == sizeof(tmpbuf)) return -1; if( (answer = index(tmpbuf, '\n')) ) { // Remove first line (echo) if( (answer_end = index(answer+1, '\n')) ) { // Found end of answer done = 1; } } } else { /* Anser didn't come in time. Cancel */ CDEBUG("Timeout waiting for answer\n"); return -1; } }// printf("buf:%08lx answer:%08lx end:%08lx\n", tmpbuf, answer, answer_end);// printf("Answer: %s\n", answer); // Remove heading and trailing \r if((*answer_end == '\r') || (*answer_end == '\n')) answer_end--; if((*answer_end == '\r') || (*answer_end == '\n')) answer_end--; if((*answer == '\r') || (*answer == '\n')) answer++; if((*answer == '\r') || (*answer == '\n')) answer++;// printf("Answer: %s\n", answer); answer_size = (answer_end) - answer +1;// printf("Answer size=%d\n", answer_size); if( (answer_size) >= rspbuflen ) return -1; strncpy(rspbuf, answer, answer_size); rspbuf[answer_size] = 0; return 0;}//// Open serial port and if we are using an r320, set it in OBEX-mode.//static int cobex_init(struct cobex_context *gt){ char rspbuf[200]; CDEBUG("\n"); if( (gt->ttyfd = open(gt->portname, O_RDWR | O_NONBLOCK | O_NOCTTY, 0)) < 0 ) { perror("Can' t open tty"); return -1; } tcgetattr(gt->ttyfd, >->oldtio); bzero(>->newtio, sizeof(struct termios)); gt->newtio.c_cflag = B115200 | CS8 | CREAD | CRTSCTS; gt->newtio.c_iflag = IGNPAR; gt->newtio.c_oflag = 0; tcflush(gt->ttyfd, TCIFLUSH); tcsetattr(gt->ttyfd, TCSANOW, >->newtio); // If we don't speak to an R320s we are happy here. if(!gt->r320) return 1; // Set up R320s phone in OBEX mode. if(cobex_do_at_cmd(gt, "ATZ\r", rspbuf, sizeof(rspbuf), 1) < 0) { printf("Comm-error sending ATZ\n"); goto err; }#ifdef TTBT /* Special BT-mode */ if(cobex_do_at_cmd(gt, TTBT, rspbuf, sizeof(rspbuf), 10) < 0) { printf("Comm-error sending AT*TTBT\n"); goto err; } if(strcasecmp("OK", rspbuf) != 0) { printf("Error doing AT*TTBT (%s)\n", rspbuf); goto err; }#endif if(strcasecmp("OK", rspbuf) != 0) { printf("Error doing ATZ (%s)\n", rspbuf); goto err; } if(cobex_do_at_cmd(gt, "AT*EOBEX\r", rspbuf, sizeof(rspbuf), 1) < 0) { printf("Comm-error sending AT*EOBEX\n"); goto err; } if(strcasecmp("CONNECT", rspbuf) != 0) { printf("Error doing AT*EOBEX (%s)\n", rspbuf); goto err; } return 1;err: cobex_cleanup(gt, TRUE); return -1;}//// Close down. If force is TRUE. Try to break out of OBEX-mode.//static void cobex_cleanup(struct cobex_context *gt, int force){ if(force) { // Send a break to get out of OBEX-mode#ifdef TCSBRKP if(ioctl(gt->ttyfd, TCSBRKP, 0) < 0) {#elif defined(TCSBRK) if(ioctl(gt->ttyfd, TCSBRK, 0) < 0) {#else if(tcsendbreak(gt->ttyfd, 0) < 0) {#endif /* TCSBRKP */ printf("Unable to send break!\n"); } } close(gt->ttyfd); gt->ttyfd = -1;}//// Open up cable OBEX//struct cobex_context * cobex_open(const char *port, int r320){ struct cobex_context *gt; CDEBUG("\n"); gt = malloc(sizeof(struct cobex_context)); if (gt == NULL) return NULL; memset(gt, 0, sizeof(struct cobex_context)); gt->ttyfd = -1; gt->portname = port; gt->r320 = r320; return gt;}//// Close down cable OBEX.//void cobex_close(struct cobex_context *gt){ free(gt);} //// Do transport connect or listen//int cobex_connect(obex_t *handle, void * userdata){ struct cobex_context *gt; CDEBUG("\n"); gt = userdata; if(gt->ttyfd >= 0) { CDEBUG("fd already exist. Using it\n"); return 1; } if(cobex_init(gt) < 0) return -1; return 1;}//// Do transport disconnect//int cobex_disconnect(obex_t *handle, void * userdata){ char rspbuf[20]; struct cobex_context *gt; CDEBUG("\n"); gt = userdata; /* The R320 will send back OK after OBEX disconnect */ if(gt->r320) { CDEBUG("R320!!!\n"); if(cobex_do_at_cmd(gt, NULL, rspbuf, sizeof(rspbuf), 1) < 0) printf("Comm-error waiting for OK after disconnect\n"); else if(strcasecmp(rspbuf, "OK") != 0) printf("Excpected OK after OBEX diconnect got %s\n", rspbuf); #ifdef TTBT sleep(2); if(cobex_do_at_cmd(gt, "---", rspbuf, sizeof(rspbuf), 5) < 0) printf("Comm-error Sending ---\n"); else if(strcasecmp(rspbuf, "DISCONNECT") != 0) printf("Error waiting for DISCONNECT (%s)\n", rspbuf); sleep(2);#endif } cobex_cleanup(gt, FALSE); return 1;}//// Called when data needs to be written//int cobex_write(obex_t *handle, void * userdata, uint8_t *buffer, int length){ struct cobex_context *gt; int actual; CDEBUG("\n"); gt = userdata; actual = write(gt->ttyfd, buffer, length); CDEBUG("Wrote %d bytes (expected %d)\n", actual, length); return actual;}//// Called when more data is needed.//int cobex_handle_input(obex_t *handle, void * userdata, int timeout){ int actual; struct cobex_context *gt; struct timeval time; fd_set fdset; int ret; CDEBUG("\n"); gt = userdata; /* Return if no fd */ if(gt->ttyfd < 0) { CDEBUG("No fd!"); return -1; } time.tv_sec = timeout; time.tv_usec = 0; FD_ZERO(&fdset); FD_SET(gt->ttyfd, &fdset); ret = select(gt->ttyfd+1, &fdset, NULL, NULL, &time); /* Check if this is a timeout (0) or error (-1) */ if (ret < 1) { return ret; CDEBUG("Timeout or error (%d)\n", ret); } actual = read(gt->ttyfd, >->inputbuf, sizeof(gt->inputbuf)); if(actual <= 0) return actual; CDEBUG("Read %d bytes\n", actual);#ifdef CABLE_DEBUG { int i = 0; for(i=0;i<actual;i++) { printf("[%0X",gt->inputbuf[i]); if(gt->inputbuf[i] >= 32) { printf(",%c",gt->inputbuf[i]); } printf("]"); } printf("\n"); }#endif OBEX_CustomDataFeed(handle, (uint8_t *) gt->inputbuf, actual); return actual;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -