/*==================[internal functions definition]==========================*/
static void UPDT_configParse(const uint8_t *payload, size_t size, UPDT_configType *info)
{
   uint32_t word;
   const uint32_t *ptr;
   ciaaPOSIX_assert(NULL != payload);
   ciaaPOSIX_assert (NULL != info);

   ptr = (const uint32_t *) payload;

   word = ciaaLibs_utilsNtohl(*ptr);
   info->reserved1 = 0xFFu & (word >> 24);
   info->firmware_version = 0xFFFFFFu & (word);

   word = ciaaLibs_utilsNtohl(*(ptr + 1));
   info->bootloader_flags = 0xFFu & (word >> 24);
   info->bootloader_version = 0xFFFFFFu & (word);

   word = ciaaLibs_utilsNtohl(*(ptr + 2));
   info->reserved2 = 0xFFu & (word >> 24);
   info->application_version = 0xFFFFFFu & (word);

   word = ciaaLibs_utilsNtohl(*(ptr + 3));
   info->vendor_id = 0xFFu & (word >> 24);
   info->model_id = 0xFFFFFFu & (word);

   info->unique_id_high = ciaaLibs_setHigh (ptr+4);
   info->unique_id_low = ciaaLibs_setLow(ptr+4);

   info->data_size = ciaaLibs_utilsNtohl(*(ptr + 6));
}
/*==================[external functions definition]==========================*/
int32_t UPDT_slaveInit(UPDT_slaveType *slave, UPDT_ITransportType *transport)
{
   ciaaPOSIX_assert(NULL != slave);
   ciaaPOSIX_assert(NULL != transport);

   slave->transport = transport;
   slave->protocol_version = 0;
   slave->sequence_number = 0;
   slave->payload_size = 0;
   slave->done = 0;

   return 0;
}
/** \brief UPDT_configFormat stores in a buffer, in compacted format, the parameters of to data structure
 ** \param config_buffer is the buffer wherein the content of the structure is stored
 ** \param data_size is the number of elements that will have the buffer
 ** \param info is a variable of the type structure used to assemble the buffer
 **/
static void UPDT_configFormat (uint8_t *config_buffer,size_t data_size, UPDT_configType *type)
{
   ciaaPOSIX_assert(data_size == 32);
   /*Set of the field "reserved1" in the buffer*/
   ciaaLibs_SetByte (config_buffer,0,(type->reserved1));
   /*Set of the field "firmware_version" in the buffer*/
   ciaaLibs_SetUint24 (config_buffer,1,(type->firmware_version));
   /*Set of the field "bootloader_flags" in the buffer*/
   ciaaLibs_SetByte (config_buffer,4,(type->bootloader_flags));
   /*Set of the field "bootloader_version" in the buffer*/
   ciaaLibs_SetUint24 (config_buffer,5,(type->bootloader_version));
   /*Set of the field "reserved2" in the buffer*/
   ciaaLibs_SetByte (config_buffer,8,(type->reserved2));
   /*Set of the field "application_version" in the buffer*/
   ciaaLibs_SetUint24 (config_buffer,9,(type->application_version));
   /*Set of the field "vendor_id" in the buffer*/
   ciaaLibs_SetByte (config_buffer,12,(type->vendor_id));
   /*Set of the field "model_id" in the buffer*/
   ciaaLibs_SetUint24 (config_buffer,13,(type->model_id));
   /*Set of the field "unique_id" in the buffer*/
   #if CIAAPLATFORM_BIGENDIAN == 0
   ciaaLibs_SetUint32 (config_buffer,16,(type->unique_id_low));
   ciaaLibs_SetUint32 (config_buffer,20,(type->unique_id_high));
   #else
   ciaaLibs_SetUint32 (config_buffer,16,(type->unique_id_high));
   ciaaLibs_SetUint32 (config_buffer,20,(type->unique_id_low));
   #endif // CIAAPLATFORM_BIGENDIAN
   /*Set of the field "data_size" in the buffer*/
   ciaaLibs_SetUint32 (config_buffer,24,(type->data_size));
}
extern void ciaaBlockDevices_readIndication(ciaaDevices_deviceType const * const device, uint32_t const nbyte)
{
   /* get block device */
   ciaaBlockDevices_deviceType * blockDevice =
      (ciaaBlockDevices_deviceType*) device->layer;

   TaskType taskID = blockDevice->blocked.taskID;

   if ( (255 != taskID) &&
        ( (void*)ciaaBlockDevices_read == blockDevice->blocked.fct) )
   {
      /* invalidate task id */
      blockDevice->blocked.taskID = 255; /* TODO add macro */
      /* reset blocked function */
      blockDevice->blocked.fct = NULL;

#ifdef POSIXE
      /* set task event */
      SetEvent(taskID, POSIXE);
#else
#endif
   } else {
      /* this shall not happens */
      ciaaPOSIX_assert(0);
   }
}
static int32_t ciaaDriverFlash_blockWrite(uint32_t address, uint8_t const * const data, uint32_t size) {
   /* holds return values */
   int32_t ret;
   /* index used to iterate through the data */
   uint32_t data_index = -1;
   /* index used to iterate through the memory buffer */
   uint32_t buffer_index;
   /* size of data to be written */
   uint32_t write_size;
   ciaaDriverFlash_flashType * flash = &ciaaDriverFlash_flash;
   uint8_t buffer[CIAADRVFLASH_BLOCK_SIZE];

   if (address <= CIAADRVFLASH_SIZE)
   {
      data_index = 0;
      while(data_index < size)
      {
         /* calculate how much is to be written in this iteration */
         write_size = (data_index + CIAADRVFLASH_BLOCK_SIZE <= size) ? CIAADRVFLASH_BLOCK_SIZE : size - data_index;

         /* rewind to change i/o mode */
         rewind(flash->storage);

         /* seek the position to write in and bring its contents */
         ret = fseek(flash->storage, address + data_index, SEEK_SET);
         ciaaPOSIX_assert(0 == ret);
         ret = fread(buffer, 1, write_size, flash->storage);
         ciaaPOSIX_assert(ret == write_size);

         /* rewind to change i/o mode */
         rewind(flash->storage);

         /* seek the position to write in */
         ret = fseek(flash->storage, address + data_index, SEEK_SET);
         ciaaPOSIX_assert(0 == ret);

         /* perform the and operation between the block brought and the new data */
         for(buffer_index = 0; buffer_index < write_size; buffer_index++, data_index++)
            buffer[buffer_index] &= data[data_index];

         /* write in to the previously sought position */
         ret = fwrite(buffer, 1, write_size, flash->storage);
         ciaaPOSIX_assert(ret == write_size);
      }
   }
   return data_index;
}
/*==================[internal functions definition]==========================*/
static int32_t UPDT_slaveSendResponse(
   UPDT_slaveType *slave,
   const uint8_t* payload,
   size_t payload_size,
   uint8_t response_type)
{
   uint8_t *buffer;
   ciaaPOSIX_assert(NULL != slave);
   ciaaPOSIX_assert(NULL != payload);

   buffer = slave->send_buffer;
   UPDT_protocolSetHeader(buffer, response_type, slave->sequence_number, payload_size);

   ciaaPOSIX_memcpy(buffer + UPDT_PROTOCOL_HEADER_SIZE, payload, payload_size);

   return UPDT_protocolSend(slave->transport, buffer, UPDT_PROTOCOL_HEADER_SIZE + payload_size);
}
void UPDT_slaveClear(UPDT_slaveType *slave)
{
   ciaaPOSIX_assert(NULL != slave);

   slave->sequence_number = 0;
   slave->protocol_version = 0;
   slave->transport = NULL;
   slave->payload_size = 0;
   slave->done = 0;
}
extern ciaaDevices_deviceType * ciaaBlockDevices_open(char const * path,
      ciaaDevices_deviceType * device, uint8_t const oflag)
{
   ciaaBlockDevices_deviceType * blockDevice =
      (ciaaBlockDevices_deviceType*) device->layer;

   /* block devices does not support that the drivers update the device */
   /* the returned device shall be the same as passed */
   ciaaPOSIX_assert(blockDevice->device->open(path, (ciaaDevices_deviceType *)device->loLayer, oflag) == device->loLayer);

   return device;
}
extern ciaaDevices_deviceType * ciaaDioDevices_open(char const * path,
      ciaaDevices_deviceType * device,
      uint8_t const oflag)
{
   ciaaDevices_deviceType * drv = (ciaaDevices_deviceType*) device->loLayer;

   /* serial devices does not support that the drivers update the device */
   /* the returned device shall be the same as passed */
   ciaaPOSIX_assert(drv->open(path, drv, oflag) == drv);

   return device;
}
ssize_t UPDT_slaveRecvInfo(
   UPDT_slaveType *slave,
   uint8_t *payload_buffer,
   size_t buffer_size)
{
   /* holds return values */
   int32_t ret;
   /* received payload size */
   ssize_t payload_size = 0;
   /* received packet header */
   uint8_t header[UPDT_PROTOCOL_HEADER_SIZE];
   /* received sequence number */
   uint8_t sequence_number;

   ciaaPOSIX_assert(buffer_size >= UPDT_PROTOCOL_PAYLOAD_MAX_SIZE);


   do
   {
      /* receive header */
      /** \todo review the timeouts. In this state a timeout does not matter */
      ret = UPDT_protocolRecv(slave->transport, header, UPDT_PROTOCOL_HEADER_SIZE);
      if(UPDT_PROTOCOL_ERROR_NONE != ret)
      {
         /* transport layer error or timeout */
         return -1;
      }

      payload_size = UPDT_protocolGetPayloadSize(header);
      sequence_number = UPDT_protocolGetSequenceNumber(header);

      /* get the data packet and remove it from the buffer */

      ret = UPDT_protocolRecv(slave->transport, payload_buffer, payload_size);
      if(UPDT_PROTOCOL_ERROR_NONE != ret)
      {
         /* transport layer error or timeout */
         return -1;
      }
   }
   /* receive again if the packet is corrupted */
   while(UPDT_protocolGetPacketType(header) != UPDT_PROTOCOL_PACKET_INF);

   /* set the expected sequence number */
   slave->sequence_number = sequence_number + 1;

   return payload_size;
}
Пример #11
0
extern ciaaDevices_deviceType * ciaaSerialDevices_open(char const * path,
      ciaaDevices_deviceType * device, uint8_t const oflag)
{
   ciaaSerialDevices_deviceType * serialDevice =
      (ciaaSerialDevices_deviceType*) device->layer;

   /* serial devices does not support that the drivers update the device */
   /* the returned device shall be the same as passed */
   ciaaPOSIX_assert(serialDevice->device->open(path, (ciaaDevices_deviceType *)device->loLayer, oflag) == device->loLayer);

   if(oflag & O_NONBLOCK)
   {
      serialDevice->flags |= ciaaSerialDevices_NONBLOCK_MODE;
   }
   return device;
}
int32_t UPDT_configWrite(void)
{
   int32_t ret = -1;
   ciaaPOSIX_assert(UPDT_config_fd >= 0);

   /*To the previous configuration is assigned the new version of protocol and firmware, because
   it's the only change (the other parameters are kept)*/
   UPDT_config_old.firmware_version = (UPDT_config_new.firmware_version);
   UPDT_config_old.application_version = UPDT_config_new.application_version;

   /*Becomes the structure in an bytes sequence*/
   UPDT_configFormat(UPDT_config_buffer,28,&UPDT_config_old);

   /*function call to move the point to the memory address where it will be written*/
   if (ciaaPOSIX_lseek (UPDT_config_fd,UPDT_CONFIG_ADDRESS,SEEK_SET) == UPDT_CONFIG_ADDRESS);
   {
      ret = ciaaPOSIX_write (UPDT_config_fd,UPDT_config_buffer,28);
   }
   return ret;
}
/** \todo Go back to the initial state if an info packet is received */
ssize_t UPDT_slaveRecvData(
   UPDT_slaveType *slave,
   uint8_t *payload_buffer,
   size_t buffer_size)
{
   /* holds return values */
   int32_t ret;
   /* received payload size */
   ssize_t payload_size = 0;
   /* received packet header */
   uint8_t header[UPDT_PROTOCOL_HEADER_SIZE];
   /* received sequence number */
   uint8_t sequence_number;

   ciaaPOSIX_assert(buffer_size >= UPDT_PROTOCOL_PAYLOAD_MAX_SIZE);

   if(0 == slave->done)
   {
      do
      {
         /* receive header */
         ret = UPDT_protocolRecv(slave->transport, header, UPDT_PROTOCOL_HEADER_SIZE);
         if(UPDT_PROTOCOL_ERROR_NONE != ret)
         {
            /* transport layer error or timeout */
            return -1;
         }

         payload_size = UPDT_protocolGetPayloadSize(header);
         sequence_number = UPDT_protocolGetSequenceNumber(header);

         /* if the expected payload size does not match with the received */
         if(slave->payload_size != payload_size)
         {
            /* if this is the first packet */
            if(0 == slave->payload_size)
            {
               /* then set the expected payload size */
               slave->payload_size = payload_size;
            } else {
               /* this is the last packet */
               slave->done = 1;
            }
         }

         /* if we receive the same sequence number again */
         if(slave->sequence_number - 1 == sequence_number)
         {
            /* then ACK sent may be lost. does not matter the packet type */

            /* resend ACK */
            UPDT_slaveSendResponse(slave, slave->send_buffer, 0, UPDT_PROTOCOL_PACKET_ACK);
         }

         /* get the data packet and remove it from the buffer */
         ret = UPDT_protocolRecv(slave->transport, payload_buffer, payload_size);
         if(UPDT_PROTOCOL_ERROR_NONE != ret)
         {
            /* transport layer error or timeout */
            return -1;
         }
      }
      /* receive again if the packet is corrupted */
      while(UPDT_protocolGetPacketType(header) != UPDT_PROTOCOL_PACKET_DAT ||
            slave->sequence_number != sequence_number);

      /* increment expected sequence number */
      ++slave->sequence_number;

      /* send acknowledge */
      UPDT_slaveSendResponse(slave, slave->send_buffer, 0, UPDT_PROTOCOL_PACKET_ACK);
   }

   return payload_size;
}
static uint32_t testDataOk(uint8_t *vector)
{
   ciaaPOSIX_assert (UPDT_PROTOCOL_PACKET_ACK == UPDT_protocolGetPacketType(vector));
   ciaaPOSIX_assert (SequenceNumber==UPDT_protocolGetSequenceNumber(vector));
   return 0;
}
static uint32_t testHandshakeOkNextSequenceNumber(test_updt_configType *type, uint8_t *vector)
{
   ciaaPOSIX_assert (UPDT_PROTOCOL_PACKET_ACK == UPDT_protocolGetPacketType(vector));
   ciaaPOSIX_assert (SequenceNumber == UPDT_protocolGetSequenceNumber(vector));
   return 0;
}