1. Changed license copyright year
[apps/core/preloaded/print-service.git] / src / pt_printer.c
1 /*
2 *  Printservice
3 *
4 * Copyright 2012-2013  Samsung Electronics Co., Ltd
5
6 * Licensed under the Flora License, Version 1.1 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9
10 * http://floralicense.org/license/
11
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20 #define _GNU_SOURCE
21 #include <sys/types.h>
22 #include <app.h>
23 #include <stdbool.h>
24 #include <glib.h>
25
26 #include "pt_debug.h"
27 #include "pt_common.h"
28 #include "pt_ppd.h"
29 #include "pt_printer.h"
30 #include "pt_utils.h"
31
32 #define PREFERENCE_DEFAULT_PRINTER_NAME "mobileprint_default_printer_name"
33 #define PREFERENCE_DEFAULT_PRINTER_ADDRESS "mobileprint_default_printer_address"
34 #define PREFERENCE_DEFAULT_PRINTER_MFG "mobileprint_default_printer_mfg"
35 #define PREFERENCE_DEFAULT_PRINTER_MDL "mobileprint_default_printer_mdl"
36
37 static void g_printer_data_destroy(gconstpointer a)
38 {
39         free((char *)a);
40 }
41
42 static gboolean __printer_compare(gconstpointer a, gconstpointer b)
43 {
44         pt_printer_info_t *printer_a = (pt_printer_info_t *)a;
45         pt_printer_info_t *printer_b = (pt_printer_info_t *)b;
46         PT_RETV_IF(a==NULL || b==NULL, FALSE, "a or b is NULL");
47
48         if (strcmp(printer_a->device_uri, printer_b->device_uri) == 0) {
49                 return TRUE;
50         } else if (!strncmp(printer_a->device_uri, "dnssd:",6) && !strncmp(printer_b->device_uri, "dnssd:",6)) {
51                 if (strcmp(printer_a->device_info, printer_b->device_info) == 0) {
52                         return TRUE;
53                 } else {
54                         return FALSE;
55                 }
56         }
57         return FALSE;
58 }
59
60 static pt_printer_info_t *pt_util_make_printer_info(const char *device_info,
61                 const char *device_make_and_model,
62                 const char *device_uri)
63 {
64         pt_printer_info_t *localdetail = NULL;
65         localdetail = (pt_printer_info_t *)malloc(sizeof(pt_printer_info_t));
66         PT_RETV_IF(localdetail == NULL, NULL, "localdetail is NULL");
67         memset(localdetail, 0, sizeof(pt_printer_info_t));
68
69         char *device_mfg = NULL;
70         char *device_mdl = NULL;
71         char *device_name = NULL;
72         int ret = 0;
73         ret = pt_utils_get_mfg_mdl(device_make_and_model, &device_mfg, &device_mdl);
74         if (ret != PT_ERR_NONE) {
75                 PT_IF_FREE_MEM(localdetail);
76                 PT_IF_FREE_MEM(device_mfg);
77                 PT_IF_FREE_MEM(device_mdl);
78                 PT_DEBUG("ERROR : %d in pt_utils_get_mfg_mdl", ret);
79                 return NULL;
80         }
81         if (device_mfg == NULL) {
82                 PT_IF_FREE_MEM(localdetail);
83                 PT_IF_FREE_MEM(device_mdl);
84                 PT_DEBUG("device_mfg == NULL");
85                 return NULL;
86         }
87         if (device_mdl == NULL) {
88                 PT_IF_FREE_MEM(localdetail);
89                 PT_IF_FREE_MEM(device_mfg);
90                 PT_DEBUG("device_mdl == NULL");
91                 return NULL;
92         }
93
94         device_name = calloc(1, strlen(device_mfg)+strlen(device_mdl)+2);
95         if (device_name == NULL) {
96                 PT_IF_FREE_MEM(localdetail);
97                 PT_IF_FREE_MEM(device_mfg);
98                 PT_IF_FREE_MEM(device_mdl);
99                 PT_DEBUG("No memory. calloc failed");
100                 return NULL;
101         }
102
103         strncat(device_name,device_mfg,strlen(device_mfg));
104         strncat(device_name," ",1);
105         strncat(device_name,device_mdl,strlen(device_mdl));
106
107         strncpy(localdetail->model_name, device_mdl, sizeof(localdetail->model_name)-1);
108         strncpy(localdetail->manufacturer, device_mfg, sizeof(localdetail->manufacturer)-1);
109         strncpy(localdetail->product_ui_name, device_name, sizeof(localdetail->product_ui_name)-1);
110         __standardization(localdetail->product_ui_name);
111         strncpy(localdetail->device_uri, device_uri, sizeof(localdetail->device_uri)-1);
112         strncpy(localdetail->device_info, device_info, sizeof(localdetail->device_info)-1);
113
114         PT_IF_FREE_MEM(device_mfg);
115         PT_IF_FREE_MEM(device_mdl);
116         PT_IF_FREE_MEM(device_name);
117
118         return localdetail;
119 }
120
121 static void pt_util_add_printer_to_hashlist(GHashTable *printer_hashlist, pt_printer_info_t *printer)
122 {
123         PT_RET_IF(printer == NULL, "printer is NULL");
124         PT_RET_IF(printer_hashlist == NULL, "printer_hashlist is NULL");
125
126         pt_printer_info_t *tempdetail = NULL;
127         tempdetail = (pt_printer_info_t *) g_hash_table_lookup(printer_hashlist, printer);
128
129         if (NULL == tempdetail) {
130                 g_hash_table_insert(printer_hashlist, printer, printer);
131                 PT_DEBUG("Added printer_hashlist: %s", printer->device_uri);
132         } else {
133                 if (strstr(tempdetail->device_uri, "_printer.") && strstr(printer->device_uri, "_ipp.")) {
134                         g_hash_table_replace(printer_hashlist, printer, printer);
135                         PT_DEBUG("Replaced printer_hashlist: %s", printer->device_uri);
136                 } else if (strstr(tempdetail->device_uri, "_pdl-datastream.") &&
137                                    (strstr(printer->device_uri, "_printer.") || strstr(printer->device_uri, "_ipp."))) {
138                         g_hash_table_replace(printer_hashlist, printer, printer);
139                         PT_DEBUG("Replaced printer_hashlist: %s", printer->device_uri);
140                 }
141         }
142 }
143
144 static int compare_printer(pt_printer_mgr_t *printer_a, pt_printer_mgr_t *printer_b)
145 {
146         if (printer_a->is_ppd_exist == TRUE && printer_b->is_ppd_exist == FALSE) {
147                 return -1;
148         } else if (printer_a->is_ppd_exist == FALSE && printer_b->is_ppd_exist == TRUE) {
149                 return 1;
150         } else {
151                 if (strcmp(printer_a->name, printer_b->name) != 0) {
152                         return strcmp(printer_a->name, printer_b->name);
153                 }
154                 else {
155                         return strcmp(printer_a->address, printer_b->address);
156                 }
157         }
158 }
159
160 static void pt_util_append_printer(pt_search_data_t *search_data, GHashTable *printer_hashlist)
161 {
162         GHashTableIter iter;
163         gpointer key, value;
164         pt_printer_info_t *printer_temp = NULL;
165         Eina_Compare_Cb cmp_func = (Eina_Compare_Cb)compare_printer;
166
167         g_hash_table_iter_init(&iter, printer_hashlist);
168         while (g_hash_table_iter_next(&iter, &key, &value)) {
169                 printer_temp = (pt_printer_info_t *)malloc(sizeof(pt_printer_info_t));
170                 PT_RET_IF(printer_temp == NULL, "printer_temp is NULL");
171                 memset(printer_temp, 0, sizeof(pt_printer_info_t));
172                 memcpy(printer_temp, value, sizeof(pt_printer_info_t));
173                 search_data->pt_local_list = eina_list_append(search_data->pt_local_list, (pt_printer_info_t *)printer_temp);
174                 if (eina_error_get()) {
175                         PT_DEBUG("Failed to add eina_list for search_data->pt_local_list");
176                 }
177         }
178
179         /* add searched printer */
180         Eina_List *cursor = NULL;
181         pt_printer_info_t *it = NULL;
182         pt_printer_mgr_t *detail = NULL;
183
184         //TODO:: free ( search_data->response_data.printerlist );  -- dwmax
185         search_data->response_data.printerlist = NULL;
186
187         Eina_Bool bfirst = EINA_TRUE;
188         /* add printer to response list */
189         EINA_LIST_FOREACH(search_data->pt_local_list, cursor, it) {
190                 detail = (pt_printer_mgr_t *)malloc(sizeof(pt_printer_mgr_t));
191                 if (detail != NULL) {
192                         memset(detail, 0, sizeof(pt_printer_mgr_t));
193                         detail->copies = 1;
194                         strncpy(detail->name, it->product_ui_name, PT_MAX_LENGTH -1);
195                         strncpy(detail->address, it->device_uri, PT_MAX_LENGTH -1);
196                         strncpy(detail->mdl, it->model_name, PT_MAX_LENGTH -1);
197                         strncpy(detail->mfg, it->manufacturer, PT_MAX_LENGTH -1);
198                         PT_DEBUG("product %s",it->product_ui_name);
199                         PT_DEBUG("url %s",it->device_uri);
200                         PT_DEBUG("mdl %s",it->model_name);
201                         PT_DEBUG("mfg %s",it->manufacturer);
202
203                         if (EINA_TRUE == bfirst) {
204                                 bfirst = EINA_FALSE;
205                         }
206
207                         if (pt_get_printer_ppd(detail) != PT_ERR_NONE) {
208                                 //Unsupported Printer
209                                 detail->is_ppd_exist = FALSE;
210                         } else {
211                                 detail->is_ppd_exist = TRUE;
212                         }
213
214 //                      search_data->response_data.printerlist = eina_list_append(search_data->response_data.printerlist, detail);
215                         search_data->response_data.printerlist = eina_list_sorted_insert(search_data->response_data.printerlist, cmp_func,detail);
216                         if (eina_error_get()) {
217                                 PT_DEBUG("Failed to add eina_list for search_data->response_data.printerlist");
218                         }
219                 }
220         }
221
222 }
223
224 static void searching_thread_notify_cb(void *data, Ecore_Thread *thread, void *msg_data)
225 {
226         PRINT_SERVICE_FUNC_ENTER;
227         PT_RET_IF(data == NULL, "data is NULL");
228         PT_RET_IF(msg_data == NULL, "msg_data is NULL");
229         PT_DEBUG("Thread is sent msg successfully.");
230
231         pt_search_data_t        *search_data    = NULL;
232         ipp_t                   *response               = NULL;
233
234         search_data = (pt_search_data_t *)data;
235         response = (ipp_t *)msg_data;
236
237         PT_RET_IF(search_data->user_cb == NULL, "user_cb is NULL");
238
239         GHashTable *printer_hashlist = g_hash_table_new_full(g_str_hash, __printer_compare, NULL, (GDestroyNotify)g_printer_data_destroy);
240
241         ipp_attribute_t *attr                           = NULL;
242         const char *device_uri                  = NULL; /* device-uri attribute value */
243         const char *device_info                         = NULL; /* device-info value */
244         const char *device_make_and_model       = NULL; /* device-make-and-model value */
245
246         for (attr = ippFirstAttribute(response); attr != NULL; attr = ippNextAttribute(response)) {
247
248
249                 if (ippGetGroupTag(attr) == IPP_TAG_ZERO) {
250                         PT_DEBUG("-----------------------------------------");
251                 } else if (ippGetGroupTag(attr) != IPP_TAG_PRINTER) {
252                         continue;
253                 } else if (!strcmp(ippGetName(attr), "device-info") && ippGetValueTag(attr) == IPP_TAG_TEXT) {
254                         device_info = ippGetString(attr, 0, NULL);
255                 } else if (!strcmp(ippGetName(attr), "device-make-and-model") && ippGetValueTag(attr) == IPP_TAG_TEXT) {
256                         device_make_and_model = ippGetString(attr, 0, NULL);
257                 } else if (!strcmp(ippGetName(attr), "device-uri") && ippGetValueTag(attr) == IPP_TAG_URI) {
258                         device_uri = ippGetString(attr, 0, NULL);
259                 } else {
260                         continue;
261                 }
262
263                 if (device_info == NULL || device_make_and_model == NULL
264                                 || device_uri == NULL) {
265                         continue;
266                 } else if (strcasestr(device_uri, "usb://") ||
267                                    strstr(device_uri,"_pdl-datastream.") ||
268                                    strstr(device_uri,"_ipp.") ||
269                                    strstr(device_uri,"_printer.")) {
270                         pt_printer_info_t *localdetail = NULL;
271                         localdetail = pt_util_make_printer_info(device_info, device_make_and_model, device_uri);
272                         pt_util_add_printer_to_hashlist(printer_hashlist, localdetail);
273                 } else {
274                         PT_DEBUG("the device has another scheme such as socket");
275                 }
276
277                 device_info                             = NULL;
278                 device_uri                              = NULL;
279                 device_make_and_model   = NULL;
280
281         }
282
283         pt_util_append_printer(search_data, printer_hashlist);
284         g_hash_table_destroy(printer_hashlist);
285         ippDelete(response);
286
287         search_data->user_cb(&search_data->response_data);
288
289         PRINT_SERVICE_FUNC_LEAVE;
290 }
291
292 static void searching_thread_end_cb(void *data, Ecore_Thread *thread)
293 {
294         PRINT_SERVICE_FUNC_ENTER;
295         g_pt_info->searching_state = PT_SEARCH_END;
296         PT_DEBUG("Thread is completed successfully.");
297         PRINT_SERVICE_FUNC_LEAVE;
298 }
299
300 static void searching_thread_cancel_cb(void *data, Ecore_Thread *thread)
301 {
302         PRINT_SERVICE_FUNC_ENTER;
303         PT_DEBUG("Thread is canceled successfully.");
304         PRINT_SERVICE_FUNC_LEAVE;
305 }
306
307 static void searching_thread(void *data, Ecore_Thread *thread)
308 {
309         PRINT_SERVICE_FUNC_ENTER;
310         PT_RET_IF(data == NULL, "data is NULL");
311         PT_RET_IF(thread == NULL, "thread is NULL");
312
313         http_t *http                            = NULL;
314         ipp_t *request                  = NULL;
315         ipp_t *response                         = NULL;
316         int connection_status           = 0;
317         int ret                                         = -1;
318         char *exclude_schemes[] = {
319                 "http",
320                 "https",
321                 "ipp",
322                 "ipp15",
323                 "ipps",
324                 "lpd",
325                 "smb",
326                 "snmp",
327                 "socket",
328                 NULL,
329                 NULL
330         };
331         int num_schemes = 9;
332
333         http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
334         PT_RET_IF(http == NULL, "unable to connect server");
335
336         request = ippNewRequest(CUPS_GET_DEVICES);
337         PT_RET_IF(request == NULL, "unable to create request");
338
339         ret = pt_get_connection_status(&connection_status);
340
341         if (ret != PT_ERR_NONE) {
342                 ippDelete(request);
343                 PT_DEBUG("unable to get connection status");
344         }
345
346         if ((connection_status & PT_CONNECTION_USB) == 0) {
347                 exclude_schemes[num_schemes++] = "usb";
348         }
349         if ((connection_status & PT_CONNECTION_WIFI) == 0 &&
350                         (connection_status & PT_CONNECTION_WIFI_DIRECT) == 0) {
351                 exclude_schemes[num_schemes++] = "dnssd";
352         }
353
354         ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "exclude-schemes",
355                                   num_schemes ,NULL, exclude_schemes);
356         ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "timeout",5);
357
358         if ((response = cupsDoRequest(http, request, "/")) != NULL) {
359                 PT_DEBUG("CUPS_GET_DEVICES (%s)",cupsLastErrorString());
360                 if (g_pt_info->searching_state == PT_SEARCH_CANCEL) {
361                         ippDelete(response);
362                         goto canceled;
363                 }
364
365                 if (ecore_thread_feedback(thread, (const void *)response) == EINA_FALSE) {
366                         PT_DEBUG("Failed to send data to main loop");
367                         ippDelete(response);
368                 }
369         } else {
370                 PT_DEBUG("CUPS_GET_DEVICES (%s)", cupsLastErrorString());
371         }
372 canceled:
373         httpClose(http);
374         PRINT_SERVICE_FUNC_LEAVE;
375 }
376
377 static void __pt_get_printers(pt_search_data_t *data)
378 {
379         PRINT_SERVICE_FUNC_ENTER;
380
381         g_pt_info->searching_thd_hdl = ecore_thread_feedback_run(
382                                                                            searching_thread,
383                                                                            searching_thread_notify_cb,
384                                                                            searching_thread_end_cb,
385                                                                            searching_thread_cancel_cb,
386                                                                            data,
387                                                                            EINA_FALSE);
388
389         PRINT_SERVICE_FUNC_LEAVE;
390 }
391
392 static Eina_Bool __pt_check_cups_before_searching(void *data)
393 {
394         PRINT_SERVICE_FUNC_ENTER;
395         Eina_Bool ret = ECORE_CALLBACK_RENEW;
396
397         if (g_pt_info->cups_pid > 0) {
398                 pt_search_data_t *ad = (pt_search_data_t *)data;
399                 __pt_get_printers(ad);
400                 ret = ECORE_CALLBACK_CANCEL;
401         }
402
403         PRINT_SERVICE_FUNC_LEAVE;
404         return ret;
405 }
406
407 /***
408 * '__enable_printer()' - Enable a printer...
409 * I - Server connection
410 * I - Printer to enable
411 * O - 0 on success, 1 on fail
412 ***/
413
414 static int      __enable_printer(http_t *http, char *printer, char *device_uri)
415 {
416         /* IPP Request */
417         ipp_t *request;
418         ipp_t *response;          /* IPP Response */
419         char uri[HTTP_MAX_URI];  /* URI for printer/class */
420
421         /*
422         * Build a CUPS_ADD_PRINTER request, which requires the following
423         * attributes:
424         *
425         *        attributes-charset
426         *        attributes-natural-language
427         *        printer-uri
428         *        printer-state
429         *        printer-is-accepting-jobs
430         */
431
432         //request = ippNewRequest(CUPS_ADD_PRINTER);
433         request = ippNewRequest(CUPS_ADD_MODIFY_PRINTER);
434
435         //httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/printers/%s", printer);
436         httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 631, "/printers/%s", printer);
437         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
438
439         if (device_uri[0] == '/') {
440                 snprintf(uri, sizeof(uri), "file://%s", device_uri);
441                 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, uri);
442         } else {
443                 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, device_uri);
444         }
445
446         ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", IPP_PRINTER_IDLE);
447
448         ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
449
450         /*
451         * Do the request and get back a response...
452         */
453         if ((response = cupsDoRequest(http, request, "/admin/")) == NULL) {
454                 PT_DEBUG("cupsDoRequest Failed");
455                 return (1);
456         } else if (ippGetStatusCode(response) > IPP_OK_EVENTS_COMPLETE) {
457                 PT_DEBUG("%x greater than IPP_OK_EVENTS_COMPLETE -- Failed", ippGetStatusCode(response));
458                 ippDelete(response);
459                 return (1);
460         } else {
461                 ippDelete(response);
462                 return (0);
463         }
464
465 }
466
467 static int      __set_printer_ppd(http_t *http, char *printer, char *ppd_file)
468 {
469         ipp_t *request = NULL;
470         ipp_t *response = NULL;
471         char uri[HTTP_MAX_URI] = {0,};
472
473         httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/printers/%s", printer);
474
475         request = ippNewRequest(CUPS_ADD_MODIFY_PRINTER);
476
477         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
478         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
479
480         if (ppd) {
481                 ppdClose(ppd);
482                 ppd = NULL;
483         }
484
485         if (ppd_file != NULL) {
486                 PT_DEBUG("ppd file is not NULL. %s", ppd_file);
487
488                 response = cupsDoFileRequest(http, request, "/admin/", ppd_file);
489
490                 if (response != NULL) {
491                         ippDelete(response);
492                         ppd = ppdOpenFile(ppd_file);
493                         if (ppd != NULL) {
494                                 pt_parse_options(ppd);
495                         }
496                 } else {
497                         PT_DEBUG("Failed to call cupsDoFileRequest");
498                 }
499         } else {
500                 PT_DEBUG("ppd file is NULL");
501                 ippDelete(request);
502                 return 1;
503         }
504
505         if (cupsLastError() > IPP_OK_CONFLICT) {
506                 PT_DEBUG("The request is failed, detail description: %s\n", cupsLastErrorString());
507                 return 1;
508         } else {
509                 return 0;
510         }
511 }
512
513 /**
514  *      This function let the app register the printer to the server
515  *      @return    If success, return PT_ERR_NONE, else return PT_ERR_FAIL
516  *      @param[in] printer_name the pointer to the printer's name
517  *      @param[in] scheme the pointer to the register's scheme
518  *      @param[in] ip_address the pointer to the printer's address
519  *      @param[in] ppd_file the pointer to the printer's ppd file
520  */
521 static int pt_utils_regist_printer(char *printer_name, char *scheme, char *ip_address, char *ppd_file)
522 {
523         PT_RETV_IF(printer_name == NULL || ip_address == NULL || ppd_file == NULL , 1 , "Invalid argument");
524
525         /* Connection to server */
526         http_t *http = NULL;
527         char device_url[PT_MAX_LENGTH] = {0,};
528
529         snprintf(device_url, MAX_URI_SIZE, "%s://%s", scheme, ip_address);
530
531         http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
532         PT_RETV_IF(http == NULL, 1, "Unable to connect to server");
533
534         if (__enable_printer(http, printer_name, device_url)) {
535                 PT_DEBUG("enable return 1");
536                 return (1);
537         }
538
539         if (__set_printer_ppd(http, printer_name, ppd_file)) {
540                 return (1);
541         }
542
543         if (http) {
544                 httpClose(http);
545         }
546         PT_DEBUG("add printer success");
547         return (0);
548 }
549
550 /**
551  *      This API let the app get the printer list
552  *      @return   If success, return PT_ERR_NONE, else return the other error code as defined in pt_err_t
553  *      @param[in] callback the pointer to the function which will be excuted after search
554  *      @param[in] userdata the pointer to the user data
555  */
556 int pt_get_printers(get_printers_cb callback, void *userdata)
557 {
558         PRINT_SERVICE_FUNC_ENTER;
559         PT_RETV_IF(g_pt_info == NULL || g_pt_info->search == NULL, PT_ERR_INVALID_PARAM, "Invalid argument");
560         PT_RETV_IF(callback == NULL || userdata == NULL, PT_ERR_INVALID_PARAM, "Invalid argument");
561
562         /*check the current connection*/
563         int status = -1;
564         int connect_type = 0;
565         status = pt_get_connection_status(&connect_type);
566         PT_RETV_IF(status != PT_ERR_NONE, PT_ERR_FAIL, "Vconf access error");
567         PT_RETV_IF(connect_type == 0, PT_ERR_FAIL, "No available connection");
568
569         pt_search_data_t *ad = g_pt_info->search;
570         ad->response_data.userdata = userdata;
571         ad->user_cb = callback;
572
573         PT_RETV_IF(ad->is_searching == 1 , PT_ERR_UNKNOWN, "in searching");
574
575         /*clear previous search result*/
576         if (ad->pt_local_list != NULL) {
577                 pt_utils_free_local_printer_list(ad->pt_local_list);
578                 ad->pt_local_list = NULL;
579         }
580
581         /*clear previous search result*/
582         if (ad->response_data.printerlist != NULL) {
583                 pt_utils_free_search_list(ad->response_data.printerlist);
584                 ad->response_data.printerlist = NULL;
585         }
586
587         g_pt_info->searching_state = PT_SEARCH_IN_PROGRESS;
588         if (g_pt_info->cups_pid > 0) {
589                 __pt_get_printers(ad);
590         } else {
591                 g_pt_info->cups_checking_timer = ecore_timer_add(1.0, (Ecore_Task_Cb)__pt_check_cups_before_searching, ad);
592         }
593
594         PRINT_SERVICE_FUNC_LEAVE;
595         return PT_ERR_NONE;
596 }
597
598 /**
599  *      This API let the app cancel getting the printer list
600  *      @return   If success, return PT_ERR_NONE, else return the other error code as defined in pt_err_t
601  */
602 int pt_cancel_get_printers()
603 {
604         PRINT_SERVICE_FUNC_ENTER;
605         PT_RETV_IF(g_pt_info == NULL, PT_ERR_INVALID_PARAM, "g_pt_info is NULL");
606         PT_RETV_IF(g_pt_info->search == NULL, PT_ERR_INVALID_PARAM, "g_pt_info->search is NULL");
607         PT_RETV_IF(g_pt_info->searching_thd_hdl == NULL, PT_ERR_INVALID_PARAM, "g_pt_info->searching_thd_hdl is NULL");
608
609         pt_search_data_t *ad = g_pt_info->search;
610
611         if (g_pt_info->cups_checking_timer) {
612                 ecore_timer_del(g_pt_info->cups_checking_timer);
613                 g_pt_info->cups_checking_timer = NULL;
614         }
615
616         if (ecore_thread_cancel(g_pt_info->searching_thd_hdl) == EINA_FALSE) {
617                 PT_DEBUG("Canceling of searching_thd_hdl[%p] is pended", g_pt_info->searching_thd_hdl);
618         }
619
620         g_pt_info->searching_state = PT_SEARCH_CANCEL;
621
622         /*clear the search result*/
623         if (ad->pt_local_list != NULL) {
624                 pt_utils_free_local_printer_list(ad->pt_local_list);
625                 ad->pt_local_list = NULL;
626         }
627
628         /*clear the search result*/
629         if (ad->response_data.printerlist != NULL) {
630                 pt_utils_free_search_list(ad->response_data.printerlist);
631                 ad->response_data.printerlist = NULL;
632         }
633
634         ad->response_data.userdata = NULL;
635         ad->user_cb = NULL;
636
637         PRINT_SERVICE_FUNC_LEAVE;
638         return PT_ERR_NONE;
639 }
640
641 /**
642  *      This API let the app get the current default printer
643  *      allocates memory for printer info structure! Please free after use!
644  *      @return   If success, return PT_ERR_NONE, else return the other error code as defined in pt_err_t
645  *      @param[out] printer the pointer to the printer object
646  */
647 int pt_get_default_printer(pt_printer_mgr_t **printer)
648 {
649         PRINT_SERVICE_FUNC_ENTER;
650         PT_RETV_IF(printer == NULL || g_pt_info == NULL, PT_ERR_INVALID_PARAM, "Invalid argument");
651         pt_printer_mgr_t *pt = NULL;
652
653         /* check whether if the default printer exists in the preference */
654         bool isexist = 0;
655         int ret = -1;
656         ret = preference_is_existing(PREFERENCE_DEFAULT_PRINTER_NAME, &isexist);
657         PT_RETV_IF(!isexist, PT_ERR_FAIL, "the default printer name isn't exist in preference!");
658
659         ret = preference_is_existing(PREFERENCE_DEFAULT_PRINTER_ADDRESS, &isexist);
660         PT_RETV_IF(!isexist, PT_ERR_FAIL, "the default printer name isn't exist in preference!");
661
662         /* get the printer in the preference */
663         char *name = NULL;
664         ret = preference_get_string(PREFERENCE_DEFAULT_PRINTER_NAME, &name);
665         PT_RETV_IF(ret, PT_ERR_FAIL, "get the default printer name failed, errno: %d!", ret);
666
667         char *address = NULL;
668         ret = preference_get_string(PREFERENCE_DEFAULT_PRINTER_ADDRESS, &address);
669         PT_RETV_IF(ret, PT_ERR_FAIL, "get the default printer name failed, errno: %d!", ret);
670
671         pt = (pt_printer_mgr_t *)calloc(1, sizeof(pt_printer_mgr_t));
672         PT_RETV_IF(pt == NULL, PT_ERR_FAIL, "Failed to calloc pt");
673         memcpy(pt->name, name, PT_MAX_LENGTH);
674         memcpy(pt->address, address, PT_MAX_LENGTH);
675
676         memcpy(g_pt_info->active_printer, pt, sizeof(pt_printer_mgr_t));
677
678         PT_DEBUG("get printer info from preference, name: %s, address: %s!",
679                          pt->name, pt->address);
680
681         PT_IF_FREE_MEM(name);
682         PT_IF_FREE_MEM(address);
683
684         *printer = pt;
685
686         PRINT_SERVICE_FUNC_LEAVE;
687         return PT_ERR_NONE;
688 }
689
690 /**
691  *      This API let the app set a printer as the default printer
692  *      @return   If success, return PT_ERR_NONE, else return the other error code as defined in pt_err_t
693  *      @param[in] printer the pointer to the printer object
694  */
695 int pt_set_default_printer(pt_printer_mgr_t *printer)
696 {
697         PRINT_SERVICE_FUNC_ENTER;
698         PT_RETV_IF(printer == NULL || g_pt_info == NULL, PT_ERR_INVALID_PARAM, "Invalid argument");
699
700         /*check the current connection*/
701         int status = -1;
702         int connect_type = 0;
703         status = pt_get_connection_status(&connect_type);
704
705         PT_RETV_IF(status != PT_ERR_NONE, PT_ERR_FAIL, "Vconf access error");
706         PT_RETV_IF(connect_type == 0, PT_ERR_FAIL, "No available connection");
707
708         /* set the printer name in the preference */
709         int ret = -1;
710         ret = preference_set_string(PREFERENCE_DEFAULT_PRINTER_NAME, (const char *)printer->name);
711         PT_RETV_IF(ret, PT_ERR_FAIL, "set the default printer name(%s) failed!", printer->name);
712
713         /* set the printer address in the preference */
714         ret = preference_set_string(PREFERENCE_DEFAULT_PRINTER_ADDRESS, (const char *)printer->address);
715         PT_RETV_IF(ret, PT_ERR_FAIL, "set the default printer name(%s) failed!", printer->address);
716
717         /* set the printer address in the preference */
718         ret = preference_set_string(PREFERENCE_DEFAULT_PRINTER_MFG, (const char *)printer->mfg);
719         PT_RETV_IF(ret, PT_ERR_FAIL, "set the default printer name(%s) failed!", printer->mfg);
720
721         /* set the printer address in the preference */
722         ret = preference_set_string(PREFERENCE_DEFAULT_PRINTER_MDL, (const char *)printer->mdl);
723         PT_RETV_IF(ret, PT_ERR_FAIL, "set the default printer name(%s) failed!", printer->mdl);
724
725         PRINT_SERVICE_FUNC_LEAVE;
726         return PT_ERR_NONE;
727 }
728
729 /**
730  *      This API let the app get the current active printer
731  *      allocates memory for printer info structure! Please free after use!
732  *      @return   If success, return PT_ERR_NONE, else return the other error code as defined in pt_err_t
733  *      @param[out] printer the pointer to the printer object
734  */
735 int pt_get_active_printer(pt_printer_mgr_t **printer)
736 {
737         PRINT_SERVICE_FUNC_ENTER;
738         PT_RETV_IF(g_pt_info == NULL || g_pt_info->active_printer == NULL
739                            , PT_ERR_INVALID_PARAM, "global printer information is NULL or no active printer");
740         PT_RETV_IF(printer == NULL, PT_ERR_INVALID_PARAM, "printer is NULL");
741
742         pt_printer_mgr_t *pt = NULL;
743         pt = (pt_printer_mgr_t *)malloc(sizeof(pt_printer_mgr_t));
744         PT_RETV_IF(pt == NULL, PT_ERR_NO_MEMORY, "Not enough memory");
745
746         memset(pt, 0, sizeof(pt_printer_mgr_t));
747         memcpy(pt, g_pt_info->active_printer, sizeof(pt_printer_mgr_t));
748
749         PT_DEBUG("g_pt_info->active_printer->name %s" , g_pt_info->active_printer->name);
750         PT_DEBUG("g_pt_info->active_printer->actived = %d", g_pt_info->active_printer->actived);
751         PT_DEBUG("g_pt_info->active_printer->ppd%s" , g_pt_info->active_printer->ppd);
752         PT_DEBUG("g_pt_info->active_printer->address %s" , g_pt_info->active_printer->address);
753         PT_DEBUG("g_pt_info->active_printer->mfg %s" , g_pt_info->active_printer->mfg);
754         PT_DEBUG("g_pt_info->active_printer->mdl %s" , g_pt_info->active_printer->mdl);
755
756         *printer = pt;
757
758         PRINT_SERVICE_FUNC_LEAVE;
759         return PT_ERR_NONE;
760 }
761
762
763 /**
764  *      This API let the app select a specify printer as active printer
765  *      @return   If success, return PT_ERR_NONE, else return the other error code as defined in pt_err_t
766  *      @param[in] printer the pointer to the printer object
767  */
768 int pt_set_active_printer(pt_printer_mgr_t *printer)
769 {
770         PRINT_SERVICE_FUNC_ENTER;
771         PT_RETV_IF(g_pt_info == NULL || g_pt_info->active_printer == NULL
772                            , PT_ERR_INVALID_PARAM, "global printer information is NULL or no active printer");
773         PT_RETV_IF(printer == NULL, PT_ERR_INVALID_PARAM, "printer is NULL");
774
775         /*check the current connection*/
776         int status = -1;
777         int connect_type = 0;
778         status = pt_get_connection_status(&connect_type);
779
780         PT_RETV_IF(status != PT_ERR_NONE, PT_ERR_FAIL, "Vconf access error");
781         PT_RETV_IF(connect_type == 0, PT_ERR_FAIL, "No available connection");
782
783         /*register the printer*/
784         int ret = -1;
785
786         if (pt_get_printer_ppd(printer) != PT_ERR_NONE) {
787                 /* Error can not get ppd info*/
788                 PT_DEBUG("Get %s ppd failed", printer->name);
789                 return PT_ERR_INVALID_PARAM;
790         }
791
792         PT_DEBUG("Get ppd info: %s", printer->ppd);
793         PT_DEBUG("address is %s", printer->address);
794
795         if ((strncasecmp(printer->address, "usb://", 6) == 0)) {
796                 /* usb mode */
797                 char *address = printer->address + sizeof("usb://") - 1;
798                 PT_DEBUG("usb address: %s", address);
799
800                 if (address) {
801                         ret = pt_utils_regist_printer(printer->name, "usb", address, printer->ppd);
802                 }
803         } else if ((strncasecmp(printer->address, "dnssd://", 8) == 0)) {
804                 /* dnssd mode */
805                 char *address = printer->address + sizeof("dnssd://") - 1;
806                 PT_DEBUG("dnssd address: %s", address);
807
808                 if (address) {
809                         PT_DEBUG("1. printer structure address: %x", printer);
810                         ret = pt_utils_regist_printer(printer->name, "dnssd", address, printer->ppd);
811                         PT_DEBUG("2. printer structure address: %x", printer);
812                 }
813         } else {
814                 ret = pt_utils_regist_printer(printer->name, "socket", printer->address, printer->ppd);
815         }
816
817         PT_RETV_IF(ret != PT_ERR_NONE, PT_ERR_UNKNOWN, "add printer failed, description:%s", cupsLastErrorString());
818
819         /* only actived printer can print file */
820         printer->actived = 1;
821         memcpy(g_pt_info->active_printer, printer, sizeof(pt_printer_mgr_t));
822         PT_DEBUG("g_pt_info->active_printer->name %s" , g_pt_info->active_printer->name);
823         PT_DEBUG("g_pt_info->active_printer->address %s" , g_pt_info->active_printer->address);
824         PT_DEBUG("g_pt_info->active_printer->mfg %s" , g_pt_info->active_printer->mfg);
825         PT_DEBUG("g_pt_info->active_printer->mdl %s" , g_pt_info->active_printer->mdl);
826
827         PRINT_SERVICE_FUNC_LEAVE;
828         return PT_ERR_NONE;
829 }