Ejemplo n.º 1
0
void act_linearAct_Process(void)
{
	if (Timer_Expired(act_linearAct_TIMER_report)) {
		linearAct_sendPosition(0);
	}
#if (USE_STIMULI == 1)
	if (Timer_Expired(act_linearAct_TIMER_stimuli)) {
		gpio_toggle_pin(STIMULI);
	}
#endif
}
Ejemplo n.º 2
0
/**
 * @brief  Writes data to a serial interface.
 * @param  data1   :  1st buffer
 * @param  data2   :  2nd buffer
 * @param  n_bytes1: number of bytes in 1st buffer
 * @param  n_bytes2: number of bytes in 2nd buffer
 * @retval None
 */
void Hal_Write_Serial(const void *data1, const void *data2, int32_t n_bytes1,
		      int32_t n_bytes2)
{
	struct timer t;

	Timer_Set(&t, CLOCK_SECOND / 10);

#ifdef PRINT_CSV_FORMAT
	PRINT_CSV("00:00:00.000");
	for (int i = 0; i < n_bytes1; i++) {
		PRINT_CSV(" %02x", ((uint8_t *) data1)[i]);
	}
	for (int i = 0; i < n_bytes2; i++) {
		PRINT_CSV(" %02x", ((uint8_t *) data2)[i]);
	}
	PRINT_CSV("\n");
#endif

	while (1) {
		if (BlueNRG_SPI_Write
		    (&SpiHandle, (uint8_t *) data1, (uint8_t *) data2, n_bytes1,
		     n_bytes2) == 0)
			break;
		if (Timer_Expired(&t)) {
			break;
		}
	}
}
Ejemplo n.º 3
0
void tst_CoreLED_Process(void)
{
	/// Stuff that needs doing is done here
	
	if (Timer_Expired(tst_CoreLED_Blink_TIMER))
	{
		gpio_toggle_pin(tst_CoreLED_PIN);
	}
}
Ejemplo n.º 4
0
/**
 * @brief  Enable notification
 * @param  None 
 * @retval None
 */
void enableNotification(void)
{
  uint8_t client_char_conf_data[] = {0x01, 0x00}; // Enable notifications
  struct timer t;
  Timer_Set(&t, CLOCK_SECOND*10);
  
  while(aci_gatt_write_charac_descriptor(connection_handle, tx_handle+2, 2, client_char_conf_data)==BLE_STATUS_NOT_ALLOWED){
    /* Radio is busy */
    if(Timer_Expired(&t)) break;
  }
  notification_enabled = TRUE;
}
Ejemplo n.º 5
0
void act_output_Process(void)
{
#if act_output_USEEEPROM==1
	if (Timer_Expired(act_output_STORE_VALUE_TIMEOUT))
	{
		uint8_t index = 0;
#ifdef	act_output_CH0
		eeprom_write_byte_crc(EEDATA.ch0, chnValue[index], WITHOUT_CRC);
		index++;
#endif
#ifdef	act_output_CH1
		eeprom_write_byte_crc(EEDATA.ch1, chnValue[index], WITHOUT_CRC);
		index++;
#endif
#ifdef	act_output_CH2
		eeprom_write_byte_crc(EEDATA.ch2, chnValue[index], WITHOUT_CRC);
		index++;
#endif
#ifdef	act_output_CH3
		eeprom_write_byte_crc(EEDATA.ch3, chnValue[index], WITHOUT_CRC);
		index++;
#endif
#ifdef	act_output_CH4
		eeprom_write_byte_crc(EEDATA.ch4, chnValue[index], WITHOUT_CRC);
		index++;
#endif
#ifdef	act_output_CH5
		eeprom_write_byte_crc(EEDATA.ch5, chnValue[index], WITHOUT_CRC);
		index++;
#endif
#ifdef	act_output_CH6
		eeprom_write_byte_crc(EEDATA.ch6, chnValue[index], WITHOUT_CRC);
		index++;
#endif
#ifdef	act_output_CH7
		eeprom_write_byte_crc(EEDATA.ch7, chnValue[index], WITHOUT_CRC);
		index++;
#endif	  
#ifdef	act_output_CH8
		eeprom_write_byte_crc(EEDATA.ch8, chnValue[index], WITHOUT_CRC);
		index++;
#endif	  
#ifdef	act_output_CH9
		eeprom_write_byte_crc(EEDATA.ch9, chnValue[index], WITHOUT_CRC);
		index++;
#endif	  
		EEDATA_UPDATE_CRC;
	}
#endif

}
Ejemplo n.º 6
0
/*  Enable notification */
static void enableNotification(void)
{
    uint8_t client_char_conf_data[] = {0x01, 0x00}; // Enable notifications
    struct timer t;
    Timer_Set(&t, CLOCK_SECOND*10);

    while(aci_gatt_write_charac_descriptor(connection_handle, notify_read_handle+2, 2, client_char_conf_data)==BLE_STATUS_NOT_ALLOWED) {
        /* Radio is busy */
        if(Timer_Expired(&t)) break;
    }
    host_notification_enabled = TRUE;
    HAL_Delay(100);
    ble_host_on_connect();
    printf("notification enable\n\r");
}
Ejemplo n.º 7
0
void sns_rfid_Process(void)
{
    uint8_t version;
    uint32_t id;
    if( 0 == rfid_fetch( &version, &id ) ) {
        if( !sns_rfid_got_card ) {
            sns_rfid_got_card = 1;
            sns_rfid_card.id      = id;
            sns_rfid_card.version = version;
            // Card arrived
            sns_rfid_HandleCardEvent(1);
        }
        Timer_SetTimeout(sns_rfid_CARD_LEFT_TIMER, sns_rfid_CARD_LEFT_TIME, TimerTypeOneShot, 0);
    }
    if ( Timer_Expired(sns_rfid_CARD_LEFT_TIMER) ) {
        sns_rfid_got_card = 0;
        // Card left
        sns_rfid_HandleCardEvent(0);
    }
}
Ejemplo n.º 8
0
void sns_counter_Process(void)
{
#if sns_counter_USEEEPROM==1
	if (StoreInEEPROM == 1)
	{
		StoreInEEPROM = 0;
		eeprom_write_dword_crc(EEDATA32.Count[0], (uint32_t)(Count[0]), WITH_CRC);
	}
#endif
#ifdef sns_counter_SEND_TIMER
	if (Timer_Expired(sns_counter_SEND_TIMER)) {
	#ifdef sns_counter_CH0
		sns_counter_send_counter(0);
	#endif
	#ifdef sns_counter_CH1
		sns_counter_send_counter(1);
	#endif
	#ifdef sns_counter_CH2
		sns_counter_send_counter(2);
	#endif
	#ifdef sns_counter_CH3
		sns_counter_send_counter(3);
	#endif
	#ifdef sns_counter_CH4
		sns_counter_send_counter(4);
	#endif
	#ifdef sns_counter_CH5
		sns_counter_send_counter(5);
	#endif
	#ifdef sns_counter_CH6
		sns_counter_send_counter(6);
	#endif
	#ifdef sns_counter_CH7
		sns_counter_send_counter(7);
	#endif
	}
#endif
}
Ejemplo n.º 9
0
int hci_send_req(struct hci_request *r, BOOL async)
{
  uint8_t *ptr;
  uint16_t opcode = htobs(cmd_opcode_pack(r->ogf, r->ocf));
  hci_event_pckt *event_pckt;
  hci_uart_pckt *hci_hdr;
  int to = DEFAULT_TIMEOUT;
  struct timer t;
  tHciDataPacket * hciReadPacket = NULL;
  tListNode hciTempQueue;
  
  list_init_head(&hciTempQueue);
  
  hci_send_cmd(r->ogf, r->ocf, r->clen, r->cparam);
  
  if(async){
    goto done;
  }
  
  /* Minimum timeout is 1. */
  if(to == 0)
    to = 1;
  
  Timer_Set(&t, to);
  
  while(1) {
    evt_cmd_complete *cc;
    evt_cmd_status *cs;
    evt_le_meta_event *me;
    int len;
      
#if ENABLE_MICRO_SLEEP    
    while(1){
      ATOMIC_SECTION_BEGIN();
      if(Timer_Expired(&t)){
        ATOMIC_SECTION_END();
        goto failed;
      }
      if(!HCI_Queue_Empty()){
        ATOMIC_SECTION_END();
        break;
      }
      Enter_Sleep_Mode();
      ATOMIC_SECTION_END();
    }
#else
    while(1){
      if(Timer_Expired(&t)){
        goto failed;
      }
      if(!HCI_Queue_Empty()){
        break;
      }
    }
#endif
    
    /* Extract packet from HCI event queue. */
    Disable_SPI_IRQ();
    list_remove_head(&hciReadPktRxQueue, (tListNode **)&hciReadPacket);    
    
    hci_hdr = (void *)hciReadPacket->dataBuff;
    if(hci_hdr->type != HCI_EVENT_PKT){
      list_insert_tail(&hciTempQueue, (tListNode *)hciReadPacket); // See comment below
      Enable_SPI_IRQ();
      continue;
    }
    
    event_pckt = (void *) (hci_hdr->data);
    
    ptr = hciReadPacket->dataBuff + (1 + HCI_EVENT_HDR_SIZE);
    len = hciReadPacket->data_len - (1 + HCI_EVENT_HDR_SIZE);
    
    switch (event_pckt->evt) {
      
    case EVT_CMD_STATUS:
      cs = (void *) ptr;
      
      if (cs->opcode != opcode)
        goto failed;
      
      if (r->event != EVT_CMD_STATUS) {
        if (cs->status) {
          goto failed;
        }
        break;
      }
      
      r->rlen = MIN(len, r->rlen);
      Osal_MemCpy(r->rparam, ptr, r->rlen);
      goto done;
      
    case EVT_CMD_COMPLETE:
      cc = (void *) ptr;
      
      if (cc->opcode != opcode)
        goto failed;
      
      ptr += EVT_CMD_COMPLETE_SIZE;
      len -= EVT_CMD_COMPLETE_SIZE;
      
      r->rlen = MIN(len, r->rlen);
      Osal_MemCpy(r->rparam, ptr, r->rlen);
      goto done;
      
    case EVT_LE_META_EVENT:
      me = (void *) ptr;
      
      if (me->subevent != r->event)
        break;
      
      len -= 1;
      r->rlen = MIN(len, r->rlen);
      Osal_MemCpy(r->rparam, me->data, r->rlen);
      goto done;
      
    case EVT_HARDWARE_ERROR:            
      goto failed;
      
    default:      
      break;
    }
    
    /* In the meantime there could be other events from the controller.
    In this case, insert the packet in a different queue. These packets will be
    inserted back in the main queue just before exiting from send_req().
    */
    list_insert_tail(&hciTempQueue, (tListNode *)hciReadPacket);
    /* Be sure there is at list one packet in the pool to process the expected event. */
    if(list_is_empty(&hciReadPktPool)){
      pListNode tmp_node;      
      list_remove_head(&hciReadPktRxQueue, &tmp_node);
      list_insert_tail(&hciReadPktPool, tmp_node);      
    }
    
    Enable_SPI_IRQ();
    
  }
  
failed: 
  move_list(&hciReadPktRxQueue, &hciTempQueue);  
  Enable_SPI_IRQ();
  return -1;
  
done:
  // Insert the packet back into the pool.
  list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket); 
  move_list(&hciReadPktRxQueue, &hciTempQueue);
  
  Enable_SPI_IRQ();
  return 0;
}
Ejemplo n.º 10
0
void sns_flower_Process(void)
{
	static uint8_t measureState=0;
	static uint16_t results[6];
	static uint16_t resultsInv[6];
	uint16_t temp;
	static uint8_t flowerChannelToSend = 0;
  
	
	if (Timer_Expired(sns_flower_WAIT_TIMER)) {
		
		gpio_set_out(sns_flower_highSide_PIN);
		gpio_set_out(sns_flower_lowSide_PIN);
		gpio_set_pin(sns_flower_highSide_PIN);
		gpio_clr_pin(sns_flower_lowSide_PIN);
		measureState=0;
		Timer_SetTimeout(sns_flower_MEASUREMENT_TIMER, sns_flower_MEASUREMENT_PERIOD_MS , TimerTypeOneShot, 0);
	}
	
	if (Timer_Expired(sns_flower_MEASUREMENT_TIMER)) {
		StdCan_Msg_t txMsg;
		StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
		StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
		txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_VOLTAGECURRENT;
		txMsg.Header.ModuleId = sns_flower_ID;
		txMsg.Length = 3;
		switch (measureState) {
			case 0:
#ifdef sns_flower0AD
				results[0] = ADC_Get(sns_flower0AD);
#endif
#ifdef sns_flower1AD
				results[1] = ADC_Get(sns_flower1AD);
#endif
#ifdef sns_flower2AD
				results[2] = ADC_Get(sns_flower2AD);
#endif
#ifdef sns_flower3AD
				results[3] = ADC_Get(sns_flower3AD);
#endif
#ifdef sns_flower4AD
				results[4] = ADC_Get(sns_flower4AD);
#endif
#ifdef sns_flower5AD
				results[5] = ADC_Get(sns_flower5AD);
#endif	
				gpio_clr_pin(sns_flower_highSide_PIN);
				gpio_set_pin(sns_flower_lowSide_PIN);
				measureState=1;
				Timer_SetTimeout(sns_flower_MEASUREMENT_TIMER, sns_flower_MEASUREMENT_PERIOD_MS , TimerTypeOneShot, 0);
				break;
			case 1:
#ifdef sns_flower0AD
				resultsInv[0] = 1023-ADC_Get(sns_flower0AD);
#endif
#ifdef sns_flower1AD
				resultsInv[1] = 1023-ADC_Get(sns_flower1AD);
#endif
#ifdef sns_flower2AD
				resultsInv[2] = 1023-ADC_Get(sns_flower2AD);
#endif
#ifdef sns_flower3AD
				resultsInv[3] = 1023-ADC_Get(sns_flower3AD);
#endif
#ifdef sns_flower4AD
				resultsInv[4] = 1023-ADC_Get(sns_flower4AD);
#endif
#ifdef sns_flower5AD
				resultsInv[5] = 1023-ADC_Get(sns_flower5AD);
#endif	
				gpio_clr_pin(sns_flower_highSide_PIN);
				gpio_clr_pin(sns_flower_lowSide_PIN);
				gpio_set_in(sns_flower_highSide_PIN);
				gpio_set_in(sns_flower_lowSide_PIN);
				measureState=2;
				flowerChannelToSend=0;
				Timer_SetTimeout(sns_flower_MEASUREMENT_TIMER, sns_flower_MEASUREMENT_PERIOD_MS , TimerTypeOneShot, 0);
				break;
			case 2:	
				  switch(flowerChannelToSend) {
					  case 0:
#ifdef sns_flower0AD
						txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PERCENT;
						txMsg.Data[0] = 0;
						temp = (uint16_t)((float)(results[0]+resultsInv[0])*4.888);
						txMsg.Data[1] = (temp>>8)&0xff;
						txMsg.Data[2] = (temp)&0xff;

						while (StdCan_Put(&txMsg) != StdCan_Ret_OK) {}
						flowerChannelToSend = 1;
# if  !(defined(sns_flower1AD) || defined(sns_flower2AD) || defined(sns_flower3AD) || defined(sns_flower4AD) || defined(sns_flower5AD))
						flowerChannelToSend = 0;
						measureState=0;
# endif
						break;
#endif
					case 1:
#ifdef sns_flower1AD
						txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PERCENT;
						txMsg.Data[0] = 1;
						temp = (uint16_t)((float)(results[1]+resultsInv[1])*4.888);
						txMsg.Data[1] = (temp>>8)&0xff;
						txMsg.Data[2] = (temp)&0xff;

						while (StdCan_Put(&txMsg) != StdCan_Ret_OK) {}
						flowerChannelToSend = 2;
# if  !(defined(sns_flower2AD) || defined(sns_flower3AD) || defined(sns_flower4AD) || defined(sns_flower5AD))
						flowerChannelToSend = 0;
						measureState=0;
# endif
						break;
#endif
					case 2:
#ifdef sns_flower2AD
						txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PERCENT;
						txMsg.Data[0] = 2;
						temp = (uint16_t)((float)(results[2]+resultsInv[2])*4.888);
						txMsg.Data[1] = (temp>>8)&0xff;
						txMsg.Data[2] = (temp)&0xff;

						while (StdCan_Put(&txMsg) != StdCan_Ret_OK) {}
						flowerChannelToSend = 3;
#if  !(defined(sns_flower3AD) || defined(sns_flower4AD) || defined(sns_flower5AD))
						flowerChannelToSend = 0;
						measureState=0;
#endif
						break;
#endif
					case 3:
#ifdef sns_flower3AD
						txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PERCENT;
						txMsg.Data[0] = 3;
						temp = (uint16_t)((float)(results[3]+resultsInv[3])*4.888);
						txMsg.Data[1] = (temp>>8)&0xff;
						txMsg.Data[2] = (temp)&0xff;

						while (StdCan_Put(&txMsg) != StdCan_Ret_OK) {}
						flowerChannelToSend = 4;
#if  !( defined(sns_flower4AD) || defined(sns_flower5AD))
						flowerChannelToSend = 0;
						measureState=0;
#endif
						break;
#endif
					case 4:
#ifdef sns_flower4AD
						txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PERCENT;
						txMsg.Data[0] = 4;
						temp = (uint16_t)((float)(results[4]+resultsInv[4])*4.888);
						txMsg.Data[1] = (temp>>8)&0xff;
						txMsg.Data[2] = (temp)&0xff;

						while (StdCan_Put(&txMsg) != StdCan_Ret_OK) {}
						flowerChannelToSend = 5;
#if  !(defined(sns_flower5AD))
						flowerChannelToSend = 0;
						measureState=0;
#endif
						break;
#endif
					case 5:
#ifdef sns_flower5AD
						txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PERCENT;
						txMsg.Data[0] = 5;
						temp = (uint16_t)((float)(results[5]+resultsInv[5])*4.888);
						txMsg.Data[1] = (temp>>8)&0xff;
						txMsg.Data[2] = (temp)&0xff;

						while (StdCan_Put(&txMsg) != StdCan_Ret_OK) {}
						flowerChannelToSend = 0;
						measureState=0;
						break;
#endif
					default:
						measureState=0;
						break;
				}
				if (measureState != 0) {
					Timer_SetTimeout(sns_flower_MEASUREMENT_TIMER, sns_flower_CAN_MSG_PAUS_MS , TimerTypeOneShot, 0);
				}
				break;
		}
  
	}
}
Ejemplo n.º 11
0
void sns_irTransmit_Process(void)
{
	if (sns_irTransmit_state == sns_irTransmit_STATE_IDLE)
	{
	}
	else if (sns_irTransmit_state == sns_irTransmit_STATE_START_TRANSMIT)
	{
		if (expandProtocol(sns_irTransmit_txbuffer, &sns_irTransmit_length, &sns_irTransmit_proto) == IR_OK)
		{
			if (IrTransceiver_Transmit(sns_irTransmit_txbuffer, sns_irTransmit_length, sns_irTransmit_proto.modfreq) == IR_OK)
			{
				sns_irTransmit_state = sns_irTransmit_STATE_TRANSMITTING;
			}
			else
			{
				sns_irTransmit_state = sns_irTransmit_STATE_IDLE;
			}
		}
		else
		{
			sns_irTransmit_state = sns_irTransmit_STATE_IDLE;
		}
	}
	else if (sns_irTransmit_state == sns_irTransmit_STATE_TRANSMITTING){
		//polla om den är klar, om klar gå till sns_irTransmit_STATE_START_PAUSE
		if (IrTransceiver_Transmit_Poll() != IR_NOT_FINISHED)
		{
			sns_irTransmit_state = sns_irTransmit_STATE_START_PAUSE;
		}
	}
	else if (sns_irTransmit_state == sns_irTransmit_STATE_START_PAUSE)
	{
		if (sns_irTransmit_repeatCount < sns_irTransmit_proto.repeats)
		{
			sns_irTransmit_repeatCount++;
		}
		
		Timer_SetTimeout(sns_irTransmit_REPEAT_TIMER, sns_irTransmit_proto.timeout, TimerTypeOneShot, 0);
		
		if (sns_irTransmit_proto.framecnt != 255)
		{
			sns_irTransmit_proto.framecnt++;
		}
		
		sns_irTransmit_state = sns_irTransmit_STATE_PAUSING;
	}
	else if (sns_irTransmit_state == sns_irTransmit_STATE_PAUSING)
	{
		//när timeout har gått (timebase) så gå till sns_irTransmit_STATE_START_TRANSMIT
		if (Timer_Expired(sns_irTransmit_REPEAT_TIMER))
		{
			sns_irTransmit_state = sns_irTransmit_STATE_START_TRANSMIT;
		}
		
		if (sns_irTransmit_stop == 1 && sns_irTransmit_repeatCount >= sns_irTransmit_proto.repeats)
		{
			sns_irTransmit_state = sns_irTransmit_STATE_STOP;
		}
	}
	else if (sns_irTransmit_state == sns_irTransmit_STATE_STOP)
	{
		sns_irTransmit_stop = 0;
		sns_irTransmit_proto.timeout = 0;
		sns_irTransmit_proto.framecnt = 0;
		sns_irTransmit_repeatCount = 0;
		sns_irTransmit_state = sns_irTransmit_STATE_IDLE;
	}
}
Ejemplo n.º 12
0
int main( void )
{
	// Enable interrupts as early as possible
	sei();
	
	Timer_Init();

	// Set as outputs and stop rotor
	DDRD |= (1 << PD1)|(1 << PD2);
	PORTD &= ~((1 << PD1)|(1 << PD2));
	
	// Setup ADC
	initAdcFeedback();
	
	Can_Message_t txMsg;
	txMsg.Id = (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE) | (NODE_ID << CAN_SHIFT_NMT_SID);
	txMsg.DataLength = 4;
	txMsg.RemoteFlag = 0;
	txMsg.ExtendedFlag = 1;
	txMsg.Data.words[0] = APP_TYPE;
	txMsg.Data.words[1] = APP_VERSION;
	
	// Set up callback for CAN reception
	BIOS_CanCallback = &can_receive;
	// Send CAN_NMT_APP_START
	BIOS_CanSend(&txMsg);
	
	// Read calibration value from eeprom
	azimuthCalibration = eeprom_read_word( CALIBRATE_AZIMUTH );
	
	// Timer for reading position feedback
	Timer_SetTimeout(0, 100, TimerTypeFreeRunning, 0);
	Timer_SetTimeout(1, 1000, TimerTypeFreeRunning, 0);

	sendStatus( STATUS );

	while (1) {
		if (Timer_Expired(0)) {
			// Periodicly read antennas position
			readFeedback();
		}
		if (Timer_Expired(1)) {
			sendStatus(STATUS);
		}
		
		if (rxMsgFull) {
			switch (rxMsg.Id){
				case MSG_CAL_SET: // Set calibration value
					if( 2 == rxMsg.DataLength ){
						calibration( SET, rxMsg.Data.words[0] );
					}
					break;
					
				case MSG_CAL_GET: // Get calibration value
					if( 0 == rxMsg.DataLength ){
						txMsg.Id = MSG_CAL_RET; 
						txMsg.DataLength = 2;
						txMsg.Data.words[0] = calibration( GET, 0 );
						BIOS_CanSend(&txMsg);
					}
					break;
					
				case MSG_ABS: // Start turning to absolute position
					if( 2 == rxMsg.DataLength ){
						
					}
					break;
					
				case MSG_REL: // Start turning to relative position
					if( 2 == rxMsg.DataLength ){
						
					}
					break;
					
				case MSG_START: // Start turning
					if( 1 == rxMsg.DataLength ){
						// First data byte decides direction
						controlRelay( rxMsg.Data.bytes[0] );
					}
					break;
					
				case MSG_STOP: // Stop turning
					//if( 1 == rxMsg.DataLength ){
						controlRelay( ROTATE_STOP );
					//}
					break;
				case MSG_STATUS: // Get position
					if( 0 == rxMsg.DataLength ){
						sendStatus(STATUS);
					}
					break;
					
				default:
					break;
			}

    			rxMsgFull = 0; //  
		}
	}
	
	return 0;
}
void act_protectedOutput_Process() {

#if act_protectedOutput_EEPROM_ENABLED == 1
	if (Timer_Expired(act_protectedOutput_STORE_VALUE_TIMEOUT)) {
#if	act_protectedOutput_CH_COUNT >= 1
		eeprom_write_byte_crc(EEDATA.ch0, chTargetState[0], WITHOUT_CRC);
#endif
#if	act_protectedOutput_CH_COUNT >= 2
		eeprom_write_byte_crc(EEDATA.ch1, chTargetState[1], WITHOUT_CRC);
#endif
#if	act_protectedOutput_CH_COUNT >= 3
		eeprom_write_byte_crc(EEDATA.ch2, chTargetState[2], WITHOUT_CRC);
#endif
#if	act_protectedOutput_CH_COUNT >= 4
		eeprom_write_byte_crc(EEDATA.ch3, chTargetState[3], WITHOUT_CRC);
#endif
		EEDATA_UPDATE_CRC;
	}
#endif

	// shall we retry to set target output state?
	if (Timer_Expired(act_protectedOutput_RETRY_TIMER)) {
		// read DIAG pin again and update outputs accordingly
		readDiagPin();
#if act_protectedOutput_FORCED_RETRIES == 1
		// forced retry to set output states, regardless of DIAG
		updateOutput(1);
		// read DIAG pin again and hope we have a better flag
		readDiagPin();
#else
		// if DIAG allows it, retry to set the output states
		updateOutput(0);
#endif
		if (diagState == DIAG_ASSERTED) {
			// if DIAG was still asserted, initiate another timer run
			Timer_SetTimeout(act_protectedOutput_RETRY_TIMER, act_protectedOutput_RETRY_TIMER_TIME_S*1000, TimerTypeOneShot, 0);
		}
		else {
			// things went back to normal. report this
			diagReportPending = 1;
		}
	}
	
	// shall we report diag status to CAN?
	if (diagReportPending) {
		StdCan_Msg_t txMsg;
		StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS);
		StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
		txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_PROTECTEDOUTPUT;
		txMsg.Header.ModuleId = act_protectedOutput_ID;
		txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PINSTATUS;
		txMsg.Length = 2;
		txMsg.Data[0] = 0; //TODO: add support for more channels
		// we follow the standard SNS_INPUT format, but the data corresponds to the "health" rather than physical level
		if (diagState == DIAG_NORMAL) {
			txMsg.Data[1] = 1;	//healthy, target output state stable
		} else {
			txMsg.Data[1] = 0;	//not healthy, DIAG pin ASSERTED, not in target output state
		}
		while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
		diagReportPending = 0;
	}
}
Ejemplo n.º 14
0
/* 'to' is timeout in system clock ticks.  */
int hci_send_req(struct hci_request *r)
{
	uint8_t *ptr;
	uint16_t opcode = htobs(cmd_opcode_pack(r->ogf, r->ocf));
	hci_event_pckt *event_pckt;
	hci_uart_pckt *hci_hdr;
	int try;
    int to = DEFAULT_TIMEOUT;
    
	new_packet = FALSE;
	hci_set_packet_complete_callback(new_hci_event);
	if (hci_send_cmd(r->ogf, r->ocf, r->clen, r->cparam) < 0)
		goto failed;
    
	try = 10;
	while (try--) {
		evt_cmd_complete *cc;
		evt_cmd_status *cs;
		evt_le_meta_event *me;
		int len;
        
        /* Minimum timeout is 1. */
        if(to == 0)
            to = 1;
        
		if (to > 0) {
			struct timer t;
            
			Timer_Set(&t, to);
            
			while(1){
				if(Timer_Expired(&t)){
					goto failed;
				}
				if(new_packet){
					break;
				}
			}
		}
        
		hci_hdr = (void *)hci_buffer;
		if(hci_hdr->type != HCI_EVENT_PKT){
            new_packet = FALSE;
            Enable_SPI_IRQ();
            continue;
        }
        
		event_pckt = (void *) (hci_hdr->data);
        
		ptr = hci_buffer + (1 + HCI_EVENT_HDR_SIZE);
		len = hci_pckt_len - (1 + HCI_EVENT_HDR_SIZE);
        
		switch (event_pckt->evt) {
            
		case EVT_CMD_STATUS:
			cs = (void *) ptr;
            
			if (cs->opcode != opcode)
				break;
            
			if (r->event != EVT_CMD_STATUS) {
				if (cs->status) {
					goto failed;
				}
				break;
			}
            
			r->rlen = MIN(len, r->rlen);
			Osal_MemCpy(r->rparam, ptr, r->rlen);
			goto done;
            
		case EVT_CMD_COMPLETE:
			cc = (void *) ptr;
            
			if (cc->opcode != opcode)
				break;
            
			ptr += EVT_CMD_COMPLETE_SIZE;
			len -= EVT_CMD_COMPLETE_SIZE;
            
			r->rlen = MIN(len, r->rlen);
			Osal_MemCpy(r->rparam, ptr, r->rlen);
			goto done;
            
		case EVT_LE_META_EVENT:
			me = (void *) ptr;
            
			if (me->subevent != r->event)
				break;
            
			len -= 1;
			r->rlen = MIN(len, r->rlen);
			Osal_MemCpy(r->rparam, me->data, r->rlen);
			goto done;
            
        case EVT_HARDWARE_ERROR:            
            goto failed;
            
		default:
            break; // In the meantime there could be other events from the controller.
		}
        
		new_packet = FALSE;
		Enable_SPI_IRQ();
        
	}
    
failed:
	hci_set_packet_complete_callback(NULL);
	Enable_SPI_IRQ();
	return -1;
    
done:
	hci_set_packet_complete_callback(NULL);
	Enable_SPI_IRQ();
	return 0;
}

int hci_reset()
{
  	struct hci_request rq;
	uint8_t status;

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_HOST_CTL;
	rq.ocf = OCF_RESET;
	rq.rparam = &status;
	rq.rlen = 1;

	if (hci_send_req(&rq) < 0)
		return -1;

	if (status) {
		return -1;
	}

	return 0;  
}

int hci_disconnect(uint16_t	handle, uint8_t reason)
{
  struct hci_request rq;
	disconnect_cp cp;
	uint8_t status;
  
	cp.handle = handle;
	cp.reason = reason;

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LINK_CTL;
	rq.ocf = OCF_DISCONNECT;
    rq.cparam = &cp;
	rq.clen = DISCONNECT_CP_SIZE;
    rq.event = EVT_CMD_STATUS;
	rq.rparam = &status;
	rq.rlen = 1;

	if (hci_send_req(&rq) < 0)
		return -1;

	if (status) {
		return -1;
	}

	return 0;  
}

int hci_le_read_local_version(uint8_t *hci_version, uint16_t *hci_revision, uint8_t *lmp_pal_version, 
			      uint16_t *manufacturer_name, uint16_t *lmp_pal_subversion)
{
	struct hci_request rq;
	read_local_version_rp resp;

	Osal_MemSet(&resp, 0, sizeof(resp));

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_INFO_PARAM;
	rq.ocf = OCF_READ_LOCAL_VERSION;
	rq.cparam = NULL;
	rq.clen = 0;
	rq.rparam = &resp;
	rq.rlen = READ_LOCAL_VERSION_RP_SIZE;

	if (hci_send_req(&rq) < 0)
		return -1;

	if (resp.status) {
		return -1;
	}


	*hci_version = resp.hci_version;
	*hci_revision =  btohs(resp.hci_revision);
	*lmp_pal_version = resp.lmp_pal_version;
	*manufacturer_name = btohs(resp.manufacturer_name);
	*lmp_pal_subversion = btohs(resp.lmp_pal_subversion);

	return 0;
}

int hci_le_read_buffer_size(uint16_t *pkt_len, uint8_t *max_pkt)
{
	struct hci_request rq;
	le_read_buffer_size_rp resp;

	Osal_MemSet(&resp, 0, sizeof(resp));

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_READ_BUFFER_SIZE;
	rq.cparam = NULL;
	rq.clen = 0;
	rq.rparam = &resp;
	rq.rlen = LE_READ_BUFFER_SIZE_RP_SIZE;

	if (hci_send_req(&rq) < 0)
		return -1;

	if (resp.status) {
		return -1;
	}
	
	*pkt_len = resp.pkt_len;
	*max_pkt = resp.max_pkt;

	return 0;
}

int hci_le_set_advertising_parameters(uint16_t min_interval, uint16_t max_interval, uint8_t advtype,
		uint8_t own_bdaddr_type, uint8_t direct_bdaddr_type, tBDAddr direct_bdaddr, uint8_t chan_map,
		uint8_t filter)
{
	struct hci_request rq;
	le_set_adv_parameters_cp adv_cp;
	uint8_t status;

	Osal_MemSet(&adv_cp, 0, sizeof(adv_cp));
	adv_cp.min_interval = min_interval;
	adv_cp.max_interval = max_interval;
	adv_cp.advtype = advtype;
	adv_cp.own_bdaddr_type = own_bdaddr_type;
	adv_cp.direct_bdaddr_type = direct_bdaddr_type;
    Osal_MemCpy(adv_cp.direct_bdaddr,direct_bdaddr,sizeof(adv_cp.direct_bdaddr));
	adv_cp.chan_map = chan_map;
	adv_cp.filter = filter;

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_SET_ADV_PARAMETERS;
	rq.cparam = &adv_cp;
	rq.clen = LE_SET_ADV_PARAMETERS_CP_SIZE;
	rq.rparam = &status;
	rq.rlen = 1;

	if (hci_send_req(&rq) < 0)
		return -1;

	if (status) {
		return -1;
	}

	return 0;
}

int hci_le_set_advertising_data(uint8_t length, const uint8_t data[])
{
	struct hci_request rq;
	le_set_adv_data_cp adv_cp;
	uint8_t status;

	Osal_MemSet(&adv_cp, 0, sizeof(adv_cp));
	adv_cp.length = length;
	Osal_MemCpy(adv_cp.data, data, MIN(31,length));

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_SET_ADV_DATA;
	rq.cparam = &adv_cp;
	rq.clen = LE_SET_ADV_DATA_CP_SIZE;
	rq.rparam = &status;
	rq.rlen = 1;

	if (hci_send_req(&rq) < 0)
		return -1;

	if (status) {
		return -1;
	}

	return 0;
}

int hci_le_set_advertise_enable(uint8_t enable)
{
	struct hci_request rq;
	le_set_advertise_enable_cp adv_cp;
	uint8_t status;

	Osal_MemSet(&adv_cp, 0, sizeof(adv_cp));
	adv_cp.enable = enable?1:0;

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_SET_ADVERTISE_ENABLE;
	rq.cparam = &adv_cp;
	rq.clen = LE_SET_ADVERTISE_ENABLE_CP_SIZE;
	rq.rparam = &status;
	rq.rlen = 1;

	if (hci_send_req(&rq) < 0)
		return -1;

	if (status) {
		return -1;
	}

	return 0;
}

int hci_le_rand(uint8_t random_number[8])
{
	struct hci_request rq;
	le_rand_rp resp;

	Osal_MemSet(&resp, 0, sizeof(resp));

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_RAND;
	rq.cparam = NULL;
	rq.clen = 0;
	rq.rparam = &resp;
	rq.rlen = LE_RAND_RP_SIZE;

	if (hci_send_req(&rq) < 0)
		return -1;

	if (resp.status) {
		return -1;
	}
    
    Osal_MemCpy(random_number, resp.random, 8);

	return 0;
}

int hci_le_set_scan_resp_data(uint8_t length, const uint8_t data[])
{
	struct hci_request rq;
	le_set_scan_response_data_cp scan_resp_cp;
	uint8_t status;

	Osal_MemSet(&scan_resp_cp, 0, sizeof(scan_resp_cp));
	scan_resp_cp.length = length;
	Osal_MemCpy(scan_resp_cp.data, data, MIN(31,length));

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_SET_SCAN_RESPONSE_DATA;
	rq.cparam = &scan_resp_cp;
	rq.clen = LE_SET_SCAN_RESPONSE_DATA_CP_SIZE;
	rq.rparam = &status;
	rq.rlen = 1;

	if (hci_send_req(&rq) < 0)
		return -1;

	if (status) {
		return -1;
	}

	return 0;
}

int hci_le_read_advertising_channel_tx_power(int8_t *tx_power_level)
{
	struct hci_request rq;
	le_read_adv_channel_tx_power_rp resp;

	Osal_MemSet(&resp, 0, sizeof(resp));

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_READ_ADV_CHANNEL_TX_POWER;
	rq.cparam = NULL;
	rq.clen = 0;
	rq.rparam = &resp;
	rq.rlen = LE_RAND_RP_SIZE;

	if (hci_send_req(&rq) < 0)
		return -1;

	if (resp.status) {
		return -1;
	}

	*tx_power_level = resp.level;

	return 0;
}

int hci_le_set_random_address(tBDAddr bdaddr)
{
	struct hci_request rq;
	le_set_random_address_cp set_rand_addr_cp;
	uint8_t status;

	Osal_MemSet(&set_rand_addr_cp, 0, sizeof(set_rand_addr_cp));
	Osal_MemCpy(set_rand_addr_cp.bdaddr, bdaddr, sizeof(tBDAddr));

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_SET_RANDOM_ADDRESS;
	rq.cparam = &set_rand_addr_cp;
	rq.clen = LE_SET_RANDOM_ADDRESS_CP_SIZE;
	rq.rparam = &status;
	rq.rlen = 1;

	if (hci_send_req(&rq) < 0)
		return -1;

	if (status) {
		return -1;
	}

	return 0;
}

int hci_read_bd_addr(tBDAddr bdaddr)
{
	struct hci_request rq;
	read_bd_addr_rp resp;

	Osal_MemSet(&resp, 0, sizeof(resp));

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_INFO_PARAM;
	rq.ocf = OCF_READ_BD_ADDR;
	rq.cparam = NULL;
	rq.clen = 0;
	rq.rparam = &resp;
	rq.rlen = READ_BD_ADDR_RP_SIZE;

	if (hci_send_req(&rq) < 0)
		return -1;

	if (resp.status) {
		return -1;
	}
	Osal_MemCpy(bdaddr, resp.bdaddr, sizeof(tBDAddr));

	return 0;
}

int hci_le_create_connection(uint16_t interval,	uint16_t window, uint8_t initiator_filter, uint8_t peer_bdaddr_type,
                             const tBDAddr peer_bdaddr,	uint8_t	own_bdaddr_type, uint16_t min_interval,	uint16_t max_interval,
                             uint16_t latency,	uint16_t supervision_timeout, uint16_t min_ce_length, uint16_t max_ce_length)
{
	struct hci_request rq;
	le_create_connection_cp create_cp;
	uint8_t status;

	Osal_MemSet(&create_cp, 0, sizeof(create_cp));
	create_cp.interval = interval;
	create_cp.window =  window;
	create_cp.initiator_filter = initiator_filter;
	create_cp.peer_bdaddr_type = peer_bdaddr_type;
	Osal_MemCpy(create_cp.peer_bdaddr, peer_bdaddr, sizeof(tBDAddr));
	create_cp.own_bdaddr_type = own_bdaddr_type;
	create_cp.min_interval=min_interval;
	create_cp.max_interval=max_interval;
	create_cp.latency = latency;
	create_cp.supervision_timeout=supervision_timeout;
	create_cp.min_ce_length=min_ce_length;
	create_cp.max_ce_length=max_ce_length;

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_CREATE_CONN;
	rq.cparam = &create_cp;
	rq.clen = LE_CREATE_CONN_CP_SIZE;
    rq.event = EVT_CMD_STATUS;
	rq.rparam = &status;
	rq.rlen = 1;

	if (hci_send_req(&rq) < 0)
		return -1;

	if (status) {
		return -1;
	}

	return 0;
}

int hci_le_encrypt(uint8_t key[16], uint8_t plaintextData[16], uint8_t encryptedData[16])
{
	struct hci_request rq;
	le_encrypt_cp params;
	le_encrypt_rp resp;
	
	Osal_MemSet(&resp, 0, sizeof(resp));

	Osal_MemCpy(params.key, key, 16);
	Osal_MemCpy(params.plaintext, plaintextData, 16);

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_ENCRYPT;
	rq.cparam = &params;
	rq.clen = LE_ENCRYPT_CP_SIZE;
	rq.rparam = &resp;
	rq.rlen = LE_ENCRYPT_RP_SIZE;

	if (hci_send_req(&rq) < 0){
		return -1;
	}

	if (resp.status) {
		return -1;
	}
	
	Osal_MemCpy(encryptedData, resp.encdata, 16);

	return 0;
}

int hci_le_ltk_request_reply(uint8_t key[16])
{
	struct hci_request rq;
	le_ltk_reply_cp params;
	le_ltk_reply_rp resp;
	
	Osal_MemSet(&resp, 0, sizeof(resp));

	params.handle = 1;
	Osal_MemCpy(params.key, key, 16);

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_LTK_REPLY;
	rq.cparam = &params;
	rq.clen = LE_LTK_REPLY_CP_SIZE;
	rq.rparam = &resp;
	rq.rlen = LE_LTK_REPLY_RP_SIZE;

	if (hci_send_req(&rq) < 0)
		return -1;

	if (resp.status) {
		return -1;
	}

	return 0;
}

int hci_le_ltk_request_neg_reply()
{
	struct hci_request rq;
	le_ltk_neg_reply_cp params;
	le_ltk_neg_reply_rp resp;
	
	Osal_MemSet(&resp, 0, sizeof(resp));

	params.handle = 1;

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_LTK_NEG_REPLY;
	rq.cparam = &params;
	rq.clen = LE_LTK_NEG_REPLY_CP_SIZE;
	rq.rparam = &resp;
	rq.rlen = LE_LTK_NEG_REPLY_RP_SIZE;

	if (hci_send_req(&rq) < 0)
		return -1;

	if (resp.status) {
		return -1;
	}

	return 0;
}

int hci_le_read_white_list_size(uint8_t *size)
{
	struct hci_request rq;
    le_read_white_list_size_rp resp;
	
	Osal_MemSet(&resp, 0, sizeof(resp));

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_READ_WHITE_LIST_SIZE;
	rq.rparam = &resp;
	rq.rlen = LE_READ_WHITE_LIST_SIZE_RP_SIZE;

	if (hci_send_req(&rq) < 0){
		return -1;
	}

	if (resp.status) {
		return -1;
	}
    
    *size = resp.size;

	return 0;
}

int hci_le_clear_white_list()
{
	struct hci_request rq;
	uint8_t status;

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_CLEAR_WHITE_LIST;
	rq.rparam = &status;
	rq.rlen = 1;

	if (hci_send_req(&rq) < 0){
		return -1;
	}

	if (status) {
		return -1;
	}

	return 0;
}

int hci_le_add_device_to_white_list(uint8_t	bdaddr_type, tBDAddr bdaddr)
{
	struct hci_request rq;
	le_add_device_to_white_list_cp params;
	uint8_t status;

	params.bdaddr_type = bdaddr_type;
	Osal_MemCpy(params.bdaddr, bdaddr, 6);

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_ADD_DEVICE_TO_WHITE_LIST;
	rq.cparam = &params;
	rq.clen = LE_ADD_DEVICE_TO_WHITE_LIST_CP_SIZE;
	rq.rparam = &status;
	rq.rlen = 1;

	if (hci_send_req(&rq) < 0){
		return -1;
	}

	if (status) {
		return -1;
	}

	return 0;
}

int hci_le_remove_device_from_white_list(uint8_t bdaddr_type, tBDAddr bdaddr)
{
	struct hci_request rq;
	le_remove_device_from_white_list_cp params;
	uint8_t status;

	params.bdaddr_type = bdaddr_type;
	Osal_MemCpy(params.bdaddr, bdaddr, 6);

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST;
	rq.cparam = &params;
	rq.clen = LE_REMOVE_DEVICE_FROM_WHITE_LIST_CP_SIZE;
	rq.rparam = &status;
	rq.rlen = 1;

	if (hci_send_req(&rq) < 0){
		return -1;
	}

	if (status) {
		return -1;
	}

	return 0;
}

int hci_read_transmit_power_level(uint16_t *conn_handle, uint8_t type, int8_t * tx_level)
{
    struct hci_request rq;
	read_transmit_power_level_cp params;
	read_transmit_power_level_rp resp;
	
	Osal_MemSet(&resp, 0, sizeof(resp));

	params.handle = *conn_handle;
	params.type = type;

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_HOST_CTL;
	rq.ocf = OCF_READ_TRANSMIT_POWER_LEVEL;
	rq.cparam = &params;
	rq.clen = READ_TRANSMIT_POWER_LEVEL_CP_SIZE;
	rq.rparam = &resp;
	rq.rlen = READ_TRANSMIT_POWER_LEVEL_RP_SIZE;

	if (hci_send_req(&rq) < 0){
		return -1;
	}

	if (resp.status) {
		return -1;
	}
	
    *conn_handle = resp.handle;
    *tx_level = resp.handle;

	return 0;
}

int hci_read_rssi(uint16_t *conn_handle, int8_t * rssi)
{
    struct hci_request rq;
	read_rssi_cp params;
	read_rssi_rp resp;
	
	Osal_MemSet(&resp, 0, sizeof(resp));

	params.handle = *conn_handle;

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_STATUS_PARAM;
	rq.ocf = OCF_READ_RSSI;
	rq.cparam = &params;
	rq.clen = READ_RSSI_CP_SIZE;
	rq.rparam = &resp;
	rq.rlen = READ_RSSI_RP_SIZE;

	if (hci_send_req(&rq) < 0){
		return -1;
	}

	if (resp.status) {
		return -1;
	}
	
    *conn_handle = resp.handle;
    *rssi = resp.rssi;

	return 0;
}

int hci_le_read_local_supported_features(uint8_t *features)
{
	struct hci_request rq;
    le_read_local_supported_features_rp resp;
	
	Osal_MemSet(&resp, 0, sizeof(resp));

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_READ_LOCAL_SUPPORTED_FEATURES;
	rq.rparam = &resp;
	rq.rlen = LE_READ_LOCAL_SUPPORTED_FEATURES_RP_SIZE;

	if (hci_send_req(&rq) < 0){
		return -1;
	}

	if (resp.status) {
		return -1;
	}
    
    Osal_MemCpy(features, resp.features, sizeof(resp.features));

	return 0;
}

int hci_le_read_channel_map(uint16_t conn_handle, uint8_t ch_map[5])
{
    struct hci_request rq;
	le_read_channel_map_cp params;
	le_read_channel_map_rp resp;
	
	Osal_MemSet(&resp, 0, sizeof(resp));

	params.handle = conn_handle;

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_READ_CHANNEL_MAP;
	rq.cparam = &params;
	rq.clen = LE_READ_CHANNEL_MAP_CP_SIZE;
	rq.rparam = &resp;
	rq.rlen = LE_READ_CHANNEL_MAP_RP_SIZE;

	if (hci_send_req(&rq) < 0){
		return -1;
	}

	if (resp.status) {
		return -1;
	}
    
    Osal_MemCpy(ch_map, resp.map, 5);

	return 0;
}

int hci_le_read_supported_states(uint8_t states[8])
{
	struct hci_request rq;
    le_read_supported_states_rp resp;
	
	Osal_MemSet(&resp, 0, sizeof(resp));

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_READ_SUPPORTED_STATES;
	rq.rparam = &resp;
	rq.rlen = LE_READ_SUPPORTED_STATES_RP_SIZE;

	if (hci_send_req(&rq) < 0){
		return -1;
	}

	if (resp.status) {
		return -1;
	}
    
    Osal_MemCpy(states, resp.states, 8);

	return 0;
}

int hci_le_receiver_test(uint8_t frequency)
{
	struct hci_request rq;
	le_receiver_test_cp params;
	uint8_t status;

	params.frequency = frequency;

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_RECEIVER_TEST;
	rq.cparam = &params;
	rq.clen = LE_RECEIVER_TEST_CP_SIZE;
	rq.rparam = &status;
	rq.rlen = 1;

	if (hci_send_req(&rq) < 0){
		return -1;
	}

	if (status) {
		return -1;
	}

	return 0;
}

int hci_le_transmitter_test(uint8_t frequency, uint8_t length, uint8_t payload)
{
	struct hci_request rq;
	le_transmitter_test_cp params;
	uint8_t status;

	params.frequency = frequency;
    params.length = length;
    params.payload = payload;

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_TRANSMITTER_TEST;
	rq.cparam = &params;
	rq.clen = LE_TRANSMITTER_TEST_CP_SIZE;
	rq.rparam = &status;
	rq.rlen = 1;

	if (hci_send_req(&rq) < 0){
		return -1;
	}

	if (status) {
		return -1;
	}

	return 0;
}

int hci_le_test_end(uint16_t *num_pkts)
{
	struct hci_request rq;
    le_test_end_rp resp;
	
	Osal_MemSet(&resp, 0, sizeof(resp));

	Osal_MemSet(&rq, 0, sizeof(rq));
	rq.ogf = OGF_LE_CTL;
	rq.ocf = OCF_LE_TEST_END;
	rq.rparam = &resp;
	rq.rlen = LE_TEST_END_RP_SIZE;

	if (hci_send_req(&rq) < 0){
		return -1;
	}

	if (resp.status) {
		return -1;
	}
    
    *num_pkts = resp.num_pkts;

	return 0;
}