SDP client for myBlueUSB

Dependents:   mbed_TANK_Kinect ftusbClass

Files at this revision

API Documentation at this revision

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

sdp.cpp Show annotated file Show diff for this revision Revisions of this file
sdp.h Show annotated file Show diff for this revision Revisions of this file
sdp_data.cpp Show annotated file Show diff for this revision Revisions of this file
sdp_data.h Show annotated file Show diff for this revision Revisions of this file
--- 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);