1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010, The Linux Foundation. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6     * Redistributions of source code must retain the above copyright
7       notice, this list of conditions and the following disclaimer.
8     * Redistributions in binary form must reproduce the above copyright
9       notice, this list of conditions and the following disclaimer in the
10       documentation and/or other materials provided with the distribution.
11     * Neither the name of The Linux Foundation nor
12       the names of its contributors may be used to endorse or promote
13       products derived from this software without specific prior written
14       permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include <fcntl.h>
33 #include <errno.h>
34 
35 #include <aenc_svr.h>
36 
37 /**
38  @brief This function processes posted messages
39 
40  Once thread is being spawned, this function is run to
41  start processing commands posted by client
42 
43  @param info pointer to context
44 
45  */
omx_aac_msg(void * info)46 void *omx_aac_msg(void *info)
47 {
48     struct aac_ipc_info *aac_info = (struct aac_ipc_info*)info;
49     unsigned char id;
50     ssize_t n;
51 
52     DEBUG_DETAIL("\n%s: message thread start\n", __FUNCTION__);
53     while (!aac_info->dead)
54     {
55         n = read(aac_info->pipe_in, &id, 1);
56         if (0 == n) break;
57         if (1 == n)
58         {
59           DEBUG_DETAIL("\n%s-->pipe_in=%d pipe_out=%d\n",
60                                                aac_info->thread_name,
61                                                aac_info->pipe_in,
62                                                aac_info->pipe_out);
63 
64             aac_info->process_msg_cb(aac_info->client_data, id);
65         }
66         if ((n < 0) && (errno != EINTR)) break;
67     }
68     DEBUG_DETAIL("%s: message thread stop\n", __FUNCTION__);
69 
70     return 0;
71 }
72 
omx_aac_events(void * info)73 void *omx_aac_events(void *info)
74 {
75     struct aac_ipc_info *aac_info = (struct aac_ipc_info*)info;
76     unsigned char id = 0;
77 
78     DEBUG_DETAIL("%s: message thread start\n", aac_info->thread_name);
79     aac_info->process_msg_cb(aac_info->client_data, id);
80     DEBUG_DETAIL("%s: message thread stop\n", aac_info->thread_name);
81     return 0;
82 }
83 
84 /**
85  @brief This function starts command server
86 
87  @param cb pointer to callback function from the client
88  @param client_data reference client wants to get back
89   through callback
90  @return handle to msging thread
91  */
omx_aac_thread_create(message_func cb,void * client_data,char * th_name)92 struct aac_ipc_info *omx_aac_thread_create(
93                                     message_func cb,
94                                     void* client_data,
95                                     char* th_name)
96 {
97     int r;
98     int fds[2];
99     struct aac_ipc_info *aac_info;
100 
101     aac_info = calloc(1, sizeof(struct aac_ipc_info));
102     if (!aac_info)
103     {
104         return 0;
105     }
106 
107     aac_info->client_data = client_data;
108     aac_info->process_msg_cb = cb;
109     strlcpy(aac_info->thread_name, th_name, sizeof(aac_info->thread_name));
110 
111     if (pipe(fds))
112     {
113         DEBUG_PRINT_ERROR("\n%s: pipe creation failed\n", __FUNCTION__);
114         goto fail_pipe;
115     }
116 
117     aac_info->pipe_in = fds[0];
118     aac_info->pipe_out = fds[1];
119 
120     r = pthread_create(&aac_info->thr, 0, omx_aac_msg, aac_info);
121     if (r < 0) goto fail_thread;
122 
123     DEBUG_DETAIL("Created thread for %s \n", aac_info->thread_name);
124     return aac_info;
125 
126 
127 fail_thread:
128     close(aac_info->pipe_in);
129     close(aac_info->pipe_out);
130 
131 fail_pipe:
132     free(aac_info);
133 
134     return 0;
135 }
136 
137 /**
138  *  @brief This function starts command server
139  *
140  *   @param cb pointer to callback function from the client
141  *    @param client_data reference client wants to get back
142  *      through callback
143  *       @return handle to msging thread
144  *        */
omx_aac_event_thread_create(message_func cb,void * client_data,char * th_name)145 struct aac_ipc_info *omx_aac_event_thread_create(
146                                     message_func cb,
147                                     void* client_data,
148                                     char* th_name)
149 {
150     int r;
151     int fds[2];
152     struct aac_ipc_info *aac_info;
153 
154     aac_info = calloc(1, sizeof(struct aac_ipc_info));
155     if (!aac_info)
156     {
157         return 0;
158     }
159 
160     aac_info->client_data = client_data;
161     aac_info->process_msg_cb = cb;
162     strlcpy(aac_info->thread_name, th_name, sizeof(aac_info->thread_name));
163 
164     if (pipe(fds))
165     {
166         DEBUG_PRINT("\n%s: pipe creation failed\n", __FUNCTION__);
167         goto fail_pipe;
168     }
169 
170     aac_info->pipe_in = fds[0];
171     aac_info->pipe_out = fds[1];
172 
173     r = pthread_create(&aac_info->thr, 0, omx_aac_events, aac_info);
174     if (r < 0) goto fail_thread;
175 
176     DEBUG_DETAIL("Created thread for %s \n", aac_info->thread_name);
177     return aac_info;
178 
179 
180 fail_thread:
181     close(aac_info->pipe_in);
182     close(aac_info->pipe_out);
183 
184 fail_pipe:
185     free(aac_info);
186 
187     return 0;
188 }
189 
omx_aac_thread_stop(struct aac_ipc_info * aac_info)190 void omx_aac_thread_stop(struct aac_ipc_info *aac_info) {
191     DEBUG_DETAIL("%s stop server\n", __FUNCTION__);
192     close(aac_info->pipe_in);
193     close(aac_info->pipe_out);
194     pthread_join(aac_info->thr,NULL);
195     aac_info->pipe_out = -1;
196     aac_info->pipe_in = -1;
197     DEBUG_DETAIL("%s: message thread close fds%d %d\n", aac_info->thread_name,
198         aac_info->pipe_in,aac_info->pipe_out);
199     free(aac_info);
200 }
201 
omx_aac_post_msg(struct aac_ipc_info * aac_info,unsigned char id)202 void omx_aac_post_msg(struct aac_ipc_info *aac_info, unsigned char id) {
203     DEBUG_DETAIL("\n%s id=%d\n", __FUNCTION__,id);
204 
205     write(aac_info->pipe_out, &id, 1);
206 }
207