linux/drivers/staging/csr/csr_msgconv.c
<<
>>
Prefs
   1/*****************************************************************************
   2
   3            (c) Cambridge Silicon Radio Limited 2010
   4            All rights reserved and confidential information of CSR
   5
   6            Refer to LICENSE.txt included with this source for details
   7            on the license terms.
   8
   9*****************************************************************************/
  10
  11#include <linux/module.h>
  12#include <linux/types.h>
  13#include <linux/slab.h>
  14#include "csr_panic.h"
  15#include "csr_sched.h"
  16#include "csr_msgconv.h"
  17#include "csr_macro.h"
  18
  19static CsrMsgConvEntry *converter;
  20
  21CsrMsgConvPrimEntry *CsrMsgConvFind(u16 primType)
  22{
  23    CsrMsgConvPrimEntry *ptr = NULL;
  24
  25    if (converter)
  26    {
  27        ptr = converter->profile_converters;
  28        while (ptr)
  29        {
  30            if (ptr->primType == primType)
  31            {
  32                break;
  33            }
  34            else
  35            {
  36                ptr = ptr->next;
  37            }
  38        }
  39    }
  40
  41    return ptr;
  42}
  43
  44static const CsrMsgConvMsgEntry *find_msg_converter(CsrMsgConvPrimEntry *ptr, u16 msgType)
  45{
  46    const CsrMsgConvMsgEntry *cv = ptr->conv;
  47    if (ptr->lookupFunc)
  48    {
  49        return (const CsrMsgConvMsgEntry *) ptr->lookupFunc((CsrMsgConvMsgEntry *) cv, msgType);
  50    }
  51
  52    while (cv)
  53    {
  54        if (cv->serFunc == NULL)
  55        {
  56            /* We've reached the end of the chain */
  57            cv = NULL;
  58            break;
  59        }
  60
  61        if (cv->msgType == msgType)
  62        {
  63            break;
  64        }
  65        else
  66        {
  67            cv++;
  68        }
  69    }
  70
  71    return cv;
  72}
  73
  74static void *deserialize_data(u16 primType,
  75    size_t length,
  76    u8 *data)
  77{
  78    CsrMsgConvPrimEntry *ptr;
  79    u8 *ret;
  80
  81    ptr = CsrMsgConvFind(primType);
  82
  83    if (ptr)
  84    {
  85        const CsrMsgConvMsgEntry *cv;
  86        u16 msgId = 0;
  87        size_t offset = 0;
  88        CsrUint16Des(&msgId, data, &offset);
  89
  90        cv = find_msg_converter(ptr, msgId);
  91        if (cv)
  92        {
  93            ret = cv->deserFunc(data, length);
  94        }
  95        else
  96        {
  97            ret = NULL;
  98        }
  99    }
 100    else
 101    {
 102        ret = NULL;
 103    }
 104
 105    return ret;
 106}
 107
 108static size_t sizeof_message(u16 primType, void *msg)
 109{
 110    CsrMsgConvPrimEntry *ptr = CsrMsgConvFind(primType);
 111    size_t ret;
 112
 113    if (ptr)
 114    {
 115        const CsrMsgConvMsgEntry *cv;
 116        u16 msgId = *(u16 *) msg;
 117
 118        cv = find_msg_converter(ptr, msgId);
 119        if (cv)
 120        {
 121            ret = cv->sizeofFunc(msg);
 122        }
 123        else
 124        {
 125            ret = 0;
 126        }
 127    }
 128    else
 129    {
 130        ret = 0;
 131    }
 132
 133    return ret;
 134}
 135
 136static u8 free_message(u16 primType, u8 *data)
 137{
 138    CsrMsgConvPrimEntry *ptr;
 139    u8 ret;
 140
 141    ptr = CsrMsgConvFind(primType);
 142
 143    if (ptr)
 144    {
 145        const CsrMsgConvMsgEntry *cv;
 146        u16 msgId = *(u16 *) data;
 147
 148        cv = find_msg_converter(ptr, msgId);
 149        if (cv)
 150        {
 151            cv->freeFunc(data);
 152            ret = TRUE;
 153        }
 154        else
 155        {
 156            ret = FALSE;
 157        }
 158    }
 159    else
 160    {
 161        ret = FALSE;
 162    }
 163
 164    return ret;
 165}
 166
 167static u8 *serialize_message(u16 primType,
 168    void *msg,
 169    size_t *length,
 170    u8 *buffer)
 171{
 172    CsrMsgConvPrimEntry *ptr;
 173    u8 *ret;
 174
 175    ptr = CsrMsgConvFind(primType);
 176
 177    *length = 0;
 178
 179    if (ptr)
 180    {
 181        const CsrMsgConvMsgEntry *cv;
 182
 183        cv = find_msg_converter(ptr, *(u16 *) msg);
 184        if (cv)
 185        {
 186            ret = cv->serFunc(buffer, length, msg);
 187        }
 188        else
 189        {
 190            ret = NULL;
 191        }
 192    }
 193    else
 194    {
 195        ret = NULL;
 196    }
 197
 198    return ret;
 199}
 200
 201size_t CsrMsgConvSizeof(u16 primType, void *msg)
 202{
 203    return sizeof_message(primType, msg);
 204}
 205
 206u8 *CsrMsgConvSerialize(u8 *buffer, size_t maxBufferOffset, size_t *offset, u16 primType, void *msg)
 207{
 208    if (converter)
 209    {
 210        size_t serializedLength;
 211        u8 *bufSerialized;
 212        u8 *bufOffset = &buffer[*offset];
 213        bufSerialized = converter->serialize_message(primType, msg, &serializedLength, bufOffset);
 214        *offset += serializedLength;
 215        return bufSerialized;
 216    }
 217    else
 218    {
 219        return NULL;
 220    }
 221}
 222
 223/* Insert profile converter at head of converter list. */
 224void CsrMsgConvInsert(u16 primType, const CsrMsgConvMsgEntry *ce)
 225{
 226    CsrMsgConvPrimEntry *pc;
 227    pc = CsrMsgConvFind(primType);
 228
 229    if (pc)
 230    {
 231        /* Already registered. Do nothing */
 232    }
 233    else
 234    {
 235        pc = kmalloc(sizeof(*pc), GFP_KERNEL);
 236        pc->primType = primType;
 237        pc->conv = ce;
 238        pc->lookupFunc = NULL;
 239        pc->next = converter->profile_converters;
 240        converter->profile_converters = pc;
 241    }
 242}
 243EXPORT_SYMBOL_GPL(CsrMsgConvInsert);
 244
 245CsrMsgConvMsgEntry *CsrMsgConvFindEntry(u16 primType, u16 msgType)
 246{
 247    CsrMsgConvPrimEntry *ptr = CsrMsgConvFind(primType);
 248    if (ptr)
 249    {
 250        return (CsrMsgConvMsgEntry *) find_msg_converter(ptr, msgType);
 251    }
 252    return NULL;
 253}
 254EXPORT_SYMBOL_GPL(CsrMsgConvFindEntry);
 255
 256CsrMsgConvMsgEntry *CsrMsgConvFindEntryByMsg(u16 primType, const void *msg)
 257{
 258    CsrMsgConvPrimEntry *ptr = CsrMsgConvFind(primType);
 259    if (ptr && msg)
 260    {
 261        u16 msgType = *((u16 *) msg);
 262        return (CsrMsgConvMsgEntry *) find_msg_converter(ptr, msgType);
 263    }
 264    return NULL;
 265}
 266
 267void CsrMsgConvCustomLookupRegister(u16 primType, CsrMsgCustomLookupFunc *lookupFunc)
 268{
 269    CsrMsgConvPrimEntry *ptr = CsrMsgConvFind(primType);
 270    if (ptr)
 271    {
 272        ptr->lookupFunc = lookupFunc;
 273    }
 274}
 275EXPORT_SYMBOL_GPL(CsrMsgConvCustomLookupRegister);
 276
 277CsrMsgConvEntry *CsrMsgConvInit(void)
 278{
 279    if (!converter)
 280    {
 281        converter = kmalloc(sizeof(CsrMsgConvEntry), GFP_KERNEL);
 282
 283        converter->profile_converters = NULL;
 284        converter->free_message = free_message;
 285        converter->sizeof_message = sizeof_message;
 286        converter->serialize_message = serialize_message;
 287        converter->deserialize_data = deserialize_data;
 288    }
 289
 290    return converter;
 291}
 292EXPORT_SYMBOL_GPL(CsrMsgConvInit);
 293