Skip to content
Snippets Groups Projects
card10.c 15.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include "wsf_types.h"
    #include "wsf_os.h"
    #include "wsf_buf.h"
    #include "wsf_timer.h"
    #include "wsf_trace.h"
    #include "app_ui.h"
    #include "fit/fit_api.h"
    #include "hci_vs.h"
    
    #include "ff.h"
    
    #include "util/bstream.h"
    #include "att_api.h"
    
    #include "FreeRTOS.h"
    #include "crc32.h"
    
    #include "epicardium.h"
    
    #include <stdio.h>
    #include <string.h>
    #include <stdbool.h>
    #include <machine/endian.h>
    
    #define CARD10_UUID_SUFFIX                                                     \
    	0x42, 0x23, 0x42, 0x23, 0x42, 0x23, 0x42, 0x23, 0x42, 0x23, 0x42, 0x23
    
    genofire's avatar
    genofire committed
    #define CARD10_UUID_PREFIX 0x02, 0x23, 0x42
    
    
    /*!< \brief Service start handle. */
    #define CARD10_START_HDL 0x920
    /*!< \brief Service end handle. */
    #define CARD10_END_HDL (CARD10_MAX_HDL - 1)
    
    /*
     * This has to match in order and number of members to the functions
    
    genofire's avatar
    genofire committed
     * called in addCard10GroupDyn() otherwise the stack breaks.
    
     */
    enum {
    	/*!< \brief card10 service declaration */
    	CARD10_SVC_HDL = CARD10_START_HDL,
    
    	/*!< \brief time update characteristic */
    	CARD10_TIME_UPDATE_CH_HDL,
    	CARD10_TIME_UPDATE_VAL_HDL,
    
    	/*!< \brief vibra characteristic */
    	CARD10_VIRBA_CH_HDL,
    	CARD10_VIBRA_VAL_HDL,
    	/*!< \brief rockets led characteristic */
    	CARD10_ROCKETS_CH_HDL,
    	CARD10_ROCKETS_VAL_HDL,
    
    genofire's avatar
    genofire committed
    	/*!< \brief led for background on bottom left characteristic */
    	CARD10_LED_BG_BOTTOM_LEFT_CH_HDL,
    	CARD10_LED_BG_BOTTOM_LEFT_VAL_HDL,
    	/*!< \brief led for background on bottom right characteristic */
    	CARD10_LED_BG_BOTTOM_RIGHT_CH_HDL,
    	CARD10_LED_BG_BOTTOM_RIGHT_VAL_HDL,
    	/*!< \brief led for background on top right characteristic */
    	CARD10_LED_BG_TOP_RIGHT_CH_HDL,
    	CARD10_LED_BG_TOP_RIGHT_VAL_HDL,
    	/*!< \brief led for background on top left characteristic */
    	CARD10_LED_BG_TOP_LEFT_CH_HDL,
    	CARD10_LED_BG_TOP_LEFT_VAL_HDL,
    
    genofire's avatar
    genofire committed
    	/*!< \brief dim leds on bottom characteristic */
    	CARD10_LEDS_BOTTOM_DIM_CH_HDL,
    	CARD10_LEDS_BOTTOM_DIM_VAL_HDL,
    	/*!< \brief dim leds on top characteristic */
    	CARD10_LEDS_TOP_DIM_CH_HDL,
    	CARD10_LEDS_TOP_DIM_VAL_HDL,
    
    genofire's avatar
    genofire committed
    	/*!< \brief leds above characteristic */
    	CARD10_LEDS_ABOVE_CH_HDL,
    	CARD10_LEDS_ABOVE_VAL_HDL,
    
    	/*!< \brief single led characteristic */
    	CARD10_LED_S_CH_HDL,
    	CARD10_LED_S_VAL_HDL,
    
    	/*!< \brief light sensor characteristic */
    	CARD10_LIGHT_SENSOR_CH_HDL,
    	CARD10_LIGHT_SENSOR_VAL_HDL,
    	/*!< \brief Maximum handle. */
    	CARD10_MAX_HDL
    };
    
    
    genofire's avatar
    genofire committed
    /* clang-format off */
    
    
    /* BLE UUID for card10 service*/
    
    genofire's avatar
    genofire committed
    static const uint8_t UUID_svc[] = { CARD10_UUID_SUFFIX, 0x0, CARD10_UUID_PREFIX };
    
    
    // starting at 0x01 with write (non visual) charateristics
    
    /* BLE UUID for card10 time update */
    static const uint8_t UUID_char_time[] = {
    	ATT_PROP_WRITE,
    	UINT16_TO_BYTES(CARD10_TIME_UPDATE_VAL_HDL),
    	CARD10_UUID_SUFFIX, 0x01, CARD10_UUID_PREFIX
    };
    
    static const uint8_t UUID_attChar_time[] = {
    	CARD10_UUID_SUFFIX, 0x01, CARD10_UUID_PREFIX
    };
    
    
    /* BLE UUID for card10 char vibra */
    
    genofire's avatar
    genofire committed
    static const uint8_t UUID_char_vibra[] = {
    	ATT_PROP_WRITE_NO_RSP,
    	UINT16_TO_BYTES(CARD10_VIBRA_VAL_HDL),
    
    	CARD10_UUID_SUFFIX, 0x0f, CARD10_UUID_PREFIX
    
    genofire's avatar
    genofire committed
    };
    
    
    static const uint8_t UUID_attChar_vibra[] = {
    
    	CARD10_UUID_SUFFIX, 0x0f, CARD10_UUID_PREFIX
    
    
    // starting at 0x10 with write of leds (visual output)
    
    
    /* BLE UUID for card10 char rockets */
    
    genofire's avatar
    genofire committed
    static const uint8_t UUID_char_rockets[] = {
    	ATT_PROP_WRITE_NO_RSP,
    	UINT16_TO_BYTES(CARD10_ROCKETS_VAL_HDL),
    
    genofire's avatar
    genofire committed
    	CARD10_UUID_SUFFIX, 0x10, CARD10_UUID_PREFIX
    
    genofire's avatar
    genofire committed
    };
    
    
    static const uint8_t UUID_attChar_rockets[] = {
    
    genofire's avatar
    genofire committed
    	CARD10_UUID_SUFFIX, 0x10, CARD10_UUID_PREFIX
    
    genofire's avatar
    genofire committed
    /* BLE UUID for card10 led background bottom left */
    static const uint8_t UUID_char_led_bg_bottom_left[] = {
    	ATT_PROP_WRITE_NO_RSP,
    	UINT16_TO_BYTES(CARD10_LED_BG_BOTTOM_LEFT_VAL_HDL),
    	CARD10_UUID_SUFFIX, 0x11, CARD10_UUID_PREFIX
    };
    
    static const uint8_t UUID_attChar_led_bg_bottom_left[] = {
    	CARD10_UUID_SUFFIX, 0x11, CARD10_UUID_PREFIX
    };
    
    /* BLE UUID for card10 led background bottom right */
    static const uint8_t UUID_char_led_bg_bottom_right[] = {
    	ATT_PROP_WRITE_NO_RSP,
    	UINT16_TO_BYTES(CARD10_LED_BG_BOTTOM_RIGHT_VAL_HDL),
    	CARD10_UUID_SUFFIX, 0x12, CARD10_UUID_PREFIX
    };
    
    static const uint8_t UUID_attChar_led_bg_bottom_right[] = {
    	CARD10_UUID_SUFFIX, 0x12, CARD10_UUID_PREFIX
    };
    
    /* BLE UUID for card10 led background top right */
    static const uint8_t UUID_char_led_bg_top_right[] = {
    	ATT_PROP_WRITE_NO_RSP,
    	UINT16_TO_BYTES(CARD10_LED_BG_TOP_RIGHT_VAL_HDL),
    	CARD10_UUID_SUFFIX, 0x13, CARD10_UUID_PREFIX
    };
    
    static const uint8_t UUID_attChar_led_bg_top_right[] = {
    	CARD10_UUID_SUFFIX, 0x13, CARD10_UUID_PREFIX
    };
    
    /* BLE UUID for card10 led background top left */
    static const uint8_t UUID_char_led_bg_top_left[] = {
    	ATT_PROP_WRITE_NO_RSP,
    	UINT16_TO_BYTES(CARD10_LED_BG_TOP_LEFT_VAL_HDL),
    	CARD10_UUID_SUFFIX, 0x14, CARD10_UUID_PREFIX
    };
    
    static const uint8_t UUID_attChar_led_bg_top_left[] = {
    	CARD10_UUID_SUFFIX, 0x14, CARD10_UUID_PREFIX
    };
    
    
    genofire's avatar
    genofire committed
    /* BLE UUID for card10 dim leds on bottom */
    static const uint8_t UUID_char_leds_bottom_dim[] = {
    
    	ATT_PROP_WRITE,
    
    genofire's avatar
    genofire committed
    	UINT16_TO_BYTES(CARD10_LEDS_BOTTOM_DIM_VAL_HDL),
    	CARD10_UUID_SUFFIX, 0x15, CARD10_UUID_PREFIX
    };
    
    static const uint8_t UUID_attChar_leds_bottom_dim[] = {
    	CARD10_UUID_SUFFIX, 0x15, CARD10_UUID_PREFIX
    };
    
    /* BLE UUID for card10 dim leds on top */
    static const uint8_t UUID_char_leds_top_dim[] = {
    
    	ATT_PROP_WRITE,
    
    genofire's avatar
    genofire committed
    	UINT16_TO_BYTES(CARD10_LEDS_TOP_DIM_VAL_HDL),
    	CARD10_UUID_SUFFIX, 0x16, CARD10_UUID_PREFIX
    };
    
    static const uint8_t UUID_attChar_leds_top_dim[] = {
    	CARD10_UUID_SUFFIX, 0x16, CARD10_UUID_PREFIX
    };
    
    
    genofire's avatar
    genofire committed
    /* BLE UUID for card10 above leds */
    static const uint8_t UUID_char_leds_above[] = {
    	ATT_PROP_WRITE_NO_RSP,
    	UINT16_TO_BYTES(CARD10_LEDS_ABOVE_VAL_HDL),
    	CARD10_UUID_SUFFIX, 0x20, CARD10_UUID_PREFIX
    };
    
    static const uint8_t UUID_attChar_leds_above[] = {
    	CARD10_UUID_SUFFIX, 0x20, CARD10_UUID_PREFIX
    };
    
    
    /* BLE UUID for card10 char led single (debugging) */
    static const uint8_t UUID_char_led_s[] = {
    	ATT_PROP_WRITE_NO_RSP,
    	UINT16_TO_BYTES(CARD10_LED_S_VAL_HDL),
    	CARD10_UUID_SUFFIX, 0xef, CARD10_UUID_PREFIX
    };
    
    static const uint8_t UUID_attChar_led_s[] = {
    	CARD10_UUID_SUFFIX, 0xef, CARD10_UUID_PREFIX
    };
    
    // starting at 0xf0 with read only characteristics
    
    
    /* BLE UUID for card10 char light sensor */
    static const uint8_t UUID_char_light_sensor[] = {
    	ATT_PROP_READ,
    	UINT16_TO_BYTES(CARD10_LIGHT_SENSOR_VAL_HDL),
    
    genofire's avatar
    genofire committed
    	CARD10_UUID_SUFFIX, 0xf0, CARD10_UUID_PREFIX
    
    };
    static const uint8_t UUID_attChar_light_sensor[] = {
    
    genofire's avatar
    genofire committed
    	CARD10_UUID_SUFFIX, 0xf0, CARD10_UUID_PREFIX
    
    genofire's avatar
    genofire committed
    /* clang-format on */
    
    
    /*
     * Create the BLE service description. 
     */
    static void *addCard10GroupDyn(void)
    {
    	void *pSHdl;
    
    	uint8_t initLightSensorValue[] = { UINT16_TO_BYTES(0) };
    
    	/* Create the service */
    	pSHdl = AttsDynCreateGroup(CARD10_START_HDL, CARD10_END_HDL);
    	if (pSHdl != NULL) {
    		/* Primary service */
    		AttsDynAddAttrConst(
    			pSHdl,
    			attPrimSvcUuid,
    			UUID_svc,
    			sizeof(UUID_svc),
    			0,
    			ATTS_PERMIT_READ
    		);
    
    
    		// TIME UPDTAE
    
    		AttsDynAddAttrConst(
    			pSHdl,
    			attChUuid,
    			UUID_char_time,
    			sizeof(UUID_char_time),
    			0,
    			ATTS_PERMIT_READ
    		);
    
    		AttsDynAddAttr(
    			pSHdl,
    			UUID_attChar_time,
    			NULL,
    			0,
    			sizeof(uint64_t),
    			ATTS_SET_WRITE_CBACK,
    
    			ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC |
    				ATTS_PERMIT_WRITE_AUTH);
    
    		// VIBRA
    
    		AttsDynAddAttrConst(
    			pSHdl,
    			attChUuid,
    			UUID_char_vibra,
    			sizeof(UUID_char_vibra),
    			0,
    			ATTS_PERMIT_READ
    		);
    
    		AttsDynAddAttr(
    			pSHdl,
    			UUID_attChar_vibra,
    			NULL,
    
    genofire's avatar
    genofire committed
    			0,
    
    			sizeof(uint16_t),
    			ATTS_SET_WRITE_CBACK,
    
    			ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC |
    				ATTS_PERMIT_WRITE_AUTH);
    
    
    		// ROCKETS
    
    		AttsDynAddAttrConst(
    			pSHdl,
    			attChUuid,
    			UUID_char_rockets,
    			sizeof(UUID_char_rockets),
    			0,
    			ATTS_PERMIT_READ
    		);
    
    		AttsDynAddAttr(
    			pSHdl,
    			UUID_attChar_rockets,
    			NULL,
    
    genofire's avatar
    genofire committed
    			0,
    
    			3 * sizeof(uint8_t),
    			ATTS_SET_WRITE_CBACK,
    
    			ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC |
    				ATTS_PERMIT_WRITE_AUTH);
    
    genofire's avatar
    genofire committed
    		// BG LED Bottom left
    
    		AttsDynAddAttrConst(
    			pSHdl,
    			attChUuid,
    			UUID_char_led_bg_bottom_left,
    			sizeof(UUID_char_led_bg_bottom_left),
    			0,
    			ATTS_PERMIT_READ
    		);
    
    		AttsDynAddAttr(
    			pSHdl,
    			UUID_attChar_led_bg_bottom_left,
    			NULL,
    			0,
    			3 * sizeof(uint8_t),
    			ATTS_SET_WRITE_CBACK,
    
    			ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC |
    				ATTS_PERMIT_WRITE_AUTH);
    
    genofire's avatar
    genofire committed
    
    		// BG LED Bottom right
    
    		AttsDynAddAttrConst(
    			pSHdl,
    			attChUuid,
    			UUID_char_led_bg_bottom_right,
    			sizeof(UUID_char_led_bg_bottom_right),
    			0,
    			ATTS_PERMIT_READ
    		);
    
    		AttsDynAddAttr(
    			pSHdl,
    			UUID_attChar_led_bg_bottom_right,
    			NULL,
    			0,
    			3 * sizeof(uint8_t),
    			ATTS_SET_WRITE_CBACK,
    
    			ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC |
    				ATTS_PERMIT_WRITE_AUTH);
    
    genofire's avatar
    genofire committed
    
    		// BG LED top right
    
    		AttsDynAddAttrConst(
    			pSHdl,
    			attChUuid,
    			UUID_char_led_bg_top_right,
    			sizeof(UUID_char_led_bg_top_right),
    			0,
    			ATTS_PERMIT_READ
    		);
    
    		AttsDynAddAttr(
    			pSHdl,
    			UUID_attChar_led_bg_top_right,
    			NULL,
    			0,
    			3 * sizeof(uint8_t),
    			ATTS_SET_WRITE_CBACK,
    
    			ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC |
    				ATTS_PERMIT_WRITE_AUTH);
    
    genofire's avatar
    genofire committed
    
    		// BG LED top left
    
    		AttsDynAddAttrConst(
    			pSHdl,
    			attChUuid,
    			UUID_char_led_bg_top_left,
    			sizeof(UUID_char_led_bg_top_left),
    			0,
    			ATTS_PERMIT_READ
    		);
    
    		AttsDynAddAttr(
    			pSHdl,
    			UUID_attChar_led_bg_top_left,
    			NULL,
    			0,
    			3 * sizeof(uint8_t),
    			ATTS_SET_WRITE_CBACK,
    
    			ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC |
    				ATTS_PERMIT_WRITE_AUTH);
    
    genofire's avatar
    genofire committed
    		// Dim bottom module
    
    		AttsDynAddAttrConst(
    			pSHdl,
    			attChUuid,
    			UUID_char_leds_bottom_dim,
    			sizeof(UUID_char_leds_bottom_dim),
    			0,
    			ATTS_PERMIT_READ
    		);
    
    		AttsDynAddAttr(
    			pSHdl,
    			UUID_attChar_leds_bottom_dim,
    			NULL,
    			0,
    			sizeof(uint8_t),
    			ATTS_SET_WRITE_CBACK,
    
    			ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC |
    				ATTS_PERMIT_WRITE_AUTH);
    
    genofire's avatar
    genofire committed
    
    		// Dim top module
    
    		AttsDynAddAttrConst(
    			pSHdl,
    			attChUuid,
    			UUID_char_leds_top_dim,
    			sizeof(UUID_char_leds_top_dim),
    			0,
    			ATTS_PERMIT_READ
    		);
    
    		AttsDynAddAttr(
    			pSHdl,
    			UUID_attChar_leds_top_dim,
    			NULL,
    			0,
    			sizeof(uint8_t),
    			ATTS_SET_WRITE_CBACK,
    
    			ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC |
    				ATTS_PERMIT_WRITE_AUTH);
    
    genofire's avatar
    genofire committed
    		// ABOVE LEDS
    
    		AttsDynAddAttrConst(
    			pSHdl,
    			attChUuid,
    			UUID_char_leds_above,
    			sizeof(UUID_char_leds_above),
    			0,
    			ATTS_PERMIT_READ
    		);
    
    		AttsDynAddAttr(
    			pSHdl,
    			UUID_attChar_leds_above,
    			NULL,
    			0,
    			11 * 3 * sizeof(uint8_t),
    			ATTS_SET_WRITE_CBACK,
    
    			ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC |
    				ATTS_PERMIT_WRITE_AUTH);
    
    		// SINGLE LED
    
    		AttsDynAddAttrConst(
    			pSHdl,
    			attChUuid,
    			UUID_char_led_s,
    			sizeof(UUID_char_led_s),
    			0,
    			ATTS_PERMIT_READ
    		);
    
    		AttsDynAddAttr(
    			pSHdl,
    			UUID_attChar_led_s,
    			NULL,
    			0,
    			sizeof(uint16_t) + 3 * sizeof(uint8_t),
    			ATTS_SET_WRITE_CBACK,
    
    			ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC |
    				ATTS_PERMIT_WRITE_AUTH);
    
    		// LIGHT_SENSOR
    
    		AttsDynAddAttrConst(
    			pSHdl,
    			attChUuid,
    			UUID_char_light_sensor,
    			sizeof(UUID_char_light_sensor),
    			0,
    			ATTS_PERMIT_READ
    		);
    
    		AttsDynAddAttr(
    			pSHdl,
    			UUID_attChar_light_sensor,
    			initLightSensorValue,
    			sizeof(uint8_t),
    			sizeof(uint8_t),
    			ATTS_SET_READ_CBACK,
    
    			ATTS_PERMIT_READ | ATTS_PERMIT_READ_ENC |
    				ATTS_PERMIT_READ_AUTH);
    
    genofire's avatar
    genofire committed
    		APP_TRACE_INFO0("ble-card10: services bound\n");
    
    /*
     * Set the time given in milliseconds since 1.1.1970 as 64 bit integer.
     */
    static uint8_t setTime(uint8_t *pValue, uint16_t len)
    {
    	uint64_t timeNet;
    	uint64_t time;
    
    	if (len < sizeof(uint64_t)) {
    		return ATT_ERR_LENGTH;
    	}
    	memcpy(&timeNet, pValue, sizeof(timeNet));
    
    	time = __bswap64(timeNet);
    	epic_rtc_set_milliseconds(time);
    
    	return ATT_SUCCESS;
    }
    
    
    genofire's avatar
    genofire committed
     * BLE card10 write callback.
    
     */
    
    static uint8_t writeCard10CB(
    	dmConnId_t connId,
    	uint16_t handle,
    	uint8_t operation,
    	uint16_t offset,
    	uint16_t len,
    	uint8_t *pValue,
    	attsAttr_t *pAttr
    ) {
    
    	uint16_t ui16 = 0;
    
    	uint8_t ui8   = 0;
    
    	case CARD10_TIME_UPDATE_VAL_HDL:
    		if (operation == ATT_PDU_PREP_WRITE_REQ) {
    			if (len < sizeof(uint64_t)) {
    				return ATT_ERR_LENGTH;
    			}
    			return ATT_SUCCESS;
    		}
    		return setTime(pValue, len);
    
    	case CARD10_VIBRA_VAL_HDL:
    		BYTES_TO_UINT16(ui16, pValue);
    		epic_vibra_vibrate(ui16);
    		APP_TRACE_INFO1("ble-card10: set vibra for %dms\n", ui16);
    		return ATT_SUCCESS;
    
    	case CARD10_ROCKETS_VAL_HDL:
    		epic_leds_set_rocket(0, pValue[0]);
    		epic_leds_set_rocket(1, pValue[1]);
    		epic_leds_set_rocket(2, pValue[2]);
    		APP_TRACE_INFO3(
    			"ble-card10: set rockets 0:%d, 1:%d, 2:%d\n",
    			pValue[0],
    			pValue[1],
    			pValue[2]
    		);
    		return ATT_SUCCESS;
    
    genofire's avatar
    genofire committed
    	case CARD10_LED_BG_BOTTOM_LEFT_VAL_HDL:
    		epic_leds_set(11, pValue[0], pValue[1], pValue[2]);
    		APP_TRACE_INFO3(
    			"ble-card10: set bg bottom left: #%02x%02x%02x\n",
    			pValue[0],
    			pValue[1],
    			pValue[2]
    		);
    		return ATT_SUCCESS;
    	case CARD10_LED_BG_BOTTOM_RIGHT_VAL_HDL:
    		epic_leds_set(12, pValue[0], pValue[1], pValue[2]);
    		APP_TRACE_INFO3(
    			"ble-card10: set bg bottom right: #%02x%02x%02x\n",
    			pValue[0],
    			pValue[1],
    			pValue[2]
    		);
    		return ATT_SUCCESS;
    	case CARD10_LED_BG_TOP_RIGHT_VAL_HDL:
    		epic_leds_set(13, pValue[0], pValue[1], pValue[2]);
    		APP_TRACE_INFO3(
    			"ble-card10: set bg top right: #%02x%02x%02x\n",
    			pValue[0],
    			pValue[1],
    			pValue[2]
    		);
    		return ATT_SUCCESS;
    	case CARD10_LED_BG_TOP_LEFT_VAL_HDL:
    		epic_leds_set(14, pValue[0], pValue[1], pValue[2]);
    		APP_TRACE_INFO3(
    			"ble-card10: set bg top left: #%02x%02x%02x\n",
    			pValue[0],
    			pValue[1],
    			pValue[2]
    		);
    		return ATT_SUCCESS;
    
    genofire's avatar
    genofire committed
    	case CARD10_LEDS_BOTTOM_DIM_VAL_HDL:
    
    		ui8 = pValue[0];
    
    		if (ui8 >= 1 && ui8 <= 8) {
    
    			epic_leds_dim_bottom(pValue[0]);
    			APP_TRACE_INFO1("dim bottom to: %d\n", pValue[0]);
    			return ATT_SUCCESS;
    		}
    		APP_TRACE_INFO1("dim bottom invalid value (1-8): %d\n", ui8);
    		return ATT_ERR_RANGE;
    
    genofire's avatar
    genofire committed
    	case CARD10_LEDS_TOP_DIM_VAL_HDL:
    
    		ui8 = pValue[0];
    
    		if (ui8 >= 1 && ui8 <= 8) {
    
    			epic_leds_dim_top(ui8);
    			APP_TRACE_INFO1("dim top to: %d\n", ui8);
    			return ATT_SUCCESS;
    		}
    		APP_TRACE_INFO1("dim top invalid value (1-8): %d\n", ui8);
    		return ATT_ERR_RANGE;
    
    genofire's avatar
    genofire committed
    	case CARD10_LEDS_ABOVE_VAL_HDL:
    
    genofire's avatar
    genofire committed
    		for (ui16 = 0; ui16 < 11; ui16++) {
    
    genofire's avatar
    genofire committed
    			epic_leds_set(
    				ui16,
    				pValue[ui16 * 3],
    				pValue[ui16 * 3 + 1],
    				pValue[ui16 * 3 + 2]
    			);
    			APP_TRACE_INFO4(
    				"ble-card10: set led %ld above to #%02x%02x%02x\n",
    				ui16,
    				pValue[ui16 * 3],
    				pValue[ui16 * 3 + 1],
    				pValue[ui16 * 3 + 2]
    			);
    		}
    
    	case CARD10_LED_S_VAL_HDL:
    		BYTES_TO_UINT16(ui16, pValue);
    		epic_leds_set(ui16, pValue[2], pValue[3], pValue[4]);
    		APP_TRACE_INFO4(
    
    genofire's avatar
    genofire committed
    			"ble-card10: set single led %ld to #%02x%02x%02x\n",
    
    			ui16,
    			pValue[2],
    			pValue[3],
    			pValue[4]
    		);
    		return ATT_SUCCESS;
    
    	default:
    		APP_TRACE_INFO1(
    			"ble-card10: unsupported characteristic: %c\n", handle
    		);
    		return ATT_ERR_HANDLE;
    	}
    }
    
    
    genofire's avatar
    genofire committed
    /*
     * BLE card10 read callback.
     */
    
    
    static uint8_t readCard10CB(
    	dmConnId_t connId,
    	uint16_t handle,
    	uint8_t operation,
    	uint16_t offset,
    	attsAttr_t *pAttr
    ) {
    	uint16_t ui16 = 0;
    
    	switch (handle) {
    	case CARD10_LIGHT_SENSOR_VAL_HDL:
    		epic_light_sensor_get(&ui16);
    		*pAttr->pValue = ui16;
    		APP_TRACE_INFO1("ble-card10: read lightsensor: %d\n", ui16);
    		return ATT_SUCCESS;
    	default:
    		APP_TRACE_INFO0("ble-card10: read no handler found\n");
    		return ATT_ERR_HANDLE;
    	}
    }
    
    /*
    
    genofire's avatar
    genofire committed
     * This registers and starts the BLE card10 service.
    
     */
    
    void bleCard10_init(void)
    {
    	void *pSHdl = addCard10GroupDyn();
    	AttsDynRegister(pSHdl, readCard10CB, writeCard10CB);
    }