clip.c

00001 /*
00002  * Copyright (c) 2009 Martin Decky
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00029 #include <stdio.h>
00030 #include <bool.h>
00031 #include <async.h>
00032 #include <ipc/ns.h>
00033 #include <ipc/services.h>
00034 #include <ipc/clipboard.h>
00035 #include <malloc.h>
00036 #include <fibril_synch.h>
00037 #include <errno.h>
00038 
00039 #define NAME  "clip"
00040 
00041 static char *clip_data = NULL;
00042 static size_t clip_size = 0;
00043 static clipboard_tag_t clip_tag = CLIPBOARD_TAG_NONE;
00044 static FIBRIL_MUTEX_INITIALIZE(clip_mtx);
00045 
00046 static void clip_put_data(ipc_callid_t rid, ipc_call_t *request)
00047 {
00048         char *data;
00049         int rc;
00050         size_t size;
00051         
00052         switch (IPC_GET_ARG1(*request)) {
00053         case CLIPBOARD_TAG_NONE:
00054                 fibril_mutex_lock(&clip_mtx);
00055                 
00056                 if (clip_data)
00057                         free(clip_data);
00058                 
00059                 clip_data = NULL;
00060                 clip_size = 0;
00061                 clip_tag = CLIPBOARD_TAG_NONE;
00062                 
00063                 fibril_mutex_unlock(&clip_mtx);
00064                 async_answer_0(rid, EOK);
00065                 break;
00066         case CLIPBOARD_TAG_DATA:
00067                 rc = async_data_write_accept((void **) &data, false, 0, 0, 0, &size);
00068                 if (rc != EOK) {
00069                         async_answer_0(rid, rc);
00070                         break;
00071                 }
00072                 
00073                 fibril_mutex_lock(&clip_mtx);
00074                 
00075                 if (clip_data)
00076                         free(clip_data);
00077                 
00078                 clip_data = data;
00079                 clip_size = size;
00080                 clip_tag = CLIPBOARD_TAG_DATA;
00081                 
00082                 fibril_mutex_unlock(&clip_mtx);
00083                 async_answer_0(rid, EOK);
00084                 break;
00085         default:
00086                 async_answer_0(rid, EINVAL);
00087         }
00088 }
00089 
00090 static void clip_get_data(ipc_callid_t rid, ipc_call_t *request)
00091 {
00092         fibril_mutex_lock(&clip_mtx);
00093         
00094         ipc_callid_t callid;
00095         size_t size;
00096         
00097         /* Check for clipboard data tag compatibility */
00098         switch (IPC_GET_ARG1(*request)) {
00099         case CLIPBOARD_TAG_DATA:
00100                 if (!async_data_read_receive(&callid, &size)) {
00101                         async_answer_0(callid, EINVAL);
00102                         async_answer_0(rid, EINVAL);
00103                         break;
00104                 }
00105                 
00106                 if (clip_tag != CLIPBOARD_TAG_DATA) {
00107                         /* So far we only understand binary data */
00108                         async_answer_0(callid, EOVERFLOW);
00109                         async_answer_0(rid, EOVERFLOW);
00110                         break;
00111                 }
00112                 
00113                 if (clip_size != size) {
00114                         /* The client expects different size of data */
00115                         async_answer_0(callid, EOVERFLOW);
00116                         async_answer_0(rid, EOVERFLOW);
00117                         break;
00118                 }
00119                 
00120                 sysarg_t retval = async_data_read_finalize(callid, clip_data, size);
00121                 if (retval != EOK) {
00122                         async_answer_0(rid, retval);
00123                         break;
00124                 }
00125                 
00126                 async_answer_0(rid, EOK);
00127         default:
00128                 /*
00129                  * Sorry, we don't know how to get unknown or NONE
00130                  * data from the clipbard
00131                  */
00132                 async_answer_0(rid, EINVAL);
00133                 break;
00134         }
00135         
00136         fibril_mutex_unlock(&clip_mtx);
00137 }
00138 
00139 static void clip_content(ipc_callid_t rid, ipc_call_t *request)
00140 {
00141         fibril_mutex_lock(&clip_mtx);
00142         
00143         size_t size = clip_size;
00144         clipboard_tag_t tag = clip_tag;
00145         
00146         fibril_mutex_unlock(&clip_mtx);
00147         async_answer_2(rid, EOK, (sysarg_t) size, (sysarg_t) tag);
00148 }
00149 
00150 static void clip_connection(ipc_callid_t iid, ipc_call_t *icall)
00151 {
00152         /* Accept connection */
00153         async_answer_0(iid, EOK);
00154         
00155         bool cont = true;
00156         while (cont) {
00157                 ipc_call_t call;
00158                 ipc_callid_t callid = async_get_call(&call);
00159                 
00160                 switch (IPC_GET_IMETHOD(call)) {
00161                 case IPC_M_PHONE_HUNGUP:
00162                         cont = false;
00163                         continue;
00164                 case CLIPBOARD_PUT_DATA:
00165                         clip_put_data(callid, &call);
00166                         break;
00167                 case CLIPBOARD_GET_DATA:
00168                         clip_get_data(callid, &call);
00169                         break;
00170                 case CLIPBOARD_CONTENT:
00171                         clip_content(callid, &call);
00172                         break;
00173                 default:
00174                         async_answer_0(callid, ENOENT);
00175                 }
00176         }
00177 }
00178 
00179 int main(int argc, char *argv[])
00180 {
00181         printf(NAME ": HelenOS clipboard service\n");
00182         
00183         async_set_client_connection(clip_connection);
00184         
00185         if (service_register(SERVICE_CLIPBOARD) != EOK)
00186                 return -1;
00187         
00188         printf(NAME ": Accepting connections\n");
00189         async_manager();
00190         
00191         /* Never reached */
00192         return 0;
00193 }

Generated on Thu Jun 2 07:45:49 2011 for HelenOS/USB by  doxygen 1.4.7