
Опытный
 
Профиль
Группа: Участник
Сообщений: 494
Регистрация: 16.10.2004
Где: Dnepr
Репутация: нет Всего: 7
|
Доки - сорцы bluez и openobex даю код(обобщать облом потому даю так как он записан у меня) | Код | //bluetooth.cpp extern CSettings m_settings;
static int chgl;
struct context4obex { int serverdone; int clientdone; char *get_name; /* Name of last get-request */ };
/* Pass args to the inquiry/search handler */ struct context4sdp { char *svc; /* Service */ uuid_t group; /* Browse group */ uint32_t handle; /* Service record handle */ };
struct context4obex global_context = {0, 0, NULL};
#define RESP_WAIT 0x00 #define RESP_FAIL 0x01 #define RESP_SUCCESS 0x02 int global_resp;
#define OBEX_STREAM_CHUNK 4096 uint8_t buffer[OBEX_STREAM_CHUNK]; int fileDesc; uint progress;
int fillstream(obex_t *handle, obex_object_t *object); void client_done(obex_t *handle, obex_object_t *object, int obex_cmd, int obex_rsp); // void connect_client_done(obex_t *handle, obex_object_t *object, int obex_rsp); // void disconnect_client_done(obex_t *handle, obex_object_t *object, int obex_rsp);
// // Wait for an obex command to finish. // int syncwait(obex_t *handle) { int ret; struct context4obex *gt;
global_resp = RESP_WAIT; gt = (struct context4obex*)OBEX_GetUserData(handle); if(gt == NULL) return RV_ERR; progress = 0; while(!gt->clientdone) { ret = OBEX_HandleInput(handle, 10); if(ret < 0) { return RV_ERR; }; };
gt->clientdone = false; return RV_OK; }
static void bt_event_func(obex_t *handle, obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp) { switch(event) { case OBEX_EV_PROGRESS: break; case OBEX_EV_ABORT: break; case OBEX_EV_REQDONE: client_done(handle, object, obex_cmd, obex_rsp); break; case OBEX_EV_LINKERR: client_done(handle, object, obex_cmd, obex_rsp); break; case OBEX_EV_STREAMEMPTY: fillstream(handle, object); break; default: printf("Unknown event %02x!\n", event); break; }; }
int fillstream(obex_t *handle, obex_object_t *object) { int actual; obex_headerdata_t hv;
actual = read(fileDesc, buffer, OBEX_STREAM_CHUNK);
if(actual > 0) { /* Read was ok! */ m_settings.operation_data[OP_TRANSMITED] += actual; hv.bs = buffer; OBEX_ObjectAddHeader(handle, object, OBEX_HDR_BODY, hv, actual, OBEX_FL_STREAM_DATA); } else if(actual == 0) { /* EOF */ hv.bs = buffer; close(fileDesc); fileDesc = -1; OBEX_ObjectAddHeader(handle, object, OBEX_HDR_BODY, hv, 0, OBEX_FL_STREAM_DATAEND); } else { /* Error */ hv.bs = NULL; close(fileDesc); fileDesc = -1; OBEX_ObjectAddHeader(handle, object, OBEX_HDR_BODY, hv, 0, OBEX_FL_STREAM_DATA); };
return actual; }
// // // void client_done(obex_t *handle, obex_object_t *object, int obex_cmd, int obex_rsp) { struct context4obex *gt; gt = (struct context4obex*)OBEX_GetUserData(handle);
switch(obex_cmd) { case OBEX_CMD_CONNECT: if(obex_rsp == OBEX_RSP_SUCCESS) global_resp = RESP_SUCCESS; else global_resp = RESP_FAIL; break; case OBEX_CMD_DISCONNECT: if(obex_rsp == OBEX_RSP_SUCCESS) global_resp = RESP_SUCCESS; else global_resp = RESP_FAIL; break; case OBEX_CMD_PUT: if(obex_rsp == OBEX_RSP_SUCCESS) global_resp = RESP_SUCCESS; else global_resp = RESP_FAIL; break; }; gt->clientdone = true; }
// // Get the filesize in a "portable" way // int get_filesize(const char *filename) { struct stat stats;
/* Need to know the file length */ stat(filename, &stats); return (int) stats.st_size; }
// // Read a file and alloc a buffer for it // uint8_t* easy_readfile(const char *filename, int *file_size) { int actual; int fd; uint8_t *buf;
*file_size = get_filesize(filename);
fd = open(filename, O_RDONLY, 0); if(fd == -1) { return NULL; }; if(!(buf = (uint8_t*)malloc(*file_size))) { return NULL; }; actual = read(fd, buf, *file_size); close(fd);
*file_size = actual; m_settings.operation_data[OP_FULLSIZE] = *file_size; return buf; }
static void print_service_desc(void *value, void *user) { char str[MAX_LEN_PROTOCOL_UUID_STR]; sdp_data_t *p = (sdp_data_t *)value; int i = 0, proto = 0; static char UUID_str[MAX_LEN_UUID_STR];
for (; p; p = p->next, i++) { switch (p->dtd) { case SDP_UUID16: case SDP_UUID32: case SDP_UUID128: sdp_uuid2strn(&p->val.uuid, UUID_str, MAX_LEN_UUID_STR); sdp_proto_uuid2strn(&p->val.uuid, str, sizeof(str)); proto = sdp_uuid_to_proto(&p->val.uuid); break; case SDP_UINT8: if (proto == RFCOMM_UUID) chgl = p->val.uint8; else chgl = -1; break; case SDP_UINT16: break; case SDP_SEQ16: break; case SDP_SEQ8: break; default: printf(" FIXME: dtd=0%x\n", p->dtd); break; } } }
static void print_access_protos(void *value, void *userData) { sdp_list_t *protDescSeq = (sdp_list_t *)value; sdp_list_foreach(protDescSeq, print_service_desc, 0); }
/* * Search for a specific SDP service */ static int do_search(bdaddr_t* bdaddr, struct context4sdp* context_do) { sdp_list_t *attrid, *search, *seq, *next; uint32_t range = 0x0000ffff; sdp_session_t *sess; bdaddr_t anyddr; sdp_list_t *proto = 0;
chgl = -1; str2ba("00:00:00:00:00:00", &anyddr); sess = sdp_connect(&anyddr, bdaddr, SDP_RETRY_IF_BUSY);
attrid = sdp_list_append(0, &range); search = sdp_list_append(0, &context_do->group); if(sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE, attrid, &seq)) { sdp_close(sess); return RV_ERR; }; sdp_list_free(attrid, 0); sdp_list_free(search, 0);
for (; seq; seq = next) { sdp_record_t *rec = (sdp_record_t*)seq->data;
if(sdp_get_access_protos(rec, &proto) == 0) { sdp_list_foreach(proto, print_access_protos, 0); sdp_list_foreach(proto, (sdp_list_func_t)sdp_list_free, 0); sdp_list_free(proto, 0); }; next = seq->next; free(seq); sdp_record_free(rec); }; sdp_close(sess); if(chgl == -1) return RV_ERR; else return RV_OK; }
CBluetooth::CBluetooth() : QThread() { self = NULL; inited = false; connected = false; transport = OBEX_TRANS_BLUETOOTH; channel = 5; fileDesc = -1; global_context.clientdone = 0; global_context.serverdone = 0; global_context.get_name = NULL; }
CBluetooth::~CBluetooth() { }
uint CBluetooth::Init() { self = OBEX_Init(transport, bt_event_func, 0); if(self == NULL) { inited = false; return RV_ERR; }; OBEX_SetUserData(self, &global_context);
inited = true; return RV_OK; }
void CBluetooth::Close() { OBEX_Cleanup(self); }
uint CBluetooth::Inquiry(uint *num) { int num_rsp = 0; int length = 8;// ~10 seconds int flags = 0; int dd; char name[249]; uint8_t lap[3] = {0x33, 0x8b, 0x9e}; _rsp temp_rsp; inquiry_info *info = NULL;
num_rsp = hci_inquiry(m_settings.hci_device, length, num_rsp, lap, &info, flags); if(num_rsp < 0) return RV_ERR; if(num_rsp == 0) { *num = 0; return RV_OK; }; dd = hci_open_dev(m_settings.hci_device); if(dd < 0) return RV_ERR; *num = num_rsp; for(uint i = 0; i < num_rsp; i++) { memset(name, 0, sizeof(name)); if(hci_read_remote_name_with_clock_offset(dd, &(info+i)->bdaddr, (info+i)->pscan_rep_mode, (info+i)->clock_offset | 0x8000, sizeof(name), name, 100000) < 0) continue; temp_rsp.mac = (info + i)->bdaddr; temp_rsp.name = name; rl.push_back(temp_rsp); }; return RV_OK; }
uint CBluetooth::Connect(uint rsp_num) { int ret; obex_object_t *object; obex_headerdata_t hd; bdaddr_t anyddr;
if(rsp_num >= rl.size()) return RV_ERR; str2ba("00:00:00:00:00:00", &anyddr); connected = false; if(!inited) return RV_ERR; //browse for OBEX service ret = GetObexChannel(rsp_num); if(ret != RV_OK) return RV_ERR; //transport connect ret = BtOBEX_TransportConnect(self, &anyddr, &rl.at(rsp_num).mac, channel); if(ret < 0) return RV_ERR; //sending connect request if(!(object = OBEX_ObjectNew(self, OBEX_CMD_CONNECT))) return RV_ERR; //filling who header hd.bs = (uint8_t *) "SiMBox"; if(OBEX_ObjectAddHeader(self, object, OBEX_HDR_WHO, hd, 6, OBEX_FL_FIT_ONE_PACKET) < 0) { OBEX_ObjectDelete(self, object); return RV_ERR; }; OBEX_Request(self, object); ret = syncwait(self);
if(ret != RV_OK || global_resp != RESP_SUCCESS) { OBEX_TransportDisconnect(self); return RV_ERR; }; connected = true; return RV_OK; }
void CBluetooth::Disconnect() { obex_object_t *object = NULL;
object = OBEX_ObjectNew(self, OBEX_CMD_DISCONNECT); if(object != NULL) { OBEX_Request(self, object); syncwait(self); }; OBEX_TransportDisconnect(self); connected = false; }
uint CBluetooth::Send(const QString &fn) { uint8_t *buf, *unicodename; char *fname; char *bfname; int body_size, name_size, uname_size, ret; obex_object_t *object = NULL; obex_headerdata_t hd;
if(!connected) return RV_ERR; filename = fn; //preparing file fname = new char[filename.length()]; strcpy(fname, (const char*)QFile::encodeName(filename)); bfname = strdup(basename(fname)); buf = easy_readfile(fname, &body_size); if(buf == NULL) return RV_ERR; fileDesc = open(fname, O_RDONLY, 0); if(fileDesc < 0) { free(buf); free(bfname); return RV_ERR; }; //sending object = OBEX_ObjectNew(self, OBEX_CMD_PUT); if(object == NULL) return RV_ERR; //Creating unicode name <--------------------------------------- name_size = strlen(bfname) + 1; uname_size = name_size * 2; unicodename = new uint8_t[uname_size]; if((ret = OBEX_CharToUnicode(unicodename, (const uint8_t*)bfname, uname_size)) < 0) { delete unicodename; return RV_ERR; }; // Add unicode name header <--------------------------------------- hd.bs = unicodename; OBEX_ObjectAddHeader(self, object, OBEX_HDR_NAME, hd, uname_size, 0); delete unicodename; // Add length header <--------------------------------------- hd.bq4 = body_size; OBEX_ObjectAddHeader(self, object, OBEX_HDR_LENGTH, hd, sizeof(hd.bq4), 0); // Add body header <--------------------------------------- hd.bs = NULL; OBEX_ObjectAddHeader(self, object, OBEX_HDR_BODY, hd, 0, OBEX_FL_STREAM_START);
if(OBEX_Request(self, object) < 0) { delete object; return RV_ERR; }; start(); return RV_OK; }
uint CBluetooth::GetName(QString *name, uint num) { if(num < rl.size()) { *name = rl[num].name; return RV_OK; }; return RV_ERR; }
void CBluetooth::run() { int ret;
status = BT_PROGRESS; ret = syncwait(self); status = BT_STOP; if(ret != RV_OK || global_resp != RESP_SUCCESS) last_err = RV_ERR; else last_err = RV_OK; Disconnect(); m_settings.operation_data[OP_TRANSMITED] = 1; m_settings.operation_data[OP_FULLSIZE] = 1; }
uint CBluetooth::GetObexChannel(uint rsp_num) { struct context4sdp context_sdp; uint16_t sv_class = 0;
// Initialise context memset(&context_sdp, '\0', sizeof(struct context4sdp)); sv_class = 0x1105; sdp_uuid16_create(&context_sdp.group, sv_class); if((do_search(&rl.at(rsp_num).mac, &context_sdp) == RV_OK) && (chgl != -1)) { channel = chgl; return RV_OK; }; return RV_ERR; }
|
| Код | //bluetooth.h /** @author smalcom */
struct _rsp { QString name; bdaddr_t mac; };
class CBluetooth : public QThread { private: uint nor; std::vector<_rsp> rl; bool inited; obex_t *self; int transport; int channel; QString filename;
public: bool connected; uint status; uint last_err; uint Init(); uint Inquiry(uint *num); uint GetName(QString *name, uint num); uint Connect(uint rsp_num); void Disconnect(); uint Send(const QString &fn); uint GetObexChannel(uint rsp_num); uint GetProgress(); void Close();
virtual void run();
CBluetooth(); ~CBluetooth(); };
|
и как его использовать | Код | //scanning for remote devices void ScanBT() { uint num = 0;
if(m_bluetooth.Inquiry(&num) != RV_OK) { //error return; }; if(num == 0) { //no responders found return; }; // m_bluetooth.GetName(get_responder_name, num_of_responder); m_bluetooth.GetName(&name, i); return; }
//sending file void CMainPanel::SendViaBT() { if(m_bluetooth.Connect(responder_name) == RV_OK) { m_settings.operation_data[OP_TRANSMITED] = 0; bt_lab->setText(codec->toUnicode(m_settings.bt_label.text) + QString::number(m_settings.operation_data[OP_TRANSMITED]) + codec->toUnicode(" из ") + QString::number(m_settings.operation_data[OP_FULLSIZE])); bt_lab->show(); if(m_bluetooth.Send(bt_path) != RV_OK) goto send_end1; return; }; send_end1:
m_bluetooth.Disconnect(); //error }
//1second timer funcion void Iter() { if(bt_lab->isVisible()) { bt_lab->setText(codec->toUnicode(m_settings.bt_label.text) + QString::number(uint(100 * m_settings.operation_data[OP_TRANSMITED] / m_settings.operation_data[OP_FULLSIZE])) + codec->toUnicode("% из ") + QString::number(m_settings.operation_data[OP_FULLSIZE])); if(m_settings.operation_data[OP_TRANSMITED] >= m_settings.operation_data[OP_FULLSIZE]) bt_lab->hide(); }; }
|
Будут вопросы - попробуем решить
--------------------
What DA F...???
|