Модераторы: xvr
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Програмирование Bluetooth, bluez, obex 
V
    Опции темы
smalcom
Дата 18.10.2006, 11:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 494
Регистрация: 16.10.2004
Где: Dnepr

Репутация: нет
Всего: 7



Не могу разобраться с передачей файлов на телефон с компа. Пробовал использовать Bluez, через hci_connect подсоединяюсь, но незнаю как передать файл. OBEX пишет ошибки - незнаю как правильно заполнить структура sockaddr для connect(errno=22). obexftp ваще страно себя ведет и нехочет со мной сотрудничать.

Система Deepstyle(Slackware 10.2)
Стоят либы dbus, bluez, obex.


--------------------
What DA F...???
PM MAIL WWW Skype Jabber   Вверх
kirjanov
Дата 18.10.2006, 12:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 326
Регистрация: 22.1.2006
Где: Dark wood of erro r

Репутация: 3
Всего: 15



smalcom, код в студию, а там разберемся  smile 
PM MAIL   Вверх
smalcom
Дата 18.10.2006, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 494
Регистрация: 16.10.2004
Где: Dnepr

Репутация: нет
Всего: 7



Код

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
//#include <obexftp/obexftp.h>
//#include <obexftp/client.h>
//#include <obexftp/uuid.h>
#include <openobex/obex.h>
#include <openobex/obex_const.h>

#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>

#define DEBUG

using namespace std;

extern int errno;
char *device = "hci0";
int transport = OBEX_TRANS_BLUETOOTH;
int channel = 1;
obex_t *self = NULL;
char *str_mac_vis = "00:16:20:D3:42:39";
struct sockaddr *saddr;

static void bt_event_func(obex_t *handle, obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp)
{
    (void) handle;
    (void) object;
    (void) mode;
    (void) event;
    (void) obex_cmd;
    (void) obex_rsp;
}

int get_peer_addr(char *name, struct sockaddr_in *peer)
{
        struct hostent *host;
        u_long inaddr;

        /* Is the address in dotted decimal? */
        if ((inaddr = inet_addr(name)) != INADDR_NONE) {
                memcpy((char *) &peer->sin_addr, (char *) &inaddr,
                      sizeof(inaddr));
        }
        else {
                if ((host = gethostbyname(name)) == NULL) {
                        printf( "Bad host name: ");
                        exit(-1);
                }
                memcpy((char *) &peer->sin_addr, host->h_addr,
                                host->h_length);
        }
        return 0;
}

int main(int argc, char *argv[])
{
int ret;

    saddr = new sockaddr;
    saddr->sa_family = AF_BLUETOOTH;
    for(uint i = 0; i < 14; i++) saddr->sa_data[i] = 0x00;
    saddr->sa_data[0] = 0x00;
    saddr->sa_data[1] = 0x16;
    saddr->sa_data[2] = 0x20;
    saddr->sa_data[3] = 0xD3;
    saddr->sa_data[4] = 0x42;
    saddr->sa_data[5] = 0x39;
    printf("Init...");
    self = OBEX_Init(transport, bt_event_func, 0);
    if(self == NULL)
    {
        printf("failed.errno=%i\n", errno);
        return (-1);
    };
    printf("success\n");
    printf("Connect to %s...", str_mac_vis);

    ret = OBEX_TransportConnect(self, saddr, sizeof(struct sockaddr));//здесь происходит ошипка и errno = 22
    if(ret < 0)
    {
        printf("failed.errno=%i\n", errno);
        return (-1);
    };
    printf("success\n");
    //send cmd OBEX_connect
    //send cmd OBEX_disconnect
//    OBEX_TransportDisconnect();
//    printf("Using BT: %s (%d)\n", device, channel);
    printf("Cleanup OBEX\n");
    OBEX_Cleanup(self);
    return 0;
}


скачал kbluetooth буду разбираца када принесут синезубое тело


--------------------
What DA F...???
PM MAIL WWW Skype Jabber   Вверх
kirjanov
Дата 20.10.2006, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 326
Регистрация: 22.1.2006
Где: Dark wood of erro r

Репутация: 3
Всего: 15



ты, скорее всего, неправильно инициализируешь *saddr. Попробуй функцию BtOBEX_TransportConnect вместо OBEX_TransportConnect. Может поможет  smile 
PM MAIL   Вверх
smalcom
Дата 29.10.2006, 01:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 494
Регистрация: 16.10.2004
Где: Dnepr

Репутация: нет
Всего: 7



все сделал када отлажу если возникнет необходимость могу кинуть исходники


--------------------
What DA F...???
PM MAIL WWW Skype Jabber   Вверх
Dimonius
Дата 10.11.2006, 02:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 11.10.2006

Репутация: нет
Всего: 1



Цитата(smalcom @ 29.10.2006,  01:10)
все сделал када отлажу если возникнет необходимость могу кинуть исходники

если отладил можешь скидывать. (поучусь на примерах)
попутно можно дать ссылки на документацию по Bluetooth. Мне нужно написать приложение, которое будет работать через блютуз между двумя наладонниками - игра на двоих (морской бой).
На девайсах стоит дебиан.
PM MAIL   Вверх
smalcom
Дата 10.11.2006, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 494
Регистрация: 16.10.2004
Где: Dnepr

Репутация: нет
Всего: 7



Доки - сорцы bluez и openobex  smile 

даю код(обобщать облом потому даю так как он записан у меня)


Код

//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...???
PM MAIL WWW Skype Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr.

 
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема »


 




[ Время генерации скрипта: 0.0540 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.