Skip to content
Snippets Groups Projects
Verified Commit f0a9fd42 authored by schneider's avatar schneider Committed by rahix
Browse files

chore(ble): Apply code style

parent 0f26c9f3
No related branches found
No related tags found
No related merge requests found
......@@ -22,6 +22,8 @@
*
* Reason: we need to correctly implement AppHandleNumericComparison
*/
/* clang-format off */
/* clang-formet turned off for easier diffing against orginal file */
#include <string.h>
#include "wsf_types.h"
#include "wsf_msg.h"
......@@ -418,3 +420,4 @@ void AppUpdatePrivacyMode(appDbHdl_t hdl)
}
}
}
/* clang-format on */
......@@ -22,6 +22,8 @@
*
* Reason: we need to implement persistent storage for pairings
*/
/* clang-format off */
/* clang-formet turned off for easier diffing against orginal file */
#include <string.h>
#include "wsf_types.h"
#include "wsf_assert.h"
......@@ -708,3 +710,4 @@ void AppDbSetPeerRpao(appDbHdl_t hdl, bool_t peerRpao)
{
((appDbRec_t *)hdl)->peerRpao = peerRpao;
}
/* clang-format on */
......@@ -28,6 +28,8 @@
* Reason: has several user interactions which we likley have to implement
*/
/* clang-format off */
/* clang-formet turned off for easier diffing against orginal file */
/**************************************************************************************************
Global Variables
**************************************************************************************************/
......@@ -330,3 +332,4 @@ void AppUiBtnTest(uint8_t btn)
}
}
/* clang-format on */
#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 "ble_api.h"
#include "hci_vs.h"
#include "att_defs.h"
#include "util/bstream.h"
#include "att_api.h"
#include "modules/modules.h"
#include "fs_util.h"
#include "FreeRTOS.h"
#include "timers.h"
......@@ -21,19 +13,18 @@
#include <string.h>
#include <stdbool.h>
#define WSF_BUF_POOLS 6
#define WSF_BUF_SIZE 0x1048
/* Size of buffer for stdio functions */
#define WSF_BUF_POOLS 6
#define WSF_BUF_SIZE 0x1048
uint32_t SystemHeapSize=WSF_BUF_SIZE;
uint32_t SystemHeap[WSF_BUF_SIZE/4];
uint32_t SystemHeapSize = WSF_BUF_SIZE;
uint32_t SystemHeap[WSF_BUF_SIZE / 4];
uint32_t SystemHeapStart;
/* Task ID for the ble handler */
static TaskHandle_t ble_task_id = NULL;
/*! Default pool descriptor. */
/* clang-format off */
static wsfBufPoolDesc_t mainPoolDesc[WSF_BUF_POOLS] =
{
{ 16, 8 },
......@@ -43,6 +34,11 @@ static wsfBufPoolDesc_t mainPoolDesc[WSF_BUF_POOLS] =
{ 256, 4 },
{ 512, 4 }
};
/* clang-format on */
static StaticTimer_t x;
static TimerHandle_t timerWakeup = NULL;
static int lasttick = 0;
/*! \brief Stack initialization for app. */
extern void StackInit(void);
......@@ -52,164 +48,156 @@ extern void bleuart_init(void);
/*************************************************************************************************/
void PalSysAssertTrap(void)
{
while(1) {}
while (1) {
}
}
/*************************************************************************************************/
static bool_t myTrace(const uint8_t *pBuf, uint32_t len)
{
extern uint8_t wsfCsNesting;
extern uint8_t wsfCsNesting;
if (wsfCsNesting == 0)
{
fwrite(pBuf, len, 1, stdout);
return TRUE;
}
if (wsfCsNesting == 0) {
fwrite(pBuf, len, 1, stdout);
return TRUE;
}
return FALSE;
return FALSE;
}
/*************************************************************************************************/
/*!
* \brief Initialize WSF.
*
* \return None.
*/
/*************************************************************************************************/
static void WsfInit(void)
{
uint32_t bytesUsed;
WsfTimerInit();
SystemHeapStart = (uint32_t)&SystemHeap;
memset(SystemHeap, 0, sizeof(SystemHeap));
//printf("SystemHeapStart = 0x%x\n", SystemHeapStart);
//printf("SystemHeapSize = 0x%x\n", SystemHeapSize);
bytesUsed = WsfBufInit(WSF_BUF_POOLS, mainPoolDesc);
printf("bytesUsed = %u\n", (unsigned int)bytesUsed);
WsfTraceRegisterHandler(myTrace);
WsfTraceEnable(TRUE);
uint32_t bytesUsed;
WsfTimerInit();
SystemHeapStart = (uint32_t)&SystemHeap;
memset(SystemHeap, 0, sizeof(SystemHeap));
//printf("SystemHeapStart = 0x%x\n", SystemHeapStart);
//printf("SystemHeapSize = 0x%x\n", SystemHeapSize);
bytesUsed = WsfBufInit(WSF_BUF_POOLS, mainPoolDesc);
printf("bytesUsed = %u\n", (unsigned int)bytesUsed);
WsfTraceRegisterHandler(myTrace);
WsfTraceEnable(TRUE);
}
/*************************************************************************************************/
/* TODO: We need a source of MACs */
static void setAddress(void)
{
uint8_t bdAddr[6] = {0x02, 0x02, 0x44, 0x8B, 0x05, 0x00};
char buf[32];
fs_read_text_file("mac.txt", buf, sizeof(buf));
printf("mac file: %s\n", buf);
int a, b, c, d, e, f;
if(sscanf(buf, "%x:%x:%x:%x:%x:%x", &a, &b, &c, &d, &e, &f) == 6) {
bdAddr[0] = f;
bdAddr[1] = e;
bdAddr[2] = d;
bdAddr[3] = c;
bdAddr[4] = b;
bdAddr[5] = a;
}
printf("Setting address -- MAC %02X:%02X:%02X:%02X:%02X:%02X\n", bdAddr[5], bdAddr[4], bdAddr[3], bdAddr[2], bdAddr[1], bdAddr[0]);
HciVsSetBdAddr(bdAddr);
uint8_t bdAddr[6] = { 0x02, 0x02, 0x44, 0x8B, 0x05, 0x00 };
char buf[32];
fs_read_text_file("mac.txt", buf, sizeof(buf));
printf("mac file: %s\n", buf);
int a, b, c, d, e, f;
if (sscanf(buf, "%x:%x:%x:%x:%x:%x", &a, &b, &c, &d, &e, &f) == 6) {
bdAddr[0] = f;
bdAddr[1] = e;
bdAddr[2] = d;
bdAddr[3] = c;
bdAddr[4] = b;
bdAddr[5] = a;
}
printf("Setting address -- MAC %02X:%02X:%02X:%02X:%02X:%02X\n",
bdAddr[5],
bdAddr[4],
bdAddr[3],
bdAddr[2],
bdAddr[1],
bdAddr[0]);
HciVsSetBdAddr(bdAddr);
}
static StaticTimer_t x;
TimerHandle_t timerWakeup = NULL;
int lasttick = 0;
bool schedule_needed = false;
/*************************************************************************************************/
static void vTimerCallback(xTimerHandle pxTimer)
{
//printf("wake\n");
int tick = xTaskGetTickCount();
//printf("WsfTimerUpdate(%d)\n", tick - lasttick);
WsfTimerUpdate(tick - lasttick);
lasttick = tick;
//printf("done\n");
//printf("wake\n");
int tick = xTaskGetTickCount();
//printf("WsfTimerUpdate(%d)\n", tick - lasttick);
WsfTimerUpdate(tick - lasttick);
lasttick = tick;
//printf("done\n");
}
/*************************************************************************************************/
static void notify(void)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if(xPortIsInsideInterrupt()) {
vTaskNotifyGiveFromISR(ble_task_id, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
} else {
xTaskNotifyGive(ble_task_id);
}
if (xPortIsInsideInterrupt()) {
vTaskNotifyGiveFromISR(ble_task_id, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
} else {
xTaskNotifyGive(ble_task_id);
}
}
/*************************************************************************************************/
void WsfTimerNotify(void)
{
//printf("WsfTimerNotify\n");
// TODO: Can we do this without waking up the task?
// xTimerChangePeriodFromISR exists
notify();
//printf("WsfTimerNotify\n");
// TODO: Can we do this without waking up the task?
// xTimerChangePeriodFromISR exists
notify();
}
/*************************************************************************************************/
void wsf_ble_signal_event(void)
{
//printf("wsf_ble_signal_event\n");
notify();
//printf("wsf_ble_signal_event\n");
notify();
}
/*************************************************************************************************/
static void scheduleTimer(void)
{
bool_t timerRunning;
wsfTimerTicks_t time_to_next_expire;
vTimerCallback(NULL);
time_to_next_expire = WsfTimerNextExpiration(&timerRunning);
if(timerRunning) {
//printf("time_to_next_expire = %d\n", time_to_next_expire);
//printf("change period\n");
if(timerWakeup != NULL) {
xTimerChangePeriod(timerWakeup, pdMS_TO_TICKS(time_to_next_expire), 0);
//printf("insert done\n");
} else {
printf("could not create timer\n");
}
} else {
printf("No timer running\n");
}
bool_t timerRunning;
wsfTimerTicks_t time_to_next_expire;
vTimerCallback(NULL);
time_to_next_expire = WsfTimerNextExpiration(&timerRunning);
if (timerRunning) {
//printf("time_to_next_expire = %d\n", time_to_next_expire);
//printf("change period\n");
if (timerWakeup != NULL) {
xTimerChangePeriod(
timerWakeup,
pdMS_TO_TICKS(time_to_next_expire),
0
);
//printf("insert done\n");
} else {
printf("could not create timer\n");
}
} else {
printf("No timer running\n");
}
}
static void ble_init(void)
{
WsfInit();
StackInit();
setAddress();
NVIC_SetPriority(BTLE_SFD_TO_IRQn, 2);
NVIC_SetPriority(BTLE_TX_DONE_IRQn, 2);
NVIC_SetPriority(BTLE_RX_RCVD_IRQn, 2);
AppInit();
BleStart();
AttsDynInit();
bleuart_init();
lasttick = xTaskGetTickCount();
timerWakeup = xTimerCreateStatic(
"timerWakeup", /* name */
pdMS_TO_TICKS(1), /* period/time */
pdFALSE, /* auto reload */
NULL, /* timer ID */
vTimerCallback, &x); /* callback */
}
void vBleTask(void*pvParameters)
/*************************************************************************************************/
void vBleTask(void *pvParameters)
{
ble_task_id = xTaskGetCurrentTaskHandle();
ble_init();
while (1){
WsfInit();
StackInit();
setAddress();
NVIC_SetPriority(BTLE_SFD_TO_IRQn, 2);
NVIC_SetPriority(BTLE_TX_DONE_IRQn, 2);
NVIC_SetPriority(BTLE_RX_RCVD_IRQn, 2);
AppInit();
BleStart();
AttsDynInit();
bleuart_init();
lasttick = xTaskGetTickCount();
timerWakeup = xTimerCreateStatic(
"timerWakeup", /* name */
pdMS_TO_TICKS(1), /* period/time */
pdFALSE, /* auto reload */
NULL, /* timer ID */
vTimerCallback,
&x); /* callback */
while (1) {
ulTaskNotifyTake(pdTRUE, portTICK_PERIOD_MS * 1000);
wsfOsDispatcher();
scheduleTimer();
}
wsfOsDispatcher();
scheduleTimer();
}
}
......@@ -11,6 +11,8 @@
* Fit -> Ble
* FIT -> BLE
*/
/* clang-format off */
/* clang-formet turned off for easier diffing against orginal file */
#include <string.h>
#include "wsf_types.h"
#include "util/bstream.h"
......@@ -508,3 +510,4 @@ void BleStart(void)
/* Reset the device */
DmDevReset();
}
/* clang-format on */
......@@ -29,6 +29,8 @@
* Many components are related to the role of the device. Different components need to be
* initialized for central and peripheral roles.
*/
/* clang-format off */
/* clang-formet turned off for easier diffing against orginal file */
#include <stdio.h>
#include <string.h>
#include "wsf_types.h"
......@@ -184,3 +186,4 @@ void StackInit(void)
/*TODO card10: Probably want to adjust this */
HciSetMaxRxAclLen(100);
}
/* clang-format off */
......@@ -20,6 +20,8 @@
/* card10:
* copied from lib/sdk/Libraries/BTLE/stack/ble-profiles/sources/services/svc_core.c
*/
/* clang-format off */
/* clang-formet turned off for easier diffing against orginal file */
#include "wsf_types.h"
#include "att_api.h"
#include "att_uuid.h"
......@@ -344,3 +346,4 @@ void SvcCoreGapAddRpaoCh(void)
svcGapGroup.endHandle = GAP_RPAO_HDL;
}
}
/* clang-format on */
......@@ -22,6 +22,8 @@
*
* Contains adaptions for the card10 (e.g. manufacturer name)
*/
/* clang-format off */
/* clang-formet turned off for easier diffing against orginal file */
#include "wsf_types.h"
#include "att_api.h"
#include "wsf_assert.h"
......@@ -331,3 +333,4 @@ void SvcDisRemoveGroup(void)
{
AttsRemoveGroup(DIS_START_HDL);
}
/* clang-format on */
......@@ -11,24 +11,21 @@
#include <string.h>
#include <stdbool.h>
#define UART_START_HDL 0x800 /*!< \brief Service start handle. */
#define UART_END_HDL (UART_MAX_HDL - 1) /*!< \brief Service end handle. */
#define UART_START_HDL 0x800 /*!< \brief Service start handle. */
#define UART_END_HDL (UART_MAX_HDL - 1) /*!< \brief Service end handle. */
/**************************************************************************************************
Handles
**************************************************************************************************/
/*! \brief UART Service Handles */
enum
{
UART_SVC_HDL = UART_START_HDL, /*!< \brief UART service declaration */
UART_RX_CH_HDL, /*!< \brief UART rx characteristic */
UART_RX_HDL, /*!< \brief UART rx value */
UART_TX_CH_HDL, /*!< \brief UART tx characteristic */
UART_TX_HDL, /*!< \brief UART tx value */
UART_TX_CH_CCC_HDL, /*!< \brief UART tx CCCD */
UART_MAX_HDL /*!< \brief Maximum handle. */
enum { UART_SVC_HDL = UART_START_HDL, /*!< \brief UART service declaration */
UART_RX_CH_HDL, /*!< \brief UART rx characteristic */
UART_RX_HDL, /*!< \brief UART rx value */
UART_TX_CH_HDL, /*!< \brief UART tx characteristic */
UART_TX_HDL, /*!< \brief UART tx value */
UART_TX_CH_CCC_HDL, /*!< \brief UART tx CCCD */
UART_MAX_HDL /*!< \brief Maximum handle. */
};
/**@}*/
......@@ -42,75 +39,84 @@ static const uint8_t uartTxCh[] = {ATT_PROP_READ | ATT_PROP_NOTIFY, UINT16_TO_BY
const uint8_t attUartTxChUuid[] = {0x9E,0xCA,0xDC,0x24,0x0E,0xE5, 0xA9,0xE0,0x93,0xF3,0xA3,0xB5,0x03,0x00,0x40,0x6E};
/* clang-format on */
static void *SvcUARTAddGroupDyn(void)
{
void *pSHdl;
uint8_t initCcc[] = {UINT16_TO_BYTES(0x0000)};
/* Create the service */
pSHdl = AttsDynCreateGroup(UART_START_HDL, UART_END_HDL);
if (pSHdl != NULL)
{
/* Primary service */
AttsDynAddAttrConst(pSHdl, attPrimSvcUuid, UARTSvc, sizeof(UARTSvc), 0, ATTS_PERMIT_READ);
/* UART rx characteristic */
AttsDynAddAttrConst(pSHdl, attChUuid, uartRxCh, sizeof(uartRxCh), 0, ATTS_PERMIT_READ);
// XXX: attUartRxChUuid is 16 bytes but nothing says so....
/* UART rx value */
// XXX: not sure if max value of 128 is fine...
AttsDynAddAttr(pSHdl, attUartRxChUuid, NULL, 0, 128,
ATTS_SET_WRITE_CBACK | ATTS_SET_VARIABLE_LEN, ATTS_PERMIT_WRITE);
/* UART tx characteristic */
AttsDynAddAttrConst(pSHdl, attChUuid, uartTxCh, sizeof(uartTxCh), 0, ATTS_PERMIT_READ);
/* UART tx value */
/* TODO: do we need ATTS_SET_READ_CBACK ? */
AttsDynAddAttr(pSHdl, attUartTxChUuid, NULL, 0, sizeof(uint8_t),
ATTS_SET_READ_CBACK, ATTS_PERMIT_READ);
/* UART tx CCC descriptor */
AttsDynAddAttr(pSHdl, attCliChCfgUuid, initCcc, sizeof(uint16_t), sizeof(uint16_t),
ATTS_SET_CCC, ATTS_PERMIT_READ | ATTS_PERMIT_WRITE);
}
return pSHdl;
void *pSHdl;
uint8_t initCcc[] = { UINT16_TO_BYTES(0x0000) };
/* Create the service */
pSHdl = AttsDynCreateGroup(UART_START_HDL, UART_END_HDL);
if (pSHdl != NULL) {
/* clang-format off */
/* Primary service */
AttsDynAddAttrConst( pSHdl, attPrimSvcUuid, UARTSvc, sizeof(UARTSvc),
0, ATTS_PERMIT_READ);
/* UART rx characteristic */
AttsDynAddAttrConst( pSHdl, attChUuid, uartRxCh, sizeof(uartRxCh),
0, ATTS_PERMIT_READ);
// XXX: attUartRxChUuid is 16 bytes but nothing says so....
/* UART rx value */
// XXX: not sure if max value of 128 is fine...
AttsDynAddAttr( pSHdl, attUartRxChUuid, NULL, 0, 128,
ATTS_SET_WRITE_CBACK | ATTS_SET_VARIABLE_LEN, ATTS_PERMIT_WRITE);
/* UART tx characteristic */
AttsDynAddAttrConst( pSHdl, attChUuid, uartTxCh, sizeof(uartTxCh),
0, ATTS_PERMIT_READ);
/* UART tx value */
/* TODO: do we need ATTS_SET_READ_CBACK ? */
AttsDynAddAttr( pSHdl, attUartTxChUuid, NULL, 0, sizeof(uint8_t),
ATTS_SET_READ_CBACK, ATTS_PERMIT_READ);
/* UART tx CCC descriptor */
AttsDynAddAttr( pSHdl, attCliChCfgUuid, initCcc, sizeof(uint16_t), sizeof(uint16_t),
ATTS_SET_CCC, ATTS_PERMIT_READ | ATTS_PERMIT_WRITE);
/* clang-format on */
}
return pSHdl;
}
dmConnId_t active_connection = 0;
static uint8_t UARTReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation,
uint16_t offset, attsAttr_t *pAttr)
{
printf("read callback\n");
return ATT_SUCCESS;
static uint8_t UARTReadCback(
dmConnId_t connId,
uint16_t handle,
uint8_t operation,
uint16_t offset,
attsAttr_t *pAttr
) {
printf("read callback\n");
return ATT_SUCCESS;
}
static uint8_t UARTWriteCback(dmConnId_t connId, uint16_t handle, uint8_t operation,
uint16_t offset, uint16_t len, uint8_t *pValue,
attsAttr_t *pAttr)
{
active_connection = connId;
//printf("UARTWriteCback %d: ", len);
int i;
for(i=0; i<len; i++) {
//printf("%c", pValue[i]);
serial_enqueue_char(pValue[i]);
}
serial_enqueue_char('\r');
//printf("\n");
static uint8_t UARTWriteCback(
dmConnId_t connId,
uint16_t handle,
uint8_t operation,
uint16_t offset,
uint16_t len,
uint8_t *pValue,
attsAttr_t *pAttr
) {
active_connection = connId;
//printf("UARTWriteCback %d: ", len);
int i;
for (i = 0; i < len; i++) {
//printf("%c", pValue[i]);
serial_enqueue_char(pValue[i]);
}
serial_enqueue_char('\r');
//printf("\n");
#if 0
AttsSetAttr(UART_TX_HDL, len, pValue);
AttsHandleValueNtf(connId, UART_TX_HDL, len, pValue);
#endif
return ATT_SUCCESS;
return ATT_SUCCESS;
}
uint8_t ble_uart_tx_buf[129];
......@@ -119,42 +125,51 @@ int ble_uart_lasttick = 0;
void ble_uart_write(uint8_t *pValue, uint8_t len)
{
int i;
for(i=0; i<len; i++) {
if(pValue[i] >= 0x20 && pValue[i] < 0x7f) {
ble_uart_tx_buf[ble_uart_buf_tx_fill] = pValue[i];
ble_uart_buf_tx_fill++;
} else if(pValue[i] == '\r' || pValue[i] == '\n') {
if(ble_uart_buf_tx_fill > 0) {
AttsSetAttr(UART_TX_HDL, ble_uart_buf_tx_fill, ble_uart_tx_buf);
if(active_connection) {
int x = xTaskGetTickCount() - ble_uart_lasttick;
if(x < 100) {
// Ugly hack if we already send something recently.
// TODO: figure out how fast we can send or use indications
vTaskDelay(100 - x);
}
//printf("notify: ");
//int j;
//for(j=0;j<ble_uart_buf_tx_fill;j++) {
// printf("%02x ", ble_uart_tx_buf[j]);
//}
//printf("\n");
AttsHandleValueNtf(active_connection, UART_TX_HDL, ble_uart_buf_tx_fill, ble_uart_tx_buf);
ble_uart_lasttick = xTaskGetTickCount();
}
ble_uart_buf_tx_fill = 0;
}
}
}
int i;
for (i = 0; i < len; i++) {
if (pValue[i] >= 0x20 && pValue[i] < 0x7f) {
ble_uart_tx_buf[ble_uart_buf_tx_fill] = pValue[i];
ble_uart_buf_tx_fill++;
} else if (pValue[i] == '\r' || pValue[i] == '\n') {
if (ble_uart_buf_tx_fill > 0) {
AttsSetAttr(
UART_TX_HDL,
ble_uart_buf_tx_fill,
ble_uart_tx_buf
);
if (active_connection) {
int x = xTaskGetTickCount() -
ble_uart_lasttick;
if (x < 100) {
// Ugly hack if we already send something recently.
// TODO: figure out how fast we can send or use indications
vTaskDelay(100 - x);
}
//printf("notify: ");
//int j;
//for(j=0;j<ble_uart_buf_tx_fill;j++) {
// printf("%02x ", ble_uart_tx_buf[j]);
//}
//printf("\n");
AttsHandleValueNtf(
active_connection,
UART_TX_HDL,
ble_uart_buf_tx_fill,
ble_uart_tx_buf
);
ble_uart_lasttick = xTaskGetTickCount();
}
ble_uart_buf_tx_fill = 0;
}
}
}
}
void bleuart_init(void)
{
/* Add the UART service dynamically */
void *pSHdl;
pSHdl = SvcUARTAddGroupDyn();
AttsDynRegister(pSHdl, UARTReadCback, UARTWriteCback);
//AttsDynRegister(pSHdl, NULL, UARTWriteCback);
/* Add the UART service dynamically */
void *pSHdl;
pSHdl = SvcUARTAddGroupDyn();
AttsDynRegister(pSHdl, UARTReadCback, UARTWriteCback);
//AttsDynRegister(pSHdl, NULL, UARTWriteCback);
}
......@@ -25,7 +25,7 @@
TaskHandle_t dispatcher_task_id;
void vBleTask(void*pvParameters);
void vBleTask(void *pvParameters);
/*
* API dispatcher task. This task will sleep until an API call is issued and
......@@ -105,16 +105,15 @@ int main(void)
abort();
}
/* BLE */
/* BLE */
if (xTaskCreate(
vBleTask,
(const char*)"BLE",
configMINIMAL_STACK_SIZE * 10,
NULL,
tskIDLE_PRIORITY + 1,
NULL
) != pdPASS) {
printf("Failed to create BLE task!\n");
vBleTask,
(const char *)"BLE",
configMINIMAL_STACK_SIZE * 10,
NULL,
tskIDLE_PRIORITY + 1,
NULL) != pdPASS) {
LOG_CRIT("startup", "Failed to create %s task!", "BLE");
abort();
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment