| /* |
| * 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 <stddef.h> |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <signal.h> |
| #include <unistd.h> |
| |
| #include <phOsalNfc.h> |
| |
| #ifdef ANDROID |
| #define LOG_TAG "NFC-HCI" |
| |
| #include <utils/Log.h> |
| |
| 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); |
| } |