DSMCC  17.9.0
 All Data Structures Files Functions Typedefs
module.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2004 Ocean Blue Software Ltd
4  * Copyright © 2001 Koninklijke Philips Electronics N.V
5  *
6  * This file is part of a DTVKit Software Component
7  * You are permitted to copy, modify or distribute this file subject to the terms
8  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
9  *
10  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
11  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
12  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
13  *
14  * If you or your organisation is not a member of DTVKit then you have access
15  * to this source code outside of the terms of the licence agreement
16  * and you are expected to delete this and any associated files immediately.
17  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
18  *******************************************************************************/
26 /*---includes for this file--------------------------------------------------*/
27 #include "clDsmSystem.h"
28 #include "module.h"
29 
30 #include "clDsmUtils.h"
31 #include "cacheMgr.h"
32 #include "moduleData.h"
33 #include "moduleDecompress.h"
34 #include "loadRqst.h"
35 #include "dataCarousel.h"
36 #include "sectionTimer.h"
37 #include "loadMgr.h"
38 #include "stb_os.h"
39 
40 /*------------------------------- Local Macros -------------------------------*/
41 
42 #define CACHE0_TIMEOUT_MS 30
43 
44 /*--------------------------------Local Types --------------------------------*/
45 
46 
47 /*------------------------------- Local Statics ------------------------------*/
48 
49 
50 /*------------------- local prototypes/forward declarations ------------------*/
51 
52 #ifdef DSM_NO_MEM_CONTEXT
53 #define builderConstruct( x, a, b, c, d, e ) \
54  builderConstruct( a, b, c, d, e )
55 #endif
56 
57 static E_DscError builderCreate( P_DsmCoreInst idp,
58  U32BIT moduleSize, U16BIT blockSize,
59  P_ModuleBuilder *ppModuleBuilder );
60 
61 static void builderDestroy( P_DsmCoreInst idp, P_ModuleBuilder *ppModuleBuilder );
62 
63 static void builderConstruct( P_DsmCoreInst idp, P_ModuleBuilder pModuleBuilder,
64  U16BIT blockNum, U16BIT ddbDataSize, U8BIT *pDDBData, P_ModuleData *phModuleData );
65 
66 
67 /*---------------------------- Exported Functions ----------------------------*/
68 
69 /* /////////////////////////////////////////////////////////////////////////////
70 // DSC_ModuleCreate
71 // Creates an instance of the Module struct, and initialises it.
73 E_DscError DSC_ModuleCreate( P_DsmCoreInst idp,
74  U16BIT moduleId, P_Module *ppModule )
75 {
76  P_Module pModule = NULL;
77  E_DscError err = CLDSM_OK;
78 
79  dsmDP3(("DSC_ModuleCreate()\n"));
80  dsmAssert((idp != NULL));
81  dsmAssert((ppModule != NULL));
82 
83  pModule = (P_Module)DSC_CmMemGet( idp, sizeof(S_Module) );
84  if (!pModule)
85  {
86  err = CLDSM_ERR_MEM_HEAP_FULL;
87  }
88  else
89  {
90  memset( pModule, 0, sizeof(S_Module) );
91 
92  llLinkInit( pModule->llData, NUM_LISTS_MODULE );
93 
94  pModule->moduleInfo.moduleId = moduleId;
95 
96  pModule->moduleInfo.associationTag = INVALID_ASSOCIATION_TAG;
97  pModule->cachingRules = CACHE_RULES_DEFAULT;
98 
99  err = CLDSM_OK;
100  }
101  *ppModule = pModule;
102 
103  DEBUG_CHK( err == CLDSM_OK,
104  dsmDP1(("ERROR: DSC_ModuleCreate: %u\n", err)));
105  dsmDP3(("exit DSC_ModuleCreate -> rtn: %u\n", err));
106  return err;
107 }
108 
109 /* /////////////////////////////////////////////////////////////////////////////
110 // DSC_ModuleDestroy
111 // Destroys an instance of the Module struct, and all associated data.
113 void DSC_ModuleDestroy( P_DsmCoreInst idp, P_Module pModule )
114 {
115  dsmDP3(("DSC_ModuleDestroy()\n"));
116  dsmAssert((idp != NULL));
117  dsmAssert((pModule != NULL));
118 
119  /* -- Check that the module is no longer linked into any lists */
120  dsmAssert((pModule->llData[DC_MODULE_LIST ].pLLCtrl == NULL));
121  dsmAssert((pModule->llData[MODULE_ACQUIRE_LIST].pLLCtrl == NULL));
122  dsmAssert((pModule->llData[MODULE_DELETE_LIST ].pLLCtrl == NULL));
123 
124  /* -- Check that module has no loadRequestList attached */
125  dsmAssert((pModule->llcLoadRequests == NULL));
126 
127  /* -- Check that the module has no section filter associated */
128  dsmAssert((pModule->pDdbSf == 0));
129 
130  /* -- Check that the module is not in use */
131  dsmAssert((pModule->currentUseCount == 0));
132 
133  /* -- Check that the module has no loaded objects associated */
134  dsmAssert((pModule->loadedCount == 0));
135 
136  /* -- Check that the module has no client requests */
137  dsmAssert((pModule->highPriorityCount == 0));
138 
139  if (pModule->pModuleBuilder)
140  {
141  builderDestroy( idp, &pModule->pModuleBuilder );
142  }
143  if (pModule->hCompModuleData)
144  {
145  dsmAssert((pModule->hCompModuleData != pModule->hModuleData));
146  moduleDataDestroy( idp, &pModule->hCompModuleData );
147  }
148  if (pModule->hModuleData)
149  {
150  moduleDataDestroy( idp, &pModule->hModuleData );
151  }
152 
153  DSC_CmMemRelease( idp, pModule );
154 
155  dsmDP3(("exit DSC_ModuleDestroy\n"));
156 }
157 
158 /*
159 -- Increments module currentUseCount
160 --
161 -- NB. Regardless of it's priority, if module is in use (ie. currentUseCount
162 -- is > 0), it cannot be deleted to make space in the cache.
163 --
164 */
165 void DSC_ModuleUse( P_DsmCoreInst idp, P_Module pModule )
166 {
167  dsmAssert((idp != NULL));
168  dsmAssert((pModule != NULL));
169 
170 #define MAX_CURRENT_USE_COUNT \
171  (~(0xFFFFFFFF << ((sizeof(pModule->currentUseCount) * 8) - 1)))
172 
173  /* -- NB. Should never reach max value */
174  dsmAssert((pModule->currentUseCount <= MAX_CURRENT_USE_COUNT));
175 
176  /* -- Detect/prevent overflow errors in retail */
177  if (pModule->currentUseCount < MAX_CURRENT_USE_COUNT)
178  {
179  pModule->currentUseCount++;
180  }
181 }
182 
183 /*
184 -- Decrements module currentUseCount
185 */
186 void DSC_ModuleUnUse( P_DsmCoreInst idp, P_Module pModule )
187 {
188  dsmAssert((idp != NULL));
189  dsmAssert((pModule != NULL));
190 
191  /* -- Should never underrun */
192  dsmAssert((pModule->currentUseCount > 0));
193 
194  /* -- Detect/prevent underrun errors in retail */
195  if (pModule->currentUseCount > 0)
196  {
197  pModule->currentUseCount--;
198  }
199 }
200 
205  P_Module pModule, E_SFPriority sfPriority )
206 {
207  S_SfTarget target;
208  P_DataCarousel pDC;
209  E_DscError err;
210 
211  dsmAssert((idp != NULL));
212  dsmAssert((pModule != NULL));
213  pDC = LLParent(pModule, DC_MODULE_LIST);
214  dsmAssert((pDC != NULL));
215  if (LLInsertHead( pDC->llcModuleAcquires, pModule ))
216  {
217  target.kind = SFK_DDB;
218  target.id = pModule->moduleInfo.moduleId;
219  target.associationTag = pModule->moduleInfo.associationTag;
220  target.serviceId = (target.associationTag == INVALID_ASSOCIATION_TAG) ?
221  DSC_DataCrslGetPid(pDC) : DSC_DataCrslGetServiceId(pDC);
222  target.u.pModule = pModule;
223  dsmDP3(("INFO: Load Module Id: %u pModule = 0x%p [timeout = %u]\n",
224  pModule->moduleInfo.moduleId, pModule,
225  pModule->moduleInfo.u.mhgp.moduleTimeout));
226  /* -- Module/DDB not already being acquired, so start section filter */
227  err = DSC_SectionFilterStart( idp, &target, sfPriority, &pModule->pDdbSf );
228  if (err == CLDSM_ERR_SI_QUERY_FAILED)
229  {
230  DBGLOG((DD_SF|DD_MOD), " Treating query failure as OK")
231  err = CLDSM_OK;
232  }
233  }
234  else
235  {
236  /* -- Module/DDB already being acquired so update filter priority */
237  err = DSC_SsectionFilterUpdatePriority( idp, pModule->pDdbSf, sfPriority, /*latchHighest*/ TRUE );
238  }
239  if (err)
240  {
241  LLRemove( pModule, MODULE_ACQUIRE_LIST );
242  }
243 
244  DEBUG_CHK( err == CLDSM_OK,
245  dsmDP1(("ERROR: ocModuleAcquireStart %u\n", err)));
246  return err;
247 }
248 
253 {
254  S_SfTarget target;
255  E_SFPriority sfPriority;
256  E_DscError err;
257 
258  dsmAssert((idp != NULL));
259  dsmAssert((pModule != NULL));
260 
261  if (pModule->pDdbSf != NULL)
262  {
263  target = pModule->pDdbSf->target;
264  sfPriority = pModule->pDdbSf->filter.priority;
265  DSC_SectionFilterStop( idp, &pModule->pDdbSf );
266  }
267  else
268  {
269  P_DataCarousel pDC = LLParent(pModule, DC_MODULE_LIST);
270  dsmAssert((pDC != NULL));
271  target.kind = SFK_DDB;
272  target.id = pModule->moduleInfo.moduleId;
273  target.associationTag = pModule->moduleInfo.associationTag;
274  target.serviceId = (target.associationTag == INVALID_ASSOCIATION_TAG) ?
275  DSC_DataCrslGetPid(pDC) : DSC_DataCrslGetServiceId(pDC);
276  target.u.pModule = pModule;
277  sfPriority = DSC_ModulePriority(pModule);
278  }
279  err = DSC_SectionFilterStart( idp, &target, sfPriority, &pModule->pDdbSf );
280  DEBUG_CHK( err == CLDSM_OK,
281  dsmDP1(("ERROR: DSC_ModuleAcquireRestart %u\n", err)));
282  return err;
283 }
284 
289 {
290  dsmAssert((idp != NULL));
291  dsmAssert((pModule != NULL));
292 
293  LLRemove( pModule, MODULE_ACQUIRE_LIST );
294 
295  /* -- Stop DDB section filter (also Nulls reference in Module) */
296  dsmAssert((pModule->pDdbSf));
297  DSC_SectionFilterStop( idp, &pModule->pDdbSf );
298 }
299 
300 /* /////////////////////////////////////////////////////////////////////////////
301 //
303 void DSC_ModuleDelete( P_DsmCoreInst idp, P_Module pModule )
304 {
305  P_DataCarousel pDC;
306  BOOLEAN inList;
307 
308  dsmAssert((idp != NULL));
309  dsmAssert((pModule != NULL));
310 
311  pDC = LLParent( pModule, DC_MODULE_LIST );
312  dsmAssert((pDC != NULL));
313 
314  DBGLOG(DD_MOD, "pModule->status=%d", pModule->status)
315  /* -- Determine which related section filters etc. to stop */
316  switch (pModule->status)
317  {
318  case MS_INITIAL:
319  /* -- Nothing to do */
320  break;
321 
322  case MS_PENDING_INFO:
323  /* -- DII request must be made */
324  DSC_DataCrslAcquireStop( idp, pDC, SF_PRIORITY_HIGH );
325  break;
326 
327  case MS_PENDING_DDB:
328  /* -- DII monitor must be active */
329  DSC_DataCrslAcquireStop( idp, pDC, SF_PRIORITY_LOW );
330 
331  /*
332  -- If module is in acquire list then stop acquisition.
333  -- NB. Module is only put in acquire list when section filter
334  -- start (or resulting SI query start) is successful.
335  */
336  inList = LLCheckInListId( MODULE_ACQUIRE_LIST, pModule );
337  if (inList)
338  {
339  DSC_ModuleAcquireStop( idp, pModule );
340  }
341  break;
342 
343  case MS_BUILDING:
344  /* -- DII monitor must be active and section filter
345  -- started so stop them */
346  DSC_DataCrslAcquireStop( idp, pDC, SF_PRIORITY_LOW );
347  DSC_ModuleAcquireStop( idp, pModule );
348  break;
349 
350  case MS_CACHED:
351  case MS_ACQ_ABORTED:
352  /* TODO: -- Only remove DII monitor here if module is
353  transparently cached ? */
354  DSC_DataCrslAcquireStop( idp, pDC, SF_PRIORITY_LOW );
355  break;
356 
357  case MS_ACQ_FAILED: /* -> Transient state */
358  case MS_EXPIRED: /* -> Module already deleted! */
359  default:
360  /* -- This should not be called if module is in any other state */
361  dsmAssert((0));
362  break;
363  }
364 
365  /* -- Unlink module from any remaining lists */
366  LLRemoveFromAll( pModule, NUM_LISTS_MODULE );
367 
368  /* -- Abort any loadRequests waiting on this module */
369  /* -- NB. Must do this here because hOC must be finished with in case
370  -- it is unloaded/destroyed from notify callback */
371  DSC_ModuleAbortLoadRequests( idp, pModule );
372 
373  /* -- Delete/destroy module */
374  if (pModule->loadedCount > 0)
375  {
376  /* -- When this function is called, any loaded modules must be in
377  -- cached state */
378  dsmAssert((pModule->status == MS_CACHED));
379  pModule->status = MS_EXPIRED;
380  LLInsertHead( idp->llcExpiredModules, pModule );
381  }
382  else
383  {
384  DSC_ModuleDestroy( idp, pModule );
385  }
386 }
387 
389 {
390  P_RootLoadRqst pLoadRqst;
391  P_DataCarousel pDC;
392  pLoadRqst = pModule->pLoadRqst;
393  pDC = LLParent( pModule, DC_MODULE_LIST );
394  DSC_ModuleDelete( idp, pModule );
395  if (pLoadRqst)
396  {
397  DSC_LoadRsqtFinalNotify( idp, pLoadRqst, LRS_ABORTED_LOAD_ERROR );
398  }
399  else if (!LLCount(pDC->llcDcModules))
400  {
401  DSC_DataCrslDestroy( idp, pDC );
402  }
403 }
404 
405 /*
406  *
407  */
408 E_DscError DSC_ModuleDataRefresh( P_DsmCoreInst idp, P_Module pModule )
409 {
410  E_DscError err;
411  P_DataCarousel pDC;
412 
413  /* -- Update cache status of object's module according to
414  -- module's currently set caching rules */
415  /* -- Module must not have an active section filter */
416  dsmAssert((pModule->pDdbSf == NULL));
417 
418  /* -- Is there any outstanding load requests on module, or recently loaded request */
419  if (pModule->llcLoadRequests != NULL ||
420  (pModule->cachedTime + CACHE0_TIMEOUT_MS) > STB_OSGetClockMilliseconds())
421  {
422  /* special case where related files have been just loaded on same module with CCP0 */
423  pModule->cachingRules = CACHE_RULES_DEFAULT;
424 
425  DBG3(DD_MOD,"Up-to-date module %p, status %u, upd %u, now %u",
426  pModule, pModule->status, pModule->cachedTime, STB_OSGetClockMilliseconds())
427 
428  err = CLDSM_DUPLICATE_REQUEST;
429  }
430  else
431  {
432  DBG2(DD_MOD,"REFRESH module %p, status %u, lc %u, upd %u, now %u",
433  pModule, pModule->status, pModule->loadedCount, pModule->cachedTime, STB_OSGetClockMilliseconds())
434 
435  pDC = (P_DataCarousel)LLParent( pModule, DC_MODULE_LIST );
436 
437  dsmAssert((pModule->moduleInfo.blockSize == pDC->diiInfo.blockSize));
438  dsmAssert((pModule->moduleInfo.associationTag == pDC->tap.associationTag));
439 
440  if (pModule->pModuleBuilder)
441  {
442  builderDestroy( idp, &pModule->pModuleBuilder );
443  }
444  if (pModule->hCompModuleData)
445  {
446  dsmAssert((pModule->hCompModuleData != pModule->hModuleData));
447  moduleDataDestroy( idp, &pModule->hCompModuleData );
448  }
449  if (pModule->hModuleData)
450  {
451  moduleDataDestroy( idp, &pModule->hModuleData );
452  }
453  pModule->decompressFailureCount = 0;
454  pModule->cachingRules = CACHE_RULES_DEFAULT;
455  pModule->status = MS_PENDING_DDB;
456 
457  if (DSC_DataCrslFirstModule(pDC) == pModule &&
458  DSC_RootCrslSrgObjectReset(LLParent(pDC, OC_DATA_CAROUSEL_LIST)) == CLDSM_OK)
459  {
460  err = DSC_ModuleAcquireStart( idp, pModule, SF_PRIORITY_DIRECT );
461  }
462  else
463  {
464  err = DSC_ModuleAcquireStart( idp, pModule, SF_PRIORITY_CLEAR );
465  }
466  }
467  return err;
468 }
469 
470 /* /////////////////////////////////////////////////////////////////////////////
471 // DSC_ModuleResetState
472 // NB. Does not alter any attached load requests, client request count
473 // or value of module currentUseCount.
475 void DSC_ModuleResetState( P_DsmCoreInst idp,
476  P_Module pModule, E_ModuleStatus reqdState )
477 {
478  P_DataCarousel pDC;
479  dsmDP3(("DSC_ModuleResetState()\n"));
480  dsmAssert((idp != NULL));
481  dsmAssert((pModule != NULL));
482 
483 
484  /* -- Check that the module has no loaded objects associated */
485  dsmAssert((pModule->loadedCount == 0));
486 
487  switch (reqdState)
488  {
489  case MS_PENDING_INFO:
490 
491  /* -- Reset acquisitionFailureCount because module parameters will
492  -- be re-acquired */
493  pModule->decompressFailureCount = 0;
494  memset( &pModule->moduleInfo, 0, sizeof(S_ModuleInfo) );
495 
496  pDC = (P_DataCarousel)LLParent( pModule, DC_MODULE_LIST );
497  dsmAssert((pDC != NULL));
498  pModule->moduleInfo.blockSize = pDC->diiInfo.blockSize;
499  pModule->moduleInfo.associationTag = pDC->tap.associationTag;
500  pModule->cachingRules = CACHE_RULES_DEFAULT;
501 
502  if (pModule->pModuleBuilder)
503  {
504  builderDestroy( idp, &pModule->pModuleBuilder );
505  }
506  if (pModule->hCompModuleData)
507  {
508  dsmAssert((pModule->hCompModuleData != pModule->hModuleData));
509  moduleDataDestroy( idp, &pModule->hCompModuleData );
510  }
511  if (pModule->hModuleData)
512  {
513  moduleDataDestroy( idp, &pModule->hModuleData );
514  }
515 
516  pModule->status = MS_PENDING_INFO;
517  break;
518 
519 
520  case MS_ACQ_FAILED:
521 
522  /* -- NB. Don't reset decompressFailureCount since module
523  -- parameters are not being changed */
524 
525  pModule->cachingRules = CACHE_RULES_DEFAULT;
526 
527  if (pModule->pModuleBuilder)
528  {
529  builderDestroy( idp, &pModule->pModuleBuilder );
530  }
531  if (pModule->hCompModuleData)
532  {
533  dsmAssert((pModule->hCompModuleData != pModule->hModuleData));
534  moduleDataDestroy( idp, &pModule->hCompModuleData );
535  }
536  if (pModule->hModuleData)
537  {
538  moduleDataDestroy( idp, &pModule->hModuleData );
539  }
540 
541  pModule->status = MS_ACQ_FAILED;
542  break;
543 
544 
545  case MS_ACQ_ABORTED:
546 
547  /* -- NB. Don't reset decompressFailureCount since module
548  -- parameters are not being changed */
549 
550  pModule->cachingRules = CACHE_RULES_DEFAULT;
551 
552  if (pModule->pModuleBuilder)
553  {
554  builderDestroy( idp, &pModule->pModuleBuilder );
555  }
556  if (pModule->hCompModuleData)
557  {
558  dsmAssert((pModule->hCompModuleData != pModule->hModuleData));
559  moduleDataDestroy( idp, &pModule->hCompModuleData );
560  }
561  if (pModule->hModuleData)
562  {
563  moduleDataDestroy( idp, &pModule->hModuleData );
564  }
565  pModule->status = MS_ACQ_ABORTED;
566  break;
567 
568  default:
569  /* -- Illegal status */
570  dsmDP1(("ERROR: Illegal requested module state = %u\n", reqdState));
571  dsmAssert((0));
572  break;
573  }
574 
575  dsmDP3(("exit DSC_ModuleResetState\n"));
576 }
577 
578 static void RemoveAnyDuplicate( P_DsmCoreInst idp, P_Module pModule )
579 {
580  P_Module pModuleFromList, pNextModule;
581  ListId_t moduleListId;
582  P_DataCarousel pDC;
583  pDC = (P_DataCarousel)LLParent( pModule, MODULE_ACQUIRE_LIST );
584  if (pDC != NULL)
585  {
586  /* Is this the DC we want? */
587  /* go through all MODULES */
588  /* Get listId and first module in list from Control block */
589  moduleListId = LListId( pDC->llcDcModules );
590  pModuleFromList = (P_Module)LLHead( pDC->llcDcModules );
591 
592  /* Go through each module in list until the one with a matching moduleId
593  is found */
594  while (pModuleFromList)
595  {
596  pNextModule = LLNext( pModuleFromList, moduleListId );
597  if (pModuleFromList != pModule &&
598  pModuleFromList->moduleInfo.moduleId == pModule->moduleInfo.moduleId &&
599  pModuleFromList->moduleInfo.version == pModule->moduleInfo.version)
600  {
601  DSC_ModuleDelete( idp, pModuleFromList );
602  }
603  pModuleFromList = pNextModule;
604  }
605  }
606 }
607 
608 /*
609 -- Decompress a cached module
610 --
611 -- If decompress fails then request module to be re-acquired (until failure
612 -- limit reached when error generated).
613 --
614 */
615 E_DscError DSC_ModuleDecompress( P_DsmCoreInst idp, P_Module pModule )
616 {
617  E_DscError err = CLDSM_OK;
618  P_ModuleData hDecompModuleData = NULL;
619 
620  dsmDP3(("decompressCachedModule()\n"));
621  dsmAssert((idp != NULL));
622  dsmAssert((pModule != NULL));
623 
624  /* -- Mark current module used since this function allocates cache
625  -- memory and we don't want the module to be deleted! */
626  DSC_ModuleUse( idp, pModule );
627 
628  dsmAssert((pModule->hCompModuleData != NULL));
629  dsmAssert((pModule->hModuleData == NULL));
630 
631  err = moduleDecompress( idp,
632  pModule->moduleInfo.moduleSize,
633  pModule->moduleInfo.originalSize,
634  pModule->hCompModuleData, &hDecompModuleData );
635 
636  if (!err)
637  {
638  if (hDecompModuleData != NULL)
639  {
640  /* -- Decompress successful */
641  dsmDP3(("INFO: Module Id: %u decompressed\n",
642  pModule->moduleInfo.moduleId));
643  moduleDataDestroy( idp, &pModule->hCompModuleData );
644  pModule->hModuleData = hDecompModuleData;
645  pModule->decompressFailureCount = 0;
646  }
647  else
648  {
649  dsmDP1(("ERROR: Module Id: %u Rcvd: 0x%x Size: %d decompression failure - ",
650  pModule->moduleInfo.moduleId, pModule->moduleInfo.blkRcvd, pModule->moduleInfo.moduleSize));
651  /*
652  -- This may be a 'transmission' error (v.unlikely) or
653  -- a broadcast error (most likely - but will probably
654  -- be present in every module/DDB set).
655  -- Module is re-acquired one or more times (up to
656  -- DSM_MAX_MODULE_ACQUISITION_FAILURES). If it was
657  -- still not decompressed successfully an error
658  -- is generated which causes acquisition to be aborted.
659  */
660  pModule->decompressFailureCount++;
661  if (pModule->decompressFailureCount >=
662  MAX_MODULE_DECOMPRESS_FAILURES)
663  {
664  /* -- Abort module */
665  dsmDP1(("abort\n"));
666  /* -- NB. This destroys erroneous compressed module data
667  -- but does not alter decompressFailureCount */
668  DSC_ModuleResetState( idp, pModule, MS_ACQ_ABORTED);
669  err = CLDSM_ERR_MODULE_ACQUISITION_FAILURE;
670  }
671  else
672  {
673  dsmDP1(("continue\n"));
674  /* -- NB. This destroys erroneous compressed module data
675  -- but does not alter decompressFailureCount */
676  DSC_ModuleResetState( idp, pModule, MS_ACQ_FAILED);
677  /* signal need to re-try */
678  err = CLDSM_ERR_END_OF_DATA;
679  }
680  }
681  }
682  /* -- Finished using current module */
683  DSC_ModuleUnUse( idp, pModule );
684  DBGERRCHK(err)
685  return err;
686 }
687 
688 static E_DscError ModuleUpdateSsu( P_DsmCoreInst idp, P_Module pModule )
689 {
690  E_DscError err = CLDSM_OK;
691  P_DataCarousel pDC;
692  P_RootLoadRqst pLoadRqst;
693  pDC = LLParent(pModule, DC_MODULE_LIST);
694  pLoadRqst = pModule->pLoadRqst;
695  dsmAssert((pModule->status == MS_CACHED));
696  if (pModule->hModuleData == NULL)
697  {
698  err = DSC_ModuleDecompress( idp, pModule );
699  if (err)
700  {
701  ERRLOG(DD_MOD,"Decompress failed modId=%x err=%d", pModule->moduleInfo.moduleId, err)
702  }
703  }
704  if (pModule->hModuleData != NULL && pLoadRqst != NULL)
705  {
706  // TODO - could double check that pLoadRqst is in DC's list.
707  dsmAssert((idp->setup.ssuFuncs.saveModuleData != NULL));
708  dsmAssert((pLoadRqst->remaining >= pModule->moduleInfo.originalSize));
709 
710  idp->setup.ssuFuncs.saveModuleData( pLoadRqst->usrRef, MAKE_MODULE_REF(pDC->dataCarouselId, pModule->moduleInfo.moduleId),
711  pModule->moduleInfo.u.ssup.offset, pModule->moduleInfo.originalSize, moduleDataPtr(pModule->hModuleData) );
712 
713  pModule->pLoadRqst = NULL;
714 
715  if (pLoadRqst->remaining < pModule->moduleInfo.originalSize)
716  {
717  DSC_LoadRsqtAbort( idp, pLoadRqst );
718  }
719  else
720  {
721  pLoadRqst->remaining -= pModule->moduleInfo.originalSize;
722  if (pLoadRqst->remaining == 0)
723  {
724  DSC_LoadRsqtFinalNotify( idp, pLoadRqst, LRS_LOADED );
725  }
726  }
727  }
728  DBGERRCHK(err)
729  return err;
730 }
731 
732 #include "defMemUtilsContig.h" /* -- Default mem type for function */
733 
734 /* /////////////////////////////////////////////////////////////////////////////
735 // DSC_ModuleUpdate
736 // Builds modules given DDB data section. pCompleted returns true if module
737 // completed with this DDB data section.
739 E_DscError DSC_ModuleUpdate( P_DsmCoreInst idp,
740  P_Module pModule, U8BIT *pDDBMsgPayload, U16BIT ddbMsgPayloadLen )
741 {
742  U8BIT moduleVersion;
743  U16BIT ddbBlockSize;
744  U16BIT blockNum;
745  E_DscError err = CLDSM_OK;
746  P_ModuleInfo pModInfo;
747  P_ModuleData hBuiltModuleData = NULL;
748 
749  dsmAssert((idp != NULL));
750  dsmAssert((pModule != NULL));
751  dsmAssert((pDDBMsgPayload != NULL));
752  dsmAssert((ddbMsgPayloadLen >= DDB_MSG_PAYLOAD_HDR_LEN));
753 
754  pModInfo = &pModule->moduleInfo;
755 
756  /* -- Parse DDB data section to extract module version, blockNumber */
757 
758  /* -- pDDBMsgPayload -> moduleId */
759 
760  /* -- Skip moduleId */
761  SET_POS_REL( pDDBMsgPayload, 2 );
762 
763  /* -- Read moduleVersion */
764  READ_UINT8( pDDBMsgPayload, moduleVersion );
765 
766  /* -- Skip reserved data */
767  SET_POS_REL( pDDBMsgPayload, 1 );
768 
769  /* -- Calculate blockSize */
770  ddbBlockSize = (U16BIT)(ddbMsgPayloadLen - DDB_MSG_PAYLOAD_HDR_LEN);
771 
772  if (moduleVersion != pModInfo->version)
773  {
774  /*
775  -- Different module version received before updated DII acquired,
776  -- Discard unexpected DDB version since we cannot use it until
777  -- updated DII info arrives (current state of module build data
778  -- will then be destroyed and module acquistion restarted for
779  -- new module version).
780  */
781  dsmDP3(("INFO: Module Id: %u version change at DDB (ver expd: %u, rcvd: %u) - DDB discarded\n",
782  pModInfo->moduleId, pModInfo->version, moduleVersion));
783  }
784  else if (ddbBlockSize > pModInfo->blockSize) /* check blockSize is legal */
785  {
786  dsmDP1(("DATA ERROR: DDB Block size != DII Block size: %u, %u\n",
787  ddbBlockSize, pModInfo->blockSize));
788  }
789  else
790  {
791  /* -- Create module builder if necessary */
792  if (pModule->pModuleBuilder == NULL)
793  {
794  err = builderCreate( idp, pModInfo->moduleSize,
795  pModInfo->blockSize, &pModule->pModuleBuilder );
796  pModule->status = MS_BUILDING;
797  }
798  if (err)
799  {
800  DSC_ModuleDeleteDcTidyUp( idp, pModule );
801  }
802  else
803  {
804  /* -- Read blockNumber */
805  READ_UINT16( pDDBMsgPayload, blockNum );
806 
807  dsmDP3(("Mod %d: Blk=%d sz=%d rcvd=%x\n", pModInfo->moduleId, blockNum, ddbBlockSize, pModInfo->blkRcvd));
808  #ifndef NDEBUG
809  pModInfo->blkRcvd |= 1 << blockNum;
810  #endif
811  /* -- pDDBMsgPayload -> first blockDataByte */
812 
813  /* -- Send DDB data to module builder */
814  builderConstruct( idp, pModule->pModuleBuilder, blockNum,
815  ddbBlockSize, pDDBMsgPayload, &hBuiltModuleData );
816 
817  if (hBuiltModuleData)
818  {
819  /* -- Module completed */
820  builderDestroy( idp, &pModule->pModuleBuilder );
821  if (pModInfo->crslMagic == UC_MAGIC &&
822  pModInfo->u.ssup.moduleCrc != 0)
823  {
824  U32BIT crc = CDSM_UtilCalculateCRC(moduleDataPtr(hBuiltModuleData),pModInfo->moduleSize);
825  if (crc != pModInfo->u.ssup.moduleCrc)
826  {
827  ERRLOG(DD_MOD,"DATA ERROR: crc MIS-MATCH: %u, %u", crc, pModInfo->u.ssup.moduleCrc)
828  err = CLDSM_ERR_END_OF_DATA;
829  }
830  }
831  if (!err && pModInfo->compressed)
832  {
833  dsmAssert((pModule->hModuleData == NULL));
834  dsmAssert((pModule->hCompModuleData == NULL));
835  pModule->hCompModuleData = hBuiltModuleData;
836  if (pModule->llcLoadRequests)
837  {
838  err = DSC_ModuleDecompress( idp, pModule );
839  }
840  }
841  else
842  {
843  dsmAssert((pModule->hModuleData == NULL));
844  pModule->hModuleData = hBuiltModuleData;
845  }
846  if (err == CLDSM_ERR_END_OF_DATA)
847  {
848  /* Decompression failure so re-acquire module.
849  * NB. Module acquisition (section filter) is still active so no
850  * need to call DSC_ModuleAcquireStart() */
851  pModule->status = MS_PENDING_DDB;
852  err = CLDSM_OK;
853  }
854  else if (err)
855  {
856  /* -- Error decompressing module. Stop acquiring module (remove section filter ) */
857  DSC_ModuleAcquireStop( idp, pModule );
858  DSC_ModuleAbortLoadRequests( idp, pModule );
859  }
860  else
861  {
862  pModule->cachedTime = STB_OSGetClockMilliseconds();
863  pModule->status = MS_CACHED;
864  DSC_ModuleAcquireStop( idp, pModule );
865  RemoveAnyDuplicate( idp, pModule );
866  if (pModInfo->crslMagic == UC_MAGIC)
867  {
868  ModuleUpdateSsu( idp, pModule );
869  }
870  else if (pModInfo->crslMagic == OC_MAGIC)
871  {
872  /* Object Carousel data */
873  err = lmUpdateModule( idp, pModule );
874  }
875  }
876  }
877  else
878  {
879  sectionTimerUpdate(idp, pModule->pDdbSf, FALSE, FALSE);
880  }
881  }
882  }
883  DBGERRCHK(err)
884  return err;
885 }
886 
887 /* Module List Functions */
888 
889 /* /////////////////////////////////////////////////////////////////////////////
890 // DSC_ModuleListFindById
891 // Returns NULL in phModule if moduleId not found
893 P_Module DSC_ModuleListFindById( P_LLControl pModuleList, U16BIT moduleId )
894 {
895  P_Module pModuleFromList;
896  ListId_t listId;
897 
898  /* Get listId and first module in list from Control block */
899  listId = LListId( pModuleList );
900  pModuleFromList = (P_Module)LLHead( pModuleList );
901 
902  /* Go through each module in list until the one with a matching moduleId
903  is found */
904  while (pModuleFromList)
905  {
906  /* Is this the module we want? */
907  if (pModuleFromList->moduleInfo.moduleId == moduleId)
908  {
909  /* Found the module */
910  break;
911  }
912  pModuleFromList = LLNext( pModuleFromList, listId );
913  }
914  dsmDP3(("exit DSC_ModuleListFindById: %p\n", pModuleFromList));
915  return pModuleFromList;
916 }
917 
918 /*------------------------------ Local Functions -----------------------------*/
919 
920 /* /////////////////////////////////////////////////////////////////////////////
921 // builderCreate
922 // Creates an instance of the ModuleBuilder struct, and initialises it.
924 static E_DscError builderCreate( P_DsmCoreInst idp,
925  U32BIT moduleSize, U16BIT blockSize,
926  P_ModuleBuilder *ppModuleBuilder )
927 {
928  P_ModuleBuilder pModuleBuilder = NULL;
929  E_DscError err;
930  P_ModuleData hModuleData = NULL;
931  U16BIT loop;
932 
933  dsmDP3(("builderCreate( %u, %u, %p )\n",
934  moduleSize, blockSize, ppModuleBuilder));
935  dsmAssert((idp != NULL));
936  dsmAssert((moduleSize > 0));
937  dsmAssert((blockSize > 0));
938  dsmAssert((ppModuleBuilder != NULL));
939 
940  /* -- Allocate store for moduleBuilder records */
941  pModuleBuilder = (P_ModuleBuilder)DSC_CmMemGet( idp, sizeof(S_ModuleBuilder) );
942  if (!pModuleBuilder)
943  {
944  err = CLDSM_ERR_MEM_HEAP_FULL;
945  }
946  else
947  {
948  /* -- Allocate store for broadcast module data */
949  err = moduleDataCreate( idp, moduleSize, &hModuleData );
950  if (err)
951  {
952  DSC_CmMemRelease( idp, pModuleBuilder );
953  pModuleBuilder = NULL;
954  }
955  else
956  {
957  pModuleBuilder->blockSize = blockSize;
958  pModuleBuilder->downloadSize = moduleSize;
959 
960  /* -- Calculate number of data blocks (DDBs) in the module */
961  pModuleBuilder->numBlocks =
962  (U16BIT)((moduleSize + blockSize - 1) / blockSize);
963 
964  pModuleBuilder->blocksRqd = pModuleBuilder->numBlocks;
965 
966  if (pModuleBuilder->numBlocks > MAX_BLOCKS_IN_MODULE)
967  {
968  /* -- FATAL ERROR */
969  err = CLDSM_ERR_MODULE_TOO_LARGE;
970  moduleDataDestroy( idp, &hModuleData );
971  DSC_CmMemRelease( idp, pModuleBuilder );
972  pModuleBuilder = NULL;
973  }
974  else
975  {
976  /* -- Attach moduleData store to moduleBuilder */
977  pModuleBuilder->hModuleData = hModuleData;
978 
979  /* -- Clear register of which data blocks have been received */
980  loop = (pModuleBuilder->numBlocks + 7) >> 3;
981  while (loop--)
982  {
983  pModuleBuilder->blockRcvdRegister[loop] = 0x00;
984  }
985  err = CLDSM_OK;
986  }
987  }
988  }
989 
990  *ppModuleBuilder = pModuleBuilder;
991 
992  DEBUG_CHK( err == CLDSM_OK,
993  dsmDP1(("ERROR: builderCreate: %u\n", err)));
994  dsmDP3(("exit builderCreate -> rtn: %u\n", err));
995  return err;
996 }
997 
998 /* /////////////////////////////////////////////////////////////////////////////
999 // builderDestroy
1000 // Destroys an instance of the ModuleBuilder struct, and associated data.
1002 static void builderDestroy( P_DsmCoreInst idp, P_ModuleBuilder *ppModuleBuilder )
1003 {
1004  P_ModuleBuilder pModuleBuilder = NULL;
1005 
1006  dsmDP3(("builderDestroy( %p )\n", ppModuleBuilder));
1007  dsmAssert((idp != NULL));
1008  dsmAssert((ppModuleBuilder != NULL));
1009  dsmAssert((*ppModuleBuilder != NULL));
1010 
1011  pModuleBuilder = *ppModuleBuilder;
1012  if (pModuleBuilder->hModuleData)
1013  moduleDataDestroy( idp, &pModuleBuilder->hModuleData );
1014  DSC_CmMemRelease( idp, *ppModuleBuilder );
1015  *ppModuleBuilder = NULL;
1016 
1017  dsmDP3(("exit builderDestroy\n"));
1018 }
1019 
1020 #include "defMemUtilsMgd.h" /* -- Default mem type for function */
1021 
1022 /* /////////////////////////////////////////////////////////////////////////////
1023 // builderConstruct
1024 // Assembles a Module. pDDBData must point to the start of the DDB Block Data.
1025 // ddbDataSize is the size in bytes of the Block Data. blockNum starts from 0.
1027 static void builderConstruct( P_DsmCoreInst idp, P_ModuleBuilder pModuleBuilder,
1028  U16BIT blockNum, U16BIT ddbDataSize, U8BIT *pDDBData, P_ModuleData *phModuleData )
1029 {
1030  MemPtr mpModuleData;
1031  U32BIT offset;
1032  U16BIT regByteNum;
1033  U8BIT regBitPos;
1034 
1035  dsmDP3(("builderConstruct( %p, %u, %u, %p, %p )\n",
1036  pModuleBuilder, blockNum, ddbDataSize, pDDBData, phModuleData));
1037  dsmAssert((pModuleBuilder != NULL));
1038  dsmAssert((pDDBData != NULL));
1039  dsmAssert((phModuleData != NULL));
1040 
1041  offset = blockNum * pModuleBuilder->blockSize;
1042  if ((blockNum < pModuleBuilder->numBlocks) &&
1043  (offset + ddbDataSize <= pModuleBuilder->downloadSize))
1044  {
1045  regByteNum = (U16BIT)(blockNum >> 3);
1046  regBitPos = (U8BIT)(0x01 << (blockNum & 0x0007));
1047 
1048  if (!(pModuleBuilder->blockRcvdRegister[regByteNum] & regBitPos))
1049  {
1050  /* -- Have not got this block yet - so build into moduleData */
1051  MEMPTR_SEQ_OPEN( MEM_CONTEXT, moduleDataPtr(pModuleBuilder->hModuleData), offset,
1052  pModuleBuilder->downloadSize - offset, FALSE, mpModuleData );
1053 
1054  MEMPTR_WRITE( pDDBData, mpModuleData, ddbDataSize );
1055 
1056  MEMPTR_SEQ_CLOSE( MEM_CONTEXT, pModuleBuilder->hModuleData,
1057  mpModuleData );
1058 
1059  /* -- Mark block as received */
1060  pModuleBuilder->blockRcvdRegister[regByteNum] |= regBitPos;
1061  pModuleBuilder->blocksRqd--;
1062 
1063  if (pModuleBuilder->blocksRqd == 0)
1064  {
1065  /* -- Module is now completed */
1066 
1067  /* -- Pass moduleData handle back to calling routine */
1068  *phModuleData = pModuleBuilder->hModuleData;
1069 
1070  /* -- NULL builder copy of moduleData handle */
1071  pModuleBuilder->hModuleData = NULL;
1072  }
1073  }
1074  }
1075  else
1076  {
1077  /* -- Discard erroneous module block */
1078  dsmDP1(("DATA ERROR: builderConstruct (Current blockNum > Total numBlocks): %u, %u\n",
1079  blockNum, pModuleBuilder->numBlocks));
1080  dsmDP1(("OR: (offset + ddbDataSize > pModuleBuilder->downloadSize): %u, %u, %u\n",
1081  offset, ddbDataSize, pModuleBuilder->downloadSize));
1082  }
1083  dsmDP3(("exit builderConstruct\n"));
1084 }
1085 
1086 E_DscError DSC_ModuleAddLoadRequest( P_DsmCoreInst idp, P_Module pModule, H_Object hLoadRqst )
1087 {
1088  E_DscError err;
1089  dsmAssert((pModule != NULL));
1090 
1091  if (pModule->llcLoadRequests != NULL)
1092  {
1093  err = CLDSM_OK;
1094  }
1095  else
1096  {
1097  err = LLCreate( idp, pModule, MODULE_LOAD_REQUEST_LIST, &pModule->llcLoadRequests );
1098  }
1099  if (!err)
1100  {
1101  LLInsertHead( pModule->llcLoadRequests, hLoadRqst );
1102  switch (DSC_LoadRsqtPriority((P_RootLoadRqst)hLoadRqst))
1103  {
1104  case SF_PRIORITY_HIGH:
1105  {
1106  pModule->highPriorityCount++;
1107  break;
1108  }
1109  case SF_PRIORITY_DIRECT:
1110  {
1111  pModule->directPriorityCount++;
1112  break;
1113  }
1114  default:;
1115  }
1116  }
1117  return err;
1118 }
1119 
1120 BOOLEAN DSC_ModuleRemoveLoadRequest( P_DsmCoreInst idp, H_Object hLoadRqst )
1121 {
1122  P_Module pModule;
1123  BOOLEAN isEmpty;
1124 
1125  pModule = (P_Module)LLParent( hLoadRqst, MODULE_LOAD_REQUEST_LIST );
1126  isEmpty = LLRemove( hLoadRqst, MODULE_LOAD_REQUEST_LIST );
1127  if (memValidate(pModule))
1128  {
1129  switch (DSC_LoadRsqtPriority((P_RootLoadRqst)hLoadRqst))
1130  {
1131  case SF_PRIORITY_HIGH:
1132  {
1133  dsmAssert((pModule->highPriorityCount > 0));
1134  pModule->highPriorityCount--;
1135  break;
1136  }
1137  case SF_PRIORITY_DIRECT:
1138  {
1139  dsmAssert((pModule->directPriorityCount > 0));
1140  pModule->directPriorityCount--;
1141  break;
1142  }
1143  default:;
1144  }
1145  }
1146  if (isEmpty)
1147  {
1148  /* -- Module loadRequest list is now empty so destroy it */
1149  LLDestroy( idp, &pModule->llcLoadRequests );
1150  }
1151  return isEmpty;
1152 }
1153 
1154 void DSC_ModuleAbortLoadRequests( P_DsmCoreInst idp, P_Module pModule )
1155 {
1156  P_RootLoadRqst pLoadRqst;
1157 
1158  dsmAssert((idp != NULL));
1159  dsmAssert((pModule != NULL));
1160 
1161  if (pModule->llcLoadRequests)
1162  {
1163  pLoadRqst = LLRemoveHead( pModule->llcLoadRequests );
1164  while (pLoadRqst)
1165  {
1166  switch (DSC_LoadRsqtPriority(pLoadRqst))
1167  {
1168  case SF_PRIORITY_HIGH:
1169  {
1170  dsmAssert((pModule->highPriorityCount > 0));
1171  pModule->highPriorityCount--;
1172  break;
1173  }
1174  case SF_PRIORITY_DIRECT:
1175  {
1176  dsmAssert((pModule->directPriorityCount > 0));
1177  pModule->directPriorityCount--;
1178  break;
1179  }
1180  default:;
1181  }
1182 
1183  DSC_LoadRsqtAbort( idp, pLoadRqst );
1184 
1185  /* -- Get next loadRequest */
1186  pLoadRqst = LLRemoveHead( pModule->llcLoadRequests );
1187  }
1188 
1189  /* -- module loadRequest list is now empty so destroy */
1190  LLDestroy( idp, &pModule->llcLoadRequests );
1191  }
1192 }
1193 
1194 E_SFPriority DSC_ModulePriority( P_Module pModule )
1195 {
1196  return (pModule->directPriorityCount) ? SF_PRIORITY_DIRECT :
1197  (pModule->highPriorityCount) ? SF_PRIORITY_HIGH : SF_PRIORITY_LOW;
1198 }
1199 
1200 /*----------------------------------------------------------------------------*/
U32BIT STB_OSGetClockMilliseconds(void)
Get Current Computer Clock Time.
General include file for clDsm library internal definitions.
void DSC_LoadRsqtAbort(P_DsmCoreInst idp, P_RootLoadRqst pLoadRqst)
Force abort (on error) any type of load request Finalise the load request (notify client) and destroy...
Definition: loadRqst.c:157
Header to the loadMgr module.
Header to the sectionTimer module.
Header defining.
Header to the cacheMgr module.
Header to the moduleDecompress module.
void DSC_ModuleDelete(P_DsmCoreInst idp, P_Module pModule)
Destroy the module and destroy parent DC if now empty.
Definition: module.c:303
void DSC_ModuleDeleteDcTidyUp(P_DsmCoreInst idp, P_Module pModule)
Delete module and destroy parent DC if now empty.
Definition: module.c:388
void DSC_ModuleAcquireStop(P_DsmCoreInst idp, P_Module pModule)
Stop aquisition of module.
Definition: module.c:288
E_DscError DSC_ModuleAcquireStart(P_DsmCoreInst idp, P_Module pModule, E_SFPriority sfPriority)
Start aquisition of module.
Definition: module.c:204
E_DscError DSC_ModuleAcquireRestart(P_DsmCoreInst idp, P_Module pModule)
Restart aquisition of module.
Definition: module.c:252
Header to the 'module' module - Functions/methods for creating/destroying and managing attributes of ...
eader to the clDsmUtils module.
Header to the moduleData module.
Function prototypes for operating system.