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.

CC2541 change device name over serial

Hi, I'm looking for a way to change the device's name (GAP Scan Response data) over UART. I have a working UART code and currently, to change the device's  name, the user would type SN,<new device name> with <...> as whatever the name the user want to change to.

I'm using the non-volatile flash memory to store newly set name, and when the device is initializing, the name stored would be loaded and its CRC value is compared with the stored CRC value when the user was setting the device name.

Currently, no matter what the value in scanData (allocated at runtime), my tablet (Lollipop) always use the last-known default_scanData so there must be some kind of errors with the newly made scanData. If I change a single character in default_scanData and use that instead, the new name is detected fine. Can I please get some insights into what I'm doing wrong? Thanks.

This the code so far:

0. Local variables and constants...

#define SNV_ID_DEVICE_NAME              0x80
#define SNV_ID_DEVICE_NAME_LENGTH       0x81
#define SNV_ID_DEVICE_NAME_CRC          0x82

uint8 *device_name_crc;
uint8 *device_name;
uint8 *device_name_length;
uint8 *scanData;
    
// GAP Profile - Name attribute for SCAN RSP data - Name shown up when scanned
static uint8 default_scanData[] =
{
  0x15,                             // length of this data => name's size = 20 bytes
  GAP_ADTYPE_LOCAL_NAME_COMPLETE,   // AD Type = Complete local name
  'H',
  'I',
  'D',
  ' ',
  'K',
  'e',
  'y',
  'b',
  'o',
  'a',
  'r',
  'd',
  ' ',
  '&',
  ' ',
  'M',
  'o',
  'u',
  's',
  'e'
};

1. Name changing when user sends over a SN,<new name>

if((rxBuffer[1] == 'N') && (rxBuffer[2] == ',')) {
      //TO-DO: SET NAME - May have been coded correctly
      printf("Name is being set, reset to set new name\r\n");
      uint8 i;
      uint8 deviceNewName[20];
      uint8 deviceNewNameLength;
      uint8 deviceNewNameCRC;
      
      deviceNewNameLength = rxBufferIndex-3;
      if(deviceNewNameLength > 20) {
        printf("Name exceeds permitted length\r\n");
      } else {
        for(i = 3; i < rxBufferIndex; i++) {
          deviceNewName[i-3] = rxBuffer[i];
        }   
        deviceNewName[deviceNewNameLength] = '\0';
        deviceNewNameCRC = getCRC(deviceNewName, deviceNewNameLength);
        
        //printf("%i, %i\r\n", rxBufferIndex, deviceNewNameLength);
        //printf("%s\r\n", deviceNewName);
        //printf("%x\r\n", deviceNewNameCRC);
        
        osal_snv_write(SNV_ID_DEVICE_NAME, 20, deviceNewName);
        osal_snv_write(SNV_ID_DEVICE_NAME_LENGTH, 1, &deviceNewNameLength);
        osal_snv_write(SNV_ID_DEVICE_NAME_CRC, 1, &deviceNewNameCRC);
      }

2. During initialization, device checks for stored value and use the stored value if it's legit.

osal_snv_read(SNV_ID_DEVICE_NAME_CRC, 1, device_name_crc);
    osal_snv_read(SNV_ID_DEVICE_NAME_LENGTH, 1, device_name_length);
    osal_snv_read(SNV_ID_DEVICE_NAME, 20, device_name);
    
    if(*device_name_crc != getCRC(device_name, *device_name_length)) {
      printf("Using default name\r\n");
      GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( default_scanData ), default_scanData );
    } else {
      printf("Using stored name\r\n"); //this is called just fine
      printf("%s\r\n", device_name);
      createScanResponseData(device_name, device_name_length, scanData);
      //GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( default_scanData ), default_scanData ); //any changes to the default scanData is picked up fine.
      GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( scanData ), scanData ); //not updated regardless of names changed
    }

3. Related name changing functions:

//Pololu's CRC functions with minimal changes
uint8 CRCPoly = 0x89;  // the value of our CRC-7 polynomial
uint8 CRCTable[256];

void GenerateCRCTable()
{
    int i, j;
 
    // generate a table value for all 256 possible byte values
    for (i = 0; i < 256; i++)
    {
        CRCTable[i] = (i & 0x80) ? i ^ CRCPoly : i;
        for (j = 1; j < 8; j++)
        {
            CRCTable[i] <<= 1;
            if (CRCTable[i] & 0x80)
                CRCTable[i] ^= CRCPoly;
        }
    }
}
 
 
// adds a message byte to the current CRC-7 to get a the new CRC-7
uint8 CRCAdd(uint8 CRC, uint8 message_byte)
{
    return CRCTable[(CRC << 1) ^ message_byte];
}
 
 
// returns the CRC-7 for a message of "length" bytes
uint8 getCRC(uint8 message[], uint8 length)
{
    uint8 i;
    uint8 CRC = 0;
 
    for (i = 0; i < length; i++)
        CRC = CRCAdd(CRC, message[i]);
 
    return CRC;
}

void createScanResponseData(uint8 *name, uint8 *nameLength, uint8 *responseData) {
  uint8 i;
  uint8 deviceNameLength = *nameLength;
  
  responseData = osal_mem_alloc(deviceNameLength + 2);
  responseData[0] = deviceNameLength + 1;
  responseData[1] = GAP_ADTYPE_LOCAL_NAME_COMPLETE;
  for(i = 0; i < deviceNameLength; i++) {
    responseData[i+2] = name[i];
  }
//  for(i = 0; i < deviceNameLength+2; i++) {
//    printf("%c\r\n", responseData[i]);
//  }
}

  • Hi,

    Can you set the device name using the API given below and check

    // Set the GAP Characteristics
    GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN,
    (void *)attDeviceName);

    Regard,

    Arun

  • Hey Arun, 

    Is there a function to also change the scan response data to the stored values? It's the name that shows up when the host was scanning for a device. 

    Cheers

    Cong

  • Hi Arun,

    I made a mistake with the pointers in the createScanResponseData function and during setting the scanData scan response. So block 2 and 3 has been changed to as follows:

    2. During initialization, device checks for stored value and use the stored value if it's legit.

    if(*device_name_crc != getCRC(device_name, *device_name_length)) {
          printf("Using default scan response name\r\n");
          GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( default_scanData ), default_scanData );
        } else {
    //      printf("Using stored scan response name\r\n");
          printf("%s\r\n", device_name);
          scanData = createScanResponseData(device_name, device_name_length, scanData);
          
    //      printf("Scan response address: %x\r\n", scanData);
          printf("created scanData structure:\r\n");
          printf("Length: %i\r\n", scanData[0]);
          printf("GAP_ADTYPE_LOCAL_NAME_COMPLETE set: %i\r\n", scanData[1] == GAP_ADTYPE_LOCAL_NAME_COMPLETE);
          uint8 i;
          for(i = 2; i  < scanData[0]; i++) {
            printf("%c\r\n",scanData[i]);
          }
          
          uint8 status = GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( scanData ), scanData );
          //uint8 status = GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( default_scanData ), default_scanData );
          //printf("%i\r\n", status);
        }

    3. createScanResponseData() function:

    uint8 * createScanResponseData(uint8 *name, uint8 *nameLength, uint8 *responseData) {
    //  printf("Creating scan response data\r\n");
      uint8 i;
      uint8 deviceNameLength = *nameLength;
    //  printf("%i\r\n", deviceNameLength);
      responseData = osal_mem_alloc(deviceNameLength + 2);
      responseData[0] = deviceNameLength + 1;
      responseData[1] = GAP_ADTYPE_LOCAL_NAME_COMPLETE;
      for(i = 0; i < deviceNameLength; i++) {
        responseData[i+2] = name[i];
      }
    //  printf("scanData's address: %x\r\n\r\n", responseData);
      return responseData;
    }

    The serial capture prints as follows:

    HelloWorld                                                                 
    created scanData structure:                                                 
    Length: 11                                                                
    GAP_ADTYPE_LOCAL_NAME_COMPLETE set: 1                                      
    H                                                                            
    e                                                                            
    l                                                                            
    l                                                                           
    o                                                                            
    W                                                                            
    o                                                                            
    r                                                                           
    l

    On my tablet, the scan response name is now gibberish (a bunch of question marks and stars) but this is great, at least the scanData is being changed. Can you help me with figuring out why even though the scanData structure seems correct but the device does not register it correctly?

    Regards,

    Cong

  • I think the problem lies in line 18 of block 2:
    GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( scanData ), scanData );

    Everytime the device restarts, the complete (scan response) name extracted from the scan records changes so whatever is being set is not constant. I'm out of my depth here so I would really appreciate a reply.

    Cheers,

    Cong
  • I figured a walkaround by directly modifying the default_scanData variable. It's all good now.
  • Hi,

    Yes. You can set the new scanRspData by using the command

       GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( scanRspData ), scanRspData );

    But do note that in most applications scanRspData is declared as static and hence any changes you make may not get reflected. Please remove the static qualifier while declaring the scanRspData variable array.

    Regards,

    Arun