1 /* =========================================================================
2 * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.c $
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.
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.
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
35 * ========================================================================= */
48 DWC_CIRCLEQ_ENTRY(dwc_cc) list_entry;
51 DWC_CIRCLEQ_HEAD(context_list, dwc_cc);
53 /** The main structure for CC management. */
61 dwc_notifier_t *notifier;
63 struct context_list list;
67 static inline void dump_bytes(char *name, uint8_t *bytes, int len)
70 DWC_PRINTF("%s: ", name);
71 for (i=0; i<len; i++) {
72 DWC_PRINTF("%02x ", bytes[i]);
77 #define dump_bytes(x...)
80 static dwc_cc_t *alloc_cc(void *mem_ctx, uint8_t *name, uint32_t length)
82 dwc_cc_t *cc = dwc_alloc(mem_ctx, sizeof(dwc_cc_t));
86 DWC_MEMSET(cc, 0, sizeof(dwc_cc_t));
90 cc->name = dwc_alloc(mem_ctx, length);
92 dwc_free(mem_ctx, cc);
96 DWC_MEMCPY(cc->name, name, length);
102 static void free_cc(void *mem_ctx, dwc_cc_t *cc)
105 dwc_free(mem_ctx, cc->name);
107 dwc_free(mem_ctx, cc);
110 static uint32_t next_uid(dwc_cc_if_t *cc_if)
114 DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
127 static dwc_cc_t *cc_find(dwc_cc_if_t *cc_if, uint32_t uid)
130 DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
131 if (cc->uid == uid) {
138 static unsigned int cc_data_size(dwc_cc_if_t *cc_if)
140 unsigned int size = 0;
142 DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
151 static uint32_t cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
156 DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
157 if (DWC_MEMCMP(cc->chid, chid, 16) == 0) {
164 static uint32_t cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
169 DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
170 if (DWC_MEMCMP(cc->cdid, cdid, 16) == 0) {
178 /* Internal cc_add */
179 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)
185 if (cc_if->is_host) {
186 uid = cc_match_cdid(cc_if, cdid);
189 uid = cc_match_chid(cc_if, chid);
193 DWC_DEBUGC("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length);
194 cc = cc_find(cc_if, uid);
197 cc = alloc_cc(mem_ctx, name, length);
198 cc->uid = next_uid(cc_if);
199 DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry);
202 DWC_MEMCPY(&(cc->chid[0]), chid, 16);
203 DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
204 DWC_MEMCPY(&(cc->ck[0]), ck, 16);
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);
213 /* Internal cc_clear */
214 static void cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
216 while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) {
217 dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list);
218 DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
219 free_cc(mem_ctx, cc);
223 dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx,
224 dwc_notifier_t *notifier, unsigned is_host)
226 dwc_cc_if_t *cc_if = NULL;
228 /* Allocate a common_cc_if structure */
229 cc_if = dwc_alloc(mem_ctx, sizeof(dwc_cc_if_t));
234 #if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
235 DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex);
237 cc_if->mutex = dwc_mutex_alloc(mtx_ctx);
240 dwc_free(mem_ctx, cc_if);
244 DWC_CIRCLEQ_INIT(&cc_if->list);
245 cc_if->is_host = is_host;
246 cc_if->notifier = notifier;
250 void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if)
252 #if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
253 DWC_MUTEX_FREE(cc_if->mutex);
255 dwc_mutex_free(mtx_ctx, cc_if->mutex);
257 cc_clear(mem_ctx, cc_if);
258 dwc_free(mem_ctx, cc_if);
261 static void cc_changed(dwc_cc_if_t *cc_if)
263 if (cc_if->notifier) {
264 dwc_notify(cc_if->notifier, DWC_CC_LIST_CHANGED_NOTIFICATION, cc_if);
268 void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
270 DWC_MUTEX_LOCK(cc_if->mutex);
271 cc_clear(mem_ctx, cc_if);
272 DWC_MUTEX_UNLOCK(cc_if->mutex);
276 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)
281 DWC_MUTEX_LOCK(cc_if->mutex);
282 uid = cc_add(mem_ctx, cc_if, chid, cdid, ck, name, length);
283 DWC_MUTEX_UNLOCK(cc_if->mutex);
289 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)
294 DWC_DEBUGC("Change connection context %d", id);
296 DWC_MUTEX_LOCK(cc_if->mutex);
297 cc = cc_find(cc_if, id);
299 DWC_ERROR("Uid %d not found in cc list\n", id);
300 DWC_MUTEX_UNLOCK(cc_if->mutex);
305 DWC_MEMCPY(&(cc->chid[0]), chid, 16);
308 DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
311 DWC_MEMCPY(&(cc->ck[0]), ck, 16);
316 dwc_free(mem_ctx, cc->name);
318 cc->name = dwc_alloc(mem_ctx, length);
320 DWC_ERROR("Out of memory in dwc_cc_change()\n");
321 DWC_MUTEX_UNLOCK(cc_if->mutex);
325 DWC_MEMCPY(cc->name, name, length);
328 DWC_MUTEX_UNLOCK(cc_if->mutex);
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);
338 void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id)
342 DWC_DEBUGC("Removing connection context %d", id);
344 DWC_MUTEX_LOCK(cc_if->mutex);
345 cc = cc_find(cc_if, id);
347 DWC_ERROR("Uid %d not found in cc list\n", id);
348 DWC_MUTEX_UNLOCK(cc_if->mutex);
352 DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
353 DWC_MUTEX_UNLOCK(cc_if->mutex);
354 free_cc(mem_ctx, cc);
359 uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, unsigned int *length)
365 DWC_MUTEX_LOCK(cc_if->mutex);
366 *length = cc_data_size(cc_if);
368 DWC_MUTEX_UNLOCK(cc_if->mutex);
372 DWC_DEBUGC("Creating data for saving (length=%d)", *length);
374 buf = dwc_alloc(mem_ctx, *length);
377 DWC_MUTEX_UNLOCK(cc_if->mutex);
382 DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
383 DWC_MEMCPY(x, cc->chid, 16);
385 DWC_MEMCPY(x, cc->cdid, 16);
387 DWC_MEMCPY(x, cc->ck, 16);
390 DWC_MEMCPY(x, &cc->length, 1);
392 DWC_MEMCPY(x, cc->name, cc->length);
396 DWC_MEMCPY(x, &zero, 1);
400 DWC_MUTEX_UNLOCK(cc_if->mutex);
405 void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length)
414 DWC_MUTEX_LOCK(cc_if->mutex);
415 cc_clear(mem_ctx, cc_if);
425 name_length = data[i];
436 /* check to see if we haven't overflown the buffer */
438 DWC_ERROR("Data format error while attempting to load CCs "
439 "(nlen=%d, iter=%d, buflen=%d).\n", name_length, i, length);
443 cc_add(mem_ctx, cc_if, chid, cdid, ck, name, name_length);
445 DWC_MUTEX_UNLOCK(cc_if->mutex);
450 uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
454 DWC_MUTEX_LOCK(cc_if->mutex);
455 uid = cc_match_chid(cc_if, chid);
456 DWC_MUTEX_UNLOCK(cc_if->mutex);
459 uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
463 DWC_MUTEX_LOCK(cc_if->mutex);
464 uid = cc_match_cdid(cc_if, cdid);
465 DWC_MUTEX_UNLOCK(cc_if->mutex);
469 uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id)
474 DWC_MUTEX_LOCK(cc_if->mutex);
475 cc = cc_find(cc_if, id);
479 DWC_MUTEX_UNLOCK(cc_if->mutex);
485 uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id)
487 uint8_t *retval = NULL;
490 DWC_MUTEX_LOCK(cc_if->mutex);
491 cc = cc_find(cc_if, id);
495 DWC_MUTEX_UNLOCK(cc_if->mutex);
500 uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id)
502 uint8_t *retval = NULL;
505 DWC_MUTEX_LOCK(cc_if->mutex);
506 cc = cc_find(cc_if, id);
510 DWC_MUTEX_UNLOCK(cc_if->mutex);
515 uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length)
517 uint8_t *retval = NULL;
520 DWC_MUTEX_LOCK(cc_if->mutex);
522 cc = cc_find(cc_if, id);
524 *length = cc->length;
527 DWC_MUTEX_UNLOCK(cc_if->mutex);
532 #endif /* DWC_CCLIB */