/**
 *  SNP_executeHCIcmd
 */
uint8_t SNP_executeHCIcmd(snpHciCmdReq_t *pReq, uint16_t dataLen)
{  
  bStatus_t stat;   
  uint16_t opcode =  pReq->opcode;
  uint8_t *pData = (uint8_t*)&pReq->pData;
  uint8_t status = blePending; 
  
  if(snp_HCIstore.validity)
  {
    return SNP_CMD_ALREADY_IN_PROGRESS;
  }     
      
  switch (opcode)
  {     
    case SNP_HCI_OPCODE_EXT_RESET_SYSTEM:
    {
      stat =  HCI_EXT_ResetSystemCmd(LL_EXT_RESET_SYSTEM_HARD);
      if(stat == SUCCESS)
      {
        status = SNP_SUCCESS;
      }
      else
      {
        status = bleIncorrectMode;
      }
    }
    break;
    
    case SNP_HCI_OPCODE_READ_BDADDR:
    {
      stat = HCI_ReadBDADDRCmd();
      if(stat == SUCCESS)
      {
        // Set state to wait for the HCI event with the address
        snp_HCIstore.validity = TRUE;
        snp_HCIstore.opcode = opcode;
        status = blePending;
      }
      else
      {
        status = stat;
      }
    }
    break;
    
    case SNP_HCI_OPCODE_EXT_SET_BDADDR:
      {
        if(dataLen != B_ADDR_LEN) 
        {
          status = SNP_INVALID_PARAMS;
        }
        else
        {
          stat = HCI_EXT_SetBDADDRCmd(pData);
          if(stat == SUCCESS)
          {
            // Set state to wait for the HCI event with the address
            snp_HCIstore.validity = TRUE;
            snp_HCIstore.opcode = opcode;
            status = blePending;
          }
          else
          {
            status = stat;
          }
        }
      }
      break;
      
    case SNP_HCI_OPCODE_EXT_SET_TX_POWER:
      {
        if(dataLen != sizeof(uint8_t)) 
        {
          status = SNP_INVALID_PARAMS;
        }
        else
        {
          stat = HCI_EXT_SetTxPowerCmd(pData[0]);
          if(stat == SUCCESS)
          {
            // Set state to wait for the HCI event with the address
            snp_HCIstore.validity = TRUE;
            snp_HCIstore.opcode = opcode;
            status = blePending;
          }
          else
          {
            status = stat;
          }
        }
      }
      break;
      
    case SNP_HCI_OPCODE_EXT_SET_SCA:
      if(dataLen != sizeof(uint16_t)) 
      {
        status = SNP_INVALID_PARAMS;
      }
      else
      {
        stat = HCI_EXT_SetSCACmd((pData[0] &0xFF) +  (pData[1] << 8));
        if(stat == SUCCESS)
        {
          // Set state to wait for the HCI event with the address
          snp_HCIstore.validity = TRUE;
          snp_HCIstore.opcode = opcode;
          status = blePending;
        }
        else
        {
          status = stat;
        }
      }
      break;
      
    case SNP_HCI_OPCODE_EXT_MODEM_TEST_TX:
      if(dataLen != 2*sizeof(uint8_t)) 
      {
        status = SNP_INVALID_PARAMS;
      }
      else
      {
        stat = HCI_EXT_ModemTestTxCmd(pData[0], pData[1]);
        if(stat == SUCCESS)
        {
          // Set state to wait for the HCI event with the address
          snp_HCIstore.validity = TRUE;
          snp_HCIstore.opcode = opcode;
          status = blePending;
        }
        else
        {
          status = stat;
        }
      }
      break;
      
    case SNP_HCI_OPCODE_EXT_MODEM_HOP_TEST_TX:
      stat = HCI_EXT_ModemHopTestTxCmd();
      if(stat == SUCCESS)
      {
        // Set state to wait for the HCI event with the address
        snp_HCIstore.validity = TRUE;
        snp_HCIstore.opcode = opcode;
        status = blePending;
      }
      else
      {
        status = stat;
      }
      break;
      
    case SNP_HCI_OPCODE_EXT_MODEM_TEST_RX:
      if(dataLen != sizeof(uint8_t)) 
      {
        status = SNP_INVALID_PARAMS;
      }
      else
      {
        stat = HCI_EXT_ModemTestRxCmd(pData[0]);
        if(stat == SUCCESS)
        {
          // Set state to wait for the HCI event with the address
          snp_HCIstore.validity = TRUE;
          snp_HCIstore.opcode = opcode;
          status = blePending;
        }
        else
        {
          status = stat;
        }
      }
      break;
      
    case SNP_HCI_OPCODE_EXT_END_MODEM_TEST:
      stat = HCI_EXT_EndModemTestCmd();
      if(stat == SUCCESS)
      {
        // Set state to wait for the HCI event with the address
        snp_HCIstore.validity = TRUE;
        snp_HCIstore.opcode = opcode;
        status = blePending;
      }
      else
      {
        status = stat;
      }
      break;
      
    case SNP_HCI_OPCODE_EXT_ENABLE_PTM:
      stat = HCI_EXT_EnablePTMCmd();
      if(stat == SUCCESS)
      {
        status = SNP_SUCCESS;
      }
      else
      {
        status = stat;
      }
      break;
      
    case SNP_HCI_OPCODE_EXT_SET_MAX_DTM_TX_POWER:
      if(dataLen != sizeof(uint8_t)) 
      {
        status = SNP_INVALID_PARAMS;
      }
      else
      {
        stat = HCI_EXT_SetMaxDtmTxPowerCmd(pData[0]);
        if(stat == SUCCESS)
        {
          // Set state to wait for the HCI event with the address
          snp_HCIstore.validity = TRUE;
          snp_HCIstore.opcode = opcode;
          status = blePending;
        }
        else
        {
          status = stat;
        }
      }
      break;
      
    case SNP_HCI_OPCODE_READ_RSSI:
      if(dataLen != sizeof(uint16_t)) 
      {
        status = SNP_INVALID_PARAMS;
      }
      else
      {
        stat = HCI_ReadRssiCmd((pData[0] &0xFF) +  (pData[1] << 8));
        if(stat == SUCCESS)
        {
          // Set state to wait for the HCI event with the address
          snp_HCIstore.validity = TRUE;
          snp_HCIstore.opcode = opcode;
          status = blePending;
        }
        else
        {
          status = stat;
        }
      }
      break;
      
    case SNP_HCI_OPCODE_LE_RECEIVER_TEST:
      if(dataLen != sizeof(uint8_t)) 
      {
        status = SNP_INVALID_PARAMS;
      }
      else
      {
        stat = HCI_LE_ReceiverTestCmd(pData[0]);
        if(stat == SUCCESS)
        {
          // Set state to wait for the HCI event with the address
          snp_HCIstore.validity = TRUE;
          snp_HCIstore.opcode = opcode;
          status = blePending;
        }
        else
        {
          status = stat;
        }
      }
      break;
      
    case SNP_HCI_OPCODE_LE_TRANSMITTER_TEST:
      if(dataLen != 3 * sizeof(uint8_t)) 
      {
        status = SNP_INVALID_PARAMS;
      }
      else
      {
        stat = HCI_LE_TransmitterTestCmd(pData[0], pData[1], pData[2]);
        if(stat == SUCCESS)
        {
          // Set state to wait for the HCI event with the address
          snp_HCIstore.validity = TRUE;
          snp_HCIstore.opcode = opcode;
          status = blePending;
        }
        else
        {
          status = stat;
        }
      }
      break;
      
    case SNP_HCI_OPCODE_LE_TEST_END:
      stat = HCI_LE_TestEndCmd();
      if(stat == SUCCESS)
      {
        // Set state to wait for the HCI event with the address
        snp_HCIstore.validity = TRUE;
        snp_HCIstore.opcode = opcode;
        status = blePending;
      }
      else
      {
        status = stat;
      }
      break;
      
    case SNP_HCI_OPCODE_EXT_PER:
      if(dataLen != (sizeof(uint8_t) + sizeof(uint16_t))) 
      {
        status = SNP_INVALID_PARAMS;
      }
      else
      {
        stat = HCI_EXT_PacketErrorRateCmd(pData[0] +  (pData[1] << 8),
                                          pData[2]);
        if(stat == SUCCESS)
        {
          // Set state to wait for the HCI event with the address
          snp_HCIstore.validity = TRUE;
          snp_HCIstore.opcode = opcode;
          status = blePending;
        }
        else
        {
          status = stat;
        }
      }
      break;
      
    case SNP_HCI_OPCODE_EXT_DECRYPT:
      if(dataLen != (KEYLEN + KEYLEN)) 
      {
        status = SNP_INVALID_PARAMS;
      }
      else
      {
        // reverse byte order of key (MSB..LSB required)
        SNP_ReverseBytes(&pData[0], KEYLEN);

        // reverse byte order of encText (MSB..LSB required)
        SNP_ReverseBytes(&pData[KEYLEN], KEYLEN);
        
        stat = HCI_EXT_DecryptCmd(&pData[0], &pData[KEYLEN]);
        if(stat == SUCCESS)
        {
          // Set state to wait for the HCI event with the address
          snp_HCIstore.validity = TRUE;
          snp_HCIstore.opcode = opcode;
          status = blePending;
        }
        else
        {
          status = stat;
        }
      }
      break;
      
    case SNP_HCI_OPCODE_LE_ENCRYPT:
      if(dataLen != (KEYLEN + KEYLEN)) 
      {
        status = SNP_INVALID_PARAMS;
      }
      else
      {
        // reverse byte order of key (MSB..LSB required)
        SNP_ReverseBytes(&pData[0], KEYLEN);

        // reverse byte order of encText (MSB..LSB required)
        SNP_ReverseBytes(&pData[KEYLEN], KEYLEN);
        
        stat = HCI_LE_EncryptCmd(&pData[0], &pData[KEYLEN]);
        if(stat == SUCCESS)
        {
          // Set state to wait for the HCI event with the address
          snp_HCIstore.validity = TRUE;
          snp_HCIstore.opcode = opcode;
          status = blePending;
        }
        else
        {
          status = stat;
        }
      }
      break;
      
    case SNP_HCI_OPCODE_EXT_OVERRIDE_SL:
      if(dataLen != sizeof(uint8_t)) 
      {
        status = SNP_INVALID_PARAMS;
      }
      else
      {
      
        stat = HCI_EXT_SetSlaveLatencyOverrideCmd(pData[0]);
        if(stat == SUCCESS)
        {
          // Set state to wait for the HCI event with the address
          snp_HCIstore.validity = TRUE;
          snp_HCIstore.opcode = opcode;
          status = blePending;
        }
        else
        {
          status = stat;
        }
      }
      break;
      
    case SNP_HCI_OPCODE_EXT_SET_FAST_TX_RESP_TIME:
      if(dataLen != sizeof(uint8_t)) 
      {
        status = SNP_INVALID_PARAMS;
      }
      else
      {        
        stat = HCI_EXT_SetFastTxResponseTimeCmd(pData[0]);
        if(stat == SUCCESS)
        {
          // Set state to wait for the HCI event with the address
          snp_HCIstore.validity = TRUE;
          snp_HCIstore.opcode = opcode;
          status = blePending;
        }
        else
        {
          status = stat;
        }
      }
      break;
      
    case SNP_HCI_OPCODE_EXT_ONE_PKT_PER_EVT:
      if(dataLen != sizeof(uint8_t)) 
      {
        status = SNP_INVALID_PARAMS;
      }
      else
      {        
        stat = HCI_EXT_OnePktPerEvtCmd(pData[0]);
        if(stat == SUCCESS)
        {
          // Set state to wait for the HCI event with the address
          snp_HCIstore.validity = TRUE;
          snp_HCIstore.opcode = opcode;
          status = blePending;
        }
        else
        {
          status = stat;
        }
      }
      break;
      
    case SNP_HCI_OPCODE_EXT_GET_CONNECTION_INFO:
      stat = HCI_EXT_GetConnInfoCmd(NULL, NULL, NULL);
      if(stat == SUCCESS)
      {
        // Set state to wait for the HCI event with the address
        snp_HCIstore.validity = TRUE;
        snp_HCIstore.opcode = opcode;
        status = blePending;
      }
      else
      {
        status = stat;
      }
      break;
  default:
      status = SNP_HCI_CMD_UNKNOWN;
      break;
  }
   return status;
}
Exemple #2
0
/*********************************************************************
 * @fn      hidappCentralEventCB
 *
 * @brief   Notification from the profile of a state change.
 *
 * @param   pEvent - new role event
 *
 * @return  none
 */
static void hidappCentralEventCB( gapCentralRoleEvent_t *pEvent )
{
  static uint8 addrType;
  static uint8 peerDeviceFound = FALSE;

  switch( pEvent->gap.opcode )
  {
    case GAP_DEVICE_INIT_DONE_EVENT:
      {
        gapDeviceInitDoneEvent_t *pEvt = (gapDeviceInitDoneEvent_t *)pEvent;

        // See if device has a valid BD Address
        if ( osal_isbufset( pEvt->devAddr, 0xFF, B_ADDR_LEN ) == FALSE )
        {
          #if defined ( NANO_DONGLE )

          if ( hidappBondCount() > 0 )
          {
            // Initiate connection
            hidappEstablishLink( TRUE, addrType, remoteAddr );
          }
          else
          {
            // Sit idle till ask to scan
            hidappSetIdle();
          }

          #endif //  #if defined ( NANO_DONGLE )
        }
        else
        {
          uint8 ownBDaddr[] = OWN_ADDR;

          // An old CC2540 USB Dongle has all 0xFF's for its BD Address so
          // just use the hard-coded address in that case.
          HCI_EXT_SetBDADDRCmd( ownBDaddr );

          // Re-initialize the device with the new address
          osal_set_event( hidappTaskId, HIDAPP_EVT_START );
        }
      }
      break;

    case GAP_DEVICE_INFO_EVENT:
      // Goes here before entering GAP_DEVICE_DISCOVERY_EVENT

      // Read advertising/scan response data
      // if it contains HID remote, end service discovery
      if ( hidappFindSvcUuid( HID_SERVICE_UUID,
                              pEvent->deviceInfo.pEvtData,
                              pEvent->deviceInfo.dataLen ) )
      {
        // Record peer devices address data
        addrType = pEvent->deviceInfo.addrType;
        osal_memcpy( remoteAddr, pEvent->deviceInfo.addr, B_ADDR_LEN );

        peerDeviceFound = TRUE;
      }

      if ( ( peerDeviceFound == TRUE ) &&
           ( pEvent->deviceInfo.eventType == GAP_ADTYPE_SCAN_RSP_IND ) &&
           hidappFindHIDRemote( pEvent->deviceInfo.pEvtData,
                                pEvent->deviceInfo.dataLen ) )
      {
        // End device discovery
        VOID GAPCentralRole_CancelDiscovery();
      }
      break;

    case GAP_DEVICE_DISCOVERY_EVENT:
      // If we have found a connectable device, establish a connection
      if ( peerDeviceFound == TRUE )
      {
        hidappEstablishLink( FALSE, addrType, remoteAddr );

        peerDeviceFound = FALSE;
        numScans = 0;
      }
      else if ( numScans > 0 )
      {
        numScans--;

        // Scan again
        hidappDiscoverDevices();
      }
      else
      {
        // Go idle
        hidappSetIdle();
      }
      break;

    case GAP_LINK_ESTABLISHED_EVENT:
      // Cancel initiate connection timer
      VOID osal_stop_timerEx( hidappTaskId, HIDAPP_EVT_INIT_CONNECT );

      if ( pEvent->gap.hdr.status == SUCCESS )
      {
        hidappBLEState = BLE_STATE_CONNECTED;

        HalLedSet( HAL_LED_1, HAL_LED_MODE_ON );  // green led

        connHandle = ((gapEstLinkReqEvent_t*)pEvent)->connectionHandle;
      }
      else if ( hidappBondCount() > 0 )
      {
        // Re-initiate connection
        hidappEstablishLink( TRUE, addrType, remoteAddr );
      }
      else
      {
        // Go idle
        hidappSetIdle();
      }
      break;

    case GAP_LINK_TERMINATED_EVENT:
      // Cancel initiate connection timer
      VOID osal_stop_timerEx( hidappTaskId, HIDAPP_EVT_INIT_CONNECT );

      HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF ); // green led

      hidappBLEState = BLE_STATE_IDLE;
      gapBondMgrState = UNPAIRED_STATE;
      connHandle = INVALID_CONNHANDLE;

      if ( serviceDiscComplete == TRUE )
      {
        // Remember the address of the last connected remote
        osal_memcpy( remoteHandles.lastRemoteAddr, remoteAddr, B_ADDR_LEN );

        // Save handle information
        hidappSaveHandles();
      }

      // Invalidate service discovery variables.
      serviceDiscComplete    = FALSE;
      mouseCharHandle        = GATT_INVALID_HANDLE;
      keyCharHandle          = GATT_INVALID_HANDLE;
      consumerCtrlCharHandle = GATT_INVALID_HANDLE;

      mouseCCCHandle         = GATT_INVALID_HANDLE;
      keyCCCHandle           = GATT_INVALID_HANDLE;
      consumerCtrlCCCHandle  = GATT_INVALID_HANDLE;
      serviceChangeHandle    = GATT_INVALID_HANDLE;
      serviceToDiscover      = GATT_INVALID_HANDLE;

      enableCCCDs = TRUE;

      if ( hidappBondCount() > 0 )
      {
        // Re-initiate connection
        hidappEstablishLink( TRUE, addrType, remoteAddr );
      }
      else
      {
        // Go idle
        hidappSetIdle();
      }
      break;

    default:
      break;
  }
}
/*********************************************************************
 * @fn      DualImageConcept_init
 *
 * @brief   Called during initialization and contains application
 *          specific initialization (ie. hardware initialization/setup,
 *          table initialization, power up notification, etc), and
 *          profile initialization/setup.
 *
 * @param   None.
 *
 * @return  None.
 */
static void DualImageConcept_init(void)
{
  // For CC1350LP Set DIO1 High for 2.4 GHz Radio usage.
  // Set DIO30 High to power radio.
  
  
  
  // ******************************************************************
  // N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp
  // ******************************************************************
  // Register the current thread as an ICall dispatcher application
  // so that the application can send and receive messages.
  ICall_registerApp(&selfEntity, &sem);
    
  // Hard code the BD Address till CC2650 board gets its own IEEE address
  uint8 bdAddress[B_ADDR_LEN] = { 0x1C, 0xCD, 0xD1, 0x1C, 0xCD, 0xD1 };
  HCI_EXT_SetBDADDRCmd(bdAddress);
  
  // Set device's Sleep Clock Accuracy
  //HCI_EXT_SetSCACmd(40);
  
  // Create an RTOS queue for message from profile to be sent to app.
  appMsgQueue = Util_constructQueue(&appMsg);
  
  Board_initKeys(DualImageConcept_keyChangeHandler);
  
  dispHandle = Display_open(Display_Type_LCD, NULL);
  
  // Setup the GAP
  GAP_SetParamValue(TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL);

  // Setup the GAP Peripheral Role Profile
  {
    // For all hardware platforms, device starts advertising upon initialization
    uint8_t initialAdvertEnable = TRUE;

    // By setting this to zero, the device will go into the waiting state after
    // being discoverable for 30.72 second, and will not being advertising again
    // until the enabler is set back to TRUE
    uint16_t advertOffTime = 0;

    uint8_t enableUpdateRequest = DEFAULT_ENABLE_UPDATE_REQUEST;
    uint16_t desiredMinInterval = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
    uint16_t desiredMaxInterval = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
    uint16_t desiredSlaveLatency = DEFAULT_DESIRED_SLAVE_LATENCY;
    uint16_t desiredConnTimeout = DEFAULT_DESIRED_CONN_TIMEOUT;

    // Set the GAP Role Parameters
    GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), 
                         &initialAdvertEnable);
    GAPRole_SetParameter(GAPROLE_ADVERT_OFF_TIME, sizeof(uint16_t), 
                         &advertOffTime);

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

    GAPRole_SetParameter(GAPROLE_PARAM_UPDATE_ENABLE, sizeof(uint8_t), 
                         &enableUpdateRequest);
    GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16_t), 
                         &desiredMinInterval);
    GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16_t), 
                         &desiredMaxInterval);
    GAPRole_SetParameter(GAPROLE_SLAVE_LATENCY, sizeof(uint16_t), 
                         &desiredSlaveLatency);
    GAPRole_SetParameter(GAPROLE_TIMEOUT_MULTIPLIER, sizeof(uint16_t), 
                         &desiredConnTimeout);
  }

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

  // Set advertising interval
  {
    uint16_t advInt = DEFAULT_ADVERTISING_INTERVAL;

    GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MIN, advInt);
    GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MAX, advInt);
    GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, advInt);
    GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, advInt);
  }

   // Initialize GATT attributes
  GGS_AddService(GATT_ALL_SERVICES);           // GAP
  GATTServApp_AddService(GATT_ALL_SERVICES);   // GATT attributes

  // Start the Device
  VOID GAPRole_StartDevice(&DualImageConcept_gapRoleCBs);
  
  Display_print0(dispHandle, 0, 0, "CC1350 BLE Image A");
  
  // Check for shared data
  osal_snv_read(0x80, sizeof(uint8_t), &sharedData);
  
  // Write the shared data to the LCD.
  Display_print1(dispHandle, 6, 0, "Shared Data: %d", sharedData);
}