Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset d80d7a8 in mainline


Ignore:
Timestamp:
2013-09-10T20:44:58Z (8 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master
Children:
181c32f
Parents:
08bc23d
Message:

Separate module for devman-client connection handling.

Location:
uspace/srv/devman
Files:
3 added
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/devman/Makefile

    r08bc23d rd80d7a8  
    3333
    3434SOURCES = \
     35        client_conn.c \
    3536        dev.c \
    3637        devtree.c \
  • uspace/srv/devman/main.c

    r08bc23d rd80d7a8  
    5858#include <loc.h>
    5959
     60#include "client_conn.h"
    6061#include "dev.h"
    6162#include "devman.h"
     
    6869
    6970static driver_list_t drivers_list;
    70 static dev_tree_t device_tree;
     71dev_tree_t device_tree;
    7172
    7273static int init_running_drv(void *drv);
     
    802803}
    803804
    804 /** Find handle for the device instance identified by the device's path in the
    805  * device tree. */
    806 static void devman_function_get_handle(ipc_callid_t iid, ipc_call_t *icall)
    807 {
    808         char *pathname;
    809         devman_handle_t handle;
    810        
    811         int rc = async_data_write_accept((void **) &pathname, true, 0, 0, 0, 0);
    812         if (rc != EOK) {
    813                 async_answer_0(iid, rc);
    814                 return;
    815         }
    816        
    817         fun_node_t *fun = find_fun_node_by_path(&device_tree, pathname);
    818        
    819         free(pathname);
    820 
    821         if (fun == NULL) {
    822                 async_answer_0(iid, ENOENT);
    823                 return;
    824         }
    825 
    826         fibril_rwlock_read_lock(&device_tree.rwlock);
    827 
    828         /* Check function state */
    829         if (fun->state == FUN_REMOVED) {
    830                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    831                 async_answer_0(iid, ENOENT);
    832                 return;
    833         }
    834         handle = fun->handle;
    835 
    836         fibril_rwlock_read_unlock(&device_tree.rwlock);
    837 
    838         /* Delete reference created above by find_fun_node_by_path() */
    839         fun_del_ref(fun);
    840 
    841         async_answer_1(iid, EOK, handle);
    842 }
    843 
    844 /** Get device name. */
    845 static void devman_fun_get_name(ipc_callid_t iid, ipc_call_t *icall)
    846 {
    847         devman_handle_t handle = IPC_GET_ARG1(*icall);
    848 
    849         fun_node_t *fun = find_fun_node(&device_tree, handle);
    850         if (fun == NULL) {
    851                 async_answer_0(iid, ENOMEM);
    852                 return;
    853         }
    854 
    855         ipc_callid_t data_callid;
    856         size_t data_len;
    857         if (!async_data_read_receive(&data_callid, &data_len)) {
    858                 async_answer_0(iid, EINVAL);
    859                 fun_del_ref(fun);
    860                 return;
    861         }
    862 
    863         void *buffer = malloc(data_len);
    864         if (buffer == NULL) {
    865                 async_answer_0(data_callid, ENOMEM);
    866                 async_answer_0(iid, ENOMEM);
    867                 fun_del_ref(fun);
    868                 return;
    869         }
    870 
    871         fibril_rwlock_read_lock(&device_tree.rwlock);
    872 
    873         /* Check function state */
    874         if (fun->state == FUN_REMOVED) {
    875                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    876                 free(buffer);
    877 
    878                 async_answer_0(data_callid, ENOENT);
    879                 async_answer_0(iid, ENOENT);
    880                 fun_del_ref(fun);
    881                 return;
    882         }
    883 
    884         size_t sent_length = str_size(fun->name);
    885         if (sent_length > data_len) {
    886                 sent_length = data_len;
    887         }
    888 
    889         async_data_read_finalize(data_callid, fun->name, sent_length);
    890         async_answer_0(iid, EOK);
    891 
    892         fibril_rwlock_read_unlock(&device_tree.rwlock);
    893         fun_del_ref(fun);
    894         free(buffer);
    895 }
    896 
    897 /** Get function driver name. */
    898 static void devman_fun_get_driver_name(ipc_callid_t iid, ipc_call_t *icall)
    899 {
    900         devman_handle_t handle = IPC_GET_ARG1(*icall);
    901 
    902         fun_node_t *fun = find_fun_node(&device_tree, handle);
    903         if (fun == NULL) {
    904                 async_answer_0(iid, ENOMEM);
    905                 return;
    906         }
    907 
    908         ipc_callid_t data_callid;
    909         size_t data_len;
    910         if (!async_data_read_receive(&data_callid, &data_len)) {
    911                 async_answer_0(iid, EINVAL);
    912                 fun_del_ref(fun);
    913                 return;
    914         }
    915 
    916         void *buffer = malloc(data_len);
    917         if (buffer == NULL) {
    918                 async_answer_0(data_callid, ENOMEM);
    919                 async_answer_0(iid, ENOMEM);
    920                 fun_del_ref(fun);
    921                 return;
    922         }
    923 
    924         fibril_rwlock_read_lock(&device_tree.rwlock);
    925 
    926         /* Check function state */
    927         if (fun->state == FUN_REMOVED) {
    928                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    929                 free(buffer);
    930 
    931                 async_answer_0(data_callid, ENOENT);
    932                 async_answer_0(iid, ENOENT);
    933                 fun_del_ref(fun);
    934                 return;
    935         }
    936 
    937         /* Check whether function has a driver */
    938         if (fun->child == NULL || fun->child->drv == NULL) {
    939                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    940                 free(buffer);
    941 
    942                 async_answer_0(data_callid, EINVAL);
    943                 async_answer_0(iid, EINVAL);
    944                 fun_del_ref(fun);
    945                 return;
    946         }
    947 
    948         size_t sent_length = str_size(fun->child->drv->name);
    949         if (sent_length > data_len) {
    950                 sent_length = data_len;
    951         }
    952 
    953         async_data_read_finalize(data_callid, fun->child->drv->name,
    954             sent_length);
    955         async_answer_0(iid, EOK);
    956 
    957         fibril_rwlock_read_unlock(&device_tree.rwlock);
    958         fun_del_ref(fun);
    959         free(buffer);
    960 }
    961 
    962 /** Get device path. */
    963 static void devman_fun_get_path(ipc_callid_t iid, ipc_call_t *icall)
    964 {
    965         devman_handle_t handle = IPC_GET_ARG1(*icall);
    966 
    967         fun_node_t *fun = find_fun_node(&device_tree, handle);
    968         if (fun == NULL) {
    969                 async_answer_0(iid, ENOMEM);
    970                 return;
    971         }
    972 
    973         ipc_callid_t data_callid;
    974         size_t data_len;
    975         if (!async_data_read_receive(&data_callid, &data_len)) {
    976                 async_answer_0(iid, EINVAL);
    977                 fun_del_ref(fun);
    978                 return;
    979         }
    980 
    981         void *buffer = malloc(data_len);
    982         if (buffer == NULL) {
    983                 async_answer_0(data_callid, ENOMEM);
    984                 async_answer_0(iid, ENOMEM);
    985                 fun_del_ref(fun);
    986                 return;
    987         }
    988        
    989         fibril_rwlock_read_lock(&device_tree.rwlock);
    990        
    991         /* Check function state */
    992         if (fun->state == FUN_REMOVED) {
    993                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    994                 free(buffer);
    995 
    996                 async_answer_0(data_callid, ENOENT);
    997                 async_answer_0(iid, ENOENT);
    998                 fun_del_ref(fun);
    999                 return;
    1000         }
    1001        
    1002         size_t sent_length = str_size(fun->pathname);
    1003         if (sent_length > data_len) {
    1004                 sent_length = data_len;
    1005         }
    1006 
    1007         async_data_read_finalize(data_callid, fun->pathname, sent_length);
    1008         async_answer_0(iid, EOK);
    1009 
    1010         fibril_rwlock_read_unlock(&device_tree.rwlock);
    1011         fun_del_ref(fun);
    1012         free(buffer);
    1013 }
    1014 
    1015 static void devman_dev_get_functions(ipc_callid_t iid, ipc_call_t *icall)
    1016 {
    1017         ipc_callid_t callid;
    1018         size_t size;
    1019         size_t act_size;
    1020         int rc;
    1021        
    1022         if (!async_data_read_receive(&callid, &size)) {
    1023                 async_answer_0(callid, EREFUSED);
    1024                 async_answer_0(iid, EREFUSED);
    1025                 return;
    1026         }
    1027        
    1028         fibril_rwlock_read_lock(&device_tree.rwlock);
    1029        
    1030         dev_node_t *dev = find_dev_node_no_lock(&device_tree,
    1031             IPC_GET_ARG1(*icall));
    1032         if (dev == NULL || dev->state == DEVICE_REMOVED) {
    1033                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    1034                 async_answer_0(callid, ENOENT);
    1035                 async_answer_0(iid, ENOENT);
    1036                 return;
    1037         }
    1038        
    1039         devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size);
    1040         if (hdl_buf == NULL) {
    1041                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    1042                 async_answer_0(callid, ENOMEM);
    1043                 async_answer_0(iid, ENOMEM);
    1044                 return;
    1045         }
    1046        
    1047         rc = dev_get_functions(&device_tree, dev, hdl_buf, size, &act_size);
    1048         if (rc != EOK) {
    1049                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    1050                 async_answer_0(callid, rc);
    1051                 async_answer_0(iid, rc);
    1052                 return;
    1053         }
    1054        
    1055         fibril_rwlock_read_unlock(&device_tree.rwlock);
    1056        
    1057         sysarg_t retval = async_data_read_finalize(callid, hdl_buf, size);
    1058         free(hdl_buf);
    1059        
    1060         async_answer_1(iid, retval, act_size);
    1061 }
    1062 
    1063 
    1064 /** Get handle for child device of a function. */
    1065 static void devman_fun_get_child(ipc_callid_t iid, ipc_call_t *icall)
    1066 {
    1067         fun_node_t *fun;
    1068        
    1069         fibril_rwlock_read_lock(&device_tree.rwlock);
    1070        
    1071         fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall));
    1072         if (fun == NULL || fun->state == FUN_REMOVED) {
    1073                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    1074                 async_answer_0(iid, ENOENT);
    1075                 return;
    1076         }
    1077        
    1078         if (fun->child == NULL) {
    1079                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    1080                 async_answer_0(iid, ENOENT);
    1081                 return;
    1082         }
    1083        
    1084         async_answer_1(iid, EOK, fun->child->handle);
    1085        
    1086         fibril_rwlock_read_unlock(&device_tree.rwlock);
    1087 }
    1088 
    1089 /** Online function.
    1090  *
    1091  * Send a request to online a function to the responsible driver.
    1092  * The driver may offline other functions if necessary (i.e. if the state
    1093  * of this function is linked to state of another function somehow).
    1094  */
    1095 static void devman_fun_online(ipc_callid_t iid, ipc_call_t *icall)
    1096 {
    1097         fun_node_t *fun;
    1098         int rc;
    1099 
    1100         fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
    1101         if (fun == NULL) {
    1102                 async_answer_0(iid, ENOENT);
    1103                 return;
    1104         }
    1105        
    1106         rc = driver_fun_online(&device_tree, fun);
    1107         fun_del_ref(fun);
    1108        
    1109         async_answer_0(iid, (sysarg_t) rc);
    1110 }
    1111 
    1112 /** Offline function.
    1113  *
    1114  * Send a request to offline a function to the responsible driver. As
    1115  * a result the subtree rooted at that function should be cleanly
    1116  * detatched. The driver may offline other functions if necessary
    1117  * (i.e. if the state of this function is linked to state of another
    1118  * function somehow).
    1119  */
    1120 static void devman_fun_offline(ipc_callid_t iid, ipc_call_t *icall)
    1121 {
    1122         fun_node_t *fun;
    1123         int rc;
    1124 
    1125         fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
    1126         if (fun == NULL) {
    1127                 async_answer_0(iid, ENOENT);
    1128                 return;
    1129         }
    1130        
    1131         rc = driver_fun_offline(&device_tree, fun);
    1132         fun_del_ref(fun);
    1133        
    1134         async_answer_0(iid, (sysarg_t) rc);
    1135 }
    1136 
    1137 /** Find handle for the function instance identified by its service ID. */
    1138 static void devman_fun_sid_to_handle(ipc_callid_t iid, ipc_call_t *icall)
    1139 {
    1140         fun_node_t *fun;
    1141 
    1142         fun = find_loc_tree_function(&device_tree, IPC_GET_ARG1(*icall));
    1143        
    1144         if (fun == NULL) {
    1145                 async_answer_0(iid, ENOENT);
    1146                 return;
    1147         }
    1148 
    1149         fibril_rwlock_read_lock(&device_tree.rwlock);
    1150 
    1151         /* Check function state */
    1152         if (fun->state == FUN_REMOVED) {
    1153                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    1154                 async_answer_0(iid, ENOENT);
    1155                 return;
    1156         }
    1157 
    1158         async_answer_1(iid, EOK, fun->handle);
    1159         fibril_rwlock_read_unlock(&device_tree.rwlock);
    1160         fun_del_ref(fun);
    1161 }
    1162 
    1163 /** Function for handling connections from a client to the device manager. */
    1164 static void devman_connection_client(ipc_callid_t iid, ipc_call_t *icall)
    1165 {
    1166         /* Accept connection. */
    1167         async_answer_0(iid, EOK);
    1168        
    1169         while (true) {
    1170                 ipc_call_t call;
    1171                 ipc_callid_t callid = async_get_call(&call);
    1172                
    1173                 if (!IPC_GET_IMETHOD(call))
    1174                         break;
    1175                
    1176                 switch (IPC_GET_IMETHOD(call)) {
    1177                 case DEVMAN_DEVICE_GET_HANDLE:
    1178                         devman_function_get_handle(callid, &call);
    1179                         break;
    1180                 case DEVMAN_DEV_GET_FUNCTIONS:
    1181                         devman_dev_get_functions(callid, &call);
    1182                         break;
    1183                 case DEVMAN_FUN_GET_CHILD:
    1184                         devman_fun_get_child(callid, &call);
    1185                         break;
    1186                 case DEVMAN_FUN_GET_NAME:
    1187                         devman_fun_get_name(callid, &call);
    1188                         break;
    1189                 case DEVMAN_FUN_GET_DRIVER_NAME:
    1190                         devman_fun_get_driver_name(callid, &call);
    1191                         break;
    1192                 case DEVMAN_FUN_GET_PATH:
    1193                         devman_fun_get_path(callid, &call);
    1194                         break;
    1195                 case DEVMAN_FUN_ONLINE:
    1196                         devman_fun_online(callid, &call);
    1197                         break;
    1198                 case DEVMAN_FUN_OFFLINE:
    1199                         devman_fun_offline(callid, &call);
    1200                         break;
    1201                 case DEVMAN_FUN_SID_TO_HANDLE:
    1202                         devman_fun_sid_to_handle(callid, &call);
    1203                         break;
    1204                 default:
    1205                         async_answer_0(callid, ENOENT);
    1206                 }
    1207         }
    1208 }
    1209 
    1210805static void devman_forward(ipc_callid_t iid, ipc_call_t *icall,
    1211806    bool drv_to_parent)
Note: See TracChangeset for help on using the changeset viewer.