SDP client for myBlueUSB
Dependents: mbed_TANK_Kinect ftusbClass
Revision 2:d5a27b2d2e08, committed 2011-04-07
- Comitter:
- networker
- Date:
- Thu Apr 07 21:01:39 2011 +0000
- Parent:
- 1:70ee392bcfd4
- Child:
- 3:e8d2ebb7392e
- Commit message:
- fixed some memory problems; able to read my iPhone services
Changed in this revision
--- a/sdp.cpp Wed Apr 06 18:09:20 2011 +0000 +++ b/sdp.cpp Thu Apr 07 21:01:39 2011 +0000 @@ -23,12 +23,16 @@ void SDPManager::OnSdpRsp(const u8* data, int len) { static sdp_data list(sdp_data::SEQUENCE); static sdp_data all(0x0000ffffU,4); + static sdp_data serviceID(0U, 2); + static sdp_data name(0x100U, 2); static sdp_data root(sdp_data::UUID, BROWSEROOT); static sdp_data req(sdp_data::SEQUENCE); static bool once = true; - printf("_state=%d first=%d ", _state, once); + //printf("_state=%d first=%d ", _state, once); if (once) { list.add_element(&all); + //list.add_element(&serviceID); + //list.add_element(&name); req.add_element(&root); once = false; } @@ -39,7 +43,7 @@ case 0: //closed if (len==0) { //socket just opened //'Open' cleared the services list - ServiceSearchRequest(&req, 1); + ServiceSearchRequest(&req, 10); _state = 1; //wait for service handles } break; @@ -51,7 +55,7 @@ index = services.begin(); if (index != services.end()) { unsigned handle = (*index).first; - printf("req.: handle %#X\n", handle); + //printf("req.: handle %#X\n", handle); ServiceAttributeRequest(handle, 100, &list);//0x1001D } else printf(" - empty list - \n");//should not happen @@ -67,7 +71,7 @@ if (data[0]==5) { index++; //move to next service if (index != services.end()) { - printf("req.: handle %#X\n", (*index).first); + //printf("req.: handle %#X\n", (*index).first); ServiceAttributeRequest((*index).first, 100, &list); } else { printf(" - end of list - \n"); @@ -308,21 +312,21 @@ case sdp_data::ALTERNATIVE: item = new sdp_data(sdp_data::ALTERNATIVE); skip: {//p points just after the length indicator, hence at the first item IN the sequence - //printf("SEQ%d{%p ", len, item); + //printf("SEQ%d{%p ", len, item); int n = 0; unsigned short key; - serv_rec *dummy = 0; + serv_rec *dummy = 0;//means: there is no service record to fill in for deeper levels while (p < end) { - sdp_data *elem = 0; + sdp_data *elem = 0; //this becomes the tree with attribute values p += parse(el + p, len-p, elem, dummy);//parse each element in the sequence, the second arg is as yet unused - item->add_element(elem); - if (record) { + if (record) { //if at the level of attribute list, add elem to record as key/value pair if (n & 1) { //value record->insert(pair<unsigned short, sdp_data*>(key, elem)); } else //key key = elem->asUnsigned(); n++; - } + } else //just add the elements to the value tree + item->add_element(elem); } } //printf("}\n"); @@ -356,10 +360,13 @@ byteCount = 0; } + +//TODO: test case 7, add server support (cases 2, 4, 6) +//3 cases: cont==0 && contBuf==0 -> use rsp; cont!=0 -> append; cont==0 && contBuf!=0 -> append and use contBuf int SDPManager::parseRsp(const unsigned char*rsp, int len) { unsigned tid = rsp[2] + ((unsigned)rsp[1]<<8); unsigned parlen = rsp[4] + ((unsigned)rsp[3]<<8); - printf("ParseRsp: tid=%04X, parlen=%d ", tid, parlen); + //printf("ParseRsp: tid=%04X, parlen=%d ", tid, parlen); unsigned cont = 0; switch (rsp[0]) { case 1: {//errorRsp @@ -394,19 +401,26 @@ } break; case 5: { //serviceattributeRsp - if (tree) delete tree; unsigned count = rsp[6] + ((unsigned)rsp[5]<<8);//bytes in this part of the attribute list - append(rsp+7, count); +// append(rsp+7, count); cont = rsp[7+count]; memcpy(contState, &rsp[7+count], cont+1);//copy the continuation state - if (cont) break; - printf("count=%d parsing...\n", byteCount); + if (cont) { + append(rsp+7, count); + break; + } + //printf("count=%d parsing...\n", byteCount); serv_rec *serv = new serv_rec; - parse(contBuf, byteCount, tree, serv); - printf("...parsing done, "); - unsigned key = (*serv)[0]->asUnsigned();//'0' is always the serviceID - printf("Key=%#X\n", key); - services[key] = serv; + if (contBuf){ + append(rsp+7, count); + parse(contBuf, byteCount, tree, serv); + } else + parse(rsp+7, count, tree, serv); + //printf("...parsing done, "); + //get the AttributeID, make sure attribId 0 is always included in the request + unsigned key = (*serv)[0]->asUnsigned();//AttributeID '0' always refers to the serviceID + //printf("Key=%#X\n", key); //key will be 0 when not requested + services[key] = serv; //Add the attribute list to the services freeBuf(); if (ServiceAttributeResponse) ServiceAttributeResponse(serv); @@ -414,7 +428,6 @@ break; //below is UNTESTED case 7: { //servicesearchattributeRsp - if (tree) delete tree; unsigned count = rsp[6] + ((unsigned)rsp[5]<<8); append(rsp+7, count); cont = rsp[7+count];
--- a/sdp.h Wed Apr 06 18:09:20 2011 +0000 +++ b/sdp.h Thu Apr 07 21:01:39 2011 +0000 @@ -10,6 +10,8 @@ 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; @@ -37,18 +39,24 @@ _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; + printf("This SDP supports only one connection at a time\n"); + return 0; } //BD_ADDR* a = &ad->bdaddr; sdp_socket = sock->ID; - for (index = services.begin(); index != services.end(); index++) - delete (*index).second; - services.clear(); 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) { @@ -65,8 +73,11 @@ } virtual int Close(SocketInternal* sock) { - printf("SDP socket %d and L2CAP socket %d closed\n", sock->ID, _l2cap); - return Socket_Close(_l2cap); + 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() { @@ -77,15 +88,15 @@ //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)); +// 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){ + 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) ;
--- a/sdp_data.cpp Wed Apr 06 18:09:20 2011 +0000 +++ b/sdp_data.cpp Thu Apr 07 21:01:39 2011 +0000 @@ -1,5 +1,6 @@ #include "mbed.h" #include "sdp_data.h" +#include "Utils.h" char sdp_data::ret[12]; @@ -144,6 +145,8 @@ d[i] = s[n-i-1]; } + +//TODO: handling of maximum nr of bytes is probably wrong, it is better to ignore it and truncate later unsigned sdp_data::build(unsigned char *buf, unsigned max) { int p = 0; if (size+5 < max) { @@ -190,14 +193,17 @@ break; case SEQUENCE: case ALTERNATIVE: - p += sizedesc(buf+p); - for (int i = 0; i < sequence.size(); i++) - sequence.at(i)->build(buf+p, max-p); + { int n = 0; + p += sizedesc(buf+p); + for (int i = 0; i < sequence.size(); i++) + n += sequence.at(i)->build(buf+p+n, max-p); + } break; } p += size; } else { //too big, make continuation printf ("Data too large to fit\n"); } +// printfBytes("Build:", buf, p); return p; }
--- a/sdp_data.h Wed Apr 06 18:09:20 2011 +0000 +++ b/sdp_data.h Thu Apr 07 21:01:39 2011 +0000 @@ -18,9 +18,9 @@ unsigned short uuid[8]; #endif }; + vector<sdp_data*> sequence; //not allowed to be in union static char ret[12]; char *longstr; - vector<sdp_data*> sequence; public: sdp_data(): type(NULL_), size(0), longstr(0) { //printf("NULL%d ", size); @@ -31,18 +31,19 @@ } sdp_data(signed d, unsigned sz=4): type(SIGNED), size(sz), longstr(0) { data=d; - // printf("INT%d=%d ", size, data); + //printf("INT%d=%d ", size, data); } sdp_data(bool d, unsigned sz=1): type(BOOL), size(sz), longstr(0) { data=d; - // printf("BOOL%d=%u ", size, data); + //printf("BOOL%d=%u ", size, data); } sdp_data(char*s, unsigned sz=0): type(STRING), longstr(0) { - if (sz) size = sz; + if (sz) size = sz+1; else size = strlen(s)+1; str = new char[size]; strncpy(str, s, size); - // printf("STR%d='%s' ", size, str); + str[size-1] = '\0'; + //printf("STR%d='%s' ", size, str); } sdp_data(enum elements t, unsigned d, unsigned sz=2): type(t), size(sz), longstr(0) { if (t==UUID) { @@ -89,7 +90,8 @@ delete sequence.at(i); break; } - delete[] longstr; + if (longstr) + delete[] longstr; } void add_element(sdp_data *el) { sequence.push_back(el);