Branch data Line data Source code
1 : : /* =========================================================================
2 : : * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.c $
3 : : * $Revision: #4 $
4 : : * $Date: 2010/11/04 $
5 : : * $Change: 1621692 $
6 : : *
7 : : * Synopsys Portability Library Software and documentation
8 : : * (hereinafter, "Software") is an Unsupported proprietary work of
9 : : * Synopsys, Inc. unless otherwise expressly agreed to in writing
10 : : * between Synopsys and you.
11 : : *
12 : : * The Software IS NOT an item of Licensed Software or Licensed Product
13 : : * under any End User Software License Agreement or Agreement for
14 : : * Licensed Product with Synopsys or any supplement thereto. You are
15 : : * permitted to use and redistribute this Software in source and binary
16 : : * forms, with or without modification, provided that redistributions
17 : : * of source code must retain this notice. You may not view, use,
18 : : * disclose, copy or distribute this file or any information contained
19 : : * herein except pursuant to this license grant from Synopsys. If you
20 : : * do not agree with this notice, including the disclaimer below, then
21 : : * you are not authorized to use the Software.
22 : : *
23 : : * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
24 : : * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 : : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 : : * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
27 : : * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 : : * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 : : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 : : * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
31 : : * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
33 : : * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
34 : : * DAMAGE.
35 : : * ========================================================================= */
36 : : #ifdef DWC_CCLIB
37 : :
38 : : #include "dwc_cc.h"
39 : :
40 : : typedef struct dwc_cc
41 : : {
42 : : uint32_t uid;
43 : : uint8_t chid[16];
44 : : uint8_t cdid[16];
45 : : uint8_t ck[16];
46 : : uint8_t *name;
47 : : uint8_t length;
48 : : DWC_CIRCLEQ_ENTRY(dwc_cc) list_entry;
49 : : } dwc_cc_t;
50 : :
51 : : DWC_CIRCLEQ_HEAD(context_list, dwc_cc);
52 : :
53 : : /** The main structure for CC management. */
54 : : struct dwc_cc_if
55 : : {
56 : : dwc_mutex_t *mutex;
57 : : char *filename;
58 : :
59 : : unsigned is_host:1;
60 : :
61 : : dwc_notifier_t *notifier;
62 : :
63 : : struct context_list list;
64 : : };
65 : :
66 : : #ifdef DEBUG
67 : : static inline void dump_bytes(char *name, uint8_t *bytes, int len)
68 : : {
69 : : int i;
70 : : DWC_PRINTF("%s: ", name);
71 : : for (i=0; i<len; i++) {
72 : : DWC_PRINTF("%02x ", bytes[i]);
73 : : }
74 : : DWC_PRINTF("\n");
75 : : }
76 : : #else
77 : : #define dump_bytes(x...)
78 : : #endif
79 : :
80 : 0 : static dwc_cc_t *alloc_cc(void *mem_ctx, uint8_t *name, uint32_t length)
81 : : {
82 : 0 : dwc_cc_t *cc = dwc_alloc(mem_ctx, sizeof(dwc_cc_t));
83 [ # # ]: 0 : if (!cc) {
84 : : return NULL;
85 : : }
86 : 0 : DWC_MEMSET(cc, 0, sizeof(dwc_cc_t));
87 : :
88 [ # # ]: 0 : if (name) {
89 : 0 : cc->length = length;
90 : 0 : cc->name = dwc_alloc(mem_ctx, length);
91 [ # # ]: 0 : if (!cc->name) {
92 : 0 : dwc_free(mem_ctx, cc);
93 : 0 : return NULL;
94 : : }
95 : :
96 : 0 : DWC_MEMCPY(cc->name, name, length);
97 : : }
98 : :
99 : 0 : return cc;
100 : : }
101 : :
102 : 0 : static void free_cc(void *mem_ctx, dwc_cc_t *cc)
103 : : {
104 [ # # ]: 0 : if (cc->name) {
105 : 0 : dwc_free(mem_ctx, cc->name);
106 : : }
107 : 0 : dwc_free(mem_ctx, cc);
108 : 0 : }
109 : :
110 : : static uint32_t next_uid(dwc_cc_if_t *cc_if)
111 : : {
112 : : uint32_t uid = 0;
113 : : dwc_cc_t *cc;
114 [ # # ]: 0 : DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
115 [ # # ]: 0 : if (cc->uid > uid) {
116 : : uid = cc->uid;
117 : : }
118 : : }
119 : :
120 [ # # ]: 0 : if (uid == 0) {
121 : : uid = 255;
122 : : }
123 : :
124 : 0 : return uid + 1;
125 : : }
126 : :
127 : : static dwc_cc_t *cc_find(dwc_cc_if_t *cc_if, uint32_t uid)
128 : : {
129 : : dwc_cc_t *cc;
130 [ # # # # : 0 : DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
# # # # #
# # # #
# ]
131 [ # # # # : 0 : if (cc->uid == uid) {
# # # # #
# # # #
# ]
132 : 0 : return cc;
133 : : }
134 : : }
135 : : return NULL;
136 : : }
137 : :
138 : : static unsigned int cc_data_size(dwc_cc_if_t *cc_if)
139 : : {
140 : : unsigned int size = 0;
141 : : dwc_cc_t *cc;
142 [ # # ]: 0 : DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
143 : 0 : size += (48 + 1);
144 [ # # ]: 0 : if (cc->name) {
145 : 0 : size += cc->length;
146 : : }
147 : : }
148 : 0 : return size;
149 : : }
150 : :
151 : 0 : static uint32_t cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
152 : : {
153 : : uint32_t uid = 0;
154 : : dwc_cc_t *cc;
155 : :
156 [ # # ]: 0 : DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
157 [ # # ]: 0 : if (DWC_MEMCMP(cc->chid, chid, 16) == 0) {
158 : 0 : uid = cc->uid;
159 : 0 : break;
160 : : }
161 : : }
162 : 0 : return uid;
163 : : }
164 : 0 : static uint32_t cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
165 : : {
166 : : uint32_t uid = 0;
167 : : dwc_cc_t *cc;
168 : :
169 [ # # ]: 0 : DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
170 [ # # ]: 0 : if (DWC_MEMCMP(cc->cdid, cdid, 16) == 0) {
171 : 0 : uid = cc->uid;
172 : 0 : break;
173 : : }
174 : : }
175 : 0 : return uid;
176 : : }
177 : :
178 : : /* Internal cc_add */
179 : 0 : static int32_t cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
180 : : uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
181 : : {
182 : : dwc_cc_t *cc;
183 : : uint32_t uid;
184 : :
185 [ # # ]: 0 : if (cc_if->is_host) {
186 : 0 : uid = cc_match_cdid(cc_if, cdid);
187 : : }
188 : : else {
189 : 0 : uid = cc_match_chid(cc_if, chid);
190 : : }
191 : :
192 [ # # ]: 0 : if (uid) {
193 : : DWC_DEBUGC("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length);
194 : : cc = cc_find(cc_if, uid);
195 : : }
196 : : else {
197 : 0 : cc = alloc_cc(mem_ctx, name, length);
198 : 0 : cc->uid = next_uid(cc_if);
199 [ # # ]: 0 : DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry);
200 : : }
201 : :
202 : 0 : DWC_MEMCPY(&(cc->chid[0]), chid, 16);
203 : 0 : DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
204 : 0 : DWC_MEMCPY(&(cc->ck[0]), ck, 16);
205 : :
206 : : DWC_DEBUGC("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length);
207 : : dump_bytes("CHID", cc->chid, 16);
208 : : dump_bytes("CDID", cc->cdid, 16);
209 : : dump_bytes("CK", cc->ck, 16);
210 : 0 : return cc->uid;
211 : : }
212 : :
213 : : /* Internal cc_clear */
214 : 0 : static void cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
215 : : {
216 [ # # ]: 0 : while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) {
217 : : dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list);
218 [ # # # # ]: 0 : DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
219 : 0 : free_cc(mem_ctx, cc);
220 : : }
221 : 0 : }
222 : :
223 : 0 : dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx,
224 : : dwc_notifier_t *notifier, unsigned is_host)
225 : : {
226 : : dwc_cc_if_t *cc_if = NULL;
227 : :
228 : : /* Allocate a common_cc_if structure */
229 : 0 : cc_if = dwc_alloc(mem_ctx, sizeof(dwc_cc_if_t));
230 : :
231 [ # # ]: 0 : if (!cc_if)
232 : : return NULL;
233 : :
234 : : #if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
235 : : DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex);
236 : : #else
237 : 0 : cc_if->mutex = dwc_mutex_alloc(mtx_ctx);
238 : : #endif
239 [ # # ]: 0 : if (!cc_if->mutex) {
240 : 0 : dwc_free(mem_ctx, cc_if);
241 : 0 : return NULL;
242 : : }
243 : :
244 : 0 : DWC_CIRCLEQ_INIT(&cc_if->list);
245 : 0 : cc_if->is_host = is_host;
246 : 0 : cc_if->notifier = notifier;
247 : 0 : return cc_if;
248 : : }
249 : :
250 : 0 : void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if)
251 : : {
252 : : #if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
253 : : DWC_MUTEX_FREE(cc_if->mutex);
254 : : #else
255 : 0 : dwc_mutex_free(mtx_ctx, cc_if->mutex);
256 : : #endif
257 : 0 : cc_clear(mem_ctx, cc_if);
258 : 0 : dwc_free(mem_ctx, cc_if);
259 : 0 : }
260 : :
261 : : static void cc_changed(dwc_cc_if_t *cc_if)
262 : : {
263 [ # # # # : 0 : if (cc_if->notifier) {
# # # # #
# ]
264 : 0 : dwc_notify(cc_if->notifier, DWC_CC_LIST_CHANGED_NOTIFICATION, cc_if);
265 : : }
266 : : }
267 : :
268 : 0 : void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
269 : : {
270 : 0 : DWC_MUTEX_LOCK(cc_if->mutex);
271 : 0 : cc_clear(mem_ctx, cc_if);
272 : 0 : DWC_MUTEX_UNLOCK(cc_if->mutex);
273 : : cc_changed(cc_if);
274 : 0 : }
275 : :
276 : 0 : int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
277 : : uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
278 : : {
279 : : uint32_t uid;
280 : :
281 : 0 : DWC_MUTEX_LOCK(cc_if->mutex);
282 : 0 : uid = cc_add(mem_ctx, cc_if, chid, cdid, ck, name, length);
283 : 0 : DWC_MUTEX_UNLOCK(cc_if->mutex);
284 : : cc_changed(cc_if);
285 : :
286 : 0 : return uid;
287 : : }
288 : :
289 : 0 : void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid,
290 : : uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
291 : : {
292 : : dwc_cc_t* cc;
293 : :
294 : : DWC_DEBUGC("Change connection context %d", id);
295 : :
296 : 0 : DWC_MUTEX_LOCK(cc_if->mutex);
297 : 0 : cc = cc_find(cc_if, id);
298 [ # # ]: 0 : if (!cc) {
299 : 0 : DWC_ERROR("Uid %d not found in cc list\n", id);
300 : 0 : DWC_MUTEX_UNLOCK(cc_if->mutex);
301 : 0 : return;
302 : : }
303 : :
304 [ # # ]: 0 : if (chid) {
305 : 0 : DWC_MEMCPY(&(cc->chid[0]), chid, 16);
306 : : }
307 [ # # ]: 0 : if (cdid) {
308 : 0 : DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
309 : : }
310 [ # # ]: 0 : if (ck) {
311 : 0 : DWC_MEMCPY(&(cc->ck[0]), ck, 16);
312 : : }
313 : :
314 [ # # ]: 0 : if (name) {
315 [ # # ]: 0 : if (cc->name) {
316 : 0 : dwc_free(mem_ctx, cc->name);
317 : : }
318 : 0 : cc->name = dwc_alloc(mem_ctx, length);
319 [ # # ]: 0 : if (!cc->name) {
320 : 0 : DWC_ERROR("Out of memory in dwc_cc_change()\n");
321 : 0 : DWC_MUTEX_UNLOCK(cc_if->mutex);
322 : 0 : return;
323 : : }
324 : 0 : cc->length = length;
325 : 0 : DWC_MEMCPY(cc->name, name, length);
326 : : }
327 : :
328 : 0 : DWC_MUTEX_UNLOCK(cc_if->mutex);
329 : :
330 : : cc_changed(cc_if);
331 : :
332 : : DWC_DEBUGC("Changed connection context id=%d\n", id);
333 : : dump_bytes("New CHID", cc->chid, 16);
334 : : dump_bytes("New CDID", cc->cdid, 16);
335 : : dump_bytes("New CK", cc->ck, 16);
336 : : }
337 : :
338 : 0 : void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id)
339 : : {
340 : : dwc_cc_t *cc;
341 : :
342 : : DWC_DEBUGC("Removing connection context %d", id);
343 : :
344 : 0 : DWC_MUTEX_LOCK(cc_if->mutex);
345 : 0 : cc = cc_find(cc_if, id);
346 [ # # ]: 0 : if (!cc) {
347 : 0 : DWC_ERROR("Uid %d not found in cc list\n", id);
348 : 0 : DWC_MUTEX_UNLOCK(cc_if->mutex);
349 : 0 : return;
350 : : }
351 : :
352 [ # # # # ]: 0 : DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
353 : 0 : DWC_MUTEX_UNLOCK(cc_if->mutex);
354 : 0 : free_cc(mem_ctx, cc);
355 : :
356 : : cc_changed(cc_if);
357 : : }
358 : :
359 : 0 : uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, unsigned int *length)
360 : : {
361 : : uint8_t *buf, *x;
362 : 0 : uint8_t zero = 0;
363 : : dwc_cc_t *cc;
364 : :
365 : 0 : DWC_MUTEX_LOCK(cc_if->mutex);
366 : 0 : *length = cc_data_size(cc_if);
367 [ # # ]: 0 : if (!(*length)) {
368 : 0 : DWC_MUTEX_UNLOCK(cc_if->mutex);
369 : 0 : return NULL;
370 : : }
371 : :
372 : : DWC_DEBUGC("Creating data for saving (length=%d)", *length);
373 : :
374 : 0 : buf = dwc_alloc(mem_ctx, *length);
375 [ # # ]: 0 : if (!buf) {
376 : 0 : *length = 0;
377 : 0 : DWC_MUTEX_UNLOCK(cc_if->mutex);
378 : 0 : return NULL;
379 : : }
380 : :
381 : : x = buf;
382 [ # # ]: 0 : DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
383 : 0 : DWC_MEMCPY(x, cc->chid, 16);
384 : 0 : x += 16;
385 : 0 : DWC_MEMCPY(x, cc->cdid, 16);
386 : 0 : x += 16;
387 : 0 : DWC_MEMCPY(x, cc->ck, 16);
388 : 0 : x += 16;
389 [ # # ]: 0 : if (cc->name) {
390 : 0 : DWC_MEMCPY(x, &cc->length, 1);
391 : 0 : x += 1;
392 : 0 : DWC_MEMCPY(x, cc->name, cc->length);
393 : 0 : x += cc->length;
394 : : }
395 : : else {
396 : 0 : DWC_MEMCPY(x, &zero, 1);
397 : 0 : x += 1;
398 : : }
399 : : }
400 : 0 : DWC_MUTEX_UNLOCK(cc_if->mutex);
401 : :
402 : 0 : return buf;
403 : : }
404 : :
405 : 0 : void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length)
406 : : {
407 : : uint8_t name_length;
408 : : uint8_t *name;
409 : : uint8_t *chid;
410 : : uint8_t *cdid;
411 : : uint8_t *ck;
412 : : uint32_t i = 0;
413 : :
414 : 0 : DWC_MUTEX_LOCK(cc_if->mutex);
415 : 0 : cc_clear(mem_ctx, cc_if);
416 : :
417 [ # # ]: 0 : while (i < length) {
418 : 0 : chid = &data[i];
419 : 0 : i += 16;
420 : 0 : cdid = &data[i];
421 : 0 : i += 16;
422 : 0 : ck = &data[i];
423 : 0 : i += 16;
424 : :
425 : 0 : name_length = data[i];
426 : 0 : i ++;
427 : :
428 [ # # ]: 0 : if (name_length) {
429 : 0 : name = &data[i];
430 : 0 : i += name_length;
431 : : }
432 : : else {
433 : : name = NULL;
434 : : }
435 : :
436 : : /* check to see if we haven't overflown the buffer */
437 [ # # ]: 0 : if (i > length) {
438 : 0 : DWC_ERROR("Data format error while attempting to load CCs "
439 : : "(nlen=%d, iter=%d, buflen=%d).\n", name_length, i, length);
440 : 0 : break;
441 : : }
442 : :
443 : 0 : cc_add(mem_ctx, cc_if, chid, cdid, ck, name, name_length);
444 : : }
445 : 0 : DWC_MUTEX_UNLOCK(cc_if->mutex);
446 : :
447 : : cc_changed(cc_if);
448 : 0 : }
449 : :
450 : 0 : uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
451 : : {
452 : : uint32_t uid = 0;
453 : :
454 : 0 : DWC_MUTEX_LOCK(cc_if->mutex);
455 : 0 : uid = cc_match_chid(cc_if, chid);
456 : 0 : DWC_MUTEX_UNLOCK(cc_if->mutex);
457 : 0 : return uid;
458 : : }
459 : 0 : uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
460 : : {
461 : : uint32_t uid = 0;
462 : :
463 : 0 : DWC_MUTEX_LOCK(cc_if->mutex);
464 : 0 : uid = cc_match_cdid(cc_if, cdid);
465 : 0 : DWC_MUTEX_UNLOCK(cc_if->mutex);
466 : 0 : return uid;
467 : : }
468 : :
469 : 0 : uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id)
470 : : {
471 : : uint8_t *ck = NULL;
472 : : dwc_cc_t *cc;
473 : :
474 : 0 : DWC_MUTEX_LOCK(cc_if->mutex);
475 : 0 : cc = cc_find(cc_if, id);
476 [ # # ]: 0 : if (cc) {
477 : 0 : ck = cc->ck;
478 : : }
479 : 0 : DWC_MUTEX_UNLOCK(cc_if->mutex);
480 : :
481 : 0 : return ck;
482 : :
483 : : }
484 : :
485 : 0 : uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id)
486 : : {
487 : : uint8_t *retval = NULL;
488 : : dwc_cc_t *cc;
489 : :
490 : 0 : DWC_MUTEX_LOCK(cc_if->mutex);
491 : 0 : cc = cc_find(cc_if, id);
492 [ # # ]: 0 : if (cc) {
493 : 0 : retval = cc->chid;
494 : : }
495 : 0 : DWC_MUTEX_UNLOCK(cc_if->mutex);
496 : :
497 : 0 : return retval;
498 : : }
499 : :
500 : 0 : uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id)
501 : : {
502 : : uint8_t *retval = NULL;
503 : : dwc_cc_t *cc;
504 : :
505 : 0 : DWC_MUTEX_LOCK(cc_if->mutex);
506 : 0 : cc = cc_find(cc_if, id);
507 [ # # ]: 0 : if (cc) {
508 : 0 : retval = cc->cdid;
509 : : }
510 : 0 : DWC_MUTEX_UNLOCK(cc_if->mutex);
511 : :
512 : 0 : return retval;
513 : : }
514 : :
515 : 0 : uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length)
516 : : {
517 : : uint8_t *retval = NULL;
518 : : dwc_cc_t *cc;
519 : :
520 : 0 : DWC_MUTEX_LOCK(cc_if->mutex);
521 : 0 : *length = 0;
522 : 0 : cc = cc_find(cc_if, id);
523 [ # # ]: 0 : if (cc) {
524 : 0 : *length = cc->length;
525 : 0 : retval = cc->name;
526 : : }
527 : 0 : DWC_MUTEX_UNLOCK(cc_if->mutex);
528 : :
529 : 0 : return retval;
530 : : }
531 : :
532 : : #endif /* DWC_CCLIB */
|