Annotation of qemu/hw/bt-sdp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Service Discover Protocol server for QEMU L2CAP devices
                      3:  *
                      4:  * Copyright (C) 2008 Andrzej Zaborowski  <[email protected]>
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or
                      7:  * modify it under the terms of the GNU General Public License as
                      8:  * published by the Free Software Foundation; either version 2 of
                      9:  * the License, or (at your option) any later version.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful,
                     12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     14:  * GNU General Public License for more details.
                     15:  *
                     16:  * You should have received a copy of the GNU General Public License along
                     17:  * with this program; if not, write to the Free Software Foundation, Inc.,
                     18:  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
                     19:  */
                     20: 
                     21: #include "qemu-common.h"
                     22: #include "bt.h"
                     23: 
                     24: struct bt_l2cap_sdp_state_s {
                     25:     struct bt_l2cap_conn_params_s *channel;
                     26: 
                     27:     struct sdp_service_record_s {
                     28:         int match;
                     29: 
                     30:         int *uuid;
                     31:         int uuids;
                     32:         struct sdp_service_attribute_s {
                     33:             int match;
                     34: 
                     35:             int attribute_id;
                     36:             int len;
                     37:             void *pair;
                     38:         } *attribute_list;
                     39:         int attributes;
                     40:     } *service_list;
                     41:     int services;
                     42: };
                     43: 
                     44: static ssize_t sdp_datalen(const uint8_t **element, ssize_t *left)
                     45: {
                     46:     size_t len = *(*element) ++ & SDP_DSIZE_MASK;
                     47: 
                     48:     if (!*left)
                     49:         return -1;
                     50:     (*left) --;
                     51: 
                     52:     if (len < SDP_DSIZE_NEXT1)
                     53:         return 1 << len;
                     54:     else if (len == SDP_DSIZE_NEXT1) {
                     55:         if (*left < 1)
                     56:             return -1;
                     57:         (*left) --;
                     58: 
                     59:         return *(*element) ++;
                     60:     } else if (len == SDP_DSIZE_NEXT2) {
                     61:         if (*left < 2)
                     62:             return -1;
                     63:         (*left) -= 2;
                     64: 
                     65:         len = (*(*element) ++) << 8;
                     66:         return len | (*(*element) ++);
                     67:     } else {
                     68:         if (*left < 4)
                     69:             return -1;
                     70:         (*left) -= 4;
                     71: 
                     72:         len = (*(*element) ++) << 24;
                     73:         len |= (*(*element) ++) << 16;
                     74:         len |= (*(*element) ++) << 8;
                     75:         return len | (*(*element) ++);
                     76:     }
                     77: }
                     78: 
                     79: static const uint8_t bt_base_uuid[12] = {
                     80:     0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb,
                     81: };
                     82: 
                     83: static int sdp_uuid_match(struct sdp_service_record_s *record,
                     84:                 const uint8_t *uuid, ssize_t datalen)
                     85: {
                     86:     int *lo, hi, val;
                     87: 
                     88:     if (datalen == 16 || datalen == 4) {
                     89:         if (datalen == 16 && memcmp(uuid + 4, bt_base_uuid, 12))
                     90:             return 0;
                     91: 
                     92:         if (uuid[0] | uuid[1])
                     93:             return 0;
                     94:         uuid += 2;
                     95:     }
                     96: 
                     97:     val = (uuid[0] << 8) | uuid[1];
                     98:     lo = record->uuid;
                     99:     hi = record->uuids;
                    100:     while (hi >>= 1)
                    101:         if (lo[hi] <= val)
                    102:             lo += hi;
                    103: 
                    104:     return *lo == val;
                    105: }
                    106: 
                    107: #define CONTINUATION_PARAM_SIZE        (1 + sizeof(int))
                    108: #define MAX_PDU_OUT_SIZE       96      /* Arbitrary */
                    109: #define PDU_HEADER_SIZE                5
                    110: #define MAX_RSP_PARAM_SIZE     (MAX_PDU_OUT_SIZE - PDU_HEADER_SIZE - \
                    111:                 CONTINUATION_PARAM_SIZE)
                    112: 
                    113: static int sdp_svc_match(struct bt_l2cap_sdp_state_s *sdp,
                    114:                 const uint8_t **req, ssize_t *len)
                    115: {
                    116:     size_t datalen;
                    117:     int i;
                    118: 
                    119:     if ((**req & ~SDP_DSIZE_MASK) != SDP_DTYPE_UUID)
                    120:         return 1;
                    121: 
                    122:     datalen = sdp_datalen(req, len);
                    123:     if (datalen != 2 && datalen != 4 && datalen != 16)
                    124:         return 1;
                    125: 
                    126:     for (i = 0; i < sdp->services; i ++)
                    127:         if (sdp_uuid_match(&sdp->service_list[i], *req, datalen))
                    128:             sdp->service_list[i].match = 1;
                    129: 
                    130:     (*req) += datalen;
                    131:     (*len) -= datalen;
                    132: 
                    133:     return 0;
                    134: }
                    135: 
                    136: static ssize_t sdp_svc_search(struct bt_l2cap_sdp_state_s *sdp,
                    137:                 uint8_t *rsp, const uint8_t *req, ssize_t len)
                    138: {
                    139:     ssize_t seqlen;
                    140:     int i, count, start, end, max;
                    141:     int32_t handle;
                    142: 
                    143:     /* Perform the search */
                    144:     for (i = 0; i < sdp->services; i ++)
                    145:         sdp->service_list[i].match = 0;
                    146: 
                    147:     if (len < 1)
                    148:         return -SDP_INVALID_SYNTAX;
                    149:     if ((*req & ~SDP_DSIZE_MASK) == SDP_DTYPE_SEQ) {
                    150:         seqlen = sdp_datalen(&req, &len);
                    151:         if (seqlen < 3 || len < seqlen)
                    152:             return -SDP_INVALID_SYNTAX;
                    153:         len -= seqlen;
                    154: 
                    155:         while (seqlen)
                    156:             if (sdp_svc_match(sdp, &req, &seqlen))
                    157:                 return -SDP_INVALID_SYNTAX;
                    158:     } else if (sdp_svc_match(sdp, &req, &seqlen))
                    159:         return -SDP_INVALID_SYNTAX;
                    160: 
                    161:     if (len < 3)
                    162:         return -SDP_INVALID_SYNTAX;
                    163:     end = (req[0] << 8) | req[1];
                    164:     req += 2;
                    165:     len -= 2;
                    166: 
                    167:     if (*req) {
                    168:         if (len <= sizeof(int))
                    169:             return -SDP_INVALID_SYNTAX;
                    170:         len -= sizeof(int);
                    171:         memcpy(&start, req + 1, sizeof(int));
                    172:     } else
                    173:         start = 0;
                    174: 
                    175:     if (len > 1);
                    176:         return -SDP_INVALID_SYNTAX;
                    177: 
                    178:     /* Output the results */
                    179:     len = 4;
                    180:     count = 0;
                    181:     end = start;
                    182:     for (i = 0; i < sdp->services; i ++)
                    183:         if (sdp->service_list[i].match) {
                    184:             if (count >= start && count < max && len + 4 < MAX_RSP_PARAM_SIZE) {
                    185:                 handle = i;
                    186:                 memcpy(rsp + len, &handle, 4);
                    187:                 len += 4;
                    188:                 end = count + 1;
                    189:             }
                    190: 
                    191:             count ++;
                    192:         }
                    193: 
                    194:     rsp[0] = count >> 8;
                    195:     rsp[1] = count & 0xff;
                    196:     rsp[2] = (end - start) >> 8;
                    197:     rsp[3] = (end - start) & 0xff;
                    198: 
                    199:     if (end < count) {
                    200:         rsp[len ++] = sizeof(int);
                    201:         memcpy(rsp + len, &end, sizeof(int));
                    202:         len += 4;
                    203:     } else
                    204:         rsp[len ++] = 0;
                    205: 
                    206:     return len;
                    207: }
                    208: 
                    209: static int sdp_attr_match(struct sdp_service_record_s *record,
                    210:                 const uint8_t **req, ssize_t *len)
                    211: {
                    212:     int i, start, end;
                    213: 
                    214:     if (**req == (SDP_DTYPE_UINT | SDP_DSIZE_2)) {
                    215:         (*req) ++;
                    216:         if (*len < 3)
                    217:             return 1;
                    218: 
                    219:         start = (*(*req) ++) << 8;
                    220:         start |= *(*req) ++;
                    221:         end = start;
                    222:         *len -= 3;
                    223:     } else if (**req == (SDP_DTYPE_UINT | SDP_DSIZE_4)) {
                    224:         (*req) ++;
                    225:         if (*len < 5)
                    226:             return 1;
                    227: 
                    228:         start = (*(*req) ++) << 8;
                    229:         start |= *(*req) ++;
                    230:         end = (*(*req) ++) << 8;
                    231:         end |= *(*req) ++;
                    232:         *len -= 5;
                    233:     } else
                    234:         return 1;
                    235: 
                    236:     for (i = 0; i < record->attributes; i ++)
                    237:         if (record->attribute_list[i].attribute_id >= start &&
                    238:                         record->attribute_list[i].attribute_id <= end)
                    239:             record->attribute_list[i].match = 1;
                    240: 
                    241:     return 0;
                    242: }
                    243: 
                    244: static ssize_t sdp_attr_get(struct bt_l2cap_sdp_state_s *sdp,
                    245:                 uint8_t *rsp, const uint8_t *req, ssize_t len)
                    246: {
                    247:     ssize_t seqlen;
                    248:     int i, start, end, max;
                    249:     int32_t handle;
                    250:     struct sdp_service_record_s *record;
                    251:     uint8_t *lst;
                    252: 
                    253:     /* Perform the search */
                    254:     if (len < 7)
                    255:         return -SDP_INVALID_SYNTAX;
                    256:     memcpy(&handle, req, 4);
                    257:     req += 4;
                    258:     len -= 4;
                    259: 
                    260:     if (handle < 0 || handle > sdp->services)
                    261:         return -SDP_INVALID_RECORD_HANDLE;
                    262:     record = &sdp->service_list[handle];
                    263: 
                    264:     for (i = 0; i < record->attributes; i ++)
                    265:         record->attribute_list[i].match = 0;
                    266: 
                    267:     max = (req[0] << 8) | req[1];
                    268:     req += 2;
                    269:     len -= 2;
                    270:     if (max < 0x0007)
                    271:         return -SDP_INVALID_SYNTAX;
                    272: 
                    273:     if ((*req & ~SDP_DSIZE_MASK) == SDP_DTYPE_SEQ) {
                    274:         seqlen = sdp_datalen(&req, &len);
                    275:         if (seqlen < 3 || len < seqlen)
                    276:             return -SDP_INVALID_SYNTAX;
                    277:         len -= seqlen;
                    278: 
                    279:         while (seqlen)
                    280:             if (sdp_attr_match(record, &req, &seqlen))
                    281:                 return -SDP_INVALID_SYNTAX;
                    282:     } else if (sdp_attr_match(record, &req, &seqlen))
                    283:         return -SDP_INVALID_SYNTAX;
                    284: 
                    285:     if (len < 1)
                    286:         return -SDP_INVALID_SYNTAX;
                    287: 
                    288:     if (*req) {
                    289:         if (len <= sizeof(int))
                    290:             return -SDP_INVALID_SYNTAX;
                    291:         len -= sizeof(int);
                    292:         memcpy(&start, req + 1, sizeof(int));
                    293:     } else
                    294:         start = 0;
                    295: 
                    296:     if (len > 1)
                    297:         return -SDP_INVALID_SYNTAX;
                    298: 
                    299:     /* Output the results */
                    300:     lst = rsp + 2;
                    301:     max = MIN(max, MAX_RSP_PARAM_SIZE);
                    302:     len = 3 - start;
                    303:     end = 0;
                    304:     for (i = 0; i < record->attributes; i ++)
                    305:         if (record->attribute_list[i].match) {
                    306:             if (len >= 0 && len + record->attribute_list[i].len < max) {
                    307:                 memcpy(lst + len, record->attribute_list[i].pair,
                    308:                                 record->attribute_list[i].len);
                    309:                 end = len + record->attribute_list[i].len;
                    310:             }
                    311:             len += record->attribute_list[i].len;
                    312:         }
                    313:     if (0 >= start) {
                    314:        lst[0] = SDP_DTYPE_SEQ | SDP_DSIZE_NEXT2;
                    315:        lst[1] = (len + start - 3) >> 8;
                    316:        lst[2] = (len + start - 3) & 0xff;
                    317:     }
                    318: 
                    319:     rsp[0] = end >> 8;
                    320:     rsp[1] = end & 0xff;
                    321: 
                    322:     if (end < len) {
                    323:         len = end + start;
                    324:         lst[end ++] = sizeof(int);
                    325:         memcpy(lst + end, &len, sizeof(int));
                    326:         end += sizeof(int);
                    327:     } else
                    328:         lst[end ++] = 0;
                    329: 
                    330:     return end + 2;
                    331: }
                    332: 
                    333: static int sdp_svc_attr_match(struct bt_l2cap_sdp_state_s *sdp,
                    334:                 const uint8_t **req, ssize_t *len)
                    335: {
                    336:     int i, j, start, end;
                    337:     struct sdp_service_record_s *record;
                    338: 
                    339:     if (**req == (SDP_DTYPE_UINT | SDP_DSIZE_2)) {
                    340:         (*req) ++;
                    341:         if (*len < 3)
                    342:             return 1;
                    343: 
                    344:         start = (*(*req) ++) << 8;
                    345:         start |= *(*req) ++;
                    346:         end = start;
                    347:         *len -= 3;
                    348:     } else if (**req == (SDP_DTYPE_UINT | SDP_DSIZE_4)) {
                    349:         (*req) ++;
                    350:         if (*len < 5)
                    351:             return 1;
                    352: 
                    353:         start = (*(*req) ++) << 8;
                    354:         start |= *(*req) ++;
                    355:         end = (*(*req) ++) << 8;
                    356:         end |= *(*req) ++;
                    357:         *len -= 5;
                    358:     } else
                    359:         return 1;
                    360: 
                    361:     for (i = 0; i < sdp->services; i ++)
                    362:         if ((record = &sdp->service_list[i])->match)
                    363:             for (j = 0; j < record->attributes; j ++)
                    364:                 if (record->attribute_list[j].attribute_id >= start &&
                    365:                                 record->attribute_list[j].attribute_id <= end)
                    366:                     record->attribute_list[j].match = 1;
                    367: 
                    368:     return 0;
                    369: }
                    370: 
                    371: static ssize_t sdp_svc_search_attr_get(struct bt_l2cap_sdp_state_s *sdp,
                    372:                 uint8_t *rsp, const uint8_t *req, ssize_t len)
                    373: {
                    374:     ssize_t seqlen;
                    375:     int i, j, start, end, max;
                    376:     struct sdp_service_record_s *record;
                    377:     uint8_t *lst;
                    378: 
                    379:     /* Perform the search */
                    380:     for (i = 0; i < sdp->services; i ++) {
                    381:         sdp->service_list[i].match = 0;
                    382:             for (j = 0; j < sdp->service_list[i].attributes; j ++)
                    383:                 sdp->service_list[i].attribute_list[j].match = 0;
                    384:     }
                    385: 
                    386:     if (len < 1)
                    387:         return -SDP_INVALID_SYNTAX;
                    388:     if ((*req & ~SDP_DSIZE_MASK) == SDP_DTYPE_SEQ) {
                    389:         seqlen = sdp_datalen(&req, &len);
                    390:         if (seqlen < 3 || len < seqlen)
                    391:             return -SDP_INVALID_SYNTAX;
                    392:         len -= seqlen;
                    393: 
                    394:         while (seqlen)
                    395:             if (sdp_svc_match(sdp, &req, &seqlen))
                    396:                 return -SDP_INVALID_SYNTAX;
                    397:     } else if (sdp_svc_match(sdp, &req, &seqlen))
                    398:         return -SDP_INVALID_SYNTAX;
                    399: 
                    400:     if (len < 3)
                    401:         return -SDP_INVALID_SYNTAX;
                    402:     max = (req[0] << 8) | req[1];
                    403:     req += 2;
                    404:     len -= 2;
                    405:     if (max < 0x0007)
                    406:         return -SDP_INVALID_SYNTAX;
                    407: 
                    408:     if ((*req & ~SDP_DSIZE_MASK) == SDP_DTYPE_SEQ) {
                    409:         seqlen = sdp_datalen(&req, &len);
                    410:         if (seqlen < 3 || len < seqlen)
                    411:             return -SDP_INVALID_SYNTAX;
                    412:         len -= seqlen;
                    413: 
                    414:         while (seqlen)
                    415:             if (sdp_svc_attr_match(sdp, &req, &seqlen))
                    416:                 return -SDP_INVALID_SYNTAX;
                    417:     } else if (sdp_svc_attr_match(sdp, &req, &seqlen))
                    418:         return -SDP_INVALID_SYNTAX;
                    419: 
                    420:     if (len < 1)
                    421:         return -SDP_INVALID_SYNTAX;
                    422: 
                    423:     if (*req) {
                    424:         if (len <= sizeof(int))
                    425:             return -SDP_INVALID_SYNTAX;
                    426:         len -= sizeof(int);
                    427:         memcpy(&start, req + 1, sizeof(int));
                    428:     } else
                    429:         start = 0;
                    430: 
                    431:     if (len > 1)
                    432:         return -SDP_INVALID_SYNTAX;
                    433: 
                    434:     /* Output the results */
                    435:     /* This assumes empty attribute lists are never to be returned even
                    436:      * for matching Service Records.  In practice this shouldn't happen
                    437:      * as the requestor will usually include the always present
                    438:      * ServiceRecordHandle AttributeID in AttributeIDList.  */
                    439:     lst = rsp + 2;
                    440:     max = MIN(max, MAX_RSP_PARAM_SIZE);
                    441:     len = 3 - start;
                    442:     end = 0;
                    443:     for (i = 0; i < sdp->services; i ++)
                    444:         if ((record = &sdp->service_list[i])->match) {
                    445:             len += 3;
                    446:             seqlen = len;
                    447:             for (j = 0; j < record->attributes; j ++)
                    448:                 if (record->attribute_list[j].match) {
                    449:                     if (len >= 0)
                    450:                         if (len + record->attribute_list[j].len < max) {
                    451:                             memcpy(lst + len, record->attribute_list[j].pair,
                    452:                                             record->attribute_list[j].len);
                    453:                             end = len + record->attribute_list[j].len;
                    454:                         }
                    455:                     len += record->attribute_list[j].len;
                    456:                 }
                    457:             if (seqlen == len)
                    458:                 len -= 3;
                    459:             else if (seqlen >= 3 && seqlen < max) {
                    460:                 lst[seqlen - 3] = SDP_DTYPE_SEQ | SDP_DSIZE_NEXT2;
                    461:                 lst[seqlen - 2] = (len - seqlen) >> 8;
                    462:                 lst[seqlen - 1] = (len - seqlen) & 0xff;
                    463:             }
                    464:         }
                    465:     if (len == 3 - start)
                    466:         len -= 3;
                    467:     else if (0 >= start) {
                    468:        lst[0] = SDP_DTYPE_SEQ | SDP_DSIZE_NEXT2;
                    469:        lst[1] = (len + start - 3) >> 8;
                    470:        lst[2] = (len + start - 3) & 0xff;
                    471:     }
                    472: 
                    473:     rsp[0] = end >> 8;
                    474:     rsp[1] = end & 0xff;
                    475: 
                    476:     if (end < len) {
                    477:         len = end + start;
                    478:         lst[end ++] = sizeof(int);
                    479:         memcpy(lst + end, &len, sizeof(int));
                    480:         end += sizeof(int);
                    481:     } else
                    482:         lst[end ++] = 0;
                    483: 
                    484:     return end + 2;
                    485: }
                    486: 
                    487: static void bt_l2cap_sdp_sdu_in(void *opaque, const uint8_t *data, int len)
                    488: {
                    489:     struct bt_l2cap_sdp_state_s *sdp = opaque;
                    490:     enum bt_sdp_cmd pdu_id;
                    491:     uint8_t rsp[MAX_PDU_OUT_SIZE - PDU_HEADER_SIZE], *sdu_out;
                    492:     int transaction_id, plen;
                    493:     int err = 0;
                    494:     int rsp_len = 0;
                    495: 
                    496:     if (len < 5) {
                    497:         fprintf(stderr, "%s: short SDP PDU (%iB).\n", __FUNCTION__, len);
                    498:         return;
                    499:     }
                    500: 
                    501:     pdu_id = *data ++;
                    502:     transaction_id = (data[0] << 8) | data[1];
                    503:     plen = (data[2] << 8) | data[3];
                    504:     data += 4;
                    505:     len -= 5;
                    506: 
                    507:     if (len != plen) {
                    508:         fprintf(stderr, "%s: wrong SDP PDU length (%iB != %iB).\n",
                    509:                         __FUNCTION__, plen, len);
                    510:         err = SDP_INVALID_PDU_SIZE;
                    511:         goto respond;
                    512:     }
                    513: 
                    514:     switch (pdu_id) {
                    515:     case SDP_SVC_SEARCH_REQ:
                    516:         rsp_len = sdp_svc_search(sdp, rsp, data, len);
                    517:         pdu_id = SDP_SVC_SEARCH_RSP;
                    518:         break;
                    519: 
                    520:     case SDP_SVC_ATTR_REQ:
                    521:         rsp_len = sdp_attr_get(sdp, rsp, data, len);
                    522:         pdu_id = SDP_SVC_ATTR_RSP;
                    523:         break;
                    524: 
                    525:     case SDP_SVC_SEARCH_ATTR_REQ:
                    526:         rsp_len = sdp_svc_search_attr_get(sdp, rsp, data, len);
                    527:         pdu_id = SDP_SVC_SEARCH_ATTR_RSP;
                    528:         break;
                    529: 
                    530:     case SDP_ERROR_RSP:
                    531:     case SDP_SVC_ATTR_RSP:
                    532:     case SDP_SVC_SEARCH_RSP:
                    533:     case SDP_SVC_SEARCH_ATTR_RSP:
                    534:     default:
                    535:         fprintf(stderr, "%s: unexpected SDP PDU ID %02x.\n",
                    536:                         __FUNCTION__, pdu_id);
                    537:         err = SDP_INVALID_SYNTAX;
                    538:         break;
                    539:     }
                    540: 
                    541:     if (rsp_len < 0) {
                    542:         err = -rsp_len;
                    543:         rsp_len = 0;
                    544:     }
                    545: 
                    546: respond:
                    547:     if (err) {
                    548:         pdu_id = SDP_ERROR_RSP;
                    549:         rsp[rsp_len ++] = err >> 8;
                    550:         rsp[rsp_len ++] = err & 0xff;
                    551:     }
                    552: 
                    553:     sdu_out = sdp->channel->sdu_out(sdp->channel, rsp_len + PDU_HEADER_SIZE);
                    554: 
                    555:     sdu_out[0] = pdu_id;
                    556:     sdu_out[1] = transaction_id >> 8;
                    557:     sdu_out[2] = transaction_id & 0xff;
                    558:     sdu_out[3] = rsp_len >> 8;
                    559:     sdu_out[4] = rsp_len & 0xff;
                    560:     memcpy(sdu_out + PDU_HEADER_SIZE, rsp, rsp_len);
                    561: 
                    562:     sdp->channel->sdu_submit(sdp->channel);
                    563: }
                    564: 
                    565: static void bt_l2cap_sdp_close_ch(void *opaque)
                    566: {
                    567:     struct bt_l2cap_sdp_state_s *sdp = opaque;
                    568:     int i;
                    569: 
                    570:     for (i = 0; i < sdp->services; i ++) {
                    571:         qemu_free(sdp->service_list[i].attribute_list->pair);
                    572:         qemu_free(sdp->service_list[i].attribute_list);
                    573:         qemu_free(sdp->service_list[i].uuid);
                    574:     }
                    575:     qemu_free(sdp->service_list);
                    576:     qemu_free(sdp);
                    577: }
                    578: 
                    579: struct sdp_def_service_s {
                    580:     uint16_t class_uuid;
                    581:     struct sdp_def_attribute_s {
                    582:         uint16_t id;
                    583:         struct sdp_def_data_element_s {
                    584:             uint8_t type;
                    585:             union {
                    586:                 uint32_t uint;
                    587:                 const char *str;
                    588:                 struct sdp_def_data_element_s *list;
                    589:             } value;
                    590:         } data;
                    591:     } attributes[];
                    592: };
                    593: 
                    594: /* Calculate a safe byte count to allocate that will store the given
                    595:  * element, at the same time count elements of a UUID type.  */
                    596: static int sdp_attr_max_size(struct sdp_def_data_element_s *element,
                    597:                 int *uuids)
                    598: {
                    599:     int type = element->type & ~SDP_DSIZE_MASK;
                    600:     int len;
                    601: 
                    602:     if (type == SDP_DTYPE_UINT || type == SDP_DTYPE_UUID ||
                    603:                     type == SDP_DTYPE_BOOL) {
                    604:         if (type == SDP_DTYPE_UUID)
                    605:             (*uuids) ++;
                    606:         return 1 + (1 << (element->type & SDP_DSIZE_MASK));
                    607:     }
                    608: 
                    609:     if (type == SDP_DTYPE_STRING || type == SDP_DTYPE_URL) {
                    610:         if (element->type & SDP_DSIZE_MASK) {
                    611:             for (len = 0; element->value.str[len] |
                    612:                             element->value.str[len + 1]; len ++);
                    613:             return len;
                    614:         } else
                    615:             return 2 + strlen(element->value.str);
                    616:     }
                    617: 
                    618:     if (type != SDP_DTYPE_SEQ)
                    619:         exit(-1);
                    620:     len = 2;
                    621:     element = element->value.list;
                    622:     while (element->type)
                    623:         len += sdp_attr_max_size(element ++, uuids);
                    624:     if (len > 255)
                    625:         exit (-1);
                    626: 
                    627:     return len;
                    628: }
                    629: 
                    630: static int sdp_attr_write(uint8_t *data,
                    631:                 struct sdp_def_data_element_s *element, int **uuid)
                    632: {
                    633:     int type = element->type & ~SDP_DSIZE_MASK;
                    634:     int len = 0;
                    635: 
                    636:     if (type == SDP_DTYPE_UINT || type == SDP_DTYPE_BOOL) {
                    637:         data[len ++] = element->type;
                    638:         if ((element->type & SDP_DSIZE_MASK) == SDP_DSIZE_1)
                    639:             data[len ++] = (element->value.uint >>  0) & 0xff;
                    640:         else if ((element->type & SDP_DSIZE_MASK) == SDP_DSIZE_2) {
                    641:             data[len ++] = (element->value.uint >>  8) & 0xff;
                    642:             data[len ++] = (element->value.uint >>  0) & 0xff;
                    643:         } else if ((element->type & SDP_DSIZE_MASK) == SDP_DSIZE_4) {
                    644:             data[len ++] = (element->value.uint >>  24) & 0xff;
                    645:             data[len ++] = (element->value.uint >>  16) & 0xff;
                    646:             data[len ++] = (element->value.uint >>  8) & 0xff;
                    647:             data[len ++] = (element->value.uint >>  0) & 0xff;
                    648:         }
                    649: 
                    650:         return len;
                    651:     }
                    652: 
                    653:     if (type == SDP_DTYPE_UUID) {
                    654:         *(*uuid) ++ = element->value.uint;
                    655: 
                    656:         data[len ++] = element->type;
                    657:         data[len ++] = (element->value.uint >>  24) & 0xff;
                    658:         data[len ++] = (element->value.uint >>  16) & 0xff;
                    659:         data[len ++] = (element->value.uint >>  8) & 0xff;
                    660:         data[len ++] = (element->value.uint >>  0) & 0xff;
                    661:         memcpy(data + len, bt_base_uuid, 12);
                    662: 
                    663:         return len + 12;
                    664:     }
                    665: 
                    666:     data[0] = type | SDP_DSIZE_NEXT1;
                    667:     if (type == SDP_DTYPE_STRING || type == SDP_DTYPE_URL) {
                    668:         if (element->type & SDP_DSIZE_MASK)
                    669:             for (len = 0; element->value.str[len] |
                    670:                             element->value.str[len + 1]; len ++);
                    671:         else
                    672:             len = strlen(element->value.str);
                    673:         memcpy(data + 2, element->value.str, data[1] = len);
                    674: 
                    675:         return len + 2;
                    676:     }
                    677: 
                    678:     len = 2;
                    679:     element = element->value.list;
                    680:     while (element->type)
                    681:         len += sdp_attr_write(data + len, element ++, uuid);
                    682:     data[1] = len - 2;
                    683: 
                    684:     return len;
                    685: }
                    686: 
                    687: static int sdp_attributeid_compare(const struct sdp_service_attribute_s *a,
                    688:                 const struct sdp_service_attribute_s *b)
                    689: {
                    690:     return (int) b->attribute_id - a->attribute_id;
                    691: }
                    692: 
                    693: static int sdp_uuid_compare(const int *a, const int *b)
                    694: {
                    695:     return *a - *b;
                    696: }
                    697: 
                    698: static void sdp_service_record_build(struct sdp_service_record_s *record,
                    699:                 struct sdp_def_service_s *def, int handle)
                    700: {
                    701:     int len = 0;
                    702:     uint8_t *data;
                    703:     int *uuid;
                    704: 
                    705:     record->uuids = 0;
                    706:     while (def->attributes[record->attributes].data.type) {
                    707:         len += 3;
                    708:         len += sdp_attr_max_size(&def->attributes[record->attributes ++].data,
                    709:                         &record->uuids);
                    710:     }
                    711:     record->uuids = 1 << ffs(record->uuids - 1);
                    712:     record->attribute_list =
                    713:             qemu_mallocz(record->attributes * sizeof(*record->attribute_list));
                    714:     record->uuid =
                    715:             qemu_mallocz(record->uuids * sizeof(*record->uuid));
                    716:     data = qemu_malloc(len);
                    717: 
                    718:     record->attributes = 0;
                    719:     uuid = record->uuid;
                    720:     while (def->attributes[record->attributes].data.type) {
                    721:         record->attribute_list[record->attributes].pair = data;
                    722: 
                    723:         len = 0;
                    724:         data[len ++] = SDP_DTYPE_UINT | SDP_DSIZE_2;
                    725:         data[len ++] = def->attributes[record->attributes].id >> 8;
                    726:         data[len ++] = def->attributes[record->attributes].id & 0xff;
                    727:         len += sdp_attr_write(data + len,
                    728:                         &def->attributes[record->attributes].data, &uuid);
                    729: 
                    730:         /* Special case: assign a ServiceRecordHandle in sequence */
                    731:         if (def->attributes[record->attributes].id == SDP_ATTR_RECORD_HANDLE)
                    732:             def->attributes[record->attributes].data.value.uint = handle;
                    733:         /* Note: we could also assign a ServiceDescription based on
                    734:          * sdp->device.device->lmp_name.  */
                    735: 
                    736:         record->attribute_list[record->attributes ++].len = len;
                    737:         data += len;
                    738:     }
                    739: 
                    740:     /* Sort the attribute list by the AttributeID */
                    741:     qsort(record->attribute_list, record->attributes,
                    742:                     sizeof(*record->attribute_list),
                    743:                     (void *) sdp_attributeid_compare);
                    744:     /* Sort the searchable UUIDs list for bisection */
                    745:     qsort(record->uuid, record->uuids,
                    746:                     sizeof(*record->uuid),
                    747:                     (void *) sdp_uuid_compare);
                    748: }
                    749: 
                    750: static void sdp_service_db_build(struct bt_l2cap_sdp_state_s *sdp,
                    751:                 struct sdp_def_service_s **service)
                    752: {
                    753:     sdp->services = 0;
                    754:     while (service[sdp->services])
                    755:         sdp->services ++;
                    756:     sdp->service_list =
                    757:             qemu_mallocz(sdp->services * sizeof(*sdp->service_list));
                    758: 
                    759:     sdp->services = 0;
                    760:     while (*service) {
                    761:         sdp_service_record_build(&sdp->service_list[sdp->services],
                    762:                         *service, sdp->services);
                    763:         service ++;
                    764:         sdp->services ++;
                    765:     }
                    766: }
                    767: 
                    768: #define LAST { .type = 0 }
                    769: #define SERVICE(name, attrs)                           \
                    770:     static struct sdp_def_service_s glue(glue(sdp_service_, name), _s) = { \
                    771:         .attributes = { attrs { .data = LAST } },      \
                    772:     };
                    773: #define ATTRIBUTE(attrid, val) { .id = glue(SDP_ATTR_, attrid), .data = val },
                    774: #define UINT8(val)     {                               \
                    775:         .type       = SDP_DTYPE_UINT | SDP_DSIZE_1,    \
                    776:         .value.uint = val,                             \
                    777:     },
                    778: #define UINT16(val)    {                               \
                    779:         .type       = SDP_DTYPE_UINT | SDP_DSIZE_2,    \
                    780:         .value.uint = val,                             \
                    781:     },
                    782: #define UINT32(val)    {                               \
                    783:         .type       = SDP_DTYPE_UINT | SDP_DSIZE_4,    \
                    784:         .value.uint = val,                             \
                    785:     },
                    786: #define UUID128(val)   {                               \
                    787:         .type       = SDP_DTYPE_UUID | SDP_DSIZE_16,   \
                    788:         .value.uint = val,                             \
                    789:     },
                    790: #define TRUE   {                               \
                    791:         .type       = SDP_DTYPE_BOOL | SDP_DSIZE_1,    \
                    792:         .value.uint = 1,                               \
                    793:     },
                    794: #define FALSE  {                               \
                    795:         .type       = SDP_DTYPE_BOOL | SDP_DSIZE_1,    \
                    796:         .value.uint = 0,                               \
                    797:     },
                    798: #define STRING(val)    {                               \
                    799:         .type       = SDP_DTYPE_STRING,                        \
                    800:         .value.str  = val,                             \
                    801:     },
                    802: #define ARRAY(...)     {                               \
                    803:         .type       = SDP_DTYPE_STRING | SDP_DSIZE_2,  \
                    804:         .value.str  = (char []) { __VA_ARGS__, 0, 0 }, \
                    805:     },
                    806: #define URL(val)       {                               \
                    807:         .type       = SDP_DTYPE_URL,                   \
                    808:         .value.str  = val,                             \
                    809:     },
                    810: #if 1
                    811: #define LIST(val)      {                               \
                    812:         .type       = SDP_DTYPE_SEQ,                   \
                    813:         .value.list = (struct sdp_def_data_element_s []) { val LAST }, \
                    814:     },
                    815: #endif
                    816: 
                    817: /* Try to keep each single attribute below MAX_PDU_OUT_SIZE bytes
                    818:  * in resulting SDP data representation size.  */
                    819: 
                    820: SERVICE(hid,
                    821:     ATTRIBUTE(RECORD_HANDLE,   UINT32(0))      /* Filled in later */
                    822:     ATTRIBUTE(SVCLASS_ID_LIST, LIST(UUID128(HID_SVCLASS_ID)))
                    823:     ATTRIBUTE(RECORD_STATE,    UINT32(1))
                    824:     ATTRIBUTE(PROTO_DESC_LIST, LIST(
                    825:         LIST(UUID128(L2CAP_UUID) UINT16(BT_PSM_HID_CTRL))
                    826:         LIST(UUID128(HIDP_UUID))
                    827:     ))
                    828:     ATTRIBUTE(BROWSE_GRP_LIST, LIST(UUID128(0x1002)))
                    829:     ATTRIBUTE(LANG_BASE_ATTR_ID_LIST, LIST(
                    830:         UINT16(0x656e) UINT16(0x006a) UINT16(0x0100)
                    831:     ))
                    832:     ATTRIBUTE(PFILE_DESC_LIST, LIST(
                    833:         LIST(UUID128(HID_PROFILE_ID) UINT16(0x0100))
                    834:     ))
                    835:     ATTRIBUTE(DOC_URL,         URL("http://bellard.org/qemu/user-doc.html"))
                    836:     ATTRIBUTE(SVCNAME_PRIMARY, STRING("QEMU Bluetooth HID"))
                    837:     ATTRIBUTE(SVCDESC_PRIMARY, STRING("QEMU Keyboard/Mouse"))
                    838:     ATTRIBUTE(SVCPROV_PRIMARY, STRING("QEMU " QEMU_VERSION))
                    839: 
                    840:     /* Profile specific */
                    841:     ATTRIBUTE(DEVICE_RELEASE_NUMBER,   UINT16(0x0091)) /* Deprecated, remove */
                    842:     ATTRIBUTE(PARSER_VERSION,          UINT16(0x0111))
                    843:     /* TODO: extract from l2cap_device->device.class[0] */
                    844:     ATTRIBUTE(DEVICE_SUBCLASS,         UINT8(0x40))
                    845:     ATTRIBUTE(COUNTRY_CODE,            UINT8(0x15))
                    846:     ATTRIBUTE(VIRTUAL_CABLE,           TRUE)
                    847:     ATTRIBUTE(RECONNECT_INITIATE,      FALSE)
                    848:     /* TODO: extract from hid->usbdev->report_desc */
                    849:     ATTRIBUTE(DESCRIPTOR_LIST,         LIST(
                    850:         LIST(UINT8(0x22) ARRAY(
                    851:             0x05, 0x01,        /* Usage Page (Generic Desktop) */
                    852:             0x09, 0x06,        /* Usage (Keyboard) */
                    853:             0xa1, 0x01,        /* Collection (Application) */
                    854:             0x75, 0x01,        /*   Report Size (1) */
                    855:             0x95, 0x08,        /*   Report Count (8) */
                    856:             0x05, 0x07,        /*   Usage Page (Key Codes) */
                    857:             0x19, 0xe0,        /*   Usage Minimum (224) */
                    858:             0x29, 0xe7,        /*   Usage Maximum (231) */
                    859:             0x15, 0x00,        /*   Logical Minimum (0) */
                    860:             0x25, 0x01,        /*   Logical Maximum (1) */
                    861:             0x81, 0x02,        /*   Input (Data, Variable, Absolute) */
                    862:             0x95, 0x01,        /*   Report Count (1) */
                    863:             0x75, 0x08,        /*   Report Size (8) */
                    864:             0x81, 0x01,        /*   Input (Constant) */
                    865:             0x95, 0x05,        /*   Report Count (5) */
                    866:             0x75, 0x01,        /*   Report Size (1) */
                    867:             0x05, 0x08,        /*   Usage Page (LEDs) */
                    868:             0x19, 0x01,        /*   Usage Minimum (1) */
                    869:             0x29, 0x05,        /*   Usage Maximum (5) */
                    870:             0x91, 0x02,        /*   Output (Data, Variable, Absolute) */
                    871:             0x95, 0x01,        /*   Report Count (1) */
                    872:             0x75, 0x03,        /*   Report Size (3) */
                    873:             0x91, 0x01,        /*   Output (Constant) */
                    874:             0x95, 0x06,        /*   Report Count (6) */
                    875:             0x75, 0x08,        /*   Report Size (8) */
                    876:             0x15, 0x00,        /*   Logical Minimum (0) */
                    877:             0x25, 0xff,        /*   Logical Maximum (255) */
                    878:             0x05, 0x07,        /*   Usage Page (Key Codes) */
                    879:             0x19, 0x00,        /*   Usage Minimum (0) */
                    880:             0x29, 0xff,        /*   Usage Maximum (255) */
                    881:             0x81, 0x00,        /*   Input (Data, Array) */
                    882:             0xc0       /* End Collection */
                    883:     ))))
                    884:     ATTRIBUTE(LANG_ID_BASE_LIST,       LIST(
                    885:         LIST(UINT16(0x0409) UINT16(0x0100))
                    886:     ))
                    887:     ATTRIBUTE(SDP_DISABLE,             FALSE)
                    888:     ATTRIBUTE(BATTERY_POWER,           TRUE)
                    889:     ATTRIBUTE(REMOTE_WAKEUP,           TRUE)
                    890:     ATTRIBUTE(BOOT_DEVICE,             TRUE)   /* XXX: untested */
                    891:     ATTRIBUTE(SUPERVISION_TIMEOUT,     UINT16(0x0c80))
                    892:     ATTRIBUTE(NORMALLY_CONNECTABLE,    TRUE)
                    893:     ATTRIBUTE(PROFILE_VERSION,         UINT16(0x0100))
                    894: )
                    895: 
                    896: SERVICE(sdp,
                    897:     ATTRIBUTE(RECORD_HANDLE,   UINT32(0))      /* Filled in later */
                    898:     ATTRIBUTE(SVCLASS_ID_LIST, LIST(UUID128(SDP_SERVER_SVCLASS_ID)))
                    899:     ATTRIBUTE(RECORD_STATE,    UINT32(1))
                    900:     ATTRIBUTE(PROTO_DESC_LIST, LIST(
                    901:         LIST(UUID128(L2CAP_UUID) UINT16(BT_PSM_SDP))
                    902:         LIST(UUID128(SDP_UUID))
                    903:     ))
                    904:     ATTRIBUTE(BROWSE_GRP_LIST, LIST(UUID128(0x1002)))
                    905:     ATTRIBUTE(LANG_BASE_ATTR_ID_LIST, LIST(
                    906:         UINT16(0x656e) UINT16(0x006a) UINT16(0x0100)
                    907:     ))
                    908:     ATTRIBUTE(PFILE_DESC_LIST, LIST(
                    909:         LIST(UUID128(SDP_SERVER_PROFILE_ID) UINT16(0x0100))
                    910:     ))
                    911:     ATTRIBUTE(DOC_URL,         URL("http://bellard.org/qemu/user-doc.html"))
                    912:     ATTRIBUTE(SVCPROV_PRIMARY, STRING("QEMU " QEMU_VERSION))
                    913: 
                    914:     /* Profile specific */
                    915:     ATTRIBUTE(VERSION_NUM_LIST, LIST(UINT16(0x0100)))
                    916:     ATTRIBUTE(SVCDB_STATE    , UINT32(1))
                    917: )
                    918: 
                    919: SERVICE(pnp,
                    920:     ATTRIBUTE(RECORD_HANDLE,   UINT32(0))      /* Filled in later */
                    921:     ATTRIBUTE(SVCLASS_ID_LIST, LIST(UUID128(PNP_INFO_SVCLASS_ID)))
                    922:     ATTRIBUTE(RECORD_STATE,    UINT32(1))
                    923:     ATTRIBUTE(PROTO_DESC_LIST, LIST(
                    924:         LIST(UUID128(L2CAP_UUID) UINT16(BT_PSM_SDP))
                    925:         LIST(UUID128(SDP_UUID))
                    926:     ))
                    927:     ATTRIBUTE(BROWSE_GRP_LIST, LIST(UUID128(0x1002)))
                    928:     ATTRIBUTE(LANG_BASE_ATTR_ID_LIST, LIST(
                    929:         UINT16(0x656e) UINT16(0x006a) UINT16(0x0100)
                    930:     ))
                    931:     ATTRIBUTE(PFILE_DESC_LIST, LIST(
                    932:         LIST(UUID128(PNP_INFO_PROFILE_ID) UINT16(0x0100))
                    933:     ))
                    934:     ATTRIBUTE(DOC_URL,         URL("http://bellard.org/qemu/user-doc.html"))
                    935:     ATTRIBUTE(SVCPROV_PRIMARY, STRING("QEMU " QEMU_VERSION))
                    936: 
                    937:     /* Profile specific */
                    938:     ATTRIBUTE(SPECIFICATION_ID, UINT16(0x0100))
                    939:     ATTRIBUTE(VERSION,         UINT16(0x0100))
                    940:     ATTRIBUTE(PRIMARY_RECORD,  TRUE)
                    941: )
                    942: 
                    943: static int bt_l2cap_sdp_new_ch(struct bt_l2cap_device_s *dev,
                    944:                 struct bt_l2cap_conn_params_s *params)
                    945: {
                    946:     struct bt_l2cap_sdp_state_s *sdp = qemu_mallocz(sizeof(*sdp));
                    947:     struct sdp_def_service_s *services[] = {
                    948:         &sdp_service_sdp_s,
                    949:         &sdp_service_hid_s,
                    950:         &sdp_service_pnp_s,
                    951:         0,
                    952:     };
                    953: 
                    954:     sdp->channel = params;
                    955:     sdp->channel->opaque = sdp;
                    956:     sdp->channel->close = bt_l2cap_sdp_close_ch;
                    957:     sdp->channel->sdu_in = bt_l2cap_sdp_sdu_in;
                    958: 
                    959:     sdp_service_db_build(sdp, services);
                    960: 
                    961:     return 0;
                    962: }
                    963: 
                    964: void bt_l2cap_sdp_init(struct bt_l2cap_device_s *dev)
                    965: {
                    966:     bt_l2cap_psm_register(dev, BT_PSM_SDP,
                    967:                     MAX_PDU_OUT_SIZE, bt_l2cap_sdp_new_ch);
                    968: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.