ISF  2.2 rev 5
Intelligent Sensing Framework for Kinetis with Processor Expert
ci_protocol_stream.c
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2015, Freescale Semiconductor, Inc.
4  *
5 */
6 
7 /*!
8  * @file ci_protocol_stream.c
9  *
10  * @brief Stream protocol source file that implemments the streaming functionality.
11  *
12  */
13 
14 
15 #include "isf_target.h"
16 #include "isf.h"
17 #include "isf_ci.h"
18 #include "fsl_os_abstraction.h"
19 #include "task_ci.h"
20 #include "ci_protocol_stream.h"
21 #include "isf_ci_stream.h"
22 #include "isf_util.h"
23 #include "crc.h"
24 
25 
26 // This semaphore is used for critical section.
27 
28 static semaphore_t ci_sema_stream;
29 // Top level stream list pointer.
30 static ci_stream_instance_t *gpStreamFirstInstance; // Points to first instance in the instance list.
31 static ci_stream_instance_t *gpStreamNextInstance; // Pointer used to traverse the instance list.
32 
33 // Stream registers.
34 static ci_stream_regs_t gStreamReg;
35 
36 // HDLC protocol id for the CI protocol. The ID is passed into the init
37 // function which then stores it in this variable for later use.
38 static uint8 ci_protocol_stream_id = 0;
39 
40 
41 
42 
43 
44 // Internal functions.
45 static ci_stream_config_t *ci_stream_get_config(uint8 aStreamID);
46 static ci_stream_instance_t *ci_stream_get_instance(uint8 aStreamID);
47 static uint32 ci_stream_get_streambuffer_offset(uint8 aElementIndex, uint8 aNumElements, ci_stream_element_t *apElementList);
48 static uint32 ci_stream_get_output_packet_size(uint8 aNumElements, ci_stream_element_t *apElementList);
49 static uint32 ci_stream_get_config_payload_size(uint8 aNumElements, ci_stream_element_t *apElementList);
50 static uint8 ci_stream_get_num_instances(void);
51 static ci_stream_instance_t *ci_stream_get_last_instance(void);
52 static ci_stream_config_t *ci_stream_create_config_buf(boolean aCreateTrigElementBytes,
53  uint8 anumElements, uint32 *apnumBytesAlloc);
54 static isf_status_t ci_stream_internal_init(void *apInitData);
55 
56 
59 
60 
61 // Calculate the nubmer of bytes needed for the trigger mask/state.
62 inline uint32 ci_stream_get_num_trig_bytes(uint8 anumElements) { \
63  uint32 num_bytes = anumElements / 8; \
64  if ( (anumElements ) > 0) \
65  ++num_bytes; \
66  return num_bytes; \
67 }
68 
69 // Calculate the number of bytes needed for the element list.
71  return (uint32)(anumElements * (sizeof(ci_stream_element_t))); \
72 }
73 
74 // An inline utility function to swap two bytes.
75 extern void byteswap(uint8 *p1, uint8 *p2);
76 //__inline void byteswap(uint8 *p1, uint8 *p2) { IAR_INT
77 void byteswap(uint8 *p1, uint8 *p2) {
78  uint8 temp = *p1; *p1 = *p2; *p2 = temp;
79 }
80 
81 
82 
83 
84 // CI stream initialization. One time initialization.
85 isf_status_t ci_stream_init(uint8 aprotocolID, void *apInitData)
86 {
87 
89 
90  // Set the id for this protocol.
91  ci_protocol_stream_id = aprotocolID;
92  if (OSA_SemaCreate(&ci_sema_stream, 1) != ISF_SUCCESS)
93  ret = ISF_ERR_LIB_INIT;
94 
95  // Do internal init.
96  ci_stream_internal_init(apInitData);
97 
98  return ret;
99 }
100 
101 // CI stream internal initialization that is called during reset.
102 isf_status_t ci_stream_internal_init(void *apInitData)
103 {
105 
106  // Init the registers.
107  gStreamReg.StreamCtrlReg1.ctrl_reg1 = 0;
108 
109  gpStreamFirstInstance = NULL;
110  gpStreamNextInstance = NULL;
111 
112  return ret;
113 }
114 
115 
116 
117 
119 {
120  ci_stream_config_t *pConfig = NULL;
121  OSA_SemaWait(&ci_sema_stream, OSA_WAIT_FOREVER);
122  gpStreamNextInstance = NULL;
123  if (gpStreamFirstInstance != NULL)
124  {
125  gpStreamNextInstance = gpStreamFirstInstance->pNextInstance;
126  pConfig = gpStreamFirstInstance->pStreamConfig;
127  }
128  OSA_SemaPost(&ci_sema_stream);
129  return pConfig;
130 }
131 
132 
134 {
135 
136  ci_stream_config_t *pConfig = NULL;
137 
138  OSA_SemaWait(&ci_sema_stream, OSA_WAIT_FOREVER);
139 
140  if (gpStreamNextInstance != NULL)
141  {
142  pConfig = gpStreamNextInstance->pStreamConfig;
143  gpStreamNextInstance = gpStreamNextInstance->pNextInstance;
144  }
145 
146  OSA_SemaPost(&ci_sema_stream);
147 
148  return pConfig;
149 
150 }
151 
152 
154 {
155 
156  ci_stream_config_t *pStreamConfig = NULL;
157 
158  OSA_SemaWait(&ci_sema_stream, OSA_WAIT_FOREVER);
159 
160  pStreamConfig = ci_stream_get_config(aStreamID);
161 
162  OSA_SemaPost(&ci_sema_stream);
163 
164  return pStreamConfig;
165 }
166 
167 
169 {
170 
172 
173  if (gpStreamFirstInstance == NULL)
175 
176 
177  OSA_SemaWait(&ci_sema_stream, OSA_WAIT_FOREVER);
178 
179 
180  // Find the instance with matching stream ID.
181  ci_stream_instance_t *pInstTarget = ci_stream_get_instance(aStreamID);
182  if (pInstTarget != NULL)
183  {
184  // The given stream ID exists. Delete it.
185  if (ci_stream_get_num_instances() > 1)
186  {
187 
188  if (gpStreamFirstInstance == pInstTarget)
189  {
190  // Target instance is first in list. Point the header to the next one.
191  gpStreamFirstInstance = pInstTarget->pNextInstance;
192  }
193  else
194  {
195  // Target instance is somewhere in the middle or at the end.
196 
197  ci_stream_instance_t *pInstBef = gpStreamFirstInstance;
198  ci_stream_instance_t *pInstCur = gpStreamFirstInstance;
199  do
200  {
201  if (pInstCur != pInstTarget)
202  {
203  // Increment one instance.
204  pInstBef = pInstCur;
205  pInstCur = pInstCur->pNextInstance;
206  }
207  else
208  {
209  // The instance behind the target points to the instance after the target instance.
210  pInstBef->pNextInstance = pInstTarget->pNextInstance;
211  break;
212  }
213 
214  } while(1);
215  }
216  }
217  else
218  {
219  // Only one instance in list.
220  gpStreamFirstInstance = NULL;
221  }
222 
223 
224  // Dealloc configuration and instance.
225  CI_FREE_MEM(pInstTarget->pStreamConfig);
226  CI_FREE_MEM(pInstTarget);
227 
228  }
229  else
230  {
231  // Did not find stream ID.
233  }
234 
235  OSA_SemaPost(&ci_sema_stream);
236 
237  return ret;
238 }
239 
240 
241 
242 
243 isf_status_t isf_ci_stream_create(uint8 aStreamID, uint8 aNumElements, uint8 *apTriggerMask, ci_stream_element_t *apElementList)
244 {
245 
247 
248 
249  if ( (apTriggerMask == NULL) || (apElementList == NULL) )
251 
252  if (aNumElements == 0)
254 
255 
256  OSA_SemaWait(&ci_sema_stream, OSA_WAIT_FOREVER);
257 
258 
259  // Check for duplicate stream ID.
260  if (ci_stream_get_config(aStreamID) != NULL) // Use the internal version without semaphore.
261  {
262  // Error: A config was found with matching stream ID.
263  OSA_SemaPost(&ci_sema_stream);
265  }
266 
267 
268  uint32 totalbytes;
269  uint32 num_trigmask_bytes = 0;
270  uint32 num_element_bytes = 0;
271 
272  num_trigmask_bytes = ci_stream_get_num_trig_bytes(aNumElements);
273  num_element_bytes = ci_stream_get_num_element_bytes(aNumElements);
274 
275 
276  // Create buffer for config and associated data.
277  ci_stream_config_t *pNewStreamConfig = ci_stream_create_config_buf(TRUE, aNumElements, NULL);
278 
279 
280 
281  // Create buffer for stream instance and associated data.
282  // Total bytes for instance and associated data includes:
283  //
284  // sizeof(ci_stream_instance_t) <- pStreamInstance
285  // Num trigger state bytes <- pTriggerState
286  // Stream output packet <- pStreamBuffer
287  // Stream protocol ID
288  // Command status <- Contains COCO bit set and CI_STATUS_STREAM_DATA_UPDATE status
289  // Stream ID
290  // Length
291  // Payload
292  // DatasetID/data
293  // DatasetID/data
294  // ...
295  // CRC (NOTE: CRC bytes are added so that host can dynamically enable/disable CRC generation/checking).
296 
297  totalbytes =
298  sizeof(ci_stream_instance_t)
299  + num_trigmask_bytes // Trigger state bytes
300  + ci_stream_get_output_packet_size(aNumElements, apElementList)
301  // Output packet:
302  // Stream protocol
303  // Command status
304  // Stream ID
305  // Length
306  // Payload (continuous stream of datasetID and data)
307  + STREAM_CRC_BYTESIZE; // CRC (NOTE: CRC bytes are added so that host can dynamically
308  // enable/disable CRC generation/checking).
309 
310  ci_stream_instance_t *pNewStreamInstance = CI_ALLOC_MEM_ZERO(totalbytes);
311 
312  if ( (pNewStreamConfig == NULL) || (pNewStreamInstance == NULL) )
313  {
314  // Error: Failed to alloc memory needed. Back out of the alloc that succeeded.
315 
316  if (pNewStreamConfig != NULL)
317  CI_FREE_MEM(pNewStreamInstance);
318 
319  if (pNewStreamInstance != NULL)
320  CI_FREE_MEM((uint8 *)pNewStreamConfig);
321 
323 
324  }
325  else
326  {
327 
328  // -------------------------------
329  // Stream config
330 
331  // Copy ID and number of elements.
332  pNewStreamConfig->streamID = aStreamID;
333  pNewStreamConfig->numElements = aNumElements;
334 
335  // Copy element list.
336  CI_COPY_MEM(apElementList, pNewStreamConfig->pElementList, num_element_bytes);
337 
338 
339  // For trigger bytes, copy by ORing in only the bits correspond to a dataset.
340  // For unused bits, they remain zero.
341  {
342  uint32 element_index = 0;
343 
344  // Note that when the memory buffer was created, the memory content are zeros.
345  // So all trigger bytes start out with zeros to indicate no trigger.
346 
347  while(element_index < aNumElements)
348  {
349  uint32 trigbyte_index = element_index / 8;
350  uint8 bitmask = element_index - (trigbyte_index * 8);
351 
352  // If user trigger bit is set, then OR it in.
353  pNewStreamConfig->pTriggerMask[trigbyte_index] |= (apTriggerMask[trigbyte_index] & (uint8)(1 << bitmask));
354 
355  ++element_index;
356  }
357  }
358 
359  // -------------------------------
360  // Stream instance
361 
362  // Init the trigger state/transaction pointer.
363  pNewStreamInstance->pTriggerState = (uint8 *)((uint32)pNewStreamInstance + (uint32)sizeof(ci_stream_instance_t));
364 
365 
366  // Copy trigger state/transaction which is the trigger mask from the given config. Note that we
367  // copy trigger bytes from the new configuration just created because those bytes have unused
368  // trigger bits masked out.
369  CI_COPY_MEM(pNewStreamConfig->pTriggerMask, pNewStreamInstance->pTriggerState, num_trigmask_bytes);
370 
371 
372  // The stream buffer points to the allocated buffer containing the output packet header and the data.
373  // This buffer is designed so that when an app performs a data update to the host, the entire buffer
374  // can be sent as-is.
375  //
376  // Stream output packet
377  // Stream protocol ID <- pStreamBuffer
378  // Command status <- Contains COCO bit set and CI_STATUS_STREAM_DATA_UPDATE status
379  // Stream ID
380  // Length
381  // Payload
382  // DatasetID/data
383  // DatasetID/data
384  pNewStreamInstance->pStreamBuffer = (uint8 *)((uint32)pNewStreamInstance->pTriggerState + num_trigmask_bytes);
385 
386 
387 
388  // Insert the dataset ID into the buffer for each dataset. Doing this ahead to
389  // save time during update data process.
390  {
391  uint32 element_index = 0;
392  ci_stream_element_t *pElement = pNewStreamConfig->pElementList;
393 
394  while(element_index < pNewStreamConfig->numElements)
395  {
396 
397  // Get the offset into the stream buffer to get to the location where the
398  // dataset resides.
399  uint8 *pDest = (uint8 *)
400  (
401  (uint32)pNewStreamInstance->pStreamBuffer +
402  ci_stream_get_streambuffer_offset(
403  element_index,
404  pNewStreamConfig->numElements,
405  pNewStreamConfig->pElementList) );
406 
407  // Init the dataset ID.
408  *pDest = pElement[element_index].datasetID;
409 
410  ++element_index;
411  }
412  }
413 
414  // Point to the new config.
415  pNewStreamInstance->pStreamConfig = pNewStreamConfig;
416  // Terminate the instance.
417  pNewStreamInstance->pNextInstance = NULL;
418 
419 
420  // Prepare the stream buffer header information.
421  pNewStreamInstance->pStreamBuffer[STREAM_PROTOCOL_OUTPUTPACKET_INDEX_PROTOCOLID] = ci_protocol_stream_id;
423  pNewStreamInstance->pStreamBuffer[STREAM_PROTOCOL_OUTPUTPACKET_INDEX_STREAMID] = aStreamID;
424 
425  // Enter the payload length (payload length is the size of the bytes to store the dataset ID and the data itself
426  // for each dataset).
427  uint16 len = (uint16)ci_stream_get_config_payload_size(pNewStreamConfig->numElements, pNewStreamConfig->pElementList);
428  pNewStreamInstance->pStreamBuffer[STREAM_PROTOCOL_OUTPUTPACKET_INDEX_LENGTH_MSB] = (uint8)((len >> 8) & 0xFF); // msb first
429  pNewStreamInstance->pStreamBuffer[STREAM_PROTOCOL_OUTPUTPACKET_INDEX_LENGTH_LSB] = (uint8)(len & 0xFF); // lsb last
430 
431  // Attached this instance to the end of the chain.
432  ci_stream_instance_t *pLastInstance = ci_stream_get_last_instance();
433 
434  if (pLastInstance == NULL)
435  // First instance in the list.
436  gpStreamFirstInstance = pNewStreamInstance;
437  else
438  pLastInstance->pNextInstance = pNewStreamInstance;
439 
440  }
441  OSA_SemaPost(&ci_sema_stream);
442 
443  return ret;
444 }
445 
446 
447 // - Loop through all streams. Any matching data set ID will get updated.
448 // - For each stream, if triggers are all zeros and at least one dataset was updated, then send data to host.
449 isf_status_t isf_ci_stream_update_data(uint8 aDataSetID, uint16 aLength, uint16 aOffset, uint8 *apSrc)
450 {
451 
452 
453  isf_status_t ret = ISF_SUCCESS;
454  ci_stream_instance_t *pStreamInstance = NULL;
455  uint8 num_dataset_updated_total = 0; // Total accross all streams.
456 
457 
458  if (apSrc == NULL)
460 
461  if (aLength == 0)
463 
464 
465  OSA_SemaWait(&ci_sema_stream, OSA_WAIT_FOREVER);
466 
467 
468  // Get the first instance.
469  pStreamInstance = gpStreamFirstInstance;
470 
471  // For any stream that has a matching data set, update it.
472  while (pStreamInstance != NULL)
473  {
474 
475  ci_stream_element_t *pElement = pStreamInstance->pStreamConfig->pElementList;
476  uint32 element_index = 0;
477  uint32 trigbyte_index = 0;
478  uint8 num_dataset_updated = 0;
479 
480 
481  while(element_index < pStreamInstance->pStreamConfig->numElements)
482  {
483 
484  trigbyte_index = element_index / 8;
485 
486  // Update data set if ID matches.
487  if (pElement[element_index].datasetID == aDataSetID)
488  {
489  // Data set matched.
490 
491  // Check if the data being updated by the caller overlaps with
492  // the data set region.
493 
494  // Make is easier for clarity and on the typing.
495  uint32 dataset_start = (uint32)pElement[element_index].offset;
496  uint32 dataset_end = (uint32)pElement[element_index].length + dataset_start;
497  uint32 src_start = aOffset;
498  uint32 src_end = src_start + aLength;
499 
500  // The two conditions checked here will ensure that there is an overlap between
501  // the source region and the dataset region.
502  if (
503 
504  // The dataset start location must be less than the end of the source region.
505  (dataset_start < src_end)
506 
507  &&
508  // The dataste end location must be greater than the start of the source region.
509  (dataset_end > src_start)
510  )
511  {
512 
513  // Adjust the source area to copy based on data set area.
514  if (src_start <= dataset_start)
515  src_start = dataset_start;
516  if (src_end >= dataset_end)
517  src_end = dataset_end;
518 
519  // Recalculate the length
520  uint16 len = src_end - src_start;
521 
522  // Get offset to the source data and length.
523  uint8 *pSrc = (uint8 *)((uint32)apSrc + src_start);
524 
525  // Get pointer to where dataset data buffer resides in the instance.
526  uint8 *pDest = (uint8 *)
527  (
528  CI_STREAM_DATASET_ID_BYTESIZE + // Note that byte(s) for dataset ID which was already
529  // populated when the stream was created.
530  (uint32)pStreamInstance->pStreamBuffer +
531  ci_stream_get_streambuffer_offset(
532  element_index,
533  pStreamInstance->pStreamConfig->numElements,
534  pStreamInstance->pStreamConfig->pElementList)
535  );
536 
537  if (dataset_start < src_start)
538  {
539  // Movie dest pointer up to where source data starts.
540  pDest = (uint8 *)( (uint32)pDest + (src_start - dataset_start) );
541  }
542 
543  CI_COPY_MEM(pSrc, pDest, len);
544 
545  // Data has been updated. Clear the trigger state bit for this dataset.
546  uint8 bitmask = element_index - (trigbyte_index * 8);
547  pStreamInstance->pTriggerState[trigbyte_index] &= ~(uint8)(1 << bitmask);
548 
549  // Increment match.
550  ++num_dataset_updated;
551 
552  }
553  }
554 
555  ++element_index;
556  }
557 
558 
559  // Send data if triggers are zeros and at least one dataset was updated and stream is enabled.
560  if ( (num_dataset_updated > 0) && (gStreamReg.StreamCtrlReg1.Bits.enable_stream_data == STREAM_PROTOCOL_DATA_ENABLED) )
561  {
562 
563  uint16 num_trigger_bytes = ci_stream_get_num_trig_bytes(pStreamInstance->pStreamConfig->numElements);
564  boolean bSendDataToHost = TRUE;
565 
566  // Check all the trigger bytes. If any of the values are non-zero, then DO NOT send data to host.
567  trigbyte_index = 0;
568  do
569  {
570  if (pStreamInstance->pTriggerState[trigbyte_index] != 0)
571  bSendDataToHost = FALSE;
572  } while(++trigbyte_index < num_trigger_bytes);
573 
574 
575  if (bSendDataToHost == TRUE)
576  {
577  // All trigger bits cleared. Send data to host.
578 
579  uint32 num_bytes = ( ((uint16)pStreamInstance->pStreamBuffer[STREAM_PROTOCOL_OUTPUTPACKET_INDEX_LENGTH_MSB] << 8)
580  | ((uint16)pStreamInstance->pStreamBuffer[STREAM_PROTOCOL_OUTPUTPACKET_INDEX_LENGTH_LSB] << 0) );
581  num_bytes += ( CI_STREAM_PROTOCOL_ID_BYTESIZE
585 
586 
588  {
589  uint16 crc16;
590  crc16 = ccitt_crc16_cal(num_bytes, pStreamInstance->pStreamBuffer);
591  pStreamInstance->pStreamBuffer[num_bytes] = (uint8)( (crc16 >> 8) & 0xff); // Msb first
592  pStreamInstance->pStreamBuffer[num_bytes+1] = (uint8)( (crc16 >> 0) & 0xff); // Lsb second
593 
594  num_bytes += STREAM_CRC_BYTESIZE;
595  }
596 
597 
598  // Send stream.
599  if (ci_send_packet(num_bytes, pStreamInstance->pStreamBuffer) != ISF_SUCCESS)
600  {
601  // Error
603  }
604  else
605  {
607 
608  // Reset the trigger only if data was sent successfully.
609  CI_COPY_MEM(pStreamInstance->pStreamConfig->pTriggerMask, pStreamInstance->pTriggerState, num_trigger_bytes);
610  }
611 
612  }
613 
614  }
615 
616  num_dataset_updated_total += num_dataset_updated;
617 
618  pStreamInstance = pStreamInstance->pNextInstance;
619  }
620 
621 
622  if ( (ret == ISF_SUCCESS) && (num_dataset_updated_total == 0) )
623  {
624  // No dataset was updated.
626  }
627 
628 
629  OSA_SemaPost(&ci_sema_stream);
630 
631  return ret;
632 
633 }
634 
635 
636 
637 
638 // Get the number of instances in the stream list.
640 {
641 
642  uint8 num_instances = 0;
643 
644  OSA_SemaWait(&ci_sema_stream, OSA_WAIT_FOREVER);
645 
646 
647  num_instances = ci_stream_get_num_instances();
648 
649  OSA_SemaPost(&ci_sema_stream);
650 
651  return num_instances;
652 }
653 
654 
655 
657 {
658 
659  isf_status_t ret = ISF_SUCCESS;
660  ci_stream_instance_t *pStreamInstance = NULL;
661 
662 
663  if (apTrigger == NULL)
664  return CI_STATUS_STREAM_ERR;
665 
666 
667  OSA_SemaWait(&ci_sema_stream, OSA_WAIT_FOREVER);
668 
669  pStreamInstance = ci_stream_get_instance(aStreamID);
670 
671  if (pStreamInstance != NULL)
672  {
673  uint32 num_trigger_bytes = ci_stream_get_num_trig_bytes(pStreamInstance->pStreamConfig->numElements);
674  uint32 i = 0;
675 
676  do
677  {
678  apTrigger[i] = pStreamInstance->pTriggerState[i];
679  } while(++i < num_trigger_bytes);
680 
681  }
682  else
683  {
685  }
686 
687  OSA_SemaPost(&ci_sema_stream);
688 
689  return ret;
690 }
691 
692 
694 {
695  isf_status_t ret = ISF_SUCCESS;
696  ci_stream_instance_t *pStreamInstance = NULL;
697 
698 
699  OSA_SemaWait(&ci_sema_stream, OSA_WAIT_FOREVER);
700 
701  pStreamInstance = ci_stream_get_instance(aStreamID);
702 
703  if (pStreamInstance != NULL)
704  {
705  uint32 num_trigger_bytes = ci_stream_get_num_trig_bytes(pStreamInstance->pStreamConfig->numElements);
706  uint32 i = 0;
707 
708  do
709  {
710  pStreamInstance->pTriggerState[i] = pStreamInstance->pStreamConfig->pTriggerMask[i];
711  } while(++i < num_trigger_bytes);
712 
713  }
714  else
715  {
717  }
718 
719  OSA_SemaPost(&ci_sema_stream);
720 
721  return ret;
722 }
723 
724 
725 void isf_ci_stream_set_CRC(boolean acrcEnable)
726 {
727 
728  OSA_SemaWait(&ci_sema_stream, OSA_WAIT_FOREVER);
729 
730  // Set CRC enable state.
731  if (acrcEnable > 0)
733  else
735 
736  OSA_SemaPost(&ci_sema_stream);
737 
738 }
739 
740 
741 
742 
743 
744 
745 //###########################################################################
746 //###########################################################################
747 // Internal functions. Note that internal functions are designed to be called
748 // by top level api functions and they depend on the caller to perform critical
749 // sections (for those functions that access global stream data).
750 
751 
752 static ci_stream_config_t *ci_stream_get_config(uint8 aStreamID)
753 {
754 
755  ci_stream_config_t *pStreamConfig = NULL;
756  ci_stream_instance_t *pStreamInstance;
757 
758  if (gpStreamFirstInstance != NULL)
759  {
760 
761  pStreamInstance = gpStreamFirstInstance;
762  do
763  {
764 
765  if (pStreamInstance->pStreamConfig->streamID == aStreamID)
766  {
767  // Found the config.
768  pStreamConfig = pStreamInstance->pStreamConfig;
769  }
770  else
771  {
772  // Not a match, move to next instance.
773  pStreamInstance = pStreamInstance->pNextInstance;
774  }
775 
776  } while((pStreamConfig == NULL) && (pStreamInstance !=NULL ));
777  }
778 
779  return pStreamConfig;
780 }
781 
782 
783 
784 static ci_stream_instance_t *ci_stream_get_instance(uint8 aStreamID)
785 {
786 
787  ci_stream_instance_t *pStreamInstance = NULL;
788 
789  if (gpStreamFirstInstance != NULL)
790  {
791 
792  pStreamInstance = gpStreamFirstInstance;
793  do
794  {
795 
796  if (pStreamInstance->pStreamConfig->streamID == aStreamID)
797  {
798  // Found the instance.
799  break;
800  }
801  else
802  {
803  // Not a match, move to next instance.
804  pStreamInstance = pStreamInstance->pNextInstance;
805  }
806 
807  } while(pStreamInstance !=NULL);
808  }
809 
810  return pStreamInstance;
811 }
812 
813 
814 // Get offset to the given element of the output stream buffer. The pointer returns points
815 // to the first data of the element which is the dataset ID.
816 static uint32 ci_stream_get_streambuffer_offset(uint8 aElementIndex, uint8 aNumElements, ci_stream_element_t *apElementList)
817 {
818 
819  ci_stream_element_t *pElementList;
820  uint32 offset_bytes = 0;
821 
822  if ( (apElementList == NULL) || (aNumElements == 0) || (aElementIndex >= aNumElements) )
823  return 0;
824 
825  pElementList = apElementList;
826 
827  uint8 i = 0;
828 
829  while(i < aElementIndex)
830  {
831  offset_bytes += CI_STREAM_DATASET_ID_BYTESIZE;
832  offset_bytes += pElementList[i].length;
833  ++i;
834  }
835 
836  offset_bytes +=
841 
842  return offset_bytes;
843 }
844 
845 
846 
847 
848 // Get the total output packet size including the data payload and the packet header.
849 static uint32 ci_stream_get_output_packet_size(uint8 aNumElements, ci_stream_element_t *apElementList)
850 {
851 
852  uint32 output_packet_size_bytes = 0;
853 
854  if ( (apElementList == NULL) || (aNumElements == 0) )
855  return 0;
856 
857  // Stream protocol ID.
858  output_packet_size_bytes += CI_STREAM_PROTOCOL_ID_BYTESIZE;
859 
860  // Command status.
861  output_packet_size_bytes += STREAM_PROTOCOL_CMD_STATUS_BYTESIZE;
862 
863  // Packet header: Stream ID and length.
864  output_packet_size_bytes += CI_STREAM_OUTPUTPACKET_STREAMID_BYTESIZE;
865  output_packet_size_bytes += CI_STREAM_OUTPUTPACKET_LENGTH_BYTESIZE;
866 
867  // Data payload (sequences of dataset ID / data).
868  output_packet_size_bytes += ci_stream_get_config_payload_size(aNumElements, apElementList);
869 
870  return output_packet_size_bytes;
871 }
872 
873 
874 
875 static uint32 ci_stream_get_config_payload_size(uint8 aNumElements, ci_stream_element_t *apElementList)
876 {
877 
878  ci_stream_element_t *pElementList;
879  uint32 payload_size_bytes = 0;
880 
881  if ( (apElementList == NULL) || (aNumElements == 0) )
882  return 0;
883 
884  pElementList = apElementList;
885 
886  uint8 i = aNumElements;
887 
888  while(i--)
889  {
890  payload_size_bytes += CI_STREAM_DATASET_ID_BYTESIZE;
891  payload_size_bytes += pElementList[i].length;
892  }
893 
894  return payload_size_bytes;
895 }
896 
897 
898 
899 
900 // Get the number of instances in the stream list.
901 static uint8 ci_stream_get_num_instances(void)
902 {
903 
904  uint8 num_instances = 0;
905  ci_stream_instance_t *pStreamInstance;
906 
907  if (gpStreamFirstInstance != NULL)
908  {
909 
910  pStreamInstance = gpStreamFirstInstance;
911  do
912  {
913  ++num_instances;
914 
915  pStreamInstance = pStreamInstance->pNextInstance;
916 
917  } while(pStreamInstance !=NULL );
918 
919  }
920 
921  return num_instances;
922 }
923 
924 
925 // Get the last instances in the stream list.
926 static ci_stream_instance_t *ci_stream_get_last_instance(void)
927 {
928 
929  ci_stream_instance_t *pStreamInstance = NULL;
930 
931  if (gpStreamFirstInstance != NULL)
932  {
933  pStreamInstance = gpStreamFirstInstance;
934 
935  while(pStreamInstance->pNextInstance != NULL)
936  {
937  pStreamInstance = pStreamInstance->pNextInstance;
938  }
939  }
940 
941  return pStreamInstance;
942 }
943 
944 
945 
946 // Create buffer for stream config and associated data.
947 static ci_stream_config_t *ci_stream_create_config_buf(boolean aCreateTrigElementBytes,
948  uint8 anumElements, uint32 *apnumBytesAlloc)
949 {
950 
951  if (anumElements == 0)
952  return NULL;
953 
954  ci_stream_config_t *pConfig;
955  uint32 bytes_allocated = sizeof(ci_stream_config_t);
956 
957 
958  if (aCreateTrigElementBytes == TRUE)
959  {
960  // Include memory to hold element list data and trigger bytes.
961  bytes_allocated += ci_stream_get_num_element_bytes(anumElements);
962  bytes_allocated += ci_stream_get_num_trig_bytes(anumElements);
963  }
964 
965 
966  // Create buffer for stream config and associated data.
967  // Total bytes for instance and associated data includes:
968  // sizeof(ci_stream_config_t)
969  // num trigger mask bytes
970  // element list
971  // datasetID/offset/length
972  // datasetID/offset/length
973  // ...
974  pConfig = (ci_stream_config_t *)CI_ALLOC_MEM_ZERO(bytes_allocated);
975 
976  if (pConfig != NULL)
977  {
978 
979  // Initialize as much as possible for caller.
980  pConfig->numElements = anumElements;
981 
982  // Note that element list needs to come first as it is required to be aligned properly (32bit)
983  // so that we can create a pointer to ci_stream_element_t and assign it an element and access its
984  // members properly. Trigger mask is byte size so it should go last.
985  pConfig->pElementList = (ci_stream_element_t *)((uint32)pConfig + sizeof(ci_stream_config_t)); // Element list is at end of ci_stream_config_t struct.
986 
987  pConfig->pTriggerMask = (uint8 *)((uint32)pConfig->pElementList
988  + ci_stream_get_num_element_bytes(anumElements)); // Trigger mask starts after end of element list array.
989  }
990  else
991  {
992  bytes_allocated = 0;
993  }
994 
995 
996  if (apnumBytesAlloc != NULL)
997  {
998  // Return to caller how many bytes were allocated in total.
999  *apnumBytesAlloc = bytes_allocated;
1000  }
1001 
1002  return pConfig;
1003 }
1004 
1005 
1006 
1007 
1008 
1009 
1010 isf_status_t ci_protocol_CB_stream(uint32 anumBytes, uint8 *apSrc, uint32 *apnumDestBytes, uint8 *apDest)
1011 {
1012 
1013  isf_status_t ret = ISF_SUCCESS;
1014  uint8 crc_bytes = 0;
1015 
1016  // Total response byte count. Note it is set to the minimum size here and may
1017  // increase depending on the command. This count is the total count
1018  // of the response packet including the packet header and any data
1019  // in reponse to the host command.
1020  uint32 num_response_totalbytes = STREAM_PROTOCOL_RESP_MIN_BYTESIZE;
1021 
1022  // Response data byte count. This value is only for the data bytes
1023  // returned according to the command. It does not include the response
1024  // packet header info such as protocol ID / status / command echo.
1025  // This value is needed so that we can put it in as part of the response
1026  // packet header before the data starts.
1027  uint32 num_response_data_bytes = 0;
1028 
1029 
1030  // Default response buffer. For most commands, the default size will be
1031  // sufficient. If a larger buffer is needed, such as for get info command,
1032  // a new buffer will be allocated. Note that this buffer includes bytes for
1033  // CRC if CRC is enabled.
1035 
1036  // Response buffer (contiguous). pStreamResp points to the default response
1037  // array here, but it may point a a dynamically alloc buffer for certain command
1038  // response that requires a larger buffer.
1039  uint8 *pStreamResp = &stream_resp_array[0];
1040  uint8 *pCoco_status = &stream_resp_array[STREAM_PROTOCOL_RESP_INDEX_COCO_STAT];
1041 
1042  // Normally the default response array is used (stream_resp_array). If a particular
1043  // command response requires a bigger buffer, then a new buffer is dynamically
1044  // allocated and bDynamicRespBuf is set to TRUE.
1045  boolean bDynamicRespBuf = FALSE; // Use default response array stream_resp_array.
1046 
1047 
1048 
1049 
1050  // Init COCO bit and echo command.
1051  pStreamResp[STREAM_PROTOCOL_RESP_INDEX_PROTOCOLID] = ci_protocol_stream_id;
1052  *pCoco_status = STREAM_COCO_BIT_MASK; // Same as pStreamResp[STREAM_PROTOCOL_RESP_INDEX_COCO_STAT]
1053  pStreamResp[STREAM_PROTOCOL_RESP_INDEX_CMD_ECHO] = ci_stream_get_host_cmd(apSrc); // Echo cmd back to host.
1054 
1055 
1056 
1057  // Host sent a command packet. Process it.
1058 
1059  // Do initial check for minimum number of bytes and CRC if enabled.
1061  crc_bytes = STREAM_CRC_BYTESIZE;
1062 
1063  if (anumBytes < (STREAM_PROTOCOL_RECV_MIN_BYTESIZE + crc_bytes))
1064  {
1065  *pCoco_status |= CI_STATUS_STREAM_ERR_INVALID_NUM_PARM;
1066  }
1067  else if (apSrc == NULL)
1068  {
1069  *pCoco_status |= CI_STATUS_STREAM_ERR_INVALID_PARM;
1070  }
1071  else if (gStreamReg.StreamCtrlReg1.Bits.enable_crc == STREAM_CRC_ENABLED)
1072  {
1073  uint16 crc16;
1074 
1075  // CRC check for entire host packet. Note that this packet does not
1076  // include the protocol id.
1077  crc16 = ccitt_crc16_cal(anumBytes, apSrc);
1078 
1079  if (crc16)
1080  // Return CRC error.
1081  *pCoco_status |= CI_STATUS_STREAM_ERR_CRC;
1082  }
1083 
1084 
1085  // Initial check passes. Process command.
1086  if (*pCoco_status == STREAM_COCO_BIT_MASK)
1087  {
1088 
1089  // Note that the raw received packet received does not include protocol ID.
1090  // At minimum, the packet contains the host command at this point in the code.
1091 
1092  uint8 cmd = ci_stream_get_host_cmd(apSrc);
1093 
1094  // Disregard CRC and command byte count from here on out. CRC bytes are
1095  // located at the end of the receive buffer so no need to adjust apSrc.
1096  anumBytes -= (crc_bytes + STREAM_PROTOCOL_CMD_BYTESIZE);
1097 
1098  // Skip past the host command.
1099  ++apSrc;
1100 
1101  // Note: At this point, apSrc contains only the parameter(s), if any,
1102  // that is required for the given command.
1103 
1104 
1105  switch(cmd)
1106  {
1107  case CI_CMD_STREAM_RESET:
1108  {
1109  // -------------------------------------------
1110  // CI_CMD_STREAM_RESET
1111  // - Delete all streams and reset internal states.
1112  // -
1113  //
1114  // Expected parameters:
1115  // - Parameters in receive buffer starting at apSrc[0].
1116  // - No parameters expected.
1117  //
1118  // Response packet:
1119  //
1120  // Byte Number Data
1121  // offset of bytes
1122  // ----------------------------
1123  // 0 3 [0]-Protocol ID, [1]-status, [2]-command echo
1124 
1126 
1127  if (anumBytes != 0) // No parameters expected.
1128  {
1129  *pCoco_status |= CI_STATUS_STREAM_ERR_INVALID_NUM_PARM;
1130  break;
1131  }
1132 
1133  while(pConfig != NULL)
1134  {
1135  isf_ci_stream_delete(pConfig->streamID);
1136  pConfig = isf_ci_stream_get_next();
1137  }
1138 
1139  // Do internal init.
1140  ci_stream_internal_init(NULL);
1141 
1142  }
1143  break;
1144 
1146  {
1147  // -------------------------------------------
1148  // CI_CMD_STREAM_ENABLE_DATA_UPDATE
1149  // - Enable data update.
1150  //
1151  // Expected parameters:
1152  // - Parameters in receive buffer starting at apSrc[0].
1153  // - No parameters expected.
1154  //
1155  // Response packet:
1156  //
1157  // Byte Number Data
1158  // offset of bytes
1159  // ----------------------------
1160  // 0 3 [0]-Protocol ID, [1]-status, [2]-command echo
1161 
1162  if (anumBytes != 0) // No parameters expected.
1163  {
1164  *pCoco_status |= CI_STATUS_STREAM_ERR_INVALID_NUM_PARM;
1165  break;
1166  }
1167 
1168  // Enable data stream.
1170  }
1171  break;
1172 
1174  {
1175  // -------------------------------------------
1176  // CI_CMD_STREAM_DISABLE_DATA_UPDATE
1177  // - Disable data update.
1178  //
1179  // Expected parameters:
1180  // - Parameters in receive buffer starting at apSrc[0].
1181  // - No parameters expected.
1182  //
1183  // Response packet:
1184  //
1185  // Byte Number Data
1186  // offset of bytes
1187  // ----------------------------
1188  // 0 3 [0]-Protocol ID, [1]-status, [2]-command echo
1189 
1190  if (anumBytes != 0) // No parameters expected.
1191  {
1192  *pCoco_status |= CI_STATUS_STREAM_ERR_INVALID_NUM_PARM;
1193  break;
1194  }
1195 
1196  // Disable data stream.
1198  }
1199  break;
1200 
1202  {
1203  // -------------------------------------------
1204  // CI_CMD_STREAM_GETINFO_NUMBER_STREAMS
1205  // - Get the current number of streams.
1206  //
1207  // Expected parameters:
1208  // - Parameters in receive buffer starting at apSrc[0].
1209  // - No parameters expected.
1210  //
1211  // Response packet:
1212  // - Response buffer is pStreamResp
1213  // - Return data starts at pStreamResp[STREAM_PROTOCOL_RESP_INDEX_DATASTART]
1214  // - N denotes number of data bytes going to host in response to the command
1215  // - M denotes the data value(s)
1216  //
1217  // Byte Number Data
1218  // offset of bytes value
1219  // ----------------------------
1220  // 0 3 [0]-Protocol ID, [1]-status, [2]-command echo
1221  // 3 1 Number of data bytes, MSB
1222  // 4 1 Number of data bytes, LSB
1223  // 5 1 Number of streams currently available
1224 
1225  if (anumBytes != 0) // No parameters expected.
1226  {
1227  *pCoco_status |= CI_STATUS_STREAM_ERR_INVALID_NUM_PARM;
1228  break;
1229  }
1230 
1231  num_response_data_bytes = 1; // Number of streams
1232 
1234  }
1235  break;
1236 
1238  {
1239  // -------------------------------------------
1240  // CI_CMD_STREAM_GETINFO_TRIGGER_STATE
1241  // - Get the current trigger state of a given stream ID.
1242  //
1243  // Expected parameters:
1244  // - Parameters in receive buffer starting at apSrc[0].
1245  //
1246  // Byte Number Data
1247  // offset of bytes
1248  // ----------------------------
1249  // 0 1 Stream ID
1250  //
1251  //
1252  // Response packet:
1253  // - Response buffer is pStreamResp
1254  // - Return data starts at pStreamResp[STREAM_PROTOCOL_RESP_INDEX_DATASTART]
1255  // - N denotes number of data bytes going to host in response to the command
1256  // - M denotes the data value(s)
1257  //
1258  // Byte Number Data
1259  // offset of bytes value
1260  // ----------------------------
1261  // 0 3 [0]-Protocol ID, [1]-status, [2]-command echo
1262  // 3 1 Number of data bytes, MSB
1263  // 4 1 Number of data bytes, LSB
1264  // 5:x (x-5) Trigger state bytes associated with the given stream ID
1265  //
1266 
1267  uint32 expected_bytes = 1; // Expect stream ID.
1268 
1269  if (anumBytes == expected_bytes)
1270  {
1271 
1272  // Get pointer to the stream instance of the given stream ID.
1273  ci_stream_instance_t *pInst = ci_stream_get_instance(apSrc[0]);
1274 
1275  if (pInst != NULL)
1276  {
1277  // Get the number of trigger bytes.
1278  num_response_data_bytes = ci_stream_get_num_trig_bytes(pInst->pStreamConfig->numElements);
1279 
1280  if ( (num_response_totalbytes + num_response_data_bytes) < STREAM_PROTOCOL_RESP_DEFAULT_ARRAY_BYTESIZE)
1281  {
1282  CI_COPY_MEM(pInst->pTriggerState, &pStreamResp[STREAM_PROTOCOL_RESP_INDEX_DATASTART], num_response_data_bytes);
1283  }
1284  else
1285  {
1286  *pCoco_status |= CI_STATUS_STREAM_ERR_OUT_OF_MEMORY;
1287  }
1288 
1289  }
1290  else
1291  {
1292  *pCoco_status |= CI_STATUS_STREAM_ERR_STREAMID_NOEXISTS;
1293  }
1294 
1295  }
1296  else
1297  {
1298  *pCoco_status |= CI_STATUS_STREAM_ERR_INVALID_NUM_PARM;
1299  }
1300 
1301  }
1302  break;
1303 
1304 
1306  {
1307  // -------------------------------------------
1308  // CI_CMD_STREAM_GETINFO_STREAM_CONFIG
1309  // - Get a stream configuration data given a stream ID.
1310  //
1311  // Expected parameters:
1312  // - Parameters in receive buffer starting at apSrc[0].
1313  //
1314  // Byte Number Data
1315  // offset of bytes
1316  // ----------------------------
1317  // 0 1 Stream ID
1318  //
1319  //
1320  // Response packet:
1321  // - Response buffer is pStreamResp
1322  // - Return data starts at pStreamResp[STREAM_PROTOCOL_RESP_INDEX_DATASTART]
1323  // - N denotes number of data bytes going to host in response to the command
1324  // - M denotes the data value(s)
1325  //
1326  // Byte Number Data
1327  // offset of bytes value
1328  // ----------------------------
1329  // 0 3 [0]-Protocol ID, [1]-status, [2]-command echo
1330  // 3 1 N[15:0] Number of data bytes, MSB
1331  // 4 1 N[7:0] Number of data bytes, LSB
1332  // 5 x Configuration, trigger bytes, and element list
1333  //
1334  // Configuration
1335  // 5 1 Stream ID
1336  // 6 1 Number of elements
1337  //
1338  // Trigger bytes
1339  // 7 y Trigger bytes
1340  //
1341  // Element bytes in increments of 5 bytes after the trigger bytes
1342  // (y+8)+0 1 Dataset ID
1343  // (y+8)+1 2 Length (msb first)
1344  // (y+8)+2 2 Offset (msb first)
1345 
1346  uint32 expected_bytes = 1; // Expect stream ID.
1347 
1348  if (anumBytes == expected_bytes)
1349  {
1350 
1351  // Get pointer to the stream instance of the given stream ID.
1352  ci_stream_instance_t *pInst = ci_stream_get_instance(apSrc[0]);
1353 
1354  if (pInst != NULL)
1355  {
1356  // Get the number of trigger bytes.
1357  uint32 num_trig_bytes = ci_stream_get_num_trig_bytes(pInst->pStreamConfig->numElements);
1358  uint32 num_element_bytes = ci_stream_get_num_element_bytes(pInst->pStreamConfig->numElements);
1359 
1360  num_response_data_bytes =
1363  + num_trig_bytes
1364  + num_element_bytes;
1365 
1366  uint8 *pTemp = CI_ALLOC_MEM_ZERO(
1367  num_response_totalbytes // Currently same as STREAM_PROTOCOL_RESP_MIN_BYTESIZE
1368  + num_response_data_bytes
1369  + crc_bytes);
1370 
1371  if (pTemp != NULL)
1372  {
1373  bDynamicRespBuf = TRUE;
1374 
1375  // First, copy over info from the default response buffer plus the data size.
1377 
1378  // Safe to transfer the buffer at this point. Note that the default response buffer
1379  // is a local array so it does not need to be deallocated.
1380  pStreamResp = pTemp;
1381 
1382  // Point to where response data start in the temp buffer.
1384 
1385  // Copy stream ID and number of elements.
1386  *pTemp++ = pInst->pStreamConfig->streamID;
1387  *pTemp++ = pInst->pStreamConfig->numElements;
1388 
1389  // Copy trigger bytes.
1390  CI_COPY_MEM(pInst->pStreamConfig->pTriggerMask, pTemp, num_trig_bytes);
1391  pTemp += num_trig_bytes;
1392 
1393  // Copy element bytes.
1394  {
1395  uint32 i = 0;
1396  ci_stream_element_t *pElementList = pInst->pStreamConfig->pElementList;
1397  while(i < pInst->pStreamConfig->numElements)
1398  {
1399  *pTemp++ = pElementList[i].datasetID;
1400  *pTemp++ = ((pElementList[i].length >> 8) & 0xFF); // Msb
1401  *pTemp++ = (pElementList[i].length & 0xFF); // Lsb
1402  *pTemp++ = ((pElementList[i].offset >> 8) & 0xFF); // Msb
1403  *pTemp++ = (pElementList[i].offset & 0xFF); // Lsb
1404 
1405  ++i;
1406  }
1407  }
1408 
1409  }
1410  else
1411  {
1412  *pCoco_status |= CI_STATUS_STREAM_ERR_OUT_OF_MEMORY;
1413 
1414  // If an error occurred, then reset data count.
1415  num_response_data_bytes = 0;
1416 
1417  }
1418 
1419  }
1420  else
1421  {
1422  *pCoco_status |= CI_STATUS_STREAM_ERR_STREAMID_NOEXISTS;
1423  }
1424 
1425  }
1426  else
1427  {
1428  *pCoco_status |= CI_STATUS_STREAM_ERR_INVALID_NUM_PARM;
1429  }
1430 
1431  } // CI_CMD_STREAM_GETINFO_STREAM_CONFIG
1432  break;
1433 
1435  {
1436  // -------------------------------------------
1437  // CI_CMD_STREAM_GETINFO_GET_FIRST_STREAMID
1438  // - Get the first stream ID in the list.
1439  //
1440  // Expected parameters:
1441  // - Parameters in receive buffer starting at apSrc[0].
1442  // - No parameters expected.
1443  //
1444  // Response packet:
1445  // - Response buffer is pStreamResp
1446  // - Return data starts at pStreamResp[STREAM_PROTOCOL_RESP_INDEX_DATASTART]
1447  // - N denotes number of data bytes going to host in response to the command
1448  // - M denotes the data value(s)
1449  //
1450  // Byte Number Data
1451  // offset of bytes
1452  // ----------------------------
1453  // 0 3 [0]-Protocol ID, [1]-status, [2]-command echo
1454  // 3 1 Number of data bytes, MSB
1455  // 4 1 Number of data bytes, LSB
1456  // 5 1 Stream ID
1457 
1458  if (anumBytes != 0) // No parameters expected.
1459  {
1460  *pCoco_status |= CI_STATUS_STREAM_ERR_INVALID_NUM_PARM;
1461  break;
1462  }
1463 
1464 
1465  // Get pointer to the first stream configuration.
1467 
1468  if (pConfig != NULL)
1469  {
1470  num_response_data_bytes = 1;
1471  pStreamResp[STREAM_PROTOCOL_RESP_INDEX_DATASTART] = pConfig->streamID;
1472  }
1473  else
1474  {
1475  *pCoco_status |= CI_STATUS_STREAM_ERR_STREAM_NOEXISTS;
1476  }
1477 
1478  }
1479  break;
1480 
1482  {
1483  // -------------------------------------------
1484  // CI_CMD_STREAM_GETINFO_GET_FIRST_STREAMID
1485  // - Get the next stream ID in the list.
1486  //
1487  // Expected parameters:
1488  // - Parameters in receive buffer starting at apSrc[0].
1489  // - No parameters expected.
1490  //
1491  // Response packet:
1492  // - Response buffer is pStreamResp
1493  // - Return data starts at pStreamResp[STREAM_PROTOCOL_RESP_INDEX_DATASTART]
1494  // - N denotes number of data bytes going to host in response to the command
1495  // - M denotes the data value(s)
1496  //
1497  // Byte Number Data
1498  // offset of bytes
1499  // ----------------------------
1500  // 0 3 [0]-Protocol ID, [1]-status, [2]-command echo
1501  // 3 1 Number of data bytes, MSB
1502  // 4 1 Number of data bytes, LSB
1503  // 5 1 Stream ID
1504 
1505  if (anumBytes != 0) // No parameters expected.
1506  {
1507  *pCoco_status |= CI_STATUS_STREAM_ERR_INVALID_NUM_PARM;
1508  break;
1509  }
1510 
1511 
1512  if (isf_ci_stream_get_num_streams() == 0)
1513  {
1514  *pCoco_status |= CI_STATUS_STREAM_ERR_STREAM_NOEXISTS;
1515  }
1516  else
1517  {
1518  // Get pointer to the first stream configuration.
1520 
1521  if (pConfig != NULL)
1522  {
1523  num_response_data_bytes = 1;
1524  pStreamResp[STREAM_PROTOCOL_RESP_INDEX_DATASTART] = pConfig->streamID;
1525  }
1526  else
1527  {
1528  *pCoco_status |= CI_STATUS_STREAM_STREAM_END_OF_LIST;
1529  }
1530  }
1531 
1532  }
1533  break;
1534 
1535 
1537  {
1538  // -------------------------------------------
1539  // CI_CMD_STREAM_CREATE_STREAM
1540  // - Create a stream with the given data.
1541  //
1542  // Expected parameters:
1543  // - Parameters in receive buffer starting at apSrc[0].
1544  //
1545  // Byte Number Data
1546  // offset of bytes
1547  // ----------------------------
1548  // 0 1 Stream ID
1549  // 1 1 Number of elements
1550  // 2 x Trigger byte(s)
1551  // (x+2) y Element list (data set ID, length, offset)
1552  //
1553  // Element bytes in increments of 5 bytes after the trigger bytes
1554  // 0 1 Dataset ID
1555  // 1 2 Length (msb first)
1556  // 3 2 Offset (msb first)
1557  //
1558  //
1559  // Response packet:
1560  // - Response buffer is pStreamResp
1561  // - Return data starts at pStreamResp[STREAM_PROTOCOL_RESP_INDEX_DATASTART]
1562  // - N denotes number of data bytes going to host in response to the command
1563  // - M denotes the data value(s)
1564  //
1565  // Response packet:
1566  //
1567  // Byte Number Data
1568  // offset of bytes
1569  // ----------------------------
1570  // 0 3 [0]-Protocol ID, [1]-status, [2]-command echo
1571  //
1572 
1573  uint32 expected_bytes = 0;
1574  uint8 num_elements = cmd_createstream_get_numelements(apSrc);
1575  uint32 num_trigmask_bytes = ci_stream_get_num_trig_bytes(num_elements);
1576  uint32 num_element_bytes = ci_stream_get_num_element_bytes(num_elements);
1577  uint32 element_offset;
1578 
1579  // Calculate the total bytes expected.
1580  expected_bytes += CI_STREAM_OUTPUTPACKET_STREAMID_BYTESIZE;
1581  expected_bytes += CI_STREAM_NUMELEMENTS_BYTESIZE;
1582  expected_bytes += num_trigmask_bytes; // Based on number of elements
1583  element_offset = expected_bytes; // Mark start of element list.
1584  expected_bytes += num_element_bytes; // Based on number of elements
1585 
1586 
1587  if (anumBytes == expected_bytes)
1588  {
1589  uint8 streamID = cmd_createstream_get_streamID(apSrc);
1590  uint8 *pTriggerMask = (uint8 *)cmd_createstream_get_trigmask_ptr(apSrc);
1591 
1592  uint8 *pSrcElementBytes = (uint8 *)&apSrc[element_offset];
1593  ci_stream_element_t *pDestElementList = (ci_stream_element_t *)CI_ALLOC_MEM_ZERO(num_element_bytes);
1594 
1595  // Convert offset/length from big endian to little endian.
1596  if (pDestElementList != NULL)
1597  {
1598  uint8 element_index = 0;
1599 
1600  while(element_index < num_elements)
1601  {
1602 
1603  pDestElementList[element_index].datasetID = *pSrcElementBytes++;
1604 
1605  pDestElementList[element_index].length = (uint16)(pSrcElementBytes[0] << 8) | (uint16)(pSrcElementBytes[1]);
1606  pSrcElementBytes += 2;
1607 
1608  pDestElementList[element_index].offset = (uint16)(pSrcElementBytes[0] << 8) | (uint16)(pSrcElementBytes[1]);
1609  pSrcElementBytes += 2;
1610 
1611  ++element_index;
1612  }
1613 
1614  *pCoco_status |= isf_ci_stream_create(streamID, num_elements, pTriggerMask, pDestElementList);
1615 
1616  CI_FREE_MEM(pDestElementList);
1617  }
1618  else
1619  {
1620  *pCoco_status |= CI_STATUS_STREAM_ERR_OUT_OF_MEMORY;
1621  }
1622 
1623  }
1624  else
1625  {
1626  *pCoco_status |= CI_STATUS_STREAM_ERR_INVALID_NUM_PARM;
1627  }
1628 
1629  }
1630  break;
1631 
1633  {
1634  // -------------------------------------------
1635  // CI_CMD_STREAM_DELETE_STREAM
1636  // - Delete the given stream ID.
1637  //
1638  // Expected parameters:
1639  // - Parameters in receive buffer starting at apSrc[0].
1640  //
1641  // Byte Number Data
1642  // offset of bytes
1643  // ----------------------------
1644  // 0 1 Stream ID
1645  //
1646  // Response packet:
1647  // - Response buffer is pStreamResp
1648  // - Return data starts at pStreamResp[STREAM_PROTOCOL_RESP_INDEX_DATASTART]
1649  // - N denotes number of data bytes going to host in response to the command
1650  // - M denotes the data value(s)
1651  //
1652  // Byte Number Data
1653  // offset of bytes value
1654  // ----------------------------
1655  // 0 3 [0]-Protocol ID, [1]-status, [2]-command echo
1656  //
1657 
1658  uint32 expected_bytes = 1;
1659 
1660 
1661  if (anumBytes == expected_bytes)
1662  {
1663  // Attempt to delete the stream.
1664  *pCoco_status |= isf_ci_stream_delete(apSrc[0]);
1665  }
1666  else
1667  {
1668  *pCoco_status |= CI_STATUS_STREAM_ERR_INVALID_NUM_PARM;
1669  }
1670 
1671  }
1672  break;
1673 
1675  {
1676  // -------------------------------------------
1677  // CI_CMD_STREAM_RESET_TRIGGER
1678  // - Reset the given stream ID to its default state.
1679  // - The default trigger state is the trigger mask that was
1680  // provided when the stream was created.
1681  //
1682  // Expected parameters:
1683  // - Parameters in receive buffer starting at apSrc[0].
1684  //
1685  // Byte Number Data
1686  // offset of bytes
1687  // ----------------------------
1688  // 0 1 Stream ID
1689  //
1690  // Response packet:
1691  // - Response buffer is pStreamResp
1692  // - Return data starts at pStreamResp[STREAM_PROTOCOL_RESP_INDEX_DATASTART]
1693  // - N denotes number of data bytes going to host in response to the command
1694  // - M denotes the data value(s)
1695  //
1696  // Byte Number Data
1697  // offset of bytes value
1698  // ----------------------------
1699  // 0 3 [0]-Protocol ID, [1]-status, [2]-command echo
1700  //
1701 
1702  uint32 expected_bytes = 1;
1703 
1704 
1705  if (anumBytes == expected_bytes)
1706  {
1707  // Attempt to delete the stream.
1708  *pCoco_status |= isf_ci_stream_reset_trigger(apSrc[0]);
1709  }
1710  else
1711  {
1712  *pCoco_status |= CI_STATUS_STREAM_ERR_INVALID_NUM_PARM;
1713  }
1714  }
1715 
1716  break;
1717 
1719  {
1720  // -------------------------------------------
1721  // CI_CMD_STREAM_ENABLE_CRC
1722  // - Enable CRC
1723  //
1724  // Expected parameters:
1725  // - Parameters in receive buffer starting at apSrc[0].
1726  // - No parameters expected.
1727  //
1728  // Response packet:
1729  //
1730  // Byte Number Data
1731  // offset of bytes
1732  // ----------------------------
1733  // 0 3 [0]-Protocol ID, [1]-status, [2]-command echo
1734 
1735  if (anumBytes != 0) // No parameters expected.
1736  {
1737  *pCoco_status |= CI_STATUS_STREAM_ERR_INVALID_NUM_PARM;
1738  break;
1739  }
1740 
1742  }
1743  break;
1745  {
1746  // -------------------------------------------
1747  // CI_CMD_STREAM_DISABLE_CRC
1748  // - Disable CRC
1749  //
1750  // Expected parameters:
1751  // - Parameters in receive buffer starting at apSrc[0].
1752  // - No parameters expected.
1753  //
1754  // Response packet:
1755  //
1756  // Byte Number Data
1757  // offset of bytes
1758  // ----------------------------
1759  // 0 3 [0]-Protocol ID, [1]-status, [2]-command echo
1760 
1761  if (anumBytes != 0) // No parameters expected.
1762  {
1763  *pCoco_status |= CI_STATUS_STREAM_ERR_INVALID_NUM_PARM;
1764  break;
1765  }
1766 
1768  }
1769  break;
1770 
1771  default:
1772  *pCoco_status |= CI_STATUS_STREAM_ERR_INVALID_CMD;
1773  break;
1774  }
1775 
1776  }
1777 
1778 
1779  // Total bytes to send back.
1780  num_response_totalbytes += num_response_data_bytes;
1781 
1782  // If there are data bytes in response to the command, specify the number of bytes.
1783  //if (num_response_data_bytes > 0)
1784  {
1785  pStreamResp[STREAM_PROTOCOL_RESP_INDEX_NUMDATA_MSB] = (uint8)((num_response_data_bytes >> 8) & 0xFF); // msb
1786  pStreamResp[STREAM_PROTOCOL_RESP_INDEX_NUMDATA_LSB] = (uint8) (num_response_data_bytes & 0xFF); // lsb
1787 
1788  num_response_totalbytes += STREAM_PROTOCOL_RESP_RESPDATALENGTH_BYTESIZE;
1789  }
1790 
1791 
1792 
1793  // Generate CRC if enabled.
1795  {
1796  uint16 crc16;
1797 
1798  // CRC for response packet plus data size.
1799  crc16 = ccitt_crc16_cal(num_response_totalbytes, pStreamResp);
1800 
1801  // Put CRC at the end of the buffer.
1802  pStreamResp[num_response_totalbytes + 0] = (uint8)((uint16)(crc16 & 0xff00) >> 8); // Msb first
1803  pStreamResp[num_response_totalbytes + 1] = (uint8)(crc16 & 0xff); // Lsb
1804 
1805  num_response_totalbytes += STREAM_CRC_BYTESIZE;
1806  }
1807 
1808  // Send response to host.
1809  ret = ci_send_packet(num_response_totalbytes, pStreamResp);
1810 
1811  // If the response buffer was dynamically allocated, then dealloc.
1812  if (bDynamicRespBuf == TRUE)
1813  CI_FREE_MEM(pStreamResp);
1814 
1815  if (*pCoco_status != STREAM_COCO_BIT_MASK)
1816  ret = CI_STATUS_STREAM_ERR;
1817 
1818  return ret;
1819 }
1820 
1822 {
1823 
1824 // -------------------------------------------
1825  // - Enable data update.
1826  //
1827  // Expected parameters:
1828  // - No parameters expected.
1829  // Enable data stream.
1831 }
1832 
1834 {
1835 
1836 // -------------------------------------------
1837  // - Disable data update.
1838  //
1839  // Expected parameters:
1840  // - No parameters expected.
1841  // Disable data stream.
1843 }
1844 
1845 
1846 
1847 
1848 
1849 
1850 
1851 
1852 
1853 
1854 
1855 
1856 
1857 
1858 
1859 
1860 
1861 
1862 
1863 
1864 
1865 
1866 
1867 
1868 
1869 
1870 
1871 
1872 
1873 
1874 
1875 
1876 
1877 
1878 
#define cmd_createstream_get_streamID(pSrc)
isf_status_t isf_ci_stream_reset_trigger(uint8 aStreamID)
This API resets the trigger bits of the the given stream ID.
#define STREAM_PROTOCOL_RECV_MIN_BYTESIZE
Defines the minimum number of bytes of a received host packet.
ISF board support header files.
unsigned char uint8
Definition: isf_types.h:76
#define TRUE
Definition: isf_types.h:82
#define STREAM_PROTOCOL_CMD_BYTESIZE
Defines the number of bytes for host command.
#define STREAM_PROTOCOL_CMD_STATUS_BYTESIZE
Defines the number of bytes for command status.
#define STREAM_CRC_DISABLED
#define STREAM_CRC_ENABLED
Stream control: enable/disable CRC generation/checking.
#define STREAM_PROTOCOL_RESP_INDEX_NUMDATA_LSB
ISF Command Interpreter (CI) stream protocol header file.
#define FALSE
Definition: isf_types.h:86
Command Interpreter (CI) stream protocol header file.
#define CI_STREAM_DATASET_ID_BYTESIZE
Defines the number of bytes to store the data set ID.
CRC header file.
#define STREAM_PROTOCOL_OUTPUTPACKET_INDEX_LENGTH_LSB
isf_status_t isf_ci_stream_create(uint8 aStreamID, uint8 aNumElements, uint8 *apTriggerMask, ci_stream_element_t *apElementList)
This API creates a stream.
#define STREAM_PROTOCOL_OUTPUTPACKET_INDEX_COCO_STAT
struct ci_stream_ctrl_reg1_t::@4 Bits
isf_status_t ci_stream_init(uint8 aprotocolID, void *apInitData)
This is a CI stream protocol intialization callback function pointer.
ci_stream_config_t * isf_ci_stream_get_next(void)
This API returns the configuration of the next stream in the linked list.
#define STREAM_PROTOCOL_DATA_ENABLED
Stream protocol control: enable/disable data update.
Command interpreter task header file. This file is internal ISF code.
#define CI_STREAM_OUTPUTPACKET_STREAMID_BYTESIZE
Defines the number of bytes to store the stream ID.
#define STREAM_PROTOCOL_RESP_INDEX_CMD_ECHO
isf_status_t isf_ci_stream_update_data(uint8 aDataSetID, uint16 aLength, uint16 aOffset, uint8 *apSrc)
This API updates the data of a dataset.
#define CI_STREAM_NUMELEMENTS_BYTESIZE
Defines the number of bytes to specify the number of elements.
#define cmd_createstream_get_numelements(pSrc)
ci_stream_config_t * isf_ci_stream_get(uint8 aStreamID)
#define STREAM_PROTOCOL_RESP_INDEX_PROTOCOLID
Defines the indexes of the command response array to the host.
#define STREAM_PROTOCOL_RESP_RESPDATALENGTH_BYTESIZE
Defines the number of bytes to store the length of the response data. If there are no response data...
ci_stream_config_t * isf_ci_stream_get_first(void)
This API returns the configuration of the first stream in the linked list.
The isf_util.h file contains the utility method declarations and macros.
ci_stream_instance_t
ci_stream_config_t
#define STREAM_PROTOCOL_RESP_MIN_BYTESIZE
Defines the minimum number of response bytes to the host not including CRC. Do not add CRC bytes into...
#define STREAM_PROTOCOL_OUTPUTPACKET_INDEX_LENGTH_MSB
isf_status_t ci_send_packet(uint32 anumBytes, uint8 *apSrc)
CI send packet - main function to send data to host.
Definition: task_ci.c:338
uint16 ccitt_crc16_cal(uint32 anumBytes, uint8 *apBuf)
This crc function contains the standard CCITT CRC 16-bit implementation.
Definition: crc.c:18
uint32 ci_stream_get_num_trig_bytes(uint8 anumElements)
void isf_ci_stream_set_CRC(boolean acrcEnable)
This API sets the cyclic redundancy check (CRC) code generation to the requested state.
uint32 ci_stream_get_num_element_bytes(uint8 anumElements)
#define STREAM_PROTOCOL_OUTPUTPACKET_INDEX_STREAMID
Main ISF header file. Contains code common to all ISF components.
unsigned short int uint16
Definition: isf_types.h:77
#define CI_STREAM_OUTPUTPACKET_LENGTH_BYTESIZE
Defines the number of bytes to store the length of the output packet data.
void isf_ci_stream_set_stream_enable()
This API enables data stream.
ci_stream_ctrl_reg1_t StreamCtrlReg1
#define STREAM_PROTOCOL_RESP_DEFAULT_ARRAY_BYTESIZE
Defines the fixed array size of the response buffer array. The size specified is sufficient for most ...
API definitions, types, and macros for the Intelligent Sensing Framework (ISF) Command Interpreter (C...
General library initialization failure status.
Definition: isf.h:34
#define STREAM_PROTOCOL_OUTPUTPACKET_INDEX_PROTOCOLID
Defines the indexes of the stream data update buffer (output packet).
ci_stream_element_t
#define STREAM_PROTOCOL_RESP_INDEX_NUMDATA_MSB
#define CI_STREAM_PROTOCOL_ID_BYTESIZE
Defines the number of bytes to store the protocol ID.
Stream protocol registers Structure. Contains stream protocol control registers.
#define cmd_createstream_get_trigmask_ptr(pSrc)
#define STREAM_COCO_BIT_MASK
void byteswap(uint8 *p1, uint8 *p2)
int32 isf_status_t
ISF return status type.
Definition: isf.h:76
Stream instance structure is used internally to encapsulate the information of a stream and the curre...
#define STREAM_PROTOCOL_RESP_INDEX_DATASTART
void isf_ci_stream_set_stream_disable()
This API disables data stream.
#define CI_ALLOC_MEM_ZERO(x)
Memory allocation abstraction.
Definition: task_ci.h:113
isf_status_t isf_ci_stream_delete(uint8 aStreamID)
This API deletes the given stream ID.
isf_status_t isf_ci_stream_get_trigger(uint8 aStreamID, uint8 *apTrigger)
This API returns the trigger state of the given stream ID.
#define CI_COPY_MEM(src, dest, size)
Definition: task_ci.h:116
#define STREAM_PROTOCOL_DATA_DISABLED
unsigned long int uint32
Definition: isf_types.h:78
isf_status_t ci_protocol_CB_stream(uint32 anumBytes, uint8 *apSrc, uint32 *apnumDestBytes, uint8 *apDest)
This is a CI stream protocol callback function pointer.
#define CI_FREE_MEM(x)
Definition: task_ci.h:114
uint8 isf_ci_stream_get_num_streams(void)
This API returns the number of streams.
#define ci_stream_get_host_cmd(pSrc)
Macros to access buffer received from host.
#define STREAM_PROTOCOL_RESP_INDEX_COCO_STAT
#define STREAM_CRC_BYTESIZE
Defines the number of bytes for 16-bit CRC value.