/* * Copyright (c) 2011 Martin Decky * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @addtogroup mouse_proto * @ingroup input * @{ */ /** * @file * @brief Mouse device connector controller driver. */ #include #include #include #include #include #include #include #include #include #include #include /** Mousedev softstate */ typedef struct { /** Link to generic mouse device */ mouse_dev_t *mouse_dev; /** Session to mouse device */ async_sess_t *sess; /** File descriptor of open mousedev device */ int fd; } mousedev_t; static mousedev_t *mousedev_new(mouse_dev_t *mdev) { mousedev_t *mousedev = calloc(1, sizeof(mousedev_t)); if (mousedev == NULL) return NULL; mousedev->mouse_dev = mdev; mousedev->fd = -1; return mousedev; } static void mousedev_destroy(mousedev_t *mousedev) { if (mousedev->sess != NULL) async_hangup(mousedev->sess); if (mousedev->fd >= 0) close(mousedev->fd); free(mousedev); } static void mousedev_callback_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg) { /* Mousedev device structure */ mousedev_t *mousedev = (mousedev_t *) arg; while (true) { ipc_call_t call; ipc_callid_t callid = async_get_call(&call); if (!IPC_GET_IMETHOD(call)) { /* XXX Handle hangup */ return; } int retval; switch (IPC_GET_IMETHOD(call)) { case MOUSEEV_MOVE_EVENT: mouse_push_event_move(mousedev->mouse_dev, IPC_GET_ARG1(call), IPC_GET_ARG2(call)); retval = EOK; break; case MOUSEEV_BUTTON_EVENT: mouse_push_event_button(mousedev->mouse_dev, IPC_GET_ARG1(call), IPC_GET_ARG2(call)); retval = EOK; break; default: retval = ENOTSUP; break; } async_answer_0(callid, retval); } } static int mousedev_proto_init(mouse_dev_t *mdev) { const char *pathname = mdev->dev_path; int fd = open(pathname, O_RDWR); if (fd < 0) return -1; async_sess_t *sess = fd_session(EXCHANGE_SERIALIZE, fd); if (sess == NULL) { printf("%s: Failed starting session with '%s'\n", NAME, pathname); close(fd); return -1; } mousedev_t *mousedev = mousedev_new(mdev); if (mousedev == NULL) { printf("%s: Failed allocating device structure for '%s'.\n", NAME, pathname); return -1; } mousedev->fd = fd; mousedev->sess = sess; async_exch_t *exch = async_exchange_begin(sess); if (exch == NULL) { printf("%s: Failed starting exchange with '%s'.\n", NAME, pathname); mousedev_destroy(mousedev); return -1; } int rc = async_connect_to_me(exch, 0, 0, 0, mousedev_callback_conn, mousedev); async_exchange_end(exch); if (rc != EOK) { printf("%s: Failed creating callback connection from '%s'.\n", NAME, pathname); mousedev_destroy(mousedev); return -1; } return 0; } mouse_proto_ops_t mousedev_proto = { .init = mousedev_proto_init }; /** * @} */