extern size_t ciaaLibs_circBufWriteTo(ciaaLibs_CircBufType * cbuf, int32_t filDes, size_t nbytes) { size_t rawCount; /* the tail of the circular buffer my be changed, therefore it has to be * read only once */ size_t tail = cbuf->tail; /* if the users tries to read to much data, only available data will be * provided */ if (nbytes > ciaaLibs_circBufCount(cbuf, tail)) { nbytes = ciaaLibs_circBufCount(cbuf, tail); } /* check if data to be read */ if (nbytes > 0) { rawCount = ciaaLibs_circBufRawCount(cbuf, tail); /* check if all data can be read without wrapping */ if (nbytes <= rawCount) { ciaaPOSIX_write(filDes, ciaaLibs_circBufReadPos(cbuf), nbytes); } else { ciaaPOSIX_write(filDes, ciaaLibs_circBufReadPos(cbuf), rawCount); ciaaPOSIX_write(filDes, (void*)(&cbuf->buf[0]), nbytes-rawCount); } } return nbytes; } /* end ciaaLibs_circBufWriteTo */
/** \brief test: ** - ciaaLibs_circBufSpace ** - ciaaLibs_circBufRawSpace ** - ciaaLibs_circBufCount ** - ciaaLibs_circBufRawCount **/ void test_ciaaLibs_circBufSpaceAndCount(void) { ciaaLibs_CircBufType * cbuf; char * data = "hallo world 123456789012345678901234567890213456789012345678901234567890"; char to[100]; size_t ret; /* use linux malloc */ ciaaPOSIX_malloc_StubWithCallback(malloc); ciaaPOSIX_memcpy_StubWithCallback(memcpy); /* try to create a buffer but no mem is available */ cbuf = ciaaLibs_circBufNew(64); TEST_ASSERT_TRUE(cbuf != NULL); /* 63 bytes shall be free */ TEST_ASSERT_EQUAL_INT(63, ciaaLibs_circBufSpace(cbuf, cbuf->head)); TEST_ASSERT_EQUAL_INT(63, ciaaLibs_circBufRawSpace(cbuf, cbuf->head)); /* 0 bytes shall be occupied */ TEST_ASSERT_EQUAL_INT(0, ciaaLibs_circBufCount(cbuf, cbuf->tail)); TEST_ASSERT_EQUAL_INT(0, ciaaLibs_circBufRawCount(cbuf, cbuf->tail)); /* put 40 bytes */ TEST_ASSERT_TRUE(40 == ciaaLibs_circBufPut(cbuf, data, 40)); /* 23 bytes shall be free */ TEST_ASSERT_EQUAL_INT(23, ciaaLibs_circBufSpace(cbuf, cbuf->head)); TEST_ASSERT_EQUAL_INT(23, ciaaLibs_circBufRawSpace(cbuf, cbuf->head)); /* 40 bytes shall be occupied */ TEST_ASSERT_EQUAL_INT(40, ciaaLibs_circBufCount(cbuf, cbuf->tail)); TEST_ASSERT_EQUAL_INT(40, ciaaLibs_circBufRawCount(cbuf, cbuf->tail)); /* get 30 bytes */ ret = ciaaLibs_circBufGet(cbuf, to, 30); TEST_ASSERT_EQUAL_INT(30, ret); /* 53 bytes shall be free */ TEST_ASSERT_EQUAL_INT(53, ciaaLibs_circBufSpace(cbuf, cbuf->head)); TEST_ASSERT_EQUAL_INT(24, ciaaLibs_circBufRawSpace(cbuf, cbuf->head)); /* 10 bytes shall be occupied */ TEST_ASSERT_EQUAL_INT(10, ciaaLibs_circBufCount(cbuf, cbuf->tail)); TEST_ASSERT_EQUAL_INT(10, ciaaLibs_circBufRawCount(cbuf, cbuf->tail)); /* put 50 */ TEST_ASSERT_EQUAL_INT(50, ciaaLibs_circBufPut(cbuf, data, 50)); /* 3 bytes shall be free */ TEST_ASSERT_EQUAL_INT(3, ciaaLibs_circBufSpace(cbuf, cbuf->head)); TEST_ASSERT_EQUAL_INT(3, ciaaLibs_circBufRawSpace(cbuf, cbuf->head)); /* 60 bytes shall be occupied */ TEST_ASSERT_EQUAL_INT(60, ciaaLibs_circBufCount(cbuf, cbuf->tail)); TEST_ASSERT_EQUAL_INT(34, ciaaLibs_circBufRawCount(cbuf, cbuf->tail)); /* free memory */ free(cbuf); }
/** \brief print debuf information of a circular buffer ** ** Print into screen: free space, raw free space, ** count of occupied bytes, raw count of occupied bytes ** position of head and tail and the buffer content. ** **/ void ciaaLibs_circBufPrint(ciaaLibs_CircBufType * cbuf) { printf("Free: %2d RFree: %2d Count: %2d RCount: %2d\n", ciaaLibs_circBufSpace(cbuf, cbuf->head), ciaaLibs_circBufRawSpace(cbuf, cbuf->head), ciaaLibs_circBufCount(cbuf, cbuf->tail), ciaaLibs_circBufRawCount(cbuf, cbuf->tail)); printf(" 0123456789012345678901234567890123456789012345678901234567890123\n"); printf("Head: %2d Tail: %2d Val:%s\n\n", cbuf->head, cbuf->tail, cbuf->buf); }
extern void ciaaSerialDevices_txConfirmation(ciaaDevices_deviceType const * const device, uint32_t const nbyte) { /* get serial device */ ciaaSerialDevices_deviceType * serialDevice = (ciaaSerialDevices_deviceType*) device->layer; uint32_t write = 0; ciaaLibs_CircBufType * cbuf = &serialDevice->txBuf; uint32_t tail = cbuf->tail; uint32_t rawCount = ciaaLibs_circBufRawCount(cbuf, tail); uint32_t count = ciaaLibs_circBufCount(cbuf, tail); TaskType taskID = serialDevice->blocked.taskID; /* if some data have to be transmitted */ if (count > 0) { /* write data to the driver */ write = serialDevice->device->write(device->loLayer, ciaaLibs_circBufReadPos(cbuf), rawCount); /* update buffer */ ciaaLibs_circBufUpdateHead(cbuf, write); /* if all bytes were written and more data is available */ if ( (write == rawCount) && (count > rawCount ) ) { /* re calculate rawCount */ rawCount = ciaaLibs_circBufRawCount(cbuf, tail); /* write more bytes */ write = serialDevice->device->write(device->loLayer, ciaaLibs_circBufReadPos(cbuf), rawCount); if (write > 0) { /* update buffer */ ciaaLibs_circBufUpdateHead(cbuf, write); } } /* if task is blocked and waiting for reception of this device */ if ( (255 != taskID) && (serialDevice->blocked.fct == (void*) ciaaSerialDevices_write) ) { /* invalidate task id */ serialDevice->blocked.taskID = 255; /* TODO add a macro */ /* reset function */ serialDevice->blocked.fct = NULL; /* set task event */ #ifdef POSIXE SetEvent(taskID, POSIXE); #endif } } }
extern size_t ciaaLibs_circBufGet(ciaaLibs_CircBufType * cbuf, void * data, size_t nbytes) { size_t rawCount; /* the tail of the circular buffer my be changed, therefore it has to be * read only once */ size_t tail = cbuf->tail; /* if the users tries to read to much data, only available data will be * provided */ if (nbytes > ciaaLibs_circBufCount(cbuf, tail)) { nbytes = ciaaLibs_circBufCount(cbuf, tail); } /* check if data to be read */ if (nbytes > 0) { rawCount = ciaaLibs_circBufRawCount(cbuf, tail); /* check if all data can be read without wrapping */ if (nbytes <= rawCount) { ciaaPOSIX_memcpy(data, ciaaLibs_circBufReadPos(cbuf), nbytes); } else { ciaaPOSIX_memcpy(data, ciaaLibs_circBufReadPos(cbuf), rawCount); ciaaPOSIX_memcpy((void*)((intptr_t)data + rawCount), (void*)(&cbuf->buf[0]), nbytes-rawCount); } /* calculates new head position */ ciaaLibs_circBufUpdateHead(cbuf, nbytes); } return nbytes; } /* end ciaaLibs_circBufGet */
extern int32_t ciaaSerialDevices_ioctl(ciaaDevices_deviceType const * const device, int32_t request, void* param) { int32_t ret = 0; ciaaSerialDevices_deviceType * serialDevice = (ciaaSerialDevices_deviceType *) device->layer; ciaaLibs_CircBufType * cbuf; uint32_t tail, head; switch(request) { case ciaaPOSIX_IOCTL_GET_RX_COUNT: cbuf = &serialDevice->rxBuf; tail = cbuf->tail; *(uint32_t *)param = ciaaLibs_circBufCount(cbuf, tail); ret = 0; break; case ciaaPOSIX_IOCTL_GET_TX_SPACE: cbuf = &serialDevice->txBuf; head = cbuf->head; *(uint32_t *)param = ciaaLibs_circBufSpace(cbuf, head); ret = 0; break; case ciaaPOSIX_IOCTL_RXINDICATION: break; case ciaaPOSIX_IOCTL_SET_NONBLOCK_MODE: if((bool)(intptr_t)param == false) { /* Blocking mode */ serialDevice->flags &= ~ciaaSerialDevices_NONBLOCK_MODE; } else { /* NonBlocking Mode */ serialDevice->flags |= ciaaSerialDevices_NONBLOCK_MODE; } ret = 0; break; default: ret = serialDevice->device->ioctl(device->loLayer, request, param); break; } return ret; }