source: mainline/uspace/lib/c/generic/devman.c@ f401312

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f401312 was 6610565b, checked in by Vojtech Horky <vojtechhorky@…>, 14 years ago

Merge mainline changes

  • Property mode set to 100644
File size: 7.7 KB
Line 
1/*
2 * Copyright (c) 2007 Josef Cejka
3 * Copyright (c) 2009 Jiri Svoboda
4 * Copyright (c) 2010 Lenka Trochtova
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * - The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 /** @addtogroup libc
32 * @{
33 */
34/** @file
35 */
36
37#include <str.h>
38#include <stdio.h>
39#include <ipc/ipc.h>
40#include <ipc/services.h>
41#include <ipc/devman.h>
42#include <devman.h>
43#include <async.h>
44#include <fibril_synch.h>
45#include <errno.h>
46#include <malloc.h>
47#include <bool.h>
48#include <adt/list.h>
49
50static int devman_phone_driver = -1;
51static int devman_phone_client = -1;
52
53static FIBRIL_MUTEX_INITIALIZE(devman_phone_mutex);
54
55int devman_get_phone(devman_interface_t iface, unsigned int flags)
56{
57 switch (iface) {
58 case DEVMAN_DRIVER:
59 fibril_mutex_lock(&devman_phone_mutex);
60 if (devman_phone_driver >= 0) {
61 fibril_mutex_unlock(&devman_phone_mutex);
62 return devman_phone_driver;
63 }
64
65 if (flags & IPC_FLAG_BLOCKING)
66 devman_phone_driver = async_connect_me_to_blocking(
67 PHONE_NS, SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
68 else
69 devman_phone_driver = async_connect_me_to(PHONE_NS,
70 SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
71
72 fibril_mutex_unlock(&devman_phone_mutex);
73 return devman_phone_driver;
74 case DEVMAN_CLIENT:
75 fibril_mutex_lock(&devman_phone_mutex);
76 if (devman_phone_client >= 0) {
77 fibril_mutex_unlock(&devman_phone_mutex);
78 return devman_phone_client;
79 }
80
81 if (flags & IPC_FLAG_BLOCKING)
82 devman_phone_client = async_connect_me_to_blocking(
83 PHONE_NS, SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
84 else
85 devman_phone_client = async_connect_me_to(PHONE_NS,
86 SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
87
88 fibril_mutex_unlock(&devman_phone_mutex);
89 return devman_phone_client;
90 default:
91 return -1;
92 }
93}
94
95/** Register running driver with device manager. */
96int devman_driver_register(const char *name, async_client_conn_t conn)
97{
98 int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
99
100 if (phone < 0)
101 return phone;
102
103 async_serialize_start();
104
105 ipc_call_t answer;
106 aid_t req = async_send_2(phone, DEVMAN_DRIVER_REGISTER, 0, 0, &answer);
107
108 sysarg_t retval = async_data_write_start(phone, name, str_size(name));
109 if (retval != EOK) {
110 async_wait_for(req, NULL);
111 async_serialize_end();
112 return -1;
113 }
114
115 async_set_client_connection(conn);
116
117 sysarg_t callback_phonehash;
118 ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash);
119 async_wait_for(req, &retval);
120
121 async_serialize_end();
122
123 return retval;
124}
125
126static int devman_send_match_id(int phone, match_id_t *match_id) \
127{
128 ipc_call_t answer;
129 aid_t req = async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score, &answer);
130 int retval = async_data_write_start(phone, match_id->id, str_size(match_id->id));
131 async_wait_for(req, NULL);
132 return retval;
133}
134
135
136static int devman_send_match_ids(int phone, match_id_list_t *match_ids)
137{
138 link_t *link = match_ids->ids.next;
139 match_id_t *match_id = NULL;
140 int ret = EOK;
141
142 while (link != &match_ids->ids) {
143 match_id = list_get_instance(link, match_id_t, link);
144 if (EOK != (ret = devman_send_match_id(phone, match_id)))
145 {
146 printf("Driver failed to send match id, error number = %d\n", ret);
147 return ret;
148 }
149 link = link->next;
150 }
151 return ret;
152}
153
154int devman_child_device_register(
155 const char *name, match_id_list_t *match_ids, devman_handle_t parent_handle, devman_handle_t *handle)
156{
157 int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
158
159 if (phone < 0)
160 return phone;
161
162 async_serialize_start();
163
164 int match_count = list_count(&match_ids->ids);
165 ipc_call_t answer;
166 aid_t req = async_send_2(phone, DEVMAN_ADD_CHILD_DEVICE, parent_handle, match_count, &answer);
167
168 sysarg_t retval = async_data_write_start(phone, name, str_size(name));
169 if (retval != EOK) {
170 async_wait_for(req, NULL);
171 async_serialize_end();
172 return retval;
173 }
174
175 devman_send_match_ids(phone, match_ids);
176
177 async_wait_for(req, &retval);
178
179 async_serialize_end();
180
181 if (retval != EOK) {
182 if (handle != NULL) {
183 *handle = -1;
184 }
185 return retval;
186 }
187
188 if (handle != NULL)
189 *handle = (int) IPC_GET_ARG1(answer);
190
191 return retval;
192}
193
194int devman_add_device_to_class(devman_handle_t devman_handle, const char *class_name)
195{
196 int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
197
198 if (phone < 0)
199 return phone;
200
201 async_serialize_start();
202 ipc_call_t answer;
203 aid_t req = async_send_1(phone, DEVMAN_ADD_DEVICE_TO_CLASS, devman_handle, &answer);
204
205 sysarg_t retval = async_data_write_start(phone, class_name, str_size(class_name));
206 if (retval != EOK) {
207 async_wait_for(req, NULL);
208 async_serialize_end();
209 return retval;
210 }
211
212 async_wait_for(req, &retval);
213 async_serialize_end();
214
215 return retval;
216}
217
218void devman_hangup_phone(devman_interface_t iface)
219{
220 switch (iface) {
221 case DEVMAN_DRIVER:
222 if (devman_phone_driver >= 0) {
223 ipc_hangup(devman_phone_driver);
224 devman_phone_driver = -1;
225 }
226 break;
227 case DEVMAN_CLIENT:
228 if (devman_phone_client >= 0) {
229 ipc_hangup(devman_phone_client);
230 devman_phone_client = -1;
231 }
232 break;
233 default:
234 break;
235 }
236}
237
238int devman_device_connect(devman_handle_t handle, unsigned int flags)
239{
240 int phone;
241
242 if (flags & IPC_FLAG_BLOCKING) {
243 phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAN,
244 DEVMAN_CONNECT_TO_DEVICE, handle);
245 } else {
246 phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAN,
247 DEVMAN_CONNECT_TO_DEVICE, handle);
248 }
249
250 return phone;
251}
252
253int devman_parent_device_connect(devman_handle_t handle, unsigned int flags)
254{
255 int phone;
256
257 if (flags & IPC_FLAG_BLOCKING) {
258 phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAN,
259 DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
260 } else {
261 phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAN,
262 DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
263 }
264
265 return phone;
266}
267
268int devman_device_get_handle(const char *pathname, devman_handle_t *handle, unsigned int flags)
269{
270 int phone = devman_get_phone(DEVMAN_CLIENT, flags);
271
272 if (phone < 0)
273 return phone;
274
275 async_serialize_start();
276
277 ipc_call_t answer;
278 aid_t req = async_send_2(phone, DEVMAN_DEVICE_GET_HANDLE, flags, 0,
279 &answer);
280
281 sysarg_t retval = async_data_write_start(phone, pathname, str_size(pathname));
282 if (retval != EOK) {
283 async_wait_for(req, NULL);
284 async_serialize_end();
285 return retval;
286 }
287
288 async_wait_for(req, &retval);
289
290 async_serialize_end();
291
292 if (retval != EOK) {
293 if (handle != NULL)
294 *handle = (devman_handle_t) -1;
295 return retval;
296 }
297
298 if (handle != NULL)
299 *handle = (devman_handle_t) IPC_GET_ARG1(answer);
300
301 return retval;
302}
303
304
305/** @}
306 */
Note: See TracBrowser for help on using the repository browser.