00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00037 #include <str.h>
00038 #include <stdio.h>
00039 #include <ipc/services.h>
00040 #include <ipc/devman.h>
00041 #include <devman.h>
00042 #include <async.h>
00043 #include <fibril_synch.h>
00044 #include <errno.h>
00045 #include <malloc.h>
00046 #include <bool.h>
00047 #include <adt/list.h>
00048
00049 static int devman_phone_driver = -1;
00050 static int devman_phone_client = -1;
00051
00052 static FIBRIL_MUTEX_INITIALIZE(devman_phone_mutex);
00053
00054 int devman_get_phone(devman_interface_t iface, unsigned int flags)
00055 {
00056 switch (iface) {
00057 case DEVMAN_DRIVER:
00058 fibril_mutex_lock(&devman_phone_mutex);
00059 if (devman_phone_driver >= 0) {
00060 fibril_mutex_unlock(&devman_phone_mutex);
00061 return devman_phone_driver;
00062 }
00063
00064 if (flags & IPC_FLAG_BLOCKING)
00065 devman_phone_driver = async_connect_me_to_blocking(
00066 PHONE_NS, SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
00067 else
00068 devman_phone_driver = async_connect_me_to(PHONE_NS,
00069 SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
00070
00071 fibril_mutex_unlock(&devman_phone_mutex);
00072 return devman_phone_driver;
00073 case DEVMAN_CLIENT:
00074 fibril_mutex_lock(&devman_phone_mutex);
00075 if (devman_phone_client >= 0) {
00076 fibril_mutex_unlock(&devman_phone_mutex);
00077 return devman_phone_client;
00078 }
00079
00080 if (flags & IPC_FLAG_BLOCKING) {
00081 devman_phone_client = async_connect_me_to_blocking(
00082 PHONE_NS, SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
00083 } else {
00084 devman_phone_client = async_connect_me_to(PHONE_NS,
00085 SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
00086 }
00087
00088 fibril_mutex_unlock(&devman_phone_mutex);
00089 return devman_phone_client;
00090 default:
00091 return -1;
00092 }
00093 }
00094
00096 int devman_driver_register(const char *name, async_client_conn_t conn)
00097 {
00098 int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
00099
00100 if (phone < 0)
00101 return phone;
00102
00103 async_serialize_start();
00104
00105 ipc_call_t answer;
00106 aid_t req = async_send_2(phone, DEVMAN_DRIVER_REGISTER, 0, 0, &answer);
00107
00108 sysarg_t retval = async_data_write_start(phone, name, str_size(name));
00109 if (retval != EOK) {
00110 async_wait_for(req, NULL);
00111 async_serialize_end();
00112 return -1;
00113 }
00114
00115 async_set_client_connection(conn);
00116
00117 async_connect_to_me(phone, 0, 0, 0, NULL);
00118 async_wait_for(req, &retval);
00119
00120 async_serialize_end();
00121
00122 return retval;
00123 }
00124
00125 static int devman_send_match_id(int phone, match_id_t *match_id)
00126 {
00127 ipc_call_t answer;
00128
00129 aid_t req = async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score,
00130 &answer);
00131 int retval = async_data_write_start(phone, match_id->id,
00132 str_size(match_id->id));
00133
00134 async_wait_for(req, NULL);
00135 return retval;
00136 }
00137
00138
00139 static int devman_send_match_ids(int phone, match_id_list_t *match_ids)
00140 {
00141 link_t *link = match_ids->ids.next;
00142 match_id_t *match_id = NULL;
00143 int ret = EOK;
00144
00145 while (link != &match_ids->ids) {
00146 match_id = list_get_instance(link, match_id_t, link);
00147 ret = devman_send_match_id(phone, match_id);
00148 if (ret != EOK) {
00149 return ret;
00150 }
00151
00152 link = link->next;
00153 }
00154
00155 return ret;
00156 }
00157
00171 int devman_add_function(const char *name, fun_type_t ftype,
00172 match_id_list_t *match_ids, devman_handle_t devh, devman_handle_t *funh)
00173 {
00174 int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
00175 int fun_handle;
00176
00177 if (phone < 0)
00178 return phone;
00179
00180 async_serialize_start();
00181
00182 int match_count = list_count(&match_ids->ids);
00183 ipc_call_t answer;
00184
00185 aid_t req = async_send_3(phone, DEVMAN_ADD_FUNCTION, (sysarg_t) ftype,
00186 devh, match_count, &answer);
00187
00188 sysarg_t retval = async_data_write_start(phone, name, str_size(name));
00189 if (retval != EOK) {
00190 async_wait_for(req, NULL);
00191 async_serialize_end();
00192 return retval;
00193 }
00194
00195 int match_ids_rc = devman_send_match_ids(phone, match_ids);
00196
00197 async_wait_for(req, &retval);
00198
00199 async_serialize_end();
00200
00201
00202 if ((match_ids_rc != EOK) && (retval == EOK)) {
00203 retval = match_ids_rc;
00204 }
00205
00206 if (retval == EOK)
00207 fun_handle = (int) IPC_GET_ARG1(answer);
00208 else
00209 fun_handle = -1;
00210
00211 *funh = fun_handle;
00212
00213 return retval;
00214 }
00215
00216 int devman_add_device_to_class(devman_handle_t devman_handle,
00217 const char *class_name)
00218 {
00219 int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
00220
00221 if (phone < 0)
00222 return phone;
00223
00224 async_serialize_start();
00225 ipc_call_t answer;
00226 aid_t req = async_send_1(phone, DEVMAN_ADD_DEVICE_TO_CLASS,
00227 devman_handle, &answer);
00228
00229 sysarg_t retval = async_data_write_start(phone, class_name,
00230 str_size(class_name));
00231 if (retval != EOK) {
00232 async_wait_for(req, NULL);
00233 async_serialize_end();
00234 return retval;
00235 }
00236
00237 async_wait_for(req, &retval);
00238 async_serialize_end();
00239
00240 return retval;
00241 }
00242
00243 void devman_hangup_phone(devman_interface_t iface)
00244 {
00245 switch (iface) {
00246 case DEVMAN_DRIVER:
00247 if (devman_phone_driver >= 0) {
00248 async_hangup(devman_phone_driver);
00249 devman_phone_driver = -1;
00250 }
00251 break;
00252 case DEVMAN_CLIENT:
00253 if (devman_phone_client >= 0) {
00254 async_hangup(devman_phone_client);
00255 devman_phone_client = -1;
00256 }
00257 break;
00258 default:
00259 break;
00260 }
00261 }
00262
00263 int devman_device_connect(devman_handle_t handle, unsigned int flags)
00264 {
00265 int phone;
00266
00267 if (flags & IPC_FLAG_BLOCKING) {
00268 phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAN,
00269 DEVMAN_CONNECT_TO_DEVICE, handle);
00270 } else {
00271 phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAN,
00272 DEVMAN_CONNECT_TO_DEVICE, handle);
00273 }
00274
00275 return phone;
00276 }
00277
00278 int devman_parent_device_connect(devman_handle_t handle, unsigned int flags)
00279 {
00280 int phone;
00281
00282 if (flags & IPC_FLAG_BLOCKING) {
00283 phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAN,
00284 DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
00285 } else {
00286 phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAN,
00287 DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
00288 }
00289
00290 return phone;
00291 }
00292
00293 int devman_device_get_handle(const char *pathname, devman_handle_t *handle,
00294 unsigned int flags)
00295 {
00296 int phone = devman_get_phone(DEVMAN_CLIENT, flags);
00297
00298 if (phone < 0)
00299 return phone;
00300
00301 async_serialize_start();
00302
00303 ipc_call_t answer;
00304 aid_t req = async_send_2(phone, DEVMAN_DEVICE_GET_HANDLE, flags, 0,
00305 &answer);
00306
00307 sysarg_t retval = async_data_write_start(phone, pathname,
00308 str_size(pathname));
00309 if (retval != EOK) {
00310 async_wait_for(req, NULL);
00311 async_serialize_end();
00312 return retval;
00313 }
00314
00315 async_wait_for(req, &retval);
00316
00317 async_serialize_end();
00318
00319 if (retval != EOK) {
00320 if (handle != NULL)
00321 *handle = (devman_handle_t) -1;
00322 return retval;
00323 }
00324
00325 if (handle != NULL)
00326 *handle = (devman_handle_t) IPC_GET_ARG1(answer);
00327
00328 return retval;
00329 }
00330
00331 int devman_device_get_handle_by_class(const char *classname,
00332 const char *devname, devman_handle_t *handle, unsigned int flags)
00333 {
00334 int phone = devman_get_phone(DEVMAN_CLIENT, flags);
00335
00336 if (phone < 0)
00337 return phone;
00338
00339 async_serialize_start();
00340
00341 ipc_call_t answer;
00342 aid_t req = async_send_1(phone, DEVMAN_DEVICE_GET_HANDLE_BY_CLASS,
00343 flags, &answer);
00344
00345 sysarg_t retval = async_data_write_start(phone, classname,
00346 str_size(classname));
00347 if (retval != EOK) {
00348 async_wait_for(req, NULL);
00349 async_serialize_end();
00350 return retval;
00351 }
00352 retval = async_data_write_start(phone, devname,
00353 str_size(devname));
00354 if (retval != EOK) {
00355 async_wait_for(req, NULL);
00356 async_serialize_end();
00357 return retval;
00358 }
00359
00360 async_wait_for(req, &retval);
00361
00362 async_serialize_end();
00363
00364 if (retval != EOK) {
00365 if (handle != NULL)
00366 *handle = (devman_handle_t) -1;
00367 return retval;
00368 }
00369
00370 if (handle != NULL)
00371 *handle = (devman_handle_t) IPC_GET_ARG1(answer);
00372
00373 return retval;
00374 }
00375
00376 int devman_get_device_path(devman_handle_t handle, char *path, size_t path_size)
00377 {
00378 int phone = devman_get_phone(DEVMAN_CLIENT, 0);
00379
00380 if (phone < 0)
00381 return phone;
00382
00383 async_serialize_start();
00384
00385 ipc_call_t answer;
00386 aid_t req = async_send_1(phone, DEVMAN_DEVICE_GET_DEVICE_PATH,
00387 handle, &answer);
00388
00389 ipc_call_t data_request_call;
00390 aid_t data_request = async_data_read(phone, path, path_size,
00391 &data_request_call);
00392 if (data_request == 0) {
00393 async_wait_for(req, NULL);
00394 async_serialize_end();
00395 return ENOMEM;
00396 }
00397
00398 sysarg_t data_request_rc;
00399 sysarg_t opening_request_rc;
00400 async_wait_for(data_request, &data_request_rc);
00401 async_wait_for(req, &opening_request_rc);
00402
00403 async_serialize_end();
00404
00405 if (data_request_rc != EOK) {
00406
00407 if (opening_request_rc != EOK) {
00408 return (int) opening_request_rc;
00409 } else {
00410 return (int) data_request_rc;
00411 }
00412 }
00413 if (opening_request_rc != EOK) {
00414 return (int) opening_request_rc;
00415 }
00416
00417
00418 path[path_size - 1] = 0;
00419
00420 size_t transferred_size = IPC_GET_ARG2(data_request_call);
00421
00422 if (transferred_size >= path_size) {
00423 return ELIMIT;
00424 }
00425
00426
00427 path[transferred_size] = 0;
00428
00429 return EOK;
00430 }
00431
00432