Root/drivers/staging/csr/csr_msgconv.c

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

Archive Download this file



interactive