SDP client for myBlueUSB

Dependents:   mbed_TANK_Kinect ftusbClass

sdp.h

Committer:
networker
Date:
2011-04-07
Revision:
2:d5a27b2d2e08
Parent:
1:70ee392bcfd4
Child:
3:e8d2ebb7392e

File content as of revision 2:d5a27b2d2e08:

#ifndef SDP_H
#define SDP_H
#include "AvailableMemory.h"
#include <map>
#define OFFSET  8

class SDPManager;
extern SDPManager SDP;
typedef map<unsigned short, sdp_data*> serv_rec;

void attribHandler(serv_rec *r);

//TODO: add support for multiple connections
//TODO: add server support, now only client
//at the moment, SDP can handle only one connection at a time
class SDPManager: public SocketHandler {
    int _l2cap;
    int sdp_socket; //at the moment the only socket
    unsigned char l2cap_buf[100+OFFSET];
    unsigned char* buf;
    unsigned txid;
    unsigned char contState[17];//maximum size, in practive it is 3
    unsigned char *contBuf;
    unsigned byteCount;
    int _state;
    sdp_data *tree;//root of the entire service tree
    map<unsigned, serv_rec*> services;//the set of supported services <handle, service>
    map<unsigned, serv_rec*>::iterator index;
public:
    SDPManager(): _l2cap(0), txid(1), tree(0) {
        ErrorResponse=errorhandler;
        ServiceSearchResponse=0;
        ServiceAttributeResponse=attribHandler;
        ServiceSearchAttributeResponse=0;
        buf = l2cap_buf+OFFSET;
        contBuf = 0;
        byteCount = 0;
        contState[0] = 0;
        _state = 0;
    }

    void Clear() {
        for (index = services.begin(); index != services.end(); index++) {//for all services
            for (serv_rec::iterator it = index->second->begin(); it != index->second->end(); it++)//for all attributes
                delete it->second; //delete the attribute value tree
            delete (*index).second; //delete the attribute list
        }
        services.clear();//and empty the services list
    }

    //Called as: Socket_Open(SOCKET_SDP, addr, callback, userdata(this))
    virtual int Open(SocketInternal* sock, SocketAddrHdr* addr) {
        L2CAPAddr* ad = (L2CAPAddr*)addr;
        if (_l2cap) {
            printf("This SDP supports only one connection at a time\n");
            return 0;
        }
        //BD_ADDR* a = &ad->bdaddr;
        sdp_socket = sock->ID;
        ad->psm = L2CAP_PSM_SDP;//open the l2cap channel
        _l2cap = Socket_Open(SOCKET_L2CAP, addr, OnSdpRsp, this);//this is the socket between SDP and the L2CAP layer
        if (_l2cap <= 0) {
            printf("Opening L2CAP channel failed\n");
            return _l2cap;
        }
        printf("Successfully opened L2CAP channel for SDP on socket %d\n", _l2cap);
        return sock->ID;
    }

    virtual int Send(SocketInternal* sock, const u8* data, int len) {
        printf("SDPManager::Send should not be called directly\n");
        return Socket_Send(_l2cap, data, len);
    }

    virtual int Close(SocketInternal* sock) {
        Clear();
        printf("SDP socket %d and L2CAP socket %d closed, freemem=%d\n", sock->ID, _l2cap, AvailableMemory(1));
        int retval = Socket_Close(_l2cap);//could also keep it open for the next connection
        _l2cap = 0;
        return retval;
    }

    virtual char* Name() {
        return "SDPManager SocketHandler";
    }

    void OnSdpRsp(const u8* data, int len);
    //this function is called when the L2CAP layer receives SDP packets (see SDPManager::Open), userdata is the sdpmanager instance
    static void OnSdpRsp(int socket, SocketState state, const u8* data, int len, void* userData) {
        printf("\x1B[%dm", 35);
//        printf("OnSdpRsp(socket=%d, state=%d, len=%d)\n", socket, state, len);
        printf("OnSdpRsp(socket=%d, state=%d, len=%d, freemem=%d\n", socket, state, len, AvailableMemory(1));
        SDPManager *self = (SDPManager*)userData;
        if (state == SocketState_Open) {
            self->OnSdpRsp(data, len);
        }
        printf("\x1B[%dm", 0);
    }

    //this function is called when the SDP sockets receives data (see HCICallback in TestShell),
    //currently does not happen because not forwarded from OnSdpRsp, can be used to handle multiple connections
    static void OnSockCallback(int socket, SocketState state, const u8* data, int len, void* userData) ;
    static void errorhandler(unsigned err);

    void (*ErrorResponse)(unsigned) ;
    void (*ServiceSearchResponse)() ;
    void (*ServiceAttributeResponse)(serv_rec*) ;
    void (*ServiceSearchAttributeResponse)() ;
    int ServiceSearchRequest(sdp_data *sp, unsigned count, unsigned cs=0);
    int ServiceAttributeRequest(unsigned handle, unsigned count, sdp_data* al, unsigned cs=0) ;
    int ServiceSearchAttributeRequest(sdp_data *sp, unsigned count, sdp_data* al, unsigned cs=0);
private:
    unsigned length(const unsigned char *el, unsigned &p);
    unsigned getval(const unsigned char *p, int n) ;
    unsigned parse (const unsigned char *el, unsigned count, sdp_data* &result, serv_rec* &record) ;
    unsigned parseLight (const unsigned char *el, unsigned count, sdp_data* &result, serv_rec* &record) ;
    int parseRsp(const unsigned char*rsp, int len) ;
    void append(const unsigned char*rsp, int len) ;
    void freeBuf();
};

#endif