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