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