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 |