unpack_wds_GetByteTotals function in the lite-qmi sdk

Does anyone know how to use unpack_wds_GetByteTotals in the lite-qmi sdk?
My application needs to get information of total bytes transmitted.


I’d like you to take a look at the connection manager source code and play with the connection manager. There is a API getPktStats defined there to retrieve data.

In ther SDK unpack_wds_GetByteTotals also calls UpkQmiWdsGetPktStatistics to retrievethe desired number.

Furthermore, you can follow the example of getPktStats to pack a command and unpack the response:
static int getPktStats(
pack_wds_GetPacketStatistics_t *pPktStatsIn,
unpack_wds_GetPacketStatistics_t *pPktStatsOut)
return SendReceive(&sessions[0].wdsSvc,
packGetPktStats, “pack_wds_GetPacketStatistics”, pPktStatsIn,
unpackGetPktStats, “unpack_wds_GetPacketStatistics”, pPktStatsOut);


Thanks your comments. I also found this a couple days ago and was able to get totalbytes/packets tx information. with getPktStats. My current issue is that response of getPktStats takes too long to respond back (63ms). My application requires < 5 ms. Do you know how to improve response time of getPktStats?


This is hard because unpack_wds_GetByteTotals just does as much as UpkQmiWdsGetPktStatistics does. I suspect that it could save time to use pack_wds_GetByteTotals/unpack_wds_GetByteTotals. Please see the source code:
int unpack_wds_GetByteTotals(
uint8_t *pResp,
uint16_t respLen,
unpack_wds_GetByteTotals_t *pOutput
struct QmiWdsGetPktStatisticsResp ApiResp;
int rtn;


memset(&ApiResp, 0, sizeof(ApiResp));

ApiResp.pTXOkBytesCount = (ULONGLONG*) pOutput->pTXTotalBytes;
ApiResp.pRXOkBytesCount = (ULONGLONG*) pOutput->pRXTotalBytes;

rtn = UpkQmiWdsGetPktStatistics( &pResp[SDU_HDR_LEN], &ApiResp);
pOutput->ParamPresenceMask = ApiResp.results.TlvPresenceMask;
liteqmi_log(eLOG_DEBUG,"[unpack] QMI_WDS_GET_PKT_STATISTICS xid 0x%04x returned 0x%x\n",
        helper_get_xid(pResp), rtn);

return rtn;



I found time spent (60ms) on this call, ret = QmiSyncObject_TimedWait(&syncObject, 10);
Do you know why? Is there a way to remove it?


This is used to synchronize QMI send and receive. When a QMI message is sent, the requesting thread waits for the return message, when the response is received (based on service::WDS and transaction-id), the requesting thread will get signalled to process the response. The SDK is designed this way, if we remove this, we cannot sync between send and receive threads.

What module are you using? can you send me ATI info?

What is ATI? I have EM7455 and EM7565 modules.
It is weird if I removed QmiSyncObject_TimedWait(&syncObject, 10) and do a busy polling every 2 ms, I can get response back with 6 ms. This is a good new. However, I can not query it again right away. I need to wait for another 58 ms to do a query otherwise my busy polling time will increase to 63ms if I do a query right after I got the response. So it seems there is 63ms builtin in the FW to prevent me from querying and getting a response faster than 63ms. Do you know why?


Using busypolling with usleep(2000) (See code change below), I can get 4-6ms response back from QmiService_SendRequest to a good response. The issue I am facing now is I can do repeat this query right away after I can a response. I need to wait another 58 ms otherwise my 4-6ms response time will increase to 63ms if I do another query right away., This is a weird behavior and 63ms is a magic number to me.

if (fnPacker(&req_ctx, syncObject.buffer, &syncObject.bufferSize,
pInput == (void*)-1 ? NULL : pInput) != 0)
dlog(eLOG_ERROR, “—%s error\n”,
pPackerName == NULL ? “pack” : pPackerName);
else {
// QmiSyncObject_Lock(&syncObject);

clock_gettime(CLOCK_REALTIME, &before);
int ret;
ret = QmiService_SendRequest(
    pService, req_ctx.xid, syncObject.buffer, syncObject.bufferSize,
    QmiSyncObject_ResponseCallback, (void*)&syncObject);
if (ret != SUCCESS) {
} else {
  while (1) {
    ret = usleep(2000);
    //                      ret = QmiSyncObject_TimedWait(&syncObject, 10);
    //                      QmiSyncObject_Unlock(&syncObject);

    ret = SUCCESS;
    if (ret != SUCCESS) {
      dlog(eLOG_WARN, "Function timed out\n");
      QmiService_CancelTransaction(pService, req_ctx.xid);
    } else {
      //                eLiteRet = eLITE_CONNECT_APP_OK;

      enum eQCWWANError qcError =
          fnUnpacker(syncObject.buffer, syncObject.bufferSize,
                     pOutput == (void*)-1 ? NULL : pOutput);
      if (qcError == eQCWWAN_ERR_NONE) eLiteRet = eLITE_CONNECT_APP_OK;
      //                            else if (pUnpackerName != (void*)-1)
      //                                    dlog(eLOG_INFO, "@@@@@%s failed: %d\n",
      //pUnpackerName == NULL ? "unpack" : pUnpackerName, qcError);
      if (eLiteRet == eLITE_CONNECT_APP_OK) {
        //          QmiSyncObject_Unlock(&syncObject);

        elapsed_nsecs = (after.tv_sec - before.tv_sec) * 1000000000 +
                        (after.tv_nsec - before.tv_nsec);
        printf("wait time to get a good response  (ms): %ld\n",
               elapsed_nsecs / (1000000 * 1));
        printf("packet : %d\n",   TXPacketSuccesses);

// clock_gettime(CLOCK_REALTIME, &before);

Like I said, the requesting thread use this sync mechanism to wait for the right response, based on service type, and the transaction-id. If you don’t this method, I’m not sure what a response you can get.

I tested with qmicli, an open source QMI application. I got 181 ms for --wds-get-packet-statistics
Connection statistics:
TX packets OK: 101
RX packets OK: 82
TX packets dropped: 0
RX packets dropped: 0
TX bytes OK: 13513
RX bytes OK: 19474

This was done with EM7565 module:
Manufacturer: Sierra Wireless, Incorporated
Model: EM7565
Revision: SWI9X50C_01.14.02.00 2e210b jenkins 2020/08/19 14:18:39
MEID: 35926008000151
ESN: 12802279116, 8022C6CC
IMEI: 359260080001511
FSN: UF735485060106


If your task only allows 5 ms, you may need to figure out other ways to get the response, instead of being blocked waiting for the response.

What other ways available to extract this information?