SDP client for myBlueUSB

Dependents:   mbed_TANK_Kinect ftusbClass

Files at this revision

API Documentation at this revision

Comitter:
networker
Date:
Sat Jun 11 19:43:36 2011 +0000
Parent:
3:e8d2ebb7392e
Commit message:
added some further server functions

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
--- a/sdp.cpp	Wed May 04 09:27:32 2011 +0000
+++ b/sdp.cpp	Sat Jun 11 19:43:36 2011 +0000
@@ -17,6 +17,7 @@
     }
 }
 
+#define BROWSEGROUP 0x1001
 #define BROWSEROOT  0x1002
 #define SERIALSERV  0x1101
 
@@ -235,6 +236,95 @@
     return Socket_Send(sdp_socket, l2cap_buf, parlen + 5 + OFFSET);
 }
 
+unsigned BE32(unsigned le) {
+    unsigned be=0;
+    for (int i = 0; i < 32; i+=8){
+      be |= ((le>>i)&0xFFU)<<(24-i);
+    }   
+    return be;
+}
+
+int SDPManager::ServiceSearchReply(unsigned rxid, unsigned *handles, unsigned count, unsigned cs) {//'count' is number of matching handles and capped at the maximumservicerecordcount
+    unsigned size = count*4;
+    unsigned cont = 0;//outgoing continuation
+    unsigned char *_buf = new unsigned char[OFFSET+5+4+size+3];
+    unsigned char *buf = _buf+OFFSET;
+    unsigned current = count - cs; //remainder of data to send
+    unsigned parlen = 4 + 4*current + 1 ;// attributelistbytecount+payload+no_continuation
+    //never need a continuation unless other criterion like PDU size is used
+    if (current > count) {//still too large, need continuation
+        current = count; //limit at maximum
+        cont = cs + count; //start for next iteration
+        parlen = 4 + 4*current + 3; //adjusted for payload and continuation
+        printf("Need continuation, sending handles [%d, %d> of attributeList\n", cs, cont);
+    } else {
+        //   printf("Final or only block, sending bytes [%d, %d> of attributeList\n", cs, cs+byteCount);
+    }
+    buf[0] = 3; //pdu
+    buf[1] = rxid>>8;
+    buf[2] = rxid;
+    buf[3] = parlen>>8;
+    buf[4] = parlen;
+    buf[5] = count>>8;
+    buf[6] = count;
+    buf[7] = current>>8;
+    buf[8] = current;
+    unsigned *p = (unsigned*)&buf[9];
+    for (int i = 0; i < current; i++)
+        p[i] = BE32(handles[i]);
+    //printf("'build' added %d bytes to the buffer\n", p);
+    if (cs == 0) { //this is not a continuation
+        buf[5+parlen-1] = 0;
+    } else { //this is a continuation
+        memcpy(buf+9, buf+9+cs*4, current*4);//move part of interrest to beginning of buffer
+        buf[5+parlen-3] = 2;
+        buf[5+parlen-2] = cont>>8;
+        buf[5+parlen-1] = cont;
+    }
+    //printfBytes("SDP Send: ", buf, parlen+5);
+    int retval = Socket_Send(serverSock, _buf, parlen + 5 + OFFSET);
+    delete[] _buf;
+    return retval;
+}
+
+int SDPManager::ServiceAttributeReply(unsigned rxid, sdp_data* al, unsigned count, unsigned cs) {
+    unsigned size = al->Size();
+    unsigned cont = 0;//outgoing continuation
+    unsigned char *_buf = new unsigned char[OFFSET+5+2+size+3];
+    unsigned char *buf = _buf+OFFSET;
+    unsigned byteCount = size - cs; //remainder of data to send
+    unsigned parlen = 2 + byteCount + 1 ;// attributelistbytecount+payload+no_continuation
+    if (byteCount > count) {//still too large, need continuation
+        byteCount = count; //limit at maximum
+        cont = cs + count; //start for next iteration
+        parlen = 2 + byteCount + 3; //adjusted for payload and continuation
+        printf("Need continuation, sending bytes [%d, %d> of attributeList\n", cs, cont);
+    } else {
+        //   printf("Final or only block, sending bytes [%d, %d> of attributeList\n", cs, cs+byteCount);
+    }
+    buf[0] = 5; //pdu
+    buf[1] = rxid>>8;
+    buf[2] = rxid;
+    buf[3] = parlen>>8;
+    buf[4] = parlen;
+    buf[5] = byteCount>>8;
+    buf[6] = byteCount;
+    int p = al->build(buf+7, size);//limited only by buffersize
+    //printf("'build' added %d bytes to the buffer\n", p);
+    if (cs == 0) { //this is not a continuation
+        buf[byteCount+7] = 0;
+    } else { //this is a continuation
+        memcpy(buf+7, buf+7+cs, byteCount);//move part of interrest to beginning of buffer
+        buf[byteCount+7] = 2;
+        buf[byteCount+8] = cont>>8;
+        buf[byteCount+9] = cont;
+    }
+    //printfBytes("SDP Send: ", buf, parlen+5);
+    int retval = Socket_Send(serverSock, _buf, parlen + 5 + OFFSET);
+    delete[] _buf;
+    return retval;
+}
+
 int SDPManager::ServiceSearchAttributeReply(unsigned rxid, sdp_data* al, unsigned count, unsigned cs) {
     unsigned size = al->Size();
     unsigned cont = 0;//outgoing continuation
@@ -248,7 +338,7 @@
         parlen = 2 + byteCount + 3; //adjusted for payload and continuation
         printf("Need continuation, sending bytes [%d, %d> of attributeList\n", cs, cont);
     } else {
-     //   printf("Final or only block, sending bytes [%d, %d> of attributeList\n", cs, cs+byteCount);
+        //   printf("Final or only block, sending bytes [%d, %d> of attributeList\n", cs, cs+byteCount);
     }
     buf[0] = 7; //pdu
     buf[1] = rxid>>8;
@@ -604,7 +694,8 @@
     static sdp_data chan(1U,1);
     static sdp_data handle(SVC_HANDLE,4);
     static sdp_data serviceID(0U, 2);
-    static sdp_data name("MBED BlueUSB RFCOMM Serial");
+//    static sdp_data name("MBED BlueUSB RFCOMM Serial");
+    static sdp_data name("Serial Port");
     rfcomm.add_element(&rfcommuuid);
     rfcomm.add_element(&chan);
     l2cap.add_element(&l2capuuid);
@@ -662,6 +753,10 @@
 void SDPManager::addToReply(sdp_data *svc, serv_rec *list, const unsigned char* att, int end) {
     unsigned short len, low, high;
     serv_rec::iterator from, to, idx;
+    if (list==0) {
+        printf("Invalid attribute list (NULL)\n");
+        return;
+    }
     for (unsigned pos = 0; pos < end; pos += len) {
         len = length(att, pos);
         switch (len) {
@@ -677,9 +772,9 @@
                 from = list->lower_bound(low);
                 to = list->upper_bound(high);
                 for (idx = from; idx != to; idx++) {
-                  svc->add_element(new sdp_data(idx->first, 2));
-                  svc->add_element(idx->second);
-                  printf("Found attrib %d\n", idx->first);
+                    svc->add_element(new sdp_data(idx->first, 2));
+                    svc->add_element(idx->second);
+                    printf("Found attrib %d\n", idx->first);
                 }
                 break;
             default:
@@ -705,9 +800,69 @@
         }
         break;
         case 2: { //servicesearchReq
+            printf("servicesearchReq almost implemented\n");
+            unsigned pat[12];//the received search pattern
+            int pn;//number of uuids in the pattern
+            if (data[pos]>>3 != sdp_data::SEQUENCE) {//the uuids are wrapped in a sequence
+                printf("Expected a sequence of UUIDs\n");
+                break;
+            }
+            unsigned end = pos + length(data, pos);//get the length of the list of lists and advance pos to the first list
+            bool *eligible = new bool[server.size()];//marks for the services identified by the search pattern
+            for (int i = 0; i < server.size(); i++) eligible[i] = true;
+            for (pn = 0; pn < 12 && pos < end; pn++) {
+                pat[pn] = parseUUID(data,end, pos);//store uuid from the sequence in the pattern
+                match(eligible, pat[pn]);//unmark a service when it does not contain the uuid
+                //printf("pos=%d, count=%d, uuid=%#X\n", pos, len, pat[pn]);
+            }
+
+            unsigned count = getval(data+pos, 2); //maximum length of attribute list to return
+            pos += 2;
+            unsigned tail = data[pos];
+            if (tail) {
+                tail = getval(data+pos+1, tail);
+                printf("requested continuation tailpos=%u\n", tail);
+            } else {
+                //printf("No continuation requested\n");
+            }
+            unsigned *handles = new unsigned[server.size()];
+            int total = 0, current = 0;
+            map<unsigned, serv_rec*>::iterator idx;
+            int i = 0;
+            for (idx = server.begin(); idx != server.end() && total < count; idx++, i++)
+                if (eligible[i])
+                    handles[total++] = idx->first;
+            ServiceSearchReply(tid, handles, total, tail);
+            delete[] handles;
+            delete[] eligible;
         }
         break;
         case 4: { //serviceattributeReq
+            printf("serviceattributeReq almost implemented\n");
+            sdp_data reply(sdp_data::SEQUENCE);//the attributelist of the reply
+            unsigned svcid = getval(data+pos, 4);
+            pos += 4;
+            unsigned count = getval(data+pos, 2); //maximum length of attribute list to return
+            pos += 2;
+            int len = length(data, pos); //get the length of the attributeID list
+            int cont = pos + len;
+            printf("svcid=%08X, count=%u, len=%u, pos=%u\n", svcid, count, len, pos);
+            addToReply(&reply, server[svcid], data+pos, len);
+            unsigned tail = data[cont];
+            printf("tail=%u, reply size=%d\n", tail, reply.Size());
+            if (tail) {
+                tail = getval(data+cont+1, tail);
+                printf("requested continuation tailpos=%u, size=%u\n", tail, reply.Size());
+            } else {
+                //printf("No continuation requested\n");
+            }
+
+            ServiceAttributeReply(tid, &reply, count, tail);
+            for (int k = 0; k < reply.items(); k++) {
+                if ((k & 1) == 0) //even hence ID
+                    delete reply.item(k); //destroy the ID
+                reply.remove(k);  //set all items to nil to prevent destruction of the DB
+            }
         }
         break;
         case 6: { //servicesearchattributeReq
@@ -756,17 +911,16 @@
 #endif
                 reply.add_element(svc); //append the new attribute list to the reply list
             }
-            
+
             unsigned tail = data[cont];
             if (tail) {
                 tail = getval(data+cont+1, tail);
                 printf("requested continuation tailpos=%u, size=%u\n", tail, reply.Size());
-            }
-            else {
+            } else {
                 //printf("No continuation requested\n");
             }
             ServiceSearchAttributeReply(tid, &reply, count, tail);
-            
+
             for (int j = 0; j < reply.items(); j++) {
                 sdp_data *al = reply.item(j);
                 for (int k = 0; k < al->items(); k++) {
--- a/sdp.h	Wed May 04 09:27:32 2011 +0000
+++ b/sdp.h	Sat Jun 11 19:43:36 2011 +0000
@@ -147,6 +147,8 @@
     static void addToReply(sdp_data *svc, serv_rec *list, const unsigned char* att, int end);
     static int findUUID(unsigned h, unsigned uuid);
     void buildServer();
+    static int ServiceSearchReply(unsigned rxid, unsigned *handles, unsigned count, unsigned cs=0);
+    static int ServiceAttributeReply(unsigned rxid, sdp_data* al, unsigned count, unsigned cs=0);
     static int ServiceSearchAttributeReply(unsigned rxid, sdp_data* al, unsigned count, unsigned cs=0);
     /*
         //this function is called when the SDP sockets receives data (see HCICallback in TestShell),