1 _otg_/* =========================================================================
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 * ========================================================================= */
40 typedef struct dwc_cc {
47 DWC_CIRCLEQ_ENTRY(dwc_cc) list_entry;
50 DWC_CIRCLEQ_HEAD(context_list, dwc_cc);
52 /** The main structure for CC management. */
59 dwc_notifier_t *notifier;
61 struct context_list list;
65 static inline void dump_bytes(char *name, uint8_t *bytes, int len)
68 DWC_PRINTF("%s: ", name);
69 for (i = 0; i < len; i++) {
70 DWC_PRINTF("%02x ", bytes[i]);
75 #define dump_bytes(x...)
78 static dwc_cc_t *alloc_cc(void *mem_ctx, uint8_t *name, uint32_t length)
80 dwc_cc_t *cc = dwc_alloc(mem_ctx, sizeof(dwc_cc_t));
84 DWC_MEMSET(cc, 0, sizeof(dwc_cc_t));
88 cc->name = dwc_alloc(mem_ctx, length);
90 dwc_free(mem_ctx, cc);
94 DWC_MEMCPY(cc->name, name, length);
100 static void free_cc(void *mem_ctx, dwc_cc_t *cc)
103 dwc_free(mem_ctx, cc->name);
105 dwc_free(mem_ctx, cc);
108 static uint32_t next_uid(dwc_cc_if_t *cc_if)
112 DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
125 static dwc_cc_t *cc_find(dwc_cc_if_t *cc_if, uint32_t uid)
128 DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
129 if (cc->uid == uid) {
136 static unsigned int cc_data_size(dwc_cc_if_t *cc_if)
138 unsigned int size = 0;
140 DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
149 static uint32_t cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
154 DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
155 if (DWC_MEMCMP(cc->chid, chid, 16) == 0) {
162 static uint32_t cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
167 DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
168 if (DWC_MEMCMP(cc->cdid, cdid, 16) == 0) {
176 /* Internal cc_add */
177 static int32_t cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
178 uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
183 if (cc_if->is_host) {
184 uid = cc_match_cdid(cc_if, cdid);
186 uid = cc_match_chid(cc_if, chid);
190 DWC_DEBUG("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length);
191 cc = cc_find(cc_if, uid);
193 cc = alloc_cc(mem_ctx, name, length);
194 cc->uid = next_uid(cc_if);
195 DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry);
198 DWC_MEMCPY(&(cc->chid[0]), chid, 16);
199 DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
200 DWC_MEMCPY(&(cc->ck[0]), ck, 16);
202 DWC_DEBUG("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length);
203 dump_bytes("CHID", cc->chid, 16);
204 dump_bytes("CDID", cc->cdid, 16);
205 dump_bytes("CK", cc->ck, 16);
209 /* Internal cc_clear */
210 static void cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
212 while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) {
213 dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list);
214 DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
215 free_cc(mem_ctx, cc);
219 dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx,
220 dwc_notifier_t *notifier, unsigned is_host)
222 dwc_cc_if_t *cc_if = NULL;
224 /* Allocate a common_cc_if structure */
225 cc_if = dwc_alloc(mem_ctx, sizeof(dwc_cc_if_t));
230 #if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
231 DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex);
233 cc_if->mutex = dwc_mutex_alloc(mtx_ctx);
236 dwc_free(mem_ctx, cc_if);
240 DWC_CIRCLEQ_INIT(&cc_if->list);
241 cc_if->is_host = is_host;
242 cc_if->notifier = notifier;
246 void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if)
248 #if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
249 DWC_MUTEX_FREE(cc_if->mutex);
251 dwc_mutex_free(mtx_ctx, cc_if->mutex);
253 cc_clear(mem_ctx, cc_if);
254 dwc_free(mem_ctx, cc_if);
257 static void cc_changed(dwc_cc_if_t *cc_if)
259 if (cc_if->notifier) {
260 dwc_notify(cc_if->notifier, DWC_CC_LIST_CHANGED_NOTIFICATION, cc_if);
264 void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
266 DWC_MUTEX_LOCK(cc_if->mutex);
267 cc_clear(mem_ctx, cc_if);
268 DWC_MUTEX_UNLOCK(cc_if->mutex);
272 int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
273 uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
277 DWC_MUTEX_LOCK(cc_if->mutex);
278 uid = cc_add(mem_ctx, cc_if, chid, cdid, ck, name, length);
279 DWC_MUTEX_UNLOCK(cc_if->mutex);
285 void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid,
286 uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
290 DWC_DEBUG("Change connection context %d", id);
292 DWC_MUTEX_LOCK(cc_if->mutex);
293 cc = cc_find(cc_if, id);
295 DWC_ERROR("Uid %d not found in cc list\n", id);
296 DWC_MUTEX_UNLOCK(cc_if->mutex);
301 DWC_MEMCPY(&(cc->chid[0]), chid, 16);
304 DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
307 DWC_MEMCPY(&(cc->ck[0]), ck, 16);
312 dwc_free(mem_ctx, cc->name);
314 cc->name = dwc_alloc(mem_ctx, length);
316 DWC_ERROR("Out of memory in dwc_cc_change()\n");
317 DWC_MUTEX_UNLOCK(cc_if->mutex);
321 DWC_MEMCPY(cc->name, name, length);
324 DWC_MUTEX_UNLOCK(cc_if->mutex);
328 DWC_DEBUG("Changed connection context id=%d\n", id);
329 dump_bytes("New CHID", cc->chid, 16);
330 dump_bytes("New CDID", cc->cdid, 16);
331 dump_bytes("New CK", cc->ck, 16);
334 void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id)
338 DWC_DEBUG("Removing connection context %d", id);
340 DWC_MUTEX_LOCK(cc_if->mutex);
341 cc = cc_find(cc_if, id);
343 DWC_ERROR("Uid %d not found in cc list\n", id);
344 DWC_MUTEX_UNLOCK(cc_if->mutex);
348 DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
349 DWC_MUTEX_UNLOCK(cc_if->mutex);
350 free_cc(mem_ctx, cc);
355 uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, unsigned int *length)
361 DWC_MUTEX_LOCK(cc_if->mutex);
362 *length = cc_data_size(cc_if);
364 DWC_MUTEX_UNLOCK(cc_if->mutex);
368 DWC_DEBUG("Creating data for saving (length=%d)", *length);
370 buf = dwc_alloc(mem_ctx, *length);
373 DWC_MUTEX_UNLOCK(cc_if->mutex);
378 DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
379 DWC_MEMCPY(x, cc->chid, 16);
381 DWC_MEMCPY(x, cc->cdid, 16);
383 DWC_MEMCPY(x, cc->ck, 16);
386 DWC_MEMCPY(x, &cc->length, 1);
388 DWC_MEMCPY(x, cc->name, cc->length);
391 DWC_MEMCPY(x, &zero, 1);
395 DWC_MUTEX_UNLOCK(cc_if->mutex);
400 void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length)
409 DWC_MUTEX_LOCK(cc_if->mutex);
410 cc_clear(mem_ctx, cc_if);
420 name_length = data[i];
430 /* check to see if we haven't overflown the buffer */
432 DWC_ERROR("Data format error while attempting to load CCs "
433 "(nlen=%d, iter=%d, buflen=%d).\n", name_length, i, length);
437 cc_add(mem_ctx, cc_if, chid, cdid, ck, name, name_length);
439 DWC_MUTEX_UNLOCK(cc_if->mutex);
444 uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
448 DWC_MUTEX_LOCK(cc_if->mutex);
449 uid = cc_match_chid(cc_if, chid);
450 DWC_MUTEX_UNLOCK(cc_if->mutex);
453 uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
457 DWC_MUTEX_LOCK(cc_if->mutex);
458 uid = cc_match_cdid(cc_if, cdid);
459 DWC_MUTEX_UNLOCK(cc_if->mutex);
463 uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id)
468 DWC_MUTEX_LOCK(cc_if->mutex);
469 cc = cc_find(cc_if, id);
473 DWC_MUTEX_UNLOCK(cc_if->mutex);
479 uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id)
481 uint8_t *retval = NULL;
484 DWC_MUTEX_LOCK(cc_if->mutex);
485 cc = cc_find(cc_if, id);
489 DWC_MUTEX_UNLOCK(cc_if->mutex);
494 uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id)
496 uint8_t *retval = NULL;
499 DWC_MUTEX_LOCK(cc_if->mutex);
500 cc = cc_find(cc_if, id);
504 DWC_MUTEX_UNLOCK(cc_if->mutex);
509 uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length)
511 uint8_t *retval = NULL;
514 DWC_MUTEX_LOCK(cc_if->mutex);
516 cc = cc_find(cc_if, id);
518 *length = cc->length;
521 DWC_MUTEX_UNLOCK(cc_if->mutex);
526 #endif /* DWC_CCLIB */