4 * Copyright 2012 Samsung Electronics Co., Ltd
6 * Licensed under the Flora License, Version 1.0 (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
10 * http://floralicense.org/license/
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.
21 #include <sys/types.h>
27 #include "pt_common.h"
29 #include "pt_printer.h"
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"
37 static void g_printer_data_destroy(gconstpointer a)
42 static gboolean __printer_compare(gconstpointer a, gconstpointer b)
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");
48 if (strcmp(printer_a->device_uri, printer_b->device_uri) == 0) {
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) {
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)
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));
69 char *device_mfg = NULL;
70 char *device_mdl = NULL;
71 char *device_name = NULL;
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);
81 if (device_mfg == NULL) {
82 PT_IF_FREE_MEM(localdetail);
83 PT_IF_FREE_MEM(device_mdl);
84 PT_DEBUG("device_mfg == NULL");
87 if (device_mdl == NULL) {
88 PT_IF_FREE_MEM(localdetail);
89 PT_IF_FREE_MEM(device_mfg);
90 PT_DEBUG("device_mdl == NULL");
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");
103 strncat(device_name,device_mfg,strlen(device_mfg));
104 strncat(device_name," ",1);
105 strncat(device_name,device_mdl,strlen(device_mdl));
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);
114 PT_IF_FREE_MEM(device_mfg);
115 PT_IF_FREE_MEM(device_mdl);
116 PT_IF_FREE_MEM(device_name);
121 static void pt_debug_print_device_attr(ipp_attribute_t *attr)
123 PT_RET_IF(attr == NULL, "Invalid argument");
124 /* CUPS 1.6.1 support new ippGet function
142 if (ippGetValueTag(attr) == IPP_TAG_TEXT || ippGetValueTag(attr) == IPP_TAG_URI) {
143 PT_DEBUG("grp=[%d] name=[%s] text=[%s]", ippGetGroupTag(attr), (ippGetName(attr) ==NULL)?"nill":ippGetName(attr), ippGetString(attr, 0, NULL));
144 } else if (ippGetValueTag(attr) == IPP_TAG_INTEGER) {
145 PT_DEBUG("grp=[%d] name=[%s] int=[%d]", ippGetGroupTag(attr), (ippGetName(attr)==NULL)?"nill":ippGetName(attr), ippGetInteger(attr,0));
146 } else if (ippGetValueTag(attr) == IPP_TAG_BOOLEAN) {
147 PT_DEBUG("grp=[%d] name=[%s] bool=[%d]", ippGetGroupTag(attr), (ippGetName(attr)==NULL)?"nill":ippGetName(attr), ippGetBoolean(attr,0));
148 } else if (ippGetValueTag(attr) == IPP_TAG_RESOLUTION) {
151 ipp_res_t units = -1;
152 xres = ippGetResolution(attr, 0, &yres, &units);
153 PT_DEBUG("grp=[%d] name=[%s] res=[%d,%d, %d]", ippGetGroupTag(attr), (ippGetName(attr)==NULL)?"nill":ippGetName(attr),
155 } else if (ippGetValueTag(attr) == IPP_TAG_RANGE) {
158 lower = ippGetRange(attr, 0, &uppper);
159 PT_DEBUG("grp=[%d] name=[%s] range=[%d,%d]", ippGetGroupTag(attr), (ippGetName(attr)==NULL)?"nill":ippGetName(attr), uppper, lower);
160 } else if (ippGetValueTag(attr) == IPP_TAG_EVENT_NOTIFICATION) {
161 PT_DEBUG("IPP_TAG_EVENT_NOTIFICATION");
162 PT_DEBUG("grp=[%d] name=[%s] value_tag=[%d]", ippGetGroupTag(attr), (ippGetName(attr)==NULL)?"nill":ippGetName(attr), ippGetValueTag(attr));
163 } else if (ippGetValueTag(attr) == IPP_TAG_SUBSCRIPTION) {
164 PT_DEBUG("grp=[%d] name=[%s] value_tag=[%d]", ippGetGroupTag(attr), (ippGetName(attr)==NULL)?"nill":ippGetName(attr), ippGetValueTag(attr));
166 PT_DEBUG("grp=[%d] name=[%s] value_tag=[%d]", ippGetGroupTag(attr), (ippGetName(attr)==NULL)?"nill":ippGetName(attr), ippGetValueTag(attr));
171 static void pt_util_add_printer_to_hashlist(GHashTable *printer_hashlist, pt_printer_info_t *printer)
173 PT_RET_IF(printer == NULL, "printer is NULL");
174 PT_RET_IF(printer_hashlist == NULL, "printer_hashlist is NULL");
176 pt_printer_info_t *tempdetail = NULL;
177 tempdetail = (pt_printer_info_t *) g_hash_table_lookup(printer_hashlist, printer);
179 if (NULL == tempdetail) {
180 g_hash_table_insert(printer_hashlist, printer, printer);
181 PT_DEBUG("Added printer_hashlist: %s", printer->device_uri);
183 if (strstr(tempdetail->device_uri, "_printer.") && strstr(printer->device_uri, "_ipp.")) {
184 g_hash_table_replace(printer_hashlist, printer, printer);
185 PT_DEBUG("Replaced printer_hashlist: %s", printer->device_uri);
186 } else if (strstr(tempdetail->device_uri, "_pdl-datastream.") &&
187 (strstr(printer->device_uri, "_printer.") || strstr(printer->device_uri, "_ipp."))) {
188 g_hash_table_replace(printer_hashlist, printer, printer);
189 PT_DEBUG("Replaced printer_hashlist: %s", printer->device_uri);
194 static int compare_printer(pt_printer_mgr_t *printer_a, pt_printer_mgr_t *printer_b)
196 if (printer_a->is_ppd_exist == TRUE && printer_b->is_ppd_exist == FALSE) {
198 } else if (printer_a->is_ppd_exist == FALSE && printer_b->is_ppd_exist == TRUE) {
201 if (strcmp(printer_a->name, printer_b->name) != 0) {
202 return strcmp(printer_a->name, printer_b->name);
205 return strcmp(printer_a->address, printer_b->address);
210 static void pt_util_append_printer(pt_search_data_t *search_data, GHashTable *printer_hashlist)
214 pt_printer_info_t *printer_temp = NULL;
215 Eina_Compare_Cb cmp_func = (Eina_Compare_Cb)compare_printer;
217 g_hash_table_iter_init(&iter, printer_hashlist);
218 while (g_hash_table_iter_next(&iter, &key, &value)) {
219 printer_temp = (pt_printer_info_t *)malloc(sizeof(pt_printer_info_t));
220 PT_RET_IF(printer_temp == NULL, "printer_temp is NULL");
221 memset(printer_temp, 0, sizeof(pt_printer_info_t));
222 memcpy(printer_temp, value, sizeof(pt_printer_info_t));
223 search_data->pt_local_list = eina_list_append(search_data->pt_local_list, (pt_printer_info_t *)printer_temp);
224 if (eina_error_get()) {
225 PT_DEBUG("Failed to add eina_list for search_data->pt_local_list");
229 /* add searched printer */
230 Eina_List *cursor = NULL;
231 pt_printer_info_t *it = NULL;
232 pt_printer_mgr_t *detail = NULL;
234 //TODO:: free ( search_data->response_data.printerlist ); -- dwmax
235 search_data->response_data.printerlist = NULL;
237 Eina_Bool bfirst = EINA_TRUE;
238 /* add printer to response list */
239 EINA_LIST_FOREACH(search_data->pt_local_list, cursor, it) {
240 detail = (pt_printer_mgr_t *)malloc(sizeof(pt_printer_mgr_t));
241 if (detail != NULL) {
242 memset(detail, 0, sizeof(pt_printer_mgr_t));
244 strncpy(detail->name, it->product_ui_name, PT_MAX_LENGTH -1);
245 strncpy(detail->address, it->device_uri, PT_MAX_LENGTH -1);
246 strncpy(detail->mdl, it->model_name, PT_MAX_LENGTH -1);
247 strncpy(detail->mfg, it->manufacturer, PT_MAX_LENGTH -1);
248 PT_DEBUG("product %s",it->product_ui_name);
249 PT_DEBUG("url %s",it->device_uri);
250 PT_DEBUG("mdl %s",it->model_name);
251 PT_DEBUG("mfg %s",it->manufacturer);
253 if (EINA_TRUE == bfirst) {
257 if (pt_get_printer_ppd(detail) != PT_ERR_NONE) {
258 //Unsupported Printer
259 detail->is_ppd_exist = FALSE;
261 detail->is_ppd_exist = TRUE;
264 // search_data->response_data.printerlist = eina_list_append(search_data->response_data.printerlist, detail);
265 search_data->response_data.printerlist = eina_list_sorted_insert(search_data->response_data.printerlist, cmp_func,detail);
266 if (eina_error_get()) {
267 PT_DEBUG("Failed to add eina_list for search_data->response_data.printerlist");
274 static void searching_thread_notify_cb(void *data, Ecore_Thread *thread, void *msg_data)
276 PRINT_SERVICE_FUNC_ENTER;
277 PT_RET_IF(data == NULL, "data is NULL");
278 PT_RET_IF(msg_data == NULL, "msg_data is NULL");
279 PT_DEBUG("Thread is sent msg successfully.");
281 pt_search_data_t *search_data = NULL;
282 ipp_t *response = NULL;
284 search_data = (pt_search_data_t *)data;
285 response = (ipp_t *)msg_data;
287 PT_RET_IF(search_data->user_cb == NULL, "user_cb is NULL");
289 GHashTable *printer_hashlist = g_hash_table_new_full(g_str_hash, __printer_compare, NULL, (GDestroyNotify)g_printer_data_destroy);
291 ipp_attribute_t *attr = NULL;
292 const char *device_uri = NULL; /* device-uri attribute value */
293 const char *device_info = NULL; /* device-info value */
294 const char *device_make_and_model = NULL; /* device-make-and-model value */
296 for (attr = ippFirstAttribute(response); attr != NULL; attr = ippNextAttribute(response)) {
298 pt_debug_print_device_attr(attr);
300 if (ippGetGroupTag(attr) == IPP_TAG_ZERO) {
301 PT_DEBUG("-----------------------------------------");
302 } else if (ippGetGroupTag(attr) != IPP_TAG_PRINTER) {
304 } else if (!strcmp(ippGetName(attr), "device-info") && ippGetValueTag(attr) == IPP_TAG_TEXT) {
305 device_info = ippGetString(attr, 0, NULL);
306 } else if (!strcmp(ippGetName(attr), "device-make-and-model") && ippGetValueTag(attr) == IPP_TAG_TEXT) {
307 device_make_and_model = ippGetString(attr, 0, NULL);
308 } else if (!strcmp(ippGetName(attr), "device-uri") && ippGetValueTag(attr) == IPP_TAG_URI) {
309 device_uri = ippGetString(attr, 0, NULL);
314 if (device_info == NULL || device_make_and_model == NULL
315 || device_uri == NULL) {
317 } else if (strcasestr(device_uri, "usb://") ||
318 strstr(device_uri,"_pdl-datastream.") ||
319 strstr(device_uri,"_ipp.") ||
320 strstr(device_uri,"_printer.")) {
321 pt_printer_info_t *localdetail = NULL;
322 localdetail = pt_util_make_printer_info(device_info, device_make_and_model, device_uri);
323 pt_util_add_printer_to_hashlist(printer_hashlist, localdetail);
325 PT_DEBUG("the device has another scheme such as socket");
330 device_make_and_model = NULL;
334 pt_util_append_printer(search_data, printer_hashlist);
335 g_hash_table_destroy(printer_hashlist);
338 search_data->user_cb(&search_data->response_data);
340 PRINT_SERVICE_FUNC_LEAVE;
343 static void searching_thread_end_cb(void *data, Ecore_Thread *thread)
345 PRINT_SERVICE_FUNC_ENTER;
346 g_pt_info->searching_state = PT_SEARCH_END;
347 PT_DEBUG("Thread is completed successfully.");
348 PRINT_SERVICE_FUNC_LEAVE;
351 static void searching_thread_cancel_cb(void *data, Ecore_Thread *thread)
353 PRINT_SERVICE_FUNC_ENTER;
354 PT_DEBUG("Thread is canceled successfully.");
355 PRINT_SERVICE_FUNC_LEAVE;
358 static void searching_thread(void *data, Ecore_Thread *thread)
360 PRINT_SERVICE_FUNC_ENTER;
361 PT_RET_IF(data == NULL, "data is NULL");
362 PT_RET_IF(thread == NULL, "thread is NULL");
365 ipp_t *request = NULL;
366 ipp_t *response = NULL;
367 int connection_status = 0;
369 char *exclude_schemes[] = {
384 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
385 PT_RET_IF(http == NULL, "unable to connect server");
387 request = ippNewRequest(CUPS_GET_DEVICES);
388 PT_RET_IF(request == NULL, "unable to create request");
390 ret = pt_get_connection_status(&connection_status);
392 if (ret != PT_ERR_NONE) {
394 PT_DEBUG("unable to get connection status");
397 if ((connection_status & PT_CONNECTION_USB) == 0) {
398 exclude_schemes[num_schemes++] = "usb";
400 if ((connection_status & PT_CONNECTION_WIFI) == 0 &&
401 (connection_status & PT_CONNECTION_WIFI_DIRECT) == 0) {
402 exclude_schemes[num_schemes++] = "dnssd";
405 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "exclude-schemes",
406 num_schemes ,NULL, exclude_schemes);
407 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "timeout",5);
409 if ((response = cupsDoRequest(http, request, "/")) != NULL) {
410 PT_DEBUG("CUPS_GET_DEVICES (%s)",cupsLastErrorString());
411 if (g_pt_info->searching_state == PT_SEARCH_CANCEL) {
416 if (ecore_thread_feedback(thread, (const void *)response) == EINA_FALSE) {
417 PT_DEBUG("Failed to send data to main loop");
421 PT_DEBUG("CUPS_GET_DEVICES (%s)", cupsLastErrorString());
425 PRINT_SERVICE_FUNC_LEAVE;
428 static void __pt_get_printers(pt_search_data_t *data)
430 PRINT_SERVICE_FUNC_ENTER;
432 g_pt_info->searching_thd_hdl = ecore_thread_feedback_run(
434 searching_thread_notify_cb,
435 searching_thread_end_cb,
436 searching_thread_cancel_cb,
440 PRINT_SERVICE_FUNC_LEAVE;
443 static Eina_Bool __pt_check_cups_before_searching(void *data)
445 PRINT_SERVICE_FUNC_ENTER;
446 Eina_Bool ret = ECORE_CALLBACK_RENEW;
448 if (g_pt_info->cups_pid > 0) {
449 pt_search_data_t *ad = (pt_search_data_t *)data;
450 __pt_get_printers(ad);
451 ret = ECORE_CALLBACK_CANCEL;
454 PRINT_SERVICE_FUNC_LEAVE;
459 * '__enable_printer()' - Enable a printer...
460 * I - Server connection
461 * I - Printer to enable
462 * O - 0 on success, 1 on fail
465 static int __enable_printer(http_t *http, char *printer, char *device_uri)
469 ipp_t *response; /* IPP Response */
470 char uri[HTTP_MAX_URI]; /* URI for printer/class */
473 * Build a CUPS_ADD_PRINTER request, which requires the following
477 * attributes-natural-language
480 * printer-is-accepting-jobs
483 //request = ippNewRequest(CUPS_ADD_PRINTER);
484 request = ippNewRequest(CUPS_ADD_MODIFY_PRINTER);
486 //httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/printers/%s", printer);
487 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 631, "/printers/%s", printer);
488 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
490 if (device_uri[0] == '/') {
491 snprintf(uri, sizeof(uri), "file://%s", device_uri);
492 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, uri);
494 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, device_uri);
497 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", IPP_PRINTER_IDLE);
499 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
502 * Do the request and get back a response...
504 if ((response = cupsDoRequest(http, request, "/admin/")) == NULL) {
505 PT_DEBUG("cupsDoRequest Failed");
507 } else if (ippGetStatusCode(response) > IPP_OK_EVENTS_COMPLETE) {
508 PT_DEBUG("%x greater than IPP_OK_EVENTS_COMPLETE -- Failed", ippGetStatusCode(response));
518 static int __set_printer_ppd(http_t *http, char *printer, char *ppd_file)
520 ipp_t *request = NULL;
521 ipp_t *response = NULL;
522 char uri[HTTP_MAX_URI] = {0,};
524 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, "/printers/%s", printer);
526 request = ippNewRequest(CUPS_ADD_MODIFY_PRINTER);
528 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
529 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
536 if (ppd_file != NULL) {
537 PT_DEBUG("ppd file is not NULL. %s", ppd_file);
539 response = cupsDoFileRequest(http, request, "/admin/", ppd_file);
541 if (response != NULL) {
543 ppd = ppdOpenFile(ppd_file);
545 pt_parse_options(ppd);
548 PT_DEBUG("Failed to call cupsDoFileRequest");
551 PT_DEBUG("ppd file is NULL");
556 if (cupsLastError() > IPP_OK_CONFLICT) {
557 PT_DEBUG("The request is failed, detail description: %s\n", cupsLastErrorString());
565 * This function let the app register the printer to the server
566 * @return If success, return PT_ERR_NONE, else return PT_ERR_FAIL
567 * @param[in] printer_name the pointer to the printer's name
568 * @param[in] scheme the pointer to the register's scheme
569 * @param[in] ip_address the pointer to the printer's address
570 * @param[in] ppd_file the pointer to the printer's ppd file
572 static int pt_utils_regist_printer(char *printer_name, char *scheme, char *ip_address, char *ppd_file)
574 PT_RETV_IF(printer_name == NULL || ip_address == NULL || ppd_file == NULL , 1 , "Invalid argument");
576 /* Connection to server */
578 char device_url[PT_MAX_LENGTH] = {0,};
580 snprintf(device_url, MAX_URI_SIZE, "%s://%s", scheme, ip_address);
582 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
583 PT_RETV_IF(http == NULL, 1, "Unable to connect to server");
585 if (__enable_printer(http, printer_name, device_url)) {
586 PT_DEBUG("enable return 1");
590 if (__set_printer_ppd(http, printer_name, ppd_file)) {
597 PT_DEBUG("add printer success");
602 * This API let the app get the printer list
603 * @return If success, return PT_ERR_NONE, else return the other error code as defined in pt_err_t
604 * @param[in] callback the pointer to the function which will be excuted after search
605 * @param[in] userdata the pointer to the user data
607 int pt_get_printers(get_printers_cb callback, void *userdata)
609 PRINT_SERVICE_FUNC_ENTER;
610 PT_RETV_IF(g_pt_info == NULL || g_pt_info->search == NULL, PT_ERR_INVALID_PARAM, "Invalid argument");
611 PT_RETV_IF(callback == NULL || userdata == NULL, PT_ERR_INVALID_PARAM, "Invalid argument");
613 /*check the current connection*/
615 int connect_type = 0;
616 status = pt_get_connection_status(&connect_type);
617 PT_RETV_IF(status != PT_ERR_NONE, PT_ERR_FAIL, "Vconf access error");
618 PT_RETV_IF(connect_type == 0, PT_ERR_FAIL, "No available connection");
620 pt_search_data_t *ad = g_pt_info->search;
621 ad->response_data.userdata = userdata;
622 ad->user_cb = callback;
624 PT_RETV_IF(ad->is_searching == 1 , PT_ERR_UNKNOWN, "in searching");
626 /*clear previous search result*/
627 if (ad->pt_local_list != NULL) {
628 pt_utils_free_local_printer_list(ad->pt_local_list);
629 ad->pt_local_list = NULL;
632 /*clear previous search result*/
633 if (ad->response_data.printerlist != NULL) {
634 pt_utils_free_search_list(ad->response_data.printerlist);
635 ad->response_data.printerlist = NULL;
638 g_pt_info->searching_state = PT_SEARCH_IN_PROGRESS;
639 if (g_pt_info->cups_pid > 0) {
640 __pt_get_printers(ad);
642 g_pt_info->cups_checking_timer = ecore_timer_add(1.0, (Ecore_Task_Cb)__pt_check_cups_before_searching, ad);
645 PRINT_SERVICE_FUNC_LEAVE;
650 * This API let the app cancel getting the printer list
651 * @return If success, return PT_ERR_NONE, else return the other error code as defined in pt_err_t
653 int pt_cancel_get_printers()
655 PRINT_SERVICE_FUNC_ENTER;
656 PT_RETV_IF(g_pt_info == NULL, PT_ERR_INVALID_PARAM, "g_pt_info is NULL");
657 PT_RETV_IF(g_pt_info->search == NULL, PT_ERR_INVALID_PARAM, "g_pt_info->search is NULL");
658 PT_RETV_IF(g_pt_info->searching_thd_hdl == NULL, PT_ERR_INVALID_PARAM, "g_pt_info->searching_thd_hdl is NULL");
660 pt_search_data_t *ad = g_pt_info->search;
662 if (g_pt_info->cups_checking_timer) {
663 ecore_timer_del(g_pt_info->cups_checking_timer);
664 g_pt_info->cups_checking_timer = NULL;
667 if (ecore_thread_cancel(g_pt_info->searching_thd_hdl) == EINA_FALSE) {
668 PT_DEBUG("Canceling of searching_thd_hdl[%p] is pended", g_pt_info->searching_thd_hdl);
671 g_pt_info->searching_state = PT_SEARCH_CANCEL;
673 /*clear the search result*/
674 if (ad->pt_local_list != NULL) {
675 pt_utils_free_local_printer_list(ad->pt_local_list);
676 ad->pt_local_list = NULL;
679 /*clear the search result*/
680 if (ad->response_data.printerlist != NULL) {
681 pt_utils_free_search_list(ad->response_data.printerlist);
682 ad->response_data.printerlist = NULL;
685 ad->response_data.userdata = NULL;
688 PRINT_SERVICE_FUNC_LEAVE;
693 * This API let the app get the current default printer
694 * allocates memory for printer info structure! Please free after use!
695 * @return If success, return PT_ERR_NONE, else return the other error code as defined in pt_err_t
696 * @param[out] printer the pointer to the printer object
698 int pt_get_default_printer(pt_printer_mgr_t **printer)
700 PRINT_SERVICE_FUNC_ENTER;
701 PT_RETV_IF(printer == NULL || g_pt_info == NULL, PT_ERR_INVALID_PARAM, "Invalid argument");
702 pt_printer_mgr_t *pt = NULL;
704 /* check whether if the default printer exists in the preference */
707 ret = preference_is_existing(PREFERENCE_DEFAULT_PRINTER_NAME, &isexist);
708 PT_RETV_IF(!isexist, PT_ERR_FAIL, "the default printer name isn't exist in preference!");
710 ret = preference_is_existing(PREFERENCE_DEFAULT_PRINTER_ADDRESS, &isexist);
711 PT_RETV_IF(!isexist, PT_ERR_FAIL, "the default printer name isn't exist in preference!");
713 /* get the printer in the preference */
715 ret = preference_get_string(PREFERENCE_DEFAULT_PRINTER_NAME, &name);
716 PT_RETV_IF(ret, PT_ERR_FAIL, "get the default printer name failed, errno: %d!", ret);
718 char *address = NULL;
719 ret = preference_get_string(PREFERENCE_DEFAULT_PRINTER_ADDRESS, &address);
720 PT_RETV_IF(ret, PT_ERR_FAIL, "get the default printer name failed, errno: %d!", ret);
722 pt = (pt_printer_mgr_t *)calloc(1, sizeof(pt_printer_mgr_t));
723 PT_RETV_IF(pt == NULL, PT_ERR_FAIL, "Failed to calloc pt");
724 memcpy(pt->name, name, PT_MAX_LENGTH);
725 memcpy(pt->address, address, PT_MAX_LENGTH);
727 memcpy(g_pt_info->active_printer, pt, sizeof(pt_printer_mgr_t));
729 PT_DEBUG("get printer info from preference, name: %s, address: %s!",
730 pt->name, pt->address);
732 PT_IF_FREE_MEM(name);
733 PT_IF_FREE_MEM(address);
737 PRINT_SERVICE_FUNC_LEAVE;
742 * This API let the app set a printer as the default printer
743 * @return If success, return PT_ERR_NONE, else return the other error code as defined in pt_err_t
744 * @param[in] printer the pointer to the printer object
746 int pt_set_default_printer(pt_printer_mgr_t *printer)
748 PRINT_SERVICE_FUNC_ENTER;
749 PT_RETV_IF(printer == NULL || g_pt_info == NULL, PT_ERR_INVALID_PARAM, "Invalid argument");
751 /*check the current connection*/
753 int connect_type = 0;
754 status = pt_get_connection_status(&connect_type);
756 PT_RETV_IF(status != PT_ERR_NONE, PT_ERR_FAIL, "Vconf access error");
757 PT_RETV_IF(connect_type == 0, PT_ERR_FAIL, "No available connection");
759 /* set the printer name in the preference */
761 ret = preference_set_string(PREFERENCE_DEFAULT_PRINTER_NAME, (const char *)printer->name);
762 PT_RETV_IF(ret, PT_ERR_FAIL, "set the default printer name(%s) failed!", printer->name);
764 /* set the printer address in the preference */
765 ret = preference_set_string(PREFERENCE_DEFAULT_PRINTER_ADDRESS, (const char *)printer->address);
766 PT_RETV_IF(ret, PT_ERR_FAIL, "set the default printer name(%s) failed!", printer->address);
768 /* set the printer address in the preference */
769 ret = preference_set_string(PREFERENCE_DEFAULT_PRINTER_MFG, (const char *)printer->mfg);
770 PT_RETV_IF(ret, PT_ERR_FAIL, "set the default printer name(%s) failed!", printer->mfg);
772 /* set the printer address in the preference */
773 ret = preference_set_string(PREFERENCE_DEFAULT_PRINTER_MDL, (const char *)printer->mdl);
774 PT_RETV_IF(ret, PT_ERR_FAIL, "set the default printer name(%s) failed!", printer->mdl);
776 PRINT_SERVICE_FUNC_LEAVE;
781 * This API let the app get the current active printer
782 * allocates memory for printer info structure! Please free after use!
783 * @return If success, return PT_ERR_NONE, else return the other error code as defined in pt_err_t
784 * @param[out] printer the pointer to the printer object
786 int pt_get_active_printer(pt_printer_mgr_t **printer)
788 PRINT_SERVICE_FUNC_ENTER;
789 PT_RETV_IF(g_pt_info == NULL || g_pt_info->active_printer == NULL
790 , PT_ERR_INVALID_PARAM, "global printer information is NULL or no active printer");
791 PT_RETV_IF(printer == NULL, PT_ERR_INVALID_PARAM, "printer is NULL");
793 pt_printer_mgr_t *pt = NULL;
794 pt = (pt_printer_mgr_t *)malloc(sizeof(pt_printer_mgr_t));
795 PT_RETV_IF(pt == NULL, PT_ERR_NO_MEMORY, "Not enough memory");
797 memset(pt, 0, sizeof(pt_printer_mgr_t));
798 memcpy(pt, g_pt_info->active_printer, sizeof(pt_printer_mgr_t));
800 PT_DEBUG("g_pt_info->active_printer->name %s" , g_pt_info->active_printer->name);
801 PT_DEBUG("g_pt_info->active_printer->actived = %d", g_pt_info->active_printer->actived);
802 PT_DEBUG("g_pt_info->active_printer->ppd%s" , g_pt_info->active_printer->ppd);
803 PT_DEBUG("g_pt_info->active_printer->address %s" , g_pt_info->active_printer->address);
804 PT_DEBUG("g_pt_info->active_printer->mfg %s" , g_pt_info->active_printer->mfg);
805 PT_DEBUG("g_pt_info->active_printer->mdl %s" , g_pt_info->active_printer->mdl);
809 PRINT_SERVICE_FUNC_LEAVE;
815 * This API let the app select a specify printer as active printer
816 * @return If success, return PT_ERR_NONE, else return the other error code as defined in pt_err_t
817 * @param[in] printer the pointer to the printer object
819 int pt_set_active_printer(pt_printer_mgr_t *printer)
821 PRINT_SERVICE_FUNC_ENTER;
822 PT_RETV_IF(g_pt_info == NULL || g_pt_info->active_printer == NULL
823 , PT_ERR_INVALID_PARAM, "global printer information is NULL or no active printer");
824 PT_RETV_IF(printer == NULL, PT_ERR_INVALID_PARAM, "printer is NULL");
826 /*check the current connection*/
828 int connect_type = 0;
829 status = pt_get_connection_status(&connect_type);
831 PT_RETV_IF(status != PT_ERR_NONE, PT_ERR_FAIL, "Vconf access error");
832 PT_RETV_IF(connect_type == 0, PT_ERR_FAIL, "No available connection");
834 /*register the printer*/
837 if (pt_get_printer_ppd(printer) != PT_ERR_NONE) {
838 /* Error can not get ppd info*/
839 PT_DEBUG("Get %s ppd failed", printer->name);
840 return PT_ERR_INVALID_PARAM;
843 PT_DEBUG("Get ppd info: %s", printer->ppd);
844 PT_DEBUG("address is %s", printer->address);
846 if ((strncasecmp(printer->address, "usb://", 6) == 0)) {
848 char *address = printer->address + sizeof("usb://") - 1;
849 PT_DEBUG("usb address: %s", address);
852 ret = pt_utils_regist_printer(printer->name, "usb", address, printer->ppd);
854 } else if ((strncasecmp(printer->address, "dnssd://", 8) == 0)) {
856 char *address = printer->address + sizeof("dnssd://") - 1;
857 PT_DEBUG("dnssd address: %s", address);
860 PT_DEBUG("1. printer structure address: %x", printer);
861 ret = pt_utils_regist_printer(printer->name, "dnssd", address, printer->ppd);
862 PT_DEBUG("2. printer structure address: %x", printer);
865 ret = pt_utils_regist_printer(printer->name, "socket", printer->address, printer->ppd);
868 PT_RETV_IF(ret != PT_ERR_NONE, PT_ERR_UNKNOWN, "add printer failed, description:%s", cupsLastErrorString());
870 /* only actived printer can print file */
871 printer->actived = 1;
872 memcpy(g_pt_info->active_printer, printer, sizeof(pt_printer_mgr_t));
873 PT_DEBUG("g_pt_info->active_printer->name %s" , g_pt_info->active_printer->name);
874 PT_DEBUG("g_pt_info->active_printer->address %s" , g_pt_info->active_printer->address);
875 PT_DEBUG("g_pt_info->active_printer->mfg %s" , g_pt_info->active_printer->mfg);
876 PT_DEBUG("g_pt_info->active_printer->mdl %s" , g_pt_info->active_printer->mdl);
878 PRINT_SERVICE_FUNC_LEAVE;