Changeset e280857 in mainline for uspace/srv/devman
- Timestamp:
- 2011-08-18T12:35:59Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 99ac5cf
- Parents:
- 12f9f0d0
- Location:
- uspace/srv/devman
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/devman/devman.c
r12f9f0d0 re280857 73 73 } 74 74 75 static int loc_devices_class_compare(unsigned long key[], hash_count_t keys,76 link_t *item)77 {78 dev_class_info_t *class_info79 = hash_table_get_instance(item, dev_class_info_t, loc_link);80 assert(class_info != NULL);81 82 return (class_info->service_id == (service_id_t) key[0]);83 }84 85 75 static void devices_remove_callback(link_t *item) 86 76 { … … 102 92 .hash = devices_hash, 103 93 .compare = loc_functions_compare, 104 .remove_callback = devices_remove_callback105 };106 107 static hash_table_operations_t loc_devices_class_ops = {108 .hash = devices_hash,109 .compare = loc_devices_class_compare,110 94 .remove_callback = devices_remove_callback 111 95 }; … … 950 934 link_initialize(&res->dev_functions); 951 935 list_initialize(&res->match_ids.ids); 952 list_initialize(&res->classes);953 936 link_initialize(&res->devman_fun); 954 937 link_initialize(&res->loc_fun); … … 1193 1176 } 1194 1177 1195 /** Find function node by its class name and index. */1196 fun_node_t *find_fun_node_by_class(class_list_t *class_list,1197 const char *class_name, const char *dev_name)1198 {1199 assert(class_list != NULL);1200 assert(class_name != NULL);1201 assert(dev_name != NULL);1202 1203 fibril_rwlock_read_lock(&class_list->rwlock);1204 1205 dev_class_t *cl = find_dev_class_no_lock(class_list, class_name);1206 if (cl == NULL) {1207 fibril_rwlock_read_unlock(&class_list->rwlock);1208 return NULL;1209 }1210 1211 dev_class_info_t *dev = find_dev_in_class(cl, dev_name);1212 if (dev == NULL) {1213 fibril_rwlock_read_unlock(&class_list->rwlock);1214 return NULL;1215 }1216 1217 fun_node_t *fun = dev->fun;1218 1219 fibril_rwlock_read_unlock(&class_list->rwlock);1220 1221 return fun;1222 }1223 1224 1225 1178 /** Find child function node with a specified name. 1226 1179 * … … 1235 1188 return find_fun_node_in_device(pfun->child, name); 1236 1189 } 1237 1238 /* Device classes */1239 1240 /** Create device class.1241 *1242 * @return Device class.1243 */1244 dev_class_t *create_dev_class(void)1245 {1246 dev_class_t *cl;1247 1248 cl = (dev_class_t *) malloc(sizeof(dev_class_t));1249 if (cl != NULL) {1250 memset(cl, 0, sizeof(dev_class_t));1251 list_initialize(&cl->devices);1252 fibril_mutex_initialize(&cl->mutex);1253 }1254 1255 return cl;1256 }1257 1258 /** Create device class info.1259 *1260 * @return Device class info.1261 */1262 dev_class_info_t *create_dev_class_info(void)1263 {1264 dev_class_info_t *info;1265 1266 info = (dev_class_info_t *) malloc(sizeof(dev_class_info_t));1267 if (info != NULL) {1268 memset(info, 0, sizeof(dev_class_info_t));1269 link_initialize(&info->dev_classes);1270 link_initialize(&info->loc_link);1271 link_initialize(&info->link);1272 }1273 1274 return info;1275 }1276 1277 size_t get_new_class_dev_idx(dev_class_t *cl)1278 {1279 size_t dev_idx;1280 1281 fibril_mutex_lock(&cl->mutex);1282 dev_idx = ++cl->curr_dev_idx;1283 fibril_mutex_unlock(&cl->mutex);1284 1285 return dev_idx;1286 }1287 1288 1289 /** Create unique device name within the class.1290 *1291 * @param cl The class.1292 * @param base_dev_name Contains the base name for the device if it was1293 * specified by the driver when it registered the device by1294 * the class; NULL if driver specified no base name.1295 * @return The unique name for the device within the class.1296 */1297 char *create_dev_name_for_class(dev_class_t *cl, const char *base_dev_name)1298 {1299 char *dev_name;1300 const char *base_name;1301 1302 if (base_dev_name != NULL)1303 base_name = base_dev_name;1304 else1305 base_name = cl->base_dev_name;1306 1307 size_t idx = get_new_class_dev_idx(cl);1308 asprintf(&dev_name, "%s%zu", base_name, idx);1309 1310 return dev_name;1311 }1312 1313 /** Add the device function to the class.1314 *1315 * The device may be added to multiple classes and a class may contain multiple1316 * devices. The class and the device are associated with each other by the1317 * dev_class_info_t structure.1318 *1319 * @param dev The device.1320 * @param class The class.1321 * @param base_dev_name The base name of the device within the class if1322 * specified by the driver, NULL otherwise.1323 * @return dev_class_info_t structure which associates the device1324 * with the class.1325 */1326 dev_class_info_t *add_function_to_class(fun_node_t *fun, dev_class_t *cl,1327 const char *base_dev_name)1328 {1329 dev_class_info_t *info;1330 1331 assert(fun != NULL);1332 assert(cl != NULL);1333 1334 info = create_dev_class_info();1335 1336 1337 if (info != NULL) {1338 info->dev_class = cl;1339 info->fun = fun;1340 1341 /* Add the device to the class. */1342 fibril_mutex_lock(&cl->mutex);1343 list_append(&info->link, &cl->devices);1344 fibril_mutex_unlock(&cl->mutex);1345 1346 /* Add the class to the device. */1347 list_append(&info->dev_classes, &fun->classes);1348 1349 /* Create unique name for the device within the class. */1350 info->dev_name = create_dev_name_for_class(cl, base_dev_name);1351 }1352 1353 return info;1354 }1355 1356 dev_class_t *get_dev_class(class_list_t *class_list, char *class_name)1357 {1358 dev_class_t *cl;1359 1360 fibril_rwlock_write_lock(&class_list->rwlock);1361 cl = find_dev_class_no_lock(class_list, class_name);1362 if (cl == NULL) {1363 cl = create_dev_class();1364 if (cl != NULL) {1365 cl->name = class_name;1366 cl->base_dev_name = "";1367 add_dev_class_no_lock(class_list, cl);1368 }1369 }1370 1371 fibril_rwlock_write_unlock(&class_list->rwlock);1372 return cl;1373 }1374 1375 dev_class_t *find_dev_class_no_lock(class_list_t *class_list,1376 const char *class_name)1377 {1378 dev_class_t *cl;1379 1380 list_foreach(class_list->classes, link) {1381 cl = list_get_instance(link, dev_class_t, link);1382 if (str_cmp(cl->name, class_name) == 0) {1383 return cl;1384 }1385 }1386 1387 return NULL;1388 }1389 1390 void add_dev_class_no_lock(class_list_t *class_list, dev_class_t *cl)1391 {1392 list_append(&cl->link, &class_list->classes);1393 }1394 1395 dev_class_info_t *find_dev_in_class(dev_class_t *dev_class, const char *dev_name)1396 {1397 assert(dev_class != NULL);1398 assert(dev_name != NULL);1399 1400 list_foreach(dev_class->devices, link) {1401 dev_class_info_t *dev = list_get_instance(link,1402 dev_class_info_t, link);1403 1404 if (str_cmp(dev->dev_name, dev_name) == 0) {1405 return dev;1406 }1407 }1408 1409 return NULL;1410 }1411 1412 void init_class_list(class_list_t *class_list)1413 {1414 list_initialize(&class_list->classes);1415 fibril_rwlock_initialize(&class_list->rwlock);1416 hash_table_create(&class_list->loc_functions, DEVICE_BUCKETS, 1,1417 &loc_devices_class_ops);1418 }1419 1420 1190 1421 1191 /* loc devices */ … … 1436 1206 } 1437 1207 1438 fun_node_t *find_loc_class_function(class_list_t *classes,1439 service_id_t service_id)1440 {1441 fun_node_t *fun = NULL;1442 dev_class_info_t *cli;1443 link_t *link;1444 unsigned long key = (unsigned long)service_id;1445 1446 fibril_rwlock_read_lock(&classes->rwlock);1447 link = hash_table_find(&classes->loc_functions, &key);1448 if (link != NULL) {1449 cli = hash_table_get_instance(link, dev_class_info_t,1450 loc_link);1451 fun = cli->fun;1452 }1453 fibril_rwlock_read_unlock(&classes->rwlock);1454 1455 return fun;1456 }1457 1458 void class_add_loc_function(class_list_t *class_list, dev_class_info_t *cli)1459 {1460 unsigned long key = (unsigned long) cli->service_id;1461 1462 fibril_rwlock_write_lock(&class_list->rwlock);1463 hash_table_insert(&class_list->loc_functions, &key, &cli->loc_link);1464 fibril_rwlock_write_unlock(&class_list->rwlock);1465 1466 assert(find_loc_class_function(class_list, cli->service_id) != NULL);1467 }1468 1469 1208 void tree_add_loc_function(dev_tree_t *tree, fun_node_t *fun) 1470 1209 { -
uspace/srv/devman/devman.h
r12f9f0d0 re280857 53 53 #define DEVICE_BUCKETS 256 54 54 55 #define LOC_CLASS_NAMESPACE "class"56 55 #define LOC_DEVICE_NAMESPACE "devices" 57 56 #define LOC_SEPARATOR '\\' … … 170 169 match_id_list_t match_ids; 171 170 172 /** List of device classes to which this device function belongs. */173 list_t classes;174 171 /** Service ID if the device function is registered with loc. */ 175 172 service_id_t service_id; … … 213 210 hash_table_t loc_functions; 214 211 } dev_tree_t; 215 216 typedef struct dev_class {217 /** The name of the class. */218 const char *name;219 220 /**221 * Pointer to the previous and next class in the list of registered222 * classes.223 */224 link_t link;225 226 /**227 * List of dev_class_info structures - one for each device registered by228 * this class.229 */230 list_t devices;231 232 /**233 * Default base name for the device within the class, might be overrided234 * by the driver.235 */236 const char *base_dev_name;237 238 /** Unique numerical identifier of the newly added device. */239 size_t curr_dev_idx;240 /** Synchronize access to the list of devices in this class. */241 fibril_mutex_t mutex;242 } dev_class_t;243 244 /**245 * Provides n-to-m mapping between function nodes and classes - each function246 * can register in an arbitrary number of classes and each class can contain247 * an arbitrary number of device functions.248 */249 typedef struct dev_class_info {250 /** The class. */251 dev_class_t *dev_class;252 /** The device. */253 fun_node_t *fun;254 255 /**256 * Pointer to the previous and next class info in the list of devices257 * registered by the class.258 */259 link_t link;260 261 /**262 * Pointer to the previous and next class info in the list of classes263 * by which the device is registered.264 */265 link_t dev_classes;266 267 /** The name of the device function within the class. */268 char *dev_name;269 /** Service ID in the class namespace. */270 service_id_t service_id;271 272 /**273 * Link to hash table of services registered with location service using274 * their class names.275 */276 link_t loc_link;277 } dev_class_info_t;278 279 /** The list of device classes. */280 typedef struct class_list {281 /** List of classes. */282 list_t classes;283 284 /**285 * Hash table of services registered with location service using their286 * class name, indexed by service IDs.287 */288 hash_table_t loc_functions;289 290 /** Fibril mutex for list of classes. */291 fibril_rwlock_t rwlock;292 } class_list_t;293 212 294 213 /* Match ids and scores */ … … 339 258 extern fun_node_t *find_fun_node_by_path(dev_tree_t *, char *); 340 259 extern fun_node_t *find_fun_node_in_device(dev_node_t *, const char *); 341 extern fun_node_t *find_fun_node_by_class(class_list_t *, const char *, const char *);342 260 343 261 /* Device tree */ … … 348 266 extern bool insert_fun_node(dev_tree_t *, fun_node_t *, char *, dev_node_t *); 349 267 350 /* Device classes */351 352 extern dev_class_t *create_dev_class(void);353 extern dev_class_info_t *create_dev_class_info(void);354 extern size_t get_new_class_dev_idx(dev_class_t *);355 extern char *create_dev_name_for_class(dev_class_t *, const char *);356 extern dev_class_info_t *add_function_to_class(fun_node_t *, dev_class_t *,357 const char *);358 359 extern void init_class_list(class_list_t *);360 361 extern dev_class_t *get_dev_class(class_list_t *, char *);362 extern dev_class_t *find_dev_class_no_lock(class_list_t *, const char *);363 extern dev_class_info_t *find_dev_in_class(dev_class_t *, const char *);364 extern void add_dev_class_no_lock(class_list_t *, dev_class_t *);365 366 268 /* Loc services */ 367 269 … … 369 271 370 272 extern fun_node_t *find_loc_tree_function(dev_tree_t *, service_id_t); 371 extern fun_node_t *find_loc_class_function(class_list_t *, service_id_t); 372 373 extern void class_add_loc_function(class_list_t *, dev_class_info_t *); 273 374 274 extern void tree_add_loc_function(dev_tree_t *, fun_node_t *); 375 275 -
uspace/srv/devman/main.c
r12f9f0d0 re280857 64 64 static driver_list_t drivers_list; 65 65 static dev_tree_t device_tree; 66 static class_list_t class_list;67 66 68 67 /** Register running driver. */ … … 333 332 } 334 333 335 static void loc_register_class_dev(dev_class_info_t *cli)336 {337 /* Create loc path and name for the service. */338 char *loc_pathname = NULL;339 340 asprintf(&loc_pathname, "%s/%s%c%s", LOC_CLASS_NAMESPACE,341 cli->dev_class->name, LOC_SEPARATOR, cli->dev_name);342 if (loc_pathname == NULL)343 return;344 345 /*346 * Register the device with location service and remember its347 * service ID.348 */349 loc_service_register_with_iface(loc_pathname,350 &cli->service_id, DEVMAN_CONNECT_FROM_LOC);351 352 /*353 * Add device to the hash map of class devices registered with354 * location service.355 */356 class_add_loc_function(&class_list, cli);357 358 free(loc_pathname);359 }360 361 334 static void devman_add_function_to_class(ipc_callid_t callid, ipc_call_t *call) 362 335 { … … 380 353 } 381 354 382 dev_class_t *cl = get_dev_class(&class_list, class_name);383 dev_class_info_t *class_info = add_function_to_class(fun, cl, NULL);384 385 /* Register the device's class alias with location service. */386 loc_register_class_dev(class_info);387 388 355 rc = loc_category_get_id(class_name, &cat_id, IPC_FLAG_BLOCKING); 389 356 if (rc == EOK) { … … 394 361 } 395 362 396 log_msg(LVL_NOTE, "Function `%s' added to class `%s' as `%s'.",397 fun->pathname, class_name , class_info->dev_name);363 log_msg(LVL_NOTE, "Function `%s' added to class `%s'.", 364 fun->pathname, class_name); 398 365 399 366 async_answer_0(callid, EOK); … … 483 450 } 484 451 485 /** Find handle for the device instance identified by device class name. */486 static void devman_function_get_handle_by_class(ipc_callid_t iid,487 ipc_call_t *icall)488 {489 char *classname;490 char *devname;491 492 int rc = async_data_write_accept((void **) &classname, true, 0, 0, 0, 0);493 if (rc != EOK) {494 async_answer_0(iid, rc);495 return;496 }497 rc = async_data_write_accept((void **) &devname, true, 0, 0, 0, 0);498 if (rc != EOK) {499 free(classname);500 async_answer_0(iid, rc);501 return;502 }503 504 505 fun_node_t *fun = find_fun_node_by_class(&class_list,506 classname, devname);507 508 free(classname);509 free(devname);510 511 if (fun == NULL) {512 async_answer_0(iid, ENOENT);513 return;514 }515 516 async_answer_1(iid, EOK, fun->handle);517 }518 519 452 /** Find device path by its handle. */ 520 453 static void devman_get_device_path_by_handle(ipc_callid_t iid, … … 554 487 } 555 488 489 /** Find handle for the function instance identified by its service ID. */ 490 static void devman_fun_sid_to_handle(ipc_callid_t iid, ipc_call_t *icall) 491 { 492 fun_node_t *fun; 493 494 fun = find_loc_tree_function(&device_tree, IPC_GET_ARG1(*icall)); 495 496 if (fun == NULL) { 497 async_answer_0(iid, ENOENT); 498 return; 499 } 500 501 async_answer_1(iid, EOK, fun->handle); 502 } 556 503 557 504 /** Function for handling connections from a client to the device manager. */ … … 572 519 devman_function_get_handle(callid, &call); 573 520 break; 574 case DEVMAN_DEVICE_GET_HANDLE_BY_CLASS:575 devman_function_get_handle_by_class(callid, &call);576 break;577 521 case DEVMAN_DEVICE_GET_DEVICE_PATH: 578 522 devman_get_device_path_by_handle(callid, &call); 523 break; 524 case DEVMAN_FUN_SID_TO_HANDLE: 525 devman_fun_sid_to_handle(callid, &call); 579 526 break; 580 527 default: … … 678 625 679 626 fun = find_loc_tree_function(&device_tree, service_id); 680 if (fun == NULL)681 fun = find_loc_class_function(&class_list, service_id);682 627 683 628 if (fun == NULL || fun->dev->drv == NULL) { … … 750 695 } 751 696 752 init_class_list(&class_list);753 754 697 /* 755 698 * !!! devman_connection ... as the device manager is not a real loc
Note:
See TracChangeset
for help on using the changeset viewer.