Pulse Oximeter (NONIN) communicates with mbed via Bluetooth dongle and sends Heart Rate and Oxygen Saturation via GPRS module

Dependencies:   C12832 GPS GSM mbed

Fork of myBlueUSB_localfix by Nobuaki Aoki

Committer:
samialshorman
Date:
Tue Apr 14 21:48:07 2015 +0000
Revision:
3:55a622e3dbb5
Parent:
0:003889bc474f
Nonin (Pulse Oximeter) connected to mbed lpc 1768 by Bluetooth dongle and sends SMS including Heart Rate and Oxygen saturation by GPRS module

Who changed what in which revision?

UserRevisionLine numberNew contents of line
nobukuma 0:003889bc474f 1 #include "mbed.h"
nobukuma 0:003889bc474f 2 #include "Utils.h"
nobukuma 0:003889bc474f 3 #include "hci.h"
nobukuma 0:003889bc474f 4 #include "sdp_data.h"
nobukuma 0:003889bc474f 5 #include "sdp.h"
nobukuma 0:003889bc474f 6
nobukuma 0:003889bc474f 7 SDPManager SDP; //instance
nobukuma 0:003889bc474f 8 const unsigned char base_uuid[16] = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0, 0x07, 0x70, 0, 0x10, 0, 0};
nobukuma 0:003889bc474f 9 map<unsigned, serv_rec*> SDPManager::server;
nobukuma 0:003889bc474f 10 int SDPManager::serverSock = 0;
nobukuma 0:003889bc474f 11
nobukuma 0:003889bc474f 12 void attribHandler(serv_rec *r) {
nobukuma 0:003889bc474f 13 printf("Service 0x%08X\n", (*r)[0x0000]->asUnsigned());
nobukuma 0:003889bc474f 14 map<unsigned short, sdp_data*>::iterator it = r->begin();
nobukuma 0:003889bc474f 15 for (;it != r->end();it++) {
nobukuma 0:003889bc474f 16 printf(" 0x%04X: %s\n", (*it).first, (*it).second->asString());
nobukuma 0:003889bc474f 17 }
nobukuma 0:003889bc474f 18 }
nobukuma 0:003889bc474f 19
nobukuma 0:003889bc474f 20 #define BROWSEGROUP 0x1001
nobukuma 0:003889bc474f 21 #define BROWSEROOT 0x1002
nobukuma 0:003889bc474f 22 #define SERIALSERV 0x1101
nobukuma 0:003889bc474f 23
nobukuma 0:003889bc474f 24 SDPHandler::SDPHandler(): txid(1), tree(0) {
nobukuma 0:003889bc474f 25 ErrorResponse=errorhandler;
nobukuma 0:003889bc474f 26 ServiceSearchResponse=0;
nobukuma 0:003889bc474f 27 ServiceAttributeResponse=attribHandler;
nobukuma 0:003889bc474f 28 ServiceSearchAttributeResponse=0;
nobukuma 0:003889bc474f 29 buf = l2cap_buf+OFFSET;
nobukuma 0:003889bc474f 30 contBuf = 0;
nobukuma 0:003889bc474f 31 byteCount = 0;
nobukuma 0:003889bc474f 32 contState[0] = 0;
nobukuma 0:003889bc474f 33 _state = 0;
nobukuma 0:003889bc474f 34 }
nobukuma 0:003889bc474f 35
nobukuma 0:003889bc474f 36 void SDPHandler::Clear() {
nobukuma 0:003889bc474f 37 for (index = services.begin(); index != services.end(); index++) {//for all services
nobukuma 0:003889bc474f 38 for (serv_rec::iterator it = index->second->begin(); it != index->second->end(); it++)//for all attributes
nobukuma 0:003889bc474f 39 delete it->second; //delete the attribute value tree
nobukuma 0:003889bc474f 40 delete (*index).second; //delete the attribute list
nobukuma 0:003889bc474f 41 }
nobukuma 0:003889bc474f 42 services.clear();//and empty the services list
nobukuma 0:003889bc474f 43 }
nobukuma 0:003889bc474f 44
nobukuma 0:003889bc474f 45 //Called as: Socket_Open(SOCKET_SDP, addr, callback, userdata(this)) from SDPManager
nobukuma 0:003889bc474f 46 //never called
nobukuma 0:003889bc474f 47 int SDPHandler::Open(SocketInternal* sock, SocketAddrHdr* addr) {
nobukuma 0:003889bc474f 48 printf("Successfully opened SDP socket %d\n", sock->ID);
nobukuma 0:003889bc474f 49 sock->SetState(SocketState_Open);
nobukuma 0:003889bc474f 50 sdp_socket = sock->ID;
nobukuma 0:003889bc474f 51 return sdp_socket;
nobukuma 0:003889bc474f 52 }
nobukuma 0:003889bc474f 53
nobukuma 0:003889bc474f 54 int SDPHandler::Send(SocketInternal* sock, const u8* data, int len) {
nobukuma 0:003889bc474f 55 printf("SDPHandler::Send should not be called directly\n");
nobukuma 0:003889bc474f 56 // return Socket_Send(_l2cap, data, len);
nobukuma 0:003889bc474f 57 BTDevice *l2cap = (BTDevice*)sock->userData;
nobukuma 0:003889bc474f 58 return l2cap->Send(sock, data, len);
nobukuma 0:003889bc474f 59 }
nobukuma 0:003889bc474f 60
nobukuma 0:003889bc474f 61 int SDPHandler::Close(SocketInternal* sock) {
nobukuma 0:003889bc474f 62 printf("SDPHandler::Close(%d)\n", sock->ID);
nobukuma 0:003889bc474f 63 Clear();
nobukuma 0:003889bc474f 64 // printf("SDP socket %d and L2CAP socket %d closed, freemem=%d\n", sock->ID, _l2cap, AvailableMemory(1));
nobukuma 0:003889bc474f 65 int retval = 0;//Socket_Close(_l2cap);//could also keep it open for the next connection
nobukuma 0:003889bc474f 66 return retval;
nobukuma 0:003889bc474f 67 }
nobukuma 0:003889bc474f 68
nobukuma 0:003889bc474f 69 //this function is called when the L2CAP layer receives SDP packets (see SDPHandler::Open), userdata is the sdpmanager instance
nobukuma 0:003889bc474f 70 void SDPHandler::OnSdpRsp(int socket, SocketState state, const u8* data, int len, void* userData) {
nobukuma 0:003889bc474f 71 printf("\x1B[%dm", 35);
nobukuma 0:003889bc474f 72 // printf("OnSdpRsp(socket=%d, state=%d, len=%d)\n", socket, state, len);
nobukuma 0:003889bc474f 73 printf("SDPHandler::OnSdpRsp(socket=%d, state=%d, len=%d, freemem=%d\n", socket, state, len, AvailableMemory(1));
nobukuma 0:003889bc474f 74 SDPHandler *self = (SDPHandler*)userData;
nobukuma 0:003889bc474f 75 if (state == SocketState_Open) {
nobukuma 0:003889bc474f 76 self->sdp_socket = socket;
nobukuma 0:003889bc474f 77 self->OnSdpRsp(data, len);
nobukuma 0:003889bc474f 78 } else if (state == SocketState_Closed) {
nobukuma 0:003889bc474f 79 SDP.Destroy(socket);
nobukuma 0:003889bc474f 80 }
nobukuma 0:003889bc474f 81 printf("\x1B[%dm", 0);
nobukuma 0:003889bc474f 82 }
nobukuma 0:003889bc474f 83
nobukuma 0:003889bc474f 84 //this function is called when the L2CAP layer receives SDP packets (see SDPHandler::Open), userdata is the sdpmanager instance
nobukuma 0:003889bc474f 85 //void SDPHandler::OnSdpRsp(int socket, SocketState state, const u8* data, int len, void* userData) {
nobukuma 0:003889bc474f 86 void SDPHandler::OnSdpRsp(const u8* data, int len) {
nobukuma 0:003889bc474f 87 static sdp_data list(sdp_data::SEQUENCE);
nobukuma 0:003889bc474f 88 static sdp_data all(0x0000ffffU,4);
nobukuma 0:003889bc474f 89 static sdp_data serviceID(0U, 2);
nobukuma 0:003889bc474f 90 static sdp_data name(0x100U, 2);
nobukuma 0:003889bc474f 91 static sdp_data root(sdp_data::UUID, BROWSEROOT);
nobukuma 0:003889bc474f 92 static sdp_data req(sdp_data::SEQUENCE);
nobukuma 0:003889bc474f 93 static bool once = true;
nobukuma 0:003889bc474f 94 // printf("_state=%d first=%d ", _state, once);
nobukuma 0:003889bc474f 95 if (once) {
nobukuma 0:003889bc474f 96 list.add_element(&all);
nobukuma 0:003889bc474f 97 //list.add_element(&serviceID);
nobukuma 0:003889bc474f 98 //list.add_element(&name);
nobukuma 0:003889bc474f 99 req.add_element(&root);
nobukuma 0:003889bc474f 100 once = false;
nobukuma 0:003889bc474f 101 }
nobukuma 0:003889bc474f 102 if (data) {
nobukuma 0:003889bc474f 103 parseRsp(data, len);
nobukuma 0:003889bc474f 104 }
nobukuma 0:003889bc474f 105 switch (_state) {
nobukuma 0:003889bc474f 106 case 0: //closed
nobukuma 0:003889bc474f 107 if (len==0) { //socket just opened
nobukuma 0:003889bc474f 108 //'Open' cleared the services list
nobukuma 0:003889bc474f 109 ServiceSearchRequest(&req, 10);
nobukuma 0:003889bc474f 110 _state = 1; //wait for service handles
nobukuma 0:003889bc474f 111 }
nobukuma 0:003889bc474f 112 break;
nobukuma 0:003889bc474f 113 case 1: //service handles arriving
nobukuma 0:003889bc474f 114 if (contState[0]) {//continuation, repeat request
nobukuma 0:003889bc474f 115 ServiceSearchRequest(&req, 5);
nobukuma 0:003889bc474f 116 } else {
nobukuma 0:003889bc474f 117 if (data[0]==3) {
nobukuma 0:003889bc474f 118 index = services.begin();
nobukuma 0:003889bc474f 119 if (index != services.end()) {
nobukuma 0:003889bc474f 120 unsigned handle = (*index).first;
nobukuma 0:003889bc474f 121 //printf("req.: handle %#X\n", handle);
nobukuma 0:003889bc474f 122 ServiceAttributeRequest(handle, 100, &list);//0x1001D
nobukuma 0:003889bc474f 123 } else
nobukuma 0:003889bc474f 124 printf(" - empty list - \n");//should not happen
nobukuma 0:003889bc474f 125 _state = 2; //wait for attribute response
nobukuma 0:003889bc474f 126 } else
nobukuma 0:003889bc474f 127 printf("Expected a ServiceSearchResponse 0x03, got %#x\n", data[0]);
nobukuma 0:003889bc474f 128 }
nobukuma 0:003889bc474f 129 break;
nobukuma 0:003889bc474f 130 case 2:
nobukuma 0:003889bc474f 131 if (contState[0])//repeat request
nobukuma 0:003889bc474f 132 ServiceAttributeRequest((*index).first, 100, &list);
nobukuma 0:003889bc474f 133 else {
nobukuma 0:003889bc474f 134 if (data[0]==5) {
nobukuma 0:003889bc474f 135 index++; //move to next service
nobukuma 0:003889bc474f 136 if (index != services.end()) {
nobukuma 0:003889bc474f 137 //printf("req.: handle %#X\n", (*index).first);
nobukuma 0:003889bc474f 138 ServiceAttributeRequest((*index).first, 100, &list);
nobukuma 0:003889bc474f 139 } else {
nobukuma 0:003889bc474f 140 printf(" - end of list - \n");
nobukuma 0:003889bc474f 141 Socket_Close(sdp_socket); //Note: socket=L2CAP, sdp_socket=SDP !!!
nobukuma 0:003889bc474f 142 _state = 0;
nobukuma 0:003889bc474f 143 }
nobukuma 0:003889bc474f 144 } else
nobukuma 0:003889bc474f 145 printf("Expected a ServiceAttributeResponse 0x05, got %#x\n", data[0]);
nobukuma 0:003889bc474f 146 }
nobukuma 0:003889bc474f 147 break;
nobukuma 0:003889bc474f 148 }
nobukuma 0:003889bc474f 149 }
nobukuma 0:003889bc474f 150
nobukuma 0:003889bc474f 151 //this function is called when the SDP sockets receives data (see HCICallback in TestShell),
nobukuma 0:003889bc474f 152 //currently does not happen because not forwarded from OnSdpRsp, can be used to handle multiple connections
nobukuma 0:003889bc474f 153 void SDPHandler::OnSockCallback(int socket, SocketState state, const u8* data, int len, void* userData) {
nobukuma 0:003889bc474f 154 printf("SDPHandler::OnSockCallback(socket=%d, state=%d, len=%d)\n", socket, state, len);
nobukuma 0:003889bc474f 155 printfBytes("Got SDP Response from socket: ", data, len);
nobukuma 0:003889bc474f 156 }
nobukuma 0:003889bc474f 157
nobukuma 0:003889bc474f 158 //void SDPHandler::errorhandler(unsigned err) {//default error handler
nobukuma 0:003889bc474f 159 void errorhandler(unsigned err) {//default error handler
nobukuma 0:003889bc474f 160 switch (err) {
nobukuma 0:003889bc474f 161 case 1:
nobukuma 0:003889bc474f 162 printf("Unsupported version of SDP\n");
nobukuma 0:003889bc474f 163 break;
nobukuma 0:003889bc474f 164 case 2:
nobukuma 0:003889bc474f 165 printf("Invalid SDP ServiceRecordHandle\n");
nobukuma 0:003889bc474f 166 break;
nobukuma 0:003889bc474f 167 case 3:
nobukuma 0:003889bc474f 168 printf("SDP syntax error\n");
nobukuma 0:003889bc474f 169 break;
nobukuma 0:003889bc474f 170 case 4:
nobukuma 0:003889bc474f 171 printf("PDU size was invalid\n");
nobukuma 0:003889bc474f 172 break;
nobukuma 0:003889bc474f 173 case 5:
nobukuma 0:003889bc474f 174 printf("Continuation state was invalid\n");
nobukuma 0:003889bc474f 175 break;
nobukuma 0:003889bc474f 176 case 6:
nobukuma 0:003889bc474f 177 printf("SDP server has insufficient resources\n");
nobukuma 0:003889bc474f 178 break;
nobukuma 0:003889bc474f 179 default:
nobukuma 0:003889bc474f 180 printf("Unknown SDP error code\n");
nobukuma 0:003889bc474f 181 break;
nobukuma 0:003889bc474f 182 }
nobukuma 0:003889bc474f 183 }
nobukuma 0:003889bc474f 184
nobukuma 0:003889bc474f 185 int SDPHandler::ServiceSearchRequest(sdp_data *sp, unsigned count, unsigned cs) {
nobukuma 0:003889bc474f 186 int parlen = sp->Size() + contState[0] + 3;
nobukuma 0:003889bc474f 187 buf[0] = 2; //pdu
nobukuma 0:003889bc474f 188 buf[1] = txid>>8;
nobukuma 0:003889bc474f 189 buf[2] = txid++;
nobukuma 0:003889bc474f 190 buf[4] = parlen;
nobukuma 0:003889bc474f 191 buf[3] = parlen>>8;
nobukuma 0:003889bc474f 192 int p = sp->build(buf+5, 100-10);
nobukuma 0:003889bc474f 193 buf[p+6] = count;
nobukuma 0:003889bc474f 194 buf[p+5] = count>>8;
nobukuma 0:003889bc474f 195 buf[p+7] = contState[0];
nobukuma 0:003889bc474f 196 for (int j = 1; j <= contState[0]; j++)
nobukuma 0:003889bc474f 197 buf[p+j+7] = contState[j];
nobukuma 0:003889bc474f 198 //printfBytes("SDP Send: ", buf, parlen+5);
nobukuma 0:003889bc474f 199 return Socket_Send(sdp_socket, l2cap_buf, parlen + 5 + OFFSET);
nobukuma 0:003889bc474f 200 }
nobukuma 0:003889bc474f 201
nobukuma 0:003889bc474f 202 int SDPHandler::ServiceAttributeRequest(unsigned handle, unsigned count, sdp_data* al, unsigned cs) {
nobukuma 0:003889bc474f 203 int parlen = al->Size() + contState[0] + 7;
nobukuma 0:003889bc474f 204 buf[0] = 4; //pdu
nobukuma 0:003889bc474f 205 buf[1] = txid>>8;
nobukuma 0:003889bc474f 206 buf[2] = txid++;
nobukuma 0:003889bc474f 207 buf[4] = parlen;
nobukuma 0:003889bc474f 208 buf[3] = parlen>>8;
nobukuma 0:003889bc474f 209 for (int i = 0; i < 4; i++)
nobukuma 0:003889bc474f 210 buf[i+5] = ((char*)&handle)[3-i];
nobukuma 0:003889bc474f 211 buf[9] = count>>8;
nobukuma 0:003889bc474f 212 buf[10] = count;
nobukuma 0:003889bc474f 213 int p = al->build(buf+11, 100-26);
nobukuma 0:003889bc474f 214 buf[p+11] = contState[0];
nobukuma 0:003889bc474f 215 for (int j = 1; j <= contState[0]; j++)
nobukuma 0:003889bc474f 216 buf[p+j+11] = contState[j];
nobukuma 0:003889bc474f 217 //printfBytes("SDP Send: ", buf, parlen+5);
nobukuma 0:003889bc474f 218 return Socket_Send(sdp_socket, l2cap_buf, parlen + 5 + OFFSET);
nobukuma 0:003889bc474f 219 }
nobukuma 0:003889bc474f 220
nobukuma 0:003889bc474f 221 int SDPHandler::ServiceSearchAttributeRequest(sdp_data *sp, unsigned count, sdp_data* al, unsigned cs) {
nobukuma 0:003889bc474f 222 int parlen = sp->Size() + al->Size() + contState[0] + 3; // count (2 bytes) + at least 1 cont
nobukuma 0:003889bc474f 223 buf[0] = 6; //pdu
nobukuma 0:003889bc474f 224 buf[1] = txid>>8;
nobukuma 0:003889bc474f 225 buf[2] = txid++;
nobukuma 0:003889bc474f 226 buf[4] = parlen;
nobukuma 0:003889bc474f 227 buf[3] = parlen>>8;
nobukuma 0:003889bc474f 228 int p = sp->build(buf+5, 30);
nobukuma 0:003889bc474f 229 buf[p+6] = count;
nobukuma 0:003889bc474f 230 buf[p+5] = count>>8;
nobukuma 0:003889bc474f 231 p += al->build(buf+11, 100-38);
nobukuma 0:003889bc474f 232 buf[p+7] = contState[0];
nobukuma 0:003889bc474f 233 for (int j = 1; j <= contState[0]; j++)
nobukuma 0:003889bc474f 234 buf[p+j+7] = contState[j];
nobukuma 0:003889bc474f 235 //printfBytes("SDP Send: ", buf, parlen+5);
nobukuma 0:003889bc474f 236 return Socket_Send(sdp_socket, l2cap_buf, parlen + 5 + OFFSET);
nobukuma 0:003889bc474f 237 }
nobukuma 0:003889bc474f 238
nobukuma 0:003889bc474f 239 unsigned BE32(unsigned le) {
nobukuma 0:003889bc474f 240 unsigned be=0;
nobukuma 0:003889bc474f 241 for (int i = 0; i < 32; i+=8){
nobukuma 0:003889bc474f 242 be |= ((le>>i)&0xFFU)<<(24-i);
nobukuma 0:003889bc474f 243 }
nobukuma 0:003889bc474f 244 return be;
nobukuma 0:003889bc474f 245 }
nobukuma 0:003889bc474f 246
nobukuma 0:003889bc474f 247 int SDPManager::ServiceSearchReply(unsigned rxid, unsigned *handles, unsigned count, unsigned cs) {//'count' is number of matching handles and capped at the maximumservicerecordcount
nobukuma 0:003889bc474f 248 unsigned size = count*4;
nobukuma 0:003889bc474f 249 unsigned cont = 0;//outgoing continuation
nobukuma 0:003889bc474f 250 unsigned char *_buf = new unsigned char[OFFSET+5+4+size+3];
nobukuma 0:003889bc474f 251 unsigned char *buf = _buf+OFFSET;
nobukuma 0:003889bc474f 252 unsigned current = count - cs; //remainder of data to send
nobukuma 0:003889bc474f 253 unsigned parlen = 4 + 4*current + 1 ;// attributelistbytecount+payload+no_continuation
nobukuma 0:003889bc474f 254 //never need a continuation unless other criterion like PDU size is used
nobukuma 0:003889bc474f 255 if (current > count) {//still too large, need continuation
nobukuma 0:003889bc474f 256 current = count; //limit at maximum
nobukuma 0:003889bc474f 257 cont = cs + count; //start for next iteration
nobukuma 0:003889bc474f 258 parlen = 4 + 4*current + 3; //adjusted for payload and continuation
nobukuma 0:003889bc474f 259 printf("Need continuation, sending handles [%d, %d> of attributeList\n", cs, cont);
nobukuma 0:003889bc474f 260 } else {
nobukuma 0:003889bc474f 261 // printf("Final or only block, sending bytes [%d, %d> of attributeList\n", cs, cs+byteCount);
nobukuma 0:003889bc474f 262 }
nobukuma 0:003889bc474f 263 buf[0] = 3; //pdu
nobukuma 0:003889bc474f 264 buf[1] = rxid>>8;
nobukuma 0:003889bc474f 265 buf[2] = rxid;
nobukuma 0:003889bc474f 266 buf[3] = parlen>>8;
nobukuma 0:003889bc474f 267 buf[4] = parlen;
nobukuma 0:003889bc474f 268 buf[5] = count>>8;
nobukuma 0:003889bc474f 269 buf[6] = count;
nobukuma 0:003889bc474f 270 buf[7] = current>>8;
nobukuma 0:003889bc474f 271 buf[8] = current;
nobukuma 0:003889bc474f 272 unsigned *p = (unsigned*)&buf[9];
nobukuma 0:003889bc474f 273 for (int i = 0; i < current; i++)
nobukuma 0:003889bc474f 274 p[i] = BE32(handles[i]);
nobukuma 0:003889bc474f 275 //printf("'build' added %d bytes to the buffer\n", p);
nobukuma 0:003889bc474f 276 if (cs == 0) { //this is not a continuation
nobukuma 0:003889bc474f 277 buf[5+parlen-1] = 0;
nobukuma 0:003889bc474f 278 } else { //this is a continuation
nobukuma 0:003889bc474f 279 memcpy(buf+9, buf+9+cs*4, current*4);//move part of interrest to beginning of buffer
nobukuma 0:003889bc474f 280 buf[5+parlen-3] = 2;
nobukuma 0:003889bc474f 281 buf[5+parlen-2] = cont>>8;
nobukuma 0:003889bc474f 282 buf[5+parlen-1] = cont;
nobukuma 0:003889bc474f 283 }
nobukuma 0:003889bc474f 284 //printfBytes("SDP Send: ", buf, parlen+5);
nobukuma 0:003889bc474f 285 int retval = Socket_Send(serverSock, _buf, parlen + 5 + OFFSET);
nobukuma 0:003889bc474f 286 delete[] _buf;
nobukuma 0:003889bc474f 287 return retval;
nobukuma 0:003889bc474f 288 }
nobukuma 0:003889bc474f 289
nobukuma 0:003889bc474f 290 int SDPManager::ServiceAttributeReply(unsigned rxid, sdp_data* al, unsigned count, unsigned cs) {
nobukuma 0:003889bc474f 291 unsigned size = al->Size();
nobukuma 0:003889bc474f 292 unsigned cont = 0;//outgoing continuation
nobukuma 0:003889bc474f 293 unsigned char *_buf = new unsigned char[OFFSET+5+2+size+3];
nobukuma 0:003889bc474f 294 unsigned char *buf = _buf+OFFSET;
nobukuma 0:003889bc474f 295 unsigned byteCount = size - cs; //remainder of data to send
nobukuma 0:003889bc474f 296 unsigned parlen = 2 + byteCount + 1 ;// attributelistbytecount+payload+no_continuation
nobukuma 0:003889bc474f 297 if (byteCount > count) {//still too large, need continuation
nobukuma 0:003889bc474f 298 byteCount = count; //limit at maximum
nobukuma 0:003889bc474f 299 cont = cs + count; //start for next iteration
nobukuma 0:003889bc474f 300 parlen = 2 + byteCount + 3; //adjusted for payload and continuation
nobukuma 0:003889bc474f 301 printf("Need continuation, sending bytes [%d, %d> of attributeList\n", cs, cont);
nobukuma 0:003889bc474f 302 } else {
nobukuma 0:003889bc474f 303 // printf("Final or only block, sending bytes [%d, %d> of attributeList\n", cs, cs+byteCount);
nobukuma 0:003889bc474f 304 }
nobukuma 0:003889bc474f 305 buf[0] = 5; //pdu
nobukuma 0:003889bc474f 306 buf[1] = rxid>>8;
nobukuma 0:003889bc474f 307 buf[2] = rxid;
nobukuma 0:003889bc474f 308 buf[3] = parlen>>8;
nobukuma 0:003889bc474f 309 buf[4] = parlen;
nobukuma 0:003889bc474f 310 buf[5] = byteCount>>8;
nobukuma 0:003889bc474f 311 buf[6] = byteCount;
nobukuma 0:003889bc474f 312 int p = al->build(buf+7, size);//limited only by buffersize
nobukuma 0:003889bc474f 313 //printf("'build' added %d bytes to the buffer\n", p);
nobukuma 0:003889bc474f 314 if (cs == 0) { //this is not a continuation
nobukuma 0:003889bc474f 315 buf[byteCount+7] = 0;
nobukuma 0:003889bc474f 316 } else { //this is a continuation
nobukuma 0:003889bc474f 317 memcpy(buf+7, buf+7+cs, byteCount);//move part of interrest to beginning of buffer
nobukuma 0:003889bc474f 318 buf[byteCount+7] = 2;
nobukuma 0:003889bc474f 319 buf[byteCount+8] = cont>>8;
nobukuma 0:003889bc474f 320 buf[byteCount+9] = cont;
nobukuma 0:003889bc474f 321 }
nobukuma 0:003889bc474f 322 //printfBytes("SDP Send: ", buf, parlen+5);
nobukuma 0:003889bc474f 323 int retval = Socket_Send(serverSock, _buf, parlen + 5 + OFFSET);
nobukuma 0:003889bc474f 324 delete[] _buf;
nobukuma 0:003889bc474f 325 return retval;
nobukuma 0:003889bc474f 326 }
nobukuma 0:003889bc474f 327
nobukuma 0:003889bc474f 328 int SDPManager::ServiceSearchAttributeReply(unsigned rxid, sdp_data* al, unsigned count, unsigned cs) {
nobukuma 0:003889bc474f 329 unsigned size = al->Size();
nobukuma 0:003889bc474f 330 unsigned cont = 0;//outgoing continuation
nobukuma 0:003889bc474f 331 unsigned char *_buf = new unsigned char[OFFSET+5+2+size+3];
nobukuma 0:003889bc474f 332 unsigned char *buf = _buf+OFFSET;
nobukuma 0:003889bc474f 333 unsigned byteCount = size - cs; //remainder of data to send
nobukuma 0:003889bc474f 334 unsigned parlen = 2 + byteCount + 1 ;// attributelistbytecount+payload+no_continuation
nobukuma 0:003889bc474f 335 if (byteCount > count) {//still too large, need continuation
nobukuma 0:003889bc474f 336 byteCount = count; //limit at maximum
nobukuma 0:003889bc474f 337 cont = cs + count; //start for next iteration
nobukuma 0:003889bc474f 338 parlen = 2 + byteCount + 3; //adjusted for payload and continuation
nobukuma 0:003889bc474f 339 printf("Need continuation, sending bytes [%d, %d> of attributeList\n", cs, cont);
nobukuma 0:003889bc474f 340 } else {
nobukuma 0:003889bc474f 341 // printf("Final or only block, sending bytes [%d, %d> of attributeList\n", cs, cs+byteCount);
nobukuma 0:003889bc474f 342 }
nobukuma 0:003889bc474f 343 buf[0] = 7; //pdu
nobukuma 0:003889bc474f 344 buf[1] = rxid>>8;
nobukuma 0:003889bc474f 345 buf[2] = rxid;
nobukuma 0:003889bc474f 346 buf[3] = parlen>>8;
nobukuma 0:003889bc474f 347 buf[4] = parlen;
nobukuma 0:003889bc474f 348 buf[5] = byteCount>>8;
nobukuma 0:003889bc474f 349 buf[6] = byteCount;
nobukuma 0:003889bc474f 350 int p = al->build(buf+7, size);//limited only by buffersize
nobukuma 0:003889bc474f 351 //printf("'build' added %d bytes to the buffer\n", p);
nobukuma 0:003889bc474f 352 if (cs == 0) { //this is not a continuation
nobukuma 0:003889bc474f 353 buf[byteCount+7] = 0;
nobukuma 0:003889bc474f 354 } else { //this is a continuation
nobukuma 0:003889bc474f 355 memcpy(buf+7, buf+7+cs, byteCount);//move part of interrest to beginning of buffer
nobukuma 0:003889bc474f 356 buf[byteCount+7] = 2;
nobukuma 0:003889bc474f 357 buf[byteCount+8] = cont>>8;
nobukuma 0:003889bc474f 358 buf[byteCount+9] = cont;
nobukuma 0:003889bc474f 359 }
nobukuma 0:003889bc474f 360 //printfBytes("SDP Send: ", buf, parlen+5);
nobukuma 0:003889bc474f 361 int retval = Socket_Send(serverSock, _buf, parlen + 5 + OFFSET);
nobukuma 0:003889bc474f 362 delete[] _buf;
nobukuma 0:003889bc474f 363 return retval;
nobukuma 0:003889bc474f 364 }
nobukuma 0:003889bc474f 365
nobukuma 0:003889bc474f 366 //unsigned SDPHandler::getval(const unsigned char *p, int n) {
nobukuma 0:003889bc474f 367 unsigned getval(const unsigned char *p, int n) {
nobukuma 0:003889bc474f 368 unsigned ret = 0;
nobukuma 0:003889bc474f 369 for (int i = 0; i < n; i++)
nobukuma 0:003889bc474f 370 ret = (ret<<8) + (unsigned)p[i];
nobukuma 0:003889bc474f 371 return ret;
nobukuma 0:003889bc474f 372 }
nobukuma 0:003889bc474f 373
nobukuma 0:003889bc474f 374 //unsigned SDPHandler::length(const unsigned char *el, unsigned &p) {
nobukuma 0:003889bc474f 375 unsigned length(const unsigned char *el, unsigned &p) {
nobukuma 0:003889bc474f 376 unsigned len = 0;
nobukuma 0:003889bc474f 377 switch (el[p++] & 7) {//length
nobukuma 0:003889bc474f 378 case 0:
nobukuma 0:003889bc474f 379 len = 1;
nobukuma 0:003889bc474f 380 break;
nobukuma 0:003889bc474f 381 case 1:
nobukuma 0:003889bc474f 382 len = 2;
nobukuma 0:003889bc474f 383 break;
nobukuma 0:003889bc474f 384 case 2:
nobukuma 0:003889bc474f 385 len = 4;
nobukuma 0:003889bc474f 386 break;
nobukuma 0:003889bc474f 387 case 3:
nobukuma 0:003889bc474f 388 len = 8;
nobukuma 0:003889bc474f 389 break;
nobukuma 0:003889bc474f 390 case 4:
nobukuma 0:003889bc474f 391 len = 16;
nobukuma 0:003889bc474f 392 break;
nobukuma 0:003889bc474f 393 case 7://4bytes
nobukuma 0:003889bc474f 394 len= el[p++]<<24;
nobukuma 0:003889bc474f 395 len += el[p++]<<16;
nobukuma 0:003889bc474f 396 case 6://2bytes
nobukuma 0:003889bc474f 397 len += el[p++]<<8;
nobukuma 0:003889bc474f 398 case 5://1byte
nobukuma 0:003889bc474f 399 len += el[p++];
nobukuma 0:003889bc474f 400 break;
nobukuma 0:003889bc474f 401 }
nobukuma 0:003889bc474f 402 return len;
nobukuma 0:003889bc474f 403 }
nobukuma 0:003889bc474f 404
nobukuma 0:003889bc474f 405 extern "C" void HardFault_Handler() {
nobukuma 0:003889bc474f 406 printf("Hard Fault! %d bytes left\n", AvailableMemory(1));
nobukuma 0:003889bc474f 407 while (1);
nobukuma 0:003889bc474f 408 }
nobukuma 0:003889bc474f 409
nobukuma 0:003889bc474f 410 unsigned SDPHandler::parseLight (const unsigned char *el, unsigned count, sdp_data* &result, serv_rec* &record) {
nobukuma 0:003889bc474f 411 unsigned p = 0;
nobukuma 0:003889bc474f 412 unsigned len = length(el, p);
nobukuma 0:003889bc474f 413 int end = p+len;//end is the index of the item just after the sequence
nobukuma 0:003889bc474f 414 sdp_data *item = 0;
nobukuma 0:003889bc474f 415 switch (el[0]>>3) {//type
nobukuma 0:003889bc474f 416 case sdp_data::NULL_:
nobukuma 0:003889bc474f 417 printf("NULL ");
nobukuma 0:003889bc474f 418 break;
nobukuma 0:003889bc474f 419 case sdp_data::UNSIGNED:
nobukuma 0:003889bc474f 420 printf("UINT%d=%u ", len, (unsigned)getval(el+p, len));
nobukuma 0:003889bc474f 421 break;
nobukuma 0:003889bc474f 422 case sdp_data::SIGNED:
nobukuma 0:003889bc474f 423 printf("INT%d=%d ", len, (unsigned)getval(el+p, len));
nobukuma 0:003889bc474f 424 break;
nobukuma 0:003889bc474f 425 case sdp_data::UUID:
nobukuma 0:003889bc474f 426 if (len==16) {
nobukuma 0:003889bc474f 427 printf("UUID16= ");
nobukuma 0:003889bc474f 428 for (int i = 0; i < 16; i++)
nobukuma 0:003889bc474f 429 printf("%02x ", el[p+i]);
nobukuma 0:003889bc474f 430 } else
nobukuma 0:003889bc474f 431 printf("UUID%d=%u ", len, (unsigned)getval(el+p, len));
nobukuma 0:003889bc474f 432 break;
nobukuma 0:003889bc474f 433 case sdp_data::STRING:
nobukuma 0:003889bc474f 434 printf("STR%d='%s' ", len, (char*)el+p);
nobukuma 0:003889bc474f 435 break;
nobukuma 0:003889bc474f 436 case sdp_data::BOOL:
nobukuma 0:003889bc474f 437 printf("BOOL%d=%d ", len, (unsigned)getval(el+p, len));
nobukuma 0:003889bc474f 438 break;
nobukuma 0:003889bc474f 439 case sdp_data::SEQUENCE:
nobukuma 0:003889bc474f 440 goto skip;
nobukuma 0:003889bc474f 441 case sdp_data::ALTERNATIVE:
nobukuma 0:003889bc474f 442 skip: {//p points just after the length indicator, hence at the first item IN the sequence
nobukuma 0:003889bc474f 443 printf("SEQ%d{%p ", len, item);
nobukuma 0:003889bc474f 444 int n = 0;
nobukuma 0:003889bc474f 445 unsigned short key;
nobukuma 0:003889bc474f 446 serv_rec *dummy = 0;
nobukuma 0:003889bc474f 447 while (p < end) {
nobukuma 0:003889bc474f 448 sdp_data *elem = 0;
nobukuma 0:003889bc474f 449 p += parseLight(el + p, len-p, elem, dummy);//parse each element in the sequence, the second arg is as yet unused
nobukuma 0:003889bc474f 450 if (record) {
nobukuma 0:003889bc474f 451 if (n & 1) { //value
nobukuma 0:003889bc474f 452 record->insert(pair<unsigned short, sdp_data*>(key, elem));
nobukuma 0:003889bc474f 453 } else //key
nobukuma 0:003889bc474f 454 key = n;
nobukuma 0:003889bc474f 455 n++;
nobukuma 0:003889bc474f 456 }
nobukuma 0:003889bc474f 457 }
nobukuma 0:003889bc474f 458 }
nobukuma 0:003889bc474f 459 printf("}\n");
nobukuma 0:003889bc474f 460 break;
nobukuma 0:003889bc474f 461 case 8:
nobukuma 0:003889bc474f 462 printf("URL%d='%s' ", len, (char*)el+p);
nobukuma 0:003889bc474f 463 break;
nobukuma 0:003889bc474f 464 default:
nobukuma 0:003889bc474f 465 printf("Parse: Unknown type %d, len=%d (code=%#02X)\n", el[0]>>3, len, el[0]);
nobukuma 0:003889bc474f 466 }
nobukuma 0:003889bc474f 467 result = item;
nobukuma 0:003889bc474f 468 return end;
nobukuma 0:003889bc474f 469 }
nobukuma 0:003889bc474f 470
nobukuma 0:003889bc474f 471 unsigned SDPHandler::parse (const unsigned char *el, unsigned count, sdp_data* &result, serv_rec* &record) {
nobukuma 0:003889bc474f 472 unsigned p = 0;
nobukuma 0:003889bc474f 473 unsigned len = length(el, p);
nobukuma 0:003889bc474f 474 int end = p+len;//end is the index of the item just after the sequence
nobukuma 0:003889bc474f 475 sdp_data *item = 0;
nobukuma 0:003889bc474f 476 switch (el[0]>>3) {//type
nobukuma 0:003889bc474f 477 case sdp_data::NULL_:
nobukuma 0:003889bc474f 478 item = new sdp_data();
nobukuma 0:003889bc474f 479 break;
nobukuma 0:003889bc474f 480 case sdp_data::UNSIGNED:
nobukuma 0:003889bc474f 481 item = new sdp_data((unsigned)getval(el+p, len), len);
nobukuma 0:003889bc474f 482 break;
nobukuma 0:003889bc474f 483 case sdp_data::SIGNED:
nobukuma 0:003889bc474f 484 item = new sdp_data((int)getval(el+p, len), len);
nobukuma 0:003889bc474f 485 break;
nobukuma 0:003889bc474f 486 case sdp_data::UUID:
nobukuma 0:003889bc474f 487 if (len==16) {
nobukuma 0:003889bc474f 488 char rev[16];
nobukuma 0:003889bc474f 489 for (int i = 0; i < 16; i++)
nobukuma 0:003889bc474f 490 rev[i] = el[p+15-i];
nobukuma 0:003889bc474f 491 item = new sdp_data(sdp_data::UUID, rev, len);
nobukuma 0:003889bc474f 492 } else
nobukuma 0:003889bc474f 493 item = new sdp_data(sdp_data::UUID, getval(el+p, len), len);
nobukuma 0:003889bc474f 494 break;
nobukuma 0:003889bc474f 495 case sdp_data::STRING:
nobukuma 0:003889bc474f 496 item = new sdp_data((char*)el+p, len);
nobukuma 0:003889bc474f 497 break;
nobukuma 0:003889bc474f 498 case sdp_data::BOOL:
nobukuma 0:003889bc474f 499 item = new sdp_data((bool)getval(el+p, len), len);
nobukuma 0:003889bc474f 500 break;
nobukuma 0:003889bc474f 501 case sdp_data::SEQUENCE:
nobukuma 0:003889bc474f 502 item = new sdp_data(sdp_data::SEQUENCE);
nobukuma 0:003889bc474f 503 goto skip;
nobukuma 0:003889bc474f 504 case sdp_data::ALTERNATIVE:
nobukuma 0:003889bc474f 505 item = new sdp_data(sdp_data::ALTERNATIVE);
nobukuma 0:003889bc474f 506 skip: {//p points just after the length indicator, hence at the first item IN the sequence
nobukuma 0:003889bc474f 507 //printf("SEQ%d{%p ", len, item);
nobukuma 0:003889bc474f 508 int n = 0;
nobukuma 0:003889bc474f 509 unsigned short key;
nobukuma 0:003889bc474f 510 serv_rec *dummy = 0;//means: there is no service record to fill in for deeper levels
nobukuma 0:003889bc474f 511 while (p < end) {
nobukuma 0:003889bc474f 512 sdp_data *elem = 0; //this becomes the tree with attribute values
nobukuma 0:003889bc474f 513 p += parse(el + p, len-p, elem, dummy);//parse each element in the sequence, the second arg is as yet unused
nobukuma 0:003889bc474f 514 if (record) { //if at the level of attribute list, add elem to record as key/value pair
nobukuma 0:003889bc474f 515 if (n & 1) { //value
nobukuma 0:003889bc474f 516 record->insert(pair<unsigned short, sdp_data*>(key, elem));
nobukuma 0:003889bc474f 517 } else //key
nobukuma 0:003889bc474f 518 key = elem->asUnsigned();
nobukuma 0:003889bc474f 519 n++;
nobukuma 0:003889bc474f 520 } else //just add the elements to the value tree
nobukuma 0:003889bc474f 521 item->add_element(elem);
nobukuma 0:003889bc474f 522 }
nobukuma 0:003889bc474f 523 }
nobukuma 0:003889bc474f 524 //printf("}\n");
nobukuma 0:003889bc474f 525 break;
nobukuma 0:003889bc474f 526 case 8:
nobukuma 0:003889bc474f 527 item = new sdp_data(sdp_data::URL, (char*)el+p, len);
nobukuma 0:003889bc474f 528 break;
nobukuma 0:003889bc474f 529 default:
nobukuma 0:003889bc474f 530 printf("Parse: Unknown type %d, len=%d (code=%#02X)\n", el[0]>>3, len, el[0]);
nobukuma 0:003889bc474f 531 }
nobukuma 0:003889bc474f 532 result = item;
nobukuma 0:003889bc474f 533 return end;
nobukuma 0:003889bc474f 534 }
nobukuma 0:003889bc474f 535
nobukuma 0:003889bc474f 536 void SDPHandler::append(const unsigned char *payload, int len) {
nobukuma 0:003889bc474f 537 unsigned char *tmp = new unsigned char[byteCount + len];//append the payload to the previous continuation buffer
nobukuma 0:003889bc474f 538 if (contBuf && byteCount) {
nobukuma 0:003889bc474f 539 memcpy(tmp, contBuf, byteCount); //copy the existing part
nobukuma 0:003889bc474f 540 delete[] contBuf;//delete the old buffer
nobukuma 0:003889bc474f 541 }
nobukuma 0:003889bc474f 542 memcpy(tmp+byteCount, payload, len); //append the new part
nobukuma 0:003889bc474f 543 contBuf = tmp;
nobukuma 0:003889bc474f 544 byteCount += len;
nobukuma 0:003889bc474f 545 }
nobukuma 0:003889bc474f 546
nobukuma 0:003889bc474f 547 void SDPHandler::freeBuf() {
nobukuma 0:003889bc474f 548 if (contBuf) {
nobukuma 0:003889bc474f 549 delete[] contBuf;
nobukuma 0:003889bc474f 550 contBuf = 0;
nobukuma 0:003889bc474f 551 }
nobukuma 0:003889bc474f 552 byteCount = 0;
nobukuma 0:003889bc474f 553 }
nobukuma 0:003889bc474f 554
nobukuma 0:003889bc474f 555
nobukuma 0:003889bc474f 556 //TODO: test case 7, add server support (cases 2, 4, 6)
nobukuma 0:003889bc474f 557 //3 cases: cont==0 && contBuf==0 -> use rsp; cont!=0 -> append; cont==0 && contBuf!=0 -> append and use contBuf
nobukuma 0:003889bc474f 558 int SDPHandler::parseRsp(const unsigned char*rsp, int len) {
nobukuma 0:003889bc474f 559 //unsigned tid = rsp[2] + ((unsigned)rsp[1]<<8);
nobukuma 0:003889bc474f 560 unsigned parlen = rsp[4] + ((unsigned)rsp[3]<<8);
nobukuma 0:003889bc474f 561 //printf("ParseRsp: tid=%04X, parlen=%d ", tid, parlen);
nobukuma 0:003889bc474f 562 unsigned cont = 0;
nobukuma 0:003889bc474f 563 switch (rsp[0]) {
nobukuma 0:003889bc474f 564 case 1: {//errorRsp
nobukuma 0:003889bc474f 565 unsigned errorcode = rsp[6] + ((unsigned)rsp[5]<<8);
nobukuma 0:003889bc474f 566 if (parlen > 2) {
nobukuma 0:003889bc474f 567 printf("ErrorInfo (%d bytes) for error %d is available\n", parlen-2, errorcode);
nobukuma 0:003889bc474f 568 }
nobukuma 0:003889bc474f 569 if (ErrorResponse)
nobukuma 0:003889bc474f 570 ErrorResponse(errorcode);
nobukuma 0:003889bc474f 571 return errorcode;
nobukuma 0:003889bc474f 572 }
nobukuma 0:003889bc474f 573 //break;
nobukuma 0:003889bc474f 574 case 3: { //servicesearchRsp
nobukuma 0:003889bc474f 575 unsigned total = rsp[6] + ((unsigned)rsp[5]<<8);
nobukuma 0:003889bc474f 576 unsigned current = rsp[8] + ((unsigned)rsp[7]<<8);
nobukuma 0:003889bc474f 577 cont = rsp[9+4*current];
nobukuma 0:003889bc474f 578 memcpy(contState, &rsp[9+4*current], cont+1);//copy the continuation state
nobukuma 0:003889bc474f 579 //printf("total=%d, current=%d, cont=%d\n", total, current, cont);
nobukuma 0:003889bc474f 580 if (cont) {
nobukuma 0:003889bc474f 581 //no special handling here, just append the servicerecordhandles
nobukuma 0:003889bc474f 582 }
nobukuma 0:003889bc474f 583 //linear list of 32bit service-handles
nobukuma 0:003889bc474f 584 for (int i = 0; i < current; i++) {
nobukuma 0:003889bc474f 585 unsigned result = 0;
nobukuma 0:003889bc474f 586 for (int j = 0; j< 4; j++)
nobukuma 0:003889bc474f 587 result = (result<<8) + rsp[9 + 4*i + j];
nobukuma 0:003889bc474f 588 printf("SDP Search handle %08X\n", result);
nobukuma 0:003889bc474f 589 services.insert(pair<unsigned, serv_rec*>(result, 0));
nobukuma 0:003889bc474f 590 }
nobukuma 0:003889bc474f 591 if (ServiceSearchResponse)
nobukuma 0:003889bc474f 592 ServiceSearchResponse();
nobukuma 0:003889bc474f 593 }
nobukuma 0:003889bc474f 594 break;
nobukuma 0:003889bc474f 595 case 5: { //serviceattributeRsp
nobukuma 0:003889bc474f 596 unsigned count = rsp[6] + ((unsigned)rsp[5]<<8);//bytes in this part of the attribute list
nobukuma 0:003889bc474f 597 // append(rsp+7, count);
nobukuma 0:003889bc474f 598 cont = rsp[7+count];
nobukuma 0:003889bc474f 599 memcpy(contState, &rsp[7+count], cont+1);//copy the continuation state
nobukuma 0:003889bc474f 600 if (cont) {
nobukuma 0:003889bc474f 601 append(rsp+7, count);
nobukuma 0:003889bc474f 602 break;
nobukuma 0:003889bc474f 603 }
nobukuma 0:003889bc474f 604 //printf("count=%d parsing...\n", byteCount);
nobukuma 0:003889bc474f 605 serv_rec *serv = new serv_rec;
nobukuma 0:003889bc474f 606 if (contBuf) {
nobukuma 0:003889bc474f 607 append(rsp+7, count);
nobukuma 0:003889bc474f 608 parse(contBuf, byteCount, tree, serv);
nobukuma 0:003889bc474f 609 } else
nobukuma 0:003889bc474f 610 parse(rsp+7, count, tree, serv);
nobukuma 0:003889bc474f 611 //printf("...parsing done, ");
nobukuma 0:003889bc474f 612 //get the AttributeID, make sure attribId 0 is always included in the request
nobukuma 0:003889bc474f 613 unsigned key = (*serv)[0]->asUnsigned();//AttributeID '0' always refers to the serviceID
nobukuma 0:003889bc474f 614 //printf("Key=%#X\n", key); //key will be 0 when not requested
nobukuma 0:003889bc474f 615 services[key] = serv; //Add the attribute list to the services
nobukuma 0:003889bc474f 616 freeBuf();
nobukuma 0:003889bc474f 617 if (ServiceAttributeResponse)
nobukuma 0:003889bc474f 618 ServiceAttributeResponse(serv);
nobukuma 0:003889bc474f 619 }
nobukuma 0:003889bc474f 620 break;
nobukuma 0:003889bc474f 621 //below is UNTESTED
nobukuma 0:003889bc474f 622 case 7: { //servicesearchattributeRsp
nobukuma 0:003889bc474f 623 unsigned count = rsp[6] + ((unsigned)rsp[5]<<8);
nobukuma 0:003889bc474f 624 append(rsp+7, count);
nobukuma 0:003889bc474f 625 cont = rsp[7+count];
nobukuma 0:003889bc474f 626 memcpy(contState, &rsp[7+count], cont+1);
nobukuma 0:003889bc474f 627 if (cont)
nobukuma 0:003889bc474f 628 break;
nobukuma 0:003889bc474f 629 unsigned pos = 0;
nobukuma 0:003889bc474f 630 if (contBuf[pos]>>3 != sdp_data::SEQUENCE) {
nobukuma 0:003889bc474f 631 printf("Expected a sequence of attribute lists\n");
nobukuma 0:003889bc474f 632 break;
nobukuma 0:003889bc474f 633 }
nobukuma 0:003889bc474f 634 unsigned len = length(contBuf, pos);//get the length of the list of lists and advance pos to the first list
nobukuma 0:003889bc474f 635 while (pos<len) {
nobukuma 0:003889bc474f 636 printf("pos=%d, count=%d, parsing...\n", pos, len);
nobukuma 0:003889bc474f 637 serv_rec *serv = new serv_rec;
nobukuma 0:003889bc474f 638 pos = parse(contBuf+pos, len, tree, serv);
nobukuma 0:003889bc474f 639 unsigned key = (*serv)[0]->asUnsigned();
nobukuma 0:003889bc474f 640 services[key] = serv;
nobukuma 0:003889bc474f 641 }
nobukuma 0:003889bc474f 642 freeBuf();
nobukuma 0:003889bc474f 643 printf("...parsing done, pos=%d\n", pos);
nobukuma 0:003889bc474f 644 if (ServiceSearchAttributeResponse)
nobukuma 0:003889bc474f 645 ServiceSearchAttributeResponse();
nobukuma 0:003889bc474f 646 }
nobukuma 0:003889bc474f 647 break;
nobukuma 0:003889bc474f 648 default:
nobukuma 0:003889bc474f 649 printf("Unknown SDP response type %02X\n", rsp[0]);
nobukuma 0:003889bc474f 650 break;
nobukuma 0:003889bc474f 651 }
nobukuma 0:003889bc474f 652 return 0;
nobukuma 0:003889bc474f 653 }
nobukuma 0:003889bc474f 654
nobukuma 0:003889bc474f 655 //************************ SERVER related *******************************************//
nobukuma 0:003889bc474f 656
nobukuma 0:003889bc474f 657 //unsigned SDPHandler::parseUUID(const u8* data, int len, unsigned &p) {
nobukuma 0:003889bc474f 658 unsigned parseUUID(const u8* data, int len, unsigned &p) {
nobukuma 0:003889bc474f 659 unsigned u = 0;
nobukuma 0:003889bc474f 660 if ((data[p]>>3) != sdp_data::UUID) {
nobukuma 0:003889bc474f 661 printf(" UUID expected, got %d ", data[p]>>3);
nobukuma 0:003889bc474f 662 return (unsigned)-1;
nobukuma 0:003889bc474f 663 }
nobukuma 0:003889bc474f 664 switch (data[p++] & 7) {
nobukuma 0:003889bc474f 665 case 1:
nobukuma 0:003889bc474f 666 u = getval(data+p, 2);
nobukuma 0:003889bc474f 667 p +=2;
nobukuma 0:003889bc474f 668 break;
nobukuma 0:003889bc474f 669 case 2:
nobukuma 0:003889bc474f 670 u = getval(data+p, 4);
nobukuma 0:003889bc474f 671 p += 4;
nobukuma 0:003889bc474f 672 break;
nobukuma 0:003889bc474f 673 case 4:
nobukuma 0:003889bc474f 674 u = getval(data+p, 4);
nobukuma 0:003889bc474f 675 p += 16;
nobukuma 0:003889bc474f 676 break;
nobukuma 0:003889bc474f 677 default:
nobukuma 0:003889bc474f 678 printf(" UUID must be 2, 4 or 16 bytes, got type %d\n", data[p-1]);
nobukuma 0:003889bc474f 679 }
nobukuma 0:003889bc474f 680 return u;
nobukuma 0:003889bc474f 681 }
nobukuma 0:003889bc474f 682
nobukuma 0:003889bc474f 683 #define SVC_HANDLE 0x0001001DU //serial service
nobukuma 0:003889bc474f 684 void SDPManager::buildServer() {
nobukuma 0:003889bc474f 685 static sdp_data rfcomm(sdp_data::SEQUENCE);
nobukuma 0:003889bc474f 686 static sdp_data l2cap(sdp_data::SEQUENCE);
nobukuma 0:003889bc474f 687 static sdp_data protocol(sdp_data::SEQUENCE);
nobukuma 0:003889bc474f 688 static sdp_data serviceclass(sdp_data::SEQUENCE);
nobukuma 0:003889bc474f 689 static sdp_data browsegroup(sdp_data::SEQUENCE);
nobukuma 0:003889bc474f 690 static sdp_data root(sdp_data::UUID, BROWSEROOT);
nobukuma 0:003889bc474f 691 static sdp_data l2capuuid(sdp_data::UUID, 0x0100);
nobukuma 0:003889bc474f 692 static sdp_data rfcommuuid(sdp_data::UUID, 0x003);
nobukuma 0:003889bc474f 693 static sdp_data serial(sdp_data::UUID, 0x1101);
nobukuma 0:003889bc474f 694 static sdp_data chan(1U,1);
nobukuma 0:003889bc474f 695 static sdp_data handle(SVC_HANDLE,4);
nobukuma 0:003889bc474f 696 static sdp_data serviceID(0U, 2);
nobukuma 0:003889bc474f 697 // static sdp_data name("MBED BlueUSB RFCOMM Serial");
nobukuma 0:003889bc474f 698 static sdp_data name("Serial Port");
nobukuma 0:003889bc474f 699 rfcomm.add_element(&rfcommuuid);
nobukuma 0:003889bc474f 700 rfcomm.add_element(&chan);
nobukuma 0:003889bc474f 701 l2cap.add_element(&l2capuuid);
nobukuma 0:003889bc474f 702 protocol.add_element(&l2cap);
nobukuma 0:003889bc474f 703 protocol.add_element(&rfcomm);
nobukuma 0:003889bc474f 704 serviceclass.add_element(&serial);
nobukuma 0:003889bc474f 705 browsegroup.add_element(&root);
nobukuma 0:003889bc474f 706 static serv_rec attr_list;
nobukuma 0:003889bc474f 707 attr_list[0] = &handle;
nobukuma 0:003889bc474f 708 attr_list[1] = &serviceclass;
nobukuma 0:003889bc474f 709 attr_list[4] = &protocol;
nobukuma 0:003889bc474f 710 attr_list[5] = &browsegroup;
nobukuma 0:003889bc474f 711 attr_list[0x100] = &name;
nobukuma 0:003889bc474f 712 server[SVC_HANDLE] = &attr_list;//server is static and this statement crashes the program when invoked from the constructor which is also invoked statically
nobukuma 0:003889bc474f 713 }
nobukuma 0:003889bc474f 714
nobukuma 0:003889bc474f 715 int SDPManager::findUUID(unsigned h, unsigned uuid) {
nobukuma 0:003889bc474f 716 serv_rec *rec = server[h];
nobukuma 0:003889bc474f 717 for ( serv_rec::iterator it = rec->begin(); it != rec->end(); it++) {
nobukuma 0:003889bc474f 718 if (it->second->findUUID(uuid))
nobukuma 0:003889bc474f 719 return it->first;
nobukuma 0:003889bc474f 720 }
nobukuma 0:003889bc474f 721 printf("rejected %08X because of %04Xx\n", h, uuid);
nobukuma 0:003889bc474f 722 return -1;
nobukuma 0:003889bc474f 723 }
nobukuma 0:003889bc474f 724
nobukuma 0:003889bc474f 725 void SDPManager::match(bool elig[], unsigned uuid) {
nobukuma 0:003889bc474f 726 map<unsigned, serv_rec*>::iterator idx;
nobukuma 0:003889bc474f 727 int i = 0;
nobukuma 0:003889bc474f 728 for (idx = server.begin(); idx != server.end(); idx++, i++)
nobukuma 0:003889bc474f 729 if (findUUID(idx->first, uuid) < 0)
nobukuma 0:003889bc474f 730 elig[i] = false;
nobukuma 0:003889bc474f 731 }
nobukuma 0:003889bc474f 732
nobukuma 0:003889bc474f 733 bool SDPManager::isInList(unsigned short id, const unsigned char* list, int end) {
nobukuma 0:003889bc474f 734 int len;
nobukuma 0:003889bc474f 735 for (unsigned pos = 0; pos < end; pos += len) {
nobukuma 0:003889bc474f 736 len = length(list, pos);
nobukuma 0:003889bc474f 737 switch (len) {
nobukuma 0:003889bc474f 738 case 2: //single value
nobukuma 0:003889bc474f 739 if (getval(list+pos, 2) == id)
nobukuma 0:003889bc474f 740 return true;
nobukuma 0:003889bc474f 741 break;
nobukuma 0:003889bc474f 742 case 4: //range
nobukuma 0:003889bc474f 743 if (getval(list+pos, 2) > id) break;
nobukuma 0:003889bc474f 744 if (getval(list+pos+2, 2) < id) break;
nobukuma 0:003889bc474f 745 return true;
nobukuma 0:003889bc474f 746 default:
nobukuma 0:003889bc474f 747 printf("Unexpected length %d\n", len);
nobukuma 0:003889bc474f 748 }
nobukuma 0:003889bc474f 749 }
nobukuma 0:003889bc474f 750 return false;
nobukuma 0:003889bc474f 751 }
nobukuma 0:003889bc474f 752
nobukuma 0:003889bc474f 753 void SDPManager::addToReply(sdp_data *svc, serv_rec *list, const unsigned char* att, int end) {
nobukuma 0:003889bc474f 754 unsigned short len, low, high;
nobukuma 0:003889bc474f 755 serv_rec::iterator from, to, idx;
nobukuma 0:003889bc474f 756 if (list==0) {
nobukuma 0:003889bc474f 757 printf("Invalid attribute list (NULL)\n");
nobukuma 0:003889bc474f 758 return;
nobukuma 0:003889bc474f 759 }
nobukuma 0:003889bc474f 760 for (unsigned pos = 0; pos < end; pos += len) {
nobukuma 0:003889bc474f 761 len = length(att, pos);
nobukuma 0:003889bc474f 762 switch (len) {
nobukuma 0:003889bc474f 763 case 2: //single value
nobukuma 0:003889bc474f 764 low = getval(att+pos, 2);
nobukuma 0:003889bc474f 765 svc->add_element(new sdp_data(low, 2));
nobukuma 0:003889bc474f 766 svc->add_element((*list)[low]);
nobukuma 0:003889bc474f 767 printf("Found attrib %d\n", low);
nobukuma 0:003889bc474f 768 break;
nobukuma 0:003889bc474f 769 case 4: //range
nobukuma 0:003889bc474f 770 low = getval(att+pos, 2);
nobukuma 0:003889bc474f 771 high = getval(att+pos+2, 2);
nobukuma 0:003889bc474f 772 from = list->lower_bound(low);
nobukuma 0:003889bc474f 773 to = list->upper_bound(high);
nobukuma 0:003889bc474f 774 for (idx = from; idx != to; idx++) {
nobukuma 0:003889bc474f 775 svc->add_element(new sdp_data(idx->first, 2));
nobukuma 0:003889bc474f 776 svc->add_element(idx->second);
nobukuma 0:003889bc474f 777 printf("Found attrib %d\n", idx->first);
nobukuma 0:003889bc474f 778 }
nobukuma 0:003889bc474f 779 break;
nobukuma 0:003889bc474f 780 default:
nobukuma 0:003889bc474f 781 printf("Unexpected length %d\n", len);
nobukuma 0:003889bc474f 782 }
nobukuma 0:003889bc474f 783 }
nobukuma 0:003889bc474f 784 }
nobukuma 0:003889bc474f 785
nobukuma 0:003889bc474f 786 //for continuations, just generate the entire list, truncate to desired length and append position of the remainder as continuation
nobukuma 0:003889bc474f 787 //on the next iteration, generate the list again, use continuation to find remainder and reiterate
nobukuma 0:003889bc474f 788 void SDPManager::SDPServer(int socket, SocketState state, const u8* data, int len, void* userData) {
nobukuma 0:003889bc474f 789 unsigned tid = data[2] + ((unsigned)data[1]<<8);
nobukuma 0:003889bc474f 790 unsigned parlen = data[4] + ((unsigned)data[3]<<8);
nobukuma 0:003889bc474f 791 //printf("ParseReq: PDU_ID=%d, tid=%04X, parlen=%d ", data[0], tid, parlen);
nobukuma 0:003889bc474f 792 unsigned pos = 5;
nobukuma 0:003889bc474f 793 switch (data[0]) {
nobukuma 0:003889bc474f 794 case 1: {//errorRsp
nobukuma 0:003889bc474f 795 unsigned errorcode = data[6] + ((unsigned)data[5]<<8);
nobukuma 0:003889bc474f 796 if (parlen > 2) {
nobukuma 0:003889bc474f 797 printf("ErrorInfo (%d bytes) for error %d is available\n", parlen-2, errorcode);
nobukuma 0:003889bc474f 798 }
nobukuma 0:003889bc474f 799 errorhandler(errorcode);
nobukuma 0:003889bc474f 800 }
nobukuma 0:003889bc474f 801 break;
nobukuma 0:003889bc474f 802 case 2: { //servicesearchReq
nobukuma 0:003889bc474f 803 printf("servicesearchReq almost implemented\n");
nobukuma 0:003889bc474f 804 unsigned pat[12];//the received search pattern
nobukuma 0:003889bc474f 805 int pn;//number of uuids in the pattern
nobukuma 0:003889bc474f 806 if (data[pos]>>3 != sdp_data::SEQUENCE) {//the uuids are wrapped in a sequence
nobukuma 0:003889bc474f 807 printf("Expected a sequence of UUIDs\n");
nobukuma 0:003889bc474f 808 break;
nobukuma 0:003889bc474f 809 }
nobukuma 0:003889bc474f 810 unsigned end = pos + length(data, pos);//get the length of the list of lists and advance pos to the first list
nobukuma 0:003889bc474f 811 bool *eligible = new bool[server.size()];//marks for the services identified by the search pattern
nobukuma 0:003889bc474f 812 for (int i = 0; i < server.size(); i++) eligible[i] = true;
nobukuma 0:003889bc474f 813 for (pn = 0; pn < 12 && pos < end; pn++) {
nobukuma 0:003889bc474f 814 pat[pn] = parseUUID(data,end, pos);//store uuid from the sequence in the pattern
nobukuma 0:003889bc474f 815 match(eligible, pat[pn]);//unmark a service when it does not contain the uuid
nobukuma 0:003889bc474f 816 //printf("pos=%d, count=%d, uuid=%#X\n", pos, len, pat[pn]);
nobukuma 0:003889bc474f 817 }
nobukuma 0:003889bc474f 818
nobukuma 0:003889bc474f 819 unsigned count = getval(data+pos, 2); //maximum length of attribute list to return
nobukuma 0:003889bc474f 820 pos += 2;
nobukuma 0:003889bc474f 821 unsigned tail = data[pos];
nobukuma 0:003889bc474f 822 if (tail) {
nobukuma 0:003889bc474f 823 tail = getval(data+pos+1, tail);
nobukuma 0:003889bc474f 824 printf("requested continuation tailpos=%u\n", tail);
nobukuma 0:003889bc474f 825 } else {
nobukuma 0:003889bc474f 826 //printf("No continuation requested\n");
nobukuma 0:003889bc474f 827 }
nobukuma 0:003889bc474f 828 unsigned *handles = new unsigned[server.size()];
nobukuma 0:003889bc474f 829 int total = 0, current = 0;
nobukuma 0:003889bc474f 830 map<unsigned, serv_rec*>::iterator idx;
nobukuma 0:003889bc474f 831 int i = 0;
nobukuma 0:003889bc474f 832 for (idx = server.begin(); idx != server.end() && total < count; idx++, i++)
nobukuma 0:003889bc474f 833 if (eligible[i])
nobukuma 0:003889bc474f 834 handles[total++] = idx->first;
nobukuma 0:003889bc474f 835 ServiceSearchReply(tid, handles, total, tail);
nobukuma 0:003889bc474f 836 delete[] handles;
nobukuma 0:003889bc474f 837 delete[] eligible;
nobukuma 0:003889bc474f 838 }
nobukuma 0:003889bc474f 839 break;
nobukuma 0:003889bc474f 840 case 4: { //serviceattributeReq
nobukuma 0:003889bc474f 841 printf("serviceattributeReq almost implemented\n");
nobukuma 0:003889bc474f 842 sdp_data reply(sdp_data::SEQUENCE);//the attributelist of the reply
nobukuma 0:003889bc474f 843 unsigned svcid = getval(data+pos, 4);
nobukuma 0:003889bc474f 844 pos += 4;
nobukuma 0:003889bc474f 845 unsigned count = getval(data+pos, 2); //maximum length of attribute list to return
nobukuma 0:003889bc474f 846 pos += 2;
nobukuma 0:003889bc474f 847 int len = length(data, pos); //get the length of the attributeID list
nobukuma 0:003889bc474f 848 int cont = pos + len;
nobukuma 0:003889bc474f 849 printf("svcid=%08X, count=%u, len=%u, pos=%u\n", svcid, count, len, pos);
nobukuma 0:003889bc474f 850 addToReply(&reply, server[svcid], data+pos, len);
nobukuma 0:003889bc474f 851 unsigned tail = data[cont];
nobukuma 0:003889bc474f 852 printf("tail=%u, reply size=%d\n", tail, reply.Size());
nobukuma 0:003889bc474f 853 if (tail) {
nobukuma 0:003889bc474f 854 tail = getval(data+cont+1, tail);
nobukuma 0:003889bc474f 855 printf("requested continuation tailpos=%u, size=%u\n", tail, reply.Size());
nobukuma 0:003889bc474f 856 } else {
nobukuma 0:003889bc474f 857 //printf("No continuation requested\n");
nobukuma 0:003889bc474f 858 }
nobukuma 0:003889bc474f 859
nobukuma 0:003889bc474f 860 ServiceAttributeReply(tid, &reply, count, tail);
nobukuma 0:003889bc474f 861 for (int k = 0; k < reply.items(); k++) {
nobukuma 0:003889bc474f 862 if ((k & 1) == 0) //even hence ID
nobukuma 0:003889bc474f 863 delete reply.item(k); //destroy the ID
nobukuma 0:003889bc474f 864 reply.remove(k); //set all items to nil to prevent destruction of the DB
nobukuma 0:003889bc474f 865 }
nobukuma 0:003889bc474f 866 }
nobukuma 0:003889bc474f 867 break;
nobukuma 0:003889bc474f 868 case 6: { //servicesearchattributeReq
nobukuma 0:003889bc474f 869 sdp_data reply(sdp_data::SEQUENCE);//the attributelist of the reply
nobukuma 0:003889bc474f 870
nobukuma 0:003889bc474f 871 unsigned pat[12];//the received search pattern
nobukuma 0:003889bc474f 872 int pn;//number of uuids in the pattern
nobukuma 0:003889bc474f 873 if (data[pos]>>3 != sdp_data::SEQUENCE) {//the uuids are wrapped in a sequence
nobukuma 0:003889bc474f 874 printf("Expected a sequence of UUIDs\n");
nobukuma 0:003889bc474f 875 break;
nobukuma 0:003889bc474f 876 }
nobukuma 0:003889bc474f 877 unsigned end = pos + length(data, pos);//get the length of the list of lists and advance pos to the first list
nobukuma 0:003889bc474f 878 bool *eligible = new bool[server.size()];//marks for the services identified by the search pattern
nobukuma 0:003889bc474f 879 for (int i = 0; i < server.size(); i++) eligible[i] = true;
nobukuma 0:003889bc474f 880 for (pn = 0; pn < 12 && pos < end; pn++) {
nobukuma 0:003889bc474f 881 pat[pn] = parseUUID(data,end, pos);//store uuid from the sequence in the pattern
nobukuma 0:003889bc474f 882 match(eligible, pat[pn]);//unmark a service when it does not contain the uuid
nobukuma 0:003889bc474f 883 //printf("pos=%d, count=%d, uuid=%#X\n", pos, len, pat[pn]);
nobukuma 0:003889bc474f 884 }
nobukuma 0:003889bc474f 885
nobukuma 0:003889bc474f 886 unsigned count = getval(data+pos, 2); //maximum length of attribute list to return
nobukuma 0:003889bc474f 887 pos += 2;
nobukuma 0:003889bc474f 888
nobukuma 0:003889bc474f 889 int len = length(data, pos); //get the length of the attributeID list
nobukuma 0:003889bc474f 890 int cont = pos + len;
nobukuma 0:003889bc474f 891 //printf("Count = %d pos=%d, data[pos]=%02x, len=%d, cont=%d\n", count, pos, data[pos], len, cont);
nobukuma 0:003889bc474f 892 int i = 0;
nobukuma 0:003889bc474f 893 for (map<unsigned, serv_rec*>::iterator idx = server.begin(); idx != server.end(); idx++, i++) {//foreach service
nobukuma 0:003889bc474f 894 //printf("testing service handle %08X\n", idx->first);
nobukuma 0:003889bc474f 895 if (!eligible[i]) continue; //skip services that don't match the pattern
nobukuma 0:003889bc474f 896 sdp_data *svc = new sdp_data(sdp_data::SEQUENCE); //create a sequence for the attributes of the present service
nobukuma 0:003889bc474f 897 #if 0
nobukuma 0:003889bc474f 898 for (serv_rec::iterator attr = idx->second->begin(); attr != idx->second->end(); attr++) {//foreach attrib in the service
nobukuma 0:003889bc474f 899 //printf("testing attribID %u\n", attr->first);
nobukuma 0:003889bc474f 900 if (isInList(attr->first, data+pos, len)) {//check if it is requested
nobukuma 0:003889bc474f 901 printf("Found attribID %d\n", attr->first);
nobukuma 0:003889bc474f 902 sdp_data *p = attr->second; //the attribute
nobukuma 0:003889bc474f 903 svc->add_element(new sdp_data(attr->first, 2)); //add the attribute ID as an unsigned short
nobukuma 0:003889bc474f 904 svc->add_element(p); //add the attribute
nobukuma 0:003889bc474f 905 //printf("appending %d bytes\n", p->Size());
nobukuma 0:003889bc474f 906 }
nobukuma 0:003889bc474f 907 }
nobukuma 0:003889bc474f 908 #else
nobukuma 0:003889bc474f 909 //alternatively use map::lower/upper_bound and equal_range, needs only one pass over the range list for each service
nobukuma 0:003889bc474f 910 addToReply(svc, idx->second, data+pos, len);
nobukuma 0:003889bc474f 911 #endif
nobukuma 0:003889bc474f 912 reply.add_element(svc); //append the new attribute list to the reply list
nobukuma 0:003889bc474f 913 }
nobukuma 0:003889bc474f 914
nobukuma 0:003889bc474f 915 unsigned tail = data[cont];
nobukuma 0:003889bc474f 916 if (tail) {
nobukuma 0:003889bc474f 917 tail = getval(data+cont+1, tail);
nobukuma 0:003889bc474f 918 printf("requested continuation tailpos=%u, size=%u\n", tail, reply.Size());
nobukuma 0:003889bc474f 919 } else {
nobukuma 0:003889bc474f 920 //printf("No continuation requested\n");
nobukuma 0:003889bc474f 921 }
nobukuma 0:003889bc474f 922 ServiceSearchAttributeReply(tid, &reply, count, tail);
nobukuma 0:003889bc474f 923
nobukuma 0:003889bc474f 924 for (int j = 0; j < reply.items(); j++) {
nobukuma 0:003889bc474f 925 sdp_data *al = reply.item(j);
nobukuma 0:003889bc474f 926 for (int k = 0; k < al->items(); k++) {
nobukuma 0:003889bc474f 927 if ((k & 1) == 0) //even hence ID
nobukuma 0:003889bc474f 928 delete al->item(k); //destroy the ID
nobukuma 0:003889bc474f 929 al->remove(k); //set all items to nil to prevent destruction of the DB
nobukuma 0:003889bc474f 930 }
nobukuma 0:003889bc474f 931 delete al; //destroy the list;
nobukuma 0:003889bc474f 932 reply.remove(j);
nobukuma 0:003889bc474f 933 }
nobukuma 0:003889bc474f 934 delete[] eligible;
nobukuma 0:003889bc474f 935 }
nobukuma 0:003889bc474f 936 break;
nobukuma 0:003889bc474f 937 default:
nobukuma 0:003889bc474f 938 printf("Unknown SDP request type %02X\n", data[0]);
nobukuma 0:003889bc474f 939 break;
nobukuma 0:003889bc474f 940 }
nobukuma 0:003889bc474f 941 }