[cups.development] Add Network Printer through libcups API

Michael Sweet msweet at apple.com
Wed Aug 31 21:23:12 PDT 2011


Not on the API side, but the backends can sometimes discover printer make and model, and from that we can suggest a driver (as I mention below...)

On Aug 31, 2011, at 8:39 PM, Azuri wrote:

> I know in CUPS web page when I select the printer model and make, it goes and figure out the required ppd files and all. SO on the API side it it possible to retrieve printer make and model from IP adress and then some cups API which goes ahead and finds out and links the correct ppd file?
> 
> Thanks,
> Azuri
> 
>> I need to develop a different GUI just for the consitency between system,s. So I am developing an app which calls cups at back end
>> 
>>> 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
>>> 
>>> 
>>> 
>>> 
>>> 
>> 
> 
> _______________________________________________
> 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