/* * Copyright (C) 2010 NXP Semiconductors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * \file phOsalNfc.c * \brief OSAL Implementation for linux * * Project: Trusted NFC Linux Light * * $Date: 03 aug 2009 * $Author: Jérémie Corbier * $Revision: 1.0 * */ #include #include #include #include #include #include #ifdef ANDROID #define LOG_TAG "NFC-HCI" #include phOsalNfc_Exception_t phOsalNfc_Exception; #endif #ifdef DEBUG #define MAX_PRINT_BUFSIZE (0x450U) char phOsalNfc_DbgTraceBuffer[MAX_PRINT_BUFSIZE]; #endif void phLibNfc_Mgt_Recovery(); /*! * \brief Allocates memory. * This function attempts to allocate \a size bytes on the heap and * returns a pointer to the allocated block. * * \param size size of the memory block to be allocated on the heap. * * \return pointer to allocated memory block or NULL in case of error. */ void *phOsalNfc_GetMemory(uint32_t size) { void *pMem = (void *)malloc(size); return pMem; } /*! * \brief Frees allocated memory block. * This function deallocates memory region pointed to by \a pMem. * * \param pMem pointer to memory block to be freed. */ void phOsalNfc_FreeMemory(void *pMem) { if(NULL != pMem) free(pMem); } void phOsalNfc_DbgString(const char *pString) { #ifdef DEBUG if(pString != NULL) #ifndef ANDROID printf(pString); #else ALOGD("%s", pString); #endif #endif } void phOsalNfc_DbgTrace(uint8_t data[], uint32_t size) { #ifdef DEBUG uint32_t i; #ifdef ANDROID char buf[10]; #endif if(size == 0) return; #ifndef ANDROID for(i = 0; i < size; i++) { if((i % 10) == 0) printf("\n\t\t\t"); printf("%02X ", data[i]); } printf("\n\tBlock size is: %d\n", size); #else phOsalNfc_DbgTraceBuffer[0] = '\0'; for(i = 0; i < size; i++) { if((i % 10) == 0) { ALOGD("%s", phOsalNfc_DbgTraceBuffer); phOsalNfc_DbgTraceBuffer[0] = '\0'; } snprintf(buf, 10, "%02X ", data[i]); strncat(phOsalNfc_DbgTraceBuffer, buf, 10); } ALOGD("%s", phOsalNfc_DbgTraceBuffer); ALOGD("Block size is: %d", size); #endif #endif } /*! * \brief Raises exception. * This function raises an exception of type \a eExceptionType with * reason \a reason to stack clients. * * \param eExceptionType exception type. * \param reason reason for this exception. * * \note Clients willing to catch exceptions are to handle the SIGABRT signal. * On Linux, exception type and reason are passed to the signal handler as * a pointer to a phOsalNfc_Exception_t structure. * As sigqueue is not available in Android, exception information are * stored in the phOsalNfc_Exception global. */ void phOsalNfc_RaiseException(phOsalNfc_ExceptionType_t eExceptionType, uint16_t reason) { if(eExceptionType == phOsalNfc_e_UnrecovFirmwareErr) { ALOGE("HCI Timeout - Exception raised - Force restart of NFC service"); phLibNfc_Mgt_Recovery(); abort(); } else { ALOGD("phOsalNfc_RaiseException() called"); } } /*! * \brief display data bytes. * This function displays data bytes for debug purpose * \param[in] pString pointer to string to be displayed. * \param[in] length number of bytes to be displayed. * \param[in] pBuffer pointer to data bytes to be displayed. * */ void phOsalNfc_PrintData(const char *pString, uint32_t length, uint8_t *pBuffer, int verbosity) { char print_buffer[length * 3 + 1]; unsigned int i; if (pString == NULL) { pString = ""; } print_buffer[0] = '\0'; for (i = 0; i < length; i++) { snprintf(&print_buffer[i*3], 4, " %02X", pBuffer[i]); } char llc[40] = ""; if (verbosity >= 2) { uint8_t llc_header = 0; if (!strcmp(pString, "SEND") && length >= 2) { llc_header = pBuffer[1]; } else if (!strcmp(pString, "RECV") && length >= 2) { llc_header = pBuffer[0]; } if ((llc_header & 0xC0) == 0x80) { // I uint8_t ns = (llc_header & 0x38) >> 3; uint8_t nr = llc_header & 0x07; snprintf(&llc[0], sizeof(llc), "I %d (%d)", ns, nr); } else if ((llc_header & 0xE0) == 0xC0) { // S uint8_t t = (llc_header & 0x18) >> 3; uint8_t nr = llc_header & 0x07; char *type; switch (t) { case 0x00: type = "RR "; break; case 0x01: type = "REJ"; break; case 0x02: type = "RNR"; break; case 0x03: type = "SREJ"; break; default: type = "???"; break; } snprintf(&llc[0], sizeof(llc), "S %s (%d)", type, nr); } else if ((llc_header & 0xE0) == 0xE0) { // U snprintf(&llc[0], sizeof(llc), "U"); } else if (length > 1) { snprintf(&llc[0], sizeof(llc), "???"); } } ALOGD("> %s:%s\t%s", pString, print_buffer, llc); }