Rev 2555 | Rev 2598 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 2555 | Rev 2594 | ||
|---|---|---|---|
| Line 39... | Line 39... | ||
| 39 | #include <ipc/ns.h> |
39 | #include <ipc/ns.h> |
| 40 | #include <async.h> |
40 | #include <async.h> |
| 41 | #include <stdio.h> |
41 | #include <stdio.h> |
| 42 | #include <errno.h> |
42 | #include <errno.h> |
| 43 | #include <bool.h> |
43 | #include <bool.h> |
| 44 | #include <libadt/list.h> |
- | |
| 45 | #include <futex.h> |
44 | #include <futex.h> |
| - | 45 | #include <stdlib.h> |
|
| - | 46 | #include <string.h> |
|
| 46 | 47 | ||
| 47 | #include "devmap.h" |
48 | #include "devmap.h" |
| 48 | 49 | ||
| 49 | LIST_INITIALIZE(device_list); |
- | |
| 50 | 50 | ||
| - | 51 | LIST_INITIALIZE(devices_list); |
|
| - | 52 | LIST_INITIALIZE(drivers_list); |
|
| - | 53 | ||
| - | 54 | /* order of locking: |
|
| - | 55 | * drivers_list_futex |
|
| - | 56 | * devices_list_futex |
|
| - | 57 | * (devmap_driver_t *)->devices_futex |
|
| - | 58 | * create_handle_futex |
|
| - | 59 | **/ |
|
| - | 60 | ||
| 51 | atomic_t device_list_futex = FUTEX_INITIALIZER; |
61 | static atomic_t devices_list_futex = FUTEX_INITIALIZER; |
| - | 62 | static atomic_t drivers_list_futex = FUTEX_INITIALIZER; |
|
| - | 63 | static atomic_t create_handle_futex = FUTEX_INITIALIZER; |
|
| - | 64 | ||
| - | 65 | ||
| - | 66 | static int devmap_create_handle(void) |
|
| - | 67 | { |
|
| - | 68 | static int last_handle = 0; |
|
| - | 69 | int handle; |
|
| - | 70 | ||
| - | 71 | /* TODO: allow reusing old handles after their unregistration |
|
| - | 72 | and implement some version of LRU algorithm */ |
|
| - | 73 | /* FIXME: overflow */ |
|
| - | 74 | futex_down(&create_handle_futex); |
|
| - | 75 | ||
| - | 76 | last_handle += 1; |
|
| - | 77 | handle = last_handle; |
|
| - | 78 | ||
| - | 79 | futex_up(&create_handle_futex); |
|
| - | 80 | ||
| - | 81 | return handle; |
|
| - | 82 | } |
|
| - | 83 | ||
| 52 | 84 | ||
| 53 | /** Initialize device mapper. |
85 | /** Initialize device mapper. |
| 54 | * |
86 | * |
| 55 | * |
87 | * |
| 56 | */ |
88 | */ |
| 57 | static int devmap_init() |
89 | static int devmap_init() |
| 58 | { |
90 | { |
| 59 | /* */ |
91 | /* TODO: */ |
| 60 | 92 | ||
| 61 | return EOK; |
93 | return EOK; |
| 62 | } |
94 | } |
| 63 | 95 | ||
| 64 | static int devmap_register() |
96 | /** Find device with given name. |
| - | 97 | * |
|
| - | 98 | */ |
|
| - | 99 | static devmap_device_t *devmap_device_find_name(const char *name) |
|
| 65 | { |
100 | { |
| - | 101 | link_t *item; |
|
| - | 102 | devmap_device_t *device = NULL; |
|
| - | 103 | ||
| - | 104 | item = devices_list.next; |
|
| - | 105 | ||
| - | 106 | while (item != &devices_list) { |
|
| - | 107 | ||
| - | 108 | device = list_get_instance(item, devmap_device_t, devices); |
|
| - | 109 | if (0 == strcmp(device->name, name)) { |
|
| - | 110 | break; |
|
| - | 111 | } |
|
| 66 | ipc_callid_t callid2; |
112 | item = item->next; |
| - | 113 | } |
|
| - | 114 | ||
| - | 115 | if (item == &devices_list) { |
|
| - | 116 | printf("DevMap: no device named %s.\n", name); |
|
| - | 117 | return NULL; |
|
| - | 118 | } |
|
| - | 119 | ||
| - | 120 | device = list_get_instance(item, devmap_device_t, devices); |
|
| - | 121 | return device; |
|
| - | 122 | } |
|
| - | 123 | ||
| - | 124 | /** Find device with given handle. |
|
| - | 125 | * @todo: use hash table |
|
| - | 126 | */ |
|
| - | 127 | static devmap_device_t *devmap_device_find_handle(int handle) |
|
| - | 128 | { |
|
| 67 | size_t size; |
129 | link_t *item; |
| - | 130 | devmap_device_t *device = NULL; |
|
| - | 131 | ||
| - | 132 | futex_down(&devices_list_futex); |
|
| - | 133 | ||
| - | 134 | item = (&devices_list)->next; |
|
| - | 135 | ||
| - | 136 | while (item != &devices_list) { |
|
| - | 137 | ||
| - | 138 | device = list_get_instance(item, devmap_device_t, devices); |
|
| - | 139 | if (device->handle == handle) { |
|
| - | 140 | break; |
|
| - | 141 | } |
|
| - | 142 | item = item->next; |
|
| - | 143 | } |
|
| - | 144 | ||
| - | 145 | if (item == &devices_list) { |
|
| 68 | char buffer[DEVMAP_NAME_MAXLEN + 1]; |
146 | futex_up(&devices_list_futex); |
| - | 147 | return NULL; |
|
| - | 148 | } |
|
| - | 149 | ||
| - | 150 | device = list_get_instance(item, devmap_device_t, devices); |
|
| - | 151 | ||
| - | 152 | futex_up(&devices_list_futex); |
|
| - | 153 | ||
| - | 154 | return device; |
|
| - | 155 | } |
|
| - | 156 | ||
| - | 157 | /** Unregister device and free it. Its assumed that driver's device list |
|
| - | 158 | * is already locked. |
|
| - | 159 | * |
|
| - | 160 | */ |
|
| - | 161 | static int devmap_device_unregister_core(devmap_device_t *device) |
|
| - | 162 | { |
|
| - | 163 | ||
| - | 164 | list_remove(&(device->devices)); |
|
| - | 165 | list_remove(&(device->driver_devices)); |
|
| - | 166 | ||
| - | 167 | free(device->name); |
|
| - | 168 | free(device); |
|
| - | 169 | ||
| - | 170 | ||
| - | 171 | return EOK; |
|
| - | 172 | } |
|
| - | 173 | ||
| - | 174 | /** Read info about new driver and add it into linked list of registered drivers. |
|
| - | 175 | */ |
|
| - | 176 | static void devmap_driver_register(devmap_driver_t **odriver) |
|
| - | 177 | { |
|
| - | 178 | size_t name_size; |
|
| 69 | ipc_callid_t callid; |
179 | ipc_callid_t callid; |
| 70 | ipc_call_t call; |
180 | ipc_call_t call; |
| - | 181 | devmap_driver_t *driver; |
|
| - | 182 | ipc_callid_t iid; |
|
| 71 | int retval; |
183 | ipc_call_t icall; |
| - | 184 | ||
| - | 185 | *odriver = NULL; |
|
| 72 | 186 | ||
| - | 187 | iid = async_get_call(&icall); |
|
| - | 188 | ||
| 73 | if (ipc_data_receive(&callid, &call, NULL, &size) != 0) { |
189 | if (IPC_GET_METHOD(icall) != DEVMAP_DRIVER_REGISTER) { |
| - | 190 | ipc_answer_fast(iid, EREFUSED, 0, 0); |
|
| - | 191 | return; |
|
| - | 192 | } |
|
| - | 193 | ||
| - | 194 | if (NULL == (driver = (devmap_driver_t *)malloc(sizeof(devmap_driver_t)))) { |
|
| - | 195 | ipc_answer_fast(iid, ENOMEM, 0, 0); |
|
| 74 | // retval = |
196 | return; |
| 75 | } |
197 | } |
| 76 | 198 | ||
| 77 | if (size > DEVMAP_NAME_MAXLEN) { |
199 | /* |
| 78 | retval = ELIMIT; |
200 | * Get driver name |
| 79 | } else { |
201 | */ |
| 80 | ipc_data_deliver(callid2, &call, buffer, size); |
202 | if (!ipc_data_receive(&callid, &call, NULL, &name_size)) { |
| - | 203 | printf("Unexpected request: %u.\n", IPC_GET_METHOD(call)); |
|
| - | 204 | free(driver); |
|
| - | 205 | ipc_answer_fast(callid, EREFUSED, 0, 0); |
|
| 81 | buffer[DEVMAP_NAME_MAXLEN] = 0; |
206 | ipc_answer_fast(iid, EREFUSED, 0, 0); |
| - | 207 | return; |
|
| 82 | } |
208 | } |
| - | 209 | ||
| - | 210 | if (name_size > DEVMAP_NAME_MAXLEN) { |
|
| - | 211 | printf("Too logn name: %u: maximum is %u.\n", name_size, DEVMAP_NAME_MAXLEN); |
|
| - | 212 | free(driver); |
|
| - | 213 | ipc_answer_fast(callid, EINVAL, 0, 0); |
|
| - | 214 | ipc_answer_fast(iid, EREFUSED, 0, 0); |
|
| - | 215 | return; |
|
| - | 216 | } |
|
| - | 217 | ||
| - | 218 | /* |
|
| - | 219 | * Allocate buffer for device name. |
|
| - | 220 | */ |
|
| - | 221 | if (NULL == (driver->name = (char *)malloc(name_size + 1))) { |
|
| - | 222 | printf("Cannot allocate space for driver name.\n"); |
|
| - | 223 | free(driver); |
|
| - | 224 | ipc_answer_fast(callid, ENOMEM, 0, 0); |
|
| - | 225 | ipc_answer_fast(iid, EREFUSED, 0, 0); |
|
| - | 226 | return; |
|
| - | 227 | } |
|
| - | 228 | ||
| - | 229 | /* |
|
| - | 230 | * Send confirmation to sender and get data into buffer. |
|
| - | 231 | */ |
|
| - | 232 | if (EOK != ipc_data_deliver(callid, &call, driver->name, name_size)) { |
|
| - | 233 | printf("Cannot read driver name.\n"); |
|
| - | 234 | free(driver->name); |
|
| - | 235 | free(driver); |
|
| - | 236 | ipc_answer_fast(iid, EREFUSED, 0, 0); |
|
| - | 237 | return; |
|
| - | 238 | } |
|
| - | 239 | ||
| - | 240 | driver->name[name_size] = 0; |
|
| - | 241 | ||
| - | 242 | printf("Read driver name: '%s'.\n", driver->name); |
|
| - | 243 | ||
| - | 244 | /* Initialize futex for list of devices owned by this driver */ |
|
| - | 245 | futex_initialize(&(driver->devices_futex) ,1); |
|
| - | 246 | ||
| - | 247 | /* |
|
| - | 248 | * Initialize list of asociated devices |
|
| - | 249 | */ |
|
| - | 250 | list_initialize(&(driver->devices)); |
|
| - | 251 | ||
| - | 252 | /* |
|
| - | 253 | * Create connection to the driver |
|
| - | 254 | */ |
|
| - | 255 | callid = async_get_call(&call); |
|
| - | 256 | ||
| - | 257 | if (IPC_M_CONNECT_TO_ME != IPC_GET_METHOD(call)) { |
|
| - | 258 | printf("DevMap: Unexpected method: %u.\n", \ |
|
| - | 259 | IPC_GET_METHOD(call)); |
|
| - | 260 | ipc_answer_fast(callid, ENOTSUP, 0, 0); |
|
| - | 261 | ||
| - | 262 | free(driver->name); |
|
| - | 263 | free(driver); |
|
| - | 264 | ipc_answer_fast(iid, ENOTSUP, 0, 0); |
|
| - | 265 | return; |
|
| - | 266 | } |
|
| - | 267 | ||
| - | 268 | driver->phone = IPC_GET_ARG3(call); |
|
| - | 269 | ||
| - | 270 | ipc_answer_fast(callid, EOK, 0, 0); |
|
| - | 271 | ||
| - | 272 | list_initialize(&(driver->drivers)); |
|
| - | 273 | ||
| - | 274 | futex_down(&drivers_list_futex); |
|
| - | 275 | ||
| - | 276 | /* TODO: check that no driver with name equals to driver->name is registered */ |
|
| - | 277 | ||
| - | 278 | /* |
|
| - | 279 | * Insert new driver into list of registered drivers |
|
| - | 280 | */ |
|
| - | 281 | list_append(&(driver->drivers), &drivers_list); |
|
| - | 282 | futex_up(&drivers_list_futex); |
|
| - | 283 | ||
| - | 284 | ipc_answer_fast(iid, EOK, 0, 0); |
|
| - | 285 | printf("Driver registered.\n"); |
|
| - | 286 | ||
| - | 287 | *odriver = driver; |
|
| 83 | return EOK; |
288 | return; |
| 84 | } |
289 | } |
| 85 | 290 | ||
| - | 291 | /** Unregister device driver, unregister all its devices and free driver structure. |
|
| - | 292 | * |
|
| - | 293 | */ |
|
| 86 | static int devmap_unregister() |
294 | static int devmap_driver_unregister(devmap_driver_t *driver) |
| 87 | { |
295 | { |
| - | 296 | devmap_device_t *device; |
|
| - | 297 | ||
| - | 298 | if (NULL == driver) { |
|
| - | 299 | printf("Error: driver == NULL.\n"); |
|
| - | 300 | return EEXISTS; |
|
| - | 301 | } |
|
| - | 302 | ||
| - | 303 | printf("Unregister driver '%s'.\n", driver->name); |
|
| - | 304 | futex_down(&drivers_list_futex); |
|
| - | 305 | ||
| - | 306 | ipc_hangup(driver->phone); |
|
| - | 307 | ||
| - | 308 | /* remove it from list of drivers */ |
|
| - | 309 | list_remove(&(driver->drivers)); |
|
| - | 310 | ||
| - | 311 | /* unregister all its devices */ |
|
| - | 312 | ||
| - | 313 | futex_down(&devices_list_futex); |
|
| - | 314 | futex_down(&(driver->devices_futex)); |
|
| - | 315 | ||
| - | 316 | while (!list_empty(&(driver->devices))) { |
|
| - | 317 | device = list_get_instance(driver->devices.next, devmap_device_t, driver_devices); |
|
| - | 318 | printf("Unregister device '%s'.\n", device->name); |
|
| - | 319 | devmap_device_unregister_core(device); |
|
| - | 320 | } |
|
| - | 321 | ||
| - | 322 | futex_up(&(driver->devices_futex)); |
|
| - | 323 | futex_up(&devices_list_futex); |
|
| - | 324 | futex_up(&drivers_list_futex); |
|
| - | 325 | ||
| - | 326 | /* free name and driver */ |
|
| - | 327 | if (NULL != driver->name) { |
|
| - | 328 | free(driver->name); |
|
| - | 329 | } |
|
| - | 330 | ||
| - | 331 | free(driver); |
|
| - | 332 | ||
| - | 333 | printf("Driver unregistered.\n"); |
|
| - | 334 | ||
| 88 | return EOK; |
335 | return EOK; |
| 89 | } |
336 | } |
| 90 | 337 | ||
| - | 338 | ||
| - | 339 | /** Register instance of device |
|
| - | 340 | * |
|
| - | 341 | */ |
|
| 91 | static int devmap_forward(int handle, ipc_call_t *call, ipc_callid_t callid) |
342 | static void devmap_device_register(ipc_callid_t iid, ipc_call_t *icall, |
| - | 343 | devmap_driver_t *driver) |
|
| 92 | { |
344 | { |
| 93 | link_t *item; |
345 | ipc_callid_t callid; |
| 94 | ipcarg_t phone; |
346 | ipc_call_t call; |
| - | 347 | size_t size; |
|
| 95 | devmap_device_t *dev; |
348 | devmap_device_t *device; |
| 96 | 349 | ||
| - | 350 | if (NULL == driver) { |
|
| - | 351 | printf("Invalid driver registration.\n"); |
|
| - | 352 | ipc_answer_fast(iid, EREFUSED, 0, 0); |
|
| - | 353 | return; |
|
| - | 354 | } |
|
| - | 355 | ||
| - | 356 | /* Create new device entry */ |
|
| - | 357 | if (NULL == (device = (devmap_device_t *)malloc(sizeof(devmap_device_t)))) { |
|
| - | 358 | printf("Cannot allocate new device.\n"); |
|
| - | 359 | ipc_answer_fast(iid, ENOMEM, 0, 0); |
|
| - | 360 | return; |
|
| - | 361 | } |
|
| - | 362 | ||
| 97 | /* FIXME: add futex */ |
363 | /* Get device name */ |
| - | 364 | if (!ipc_data_receive(&callid, &call, NULL, &size)) { |
|
| - | 365 | free(device); |
|
| 98 | futex_down(&device_list_futex); |
366 | printf("Cannot read device name.\n"); |
| - | 367 | ipc_answer_fast(iid, EREFUSED, 0, 0); |
|
| - | 368 | return; |
|
| - | 369 | } |
|
| 99 | 370 | ||
| - | 371 | if (size > DEVMAP_NAME_MAXLEN) { |
|
| - | 372 | printf("Too long device name: %u.\n", size); |
|
| 100 | item = (&device_list)->next; |
373 | free(device); |
| - | 374 | ipc_answer_fast(callid, EINVAL, 0, 0); |
|
| - | 375 | ipc_answer_fast(iid, EREFUSED, 0, 0); |
|
| - | 376 | return; |
|
| - | 377 | } |
|
| 101 | 378 | ||
| - | 379 | /* +1 for terminating \0 */ |
|
| 102 | while (item != &device_list) { |
380 | device->name = (char *)malloc(size + 1); |
| 103 | 381 | ||
| 104 | dev = list_get_instance(item, devmap_device_t, list); |
382 | if (NULL == device->name) { |
| 105 | if (dev->handle == handle) { |
383 | printf("Cannot read device name.\n"); |
| 106 | break; |
384 | free(device); |
| 107 | } |
- | |
| - | 385 | ipc_answer_fast(callid, ENOMEM, 0, 0); |
|
| - | 386 | ipc_answer_fast(iid, EREFUSED, 0, 0); |
|
| 108 | item = item->next; |
387 | return; |
| 109 | } |
388 | } |
| - | 389 | ||
| - | 390 | ipc_data_deliver(callid, &call, device->name, size); |
|
| - | 391 | device->name[size] = 0; |
|
| 110 | 392 | ||
| - | 393 | list_initialize(&(device->devices)); |
|
| - | 394 | list_initialize(&(device->driver_devices)); |
|
| - | 395 | ||
| - | 396 | futex_down(&devices_list_futex); |
|
| - | 397 | ||
| - | 398 | /* Check that device with such name is not already registered */ |
|
| - | 399 | if (NULL != devmap_device_find_name(device->name)) { |
|
| - | 400 | printf("Device '%s' already registered.\n", device->name); |
|
| 111 | if (item == &device_list) { |
401 | futex_up(&devices_list_futex); |
| - | 402 | free(device->name); |
|
| - | 403 | free(device); |
|
| - | 404 | ipc_answer_fast(iid, EEXISTS, 0, 0); |
|
| 112 | return ENOENT; |
405 | return; |
| 113 | } |
406 | } |
| 114 | 407 | ||
| - | 408 | /* Get unique device handle */ |
|
| 115 | dev = list_get_instance(item, devmap_device_t, list); |
409 | device->handle = devmap_create_handle(); |
| - | 410 | ||
| 116 | phone = dev->phone; |
411 | device->driver = driver; |
| - | 412 | ||
| - | 413 | /* Insert device into list of all devices */ |
|
| - | 414 | list_append(&(device->devices), &devices_list); |
|
| 117 | 415 | ||
| - | 416 | /* Insert device into list of devices that belog to one driver */ |
|
| 118 | futex_up(&device_list_futex); |
417 | futex_down(&(device->driver->devices_futex)); |
| 119 | 418 | ||
| - | 419 | list_append(&(device->driver_devices), &(device->driver->devices)); |
|
| - | 420 | ||
| - | 421 | futex_up(&(device->driver->devices_futex)); |
|
| - | 422 | futex_up(&devices_list_futex); |
|
| - | 423 | ||
| - | 424 | printf("Device '%s' registered.\n", device->name); |
|
| 120 | return ipc_forward_fast(callid, phone, 0, 0); |
425 | ipc_answer_fast(iid, EOK, device->handle, 0); |
| - | 426 | ||
| - | 427 | return; |
|
| 121 | } |
428 | } |
| 122 | 429 | ||
| - | 430 | /** |
|
| - | 431 | * |
|
| - | 432 | */ |
|
| - | 433 | static int devmap_device_unregister(ipc_callid_t iid, ipc_call_t *icall, |
|
| 123 | static int devmap_get_handle() |
434 | devmap_driver_t *driver) |
| 124 | { |
435 | { |
| - | 436 | /* TODO */ |
|
| - | 437 | ||
| 125 | return EOK; |
438 | return EOK; |
| 126 | } |
439 | } |
| 127 | 440 | ||
| - | 441 | /** Connect client to the device. |
|
| - | 442 | * Find device driver owning requested device and forward |
|
| - | 443 | * the message to it. |
|
| - | 444 | * |
|
| - | 445 | * |
|
| - | 446 | */ |
|
| - | 447 | static void devmap_forward(ipc_callid_t callid, ipc_call_t *call) |
|
| - | 448 | { |
|
| - | 449 | devmap_device_t *dev; |
|
| - | 450 | int handle; |
|
| - | 451 | ||
| - | 452 | /* |
|
| - | 453 | * Get handle from request |
|
| - | 454 | */ |
|
| - | 455 | handle = IPC_GET_ARG1(*call); |
|
| - | 456 | dev = devmap_device_find_handle(handle); |
|
| - | 457 | ||
| - | 458 | if (NULL == dev) { |
|
| - | 459 | printf("DevMap: No registered device with handle %d.\n", handle); |
|
| - | 460 | ipc_answer_fast(callid, ENOENT, 0, 0); |
|
| - | 461 | return; |
|
| - | 462 | } |
|
| - | 463 | ||
| - | 464 | /* FIXME: is this correct method how to pass argument on forwarding ?*/ |
|
| - | 465 | ipc_forward_fast(callid, dev->driver->phone, (ipcarg_t)(dev->handle), 0); |
|
| - | 466 | return; |
|
| - | 467 | } |
|
| - | 468 | ||
| - | 469 | /** Find handle for device instance identified by name. |
|
| - | 470 | * In answer will be send EOK and device handle in arg1 or a error |
|
| - | 471 | * code from errno.h. |
|
| - | 472 | */ |
|
| - | 473 | static void devmap_get_handle(ipc_callid_t iid, ipc_call_t *icall) |
|
| - | 474 | { |
|
| - | 475 | char *name = NULL; |
|
| - | 476 | size_t name_size; |
|
| - | 477 | const devmap_device_t *dev; |
|
| - | 478 | ipc_callid_t callid; |
|
| - | 479 | ipc_call_t call; |
|
| - | 480 | ipcarg_t retval; |
|
| - | 481 | ||
| - | 482 | ||
| - | 483 | /* |
|
| - | 484 | * Wait for incoming message with device name (but do not |
|
| - | 485 | * read the name itself until the buffer is allocated). |
|
| - | 486 | */ |
|
| - | 487 | if (!ipc_data_receive(&callid, &call, NULL, &name_size)) { |
|
| - | 488 | ipc_answer_fast(callid, EREFUSED, 0, 0); |
|
| - | 489 | ipc_answer_fast(iid, EREFUSED, 0, 0); |
|
| - | 490 | return; |
|
| - | 491 | } |
|
| - | 492 | ||
| - | 493 | if (name_size > DEVMAP_NAME_MAXLEN) { |
|
| - | 494 | ipc_answer_fast(callid, EINVAL, 0, 0); |
|
| - | 495 | ipc_answer_fast(iid, EREFUSED, 0, 0); |
|
| - | 496 | return; |
|
| - | 497 | } |
|
| - | 498 | ||
| - | 499 | /* |
|
| - | 500 | * Allocate buffer for device name. |
|
| - | 501 | */ |
|
| - | 502 | if (NULL == (name = (char *)malloc(name_size))) { |
|
| - | 503 | ipc_answer_fast(callid, ENOMEM, 0, 0); |
|
| - | 504 | ipc_answer_fast(iid, EREFUSED, 0, 0); |
|
| - | 505 | return; |
|
| - | 506 | } |
|
| - | 507 | ||
| - | 508 | /* |
|
| - | 509 | * Send confirmation to sender and get data into buffer. |
|
| - | 510 | */ |
|
| - | 511 | if (EOK != (retval = ipc_data_deliver(callid, &call, name, name_size))) { |
|
| - | 512 | ipc_answer_fast(iid, EREFUSED, 0, 0); |
|
| - | 513 | return; |
|
| - | 514 | } |
|
| - | 515 | ||
| - | 516 | /* |
|
| - | 517 | * Find device name in linked list of known devices. |
|
| - | 518 | */ |
|
| - | 519 | dev = devmap_device_find_name(name); |
|
| - | 520 | ||
| - | 521 | /* |
|
| - | 522 | * Device was not found. |
|
| - | 523 | */ |
|
| - | 524 | if (NULL == dev) { |
|
| - | 525 | printf("DevMap: device %s has not been registered.\n", name); |
|
| - | 526 | ipc_answer_fast(iid, ENOENT, 0, 0); |
|
| - | 527 | return; |
|
| - | 528 | } |
|
| - | 529 | ||
| - | 530 | printf("DevMap: device %s has handler %d.\n", name, dev->handle); |
|
| - | 531 | ||
| - | 532 | ipc_answer_fast(iid, EOK, dev->handle, 0); |
|
| - | 533 | ||
| - | 534 | return; |
|
| - | 535 | } |
|
| - | 536 | ||
| - | 537 | /** Find name of device identified by id and send it to caller. |
|
| - | 538 | * |
|
| - | 539 | */ |
|
| - | 540 | static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall) |
|
| - | 541 | { |
|
| - | 542 | const devmap_device_t *device; |
|
| - | 543 | size_t name_size; |
|
| - | 544 | ||
| - | 545 | device = devmap_device_find_handle(IPC_GET_ARG1(*icall)); |
|
| - | 546 | ||
| - | 547 | /* |
|
| - | 548 | * Device not found. |
|
| - | 549 | */ |
|
| - | 550 | if (NULL == device) { |
|
| - | 551 | ipc_answer_fast(iid, ENOENT, 0, 0); |
|
| - | 552 | return; |
|
| - | 553 | } |
|
| - | 554 | ||
| - | 555 | ipc_answer_fast(iid, EOK, 0, 0); |
|
| - | 556 | ||
| - | 557 | name_size = strlen(device->name); |
|
| - | 558 | ||
| - | 559 | ||
| - | 560 | /* FIXME: |
|
| - | 561 | we have no channel from DevMap to client -> |
|
| - | 562 | sending must be initiated by client |
|
| - | 563 | ||
| - | 564 | int rc = ipc_data_send(phone, device->name, name_size); |
|
| - | 565 | if (rc != EOK) { |
|
| - | 566 | async_wait_for(req, NULL); |
|
| - | 567 | return rc; |
|
| - | 568 | } |
|
| - | 569 | */ |
|
| - | 570 | /* TODO: send name in response */ |
|
| - | 571 | ||
| - | 572 | return; |
|
| - | 573 | } |
|
| - | 574 | ||
| 128 | /** Function for handling connections to devmap |
575 | /** Handle connection with device driver. |
| 129 | * |
576 | * |
| 130 | */ |
577 | */ |
| 131 | static void |
578 | static void |
| 132 | devmap_client_connection(ipc_callid_t iid, ipc_call_t *icall) |
579 | devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall) |
| 133 | { |
580 | { |
| 134 | ipc_callid_t callid; |
581 | ipc_callid_t callid; |
| 135 | ipc_call_t call; |
582 | ipc_call_t call; |
| 136 | int retval; |
- | |
| 137 | bool cont = true; |
583 | bool cont = true; |
| - | 584 | devmap_driver_t *driver = NULL; |
|
| 138 | 585 | ||
| 139 | printf("DevMap: new connection."); |
586 | ipc_answer_fast(iid, EOK, 0, 0); |
| 140 | 587 | ||
| 141 | ipc_answer_fast(iid, EOK, 0, 0); /* Accept connection */ |
588 | devmap_driver_register(&driver); |
| 142 | 589 | ||
| - | 590 | if (NULL == driver) { |
|
| - | 591 | printf("DevMap: driver registration failed.\n"); |
|
| - | 592 | return; |
|
| - | 593 | } |
|
| - | 594 | ||
| 143 | while (cont) { |
595 | while (cont) { |
| 144 | callid = async_get_call(&call); |
596 | callid = async_get_call(&call); |
| 145 | 597 | ||
| 146 | switch (IPC_GET_METHOD(call)) { |
598 | switch (IPC_GET_METHOD(call)) { |
| 147 | case IPC_M_PHONE_HUNGUP: |
599 | case IPC_M_PHONE_HUNGUP: |
| 148 | /* TODO: if its a device connection, remove it from table */ |
- | |
| 149 | devmap_unregister(); |
- | |
| 150 | printf("DevMap: connection hung up."); |
600 | printf("DevMap: connection hung up.\n"); |
| 151 | cont = false; |
601 | cont = false; |
| 152 | continue; /* Exit thread */ |
602 | continue; /* Exit thread */ |
| 153 | - | ||
| 154 | case DEVMAP_REGISTER: |
603 | case DEVMAP_DRIVER_UNREGISTER: |
| - | 604 | printf("DevMap: unregister driver.\n"); |
|
| 155 | 605 | if (NULL == driver) { |
|
| 156 | if ((retval = devmap_register()) != EOK) { |
606 | printf("DevMap: driver was not registered!\n"); |
| - | 607 | ipc_answer_fast(callid, ENOENT, 0, 0); |
|
| 157 | cont = false; |
608 | } else { |
| - | 609 | ipc_answer_fast(callid, EOK, 0, 0); |
|
| 158 | } |
610 | } |
| 159 | break; |
611 | break; |
| 160 | case DEVMAP_UNREGISTER: |
612 | case DEVMAP_DEVICE_REGISTER: |
| 161 | /* TODO: remove device (if registred) */ |
613 | /* Register one instance of device */ |
| - | 614 | devmap_device_register(callid, &call, driver); |
|
| - | 615 | break; |
|
| - | 616 | case DEVMAP_DEVICE_UNREGISTER: |
|
| - | 617 | /* Remove instance of device identified by handler */ |
|
| 162 | retval = devmap_unregister(); |
618 | devmap_device_unregister(callid, &call, driver); |
| - | 619 | break; |
|
| - | 620 | case DEVMAP_DEVICE_GET_HANDLE: |
|
| - | 621 | devmap_get_handle(callid, &call); |
|
| 163 | cont = false; |
622 | break; |
| - | 623 | case DEVMAP_DEVICE_GET_NAME: |
|
| - | 624 | devmap_get_handle(callid, &call); |
|
| 164 | break; |
625 | break; |
| - | 626 | default: |
|
| - | 627 | if (!(callid & IPC_CALLID_NOTIFICATION)) { |
|
| - | 628 | ipc_answer_fast(callid, ENOENT, 0, 0); |
|
| - | 629 | } |
|
| - | 630 | } |
|
| - | 631 | } |
|
| - | 632 | ||
| - | 633 | if (NULL != driver) { |
|
| - | 634 | /* |
|
| - | 635 | * Unregister the device driver and all its devices. |
|
| - | 636 | */ |
|
| - | 637 | devmap_driver_unregister(driver); |
|
| - | 638 | driver = NULL; |
|
| - | 639 | } |
|
| - | 640 | ||
| - | 641 | } |
|
| - | 642 | ||
| - | 643 | /** Handle connection with device client. |
|
| - | 644 | * |
|
| - | 645 | */ |
|
| - | 646 | static void |
|
| - | 647 | devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall) |
|
| - | 648 | { |
|
| - | 649 | ipc_callid_t callid; |
|
| - | 650 | ipc_call_t call; |
|
| - | 651 | bool cont = true; |
|
| - | 652 | ||
| - | 653 | ipc_answer_fast(iid, EOK, 0, 0); /* Accept connection */ |
|
| - | 654 | ||
| - | 655 | while (cont) { |
|
| - | 656 | callid = async_get_call(&call); |
|
| - | 657 | ||
| - | 658 | switch (IPC_GET_METHOD(call)) { |
|
| 165 | case DEVMAP_CONNECT_TO_DEVICE: |
659 | case IPC_M_PHONE_HUNGUP: |
| 166 | retval = devmap_forward(IPC_GET_ARG1(call), &call, callid); |
660 | printf("DevMap: connection hung up.\n"); |
| 167 | cont = false; |
661 | cont = false; |
| - | 662 | continue; /* Exit thread */ |
|
| - | 663 | ||
| - | 664 | case DEVMAP_DEVICE_CONNECT_ME_TO: |
|
| - | 665 | /* Connect client to selected device */ |
|
| - | 666 | printf("DevMap: connect to device %d.\n", IPC_GET_ARG1(call)); |
|
| - | 667 | devmap_forward(callid, &call); |
|
| - | 668 | break; |
|
| - | 669 | ||
| - | 670 | case DEVMAP_DEVICE_GET_HANDLE: |
|
| - | 671 | devmap_get_handle(callid, &call); |
|
| - | 672 | ||
| 168 | break; |
673 | break; |
| 169 | case DEVMAP_GET_HANDLE: |
674 | case DEVMAP_DEVICE_GET_NAME: |
| 170 | 675 | /* TODO */ |
|
| - | 676 | devmap_get_name(callid, &call); |
|
| 171 | break; |
677 | break; |
| 172 | default: |
678 | default: |
| - | 679 | if (!(callid & IPC_CALLID_NOTIFICATION)) { |
|
| 173 | retval = ENOENT; |
680 | ipc_answer_fast(callid, ENOENT, 0, 0); |
| - | 681 | } |
|
| 174 | } |
682 | } |
| 175 | ipc_answer_fast(callid, retval, 0, 0); |
- | |
| 176 | } |
683 | } |
| 177 | - | ||
| 178 | printf("DevMap: connection closed."); |
- | |
| 179 | return; |
- | |
| 180 | } |
684 | } |
| 181 | 685 | ||
| - | 686 | /** Function for handling connections to devmap |
|
| - | 687 | * |
|
| - | 688 | */ |
|
| - | 689 | static void |
|
| - | 690 | devmap_connection(ipc_callid_t iid, ipc_call_t *icall) |
|
| - | 691 | { |
|
| - | 692 | ||
| - | 693 | printf("DevMap: new connection.\n"); |
|
| - | 694 | ||
| - | 695 | /* Select interface */ |
|
| - | 696 | switch ((ipcarg_t)(IPC_GET_ARG1(*icall))) { |
|
| - | 697 | case DEVMAP_DRIVER: |
|
| - | 698 | devmap_connection_driver(iid, icall); |
|
| - | 699 | break; |
|
| - | 700 | case DEVMAP_CLIENT: |
|
| - | 701 | devmap_connection_client(iid, icall); |
|
| - | 702 | break; |
|
| - | 703 | default: |
|
| - | 704 | ipc_answer_fast(iid, ENOENT, 0, 0); /* No such interface */ |
|
| - | 705 | printf("DevMap: Unknown interface %u.\n", \ |
|
| - | 706 | (ipcarg_t)(IPC_GET_ARG1(*icall))); |
|
| - | 707 | } |
|
| - | 708 | ||
| - | 709 | /* Cleanup */ |
|
| - | 710 | ||
| - | 711 | printf("DevMap: connection closed.\n"); |
|
| - | 712 | return; |
|
| - | 713 | } |
|
| 182 | 714 | ||
| - | 715 | /** |
|
| - | 716 | * |
|
| - | 717 | */ |
|
| 183 | int main(int argc, char *argv[]) |
718 | int main(int argc, char *argv[]) |
| 184 | { |
719 | { |
| 185 | - | ||
| 186 | ipcarg_t phonead; |
720 | ipcarg_t phonead; |
| 187 | 721 | ||
| 188 | printf("DevMap: HelenOS device mapper.\n"); |
722 | printf("DevMap: HelenOS device mapper.\n"); |
| 189 | 723 | ||
| 190 | if (devmap_init() != 0) { |
724 | if (devmap_init() != 0) { |
| 191 | printf("Error while initializing DevMap service."); |
725 | printf("Error while initializing DevMap service.\n"); |
| 192 | return -1; |
726 | return -1; |
| 193 | } |
727 | } |
| 194 | 728 | ||
| 195 | /* Set a handler of incomming connections */ |
729 | /* Set a handler of incomming connections */ |
| 196 | async_set_client_connection(devmap_client_connection); |
730 | async_set_client_connection(devmap_connection); |
| 197 | 731 | ||
| 198 | /* Register device mapper at naming service */ |
732 | /* Register device mapper at naming service */ |
| 199 | if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, &phonead) != 0) |
733 | if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, &phonead) != 0) |
| 200 | return -1; |
734 | return -1; |
| 201 | 735 | ||