[cups.development] Add Network Printer through libcups API
Michael Sweet
msweet at apple.com
Wed Aug 31 10:03:33 PDT 2011
There really is no way to do this in a generic way. You could potentially use the SNMP backend to probe the IP address for a preferred device-uri, make-and-model, and 1284 device ID, and then use the make-and-model and device ID information you get back as input to a CUPS_GET_PPDS request (see the lpinfo sources) which will provide suggested drivers.
However, I question why you are doing this in the first place - Apple already supplies UI that does this (including the IP address) when you add a printer from the Print & Scan pref pane. Is there some reason you need to duplicate the system-supplied UI?
On Aug 31, 2011, at 9:58 AM, Azuri wrote:
> Ok so can you please tell me how to do that. Only info I would have is user input IP address. So how do i create and associate PPD after that. Can you provide me with code snippet how to do it? I read ppd coumentation but not having any success. Thanks.
>
>> Correct, if you do not associate a PPD with the queue, it will not be visible to Mac applications.
>>
>> On Aug 31, 2011, at 9:38 AM, Azuri wrote:
>>> So I dont need to use that? Also why is printer not showing up in File->print menu? is ti because I dont have ppd file?
>>>
>>>> As documented, cupsAddDest DOES NOT ADD A QUEUE.
>>>>
>>>> On Aug 31, 2011, at 8:17 AM, Azuri wrote:
>>>>
>>>>> I think I should be using cupsAddDest and cupsSetDest to make it visible in mac print UI list, so I added the below code. but it still doesn't show up
>>>>> cups_dest_t *mydest;
>>>>> cups_dest_t *newdest;
>>>>> int num_new_dest;
>>>>> num_new_dest = cupsAddDest(printer, NULL, num_new_dest, &newdest);
>>>>> mydest = cupsGetDest(printer, NULL, num_new_dest, newdest);
>>>>> cupsSetDests2(http,num_new_dest, mydest);
>>>>> cupsFreeDests(num_new_dest, mydest);
>>>>>
>>>>>
>>>>>> The code I am using is as below. It shows up as raw printer in cups but when I go to any file and click on print this printer doesn't show up.
>>>>>>
>>>>>> http_t *http ;
>>>>>> char *printer = "Test";
>>>>>> char *device = "socket://10.105.152.49:9100";
>>>>>> char *model = "deskjet.ppd";
>>>>>> ipp_t *request, /* IPP Request */
>>>>>> *response; /* IPP Response */
>>>>>> ipp_t *request_dev, /* IPP Request */
>>>>>> *response_dev; /* IPP Response */
>>>>>> ipp_t *request_ppd, /* IPP Request */
>>>>>> *response_ppd; /* IPP Response */
>>>>>> char uri[HTTP_MAX_URI]; /* URI for printer/class */
>>>>>> char uri_dev[HTTP_MAX_URI];
>>>>>> char uri_ppd[HTTP_MAX_URI];
>>>>>>
>>>>>> /*
>>>>>> * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
>>>>>> * attributes:
>>>>>> *
>>>>>> * attributes-charset
>>>>>> * attributes-natural-language
>>>>>> * printer-uri
>>>>>> */
>>>>>> http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
>>>>>>
>>>>>> /* set printer device */
>>>>>> request_dev = ippNewRequest(CUPS_ADD_PRINTER);
>>>>>>
>>>>>> httpAssembleURIf(HTTP_URI_CODING_ALL, uri_dev, sizeof(uri_dev), "ipp", NULL,
>>>>>> "localhost", 0, "/printers/%s", printer);
>>>>>> ippAddString(request_dev, IPP_TAG_OPERATION, IPP_TAG_URI,
>>>>>> "printer-uri", NULL, uri_dev);
>>>>>>
>>>>>> /*
>>>>>> * Add the device URI...
>>>>>> */
>>>>>>
>>>>>> if (device[0] == '/')
>>>>>> {
>>>>>> /*
>>>>>> * Convert filename to URI...
>>>>>> */
>>>>>>
>>>>>> snprintf(uri_dev, sizeof(uri_dev), "file://%s", device);
>>>>>> ippAddString(request_dev, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
>>>>>> uri_dev);
>>>>>> }
>>>>>> else
>>>>>> ippAddString(request_dev, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
>>>>>> device);
>>>>>>
>>>>>> /*
>>>>>> * Do the request and get back a response...
>>>>>> */
>>>>>>
>>>>>> if ((response_dev = cupsDoRequest(http, request_dev, "/admin/")) == NULL)
>>>>>> {
>>>>>> _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
>>>>>>
>>>>>> // return (1);
>>>>>> }
>>>>>> else if (response_dev->request.status.status_code > IPP_OK_CONFLICT)
>>>>>> {
>>>>>> _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
>>>>>>
>>>>>> ippDelete(response_dev);
>>>>>>
>>>>>> // return (1);
>>>>>> }
>>>>>> else
>>>>>> {
>>>>>> ippDelete(response_dev);
>>>>>>
>>>>>> // return (0);
>>>>>> }
>>>>>>
>>>>>>
>>>>>> /* enable_printer */
>>>>>> request = ippNewRequest(CUPS_ADD_PRINTER);
>>>>>>
>>>>>> httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
>>>>>> "localhost", 0, "/printers/%s", printer);
>>>>>> ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
>>>>>> "printer-uri", NULL, uri);
>>>>>>
>>>>>> ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
>>>>>> IPP_PRINTER_IDLE);
>>>>>>
>>>>>> ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
>>>>>>
>>>>>> /*
>>>>>> * Do the request and get back a response...
>>>>>> */
>>>>>>
>>>>>> if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
>>>>>> {
>>>>>> _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
>>>>>>
>>>>>> //return (1);
>>>>>> }
>>>>>> else if (response->request.status.status_code > IPP_OK_CONFLICT)
>>>>>> {
>>>>>> _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
>>>>>>
>>>>>> ippDelete(response);
>>>>>>
>>>>>> //return (1);
>>>>>> }
>>>>>> else
>>>>>> {
>>>>>> ippDelete(response);
>>>>>>
>>>>>> //return (0);
>>>>>> }
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>>> Thanks Chad I was able to add a printer and enebale it and I can see it in cups webpage. But the problem is user doesn have PPD file or anything. And I am not doing anything for PPD file. After I add the printer I can see it on cups webpage but cant see int he print menu on any page,where it lists all the printers. So how do I make printer visible there?
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Azuri
>>>>>>>
>>>>>>>> The usage message for lpadmin indicates that -p is how you add a printer,
>>>>>>>> which ultimately arrives at set_printer_options(). That's where you should
>>>>>>>> be looking.
>>>>>>>>
>>>>>>>> -Chad
>>>>>>>>
>>>>>>>> On 8/30/11 4:59 PM, "Azuri" <azuri.shah at fmr.com> thusly spake:
>>>>>>>>
>>>>>>>>>
>>>>>>>>> The code I am currently using from lpadmin.c file is below. I get error saying
>>>>>>>>> can't find printer or class.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> http_t *http ;
>>>>>>>>> char *printer = "socket://10.105.152.49:9100";
>>>>>>>>> char *pclass;
>>>>>>>>> int i; /* Looping var */
>>>>>>>>> ipp_t *request, /* IPP Request */
>>>>>>>>> *response; /* IPP Response */
>>>>>>>>> ipp_attribute_t *attr, /* Current attribute */
>>>>>>>>> *members; /* Members in class */
>>>>>>>>> char uri[HTTP_MAX_URI]; /* URI for printer/class */
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> /*
>>>>>>>>> * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
>>>>>>>>> following
>>>>>>>>> * attributes:
>>>>>>>>> *
>>>>>>>>> * attributes-charset
>>>>>>>>> * attributes-natural-language
>>>>>>>>> * printer-uri
>>>>>>>>> */
>>>>>>>>> http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
>>>>>>>>> request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
>>>>>>>>>
>>>>>>>>> httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
>>>>>>>>> "localhost", 0, "/classes/%s", pclass);
>>>>>>>>> ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
>>>>>>>>> "printer-uri", NULL, uri);
>>>>>>>>>
>>>>>>>>> /*
>>>>>>>>> * Do the request and get back a response...
>>>>>>>>> */
>>>>>>>>>
>>>>>>>>> response = cupsDoRequest(http, request, "/");
>>>>>>>>>
>>>>>>>>> /*
>>>>>>>>> * Build a CUPS_ADD_CLASS request, which requires the following
>>>>>>>>> * attributes:
>>>>>>>>> *
>>>>>>>>> * attributes-charset
>>>>>>>>> * attributes-natural-language
>>>>>>>>> * printer-uri
>>>>>>>>> * member-uris
>>>>>>>>> */
>>>>>>>>>
>>>>>>>>> request = ippNewRequest(CUPS_ADD_CLASS);
>>>>>>>>>
>>>>>>>>> ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
>>>>>>>>> "printer-uri", NULL, uri);
>>>>>>>>>
>>>>>>>>> /*
>>>>>>>>> * See if the printer is already in the class...
>>>>>>>>> */
>>>>>>>>>
>>>>>>>>> if (response != NULL &&
>>>>>>>>> (members = ippFindAttribute(response, "member-names", IPP_TAG_NAME))
>>>>>>>>> != NULL)
>>>>>>>>> for (i = 0; i < members->num_values; i ++)
>>>>>>>>> if (strcasecmp(printer, members->values[i].string.text) == 0)
>>>>>>>>> {
>>>>>>>>>
>>>>>>>>> ippDelete(request);
>>>>>>>>> ippDelete(response);
>>>>>>>>> //return (0);
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> /*
>>>>>>>>> * OK, the printer isn't part of the class, so add it...
>>>>>>>>> */
>>>>>>>>>
>>>>>>>>> httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
>>>>>>>>> "localhost", 0, "/printers/%s", printer);
>>>>>>>>>
>>>>>>>>> if (response != NULL &&
>>>>>>>>> (members = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) !=
>>>>>>>>> NULL)
>>>>>>>>> {
>>>>>>>>> /*
>>>>>>>>> * Add the printer to the existing list...
>>>>>>>>> */
>>>>>>>>>
>>>>>>>>> attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
>>>>>>>>> "member-uris", members->num_values + 1, NULL,
>>>>>>>>> NULL);
>>>>>>>>> for (i = 0; i < members->num_values; i ++)
>>>>>>>>> attr->values[i].string.text =
>>>>>>>>> _cupsStrAlloc(members->values[i].string.text);
>>>>>>>>>
>>>>>>>>> attr->values[i].string.text = _cupsStrAlloc(uri);
>>>>>>>>> }
>>>>>>>>> else
>>>>>>>>> ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris",
>>>>>>>>> NULL,
>>>>>>>>> uri);
>>>>>>>>>
>>>>>>>>> /*
>>>>>>>>> * Then send the request...
>>>>>>>>> */
>>>>>>>>>
>>>>>>>>> ippDelete(response);
>>>>>>>>>
>>>>>>>>> if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
>>>>>>>>> {
>>>>>>>>>
>>>>>>>>> }
>>>>>>>>> else if (response->request.status.status_code > IPP_OK_CONFLICT)
>>>>>>>>> {
>>>>>>>>> _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
>>>>>>>>>
>>>>>>>>> ippDelete(response);
>>>>>>>>>
>>>>>>>>> }
>>>>>>>>> else
>>>>>>>>> {
>>>>>>>>> ippDelete(response);
>>>>>>>>>
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>> I did look at lpadmin.c file both its not working . But I am totally confusd.
>>>>>>>>>> I did look more into add_printer_to_class method but its not working. All I
>>>>>>>>>> want is when user enters socket://123.45.45.67 to UI, my code should go ahead
>>>>>>>>>> and add the printer tot he mac. I have spent hello lot of time trying to
>>>>>>>>>> figure this out using API's but no success at all so far. Your help will be
>>>>>>>>>> appreciated.
>>>>>>>>>>
>>>>>>>>>> Russell,
>>>>>>>>>>>
>>>>>>>>>>> Just download the CUPS source and look at the lpadmin tool.
>>>>>>>>>>>
>>>>>>>>>>> -Chad
>>>>>>>>>>>
>>>>>>>>>>> On 8/30/11 4:30 PM, "Azuri" <azuri.shah at fmr.com> thusly spake:
>>>>>>>>>>>
>>>>>>>>>>>>> Russell Stewart wrote:
>>>>>>>>>>>>>> Michael Sweet wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> You need to create an IPP request and send it using cupsDoFileRequest
>>>>>>>>>>>>>>> (assuming you are using a PPD file or interface script for the queue)
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> OK, I see. So I assume that ippNewRequest() is the method to call for
>>>>>>>>>>>>>> creating the IPP request, right?
>>>>>>>>>>>>>
>>>>>>>>>>>>> Yes. See the "CUPS Implementation of IPP" document for documentation
>>>>>>>>>>>>> on the attributes and operations:
>>>>>>>>>>>>>
>>>>>>>>>>>>> http://www.cups.org/documentation.php/spec-ipp.html
>>>>>>>>>>>>>
>>>>>>>>>>>>> --
>>>>>>>>>>>>> ______________________________________________________________________
>>>>>>>>>>>>> Michael Sweet, Easy Software Products mike at easysw dot com
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Can you please provice code on how u did it? I am trying to do the same
>>>>>>>>>>>> time
>>>>>>>>>>>> but have no success so far. How can I use API's to add printer to my mac. I
>>>>>>>>>>>> am
>>>>>>>>>>>> developing a Coca app which provides GUI and takes user input to add
>>>>>>>>>>>> printer
>>>>>>>>>>>> using cups. Please let me know
>>>>>>>>>>>> _______________________________________________
>>>>>>>>>>>> cups-dev mailing list
>>>>>>>>>>>> cups-dev at easysw.com
>>>>>>>>>>>> http://lists.easysw.com/mailman/listinfo/cups-dev
>>>>>>>>>>>
>>>>>>>>>>> Chad Hulbert
>>>>>>>>>>> Software Engineer
>>>>>>>>>>> Xerox Corporation
>>>>>>>>>>> 800 Phillips Rd
>>>>>>>>>>> Webster, NY 14580
>>>>>>>>>>>
>>>>>>>>>>> p 585.427.3295 (8*707.3295)
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> cups-dev mailing list
>>>>>>>>> cups-dev at easysw.com
>>>>>>>>> http://lists.easysw.com/mailman/listinfo/cups-dev
>>>>>>>>
>>>>>>>> Chad Hulbert
>>>>>>>> Software Engineer
>>>>>>>> Xerox Corporation
>>>>>>>> 800 Phillips Rd
>>>>>>>> Webster, NY 14580
>>>>>>>>
>>>>>>>> p 585.427.3295 (8*707.3295)
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> cups-dev mailing list
>>>>> cups-dev at easysw.com
>>>>> http://lists.easysw.com/mailman/listinfo/cups-dev
>>>>
>>>> __________________________________________________
>>>> Michael Sweet, Senior Printing System Engineer, PWG Chair
>>>>
>>>
>>> _______________________________________________
>>> cups-dev mailing list
>>> cups-dev at easysw.com
>>> http://lists.easysw.com/mailman/listinfo/cups-dev
>>
>> ________________________________________________________________________
>> Michael Sweet, Senior Printing System Engineer, PWG Chair
>>
>>
>>
>>
>>
>
> _______________________________________________
> cups-dev mailing list
> cups-dev at easysw.com
> http://lists.easysw.com/mailman/listinfo/cups-dev
________________________________________________________________________
Michael Sweet, Senior Printing System Engineer, PWG Chair
More information about the cups
mailing list