📄 obex.c
字号:
/********************************************************************** * Filename: obex.c* Version: 0.9* Description: API to be used by applications wanting to use OBEX* Status: Stable.* Author: Dag Brattli <dagb@cs.uit.no>* Created at: Sat Apr 17 16:50:25 1999* CVS ID: $Id: obex.c,v 1.47 2006/05/25 18:09:41 zany Exp $* * Copyright (c) 1999, 2000 Dag Brattli, All Rights Reserved.* 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 <string.h>#include <errno.h>#include <unistd.h>#include "obex_main.h"#include "obex_object.h"#include "obex_connect.h"#include "obex_client.h"#include "irobex.h"/*** OBEX_Init - Initialize OBEX.* @transport: Which transport to use. The following transports are available :* %OBEX_TRANS_IRDA : Use regular IrDA socket (need an IrDA stack)* %OBEX_TRANS_INET : Use regular TCP/IP socket* %OBEX_TRANS_CUSTOM : Use user provided transport* %OBEX_TRANS_BLUETOOTH: Use regular Bluetooth RFCOMM socket (need the BlueZ stack)* %OBEX_TRANS_USB: Use USB transport (libusb needed)* If you use %OBEX_TRANS_CUSTOM you must register your own* transport with OBEX_RegisterCTransport()* @eventcb: Function pointer to your event callback.* See obex.h for prototype of this callback.* @flags: Bitmask of flags. The following flags are available :* %OBEX_FL_KEEPSERVER : Keep the server alive after incomming request* %OBEX_FL_FILTERHINT : Filter target devices based on Obex hint bit* %OBEX_FL_FILTERIAS : Filter target devices based on IAS entry** Returns an OBEX handle or %NULL on error.*/obex_t *OBEX_Init(int transport, obex_event_t eventcb, unsigned int flags){ obex_t *self; DEBUG(1,"\n"); obex_return_val_if_fail(eventcb != NULL, NULL); self = malloc(sizeof(obex_t)); if (self == NULL) { DEBUG(4,"can not alloc memory\n"); return NULL; } memset(self, 0, sizeof(obex_t)); self->eventcb = eventcb; self->keepserver = (flags & OBEX_FL_KEEPSERVER) ? TRUE : FALSE; self->filterhint = (flags & OBEX_FL_FILTERHINT) ? TRUE : FALSE; self->filterias = (flags & OBEX_FL_FILTERIAS ) ? TRUE : FALSE; self->state = MODE_SRV | STATE_IDLE; /* Init transport */ self->trans.type = transport; self->trans.connected = FALSE; /* Safe values. * Both self->mtu_rx and self->mtu_tx_max can be increased by app * self->mtu_tx will be whatever the other end sneds us - Jean II */ /* Set MTU to the maximum, if using USB transport - Alex Kanavin */ self->mtu_rx = OBEX_DEFAULT_MTU; self->mtu_tx = OBEX_MINIMUM_MTU; self->mtu_tx_max = OBEX_DEFAULT_MTU; /* Allocate message buffers */ /* It's safe to allocate them smaller than OBEX_MAXIMUM_MTU * because buf_t will realloc data as needed. - Jean II */ self->rx_msg = buf_new(self->mtu_rx); if (self->rx_msg == NULL) goto out_err; self->tx_msg = buf_new(self->mtu_tx_max); if (self->tx_msg == NULL) goto out_err; return self; out_err: if (self->tx_msg != NULL) buf_free(self->tx_msg); if (self->rx_msg != NULL) buf_free(self->rx_msg); free(self); return NULL;}/*** OBEX_Cleanup - Close down an OBEX instance* @self: OBEX handle** Close down an OBEX instance.*///modify by xuganganvoid OBEX_Cleanup(obex_t *self){ obex_return_if_fail(self != NULL); obex_transport_disconnect_request(self); // obex_transport_disconnect_server(self); if (self->tx_msg) buf_free(self->tx_msg); if (self->rx_msg) buf_free(self->rx_msg); free(self);}/*** OBEX_SetUserData - Set userdata of an OBEX handle* @self: OBEX handle* @data: It's all up to you!*/void OBEX_SetUserData(obex_t *self, void * data){ obex_return_if_fail(self != NULL); self->userdata=data;}/*** OBEX_GetUserData - Read the userdata from an OBEX handle* @self: OBEX handle** Returns userdata*/void * OBEX_GetUserData(obex_t *self){ obex_return_val_if_fail(self != NULL, 0); return self->userdata;}/*** OBEX_HandleInput - Let the OBEX parser do some work* @self: OBEX handle* @timeout: Maximum time to wait in seconds** Let the OBEX parser read and process incoming data. If no data* is available this call will block.** When a request has been sent or you are waiting for an incoming server-* request you should call this function until the request has finished.** Like select() this function returns -1 on error, 0 on timeout or* positive on success.*/int OBEX_HandleInput(obex_t *self, int timeout){ DEBUG(3, "\n"); obex_return_val_if_fail(self != NULL, -1); return obex_transport_handle_input(self, timeout);}/*** OBEX_TransportDisconnect - Disconnect transport* @self: OBEX handle*/int OBEX_TransportDisconnect(obex_t *self){ DEBUG(4, "\n"); obex_return_val_if_fail(self != NULL, -1); obex_transport_disconnect_request(self); return 0;}/*** OBEX_Request - Start a request (as client)* @self: OBEX handle* @object: Object containing request** Returns negative on error.*/int OBEX_Request(obex_t *self, obex_object_t *object){ DEBUG(4, "\n"); obex_return_val_if_fail(self != NULL, -1); if (self->object) { DEBUG(1, "We are busy.\n"); return -EBUSY; } obex_return_val_if_fail(object != NULL, -1); self->object = object; self->state = STATE_START | MODE_CLI; return obex_client(self, NULL, 0);}/** OBEX_ObjectNew - Create a new OBEX Object* @self: OBEX handle* @cmd: command of object** Returns a pointer to a new OBEX Object or %NULL on error.*/obex_object_t *OBEX_ObjectNew(obex_t *self, uint8_t cmd){ obex_object_t *object; obex_return_val_if_fail(self != NULL, NULL); object = obex_object_new(); if(object == NULL) return NULL; obex_object_setcmd(object, cmd, (uint8_t) (cmd | OBEX_FINAL)); /* Need some special woodoo magic on connect-frame */ if(cmd == OBEX_CMD_CONNECT) { if(obex_insert_connectframe(self, object) < 0) { obex_object_delete(object); object = NULL; } } return object;}/*** OBEX_ObjectDelete - Delete an OBEX object* @self: OBEX handle* @object: object to delete.** Note that as soon as you have passed an object to the lib using* OBEX_Request(), you shall not delete it yourself.*/int OBEX_ObjectDelete(obex_t *self, obex_object_t *object){ obex_return_val_if_fail(object != NULL, -1); return obex_object_delete(object);}/*** OBEX_ObjectAddHeader - Attach a header to an object* @self: OBEX handle* @object: OBEX object* @hi: Header identifier* @hv: Header value* @hv_size: Header size* @flags: See obex.h for possible values** Add a new header to an object.** If you want all headers to fit in one packet, use the flag* %OBEX_FL_FIT_ONE_PACKET on all headers you add to an object.** To stream a body add a body header with hv.bs = %NULL and set the flag* %OBEX_FL_STREAM_START. You will now get %OBEX_EV_STREAMEMPTY events as* soon as the the parser wants you to feed it with more data.** When you get an %OBEX_EV_STREAMEMPTY event give the parser some data by* adding a body-header and set the flag %OBEX_EV_STREAM_DATA. When you* have no more data to send set the flag %OBEX_EV_STREAM_DATAEND instead.** After adding a header you are free to do whatever you want with the buffer* if you are NOT streaming. If you are streaming you may not touch the* buffer until you get another %OBEX_EV_STREAMEMTPY or until the request* finishes.** The headers will be sent in the order you add them.*/int OBEX_ObjectAddHeader(obex_t *self, obex_object_t *object, uint8_t hi, obex_headerdata_t hv, uint32_t hv_size, unsigned int flags){ obex_return_val_if_fail(self != NULL, -1); obex_return_val_if_fail(object != NULL, -1); return obex_object_addheader(self, object, hi, hv, hv_size, flags);}/*** OBEX_ObjectGetNextHeader - Get next available header from an object* @self: OBEX handle* @object: OBEX object* @hi: Pointer to header identifier* @hv: Pointer to hv* @hv_size: Pointer to hv_size** Returns 0 when no more headers are available.** All headers are read-only.** You will get the headers in the received order.*/int OBEX_ObjectGetNextHeader(obex_t *self, obex_object_t *object, uint8_t *hi, obex_headerdata_t *hv, uint32_t *hv_size){ obex_return_val_if_fail(self != NULL, -1); obex_return_val_if_fail(object != NULL, -1); return obex_object_getnextheader(self, object, hi, hv, hv_size);}/*** OBEX_ObjectReadStream - Read data from body stream* @self: OBEX handle* @object: OBEX object* @buf: A pointer to a pointer which this function will set to a buffer which* shall be read (and ONLY read) after this function returns.** To recieve the body as a stream call this function with buf = %NULL as soon* as you get an OBEX_EV_REQHINT event.** You will now recieve %OBEX_EV_STREAMAVAIL events when data is available* for you. Call this function to get the data.** Note! When receiving a stream data is not buffered so if you don't call this* function when you get an %OBEX_EV_STREAMAVAIL event data will be lost.** Returns the number of bytes in buffer, or 0 for end-of-stream.*/int OBEX_ObjectReadStream(obex_t *self, obex_object_t *object, const uint8_t **buf){ obex_return_val_if_fail(self != NULL, -1); obex_return_val_if_fail(object != NULL, -1); return obex_object_readstream(self, object, buf);}/*** OBEX_ObjectSetRsp - Sets the response to a received request.* @self: OBEX handle* @object: OBEX object* @rsp: Respose code in non-last packets* @lastrsp: Response code in last packet** Returns -1 on error.*/int OBEX_ObjectSetRsp(obex_object_t *object, uint8_t rsp, uint8_t lastrsp){ obex_return_val_if_fail(object != NULL, -1); return obex_object_setrsp(object, rsp, lastrsp);}/*** OBEX_UnicodeToChar - Simple unicode to char function.* @c: Destination (char)* @uc: Source (unicode)* @size: Length of destination buffer, at least half the size of source** Buffers may not overlap. Returns -1 on error.*/int OBEX_UnicodeToChar(uint8_t *c, const uint8_t *uc, int size){ int n; DEBUG(4, "\n"); obex_return_val_if_fail(uc != NULL, -1); obex_return_val_if_fail(c != NULL, -1); // Make sure buffer is big enough! for(n = 0; uc[n*2+1] != 0; n++); obex_return_val_if_fail(n < size, -1); for(n = 0; uc[n*2+1] != 0; n++) c[n] = uc[n*2+1]; c[n] = 0; return 0;}/*** OBEX_CharToUnicode - Simple char to unicode function.* @uc: Destination (unicode)* @c: Source (char)* @size: Length of destination buffer, at least twice the size of source** Buffers may not overlap. Returns -1 on error.*/int OBEX_CharToUnicode(uint8_t *uc, const uint8_t *c, int size){ int len, n; DEBUG(4, "\n"); obex_return_val_if_fail(uc != NULL, -1); obex_return_val_if_fail(c != NULL, -1); len = n = strlen((char *) c); obex_return_val_if_fail(n*2+2 <= size, -1); uc[n*2+1] = 0; uc[n*2] = 0; while(n--) { uc[n*2+1] = c[n]; uc[n*2] = 0; } return (len*2)+2 ;}/*** IrOBEX_ServerRegister - Start listening for incoming connections* @self: OBEX handle* @service: Service to bind to.** An easier server function to use for IrDA (IrOBEX) only.** Returns -1 on error.*/int IrOBEX_ServerRegister(obex_t *self, const char *service){ DEBUG(3, "\n"); obex_return_val_if_fail(self != NULL, -1); obex_return_val_if_fail(service != NULL, -1); irobex_prepare_listen(self, service); return obex_transport_listen(self); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -