source: svn/newcon3bcm2_21bu/nexus/lib/ipc/bipc_server.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 14.2 KB
Line 
1/******************************************************************************
2 *    (c)2011 Broadcom Corporation
3 *
4 * This program is the proprietary software of Broadcom Corporation and/or its licensors,
5 * and may only be used, duplicated, modified or distributed pursuant to the terms and
6 * conditions of a separate, written license agreement executed between you and Broadcom
7 * (an "Authorized License").  Except as set forth in an Authorized License, Broadcom grants
8 * no license (express or implied), right to use, or waiver of any kind with respect to the
9 * Software, and Broadcom expressly reserves all rights in and to the Software and all
10 * intellectual property rights therein.  IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU
11 * HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY
12 * NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE.
13 *
14 * Except as expressly set forth in the Authorized License,
15 *
16 * 1.     This program, including its structure, sequence and organization, constitutes the valuable trade
17 * secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof,
18 * and to use this information only in connection with your use of Broadcom integrated circuit products.
19 
20 * 2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
21 * AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
22 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
23 * THE SOFTWARE.  BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES
24 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE,
25 * LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION
26 * OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF
27 * USE OR PERFORMANCE OF THE SOFTWARE.
28 *
29 * 3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
30 * LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR
31 * EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR
32 * USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF
33 * THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT
34 * ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
35 * LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF
36 * ANY LIMITED REMEDY.
37 *
38 * $brcm_Workfile: bipc_server.c $
39 * $brcm_Revision: 1 $
40 * $brcm_Date: 10/4/11 5:44p $
41 *
42 * Module Description:
43 *
44 * Revision History:
45 *
46 * $brcm_Log: /nexus/lib/ipc/bipc_server.c $
47 *
48 * 1   10/4/11 5:44p vsilyaev
49 * SW7425-1364: Reference applicaion IPC and reference server
50 *
51 *****************************************************************************/
52#include "bstd.h"
53#include "bipc_impl.h"
54
55BDBG_MODULE(bipc_server);
56
57BDBG_OBJECT_ID(bipc_server);
58BDBG_OBJECT_ID(bipc_server_client);
59
60struct bipc_server_client {
61    BDBG_OBJECT(bipc_server_client)
62    BLST_D_ENTRY(bipc_server_client) link;
63    unsigned max_instances;
64    unsigned generation;
65    bipc_server_client_create_settings create_settings;
66    b_ipc_server_instance instances[1]; /* variable length */
67};
68
69void bipc_server_get_default_create_settings(bipc_server_create_settings *create_settings)
70{
71    BDBG_ASSERT(create_settings);
72    BKNI_Memset(create_settings, 0, sizeof(*create_settings));
73    create_settings->max_instances = 4;
74    return;
75}
76
77void bipc_server_get_default_client_create_settings(bipc_server_client_create_settings *create_settings)
78{
79    BDBG_ASSERT(create_settings);
80    BKNI_Memset(create_settings, 0, sizeof(*create_settings));
81    return;
82}
83
84bipc_t bipc_server_create(const bipc_server_create_settings *create_settings)
85{
86    bipc_t ipc;
87    unsigned i;
88    size_t size;
89    BERR_Code rc;
90
91    BDBG_ASSERT(create_settings);
92    BDBG_ASSERT(create_settings->interfaces);
93    BDBG_ASSERT(create_settings->interface_count>0);
94    for(size=0,i=0;i<create_settings->interface_count;i++) {
95        BDBG_ASSERT(create_settings->interfaces[i]);
96        BDBG_ASSERT(create_settings->interfaces[i]->process);
97        size += create_settings->interfaces[i]->interface.buf_size;
98    }
99
100    ipc = BKNI_Malloc(size + sizeof(b_ipc_pkt_in) + sizeof(b_ipc_pkt_out)+sizeof(*ipc));
101    if(!ipc) {(void)BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);goto err_alloc;}
102
103    BDBG_OBJECT_INIT(&ipc->t.server, bipc_server);
104    BLST_D_INIT(&ipc->t.server.clients);
105    ipc->t.server.ipc_buf_size = size;
106    ipc->t.server.create_settings = *create_settings;
107    rc = BKNI_CreateMutex(&ipc->t.server.lock);
108    if(rc!=BERR_SUCCESS) {rc=BERR_TRACE(rc);goto err_mutex;}
109
110    return ipc;
111err_mutex:
112    BKNI_Free(ipc);
113err_alloc:
114    return NULL;
115}
116
117
118static void b_ipc_server_clean_client(bipc_t ipc, bipc_server_client_t client)
119{
120    BSTD_UNUSED(ipc);
121    for(;;) {
122        unsigned i;
123        b_ipc_server_instance *newest_instance = NULL;
124        for(i=0;i<client->max_instances;i++) {
125            b_ipc_server_instance *instance = &client->instances[i];
126            if(instance->interface) {
127                if(newest_instance==NULL || newest_instance->generation < instance->generation) {
128                    newest_instance = instance;
129                }
130            }
131        }
132        if(newest_instance) {
133            size_t send_offset, send_size;
134
135            BDBG_WRN(("bipc_server_destroy:%#lx cleaning up object %#lx(%d,%d):%s(%#lx)",(unsigned long)ipc, (unsigned long)client, client->create_settings.recv_fd, client->create_settings.send_fd, newest_instance->interface->interface.name, (unsigned long)newest_instance->object));
136            newest_instance->interface->process(&newest_instance->object, newest_instance->interface->destructor_entry, ipc->t.server.buf, sizeof(unsigned), &send_offset, &send_size);
137            newest_instance->interface = NULL;
138            newest_instance->object = NULL;
139        } else {
140            break;
141        }
142    }
143    BDBG_OBJECT_DESTROY(client, bipc_server_client);
144    BKNI_Free(client);
145    return;
146}
147
148void bipc_server_destroy(bipc_t ipc)
149{
150    bipc_server_client_t client;
151
152    BDBG_OBJECT_ASSERT(&ipc->t.server, bipc_server);
153    BKNI_AcquireMutex(ipc->t.server.lock);
154    while(NULL!=(client=BLST_D_FIRST(&ipc->t.server.clients))) {
155        BLST_D_REMOVE_HEAD(&ipc->t.server.clients, link);
156        BDBG_WRN(("bipc_server_destroy:%#lx leaked client %#lx(%d,%d)",(unsigned long)ipc, (unsigned long)client, client->create_settings.recv_fd, client->create_settings.send_fd));
157        b_ipc_server_clean_client(ipc, client);
158    }
159    BKNI_ReleaseMutex(ipc->t.server.lock);
160    BKNI_DestroyMutex(ipc->t.server.lock);
161    BDBG_OBJECT_DESTROY(&ipc->t.server, bipc_server);
162    BKNI_Free(ipc);
163    return;
164}
165
166
167static bipc_server_client_t b_ipc_server_find_client(bipc_t ipc, int recv_fd, int send_fd)
168{
169    bipc_server_client_t client;
170    for(client=BLST_D_FIRST(&ipc->t.server.clients);client;client=BLST_D_NEXT(client, link)) {
171        if(client->create_settings.recv_fd==recv_fd && client->create_settings.send_fd==send_fd) {
172            return client;
173        }
174    }
175    return NULL;
176}
177
178bipc_server_client_t bipc_server_client_create(bipc_t ipc, bipc_server_client_create_settings *create_settings)
179{
180    int rc=-1;
181    unsigned i;
182    bipc_server_client_t client;
183
184    BDBG_OBJECT_ASSERT(&ipc->t.server, bipc_server);
185    BDBG_ASSERT(create_settings);
186    BKNI_AcquireMutex(ipc->t.server.lock);
187    client = b_ipc_server_find_client(ipc, create_settings->recv_fd, create_settings->send_fd);
188    if(client) {
189        (void)BERR_TRACE(BERR_INVALID_PARAMETER);
190        BDBG_ERR(("bipc_server_add_client:%lx duplicated client for %d,%d(%#lx)", (unsigned long)ipc, create_settings->recv_fd, create_settings->send_fd, (unsigned long)client));
191        goto done;
192    }
193    client = BKNI_Malloc(sizeof(*client)+ipc->t.server.create_settings.max_instances*sizeof(client->instances));
194    if(client==NULL) { (void)BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY); goto done;}
195    BDBG_OBJECT_INIT(client, bipc_server_client);
196    client->create_settings = *create_settings;
197    client->max_instances = ipc->t.server.create_settings.max_instances;
198    client->generation = 0;
199    for(i=0;i<ipc->t.server.create_settings.max_instances;i++) {
200        client->instances[i].interface = NULL;
201        client->instances[i].object = NULL;
202    }
203    BLST_D_INSERT_HEAD(&ipc->t.server.clients, client, link);
204    rc = 0;
205done:
206    BKNI_ReleaseMutex(ipc->t.server.lock);
207    return client;
208}
209
210void bipc_server_client_destroy(bipc_t ipc, bipc_server_client_t client)
211{
212    BDBG_OBJECT_ASSERT(&ipc->t.server, bipc_server);
213    BDBG_OBJECT_ASSERT(client, bipc_server_client);
214    BKNI_AcquireMutex(ipc->t.server.lock);
215    BLST_D_REMOVE(&ipc->t.server.clients, client, link);
216    b_ipc_server_clean_client(ipc, client);
217    BKNI_ReleaseMutex(ipc->t.server.lock);
218    return;
219}
220
221
222int bipc_server_client_process(bipc_t ipc, bipc_server_client_t client)
223{
224    int result = 0;
225    b_ipc_pkt_in *in;
226    b_ipc_pkt_out out;
227    int rc;
228    size_t payload;
229    const bipc_server_descriptor *descriptor=NULL;
230    b_ipc_server_instance *instance=NULL;
231    void *process_object;
232    size_t send_offset;
233    size_t send_size;
234
235    BDBG_OBJECT_ASSERT(&ipc->t.server, bipc_server);
236    BDBG_OBJECT_ASSERT(client, bipc_server_client);
237
238    BKNI_AcquireMutex(ipc->t.server.lock);
239    in = (void *)ipc->t.server.buf;
240
241    rc = b_safe_read(client->create_settings.recv_fd, in, sizeof(*in));
242    if(rc==0) {
243        goto done;
244    } else if (rc==-(int)BERR_END_OF_FILE) {
245        goto error;
246    } else if(rc!=sizeof(*in)) { 
247        (void)BERR_TRACE(BERR_NOT_SUPPORTED); goto error;
248    }
249
250    if(in->pkt_size >= ipc->t.server.ipc_buf_size || in->pkt_size<sizeof(*in)) { (void)BERR_TRACE(BERR_NOT_SUPPORTED); goto error; }
251    payload = in->pkt_size - sizeof(*in);
252    rc = b_safe_read(client->create_settings.recv_fd, ipc->t.server.buf+sizeof(*in), payload);
253    if(rc!=(int)payload) { (void)BERR_TRACE(BERR_NOT_SUPPORTED); goto error; }
254    if(in->instance==BIPC_INSTANCE_ID_NEW) {
255        unsigned i;
256        bipc_interface_descriptor *id = (void *)(ipc->t.server.buf+sizeof(*in));
257
258        if(payload<sizeof(bipc_interface_descriptor)) { (void)BERR_TRACE(BERR_NOT_SUPPORTED);goto error;}
259        for(i=0;i<ipc->t.server.create_settings.interface_count;i++) {
260            descriptor = ipc->t.server.create_settings.interfaces[i];
261            if(BKNI_Memcmp(descriptor->interface.name, id->name, sizeof(id->name))==0) {
262                if(BKNI_Memcmp(descriptor->interface.sha1, id->sha1, sizeof(id->sha1))!=0) {
263                    BDBG_WRN(("bipc_server_process:%#lx mismatched protocol for interface %s client:%#lx", (unsigned long)ipc, descriptor->interface.name, (unsigned long)client));
264                    (void)BERR_TRACE(BERR_NOT_SUPPORTED);
265                    goto error;
266                }
267                break;
268            }
269            descriptor = NULL;
270        }
271        if(descriptor == NULL) {
272            BDBG_WRN(("bipc_server_process:%#lx unknown interface client:%#lx", (unsigned long)ipc, (unsigned long)client));
273            (void)BERR_TRACE(BERR_NOT_SUPPORTED);
274            BDBG_ASSERT(0);
275            goto error;
276        }
277        if(in->method != descriptor->constructor_entry) {
278            BDBG_WRN(("bipc_server_process:%#lx %s invalid constructor %u(%u) client:%#lx", (unsigned long)ipc, descriptor->interface.name, in->method, descriptor->constructor_entry, (unsigned long)client));
279            (void)BERR_TRACE(BERR_NOT_SUPPORTED);
280            goto error;
281        }
282        for(i=0;i<client->max_instances;i++) {
283            if(client->instances[i].interface==NULL) {
284                instance = &client->instances[i];
285                send_offset = i; /* used as object ID communicated back to the client */
286                break;
287            }
288        }
289        if(instance==NULL) {
290            BDBG_WRN(("bipc_server_process:%#lx %s not enough space client:%lx", (unsigned long)ipc, descriptor->interface.name, (unsigned long)client));
291            (void)BERR_TRACE(BERR_NOT_SUPPORTED);
292            goto error;
293        }
294        process_object = client->create_settings.ipc_context;
295    } else {
296        if(in->instance >= client->max_instances) {
297            BDBG_WRN(("bipc_server_process:%#lx invalid instance %u:%u", (unsigned long)ipc, in->instance, client->max_instances));
298            (void)BERR_TRACE(BERR_NOT_SUPPORTED);
299            goto error;
300        }
301        instance = &client->instances[in->instance];
302        process_object = instance->object;
303        if(instance == NULL) {
304            BDBG_WRN(("bipc_server_process:%#lx unknown instance %u", (unsigned long)ipc, in->instance));
305            (void)BERR_TRACE(BERR_NOT_SUPPORTED);
306            goto error;
307        }
308        descriptor = instance->interface;
309        if(in->method == descriptor->constructor_entry) {
310            BDBG_WRN(("bipc_server_process:%#lx invalid constructor call %s client:%#lx", (unsigned long)ipc, descriptor->interface.name, (unsigned long)client));
311            (void)BERR_TRACE(BERR_NOT_SUPPORTED);
312            goto error;
313        }
314    }
315    BDBG_ASSERT(descriptor);
316    BDBG_ASSERT(instance);
317    rc  =  descriptor->process(&process_object, in->method, ipc->t.server.buf+sizeof(*in),  payload, &send_offset, &send_size);
318    if(rc!=0) {
319        BDBG_WRN(("bipc_server_process:%#lx error executing method %s:%u client:%#lx", (unsigned long)ipc, descriptor->interface.name, in->method, (unsigned long)client));
320        (void)BERR_TRACE(BERR_NOT_SUPPORTED);
321        goto error;
322    }
323    out.pkt_size = send_size + sizeof(out);
324    rc =  b_safe_write(client->create_settings.send_fd, &out, sizeof(out));
325    if(rc!=sizeof(out)) { (void)BERR_TRACE(BERR_NOT_SUPPORTED); goto error; }
326    if(in->method == descriptor->constructor_entry) {
327        client->generation++;
328        instance->generation = client->generation;
329        instance->interface = descriptor;
330        instance->object = process_object;
331    } else if(in->method == descriptor->destructor_entry) {
332        instance->interface = NULL;
333        instance->object = NULL;
334    }
335    if(send_size) {
336        rc = b_safe_write(client->create_settings.send_fd, ipc->t.server.buf + sizeof(*in) + send_offset , send_size);
337        if(rc!=(int)send_size) { (void)BERR_TRACE(BERR_NOT_SUPPORTED); goto error; }
338    }
339done:
340    BKNI_ReleaseMutex(ipc->t.server.lock);
341    return result;
342error:
343    result = -1;
344    goto done;
345}
346
Note: See TracBrowser for help on using the repository browser.