1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - WM - libraries
3 File: wm_ds.c
4
5 Copyright 2003-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-09-17#$
14 $Rev: 8556 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17
18 #include <nitro/wm.h>
19 #include "wm_arm9_private.h"
20
21
22 /*---------------------------------------------------------------------------*
23 Internal Function Definitions
24 *---------------------------------------------------------------------------*/
25 static void WmDataSharingSetDataCallback(void *callback);
26 static void WmDataSharingReceiveCallback_Parent(void *callback);
27 static void WmDataSharingReceiveCallback_Child(void *callback);
28 static void WmDataSharingReceiveData(WMDataSharingInfo *dsInfo, u16 aid, u16 *data);
29 static void WmDataSharingSendDataSet(WMDataSharingInfo *dsInfo, BOOL delayed);
30 static u16 *WmGetSharedDataAddress(WMDataSharingInfo *dsInfo, u32 aidBitmap, u16 *receiveBuf,
31 u32 aid);
32
33 //// List of port numbers currently being used in data-sharing
34 //static u16 WmDataSharingPortBitmap = 0;
35
WmDataSharingGetNextIndex(u32 index)36 static inline u16 WmDataSharingGetNextIndex(u32 index)
37 {
38 return (u16)((index + 1) % WM_DS_DATASET_NUM);
39 }
40
WmDataSharingGetPrevIndex(u32 index)41 static inline u16 WmDataSharingGetPrevIndex(u32 index)
42 {
43 return (u16)((index + WM_DS_DATASET_NUM - 1) % WM_DS_DATASET_NUM);
44 }
45
46
47 /*---------------------------------------------------------------------------*
48 Name: WM_StartDataSharing
49
50 Description: Enables the data sharing feature.
51
52 Arguments: dsInfo: WMDataSharingInfo structure.
53 port: Number of port to use.
54 aidBitmap: AID bitmap of the other party for performing data sharing.
55 dataLength: Data length of shared memory (specify an even number of bytes)
56 doubleMode: Specify TRUE if using WM_StepDataSharing in every frame.
57
58 Returns: WMErrCode - Returns the processing result.
59 *---------------------------------------------------------------------------*/
60 WMErrCode
WM_StartDataSharing(WMDataSharingInfo * dsInfo,u16 port,u16 aidBitmap,u16 dataLength,BOOL doubleMode)61 WM_StartDataSharing(WMDataSharingInfo *dsInfo, u16 port, u16 aidBitmap, u16 dataLength,
62 BOOL doubleMode)
63 {
64 WMErrCode result;
65 int aid;
66 u16 connectedAIDs = 0x0001;
67
68 // Check the state
69 result = WMi_CheckStateEx(2, WM_STATE_MP_PARENT, WM_STATE_MP_CHILD);
70 WM_CHECK_RESULT(result);
71
72 // Check parameters
73 if (dsInfo == NULL)
74 {
75 WM_WARNING("Parameter \"dsInfo\" must not be NULL.\n");
76 return WM_ERRCODE_INVALID_PARAM;
77 }
78 if (port >= WM_NUM_OF_PORT)
79 {
80 WM_WARNING("Parameter \"port\" must be less than %d.\n", WM_NUM_OF_PORT);
81 return WM_ERRCODE_INVALID_PARAM;
82 }
83 if ((u32)dsInfo & 0x01f)
84 {
85 // Alignment check is a warning only, not an error
86 WM_WARNING("Parameter \"dsInfo\" is not 32-byte aligned.\n");
87 }
88 if (aidBitmap == 0)
89 {
90 WM_WARNING("Parameter \"aidBitmap\" must not be 0.\n");
91 return WM_ERRCODE_INVALID_PARAM;
92 }
93
94 // Get necessary information
95 aid = WM_GetAID();
96 if (aid == 0)
97 {
98 connectedAIDs = WM_GetConnectedAIDs();
99 }
100
101 // Initialize data sharing control variables
102 MI_CpuClearFast(dsInfo, sizeof(WMDataSharingInfo));
103 dsInfo->writeIndex = 0;
104 dsInfo->sendIndex = 0;
105 dsInfo->readIndex = 0;
106 dsInfo->dataLength = dataLength;
107 dsInfo->port = port;
108 dsInfo->aidBitmap = 0;
109 dsInfo->doubleMode = (u16)((doubleMode) ? TRUE : FALSE);
110
111 aidBitmap |= (1 << aid); // Add the self's own portion
112 dsInfo->aidBitmap = aidBitmap;
113
114 {
115 u16 count = MATH_CountPopulation(aidBitmap);
116 dsInfo->stationNumber = count;
117 dsInfo->dataSetLength = (u16)(dataLength * count);
118
119 if (dsInfo->dataSetLength > WM_DS_DATA_SIZE)
120 {
121 // Total data amount exceeds limit
122 dsInfo->aidBitmap = 0;
123 WM_WARNING("Total size of sharing data must be less than or equal to %d bytes.\n",
124 WM_DS_DATA_SIZE);
125 return WM_ERRCODE_INVALID_PARAM;
126 }
127 dsInfo->dataSetLength += 4; // aidBitmap, receivedBitmap
128 }
129
130 dsInfo->state = WM_DS_STATE_START;
131
132 if (aid == 0)
133 {
134 // Parent's start processing
135 int i;
136
137 for (i = 0; i < WM_DS_DATASET_NUM; i++)
138 {
139 dsInfo->ds[i].aidBitmap = (u16)(dsInfo->aidBitmap & (connectedAIDs | 0x0001));
140 }
141
142 (void)WM_SetPortCallback(port, WmDataSharingReceiveCallback_Parent, (void *)dsInfo);
143
144 // Sends empty data for start-up
145 for (i = 0; i < ((dsInfo->doubleMode == TRUE) ? 2 : 1); i++)
146 {
147 int res;
148
149 dsInfo->writeIndex = WmDataSharingGetNextIndex(dsInfo->writeIndex);
150 res =
151 WM_SetMPDataToPortEx(WmDataSharingSetDataCallback, dsInfo, (u16 *)&dsInfo->ds[i],
152 dsInfo->dataSetLength,
153 (u16)(dsInfo->aidBitmap & connectedAIDs), dsInfo->port,
154 WM_PRIORITY_HIGH);
155 if (res == WM_ERRCODE_NO_CHILD)
156 {
157 dsInfo->seqNum[i] = 0xffff;
158 dsInfo->sendIndex = WmDataSharingGetNextIndex(dsInfo->sendIndex);
159 }
160 else
161 {
162 if (res != WM_ERRCODE_SUCCESS && res != WM_ERRCODE_OPERATING)
163 {
164 WM_WARNING("WM_SetMPDataToPort failed during data-sharing. errcode=%x\n", res);
165 dsInfo->state = WM_DS_STATE_ERROR;
166 return WM_ERRCODE_FAILED;
167 }
168 }
169 }
170 }
171 else
172 {
173 // Child's start processing
174 dsInfo->sendIndex = (u16)(WM_DS_DATASET_NUM - 1);
175 (void)WM_SetPortCallback(port, WmDataSharingReceiveCallback_Child, (void *)dsInfo);
176 }
177
178 return WM_ERRCODE_SUCCESS; // Successful completion
179 }
180
181 /*---------------------------------------------------------------------------*
182 Name: WM_EndDataSharing
183
184 Description: Disables the data sharing feature.
185
186 Arguments: dsInfo: WMDataSharingInfo structure.
187
188 Returns: WMErrCode - Returns the processing result.
189 *---------------------------------------------------------------------------*/
WM_EndDataSharing(WMDataSharingInfo * dsInfo)190 WMErrCode WM_EndDataSharing(WMDataSharingInfo *dsInfo)
191 {
192 // Check parameters
193 if (dsInfo == NULL)
194 {
195 WM_WARNING("Parameter \"dsInfo\" must not be NULL.\n");
196 return WM_ERRCODE_INVALID_PARAM;
197 }
198
199 // Checks the data sharing state
200 if (dsInfo->aidBitmap == 0)
201 {
202 WM_WARNING("It is not data-sharing mode now.\n");
203 return WM_ERRCODE_ILLEGAL_STATE;
204 }
205
206 (void)WM_SetPortCallback(dsInfo->port, NULL, NULL);
207 dsInfo->aidBitmap = 0;
208 dsInfo->state = WM_DS_STATE_READY;
209
210 return WM_ERRCODE_SUCCESS; // Successful completion
211 }
212
213 /*---------------------------------------------------------------------------*
214 Name: WM_StepDataSharing
215
216 Description: Advances synchronicity of data sharing by one.
217
218 Arguments: dsInfo: WMDataSharingInfo structure.
219 sendData: Send data that you want to share.
220 receiveData: Received shared data.
221
222 Returns: WMErrCode - Returns the processing result.
223 *_SUCCESS: Shared data send/receive successful.
224 *_NO_DATASET: Next shared data has not come yet.
225 *---------------------------------------------------------------------------*/
WM_StepDataSharing(WMDataSharingInfo * dsInfo,const u16 * sendData,WMDataSet * receiveData)226 WMErrCode WM_StepDataSharing(WMDataSharingInfo *dsInfo, const u16 *sendData, WMDataSet *receiveData)
227 {
228 WMErrCode result;
229 u16 aid;
230 u16 connectedAIDs;
231 u16 state;
232
233 // Check the state
234 result = WMi_CheckStateEx(2, WM_STATE_MP_PARENT, WM_STATE_MP_CHILD);
235 WM_CHECK_RESULT(result);
236
237 // Check parameters
238 if (dsInfo == NULL)
239 {
240 WM_WARNING("Parameter \"dsInfo\" must not be NULL.\n");
241 return WM_ERRCODE_INVALID_PARAM;
242 }
243 if (sendData == NULL)
244 {
245 WM_WARNING("Parameter \"sendData\" must not be NULL.\n");
246 return WM_ERRCODE_INVALID_PARAM;
247 }
248 if (receiveData == NULL)
249 {
250 WM_WARNING("Parameter \"receiveData\" must not be NULL.\n");
251 return WM_ERRCODE_INVALID_PARAM;
252 }
253
254 // Get necessary information
255 aid = WM_GetAID();
256 if (aid == 0)
257 {
258 connectedAIDs = WM_GetConnectedAIDs();
259 }
260
261 // Checks the data sharing state
262 state = dsInfo->state;
263 if (state == WM_DS_STATE_ERROR)
264 {
265 WM_WARNING("An error occurred during data-sharing.\n");
266 return WM_ERRCODE_FAILED;
267 }
268 if (state != WM_DS_STATE_START && state != WM_DS_STATE_RETRY_SEND)
269 {
270 WM_WARNING("It is not data-sharing mode now.\n");
271 return WM_ERRCODE_ILLEGAL_STATE;
272 }
273
274 result = WM_ERRCODE_NO_DATASET;
275
276 if (aid == 0)
277 {
278 // If a parent
279 BOOL sendFlag = FALSE;
280 BOOL delayed = FALSE;
281
282 if (state == WM_DS_STATE_RETRY_SEND)
283 {
284 // Resends because the previous time was SEND_QUEUE_FULL
285 int res;
286 int oldWI;
287 dsInfo->state = WM_DS_STATE_START;
288
289 WM_DLOG_DATASHARING("send queue was full. do retry.");
290
291 oldWI = WmDataSharingGetPrevIndex(dsInfo->writeIndex);
292 res =
293 WM_SetMPDataToPortEx(WmDataSharingSetDataCallback, dsInfo,
294 (u16 *)&dsInfo->ds[oldWI], dsInfo->dataSetLength,
295 (u16)(dsInfo->aidBitmap & connectedAIDs), dsInfo->port,
296 WM_PRIORITY_HIGH);
297 if (res == WM_ERRCODE_NO_CHILD)
298 {
299 WM_DLOGF_DATASHARING("sent ds : write: %d, read: %d, send: %d\n",
300 dsInfo->writeIndex, dsInfo->readIndex, dsInfo->sendIndex);
301 dsInfo->seqNum[oldWI] = 0xffff;
302 dsInfo->sendIndex = WmDataSharingGetNextIndex(dsInfo->sendIndex);
303 }
304 else
305 {
306 if (res != WM_ERRCODE_SUCCESS && res != WM_ERRCODE_OPERATING)
307 {
308 WM_WARNING("WM_SetMPDataToPort failed during data-sharing. errcode=%x\n", res);
309 dsInfo->state = WM_DS_STATE_ERROR;
310 return WM_ERRCODE_FAILED;
311 }
312 }
313 }
314
315 // After the parent device has finished sending DataSet, it will be available for use, so decide the limit up to which sendIndex can read.
316 if (dsInfo->readIndex != dsInfo->sendIndex)
317 {
318 // Read processing
319 WM_DLOGF_DATASHARING("read ds : write: %d, read: %d, send: %d, seq#: %d",
320 dsInfo->writeIndex, dsInfo->readIndex, dsInfo->sendIndex,
321 dsInfo->seqNum[dsInfo->readIndex]);
322
323 dsInfo->ds[dsInfo->readIndex].aidBitmap |= 0x0001; // The lowest bit in the aidBitmap in the transmission data is a delay flag.
324 MI_CpuCopy16(&dsInfo->ds[dsInfo->readIndex], receiveData, sizeof(WMDataSet));
325 dsInfo->currentSeqNum = dsInfo->seqNum[dsInfo->readIndex];
326 dsInfo->readIndex = WmDataSharingGetNextIndex(dsInfo->readIndex);
327
328 sendFlag = TRUE;
329 result = WM_ERRCODE_SUCCESS;
330 if (dsInfo->doubleMode == FALSE && connectedAIDs != 0
331 && dsInfo->ds[dsInfo->writeIndex].aidBitmap == 0x0001)
332 {
333 // If the parent sets data, it can be sent immediately = only the parent has frame shifts.
334 delayed = TRUE;
335 }
336 else
337 {
338 delayed = FALSE;
339 }
340 }
341
342 // Sends the DataSet when the data for all the devices is ready in the send buffer
343 WmDataSharingSendDataSet(dsInfo, FALSE);
344
345 if (sendFlag)
346 {
347 // The parent inserts into its own buffer instead of sending over wireless
348 WM_DLOGF_DATASHARING("send data : write: %d, read: %d, send: %d", dsInfo->writeIndex,
349 dsInfo->readIndex, dsInfo->sendIndex);
350
351 WmDataSharingReceiveData(dsInfo, 0, (u16 *)sendData); // Remove const because chained rewrite past here is bothersome.
352
353 if (dsInfo->doubleMode == FALSE)
354 {
355 // When and only when there is not a Step in each frame, DataSet needs to be prepared at this time for sending with GF.
356 //
357 // Sends the DataSet when the data for all the devices is ready in the send buffer
358 WmDataSharingSendDataSet(dsInfo, delayed);
359 }
360 }
361 }
362 else
363 {
364 // If a child
365 BOOL sendFlag = FALSE;
366
367 if (state == WM_DS_STATE_RETRY_SEND)
368 {
369 // Resends because the previous time was SEND_QUEUE_FULL
370 sendFlag = TRUE;
371 dsInfo->state = WM_DS_STATE_START;
372 WM_DLOG_DATASHARING("send queue was full. do retry.");
373 }
374 else
375 {
376 // After the child device has finished receiving DataSet, it will be available for use, so decide the limit up to which writeIndex can read.
377 if (dsInfo->readIndex != dsInfo->writeIndex)
378 {
379 // If the delay flag is down, it is forcibly delayed by one frame.
380 // The lowest bit in the aidBitmap in the transmission data is a delay flag.
381 if (!(dsInfo->ds[dsInfo->readIndex].aidBitmap & 0x0001))
382 {
383 dsInfo->ds[dsInfo->readIndex].aidBitmap |= 0x0001;
384 }
385 else
386 {
387 // Read processing
388 WM_DLOGF_DATASHARING("read ds : write: %d, read: %d, send: %d, seq#: %d",
389 dsInfo->writeIndex, dsInfo->readIndex, dsInfo->sendIndex,
390 dsInfo->seqNum[dsInfo->readIndex]);
391 MI_CpuCopy16(&dsInfo->ds[dsInfo->readIndex], receiveData, sizeof(WMDataSet));
392 dsInfo->currentSeqNum = dsInfo->seqNum[dsInfo->readIndex];
393 dsInfo->readIndex = WmDataSharingGetNextIndex(dsInfo->readIndex);
394
395 sendFlag = TRUE;
396 result = WM_ERRCODE_SUCCESS;
397 }
398 }
399 }
400
401 if (sendFlag)
402 {
403 // The child transmits it as-is
404 int res;
405 // Use part of dsInfo->ds as a send buffer
406 u16 *buf = (u16 *)(((u8 *)&dsInfo->ds[dsInfo->sendIndex]) + 32); // 32-byte alignment is required
407
408 WM_DLOGF_DATASHARING("send data : write: %d, read: %d, send: %d", dsInfo->writeIndex,
409 dsInfo->readIndex, dsInfo->sendIndex);
410
411 MI_CpuCopy16(sendData, buf, dsInfo->dataLength);
412 res =
413 WM_SetMPDataToPortEx(WmDataSharingSetDataCallback, dsInfo, buf, dsInfo->dataLength,
414 dsInfo->aidBitmap, dsInfo->port, WM_PRIORITY_HIGH);
415 dsInfo->sendIndex = WmDataSharingGetNextIndex(dsInfo->sendIndex);
416 if (res != WM_ERRCODE_OPERATING && res != WM_ERRCODE_SUCCESS)
417 {
418 WM_WARNING("WM_SetMPDataToPort failed during data-sharing. errcode=%x\n", res);
419 dsInfo->state = WM_DS_STATE_ERROR;
420 result = WM_ERRCODE_FAILED;
421 }
422 }
423 }
424
425 return result;
426 }
427
428 /*---------------------------------------------------------------------------*
429 Name: WmDataSharingSetDataCallback
430
431 Description: Send completion callback.
432
433 Arguments: callback: A pointer to the callback structure.
434
435 Returns: None.
436 *---------------------------------------------------------------------------*/
WmDataSharingSetDataCallback(void * callback)437 static void WmDataSharingSetDataCallback(void *callback)
438 {
439 WMArm9Buf *p = WMi_GetSystemWork();
440 WMPortSendCallback *cb_Port = (WMPortSendCallback *)callback;
441 WMDataSharingInfo *dsInfo;
442 u16 aid;
443
444 // Checks if WM_EndDataSharing() has been called while DSInfo has been called in a invalid state.
445 dsInfo = (WMDataSharingInfo *)(p->portCallbackArgument[cb_Port->port]);
446 if ((p->portCallbackTable[cb_Port->port] != WmDataSharingReceiveCallback_Parent
447 && p->portCallbackTable[cb_Port->port] != WmDataSharingReceiveCallback_Child)
448 || dsInfo == NULL || dsInfo != (WMDataSharingInfo *)(cb_Port->arg))
449 {
450 WM_WARNING("data-sharing has already terminated.");
451 return;
452 }
453
454 aid = WM_GetAID();
455
456 if (cb_Port->errcode == WM_ERRCODE_SUCCESS)
457 {
458 // Send completed
459 if (aid == 0)
460 {
461 // Parent-side processing
462 WM_DLOGF_DATASHARING("sent ds : write: %d, read: %d, send: %d", dsInfo->writeIndex,
463 dsInfo->readIndex, dsInfo->sendIndex);
464
465 dsInfo->seqNum[dsInfo->sendIndex] = (u16)(cb_Port->seqNo >> 1);
466 dsInfo->sendIndex = WmDataSharingGetNextIndex(dsInfo->sendIndex);
467 }
468 else
469 {
470 // Child-side processing
471 WM_DLOGF_DATASHARING("sent data : write: %d, read: %d, send: %d", dsInfo->writeIndex,
472 dsInfo->readIndex, dsInfo->sendIndex);
473 }
474 }
475 else
476 {
477 if (cb_Port->errcode == WM_ERRCODE_SEND_QUEUE_FULL)
478 {
479 // Resend because the transmission queue was full
480 if (aid != 0)
481 {
482 // For the child, put the sendIndex back one
483 dsInfo->sendIndex = WmDataSharingGetPrevIndex(dsInfo->sendIndex);
484 }
485 dsInfo->state = WM_DS_STATE_RETRY_SEND;
486 WM_DLOG_DATASHARING("send queue is full. will retry.");
487 }
488 else
489 {
490 WM_WARNING("WM_SetMPDataToPort failed during data-sharing. errcode=%x\n",
491 cb_Port->errcode);
492 dsInfo->state = WM_DS_STATE_ERROR;
493 }
494 }
495 }
496
497 /*---------------------------------------------------------------------------*
498 Name: WmDataSharingReceiveCallback_Parent
499
500 Description: A parent port receive callback
501
502 Arguments: callback: A pointer to the callback structure.
503
504 Returns: None.
505 *---------------------------------------------------------------------------*/
WmDataSharingReceiveCallback_Parent(void * callback)506 static void WmDataSharingReceiveCallback_Parent(void *callback)
507 {
508 WMPortRecvCallback *cb_Port = (WMPortRecvCallback *)callback;
509 WMDataSharingInfo *dsInfo = (WMDataSharingInfo *)cb_Port->arg;
510
511 if (dsInfo == NULL)
512 {
513 WM_WARNING("data-sharing has already terminated.");
514 return;
515 }
516
517 if (cb_Port->errcode == WM_ERRCODE_SUCCESS)
518 {
519 switch (cb_Port->state)
520 {
521 case WM_STATECODE_PORT_RECV:
522 // Store the received child data in a buffer
523 WmDataSharingReceiveData(dsInfo, cb_Port->aid, cb_Port->data);
524 WmDataSharingSendDataSet(dsInfo, FALSE);
525 break;
526
527 case WM_STATECODE_CONNECTED:
528 WmDataSharingSendDataSet(dsInfo, FALSE); // Should not be required
529 break;
530
531 case WM_STATECODE_DISCONNECTED:
532 case WM_STATECODE_DISCONNECTED_FROM_MYSELF:
533 {
534 u32 aidBit;
535 u32 writeIndex;
536 OSIntrMode enabled;
537 aidBit = 1U << cb_Port->aid;
538 enabled = OS_DisableInterrupts();
539 writeIndex = dsInfo->writeIndex;
540 dsInfo->ds[writeIndex].aidBitmap &= ~aidBit;
541 if (dsInfo->doubleMode == TRUE)
542 {
543 dsInfo->ds[WmDataSharingGetNextIndex(writeIndex)].aidBitmap &= ~aidBit;
544 }
545 (void)OS_RestoreInterrupts(enabled);
546 WmDataSharingSendDataSet(dsInfo, FALSE);
547 if (dsInfo->doubleMode == TRUE)
548 {
549 WmDataSharingSendDataSet(dsInfo, FALSE);
550 }
551 }
552 break;
553
554 case WM_STATECODE_PORT_INIT:
555 break;
556 }
557 }
558 else
559 {
560 WM_WARNING("An unknown receiving error occured during data-sharing. errcode=%x\n",
561 cb_Port->errcode);
562 dsInfo->state = WM_DS_STATE_ERROR;
563 }
564 }
565
566 /*---------------------------------------------------------------------------*
567 Name: WmDataSharingReceiveCallback_Child
568
569 Description: A child port receive callback.
570
571 Arguments: callback: A pointer to the callback structure.
572
573 Returns: None.
574 *---------------------------------------------------------------------------*/
WmDataSharingReceiveCallback_Child(void * callback)575 static void WmDataSharingReceiveCallback_Child(void *callback)
576 {
577 WMPortRecvCallback *cb_Port = (WMPortRecvCallback *)callback;
578 WMDataSharingInfo *dsInfo = (WMDataSharingInfo *)cb_Port->arg;
579
580 if (dsInfo == NULL)
581 {
582 WM_WARNING("data-sharing has already terminated.");
583 return;
584 }
585
586 if (cb_Port->errcode == WM_ERRCODE_SUCCESS)
587 {
588 switch (cb_Port->state)
589 {
590 case WM_STATECODE_PORT_RECV:
591 {
592 u32 length;
593 u32 aid;
594 u32 aidBitmap;
595 WMDataSet *dataSet;
596
597 WM_DLOGF_DATASHARING("recv ds : write: %d, read: %d, send: %d",
598 dsInfo->writeIndex, dsInfo->readIndex, dsInfo->sendIndex);
599
600 // Saves the DataSet
601 dataSet = (WMDataSet *)(cb_Port->data);
602 aidBitmap = dataSet->aidBitmap;
603 length = cb_Port->length;
604 aid = WM_GetAID();
605
606 if (length != dsInfo->dataSetLength)
607 {
608 WM_WARNING("received DataSharing data size(%d) != dsInfo->dataSetLength(%d)\n",
609 length, dsInfo->dataSetLength);
610 if (length > sizeof(WMDataSet))
611 {
612 // If incoming data is longer than the buffer, adjust it.
613 WM_WARNING("received DataSharing data exceeds sizeof(WMDataSet)\n");
614 length = sizeof(WMDataSet);
615 }
616 }
617 #ifdef SDK_DEBUG
618 if (aidBitmap & ~(dsInfo->aidBitmap))
619 {
620 // Larger than the aidBitmap expected by the child
621 WM_WARNING("received aidBitmap(%x) has too many members.\n", aidBitmap);
622 }
623 #endif
624 if (length >= 4 && (aidBitmap & (1 << aid)))
625 {
626 MI_CpuCopy16(dataSet, &dsInfo->ds[dsInfo->writeIndex], length);
627 dsInfo->seqNum[dsInfo->writeIndex] = (u16)(cb_Port->seqNo >> 1);
628 dsInfo->writeIndex = WmDataSharingGetNextIndex(dsInfo->writeIndex);
629 }
630 }
631 break;
632 case WM_STATECODE_PORT_INIT:
633 case WM_STATECODE_CONNECTED:
634 case WM_STATECODE_DISCONNECTED:
635 case WM_STATECODE_DISCONNECTED_FROM_MYSELF:
636 break;
637 }
638 }
639 else
640 {
641 WM_WARNING("An unknown receiving error occured during data-sharing. errcode=%x\n",
642 cb_Port->errcode);
643 dsInfo->state = WM_DS_STATE_ERROR;
644 }
645 }
646
647 /*---------------------------------------------------------------------------*
648 Name: WmDataSharingReceiveData
649
650 Description: Stores the data, because the parent received data from several devices.
651
652 Arguments: dsInfo - WMDataSharingInfo structure.
653 aid: AID of the terminal that received data.
654 data: A pointer to the received data.
655
656 Returns: None.
657 *---------------------------------------------------------------------------*/
WmDataSharingReceiveData(WMDataSharingInfo * dsInfo,u16 aid,u16 * data)658 static void WmDataSharingReceiveData(WMDataSharingInfo *dsInfo, u16 aid, u16 *data)
659 {
660 u16 aidBit = (u16)(1 << aid);
661
662 WM_DLOGF_DATASHARING("recv data%d: write: %d, read: %d, send: %d", aid, dsInfo->writeIndex,
663 dsInfo->readIndex, dsInfo->sendIndex);
664
665 // Confirms whether it is a processing target
666 if (dsInfo->aidBitmap & aidBit)
667 {
668 u16 *buf;
669 u16 writeIndex;
670 OSIntrMode enabled;
671
672 if (!(dsInfo->ds[dsInfo->writeIndex].aidBitmap & aidBit))
673 {
674 if (dsInfo->doubleMode == TRUE)
675 {
676 WM_DLOGF_DATASHARING("[DS] received two DS packets from aid %d", aid);
677
678 writeIndex = WmDataSharingGetNextIndex(dsInfo->writeIndex);
679 if (!(dsInfo->ds[writeIndex].aidBitmap & aidBit))
680 {
681 // Up to two are stored in the buffer. Anything beyond that is discarded.
682 OS_Warning("received too many DataSharing packets from aid %d. discarded.\n",
683 aid);
684 return;
685 }
686 }
687 else
688 {
689 // If not in doubleMode, the buffer can hold only up to one
690 OS_Warning("received too many DataSharing packets from aid %d. discarded.\n", aid);
691 return;
692 }
693 }
694 else
695 {
696 writeIndex = dsInfo->writeIndex;
697 }
698
699 buf = WmGetSharedDataAddress(dsInfo, dsInfo->aidBitmap, dsInfo->ds[writeIndex].data, aid);
700 if (data != NULL)
701 {
702 MI_CpuCopy16(data, buf, dsInfo->dataLength);
703 }
704 else
705 {
706 MI_CpuClear16(buf, dsInfo->dataLength);
707 }
708
709 enabled = OS_DisableInterrupts();
710 // Disables the not-yet-received flag
711 dsInfo->ds[writeIndex].aidBitmap &= ~aidBit;
712 // Enables the received flag
713 dsInfo->ds[writeIndex].receivedBitmap |= aidBit;
714 (void)OS_RestoreInterrupts(enabled);
715 }
716 }
717
718 /*---------------------------------------------------------------------------*
719 Name: WmDataSharingSendDataSet
720
721 Description: After the parent confirms reception of each device's data, the data set is sent.
722
723 Arguments: dsInfo - WMDataSharingInfo structure.
724 delayed: TRUE if in frame delay state
725
726 Returns: None.
727 *---------------------------------------------------------------------------*/
WmDataSharingSendDataSet(WMDataSharingInfo * dsInfo,BOOL delayed)728 void WmDataSharingSendDataSet(WMDataSharingInfo *dsInfo, BOOL delayed)
729 {
730 OSIntrMode enabled;
731
732 enabled = OS_DisableInterrupts();
733 // If receiving is finished for all the devices (The ds[].aidBitmap, from the receive buffer, carries out the role of a not-yet-received flag)
734 //
735 if (dsInfo->ds[dsInfo->writeIndex].aidBitmap == 0)
736 {
737 u16 newWI, oldWI, resetWI;
738 WMErrCode res;
739 u16 connectedAIDs;
740
741 WM_DLOGF_DATASHARING("send ds : write: %d, read: %d, send: %d", dsInfo->writeIndex,
742 dsInfo->readIndex, dsInfo->sendIndex);
743
744 connectedAIDs = WM_GetConnectedAIDs();
745 oldWI = dsInfo->writeIndex;
746 newWI = WmDataSharingGetNextIndex(oldWI);
747 if (dsInfo->doubleMode == TRUE)
748 {
749 resetWI = WmDataSharingGetNextIndex(newWI);
750 }
751 else
752 {
753 resetWI = newWI;
754 }
755 SDK_ASSERT(newWI != dsInfo->readIndex && resetWI != dsInfo->readIndex);
756 // SDK_ASSERT( dsInfo->sendIndex == dsInfo->writeIndex);
757 MI_CpuClear16(&dsInfo->ds[resetWI], sizeof(WMDataSet));
758 dsInfo->ds[resetWI].aidBitmap = (u16)(dsInfo->aidBitmap & (connectedAIDs | 0x0001));
759 dsInfo->writeIndex = newWI;
760 dsInfo->ds[oldWI].aidBitmap = dsInfo->aidBitmap; // Enter the original value in aidBitmap before sending
761 if (delayed == TRUE)
762 {
763 // The lowest bit in the aidBitmap is a delay flag
764 dsInfo->ds[oldWI].aidBitmap &= ~0x0001;
765 }
766 (void)OS_RestoreInterrupts(enabled);
767 res =
768 WM_SetMPDataToPortEx(WmDataSharingSetDataCallback, dsInfo, (u16 *)&dsInfo->ds[oldWI],
769 dsInfo->dataSetLength, (u16)(dsInfo->aidBitmap & connectedAIDs),
770 dsInfo->port, WM_PRIORITY_HIGH);
771 if (res == WM_ERRCODE_NO_CHILD)
772 {
773 WM_DLOGF_DATASHARING("sent ds : write: %d, read: %d, send: %d", dsInfo->writeIndex,
774 dsInfo->readIndex, dsInfo->sendIndex);
775
776 dsInfo->seqNum[oldWI] = 0xffff;
777 dsInfo->sendIndex = WmDataSharingGetNextIndex(dsInfo->sendIndex);
778 }
779 else
780 {
781 if (res != WM_ERRCODE_SUCCESS && res != WM_ERRCODE_OPERATING)
782 {
783 WM_WARNING("WM_SetMPDataToPort failed during data-sharing. errcode=%x\n", res);
784 dsInfo->state = WM_DS_STATE_ERROR;
785 }
786 }
787 }
788 else
789 {
790 (void)OS_RestoreInterrupts(enabled);
791 }
792 }
793
794 /*---------------------------------------------------------------------------*
795 Name: WM_GetSharedDataAddress
796
797 Description: Gets a specific AID address during a session of receiving data in data sharing.
798
799 Arguments: dsInfo: WMDataSharingInfo structure.
800 receiveData: Received shared data.
801 aid: AID.
802
803 Returns: u16* : The address of the received data. If it does not exist, returns NULL.
804 *---------------------------------------------------------------------------*/
WM_GetSharedDataAddress(WMDataSharingInfo * dsInfo,WMDataSet * receiveData,u16 aid)805 u16 *WM_GetSharedDataAddress(WMDataSharingInfo *dsInfo, WMDataSet *receiveData, u16 aid)
806 {
807 u32 aidBitmap = receiveData->aidBitmap;
808 u32 receivedBitmap = receiveData->receivedBitmap;
809 u32 aidBit = (1U << aid);
810
811 // Check parameters
812 if (dsInfo == NULL)
813 {
814 WM_WARNING("Parameter \"dsInfo\" must not be NULL.\n");
815 return NULL;
816 }
817
818 if (receiveData == NULL)
819 {
820 WM_WARNING("Parameter \"receiveData\" must not be NULL.\n");
821 return NULL;
822 }
823
824 if (!(aidBitmap & aidBit))
825 {
826 // WM_WARNING("Parameter \"aid\" must be a member of \"receiveData->aidBitmap\".\n");
827 return NULL;
828 }
829
830 if (!(receivedBitmap & aidBit))
831 {
832 // Has not received data
833 return NULL;
834 }
835
836 return WmGetSharedDataAddress(dsInfo, aidBitmap, receiveData->data, aid);
837 }
838
839 /*---------------------------------------------------------------------------*
840 Name: WmGetSharedDataAddress
841
842 Description: Gets a specific AID address within the receive buffer.
843
844 Arguments: dsInfo: WMDataSharingInfo structure.
845 aidBitmap: Other communication peer(s) included in the data.
846 receiveBuf: Receive buffer
847 aid: AID.
848 Confirm aidBitmap & (1<<aid) before calling this.
849
850 Returns: u16* : The address of the received data.
851 *---------------------------------------------------------------------------*/
WmGetSharedDataAddress(WMDataSharingInfo * dsInfo,u32 aidBitmap,u16 * receiveBuf,u32 aid)852 u16 *WmGetSharedDataAddress(WMDataSharingInfo *dsInfo, u32 aidBitmap, u16 *receiveBuf, u32 aid)
853 {
854 u32 mask;
855 u32 count;
856 u32 offset;
857
858 // Count the '1's among the aid bits in the aidBitmap, from the bottom
859 mask = (0x0001U << aid) - 1U;
860 aidBitmap &= mask;
861 count = MATH_CountPopulation(aidBitmap);
862 offset = dsInfo->dataLength * count;
863
864 return (u16 *)(((u8 *)receiveBuf) + offset);
865 }
866
867 /*---------------------------------------------------------------------------*
868 End of file
869 *---------------------------------------------------------------------------*/
870