devmap.c

00001 /*
00002  * Copyright (c) 2007 Josef Cejka
00003  * Copyright (c) 2009 Jiri Svoboda
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  * - Redistributions of source code must retain the above copyright
00011  *   notice, this list of conditions and the following disclaimer.
00012  * - Redistributions in binary form must reproduce the above copyright
00013  *   notice, this list of conditions and the following disclaimer in the
00014  *   documentation and/or other materials provided with the distribution.
00015  * - The name of the author may not be used to endorse or promote products
00016  *   derived from this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00019  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00020  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00021  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00023  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00024  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00025  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00026  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00027  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include <str.h>
00031 #include <ipc/services.h>
00032 #include <ipc/ns.h>
00033 #include <ipc/devmap.h>
00034 #include <devmap.h>
00035 #include <async.h>
00036 #include <errno.h>
00037 #include <malloc.h>
00038 #include <bool.h>
00039 
00040 static int devmap_phone_driver = -1;
00041 static int devmap_phone_client = -1;
00042 
00044 int devmap_get_phone(devmap_interface_t iface, unsigned int flags)
00045 {
00046         switch (iface) {
00047         case DEVMAP_DRIVER:
00048                 if (devmap_phone_driver >= 0)
00049                         return devmap_phone_driver;
00050                 
00051                 if (flags & IPC_FLAG_BLOCKING)
00052                         devmap_phone_driver = service_connect_blocking(SERVICE_DEVMAP,
00053                             DEVMAP_DRIVER, 0);
00054                 else
00055                         devmap_phone_driver = service_connect(SERVICE_DEVMAP,
00056                             DEVMAP_DRIVER, 0);
00057                 
00058                 return devmap_phone_driver;
00059         case DEVMAP_CLIENT:
00060                 if (devmap_phone_client >= 0)
00061                         return devmap_phone_client;
00062                 
00063                 if (flags & IPC_FLAG_BLOCKING)
00064                         devmap_phone_client = service_connect_blocking(SERVICE_DEVMAP,
00065                             DEVMAP_CLIENT, 0);
00066                 else
00067                         devmap_phone_client = service_connect(SERVICE_DEVMAP,
00068                             DEVMAP_CLIENT, 0);
00069                 
00070                 return devmap_phone_client;
00071         default:
00072                 return -1;
00073         }
00074 }
00075 
00076 void devmap_hangup_phone(devmap_interface_t iface)
00077 {
00078         switch (iface) {
00079         case DEVMAP_DRIVER:
00080                 if (devmap_phone_driver >= 0) {
00081                         async_hangup(devmap_phone_driver);
00082                         devmap_phone_driver = -1;
00083                 }
00084                 break;
00085         case DEVMAP_CLIENT:
00086                 if (devmap_phone_client >= 0) {
00087                         async_hangup(devmap_phone_client);
00088                         devmap_phone_client = -1;
00089                 }
00090                 break;
00091         default:
00092                 break;
00093         }
00094 }
00095 
00097 int devmap_driver_register(const char *name, async_client_conn_t conn)
00098 {
00099         int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
00100         
00101         if (phone < 0)
00102                 return phone;
00103         
00104         async_serialize_start();
00105         
00106         ipc_call_t answer;
00107         aid_t req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
00108         
00109         sysarg_t retval = async_data_write_start(phone, name, str_size(name));
00110         if (retval != EOK) {
00111                 async_wait_for(req, NULL);
00112                 async_serialize_end();
00113                 return -1;
00114         }
00115         
00116         async_set_client_connection(conn);
00117         
00118         async_connect_to_me(phone, 0, 0, 0, NULL);
00119         async_wait_for(req, &retval);
00120         
00121         async_serialize_end();
00122         
00123         return retval;
00124 }
00125 
00139 int devmap_device_register_with_iface(const char *fqdn,
00140     devmap_handle_t *handle, sysarg_t interface)
00141 {
00142         int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
00143         
00144         if (phone < 0)
00145                 return phone;
00146         
00147         async_serialize_start();
00148         
00149         ipc_call_t answer;
00150         aid_t req = async_send_2(phone, DEVMAP_DEVICE_REGISTER, interface, 0,
00151             &answer);
00152         
00153         sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
00154         if (retval != EOK) {
00155                 async_wait_for(req, NULL);
00156                 async_serialize_end();
00157                 return retval;
00158         }
00159         
00160         async_wait_for(req, &retval);
00161         
00162         async_serialize_end();
00163         
00164         if (retval != EOK) {
00165                 if (handle != NULL)
00166                         *handle = -1;
00167                 return retval;
00168         }
00169         
00170         if (handle != NULL)
00171                 *handle = (devmap_handle_t) IPC_GET_ARG1(answer);
00172         
00173         return retval;
00174 }
00175 
00182 int devmap_device_register(const char *fqdn, devmap_handle_t *handle)
00183 {
00184         return devmap_device_register_with_iface(fqdn, handle, 0);
00185 }
00186 
00187 
00188 int devmap_device_get_handle(const char *fqdn, devmap_handle_t *handle, unsigned int flags)
00189 {
00190         int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
00191         
00192         if (phone < 0)
00193                 return phone;
00194         
00195         async_serialize_start();
00196         
00197         ipc_call_t answer;
00198         aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
00199             &answer);
00200         
00201         sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
00202         if (retval != EOK) {
00203                 async_wait_for(req, NULL);
00204                 async_serialize_end();
00205                 return retval;
00206         }
00207         
00208         async_wait_for(req, &retval);
00209         
00210         async_serialize_end();
00211         
00212         if (retval != EOK) {
00213                 if (handle != NULL)
00214                         *handle = (devmap_handle_t) -1;
00215                 return retval;
00216         }
00217         
00218         if (handle != NULL)
00219                 *handle = (devmap_handle_t) IPC_GET_ARG1(answer);
00220         
00221         return retval;
00222 }
00223 
00224 int devmap_namespace_get_handle(const char *name, devmap_handle_t *handle, unsigned int flags)
00225 {
00226         int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
00227         
00228         if (phone < 0)
00229                 return phone;
00230         
00231         async_serialize_start();
00232         
00233         ipc_call_t answer;
00234         aid_t req = async_send_2(phone, DEVMAP_NAMESPACE_GET_HANDLE, flags, 0,
00235             &answer);
00236         
00237         sysarg_t retval = async_data_write_start(phone, name, str_size(name));
00238         if (retval != EOK) {
00239                 async_wait_for(req, NULL);
00240                 async_serialize_end();
00241                 return retval;
00242         }
00243         
00244         async_wait_for(req, &retval);
00245         
00246         async_serialize_end();
00247         
00248         if (retval != EOK) {
00249                 if (handle != NULL)
00250                         *handle = (devmap_handle_t) -1;
00251                 return retval;
00252         }
00253         
00254         if (handle != NULL)
00255                 *handle = (devmap_handle_t) IPC_GET_ARG1(answer);
00256         
00257         return retval;
00258 }
00259 
00260 devmap_handle_type_t devmap_handle_probe(devmap_handle_t handle)
00261 {
00262         int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
00263         
00264         if (phone < 0)
00265                 return phone;
00266         
00267         sysarg_t type;
00268         int retval = async_req_1_1(phone, DEVMAP_HANDLE_PROBE, handle, &type);
00269         if (retval != EOK)
00270                 return DEV_HANDLE_NONE;
00271         
00272         return (devmap_handle_type_t) type;
00273 }
00274 
00275 int devmap_device_connect(devmap_handle_t handle, unsigned int flags)
00276 {
00277         int phone;
00278         
00279         if (flags & IPC_FLAG_BLOCKING) {
00280                 phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP,
00281                     DEVMAP_CONNECT_TO_DEVICE, handle);
00282         } else {
00283                 phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
00284                     DEVMAP_CONNECT_TO_DEVICE, handle);
00285         }
00286         
00287         return phone;
00288 }
00289 
00290 int devmap_null_create(void)
00291 {
00292         int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
00293         
00294         if (phone < 0)
00295                 return -1;
00296         
00297         sysarg_t null_id;
00298         int retval = async_req_0_1(phone, DEVMAP_NULL_CREATE, &null_id);
00299         if (retval != EOK)
00300                 return -1;
00301         
00302         return (int) null_id;
00303 }
00304 
00305 void devmap_null_destroy(int null_id)
00306 {
00307         int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
00308         
00309         if (phone < 0)
00310                 return;
00311         
00312         async_req_1_0(phone, DEVMAP_NULL_DESTROY, (sysarg_t) null_id);
00313 }
00314 
00315 static size_t devmap_count_namespaces_internal(int phone)
00316 {
00317         sysarg_t count;
00318         int retval = async_req_0_1(phone, DEVMAP_GET_NAMESPACE_COUNT, &count);
00319         if (retval != EOK)
00320                 return 0;
00321         
00322         return count;
00323 }
00324 
00325 static size_t devmap_count_devices_internal(int phone, devmap_handle_t ns_handle)
00326 {
00327         sysarg_t count;
00328         int retval = async_req_1_1(phone, DEVMAP_GET_DEVICE_COUNT, ns_handle, &count);
00329         if (retval != EOK)
00330                 return 0;
00331         
00332         return count;
00333 }
00334 
00335 size_t devmap_count_namespaces(void)
00336 {
00337         int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
00338         
00339         if (phone < 0)
00340                 return 0;
00341         
00342         return devmap_count_namespaces_internal(phone);
00343 }
00344 
00345 size_t devmap_count_devices(devmap_handle_t ns_handle)
00346 {
00347         int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
00348         
00349         if (phone < 0)
00350                 return 0;
00351         
00352         return devmap_count_devices_internal(phone, ns_handle);
00353 }
00354 
00355 size_t devmap_get_namespaces(dev_desc_t **data)
00356 {
00357         int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
00358         
00359         if (phone < 0)
00360                 return 0;
00361         
00362         /* Loop until namespaces read succesful */
00363         while (true) {
00364                 size_t count = devmap_count_namespaces_internal(phone);
00365                 if (count == 0)
00366                         return 0;
00367                 
00368                 dev_desc_t *devs = (dev_desc_t *) calloc(count, sizeof(dev_desc_t));
00369                 if (devs == NULL)
00370                         return 0;
00371                 
00372                 async_serialize_start();
00373                 
00374                 ipc_call_t answer;
00375                 aid_t req = async_send_0(phone, DEVMAP_GET_NAMESPACES, &answer);
00376                 
00377                 int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
00378                 if (rc == EOVERFLOW) {
00379                         /*
00380                          * Number of namespaces has changed since
00381                          * the last call of DEVMAP_DEVICE_GET_NAMESPACE_COUNT
00382                          */
00383                         async_serialize_end();
00384                         free(devs);
00385                         continue;
00386                 }
00387                 
00388                 if (rc != EOK) {
00389                         async_wait_for(req, NULL);
00390                         async_serialize_end();
00391                         free(devs);
00392                         return 0;
00393                 }
00394                 
00395                 sysarg_t retval;
00396                 async_wait_for(req, &retval);
00397                 async_serialize_end();
00398                 
00399                 if (retval != EOK)
00400                         return 0;
00401                 
00402                 *data = devs;
00403                 return count;
00404         }
00405 }
00406 
00407 size_t devmap_get_devices(devmap_handle_t ns_handle, dev_desc_t **data)
00408 {
00409         int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
00410         
00411         if (phone < 0)
00412                 return 0;
00413         
00414         /* Loop until namespaces read succesful */
00415         while (true) {
00416                 size_t count = devmap_count_devices_internal(phone, ns_handle);
00417                 if (count == 0)
00418                         return 0;
00419                 
00420                 dev_desc_t *devs = (dev_desc_t *) calloc(count, sizeof(dev_desc_t));
00421                 if (devs == NULL)
00422                         return 0;
00423                 
00424                 async_serialize_start();
00425                 
00426                 ipc_call_t answer;
00427                 aid_t req = async_send_1(phone, DEVMAP_GET_DEVICES, ns_handle, &answer);
00428                 
00429                 int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
00430                 if (rc == EOVERFLOW) {
00431                         /*
00432                          * Number of devices has changed since
00433                          * the last call of DEVMAP_DEVICE_GET_DEVICE_COUNT
00434                          */
00435                         async_serialize_end();
00436                         free(devs);
00437                         continue;
00438                 }
00439                 
00440                 if (rc != EOK) {
00441                         async_wait_for(req, NULL);
00442                         async_serialize_end();
00443                         free(devs);
00444                         return 0;
00445                 }
00446                 
00447                 sysarg_t retval;
00448                 async_wait_for(req, &retval);
00449                 async_serialize_end();
00450                 
00451                 if (retval != EOK)
00452                         return 0;
00453                 
00454                 *data = devs;
00455                 return count;
00456         }
00457 }

Generated on Thu Jun 2 07:45:46 2011 for HelenOS/USB by  doxygen 1.4.7