📄 sm_drv_pda.c
字号:
/* * src/sm_drv_pda.c * * Production Data Area API for Conexant CX3110x chipset. * * Copyright (C) 2005, 2006 Nokia Corporation * Author: Samuel Ortiz <samuel.ortiz@nokia.com> * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * */#include <linux/types.h>#include <linux/unistd.h>#include <linux/string.h>#include <asm/errno.h>#include "sm_drv.h"#include "sm_drv_pda.h"/* This is where we'll have our PDA */pda_record_t sm_drv_pda[] = { {0, PDR_MANUFACTURING_PART_NUMBER, NULL}, {0, PDR_PDA_VERSION, NULL}, {0, PDR_NIC_SERIAL_NUMBER, NULL}, {0, PDR_MAC_ADDRESS, NULL}, {0, PDR_REGULATORY_DOMAIN_LIST, NULL}, {0, PDR_TEMPERATURE_TYPE, NULL}, {0, PDR_PRISM_PCI_IDENTIFIER, NULL}, {0, PDR_COUNTRY_INFORMATION, NULL}, {0, PDR_INTERFACE_LIST, NULL}, {0, PDR_HARDWARE_PLATFORM_COMPONENT_ID, NULL}, {0, PDR_OEM_NAME, NULL}, {0, PDR_PRODUCT_NAME, NULL}, {0, PDR_UTF8_OEM_NAME, NULL}, {0, PDR_UTF8_PRODUCT_NAME, NULL}, {0, PDR_COUNTRY_LIST, NULL}, {0, PDR_DEFAULT_COUNTRY, NULL}, {0, PDR_ANTENNA_GAIN, NULL}, {0, PDR_PRISM_INDIGO_PA_CALIBRATION_DATA, NULL}, {0, PDR_RSSI_LINEAR_APPROXIMATION, NULL}, {0, PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS, NULL}, {0, PDR_PRISM_PA_CAL_CURVE_DATA, NULL}, {0, PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND, NULL}, {0, PDR_PRISM_ZIF_TX_IQ_CALIBRATION, NULL}, {0, PDR_REGULATORY_POWER_LIMITS, NULL}, {0, PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED, NULL}, {0, PDR_RADIATED_TRANSMISSION_CORRECTION, NULL}, {0, PDR_PRISM_TX_IQ_CALIBRATION, NULL}, {0, PDR_BASEBAND_REGISTERS, NULL}, {0, PDR_PER_CHANNEL_BASEBAND_REGISTERS, NULL}, {4, PDR_END, NULL},};/* * pda_crc_update: CRC16 update code as found on the web. the return value * will have to be ANDed with 0xffff to get rid of higher bits. */static uint16_t sm_drv_pda_crc_update(uint16_t crc, uint8_t byte){ uint16_t t; crc ^= byte; t = (crc << 8) ^ (crc << 12); crc = t ^ (t >> 5) ^ (t >> 12) ^ (crc >> 8); return crc;}static int16_t sm_drv_pda_crc_compute(pda_record_t * pdr_array){ uint16_t crc; int i = 0; /* check if the pda is there */ if(!pdr_array) return -EINVAL; crc = 0xffff; while (pdr_array[i].code != PDR_END) { if (pdr_array[i].payload != NULL) { int j, payload_size; crc = sm_drv_pda_crc_update(crc, (uint8_t)(pdr_array[i].size & 0xff)); crc = sm_drv_pda_crc_update(crc, (uint8_t)(pdr_array[i].size >> 8)); crc = sm_drv_pda_crc_update(crc, (uint8_t)(pdr_array[i].code & 0xff)); crc = sm_drv_pda_crc_update(crc, (uint8_t)(pdr_array[i].code >> 8)); payload_size = pdr_array[i].size * 2 - PDR_CODE_LENGTH; for (j = 0; j < payload_size; j++) crc = sm_drv_pda_crc_update(crc, pdr_array[i].payload[j]); } i++; } /* Calculate CRC on PDR_END size and code */ crc = sm_drv_pda_crc_update(crc, (uint8_t)(pdr_array[i].size & 0xff)); crc = sm_drv_pda_crc_update(crc, (uint8_t)(pdr_array[i].size >> 8)); crc = sm_drv_pda_crc_update(crc, (uint8_t)(pdr_array[i].code & 0xff)); crc = sm_drv_pda_crc_update(crc, (uint8_t)(pdr_array[i].code >> 8)); crc = ~crc & 0xffff; memcpy(pdr_array[i].payload, &crc, 2); return 0;}static int16_t sm_drv_pda_add_pdr(pda_record_t * pdr_array, uint16_t code, uint8_t * payload, uint16_t size){ uint16_t i = 0, j; if (!pdr_array) return -EINVAL; do { if (pdr_array[i].code == code) { DEBUG(DBG_PDA, "Found code: 0x%x\n", code); pdr_array[i].payload = (uint8_t *)kmalloc(size, GFP_KERNEL); if (!pdr_array[i].payload) { DEBUG(DBG_PDA, "Couldn't allocate PDR's payload\n"); return -ENOMEM; } DEBUG(DBG_PDA, "Adding PDR 0x%x, with payload:\n", code); memcpy(pdr_array[i].payload, payload, size); for (j = 0; j < size ; j++) DEBUG(DBG_PDA, "0x%.2x ", pdr_array[i].payload[j]); DEBUG(DBG_PDA, "\n"); pdr_array[i].size = (PDR_CODE_LENGTH + size) >> 1; break; } i++; } while (pdr_array[i].code != PDR_END); if (code == PDR_END) { DEBUG(DBG_PDA, "Found code: 0x%x\n", code); pdr_array[i].payload = kmalloc(size, GFP_KERNEL); if (!pdr_array[i].payload) { //perror("Couldn't allocate PDR's payload\n"); return -ENOMEM; } DEBUG(DBG_PDA, "Adding PDR 0x%x, with payload:\n", code); memcpy(pdr_array[i].payload, payload, size); for (j = 0; j < size ; j++) DEBUG(DBG_PDA, "0x%2x ", pdr_array[i].payload[j]); DEBUG(DBG_PDA, "\n"); pdr_array[i].size = (PDR_CODE_LENGTH + size) >> 1; } if (pdr_array[i].code == PDR_END && code != PDR_END) return -EINVAL; return 0;}int16_t sm_drv_pda_replace_pdr(pda_record_t * pdr_array, uint16_t code, uint8_t * payload, uint16_t size){ uint16_t i = 0, j; if (!pdr_array) return -EINVAL; do { if (pdr_array[i].code == code) { DEBUG(DBG_PDA, "Found code: 0x%x\n", code); kfree(pdr_array[i].payload); if (payload != NULL) { pdr_array[i].payload = (uint8_t *)kmalloc(size, GFP_KERNEL); if (!pdr_array[i].payload) { DEBUG(DBG_PDA, "Couldn't allocate PDR's payload\n"); return -ENOMEM; } DEBUG(DBG_PDA, "Adding PDR 0x%x, with payload:\n", code); memcpy(pdr_array[i].payload, payload, size); for (j = 0; j < size ; j++) DEBUG(DBG_PDA, "0x%.2x ", pdr_array[i].payload[j]); DEBUG(DBG_PDA, "\n"); pdr_array[i].size = (PDR_CODE_LENGTH + size) >> 1; } else { pdr_array[i].size = (PDR_CODE_LENGTH) >> 1; } break; } i++; } while (pdr_array[i].code != PDR_END); if (pdr_array[i].code == PDR_END) return -EINVAL; return 0; }#if 0static void sm_drv_pda_free(pda_record_t * pdr_array){ uint8_t i = 0; if (!pdr_array) return; while (pdr_array[i].code != PDR_END) { if (pdr_array[i].payload) kfree(pdr_array[i].payload); pdr_array[i].size = 0; i++; }}#endif/* * We build a pda_array structure from a raw PDA. */ short sm_drv_pda_init(pda_record_t * pdr_array, uint8_t * pda_buffer, uint16_t pda_len){ uint16_t offset = 0; int ret; do { unsigned short pdr = UINT16_GET(pda_buffer + offset + PDR_SIZE_LENGTH); unsigned char * payload = pda_buffer + offset + PDR_SIZE_LENGTH + PDR_CODE_LENGTH; DEBUG(DBG_PDA, "PDR: 0x%x at 0x%x(%d)\n", pdr, offset, offset); DEBUG(DBG_PDA, " Length: %d\n", UINT16_GET(pda_buffer + offset) * 2 - PDR_CODE_LENGTH); ret = sm_drv_pda_add_pdr(pdr_array, pdr, payload, UINT16_GET(pda_buffer + offset) * 2 - PDR_CODE_LENGTH); if (ret < 0) { return ret; } if(pdr == PDR_END) break; /* add pdr field length(2) + pdr length */ offset += PDR_SIZE_LENGTH + UINT16_GET(pda_buffer + offset) * 2; } while(1); return 0;}/* Build a s_pda struct from a pda_record */struct s_pda * sm_drv_pda_get_pda(pda_record_t * pdr_array){ struct s_pda * pda; int i = 0, offset = 0; uint8_t * pda_buffer; /* CRC the beast */ sm_drv_pda_crc_compute(pdr_array); /* First we calculate the length of the PDA */ do { if (sm_drv_pda[i].payload) { offset += PDR_SIZE_LENGTH + pdr_array[i].size * sizeof(uint16_t); if (pdr_array[i].code == PDR_END) break; } i++; } while (1); pda = (struct s_pda *)kmalloc(sizeof(struct s_pda) + offset, GFP_KERNEL); if (!pda) return pda; pda->size = offset; pda_buffer = (uint8_t*)(pda + 1); i = 0; offset = 0; /* Then we build the PDA */ do { if (sm_drv_pda[i].payload) { uint16_t size = PDR_SIZE_LENGTH + pdr_array[i].size * sizeof(uint16_t); memcpy(pda_buffer + offset, (uint8_t*)&sm_drv_pda[i], PDR_SIZE_LENGTH + PDR_CODE_LENGTH); offset += PDR_SIZE_LENGTH + PDR_CODE_LENGTH; memcpy(pda_buffer + offset, sm_drv_pda[i].payload, size - (PDR_SIZE_LENGTH + PDR_CODE_LENGTH)); offset += size - (PDR_SIZE_LENGTH + PDR_CODE_LENGTH); if (pdr_array[i].code == PDR_END) break; } i++; } while (1); return pda;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -