This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Extended inquiry problems - 0 entries / "Invalid size" on inquiry of iPhone

I am trying to read extended inquiry information so that I can get device name and such without having to go and manually fetch. Based on the Tiva C classic SPP demo, I have modified the code as such:

on startup:

GAP_Set_Inquiry_Mode(BluetoothStackID, imExtended);

in GAP event callback:

         case etExtended_Inquiry_Entry_Result:
         {
             GAP_Extended_Inquiry_Entry_Event_Data_t *pData;
             GAP_Extended_Inquiry_Response_Data_t *pResp;

             Display(("\n<%s>\n", EventNames[GAP_Event_Data->Event_Data_Type]));

             pData = GAP_Event_Data->Event_Data.GAP_Extended_Inquiry_Entry_Event_Data;
             pResp = &(pData->Extended_Inquiry_Response_Data);

             /* Next convert the BD_ADDR to a string.                    */
             BD_ADDRToStr(pData->BD_ADDR, Callback_BoardStr);
             ClassToStr(pData->Class_of_Device, Callback_ClassStr);

             Display(("\t%s - class %s - %d entries\r\n",
                     Callback_BoardStr, Callback_ClassStr,
                     pResp->Number_Data_Entries));
             ShowExtendedInquiryData(pResp);

             Display(("\n</%s>\n", EventNames[GAP_Event_Data->Event_Data_Type]));

             break;
         }

(ShowExtendedInquiryData is a function I made which steps through a GAP_Extended_Inquiry_Response_Data_t * and prints all the entries out)

When I start the inquiry, on one of the results I'll see "Invalid size" (which is not something that I print, so it must be internal to the stack), followed by an extended inquiry entry result showing "0 entries". I can see the extended inquiry result from every other device, which works fine, but I wanted to see why it couldn't process the other one.

I saw in the documentation that I could use the HCI event callback to get extended inquiry results, so I added this to that callback to try:

        case etExtended_Inquiry_Result_Event:
        {
            HCI_Extended_Inquiry_Result_Event_Data_t *pData;
            GAP_Extended_Inquiry_Response_Data_t pParsed;
            int x;
            GAP_Extended_Inquiry_Response_Data_Entry_t Data_Entries[10];

            Display(("\n<%s>\n", EventNames[HCI_Event_Data->Event_Data_Type]));

            pData = HCI_Event_Data->Event_Data.HCI_Extended_Inquiry_Result_Event_Data;

            x = GAP_Parse_Extended_Inquiry_Response_Data(
                &pData->HCI_Inquiry_Result_Data.Extended_Inquiry_Response,
                NULL);

            Display(("\tNeed %d entries for extended inquiry response parsing\n", x));

            pParsed.Number_Data_Entries = 10;
            pParsed.Data_Entries = Data_Entries;

            x = GAP_Parse_Extended_Inquiry_Response_Data(
                    &pData->HCI_Inquiry_Result_Data.Extended_Inquiry_Response,
                    &pParsed);
            if (x > 0)
            {
                Display(("\tProcessed %d entries from HCI extended inquiry event:\n", x));
                ShowExtendedInquiryData(&pParsed);
            }
            else
            {
                Display(("\tGAP Parse Extended Inquiry Response Data result: %d / 0x%02x\n", x, x));
            }
            Display(("\n</%s>\n", EventNames[HCI_Event_Data->Event_Data_Type]));
            break;
        }

Handling the HCI event reveals little else about what's going on, and also causes an "Invalid size" error to be printed out when I perform the GAP Parse Extended Inquiry Response Data. It works fine when the GAP event callback works fine, so I'll see 2 copies of each correctly parsed inquiry result and nothing of the one with the error.

When breakpointed during etExtended_Inquiry_Result_Event, I can see characters of the phone's friendly name in place of where BD_ADDR, Page_Scan_Repetition_Mode, Class of Device, etc. should be, so it looks like the memory preceding the Extended_Inquiry_Response_Data has been overwritten. I see that Extended_Inquiry_Response_Data is a char[240], but I'm not quite sure where I'd be able to make that bigger to fit what I can only assume to be a larger extended inquiry response. I do not believe I am passing it any particular address into which to fill the incoming extended inquiry response itself (only the processed data entries which are pointers), so the stack must be filling a buffer of its own.

Here is a log printout of what happens during an inquiry. An iPhone 5s and two Sena SMH10 headsets are set to visible during the scan.

Client> inquiry

Client>
<GAP Extended Inquiry Entry Result>
	0x0001950ea9bf - class 0x240404 - 3 entries
	Shortened Name: Sena SMH10 
	TX power level: 16
	Service Class UUIDs (16 bit): 0x111e 0x1108 0x110d 0x110b

</GAP Extended Inquiry Entry Result>

Client>
<HCI Extended Inquiry Result Event>
	Need 3 entries for extended inquiry response parsing
	Processed 3 entries from HCI extended inquiry event:
	Shortened Name: Sena SMH10  
	TX power level: 16
	Service Class UUIDs (16 bit): 0x111e 0x1108 0x110d 0x110b

</HCI Extended Inquiry Result Event>
Invalid size

<GAP Extended Inquiry Entry Result>
	0xb8e856e798ea - class 0x7a020c - 0 entries

</GAP Extended Inquiry Entry Result>

Client>
<HCI Extended Inquiry Result Event>
	Need 5 entries for extended inquiry response parsing
Invalid size
	GAP Parse Extended Inquiry Response Data result: 0 / 0x00

</HCI Extended Inquiry Result Event>

<GAP Extended Inquiry Entry Result>
	0x0001950f6d84 - class 0x240404 - 3 entries
	Shortened Name: Sena SMH10 
	TX power level: 16
	Service Class UUIDs (16 bit): 0x111e 0x1108 0x110d 0x110b

</GAP Extended Inquiry Entry Result>

Client>
<HCI Extended Inquiry Result Event>
	Need 3 entries for extended inquiry response parsing
	Processed 3 entries from HCI extended inquiry event:
	Shortened Name: Sena SMH10  
	TX power level: 16
	Service Class UUIDs (16 bit): 0x111e 0x1108 0x110d 0x110b

</HCI Extended Inquiry Result Event>

<GAP Inquiry Result>
	Result: 1,0x0001950ea9bf - class 0x240404.
	Result: 2,0xb8e856e798ea - class 0x7a020c.
	Result: 3,0x0001950f6d84 - class 0x240404.

</GAP Inquiry Result>

Client>

Any ideas on what could be causing an "Invalid size" error, or why the buffer could be overrunning in this manner?

edit: I was initially encountering a bus fault during/immediately after the inquiry but I can't get it to reproduce now--I'm assuming it has to do with this buffer overrun.

  • Hi,

    Moving to SSO team for precise answer.

  • Sundeep and team,

    Any ideas?

    Thanks :)

  • I have some additional information. It turns out that BTPSKRNL.c is the one printing the "Invalid size" error, as it is receiving a command to allocate a block of memory of size 0 from the section ParseExtendedInquiryDataRecords. Here is the disassembly in case it helps to find out what's going on. 0x9faca is where I breakpointed upon the attempt to allocate 0 bytes.

              ParseExtendedInquiryDataRecords:
    0009fa68:   E92D5FF0 STMDB.W         R13!, {R4, R5, R6, R7, R8, R9, R10, R11, R12, R14}
    0009fa6c:   460C     MOV             R4, R1
    0009fa6e:   4691     MOV             R9, R2
    0009fa70:   0006     LSL             R6, R0, #0x0
    0009fa72:   D05E     BEQ             0x9FB32
    0009fa74:   B3F4     CZBEQ           R4, 0x9FAF4
    0009fa76:   F00AF877 BL              CountExtendedInquiryDataRecords
    0009fa7a:   1E05     SUB             R5, R0, #0x0
    0009fa7c:   DD56     BLE             0x9FB2C
    0009fa7e:   F1B90F00 CMP.W           R9, #0
    0009fa82:   D006     BEQ             0x9FA92
    0009fa84:   EB050045 ADD.W           R0, R5, R5, LSL #1
    0009fa88:   0080     LSL             R0, R0, #0x2
    0009fa8a:   F7D2FFA7 BL              BTPS_AllocateMemory
    0009fa8e:   6060     STR             R0, [R4, #0x4]
    0009fa90:   E005     B               0x9FA9E
    0009fa92:   6820     LDR             R0, [R4]
    0009fa94:   42A8     CMP             R0, R5
    0009fa96:   D301     BCC             0x9FA9C
    0009fa98:   6860     LDR             R0, [R4, #0x4]
    0009fa9a:   B900     CZBNE           R0, 0x9FA9E
    0009fa9c:   2500     MOV             R5, #0x0
    0009fa9e:   F04F0A00 MOV.W           R10, #0
    0009faa2:   F8C4A000 STR.W           R10, [R4, #0]
    0009faa6:   B335     CZBEQ           R5, 0x9FAF6
    0009faa8:   6860     LDR             R0, [R4, #0x4]
    0009faaa:   B320     CZBEQ           R0, 0x9FAF6
    0009faac:   2700     MOV             R7, #0x0
    0009faae:   F04F0B08 MOV.W           R11, #8
    0009fab2:   5DF5     LDRB            R5, [R6, R7]
    0009fab4:   1C7F     ADD             R7, R7, #0x1
    0009fab6:   B1F5     CZBEQ           R5, 0x9FAF6
    0009fab8:   1978     ADD             R0, R7, R5
    0009faba:   28F0     CMP             R0, #0xF0
    0009fabc:   D836     BHI             0x9FB2C
    0009fabe:   F8168007 LDRB.W          R8, [R6, R7
    0009fac2:   1C7F     ADD             R7, R7, #0x1
    0009fac4:   1E68     SUB             R0, R5, #0x1
    0009fac6:   F7D2FF89 BL              BTPS_AllocateMemory
    0009faca:   E9D41200 LDRD.W          R1, R2, [R4, #0]
    0009face:   EB010341 ADD.W           R3, R1, R1, LSL #1
    0009fad2:   EB0B0183 ADD.W           R1, R11, R3, LSL #2
    0009fad6:   5050     STR             R0, [R2, R1]

  • If I force BTPS_AllocateMemory to allocate 512 bytes whenever Bluetopia asks for 0 bytes, then I do get the extended inquiry response from the phone, but I don't want to do this in case something else is broke and asks for 0 bytes, or if the extended inquiry response ever actually needs more than 512 bytes.

    <GAP Extended Inquiry Entry Result>
    0x006171CA5B8B - class 0x7A020C - 5 entries
    Name: iPhone 9 [8 bytes]
    Service Class UUIDs (16 bit): 0x1200 0x111f 0x112f 0x110a 0x110c 0x1132
    Service Class UUIDs (32 bit):
    Service Class UUIDs (128 bit):
    0xfecacadeafdecadedefacade00000000
    Manufacturer specific data received, 38 bytes
    00 4c 02 24 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

    Is there any additional information I can provide to track down the issue? It would seem that it's doing something to calculate how many bytes it needs to allocate , but that calculation is not working correctly with a certain arrangement extended inquiry entries

    This problem is observed on an HTC One as well, so it does not appear to be limited to iPhones

  • Hi,

    Please see below response, I have received internally.

    We tested an EIR Inquiry with an iPhone 5s and a HTC One and were able to get the name and UUIDs supported. I have our code snippet attached and the logs below. The Invalid size may be coming from somewhere else in the user’s code. Is it possible to provide the HCI trace.

    Device Name:

    P050 Gold iPhone 5S

    End of Device Name

    1,0x0012

    2,0x1f11

    3,0x2f11

    4,0x0a11

    5,0x0c11

    6,0x3211

     

    Device Name:

    htc-one

    End of Device Name

    1,0x0511

    2,0x0a11

    3,0x0c11

    4,0x0e11

    5,0x1211

    6,0x1511

    7,0x1611

    8,0x1f11

    9,0x2f11

    10,0x3211

    6646.EIRCodeSnippet.txt
    static void BTPSAPI HCI_Event_Callback(unsigned int BluetoothStackID, HCI_Event_Data_t *HCI_Event_Data, unsigned long CallbackParameter)
    {
       char *Mode;
    	char NameBuffer[64];
    
       /* Make sure that the input parameters that were passed to us are    */
       /* semi-valid.                                                       */
       if((BluetoothStackID) && (HCI_Event_Data))
       {
          /* Process the Event Data.                                        */
          switch(HCI_Event_Data->Event_Data_Type)
          {
             case etExtended_Inquiry_Result_Event:
                if(HCI_Event_Data->Event_Data.HCI_Extended_Inquiry_Result_Event_Data)
                {
                   /* Determine if this is a valid Key Fob Device.          */
                   /* Determine if this is a valid Key Fob Device.          */
                   
                   
                      /* Attempt to parse the name from the advertising     */
                      /* data.                                              */
                   
       ParseNameString(sizeof(Extended_Inquiry_Response_Data_t), (Byte_t *)&(HCI_Event_Data->Event_Data.HCI_Extended_Inquiry_Result_Event_Data->HCI_Inquiry_Result_Data.Extended_Inquiry_Response), (sizeof(NameBuffer)-1), NameBuffer);
    							CheckKeyFobSupported(sizeof(Extended_Inquiry_Response_Data_t), (Byte_t *)&(HCI_Event_Data->Event_Data.HCI_Extended_Inquiry_Result_Event_Data->HCI_Inquiry_Result_Data.Extended_Inquiry_Response));
                 }
                break;
    
    	  case etMode_Change_Event:
                if(HCI_Event_Data->Event_Data.HCI_Mode_Change_Event_Data)
                {
                   switch(HCI_Event_Data->Event_Data.HCI_Mode_Change_Event_Data->Current_Mode)
                   {
                      case HCI_CURRENT_MODE_HOLD_MODE:
                         Mode = "Hold";
                         break;
                      case HCI_CURRENT_MODE_SNIFF_MODE:
                         Mode = "Sniff";
                         break;
                      case HCI_CURRENT_MODE_PARK_MODE:
                         Mode = "Park";
                         break;
                      case HCI_CURRENT_MODE_ACTIVE_MODE:
                      default:
                         Mode = "Active";
                         break;
                   }
    
                   Display(("\r\n"));
                   Display(("HCI Mode Change Event, Status: 0x%02X, Connection Handle: %d, Mode: %s, Interval: %d\r\n", HCI_Event_Data->Event_Data.HCI_Mode_Change_Event_Data->Status,
                                                                                                                        HCI_Event_Data->Event_Data.HCI_Mode_Change_Event_Data->Connection_Handle,
                                                                                                                        Mode,
                                                                                                                        HCI_Event_Data->Event_Data.HCI_Mode_Change_Event_Data->Interval));
                   DisplayPrompt();
                }
                break;
          }
       }
    }
    
    
    static int PrintUUID(unsigned int DataLength, Byte_t *Data)
    {
       int          ret_val = 0;
       UUID_16_t    UUID;
       unsigned int Index;
       unsigned int UUIDCount;
       unsigned int Length;
       char   temp[128];
       unsigned int Count=1;		
       if((DataLength) && (Data))
       {
          /* Loop through the data and parse 16 bit Services supported.     */
          for(Index=0;(Index<DataLength)&&(!ret_val); )
          {
             /* Get the Length byte.                                        */
             Length = READ_UNALIGNED_BYTE_LITTLE_ENDIAN(&(Data[Index]));
    			
    			
             /* Increment the Index past the length byte.                   */
             ++Index;
    
             /* Verify we have the data for the length.                     */
             if((Length > 0) && (Length <= (DataLength-Index)))
             {
                /* See if this is a service list structure.                 */
                if((Data[Index] == HCI_LE_ADVERTISING_REPORT_DATA_TYPE_16_BIT_SERVICE_UUID_PARTIAL) || (Data[Index] == HCI_LE_ADVERTISING_REPORT_DATA_TYPE_16_BIT_SERVICE_UUID_COMPLETE))
                {
                  
                   /* Increment past the type byte.                         */
                   ++Index;
    
                   /* Calculate the number of UUIDs in the list.            */
                   UUIDCount = (Length-1)/UUID_16_SIZE;
                   while(UUIDCount--)
                   {
                      /* Copy the data directly into the UUID_16_t structure*/
                      /* since it is little endian.                         */
                      BTPS_MemCopy(&UUID, &Data[Index], UUID_16_SIZE);
    
    				BTPS_SprintF(temp, "%d,0x%02X%02X \r\n", Count, UUID.UUID_Byte0, UUID.UUID_Byte1);
    				Display((temp));
    				
                     Count++; 
    								 /* Increment past the UUID.                           */
                      Index += UUID_16_SIZE;
                   }
                }
                else
                {
                   /* Increment past the structure.                         */
                   Index += Length;
                }
             }
             else
                break;
          }
       }
    
       return(ret_val);
    }
    
       static Boolean_t ParseNameString(unsigned int DataLength, Byte_t *Data, unsigned int NameBufferLength, char *NameBuffer)
    {
       Boolean_t    ret_val = FALSE;
       unsigned int Index;
       unsigned int Length;
       unsigned int CopyLength;
    
       /* Verify that the input parameters are semi-valid.                  */
       if((DataLength) && (Data) && (NameBufferLength) && (NameBuffer))
       {
          /* Loop through the data and parse 16 bit Services supported.     */
          for(Index=0;(Index<DataLength)&&(!ret_val); )
          {
             /* Get the Length byte.                                        */
             Length = READ_UNALIGNED_BYTE_LITTLE_ENDIAN(&(Data[Index]));
    				//Display(("Length is %d", Length));
    
             /* Increment the Index past the length byte.                   */
             ++Index;
    
             /* Verify we have the data for the length.                     */
             if((Length > 0) && (Length <= (DataLength-Index)))
             {
                /* See if this is a service list structure.                 */
                if((Data[Index] == HCI_LE_ADVERTISING_REPORT_DATA_TYPE_LOCAL_NAME_SHORTENED) || (Data[Index] == HCI_LE_ADVERTISING_REPORT_DATA_TYPE_LOCAL_NAME_COMPLETE))
                {
                   /* Increment past the type byte.                         */
                   ++Index;
    
                   /* Verify that at least 1 byte is present in the length. */
                   if(--Length)
                   {
                      /* Copy the name into the provided buffer.            */
                      CopyLength = (Length > NameBufferLength)?NameBufferLength:Length;
                      BTPS_MemCopy(NameBuffer, &Data[Index], CopyLength);
    					Display(("Device Name:"));
    								 Display((NameBuffer));
    								 Display(("\r\n End of Device Name \r\n"));
                      /* Flag that the name has been parsed.                */
                      ret_val = TRUE;
    
                      /* Increment past the name.                           */
                      Index += Length;
                      break;
                   }
                }
                else
                {
                   /* Increment past the structure.                         */
                   Index += Length;
                }
             }
             else
                break;
          }
       }
    
       return(ret_val);
    }