⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sm_drv_pda.c

📁 cx3110 drivers for linux 2.6 (基于SPI)
💻 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 + -