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);
}
示例#4
0
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
      }
   }
}
示例#5
0
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 */
示例#6
0
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;
}