Exemple #1
0
boolean WebServer::begin (NetworkInterface& _netint, const Page* const _pages[]
#ifdef ENABLE_TAGS
		, const ReplacementTag* const _substitutions[]
#endif
#if defined (WEBBINO_ENABLE_SD) || defined (WEBBINO_ENABLE_SDFAT)
		, int8_t pin
#endif
		) {

	boolean ret = true;

	netint = &_netint;

	pages = _pages;

#ifndef WEBBINO_NDEBUG
	DPRINTLN (F("Pages available in flash memory:"));
	const Page *p = NULL;
	for (byte i = 0; pages && (p = reinterpret_cast<const Page *> (pgm_read_ptr (&pages[i]))); i++) {
		DPRINT (i);
		DPRINT (F(". "));
		DPRINTLN (PSTR_TO_F (p -> getName ()));
	}
#endif

#ifdef ENABLE_TAGS
	substitutions = _substitutions;

#ifndef WEBBINO_NDEBUG
	DPRINTLN (F("Tags available:"));
	const ReplacementTag* sub;
	for (byte i = 0; substitutions && (sub = reinterpret_cast<const ReplacementTag *> (pgm_read_ptr (&substitutions[i]))); i++) {
		DPRINT (i);
		DPRINT (F(". "));
		DPRINTLN (PSTR_TO_F (sub -> getName ()));
	}
#endif

#endif

#if defined (WEBBINO_ENABLE_SD) || defined (WEBBINO_ENABLE_SDFAT)
	if (pin >= 0) {
		DPRINT (F("Initializing SD card..."));
		if (!SD.begin (pin)) {
			DPRINTLN (F(" failed"));
			ret = false;
		}
		DPRINTLN (F(" done"));
	}
#endif

	return ret;
}
Exemple #2
0
EventHandlerResult MagicCombo::beforeReportingState() {
  for (byte i = 0; i < magiccombo::combos_length; i++) {
    bool match = true;
    byte j;

    for (j = 0; j < MAX_COMBO_LENGTH; j++) {
      int8_t comboKey = pgm_read_byte(&(magiccombo::combos[i].keys[j]));

      if (comboKey == 0)
        break;

      match &= KeyboardHardware.isKeyswitchPressed(comboKey);
      if (!match)
        break;
    }

    if (j != KeyboardHardware.pressedKeyswitchCount())
      match = false;

    if (match && (millis() >= end_time_)) {
      ComboAction action = (ComboAction) pgm_read_ptr(&(magiccombo::combos[i].action));

      (*action)(i);
      end_time_ = millis() + min_interval;
    }
  }

  return EventHandlerResult::OK;
}
Exemple #3
0
static inline void sleepNow() {
  // All LEDs off
  for(int i = 0; i < LED_COUNT; i++) {
    *((unsigned char *)pgm_read_ptr(&(LED_PORT[i]))) &= ~_BV(pgm_read_byte(&(LED_PIN[i])));
  }
  // We want to do this carefully. If someone pushes the button
  // while we're prepareing here, we do NOT want to 'eat' that
  // interrupt. Rather, we want to enable interrupts at the same
  // time we call sleep_cpu() (sei() is defferred for one instruction).
  // That way the button push will effectively cancel the sleep rather
  // than get 'eaten'.
  ATOMIC_BLOCK(ATOMIC_FORCEON) {
    power_timer0_disable();
    PCMSK0 |= _BV(PCINT5);
    GIMSK |= _BV(PCIE0);
    sleep_enable();
  }
  sleep_cpu();

  // And now we wake up

  sleep_disable();
  PCMSK0 &= ~_BV(PCINT5);
  GIMSK &= ~_BV(PCIE0);
  power_timer0_enable();
  button_debounce_time = millis();
  ignoring_button = 1;
  place_in_pattern = -1;
  milli_of_next_change = 0;
}
Exemple #4
0
const Page* WebServer::getPage (const char* name) const {
	const Page *p = NULL;

	// For some reason, if we make i a byte here, the code uses 8 more bytes, so don't!
	for (unsigned int i = 0; pages && (p = reinterpret_cast<const Page *> (pgm_read_ptr (&pages[i]))); i++) {
		if (strcmp_P (name, p -> getName ()) == 0)
			break;
	}

	return p;
}
Exemple #5
0
/** Retrieves a pointer to the value of the given Attribute ID from the given Attribute table.
 *
 *  \param[in] ServiceEntry    Pointer to the service entry whose attribute table is to be examined
 *  \param[in] AttributeID     Attribute ID to search for within the table
 *
 *  \return Pointer to the start of the Attribute's value if found within the table, NULL otherwise
 */
static void* SDP_GetAttributeValue(const SDP_ServiceEntry_t* const ServiceEntry,
                                   const uint16_t AttributeID)
{
	/* Search through the current Attribute table, abort when the terminator item has been reached */
	for (uint8_t i = 0; i < ServiceEntry->TotalTableAttributes; i++)
	{
		/* Check if the current Attribute ID matches the search ID - if so return a pointer to it */
		if (pgm_read_word(&ServiceEntry->AttributeTable[i].AttributeID) == AttributeID)
		  return pgm_read_ptr(&ServiceEntry->AttributeTable[i].Data);
	}

	return NULL;
}
Exemple #6
0
PString* WebServer::findSubstitutionTag (const char *tag) const {
	const ReplacementTag *sub;
	PString* ret = NULL;

	for (byte i = 0; !ret && (sub = reinterpret_cast<const ReplacementTag *> (pgm_read_ptr (&substitutions[i]))); i++) {
		if (strcmp_P (tag, sub -> getName ()) == 0) {
			PString& pb = (sub -> getFunction ()) (sub -> getData ());
			ret = &pb;
		}
	}

	return ret;
}
Exemple #7
0
inline void exec_slice(void)
{
	int8_t i;
	void (*slot_ptr)(void);
	
	for(i=0; i<NUMBER_OF_ITEMS_PER_SLOT; i++)
	{
		slot_ptr = pgm_read_ptr(&g_sched_list[g_next_slice][i]);
		if (slot_ptr != NULL)
		{
			g_next_item = i;
			(*slot_ptr)();
			clock_in();
		}
	}
}
Exemple #8
0
/** Retrieves a pointer to the value of the given Attribute ID from the given Attribute table.
 *
 *  \param[in] AttributeTable  Pointer to the Attribute table to search in
 *  \param[in] AttributeID     Attribute ID to search for within the table
 *
 *  \return Pointer to the start of the Attribute's value if found within the table, NULL otherwise
 */
static void* SDP_GetAttributeValue(const ServiceAttributeTable_t* AttributeTable,
                                   const uint16_t AttributeID)
{
	void* CurrTableItemData;
	
	/* Search through the current Attribute table, abort when the terminator item has been reached */
	while ((CurrTableItemData = pgm_read_ptr(&AttributeTable->Data)) != NULL)
	{
		/* Check if the current Attribute ID matches the search ID - if so return a pointer to it */
		if (pgm_read_word(&AttributeTable->AttributeID) == AttributeID)
		  return CurrTableItemData;
		
		AttributeTable++;
	}
			
	return NULL;
}
Exemple #9
0
/** Adds all the Attributes in the given service table to the response that appear in the Attribute table.
 *
 *  \param[in]  AttributeTable   Pointer to an Attribute table for the service to examine
 *  \param[in]  AttributeList    Pointer to a list of Attribute ranges
 *  \param[in]  TotalAttributes  Number of Attributes stored in the Attribute list
 *  \param[out] BufferPos       Pointer to the output buffer position where the retrieved attributes are to be stored
 *
 *  \return Number of bytes added to the output buffer
 */
static uint16_t SDP_AddListedAttributesToResponse(const ServiceAttributeTable_t* AttributeTable,
                                                  uint16_t AttributeList[][2],
                                                  const uint8_t TotalAttributes,
                                                  void** const BufferPos)
{
	uint16_t TotalResponseSize;

	/* Add an inner Data Element Sequence header for the current services's found Attributes */
	uint16_t* AttributeListSize = SDP_AddSequence16(BufferPos);

	/* Search through the list of Attributes one at a time looking for values in the current UUID's Attribute table */
	for (uint8_t CurrAttribute = 0; CurrAttribute < TotalAttributes; CurrAttribute++)
	{
		uint16_t* AttributeIDRange = AttributeList[CurrAttribute];
		void*     AttributeValue;
		
		/* Look through the current service's attribute list, examining all the attributes */
		while ((AttributeValue = pgm_read_ptr(&AttributeTable->Data)) != NULL)
		{
			/* Get the current Attribute's ID from the current attribute table entry */
			uint16_t CurrAttributeID = pgm_read_word(&AttributeTable->AttributeID);

			/* Check if the current Attribute's ID is within the current Attribute range */
			if ((CurrAttributeID >= AttributeIDRange[0]) && (CurrAttributeID <= AttributeIDRange[1]))
			{
				/* Increment the current UUID's returned Attribute container size by the number of added bytes */
				*AttributeListSize += SDP_AddAttributeToResponse(CurrAttributeID, AttributeValue, BufferPos);			
			}
			
			AttributeTable++;
		}
	}

	/* Record the total number of added bytes to the buffer */
	TotalResponseSize = 3 + *AttributeListSize;

	/* Fix endianness of the added attribute data element sequence */
	*AttributeListSize = SwapEndian_16(*AttributeListSize);

	return TotalResponseSize;
}
Exemple #10
0
/** Retrieves the Attribute table for the given UUID list if it exists.
 *
 *  \param[in] ServiceEntry  Pointer to the service entry whose attribute table is to be examined
 *  \param[in] UUIDList      List of UUIDs which must be matched within the service attribute table
 *  \param[in] TotalUUIDs    Total number of UUIDs stored in the UUID list
 *
 *  \return True if all the UUIDs given in the UUID list appear in the given attribute table, false otherwise
 */
static bool SDP_SearchServiceTable(const SDP_ServiceEntry_t* const ServiceEntry,
								   uint8_t UUIDList[][UUID_SIZE_BYTES],
                                   const uint8_t TotalUUIDs)
{
	uint16_t UUIDMatchFlags = 0;

	/* Search through the current attribute table, checking each attribute value for UUID matches */\
	for (uint8_t i = 0; i < ServiceEntry->TotalTableAttributes; i++)
	{
		const void* CurrAttribute = pgm_read_ptr(&ServiceEntry->AttributeTable[i].Data);
		SDP_CheckUUIDMatch(UUIDList, TotalUUIDs, &UUIDMatchFlags, CurrAttribute);
	}

	/* Determine how many UUID matches in the list we have found */
	uint8_t UUIDMatches;
	for (UUIDMatches = 0; UUIDMatchFlags; UUIDMatches++)
	  UUIDMatchFlags &= (UUIDMatchFlags - 1);

	/* If all UUIDs have been matched to the current service, return true */
	return (UUIDMatches == TotalUUIDs);
}
Exemple #11
0
/** Retrieves the Attribute table for the given UUID list if it exists.
 *
 *  \param[in] UUIDList            List of UUIDs which must be matched within the service attribute table
 *  \param[in] TotalUUIDs          Total number of UUIDs stored in the UUID list
 *  \param[in] CurrAttributeTable  Pointer to the service attribute table to search through
 *
 *  \return True if all the UUIDs given in the UUID list appear in the given attribute table, false otherwise
 */
static bool SDP_SearchServiceTable(uint8_t UUIDList[][UUID_SIZE_BYTES],
                                   const uint8_t TotalUUIDs,
			                       const ServiceAttributeTable_t* CurrAttributeTable)
{
	const void* CurrAttribute;
	uint16_t    UUIDMatchFlags = 0;
	
	/* Search through the current attribute table, checking each attribute value for UUID matches */
	while ((CurrAttribute = pgm_read_ptr(&CurrAttributeTable->Data)) != NULL)
	{
		SDP_CheckUUIDMatch(UUIDList, TotalUUIDs, &UUIDMatchFlags, CurrAttribute);
		CurrAttributeTable++;
	}

	/* Determine how many UUID matches in the list we have found */
	uint8_t UUIDMatches;
	for (UUIDMatches = 0; UUIDMatchFlags; UUIDMatches++)
	  UUIDMatchFlags &= (UUIDMatchFlags - 1);
	
	/* If all UUIDs have been matched to the current service, return true */
	return (UUIDMatches == TotalUUIDs);
}
Exemple #12
0
void loop() {
  while(1) {
    // Do this about once a minute-ish.
    if (q_random() % 30 != 0) {
      // a normal second.
      doTick();
      for(int i = 0; i < IRQS_PER_SECOND - 1; i++)
        doSleep();
      continue;
    }

    // Time to play a song!
    unsigned int song = q_random() % SONG_COUNT;
    unsigned char *current_song = (unsigned char*)pgm_read_ptr(song_table + song);
    while(1) {
      unsigned char song_data = pgm_read_byte(current_song++);
      if (song_data == 0) break; // song over
      doTick();
      for(int i = 0; i < song_data; i++)
        doSleep();
    }
  }
}
Exemple #13
0
void main() {
  // power management setup
  clock_prescale_set(clock_div_16); // 500 kHz clock
  ADCSRA = 0; // DIE, ADC! DIE!!!
  power_adc_disable();
  power_usi_disable();
  power_timer1_disable();
  ACSR = _BV(ACD);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  // millisecond timer setup
  TCCR0A = _BV(WGM01); // mode 2 - CTC
  TCCR0B = _BV(CS01) | _BV(CS00); // prescale = 64
  TIMSK0 = _BV(OCIE0A); // OCR0A interrupt only.
  OCR0A = IRQ_CYCLE_LENGTH + 1;
  millis_counter = 0;
  irq_cycle_pos = 0;
  sei();
  
  // I/O port setup 
  DDRA = _BV(PA0) | _BV(PA1) | _BV(PA2) | _BV(PA3) | _BV(PA7);
  DDRB = _BV(PB0) | _BV(PB1) | _BV(PB2);
  PORTA = _BV(PA5); // enable the pull-up on the button pin
  PORTB = 0;
  
  unsigned char pattern = eeprom_read_byte(EE_PATTERN_NUM);
  if (pattern >= PATTERN_COUNT) pattern = 0;
  place_in_pattern = -1;
  milli_of_next_change = 0;
  button_debounce_time = 0;
  button_press_time = 0;
  ignoring_button = 0;

  while(1) {
    unsigned long now = millis();

    // poll for button events
    unsigned int event = checkEvent();
    switch(event) {
      case EVENT_LONG_PUSH:
        sleepNow();
        continue;
      case EVENT_SHORT_PUSH:
        if (++pattern >= PATTERN_COUNT) pattern = 0;
        place_in_pattern = -1;
        milli_of_next_change = 0;
        eeprom_write_byte(EE_PATTERN_NUM, pattern);
        continue;
    }

    // If it's time to move to the next step in a pattern, pull out its
    // mask and clear all of the LEDs.

    // Note that now > milli_of_next_change is wrong here because our
    // time wraps. now - milli_of_next_change > 0 *looks* the same,
    // but handles cases where the sign differs.
    if (milli_of_next_change == 0 || ((long)(now - milli_of_next_change)) >= 0) {
      // It's time to go to the next step in the pattern
      place_in_pattern++;
      const struct pattern_entry *our_pattern = (struct pattern_entry *)pgm_read_ptr(&(patterns[pattern]));
      struct pattern_entry entry;
      do {
        memcpy_P(&entry, (void*)(&(our_pattern[place_in_pattern])), sizeof(struct pattern_entry));
        // A duration of 0 is the end of the pattern.
        if (entry.duration != 0) break;
        place_in_pattern = 0;   
      } while(1); // This means a pattern of a single entry with 0 duration is kryptonite.
      current_mask = entry.mask;
      // Turn out all the lights
      for(int i = 0; i < LED_COUNT; i++) {
        *((unsigned char *)pgm_read_ptr(&(LED_PORT[i]))) &= ~_BV(pgm_read_byte(&(LED_PIN[i])));
      }
      milli_of_next_change = now + entry.duration;
      current_led = 99; //invalid
    }

    // Now multiplex the LEDSs. Rotate through all of the set bits in the
    // current mask and turn the next one on every pass through this loop.
    if (current_mask != 0) { // if it IS zero, then all the lights are out anyway.
      unsigned char next_led = current_led;
      while(1) { // we know it's not zero, so there's at least one bit set
        if (++next_led >= LED_COUNT) next_led = 0;
        if (current_mask & (1 << next_led)) break; // found one!
      }
      if (next_led != current_led) {
        // turn the old one off and the new one on.
        if (current_led < LED_COUNT) // is it safe?
          *((unsigned char *)pgm_read_ptr(&(LED_PORT[current_led]))) &= ~_BV(pgm_read_byte(&(LED_PIN[current_led])));
        *((unsigned char *)pgm_read_ptr(&(LED_PORT[next_led]))) |= _BV(pgm_read_byte(&(LED_PIN[next_led])));
        current_led = next_led;
      }
    }
  }
}
Exemple #14
0
 LOOP_L_N(f, COUNT(custom_bootscreen_animation)) {
   if (f) safe_delay(CUSTOM_BOOTSCREEN_FRAME_TIME);
   draw_custom_bootscreen((u8g_pgm_uint8_t*)pgm_read_ptr(&custom_bootscreen_animation[f]), f == 0);
 }
//
// This loads a default setting from the table for the given index
//
int
MenloDweet::LoadDefaultSettingFromTable(
    struct StateSettingsParameters* parms,
    int index
    )
{
#if DWEET_STATE_ENABLE_DEFAULT_TABLE_SUPPORT
    int configDataIndex;
    int configDataLength;
    int defaultDataIndex;
    int defaultTableIndex;
    char* defaultDataPtr;
    int retVal;

    if (parms->defaultsTable == NULL) {
        return 0;
    }

    // Get the configuration data index and length for the entry
    configDataIndex = pgm_read_word(&parms->indexTable[index]);
    configDataLength = pgm_read_word(&parms->sizeTable[index]);

    //
    // Lookup the data index in the defaults table and see if an entry
    // has been provided.
    //
    // The defaults table is not in order to allow it to be sparse since
    // not all values need an automatic default setting.
    //
    for (defaultTableIndex = 0;; defaultTableIndex++) {

        defaultDataIndex =
            pgm_read_word((const int*)(&parms->defaultsTable[defaultTableIndex].configIndex));

        if (defaultDataIndex == 0) {
            // No entry found in defaultsTable
            return 0;
        }

        if (defaultDataIndex == index) {
            break;
        }
    }

    defaultDataPtr =
        (char*)pgm_read_ptr((const int*)(&parms->defaultsTable[defaultTableIndex].address));

    // Get the config data from the default data pointer
    memcpy(&parms->workingBuffer[0], defaultDataPtr, configDataLength);

    ConfigStore.ProcessConfigBufferForValidChars(&parms->workingBuffer[0], configDataLength);

    parms->workingBuffer[configDataLength] = '\0';

    // Now try and set it on the object using the SETSTATE function
    retVal = MenloDweet::DispatchFunctionFromTable(
        parms->functionTable,
        parms->object,
        index,
        parms->workingBuffer,
        configDataLength,
        true
        );

    return retVal;
#else
    return 0;
#endif
}
Exemple #16
0
/** Internal processing routine for SDP Service Attribute Requests.
 *
 *  \param[in] SDPHeader  Pointer to the start of the issued SDP request
 *  \param[in] Channel    Pointer to the Bluetooth channel structure the request was issued to
 */
static void SDP_ProcessServiceAttribute(const SDP_PDUHeader_t* const SDPHeader,
                                        Bluetooth_Channel_t* const Channel)
{
	const void* CurrentParameter = ((const void*)SDPHeader + sizeof(SDP_PDUHeader_t));

	BT_SDP_DEBUG(1, "<< Service Attribute");

	/* Retrieve the service handle whose attributes are to be examined */
	uint32_t ServiceHandle = SDP_ReadData32(&CurrentParameter);
	BT_SDP_DEBUG(2, "-- Service Handle: 0x%08lX", ServiceHandle);
	
	/* Retrieve the maximum Attribute response size from the request */
	uint16_t MaxAttributeSize = SDP_ReadData16(&CurrentParameter);
	BT_SDP_DEBUG(2, "-- Max Return Attribute Bytes: 0x%04X", MaxAttributeSize);
	
	/* Retrieve the list of Attributes from the request */
	uint16_t AttributeList[8][2];
	uint8_t  TotalAttributes = SDP_GetAttributeList(AttributeList, &CurrentParameter);
	BT_SDP_DEBUG(2, "-- Total Attributes: %d", TotalAttributes);

	struct
	{
		SDP_PDUHeader_t SDPHeader;
		uint16_t        AttributeListByteCount;
		uint8_t         ResponseData[100];
	} ResponsePacket;

	/* Create a pointer to the buffer to indicate the current location for response data to be added */
	void* CurrResponsePos = ResponsePacket.ResponseData;

	/* Clamp the maximum attribute size to the size of the allocated buffer */
	if (MaxAttributeSize > sizeof(ResponsePacket.ResponseData))
	  MaxAttributeSize = sizeof(ResponsePacket.ResponseData);

	uint16_t TotalResponseSize = 0;

	/* Search through the global UUID list an item at a time */
	for (uint8_t CurrTableItem = 0; CurrTableItem < (sizeof(SDP_Services_Table) / sizeof(void*)); CurrTableItem++)
	{
		/* Read in a pointer to the current UUID table entry's Attribute table */
		ServiceAttributeTable_t* CurrAttributeTable = pgm_read_ptr(&SDP_Services_Table[CurrTableItem]);
		
		/* Retrieve a PROGMEM pointer to the value of the Service Record Handle */
		const void* ServiceRecord = SDP_GetAttributeValue(CurrAttributeTable, SDP_ATTRIBUTE_ID_SERVICERECORDHANDLE);
		
		/* Get the size of the header for the Service Record Handle */
		uint8_t AttrHeaderSize;
		SDP_GetLocalAttributeContainerSize(ServiceRecord, &AttrHeaderSize);
		
		/* Retrieve the endian-swapped service handle of the current service being examined */
		uint32_t CurrServiceHandle = SwapEndian_32(pgm_read_dword(ServiceRecord + AttrHeaderSize));
		
		/* Check if the current service in the service table has the requested service handle */
		if (ServiceHandle == CurrServiceHandle)
		{
			/* Add the listed attributes for the found UUID to the response */
			TotalResponseSize = SDP_AddListedAttributesToResponse(CurrAttributeTable, AttributeList, TotalAttributes,
		                                                          &CurrResponsePos);
			
			/* Requested service found, abort the search through the service table */
			break;
		}
	}

	/* Continuation state - always zero */
	SDP_WriteData8(&CurrResponsePos, 0);

	/* Set the total response list size to the size of the outer container plus its header size and continuation state */
	ResponsePacket.AttributeListByteCount    = SwapEndian_16(TotalResponseSize);

	/* Calculate the total parameter length that is to be sent, including the fixed return parameters, the created attribute
	   value list and the SDP continuation state */
	uint16_t ParamLength = (sizeof(ResponsePacket.AttributeListByteCount) + TotalResponseSize + sizeof(uint8_t));
	
	/* Fill in the response packet's header */
	ResponsePacket.SDPHeader.PDU             = SDP_PDU_SERVICEATTRIBUTERESPONSE;
	ResponsePacket.SDPHeader.TransactionID   = SDPHeader->TransactionID;
	ResponsePacket.SDPHeader.ParameterLength = SwapEndian_16(ParamLength);

	BT_SDP_DEBUG(1, ">> Service Attribute Response");
	BT_SDP_DEBUG(2, "-- Param Len 0x%04X", ParamLength);

	/* Send the completed response packet to the sender */
	Bluetooth_SendPacket(&ResponsePacket, (sizeof(ResponsePacket.SDPHeader) + ParamLength), Channel);
}
Exemple #17
0
/** Internal processing routine for SDP Service Search Attribute Requests.
 *
 *  \param[in] SDPHeader  Pointer to the start of the issued SDP request
 *  \param[in] Channel    Pointer to the Bluetooth channel structure the request was issued to
 */
static void SDP_ProcessServiceSearchAttribute(const SDP_PDUHeader_t* const SDPHeader,
                                              Bluetooth_Channel_t* const Channel)
{
	const void* CurrentParameter = ((const void*)SDPHeader + sizeof(SDP_PDUHeader_t));
	
	BT_SDP_DEBUG(1, "<< Service Search Attribute");

	/* Retrieve the list of search UUIDs from the request */
	uint8_t UUIDList[12][UUID_SIZE_BYTES];
	uint8_t TotalUUIDs = SDP_GetUUIDList(UUIDList, &CurrentParameter);
	BT_SDP_DEBUG(2, "-- Total UUIDs: %d", TotalUUIDs);
	
	/* Retrieve the maximum Attribute response size from the request */
	uint16_t MaxAttributeSize = SDP_ReadData16(&CurrentParameter);
	BT_SDP_DEBUG(2, "-- Max Return Attribute Bytes: 0x%04X", MaxAttributeSize);
	
	/* Retrieve the list of Attributes from the request */
	uint16_t AttributeList[8][2];
	uint8_t  TotalAttributes = SDP_GetAttributeList(AttributeList, &CurrentParameter);
	BT_SDP_DEBUG(2, "-- Total Attributes: %d", TotalAttributes);
	
	struct
	{
		SDP_PDUHeader_t SDPHeader;
		uint16_t        AttributeListByteCount;
		uint8_t         ResponseData[100];
	} ResponsePacket;
	
	/* Create a pointer to the buffer to indicate the current location for response data to be added */
	void* CurrResponsePos = ResponsePacket.ResponseData;

	/* Clamp the maximum attribute size to the size of the allocated buffer */
	if (MaxAttributeSize > sizeof(ResponsePacket.ResponseData))
	  MaxAttributeSize = sizeof(ResponsePacket.ResponseData);

	/* Add the outer Data Element Sequence header for all of the retrieved Attributes */
	uint16_t* TotalResponseSize = SDP_AddSequence16(&CurrResponsePos);
	
	/* Search through the global service list an item at a time */
	for (uint8_t CurrTableItem = 0; CurrTableItem < (sizeof(SDP_Services_Table) / sizeof(void*)); CurrTableItem++)
	{
		/* Read in a pointer to the current UUID table entry's Attribute table */
		ServiceAttributeTable_t* CurrAttributeTable = pgm_read_ptr(&SDP_Services_Table[CurrTableItem]);

		if (!(SDP_SearchServiceTable(UUIDList, TotalUUIDs, CurrAttributeTable)))
		  continue;
		  
		BT_SDP_DEBUG(2, " -- Found search match in table");

		/* Add the listed attributes for the found UUID to the response */
		*TotalResponseSize += SDP_AddListedAttributesToResponse(CurrAttributeTable, AttributeList, TotalAttributes, 
		                                                        &CurrResponsePos);
	}
	
	/* Continuation state - always zero */
	SDP_WriteData8(&CurrResponsePos, 0);

	/* Set the total response list size to the size of the outer container plus its header size and continuation state */
	ResponsePacket.AttributeListByteCount    = SwapEndian_16(3 + *TotalResponseSize);

	/* Calculate the total parameter length that is to be sent, including the fixed return parameters, the created attribute
	   value list and the SDP continuation state */
	uint16_t ParamLength = (sizeof(ResponsePacket.AttributeListByteCount) + 
	                        (3 + *TotalResponseSize) +
	                        sizeof(uint8_t));

	/* Flip the endianness of the container's size */
	*TotalResponseSize = SwapEndian_16(*TotalResponseSize);

	/* Fill in the response packet's header */
	ResponsePacket.SDPHeader.PDU             = SDP_PDU_SERVICESEARCHATTRIBUTERESPONSE;
	ResponsePacket.SDPHeader.TransactionID   = SDPHeader->TransactionID;
	ResponsePacket.SDPHeader.ParameterLength = SwapEndian_16(ParamLength);

	BT_SDP_DEBUG(1, ">> Service Search Attribute Response");
	BT_SDP_DEBUG(2, "-- Param Len 0x%04X", ParamLength);

	/* Send the completed response packet to the sender */
	Bluetooth_SendPacket(&ResponsePacket, (sizeof(ResponsePacket.SDPHeader) + ParamLength), Channel);
}
Exemple #18
0
	inline const __FlashStringHelper* FF(const char* const* s)
	{
		return reinterpret_cast<const __FlashStringHelper*>(
			pgm_read_ptr(s));
	}
Exemple #19
0
/** Internal processing routine for SDP Service Search Requests.
 *
 *  \param[in] SDPHeader  Pointer to the start of the issued SDP request
 *  \param[in] Channel    Pointer to the Bluetooth channel structure the request was issued to
 */
static void SDP_ProcessServiceSearch(const SDP_PDUHeader_t* const SDPHeader,
                                     Bluetooth_Channel_t* const Channel)
{
	const void* CurrentParameter = ((const void*)SDPHeader + sizeof(SDP_PDUHeader_t));

	BT_SDP_DEBUG(1, "<< Service Search");

	/* Retrieve the list of search UUIDs from the request */
	uint8_t UUIDList[12][UUID_SIZE_BYTES];
	uint8_t TotalUUIDs = SDP_GetUUIDList(UUIDList, &CurrentParameter);
	BT_SDP_DEBUG(2, "-- Total UUIDs: %d", TotalUUIDs);
	
	/* Retrieve the maximum service record response count from the request */
	uint16_t MaxServiceRecordCount = SDP_ReadData16(&CurrentParameter);
	BT_SDP_DEBUG(2, "-- Max Return Service Count: 0x%04X", MaxServiceRecordCount);
	
	struct
	{
		SDP_PDUHeader_t SDPHeader;
		uint16_t        TotalServiceRecordCount;
		uint16_t        CurrentServiceRecordCount;
		uint8_t         ResponseData[100];
	} ResponsePacket;
	
	uint8_t AddedServiceHandles = 0;

	/* Create a pointer to the buffer to indicate the current location for response data to be added */
	void* CurrResponsePos = ResponsePacket.ResponseData;

	/* Search through the global service list an item at a time */
	for (uint8_t CurrTableItem = 0; CurrTableItem < (sizeof(SDP_Services_Table) / sizeof(void*)); CurrTableItem++)
	{
		/* Read in a pointer to the current UUID table entry's Attribute table */
		ServiceAttributeTable_t* CurrAttributeTable = pgm_read_ptr(&SDP_Services_Table[CurrTableItem]);

		if (!(SDP_SearchServiceTable(UUIDList, TotalUUIDs, CurrAttributeTable)))
		  continue;

		BT_SDP_DEBUG(2, " -- Found search match in table");

		/* Retrieve a PROGMEM pointer to the value of the service's record handle */
		const void* AttributeValue = SDP_GetAttributeValue(CurrAttributeTable, SDP_ATTRIBUTE_ID_SERVICERECORDHANDLE);

		/* Copy over the service record handle to the response list */
		uint8_t AttrHeaderSize;
		uint8_t AttrSize = SDP_GetLocalAttributeContainerSize(AttributeValue, &AttrHeaderSize);
		memcpy_P(CurrResponsePos, AttributeValue + AttrHeaderSize, AttrSize);
		CurrResponsePos += AttrHeaderSize + AttrSize;
		
		AddedServiceHandles++;
	}

	/* Continuation state - always zero */
	SDP_WriteData8(&CurrResponsePos, 0);

	/* Fill out the service record count values in the returned packet */
	ResponsePacket.TotalServiceRecordCount   = SwapEndian_16(AddedServiceHandles);
	ResponsePacket.CurrentServiceRecordCount = ResponsePacket.TotalServiceRecordCount;

	/* Calculate the total parameter length that is to be sent, including the fixed return parameters, the created service
	   handle list and the SDP continuation state */
	uint16_t ParamLength = (ResponsePacket.CurrentServiceRecordCount << 2) +
	                        sizeof(ResponsePacket.CurrentServiceRecordCount) +
	                        sizeof(ResponsePacket.TotalServiceRecordCount) +
	                        sizeof(uint8_t);

	/* Fill in the response packet's header */
	ResponsePacket.SDPHeader.PDU             = SDP_PDU_SERVICESEARCHRESPONSE;
	ResponsePacket.SDPHeader.TransactionID   = SDPHeader->TransactionID;
	ResponsePacket.SDPHeader.ParameterLength = SwapEndian_16(ParamLength);

	BT_SDP_DEBUG(1, ">> Service Search Response");

	/* Send the completed response packet to the sender */
	Bluetooth_SendPacket(&ResponsePacket, (sizeof(ResponsePacket.SDPHeader) + ParamLength), Channel);
}