initial commit with v2.6.32.60
[linux-2.6.32.60-moxart.git] / drivers / staging / rtl8192su / r819xU_cmdpkt.c
blob071b5c60ac282a6c57838bbf15b0393f063a1e9e
1 /******************************************************************************
3 (c) Copyright 2008, RealTEK Technologies Inc. All Rights Reserved.
5 Module: r819xusb_cmdpkt.c (RTL8190 TX/RX command packet handler Source C File)
7 Note: The module is responsible for handling TX and RX command packet.
8 1. TX : Send set and query configuration command packet.
9 2. RX : Receive tx feedback, beacon state, query configuration
10 command packet.
12 Function:
14 Export:
16 Abbrev:
18 History:
19 Data Who Remark
21 05/06/2008 amy Create initial version porting from windows driver.
23 ******************************************************************************/
24 #include "r8192U.h"
25 #include "r819xU_cmdpkt.h"
26 /*---------------------------Define Local Constant---------------------------*/
27 /* Debug constant*/
28 #define CMPK_DEBOUNCE_CNT 1
29 /* 2007/10/24 MH Add for printing a range of data. */
30 #define CMPK_PRINT(Address)\
32 unsigned char i;\
33 u32 temp[10];\
35 memcpy(temp, Address, 40);\
36 for (i = 0; i <40; i+=4)\
37 printk("\r\n %08x", temp[i]);\
39 /*---------------------------Define functions---------------------------------*/
41 bool
42 SendTxCommandPacket(
43 struct net_device *dev,
44 void* pData,
45 u32 DataLen
48 bool rtStatus = true;
49 struct r8192_priv *priv = ieee80211_priv(dev);
50 struct sk_buff *skb;
51 cb_desc *tcb_desc;
52 unsigned char *ptr_buf;
53 //bool bLastInitPacket = false;
55 //PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
57 //Get TCB and local buffer from common pool. (It is shared by CmdQ, MgntQ, and USB coalesce DataQ)
58 skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + DataLen + 4);
59 if (skb == NULL) {
60 RT_TRACE(COMP_ERR, "(%s): unable to alloc skb buffer\n",
61 __func__);
62 rtStatus = false;
63 return rtStatus;
65 memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
66 tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
67 tcb_desc->queue_index = TXCMD_QUEUE;
68 tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_NORMAL;
69 tcb_desc->bLastIniPkt = 0;
70 skb_reserve(skb, USB_HWDESC_HEADER_LEN);
71 ptr_buf = skb_put(skb, DataLen);
72 memset(ptr_buf,0,DataLen);
73 memcpy(ptr_buf,pData,DataLen);
74 tcb_desc->txbuf_size= (u16)DataLen;
76 if(!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)||
77 (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\
78 (priv->ieee80211->queue_stop) ) {
79 RT_TRACE(COMP_FIRMWARE,"===================NULL packet==================================> tx full!\n");
80 skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
81 } else {
82 priv->ieee80211->softmac_hard_start_xmit(skb,dev);
85 //PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
86 return rtStatus;
89 /*-----------------------------------------------------------------------------
90 * Function: cmpk_message_handle_tx()
92 * Overview: Driver internal module can call the API to send message to
93 * firmware side. For example, you can send a debug command packet.
94 * Or you can send a request for FW to modify RLX4181 LBUS HW bank.
95 * Otherwise, you can change MAC/PHT/RF register by firmware at
96 * run time. We do not support message more than one segment now.
98 * Input: NONE
100 * Output: NONE
102 * Return: NONE
104 * Revised History:
105 * When Who Remark
106 * 05/06/2008 amy porting from windows code.
108 *---------------------------------------------------------------------------*/
109 extern bool cmpk_message_handle_tx(
110 struct net_device *dev,
111 u8* codevirtualaddress,
112 u32 packettype,
113 u32 buffer_len)
116 bool rt_status = true;
117 return rt_status;
118 } /* CMPK_Message_Handle_Tx */
120 /*-----------------------------------------------------------------------------
121 * Function: cmpk_counttxstatistic()
123 * Overview:
125 * Input: PADAPTER pAdapter - .
126 * CMPK_TXFB_T *psTx_FB - .
128 * Output: NONE
130 * Return: NONE
132 * Revised History:
133 * When Who Remark
134 * 05/12/2008 amy Create Version 0 porting from windows code.
136 *---------------------------------------------------------------------------*/
137 static void
138 cmpk_count_txstatistic(
139 struct net_device *dev,
140 cmpk_txfb_t *pstx_fb)
142 struct r8192_priv *priv = ieee80211_priv(dev);
143 #ifdef ENABLE_PS
144 RT_RF_POWER_STATE rtState;
146 pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
148 // When RF is off, we should not count the packet for hw/sw synchronize
149 // reason, ie. there may be a duration while sw switch is changed and hw
150 // switch is being changed. 2006.12.04, by shien chang.
151 if (rtState == eRfOff)
153 return;
155 #endif
157 #ifdef TODO
158 if(pAdapter->bInHctTest)
159 return;
160 #endif
161 /* We can not know the packet length and transmit type: broadcast or uni
162 or multicast. So the relative statistics must be collected in tx
163 feedback info. */
164 if (pstx_fb->tok)
166 priv->stats.txfeedbackok++;
167 priv->stats.txoktotal++;
168 priv->stats.txokbytestotal += pstx_fb->pkt_length;
169 priv->stats.txokinperiod++;
171 /* We can not make sure broadcast/multicast or unicast mode. */
172 if (pstx_fb->pkt_type == PACKET_MULTICAST)
174 priv->stats.txmulticast++;
175 priv->stats.txbytesmulticast += pstx_fb->pkt_length;
177 else if (pstx_fb->pkt_type == PACKET_BROADCAST)
179 priv->stats.txbroadcast++;
180 priv->stats.txbytesbroadcast += pstx_fb->pkt_length;
182 else
184 priv->stats.txunicast++;
185 priv->stats.txbytesunicast += pstx_fb->pkt_length;
188 else
190 priv->stats.txfeedbackfail++;
191 priv->stats.txerrtotal++;
192 priv->stats.txerrbytestotal += pstx_fb->pkt_length;
194 /* We can not make sure broadcast/multicast or unicast mode. */
195 if (pstx_fb->pkt_type == PACKET_MULTICAST)
197 priv->stats.txerrmulticast++;
199 else if (pstx_fb->pkt_type == PACKET_BROADCAST)
201 priv->stats.txerrbroadcast++;
203 else
205 priv->stats.txerrunicast++;
209 priv->stats.txretrycount += pstx_fb->retry_cnt;
210 priv->stats.txfeedbackretry += pstx_fb->retry_cnt;
212 } /* cmpk_CountTxStatistic */
216 /*-----------------------------------------------------------------------------
217 * Function: cmpk_handle_tx_feedback()
219 * Overview: The function is responsible for extract the message inside TX
220 * feedbck message from firmware. It will contain dedicated info in
221 * ws-06-0063-rtl8190-command-packet-specification. Please
222 * refer to chapter "TX Feedback Element". We have to read 20 bytes
223 * in the command packet.
225 * Input: struct net_device * dev
226 * u8 * pmsg - Msg Ptr of the command packet.
228 * Output: NONE
230 * Return: NONE
232 * Revised History:
233 * When Who Remark
234 * 05/08/2008 amy Create Version 0 porting from windows code.
236 *---------------------------------------------------------------------------*/
237 static void
238 cmpk_handle_tx_feedback(
239 struct net_device *dev,
240 u8 * pmsg)
242 struct r8192_priv *priv = ieee80211_priv(dev);
243 cmpk_txfb_t rx_tx_fb; /* */
245 priv->stats.txfeedback++;
247 /* 0. Display received message. */
248 //cmpk_Display_Message(CMPK_RX_TX_FB_SIZE, pMsg);
250 /* 1. Extract TX feedback info from RFD to temp structure buffer. */
252 /* 2007/07/05 MH Use pointer to transfer structure memory. */
253 //memcpy((UINT8 *)&rx_tx_fb, pMsg, sizeof(CMPK_TXFB_T));
254 memcpy((u8*)&rx_tx_fb, pmsg, sizeof(cmpk_txfb_t));
255 /* 2. Use tx feedback info to count TX statistics. */
256 cmpk_count_txstatistic(dev, &rx_tx_fb);
258 /* 2007/01/17 MH Comment previous method for TX statistic function. */
259 /* Collect info TX feedback packet to fill TCB. */
260 /* We can not know the packet length and transmit type: broadcast or uni
261 or multicast. */
262 //CountTxStatistics( pAdapter, &tcb );
264 } /* cmpk_Handle_Tx_Feedback */
266 void
267 cmdpkt_beacontimerinterrupt_819xusb(
268 struct net_device *dev
271 struct r8192_priv *priv = ieee80211_priv(dev);
272 u16 tx_rate;
275 // 070117, rcnjko: 87B have to S/W beacon for DTM encryption_cmn.
277 if(priv->ieee80211->current_network.mode == IEEE_A ||
278 priv->ieee80211->current_network.mode == IEEE_N_5G ||
279 (priv->ieee80211->current_network.mode == IEEE_N_24G && (!priv->ieee80211->pHTInfo->bCurSuppCCK)))
281 tx_rate = 60;
282 DMESG("send beacon frame tx rate is 6Mbpm\n");
284 else
286 tx_rate =10;
287 DMESG("send beacon frame tx rate is 1Mbpm\n");
290 rtl819xusb_beacon_tx(dev,tx_rate); // HW Beacon
299 /*-----------------------------------------------------------------------------
300 * Function: cmpk_handle_interrupt_status()
302 * Overview: The function is responsible for extract the message from
303 * firmware. It will contain dedicated info in
304 * ws-07-0063-v06-rtl819x-command-packet-specification-070315.doc.
305 * Please refer to chapter "Interrupt Status Element".
307 * Input: struct net_device *dev,
308 * u8* pmsg - Message Pointer of the command packet.
310 * Output: NONE
312 * Return: NONE
314 * Revised History:
315 * When Who Remark
316 * 05/12/2008 amy Add this for rtl8192 porting from windows code.
318 *---------------------------------------------------------------------------*/
319 static void
320 cmpk_handle_interrupt_status(
321 struct net_device *dev,
322 u8* pmsg)
324 cmpk_intr_sta_t rx_intr_status; /* */
325 struct r8192_priv *priv = ieee80211_priv(dev);
327 DMESG("---> cmpk_Handle_Interrupt_Status()\n");
329 /* 0. Display received message. */
330 //cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg);
332 /* 1. Extract TX feedback info from RFD to temp structure buffer. */
333 /* It seems that FW use big endian(MIPS) and DRV use little endian in
334 windows OS. So we have to read the content byte by byte or transfer
335 endian type before copy the message copy. */
336 //rx_bcn_state.Element_ID = pMsg[0];
337 //rx_bcn_state.Length = pMsg[1];
338 rx_intr_status.length = pmsg[1];
339 if (rx_intr_status.length != (sizeof(cmpk_intr_sta_t) - 2))
341 DMESG("cmpk_Handle_Interrupt_Status: wrong length!\n");
342 return;
346 // Statistics of beacon for ad-hoc mode.
347 if( priv->ieee80211->iw_mode == IW_MODE_ADHOC)
349 //2 maybe need endian transform?
350 rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4));
351 //rx_intr_status.InterruptStatus = N2H4BYTE(*((UINT32 *)(pMsg + 4)));
353 DMESG("interrupt status = 0x%x\n", rx_intr_status.interrupt_status);
355 if (rx_intr_status.interrupt_status & ISR_TxBcnOk)
357 priv->ieee80211->bibsscoordinator = true;
358 priv->stats.txbeaconokint++;
360 else if (rx_intr_status.interrupt_status & ISR_TxBcnErr)
362 priv->ieee80211->bibsscoordinator = false;
363 priv->stats.txbeaconerr++;
366 if (rx_intr_status.interrupt_status & ISR_BcnTimerIntr)
368 cmdpkt_beacontimerinterrupt_819xusb(dev);
373 // Other informations in interrupt status we need?
376 DMESG("<---- cmpk_handle_interrupt_status()\n");
378 } /* cmpk_handle_interrupt_status */
381 /*-----------------------------------------------------------------------------
382 * Function: cmpk_handle_query_config_rx()
384 * Overview: The function is responsible for extract the message from
385 * firmware. It will contain dedicated info in
386 * ws-06-0063-rtl8190-command-packet-specification. Please
387 * refer to chapter "Beacon State Element".
389 * Input: u8 * pmsg - Message Pointer of the command packet.
391 * Output: NONE
393 * Return: NONE
395 * Revised History:
396 * When Who Remark
397 * 05/12/2008 amy Create Version 0 porting from windows code.
399 *---------------------------------------------------------------------------*/
400 static void
401 cmpk_handle_query_config_rx(
402 struct net_device *dev,
403 u8* pmsg)
405 cmpk_query_cfg_t rx_query_cfg; /* */
407 /* 0. Display received message. */
408 //cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg);
410 /* 1. Extract TX feedback info from RFD to temp structure buffer. */
411 /* It seems that FW use big endian(MIPS) and DRV use little endian in
412 windows OS. So we have to read the content byte by byte or transfer
413 endian type before copy the message copy. */
414 //rx_query_cfg.Element_ID = pMsg[0];
415 //rx_query_cfg.Length = pMsg[1];
416 rx_query_cfg.cfg_action = (pmsg[4] & 0x80000000)>>31;
417 rx_query_cfg.cfg_type = (pmsg[4] & 0x60) >> 5;
418 rx_query_cfg.cfg_size = (pmsg[4] & 0x18) >> 3;
419 rx_query_cfg.cfg_page = (pmsg[6] & 0x0F) >> 0;
420 rx_query_cfg.cfg_offset = pmsg[7];
421 rx_query_cfg.value = (pmsg[8] << 24) | (pmsg[9] << 16) |
422 (pmsg[10] << 8) | (pmsg[11] << 0);
423 rx_query_cfg.mask = (pmsg[12] << 24) | (pmsg[13] << 16) |
424 (pmsg[14] << 8) | (pmsg[15] << 0);
426 } /* cmpk_Handle_Query_Config_Rx */
429 /*-----------------------------------------------------------------------------
430 * Function: cmpk_count_tx_status()
432 * Overview: Count aggregated tx status from firmwar of one type rx command
433 * packet element id = RX_TX_STATUS.
435 * Input: NONE
437 * Output: NONE
439 * Return: NONE
441 * Revised History:
442 * When Who Remark
443 * 05/12/2008 amy Create Version 0 porting from windows code.
445 *---------------------------------------------------------------------------*/
446 static void cmpk_count_tx_status( struct net_device *dev,
447 cmpk_tx_status_t *pstx_status)
449 struct r8192_priv *priv = ieee80211_priv(dev);
451 #ifdef ENABLE_PS
453 RT_RF_POWER_STATE rtstate;
455 pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
457 // When RF is off, we should not count the packet for hw/sw synchronize
458 // reason, ie. there may be a duration while sw switch is changed and hw
459 // switch is being changed. 2006.12.04, by shien chang.
460 if (rtState == eRfOff)
462 return;
464 #endif
466 priv->stats.txfeedbackok += pstx_status->txok;
467 priv->stats.txoktotal += pstx_status->txok;
469 priv->stats.txfeedbackfail += pstx_status->txfail;
470 priv->stats.txerrtotal += pstx_status->txfail;
472 priv->stats.txretrycount += pstx_status->txretry;
473 priv->stats.txfeedbackretry += pstx_status->txretry;
475 //pAdapter->TxStats.NumTxOkBytesTotal += psTx_FB->pkt_length;
476 //pAdapter->TxStats.NumTxErrBytesTotal += psTx_FB->pkt_length;
477 //pAdapter->MgntInfo.LinkDetectInfo.NumTxOkInPeriod++;
479 priv->stats.txmulticast += pstx_status->txmcok;
480 priv->stats.txbroadcast += pstx_status->txbcok;
481 priv->stats.txunicast += pstx_status->txucok;
483 priv->stats.txerrmulticast += pstx_status->txmcfail;
484 priv->stats.txerrbroadcast += pstx_status->txbcfail;
485 priv->stats.txerrunicast += pstx_status->txucfail;
487 priv->stats.txbytesmulticast += pstx_status->txmclength;
488 priv->stats.txbytesbroadcast += pstx_status->txbclength;
489 priv->stats.txbytesunicast += pstx_status->txuclength;
491 priv->stats.last_packet_rate = pstx_status->rate;
492 } /* cmpk_CountTxStatus */
496 /*-----------------------------------------------------------------------------
497 * Function: cmpk_handle_tx_status()
499 * Overview: Firmware add a new tx feedback status to reduce rx command
500 * packet buffer operation load.
502 * Input: NONE
504 * Output: NONE
506 * Return: NONE
508 * Revised History:
509 * When Who Remark
510 * 05/12/2008 amy Create Version 0 porting from windows code.
512 *---------------------------------------------------------------------------*/
513 static void
514 cmpk_handle_tx_status(
515 struct net_device *dev,
516 u8* pmsg)
518 cmpk_tx_status_t rx_tx_sts; /* */
520 memcpy((void*)&rx_tx_sts, (void*)pmsg, sizeof(cmpk_tx_status_t));
521 /* 2. Use tx feedback info to count TX statistics. */
522 cmpk_count_tx_status(dev, &rx_tx_sts);
524 } /* cmpk_Handle_Tx_Status */
527 /*-----------------------------------------------------------------------------
528 * Function: cmpk_handle_tx_rate_history()
530 * Overview: Firmware add a new tx rate history
532 * Input: NONE
534 * Output: NONE
536 * Return: NONE
538 * Revised History:
539 * When Who Remark
540 * 05/12/2008 amy Create Version 0 porting from windows code.
542 *---------------------------------------------------------------------------*/
543 static void
544 cmpk_handle_tx_rate_history(
545 struct net_device *dev,
546 u8* pmsg)
548 cmpk_tx_rahis_t *ptxrate;
549 // RT_RF_POWER_STATE rtState;
550 u8 i, j;
551 u16 length = sizeof(cmpk_tx_rahis_t);
552 u32 *ptemp;
553 struct r8192_priv *priv = ieee80211_priv(dev);
556 #ifdef ENABLE_PS
557 pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
559 // When RF is off, we should not count the packet for hw/sw synchronize
560 // reason, ie. there may be a duration while sw switch is changed and hw
561 // switch is being changed. 2006.12.04, by shien chang.
562 if (rtState == eRfOff)
564 return;
566 #endif
568 ptemp = (u32 *)pmsg;
571 // Do endian transfer to word alignment(16 bits) for windows system.
572 // You must do different endian transfer for linux and MAC OS
574 for (i = 0; i < (length/4); i++)
576 u16 temp1, temp2;
578 temp1 = ptemp[i]&0x0000FFFF;
579 temp2 = ptemp[i]>>16;
580 ptemp[i] = (temp1<<16)|temp2;
583 ptxrate = (cmpk_tx_rahis_t *)pmsg;
585 if (ptxrate == NULL )
587 return;
590 for (i = 0; i < 16; i++)
592 // Collect CCK rate packet num
593 if (i < 4)
594 priv->stats.txrate.cck[i] += ptxrate->cck[i];
596 // Collect OFDM rate packet num
597 if (i< 8)
598 priv->stats.txrate.ofdm[i] += ptxrate->ofdm[i];
600 for (j = 0; j < 4; j++)
601 priv->stats.txrate.ht_mcs[j][i] += ptxrate->ht_mcs[j][i];
604 } /* cmpk_Handle_Tx_Rate_History */
607 /*-----------------------------------------------------------------------------
608 * Function: cmpk_message_handle_rx()
610 * Overview: In the function, we will capture different RX command packet
611 * info. Every RX command packet element has different message
612 * length and meaning in content. We only support three type of RX
613 * command packet now. Please refer to document
614 * ws-06-0063-rtl8190-command-packet-specification.
616 * Input: NONE
618 * Output: NONE
620 * Return: NONE
622 * Revised History:
623 * When Who Remark
624 * 05/06/2008 amy Create Version 0 porting from windows code.
626 *---------------------------------------------------------------------------*/
627 extern u32
628 cmpk_message_handle_rx(
629 struct net_device *dev,
630 struct ieee80211_rx_stats *pstats)
632 // u32 debug_level = DBG_LOUD;
633 struct r8192_priv *priv = ieee80211_priv(dev);
634 int total_length;
635 u8 cmd_length, exe_cnt = 0;
636 u8 element_id;
637 u8 *pcmd_buff;
639 /* 0. Check inpt arguments. If is is a command queue message or pointer is
640 null. */
641 if (/*(prfd->queue_id != CMPK_RX_QUEUE_ID) || */(pstats== NULL))
643 /* Print error message. */
644 /*RT_TRACE(COMP_SEND, DebugLevel,
645 ("\n\r[CMPK]-->Err queue id or pointer"));*/
646 return 0; /* This is not a command packet. */
649 /* 1. Read received command packet message length from RFD. */
650 total_length = pstats->Length;
652 /* 2. Read virtual address from RFD. */
653 pcmd_buff = pstats->virtual_address;
655 /* 3. Read command pakcet element id and length. */
656 element_id = pcmd_buff[0];
657 /*RT_TRACE(COMP_SEND, DebugLevel,
658 ("\n\r[CMPK]-->element ID=%d Len=%d", element_id, total_length));*/
660 /* 4. Check every received command packet conent according to different
661 element type. Because FW may aggregate RX command packet to minimize
662 transmit time between DRV and FW.*/
663 // Add a counter to prevent to locked in the loop too long
664 while (total_length > 0 || exe_cnt++ >100)
666 /* 2007/01/17 MH We support aggregation of different cmd in the same packet. */
667 element_id = pcmd_buff[0];
669 switch(element_id)
671 case RX_TX_FEEDBACK:
672 cmpk_handle_tx_feedback (dev, pcmd_buff);
673 cmd_length = CMPK_RX_TX_FB_SIZE;
674 break;
676 case RX_INTERRUPT_STATUS:
677 cmpk_handle_interrupt_status(dev, pcmd_buff);
678 cmd_length = sizeof(cmpk_intr_sta_t);
679 break;
681 case BOTH_QUERY_CONFIG:
682 cmpk_handle_query_config_rx(dev, pcmd_buff);
683 cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE;
684 break;
686 case RX_TX_STATUS:
687 cmpk_handle_tx_status(dev, pcmd_buff);
688 cmd_length = CMPK_RX_TX_STS_SIZE;
689 break;
691 case RX_TX_PER_PKT_FEEDBACK:
692 // You must at lease add a switch case element here,
693 // Otherwise, we will jump to default case.
694 //DbgPrint("CCX Test\r\n");
695 cmd_length = CMPK_RX_TX_FB_SIZE;
696 break;
698 case RX_TX_RATE_HISTORY:
699 //DbgPrint(" rx tx rate history\r\n");
700 cmpk_handle_tx_rate_history(dev, pcmd_buff);
701 cmd_length = CMPK_TX_RAHIS_SIZE;
702 break;
704 default:
706 RT_TRACE(COMP_ERR, "---->cmpk_message_handle_rx():unknow CMD Element\n");
707 return 1; /* This is a command packet. */
709 // 2007/01/22 MH Display received rx command packet info.
710 //cmpk_Display_Message(cmd_length, pcmd_buff);
712 // 2007/01/22 MH Add to display tx statistic.
713 //cmpk_DisplayTxStatistic(pAdapter);
715 /* 2007/03/09 MH Collect sidderent cmd element pkt num. */
716 priv->stats.rxcmdpkt[element_id]++;
718 total_length -= cmd_length;
719 pcmd_buff += cmd_length;
720 } /* while (total_length > 0) */
721 return 1; /* This is a command packet. */
723 } /* CMPK_Message_Handle_Rx */