Пример #1
0
int readChannelMsg(ant_channel_type eChannel, ant_channel_info_t *pstChnlInfo)
{
   int iRet = -1;
   int iRxLenRead;
   int iCurrentHciPacketOffset;
   int iHciDataSize;
   ANT_FUNC_START();

   // Keep trying to read while there is an error, and that error is EAGAIN
   while (((iRxLenRead = read(pstChnlInfo->iFd, &aucRxBuffer[eChannel][iRxBufferLength[eChannel]], (sizeof(aucRxBuffer[eChannel]) - iRxBufferLength[eChannel]))) < 0)
                   && errno == EAGAIN)
      ;

   if (iRxLenRead < 0) {
      if (errno == ENODEV) {
         ANT_ERROR("%s not enabled, exiting rx thread",
               pstChnlInfo->pcDevicePath);

         goto out;
      } else if (errno == ENXIO) {
         ANT_ERROR("%s there is no physical ANT device connected",
               pstChnlInfo->pcDevicePath);

         goto out;
      } else {
         ANT_ERROR("%s read thread exiting, unhandled error: %s",
               pstChnlInfo->pcDevicePath, strerror(errno));

         goto out;
      }
   } else {
      ANT_SERIAL(aucRxBuffer[eChannel], iRxLenRead, 'R');

      iRxLenRead += iRxBufferLength[eChannel];   // add existing data on

      // if we didn't get a full packet, then just exit
      if (iRxLenRead < (aucRxBuffer[eChannel][ANT_HCI_SIZE_OFFSET] + ANT_HCI_HEADER_SIZE + ANT_HCI_FOOTER_SIZE)) {
         iRxBufferLength[eChannel] = iRxLenRead;
         iRet = 0;
         goto out;
      }

      iRxBufferLength[eChannel] = 0;    // reset buffer length here since we should have a full packet

#if ANT_HCI_OPCODE_SIZE == 1  // Check the different message types by opcode
      ANT_U8 opcode = aucRxBuffer[eChannel][ANT_HCI_OPCODE_OFFSET];

      if(ANT_HCI_OPCODE_COMMAND_COMPLETE == opcode) {
         // Command Complete, so signal a FLOW_GO
         if(setFlowControl(pstChnlInfo, ANT_FLOW_GO)) {
            goto out;
         }
      } else if(ANT_HCI_OPCODE_FLOW_ON == opcode) {
         // FLow On, so resend the last Tx
#ifdef ANT_FLOW_RESEND
         // Check if there is a message to resend
         if(pstChnlInfo->ucResendMessageLength > 0) {
            ant_tx_message_flowcontrol_none(eChannel, pstChnlInfo->ucResendMessageLength, pstChnlInfo->pucResendMessage);
         } else {
            ANT_DEBUG_D("Resend requested by chip, but tx request cancelled");
         }
#endif // ANT_FLOW_RESEND
      } else if(ANT_HCI_OPCODE_ANT_EVENT == opcode)
         // ANT Event, send ANT packet to Rx Callback
#endif // ANT_HCI_OPCODE_SIZE == 1
      {
      // Received an ANT packet
         iCurrentHciPacketOffset = 0;

         while(iCurrentHciPacketOffset < iRxLenRead) {

            // TODO Allow HCI Packet Size value to be larger than 1 byte
            // This currently works as no size value is greater than 255, and little endian
            iHciDataSize = aucRxBuffer[eChannel][iCurrentHciPacketOffset + ANT_HCI_SIZE_OFFSET];

            if ((iHciDataSize + ANT_HCI_HEADER_SIZE + ANT_HCI_FOOTER_SIZE + iCurrentHciPacketOffset) >
                  iRxLenRead) {
               // we don't have a whole packet
               iRxBufferLength[eChannel] = iRxLenRead - iCurrentHciPacketOffset;
               memcpy(aucRxBuffer[eChannel], &aucRxBuffer[eChannel][iCurrentHciPacketOffset], iRxBufferLength[eChannel]);
               // the increment at the end should push us out of the while loop
            } else
#ifdef ANT_MESG_FLOW_CONTROL
            if (aucRxBuffer[eChannel][iCurrentHciPacketOffset + ANT_HCI_DATA_OFFSET + ANT_MSG_ID_OFFSET] ==
                  ANT_MESG_FLOW_CONTROL) {
               // This is a flow control packet, not a standard ANT message
               if(setFlowControl(pstChnlInfo, \
                     aucRxBuffer[eChannel][iCurrentHciPacketOffset + ANT_HCI_DATA_OFFSET + ANT_MSG_DATA_OFFSET])) {
                  goto out;
               }
            } else
#endif // ANT_MESG_FLOW_CONTROL
            {
               ANT_U8 *msg = aucRxBuffer[eChannel] + iCurrentHciPacketOffset + ANT_HCI_DATA_OFFSET;
               ANT_BOOL bIsKeepAliveResponse = memcmp(msg, KEEPALIVE_RESP, sizeof(KEEPALIVE_RESP)/sizeof(ANT_U8)) == 0;
               if (bIsKeepAliveResponse) {
                  ANT_DEBUG_V("Filtered out keepalive response.");
               } else if (pstChnlInfo->fnRxCallback != NULL) {

                  // Loop through read data until all HCI packets are written to callback
                     pstChnlInfo->fnRxCallback(iHciDataSize, \
                           msg);
               } else {
                  ANT_WARN("%s rx callback is null", pstChnlInfo->pcDevicePath);
               }
            }

            iCurrentHciPacketOffset = iCurrentHciPacketOffset + ANT_HCI_HEADER_SIZE + ANT_HCI_FOOTER_SIZE + iHciDataSize;
         }
      }

      iRet = 0;
   }

out:
   ANT_FUNC_END();
   return iRet;
}
ANTStatus ant_tx_message(ANT_U8 ucLen, ANT_U8 *pucMesg)
{
   // During a tx we must prepend a packet type byte. Thus HCI_PACKET_TYPE_SIZE is added
   // to all offsets when writing into the tx buffer.
   ANTStatus status = ANT_STATUS_FAILED;
   // TODO ANT_HCI_MAX_MSG_SIZE is transport (driver) dependent.
   ANT_U8 txBuffer[HCI_PACKET_TYPE_SIZE + ANT_HCI_MAX_MSG_SIZE];
   // TODO Message length can be greater than ANT_U8 can hold.
   // Not changed as ANT_SERIAL takes length as ANT_U8.
   ANT_U8 txMessageLength = HCI_PACKET_TYPE_SIZE + ucLen + ANT_HCI_HEADER_SIZE;
   ANT_FUNC_START();

   if (ant_radio_enabled_status() != RADIO_STATUS_ENABLED) {
      status = ANT_STATUS_FAILED_BT_NOT_INITIALIZED;
      goto out;
   }

#if ANT_HCI_OPCODE_SIZE == 1
   txBuffer[HCI_PACKET_TYPE_SIZE + ANT_HCI_OPCODE_OFFSET] = ANT_HCI_OPCODE_TX;
#elif ANT_HCI_OPCODE_SIZE > 1
#error "Specified ANT_HCI_OPCODE_SIZE not currently supported"
#endif

#if ANT_HCI_SIZE_SIZE == 1
   txBuffer[HCI_PACKET_TYPE_SIZE + ANT_HCI_SIZE_OFFSET] = ucLen;
#elif ANT_HCI_SIZE_SIZE == 2
   ANT_UTILS_StoreLE16(txBuffer + HCI_PACKET_TYPE_SIZE + ANT_HCI_SIZE_OFFSET, (ANT_U16)ucLen);
#else
#error "Specified ANT_HCI_SIZE_SIZE not currently supported"
#endif

   memcpy(txBuffer + HCI_PACKET_TYPE_SIZE + ANT_HCI_HEADER_SIZE, pucMesg, ucLen);

// We no longer do the serial logging here because the packet type byte is not yet written.
//ANT_SERIAL(txBuffer, txMessageLength, 'T');

// We only do this if we are using single physical and logical channels.
#if defined(ANT_DEVICE_NAME) && (HCI_PACKET_TYPE_SIZE == 0) // Single transport path
   ANT_SERIAL(txBuffer, txMessageLength, 'T');
   status = ant_tx_message_flowcontrol_wait(SINGLE_CHANNEL, SINGLE_CHANNEL, txMessageLength, txBuffer);
#else // Separate data/command paths
   // Each path follows this structure:
   // write the packet type if needed.
   // log the packet
   // Send using the appropriate physical channel, waiting for flow control for data commands.
   switch (txBuffer[HCI_PACKET_TYPE_SIZE + ANT_HCI_DATA_OFFSET + ANT_MSG_ID_OFFSET]) {
   case MESG_BROADCAST_DATA_ID:
   case MESG_ACKNOWLEDGED_DATA_ID:
   case MESG_BURST_DATA_ID:
   case MESG_EXT_BROADCAST_DATA_ID:
   case MESG_EXT_ACKNOWLEDGED_DATA_ID:
   case MESG_EXT_BURST_DATA_ID:
   case MESG_ADV_BURST_DATA_ID:
      ANT_DEBUG_V("Data Path");
      #if HCI_PACKET_TYPE_SIZE == 1
      txBuffer[0] = ANT_DATA_TYPE_PACKET;
      #elif HCI_PACKET_TYPE_SIZE > 1
      #error "Specified HCI_PACKET_TYPE_SIZE not supported"
      #endif
      ANT_SERIAL(txBuffer, txMessageLength, 'T');
      #ifdef ANT_DEVICE_NAME
      status = ant_tx_message_flowcontrol_wait(SINGLE_CHANNEL, SINGLE_CHANNEL, txMessageLength, txBuffer);
      #else
      status = ant_tx_message_flowcontrol_wait(DATA_CHANNEL, COMMAND_CHANNEL, txMessageLength, txBuffer);
      #endif
      break;
   default:
      ANT_DEBUG_V("Control Path");
      #if HCI_PACKET_TYPE_SIZE == 1
      txBuffer[0] = ANT_CMD_TYPE_PACKET;
      #elif HCI_PACKET_TYPE_SIZE > 1
      #error "Specified HCI_PACKET_TYPE_SIZE not supported"
      #endif
      ANT_SERIAL(txBuffer, txMessageLength, 'T');
      #ifdef ANT_DEVICE_NAME
      status = ant_tx_message_flowcontrol_none(SINGLE_CHANNEL, txMessageLength, txBuffer);
      #else
      status = ant_tx_message_flowcontrol_none(COMMAND_CHANNEL, txMessageLength, txBuffer);
      #endif
   }
#endif // Separate data/command paths

out:
   ANT_FUNC_END();
   return status;
}