1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * IEEE-1284 support functions for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker *
4*5e7646d2SAndroid Build Coastguard Worker * Copyright © 2007-2015 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
6*5e7646d2SAndroid Build Coastguard Worker *
7*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker * information.
9*5e7646d2SAndroid Build Coastguard Worker */
10*5e7646d2SAndroid Build Coastguard Worker
11*5e7646d2SAndroid Build Coastguard Worker /*
12*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers.
13*5e7646d2SAndroid Build Coastguard Worker */
14*5e7646d2SAndroid Build Coastguard Worker
15*5e7646d2SAndroid Build Coastguard Worker #include "backend-private.h"
16*5e7646d2SAndroid Build Coastguard Worker #include <cups/ppd-private.h>
17*5e7646d2SAndroid Build Coastguard Worker
18*5e7646d2SAndroid Build Coastguard Worker
19*5e7646d2SAndroid Build Coastguard Worker /*
20*5e7646d2SAndroid Build Coastguard Worker * 'backendGetDeviceID()' - Get the IEEE-1284 device ID string and
21*5e7646d2SAndroid Build Coastguard Worker * corresponding URI.
22*5e7646d2SAndroid Build Coastguard Worker */
23*5e7646d2SAndroid Build Coastguard Worker
24*5e7646d2SAndroid Build Coastguard Worker int /* O - 0 on success, -1 on failure */
backendGetDeviceID(int fd,char * device_id,int device_id_size,char * make_model,int make_model_size,const char * scheme,char * uri,int uri_size)25*5e7646d2SAndroid Build Coastguard Worker backendGetDeviceID(
26*5e7646d2SAndroid Build Coastguard Worker int fd, /* I - File descriptor */
27*5e7646d2SAndroid Build Coastguard Worker char *device_id, /* O - 1284 device ID */
28*5e7646d2SAndroid Build Coastguard Worker int device_id_size, /* I - Size of buffer */
29*5e7646d2SAndroid Build Coastguard Worker char *make_model, /* O - Make/model */
30*5e7646d2SAndroid Build Coastguard Worker int make_model_size, /* I - Size of buffer */
31*5e7646d2SAndroid Build Coastguard Worker const char *scheme, /* I - URI scheme */
32*5e7646d2SAndroid Build Coastguard Worker char *uri, /* O - Device URI */
33*5e7646d2SAndroid Build Coastguard Worker int uri_size) /* I - Size of buffer */
34*5e7646d2SAndroid Build Coastguard Worker {
35*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__ /* This function is a no-op */
36*5e7646d2SAndroid Build Coastguard Worker (void)fd;
37*5e7646d2SAndroid Build Coastguard Worker (void)device_id;
38*5e7646d2SAndroid Build Coastguard Worker (void)device_id_size;
39*5e7646d2SAndroid Build Coastguard Worker (void)make_model;
40*5e7646d2SAndroid Build Coastguard Worker (void)make_model_size;
41*5e7646d2SAndroid Build Coastguard Worker (void)scheme;
42*5e7646d2SAndroid Build Coastguard Worker (void)uri;
43*5e7646d2SAndroid Build Coastguard Worker (void)uri_size;
44*5e7646d2SAndroid Build Coastguard Worker
45*5e7646d2SAndroid Build Coastguard Worker return (-1);
46*5e7646d2SAndroid Build Coastguard Worker
47*5e7646d2SAndroid Build Coastguard Worker #else /* Get the device ID from the specified file descriptor... */
48*5e7646d2SAndroid Build Coastguard Worker # ifdef __linux
49*5e7646d2SAndroid Build Coastguard Worker int length; /* Length of device ID info */
50*5e7646d2SAndroid Build Coastguard Worker int got_id = 0;
51*5e7646d2SAndroid Build Coastguard Worker # endif /* __linux */
52*5e7646d2SAndroid Build Coastguard Worker # if defined(__sun) && defined(ECPPIOC_GETDEVID)
53*5e7646d2SAndroid Build Coastguard Worker struct ecpp_device_id did; /* Device ID buffer */
54*5e7646d2SAndroid Build Coastguard Worker # endif /* __sun && ECPPIOC_GETDEVID */
55*5e7646d2SAndroid Build Coastguard Worker char *ptr; /* Pointer into device ID */
56*5e7646d2SAndroid Build Coastguard Worker
57*5e7646d2SAndroid Build Coastguard Worker
58*5e7646d2SAndroid Build Coastguard Worker /*
59*5e7646d2SAndroid Build Coastguard Worker * Range check input...
60*5e7646d2SAndroid Build Coastguard Worker */
61*5e7646d2SAndroid Build Coastguard Worker
62*5e7646d2SAndroid Build Coastguard Worker if (!device_id || device_id_size < 32)
63*5e7646d2SAndroid Build Coastguard Worker {
64*5e7646d2SAndroid Build Coastguard Worker return (-1);
65*5e7646d2SAndroid Build Coastguard Worker }
66*5e7646d2SAndroid Build Coastguard Worker
67*5e7646d2SAndroid Build Coastguard Worker if (make_model)
68*5e7646d2SAndroid Build Coastguard Worker *make_model = '\0';
69*5e7646d2SAndroid Build Coastguard Worker
70*5e7646d2SAndroid Build Coastguard Worker if (fd >= 0)
71*5e7646d2SAndroid Build Coastguard Worker {
72*5e7646d2SAndroid Build Coastguard Worker /*
73*5e7646d2SAndroid Build Coastguard Worker * Get the device ID string...
74*5e7646d2SAndroid Build Coastguard Worker */
75*5e7646d2SAndroid Build Coastguard Worker
76*5e7646d2SAndroid Build Coastguard Worker *device_id = '\0';
77*5e7646d2SAndroid Build Coastguard Worker
78*5e7646d2SAndroid Build Coastguard Worker # ifdef __linux
79*5e7646d2SAndroid Build Coastguard Worker if (ioctl(fd, LPIOC_GET_DEVICE_ID((unsigned)device_id_size), device_id))
80*5e7646d2SAndroid Build Coastguard Worker {
81*5e7646d2SAndroid Build Coastguard Worker /*
82*5e7646d2SAndroid Build Coastguard Worker * Linux has to implement things differently for every device it seems.
83*5e7646d2SAndroid Build Coastguard Worker * Since the standard parallel port driver does not provide a simple
84*5e7646d2SAndroid Build Coastguard Worker * ioctl() to get the 1284 device ID, we have to open the "raw" parallel
85*5e7646d2SAndroid Build Coastguard Worker * device corresponding to this port and do some negotiation trickery
86*5e7646d2SAndroid Build Coastguard Worker * to get the current device ID.
87*5e7646d2SAndroid Build Coastguard Worker */
88*5e7646d2SAndroid Build Coastguard Worker
89*5e7646d2SAndroid Build Coastguard Worker if (uri && !strncmp(uri, "parallel:/dev/", 14))
90*5e7646d2SAndroid Build Coastguard Worker {
91*5e7646d2SAndroid Build Coastguard Worker char devparport[16]; /* /dev/parportN */
92*5e7646d2SAndroid Build Coastguard Worker int devparportfd, /* File descriptor for raw device */
93*5e7646d2SAndroid Build Coastguard Worker mode; /* Port mode */
94*5e7646d2SAndroid Build Coastguard Worker
95*5e7646d2SAndroid Build Coastguard Worker
96*5e7646d2SAndroid Build Coastguard Worker /*
97*5e7646d2SAndroid Build Coastguard Worker * Since the Linux parallel backend only supports 4 parallel port
98*5e7646d2SAndroid Build Coastguard Worker * devices, just grab the trailing digit and use it to construct a
99*5e7646d2SAndroid Build Coastguard Worker * /dev/parportN filename...
100*5e7646d2SAndroid Build Coastguard Worker */
101*5e7646d2SAndroid Build Coastguard Worker
102*5e7646d2SAndroid Build Coastguard Worker snprintf(devparport, sizeof(devparport), "/dev/parport%s",
103*5e7646d2SAndroid Build Coastguard Worker uri + strlen(uri) - 1);
104*5e7646d2SAndroid Build Coastguard Worker
105*5e7646d2SAndroid Build Coastguard Worker if ((devparportfd = open(devparport, O_RDWR | O_NOCTTY)) != -1)
106*5e7646d2SAndroid Build Coastguard Worker {
107*5e7646d2SAndroid Build Coastguard Worker /*
108*5e7646d2SAndroid Build Coastguard Worker * Claim the device...
109*5e7646d2SAndroid Build Coastguard Worker */
110*5e7646d2SAndroid Build Coastguard Worker
111*5e7646d2SAndroid Build Coastguard Worker if (!ioctl(devparportfd, PPCLAIM))
112*5e7646d2SAndroid Build Coastguard Worker {
113*5e7646d2SAndroid Build Coastguard Worker fcntl(devparportfd, F_SETFL, fcntl(devparportfd, F_GETFL) | O_NONBLOCK);
114*5e7646d2SAndroid Build Coastguard Worker
115*5e7646d2SAndroid Build Coastguard Worker mode = IEEE1284_MODE_COMPAT;
116*5e7646d2SAndroid Build Coastguard Worker
117*5e7646d2SAndroid Build Coastguard Worker if (!ioctl(devparportfd, PPNEGOT, &mode))
118*5e7646d2SAndroid Build Coastguard Worker {
119*5e7646d2SAndroid Build Coastguard Worker /*
120*5e7646d2SAndroid Build Coastguard Worker * Put the device into Device ID mode...
121*5e7646d2SAndroid Build Coastguard Worker */
122*5e7646d2SAndroid Build Coastguard Worker
123*5e7646d2SAndroid Build Coastguard Worker mode = IEEE1284_MODE_NIBBLE | IEEE1284_DEVICEID;
124*5e7646d2SAndroid Build Coastguard Worker
125*5e7646d2SAndroid Build Coastguard Worker if (!ioctl(devparportfd, PPNEGOT, &mode))
126*5e7646d2SAndroid Build Coastguard Worker {
127*5e7646d2SAndroid Build Coastguard Worker /*
128*5e7646d2SAndroid Build Coastguard Worker * Read the 1284 device ID...
129*5e7646d2SAndroid Build Coastguard Worker */
130*5e7646d2SAndroid Build Coastguard Worker
131*5e7646d2SAndroid Build Coastguard Worker if ((length = read(devparportfd, device_id, (size_t)device_id_size - 1)) >= 2)
132*5e7646d2SAndroid Build Coastguard Worker {
133*5e7646d2SAndroid Build Coastguard Worker device_id[length] = '\0';
134*5e7646d2SAndroid Build Coastguard Worker got_id = 1;
135*5e7646d2SAndroid Build Coastguard Worker }
136*5e7646d2SAndroid Build Coastguard Worker }
137*5e7646d2SAndroid Build Coastguard Worker }
138*5e7646d2SAndroid Build Coastguard Worker
139*5e7646d2SAndroid Build Coastguard Worker /*
140*5e7646d2SAndroid Build Coastguard Worker * Release the device...
141*5e7646d2SAndroid Build Coastguard Worker */
142*5e7646d2SAndroid Build Coastguard Worker
143*5e7646d2SAndroid Build Coastguard Worker ioctl(devparportfd, PPRELEASE);
144*5e7646d2SAndroid Build Coastguard Worker }
145*5e7646d2SAndroid Build Coastguard Worker
146*5e7646d2SAndroid Build Coastguard Worker close(devparportfd);
147*5e7646d2SAndroid Build Coastguard Worker }
148*5e7646d2SAndroid Build Coastguard Worker }
149*5e7646d2SAndroid Build Coastguard Worker }
150*5e7646d2SAndroid Build Coastguard Worker else
151*5e7646d2SAndroid Build Coastguard Worker got_id = 1;
152*5e7646d2SAndroid Build Coastguard Worker
153*5e7646d2SAndroid Build Coastguard Worker if (got_id)
154*5e7646d2SAndroid Build Coastguard Worker {
155*5e7646d2SAndroid Build Coastguard Worker /*
156*5e7646d2SAndroid Build Coastguard Worker * Extract the length of the device ID string from the first two
157*5e7646d2SAndroid Build Coastguard Worker * bytes. The 1284 spec says the length is stored MSB first...
158*5e7646d2SAndroid Build Coastguard Worker */
159*5e7646d2SAndroid Build Coastguard Worker
160*5e7646d2SAndroid Build Coastguard Worker length = (int)((((unsigned)device_id[0] & 255) << 8) + ((unsigned)device_id[1] & 255));
161*5e7646d2SAndroid Build Coastguard Worker
162*5e7646d2SAndroid Build Coastguard Worker /*
163*5e7646d2SAndroid Build Coastguard Worker * Check to see if the length is larger than our buffer; first
164*5e7646d2SAndroid Build Coastguard Worker * assume that the vendor incorrectly implemented the 1284 spec,
165*5e7646d2SAndroid Build Coastguard Worker * and then limit the length to the size of our buffer...
166*5e7646d2SAndroid Build Coastguard Worker */
167*5e7646d2SAndroid Build Coastguard Worker
168*5e7646d2SAndroid Build Coastguard Worker if (length > device_id_size || length < 14)
169*5e7646d2SAndroid Build Coastguard Worker length = (int)((((unsigned)device_id[1] & 255) << 8) + ((unsigned)device_id[0] & 255));
170*5e7646d2SAndroid Build Coastguard Worker
171*5e7646d2SAndroid Build Coastguard Worker if (length > device_id_size)
172*5e7646d2SAndroid Build Coastguard Worker length = device_id_size;
173*5e7646d2SAndroid Build Coastguard Worker
174*5e7646d2SAndroid Build Coastguard Worker /*
175*5e7646d2SAndroid Build Coastguard Worker * The length field counts the number of bytes in the string
176*5e7646d2SAndroid Build Coastguard Worker * including the length field itself (2 bytes). The minimum
177*5e7646d2SAndroid Build Coastguard Worker * length for a valid/usable device ID is 14 bytes:
178*5e7646d2SAndroid Build Coastguard Worker *
179*5e7646d2SAndroid Build Coastguard Worker * <LENGTH> MFG: <MFG> ;MDL: <MDL> ;
180*5e7646d2SAndroid Build Coastguard Worker * 2 + 4 + 1 + 5 + 1 + 1
181*5e7646d2SAndroid Build Coastguard Worker */
182*5e7646d2SAndroid Build Coastguard Worker
183*5e7646d2SAndroid Build Coastguard Worker if (length < 14)
184*5e7646d2SAndroid Build Coastguard Worker {
185*5e7646d2SAndroid Build Coastguard Worker /*
186*5e7646d2SAndroid Build Coastguard Worker * Can't use this device ID, so don't try to copy it...
187*5e7646d2SAndroid Build Coastguard Worker */
188*5e7646d2SAndroid Build Coastguard Worker
189*5e7646d2SAndroid Build Coastguard Worker device_id[0] = '\0';
190*5e7646d2SAndroid Build Coastguard Worker got_id = 0;
191*5e7646d2SAndroid Build Coastguard Worker }
192*5e7646d2SAndroid Build Coastguard Worker else
193*5e7646d2SAndroid Build Coastguard Worker {
194*5e7646d2SAndroid Build Coastguard Worker /*
195*5e7646d2SAndroid Build Coastguard Worker * Copy the device ID text to the beginning of the buffer and
196*5e7646d2SAndroid Build Coastguard Worker * nul-terminate.
197*5e7646d2SAndroid Build Coastguard Worker */
198*5e7646d2SAndroid Build Coastguard Worker
199*5e7646d2SAndroid Build Coastguard Worker length -= 2;
200*5e7646d2SAndroid Build Coastguard Worker
201*5e7646d2SAndroid Build Coastguard Worker memmove(device_id, device_id + 2, (size_t)length);
202*5e7646d2SAndroid Build Coastguard Worker device_id[length] = '\0';
203*5e7646d2SAndroid Build Coastguard Worker }
204*5e7646d2SAndroid Build Coastguard Worker }
205*5e7646d2SAndroid Build Coastguard Worker else
206*5e7646d2SAndroid Build Coastguard Worker {
207*5e7646d2SAndroid Build Coastguard Worker *device_id = '\0';
208*5e7646d2SAndroid Build Coastguard Worker }
209*5e7646d2SAndroid Build Coastguard Worker # endif /* __linux */
210*5e7646d2SAndroid Build Coastguard Worker
211*5e7646d2SAndroid Build Coastguard Worker # if defined(__sun) && defined(ECPPIOC_GETDEVID)
212*5e7646d2SAndroid Build Coastguard Worker did.mode = ECPP_CENTRONICS;
213*5e7646d2SAndroid Build Coastguard Worker did.len = device_id_size - 1;
214*5e7646d2SAndroid Build Coastguard Worker did.rlen = 0;
215*5e7646d2SAndroid Build Coastguard Worker did.addr = device_id;
216*5e7646d2SAndroid Build Coastguard Worker
217*5e7646d2SAndroid Build Coastguard Worker if (!ioctl(fd, ECPPIOC_GETDEVID, &did))
218*5e7646d2SAndroid Build Coastguard Worker {
219*5e7646d2SAndroid Build Coastguard Worker /*
220*5e7646d2SAndroid Build Coastguard Worker * Nul-terminate the device ID text.
221*5e7646d2SAndroid Build Coastguard Worker */
222*5e7646d2SAndroid Build Coastguard Worker
223*5e7646d2SAndroid Build Coastguard Worker if (did.rlen < (device_id_size - 1))
224*5e7646d2SAndroid Build Coastguard Worker device_id[did.rlen] = '\0';
225*5e7646d2SAndroid Build Coastguard Worker else
226*5e7646d2SAndroid Build Coastguard Worker device_id[device_id_size - 1] = '\0';
227*5e7646d2SAndroid Build Coastguard Worker }
228*5e7646d2SAndroid Build Coastguard Worker # endif /* __sun && ECPPIOC_GETDEVID */
229*5e7646d2SAndroid Build Coastguard Worker }
230*5e7646d2SAndroid Build Coastguard Worker
231*5e7646d2SAndroid Build Coastguard Worker /*
232*5e7646d2SAndroid Build Coastguard Worker * Check whether device ID is valid. Turn line breaks and tabs to spaces and
233*5e7646d2SAndroid Build Coastguard Worker * reject device IDs with non-printable characters.
234*5e7646d2SAndroid Build Coastguard Worker */
235*5e7646d2SAndroid Build Coastguard Worker
236*5e7646d2SAndroid Build Coastguard Worker for (ptr = device_id; *ptr; ptr ++)
237*5e7646d2SAndroid Build Coastguard Worker if (_cups_isspace(*ptr))
238*5e7646d2SAndroid Build Coastguard Worker *ptr = ' ';
239*5e7646d2SAndroid Build Coastguard Worker else if ((*ptr & 255) < ' ' || *ptr == 127)
240*5e7646d2SAndroid Build Coastguard Worker {
241*5e7646d2SAndroid Build Coastguard Worker *device_id = '\0';
242*5e7646d2SAndroid Build Coastguard Worker break;
243*5e7646d2SAndroid Build Coastguard Worker }
244*5e7646d2SAndroid Build Coastguard Worker
245*5e7646d2SAndroid Build Coastguard Worker if (scheme && uri)
246*5e7646d2SAndroid Build Coastguard Worker *uri = '\0';
247*5e7646d2SAndroid Build Coastguard Worker
248*5e7646d2SAndroid Build Coastguard Worker if (!*device_id)
249*5e7646d2SAndroid Build Coastguard Worker return (-1);
250*5e7646d2SAndroid Build Coastguard Worker
251*5e7646d2SAndroid Build Coastguard Worker /*
252*5e7646d2SAndroid Build Coastguard Worker * Get the make and model...
253*5e7646d2SAndroid Build Coastguard Worker */
254*5e7646d2SAndroid Build Coastguard Worker
255*5e7646d2SAndroid Build Coastguard Worker if (make_model)
256*5e7646d2SAndroid Build Coastguard Worker backendGetMakeModel(device_id, make_model, (size_t)make_model_size);
257*5e7646d2SAndroid Build Coastguard Worker
258*5e7646d2SAndroid Build Coastguard Worker /*
259*5e7646d2SAndroid Build Coastguard Worker * Then generate a device URI...
260*5e7646d2SAndroid Build Coastguard Worker */
261*5e7646d2SAndroid Build Coastguard Worker
262*5e7646d2SAndroid Build Coastguard Worker if (scheme && uri && uri_size > 32)
263*5e7646d2SAndroid Build Coastguard Worker {
264*5e7646d2SAndroid Build Coastguard Worker int num_values; /* Number of keys and values */
265*5e7646d2SAndroid Build Coastguard Worker cups_option_t *values; /* Keys and values in device ID */
266*5e7646d2SAndroid Build Coastguard Worker const char *mfg, /* Manufacturer */
267*5e7646d2SAndroid Build Coastguard Worker *mdl, /* Model */
268*5e7646d2SAndroid Build Coastguard Worker *sern; /* Serial number */
269*5e7646d2SAndroid Build Coastguard Worker char temp[256], /* Temporary manufacturer string */
270*5e7646d2SAndroid Build Coastguard Worker *tempptr; /* Pointer into temp string */
271*5e7646d2SAndroid Build Coastguard Worker
272*5e7646d2SAndroid Build Coastguard Worker
273*5e7646d2SAndroid Build Coastguard Worker /*
274*5e7646d2SAndroid Build Coastguard Worker * Get the make, model, and serial numbers...
275*5e7646d2SAndroid Build Coastguard Worker */
276*5e7646d2SAndroid Build Coastguard Worker
277*5e7646d2SAndroid Build Coastguard Worker num_values = _cupsGet1284Values(device_id, &values);
278*5e7646d2SAndroid Build Coastguard Worker
279*5e7646d2SAndroid Build Coastguard Worker if ((sern = cupsGetOption("SERIALNUMBER", num_values, values)) == NULL)
280*5e7646d2SAndroid Build Coastguard Worker if ((sern = cupsGetOption("SERN", num_values, values)) == NULL)
281*5e7646d2SAndroid Build Coastguard Worker sern = cupsGetOption("SN", num_values, values);
282*5e7646d2SAndroid Build Coastguard Worker
283*5e7646d2SAndroid Build Coastguard Worker if ((mfg = cupsGetOption("MANUFACTURER", num_values, values)) == NULL)
284*5e7646d2SAndroid Build Coastguard Worker mfg = cupsGetOption("MFG", num_values, values);
285*5e7646d2SAndroid Build Coastguard Worker
286*5e7646d2SAndroid Build Coastguard Worker if ((mdl = cupsGetOption("MODEL", num_values, values)) == NULL)
287*5e7646d2SAndroid Build Coastguard Worker mdl = cupsGetOption("MDL", num_values, values);
288*5e7646d2SAndroid Build Coastguard Worker
289*5e7646d2SAndroid Build Coastguard Worker if (mfg)
290*5e7646d2SAndroid Build Coastguard Worker {
291*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(mfg, "Hewlett-Packard"))
292*5e7646d2SAndroid Build Coastguard Worker mfg = "HP";
293*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(mfg, "Lexmark International"))
294*5e7646d2SAndroid Build Coastguard Worker mfg = "Lexmark";
295*5e7646d2SAndroid Build Coastguard Worker }
296*5e7646d2SAndroid Build Coastguard Worker else
297*5e7646d2SAndroid Build Coastguard Worker {
298*5e7646d2SAndroid Build Coastguard Worker strlcpy(temp, make_model, sizeof(temp));
299*5e7646d2SAndroid Build Coastguard Worker
300*5e7646d2SAndroid Build Coastguard Worker if ((tempptr = strchr(temp, ' ')) != NULL)
301*5e7646d2SAndroid Build Coastguard Worker *tempptr = '\0';
302*5e7646d2SAndroid Build Coastguard Worker
303*5e7646d2SAndroid Build Coastguard Worker mfg = temp;
304*5e7646d2SAndroid Build Coastguard Worker }
305*5e7646d2SAndroid Build Coastguard Worker
306*5e7646d2SAndroid Build Coastguard Worker if (!mdl)
307*5e7646d2SAndroid Build Coastguard Worker mdl = "";
308*5e7646d2SAndroid Build Coastguard Worker
309*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strncasecmp(mdl, mfg, strlen(mfg)))
310*5e7646d2SAndroid Build Coastguard Worker {
311*5e7646d2SAndroid Build Coastguard Worker mdl += strlen(mfg);
312*5e7646d2SAndroid Build Coastguard Worker
313*5e7646d2SAndroid Build Coastguard Worker while (isspace(*mdl & 255))
314*5e7646d2SAndroid Build Coastguard Worker mdl ++;
315*5e7646d2SAndroid Build Coastguard Worker }
316*5e7646d2SAndroid Build Coastguard Worker
317*5e7646d2SAndroid Build Coastguard Worker /*
318*5e7646d2SAndroid Build Coastguard Worker * Generate the device URI from the manufacturer, make_model, and
319*5e7646d2SAndroid Build Coastguard Worker * serial number strings.
320*5e7646d2SAndroid Build Coastguard Worker */
321*5e7646d2SAndroid Build Coastguard Worker
322*5e7646d2SAndroid Build Coastguard Worker httpAssembleURIf(HTTP_URI_CODING_ALL, uri, uri_size, scheme, NULL, mfg, 0,
323*5e7646d2SAndroid Build Coastguard Worker "/%s%s%s", mdl, sern ? "?serial=" : "", sern ? sern : "");
324*5e7646d2SAndroid Build Coastguard Worker
325*5e7646d2SAndroid Build Coastguard Worker cupsFreeOptions(num_values, values);
326*5e7646d2SAndroid Build Coastguard Worker }
327*5e7646d2SAndroid Build Coastguard Worker
328*5e7646d2SAndroid Build Coastguard Worker return (0);
329*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
330*5e7646d2SAndroid Build Coastguard Worker }
331*5e7646d2SAndroid Build Coastguard Worker
332*5e7646d2SAndroid Build Coastguard Worker
333*5e7646d2SAndroid Build Coastguard Worker /*
334*5e7646d2SAndroid Build Coastguard Worker * 'backendGetMakeModel()' - Get the make and model string from the device ID.
335*5e7646d2SAndroid Build Coastguard Worker */
336*5e7646d2SAndroid Build Coastguard Worker
337*5e7646d2SAndroid Build Coastguard Worker int /* O - 0 on success, -1 on failure */
backendGetMakeModel(const char * device_id,char * make_model,size_t make_model_size)338*5e7646d2SAndroid Build Coastguard Worker backendGetMakeModel(
339*5e7646d2SAndroid Build Coastguard Worker const char *device_id, /* O - 1284 device ID */
340*5e7646d2SAndroid Build Coastguard Worker char *make_model, /* O - Make/model */
341*5e7646d2SAndroid Build Coastguard Worker size_t make_model_size) /* I - Size of buffer */
342*5e7646d2SAndroid Build Coastguard Worker {
343*5e7646d2SAndroid Build Coastguard Worker int num_values; /* Number of keys and values */
344*5e7646d2SAndroid Build Coastguard Worker cups_option_t *values; /* Keys and values */
345*5e7646d2SAndroid Build Coastguard Worker const char *mfg, /* Manufacturer string */
346*5e7646d2SAndroid Build Coastguard Worker *mdl, /* Model string */
347*5e7646d2SAndroid Build Coastguard Worker *des; /* Description string */
348*5e7646d2SAndroid Build Coastguard Worker
349*5e7646d2SAndroid Build Coastguard Worker
350*5e7646d2SAndroid Build Coastguard Worker /*
351*5e7646d2SAndroid Build Coastguard Worker * Range check input...
352*5e7646d2SAndroid Build Coastguard Worker */
353*5e7646d2SAndroid Build Coastguard Worker
354*5e7646d2SAndroid Build Coastguard Worker if (!device_id || !*device_id || !make_model || make_model_size < 32)
355*5e7646d2SAndroid Build Coastguard Worker return (-1);
356*5e7646d2SAndroid Build Coastguard Worker
357*5e7646d2SAndroid Build Coastguard Worker *make_model = '\0';
358*5e7646d2SAndroid Build Coastguard Worker
359*5e7646d2SAndroid Build Coastguard Worker /*
360*5e7646d2SAndroid Build Coastguard Worker * Look for the description field...
361*5e7646d2SAndroid Build Coastguard Worker */
362*5e7646d2SAndroid Build Coastguard Worker
363*5e7646d2SAndroid Build Coastguard Worker num_values = _cupsGet1284Values(device_id, &values);
364*5e7646d2SAndroid Build Coastguard Worker
365*5e7646d2SAndroid Build Coastguard Worker if ((mdl = cupsGetOption("MODEL", num_values, values)) == NULL)
366*5e7646d2SAndroid Build Coastguard Worker mdl = cupsGetOption("MDL", num_values, values);
367*5e7646d2SAndroid Build Coastguard Worker
368*5e7646d2SAndroid Build Coastguard Worker if (mdl)
369*5e7646d2SAndroid Build Coastguard Worker {
370*5e7646d2SAndroid Build Coastguard Worker /*
371*5e7646d2SAndroid Build Coastguard Worker * Build a make-model string from the manufacturer and model attributes...
372*5e7646d2SAndroid Build Coastguard Worker */
373*5e7646d2SAndroid Build Coastguard Worker
374*5e7646d2SAndroid Build Coastguard Worker if ((mfg = cupsGetOption("MANUFACTURER", num_values, values)) == NULL)
375*5e7646d2SAndroid Build Coastguard Worker mfg = cupsGetOption("MFG", num_values, values);
376*5e7646d2SAndroid Build Coastguard Worker
377*5e7646d2SAndroid Build Coastguard Worker if (!mfg || !_cups_strncasecmp(mdl, mfg, strlen(mfg)))
378*5e7646d2SAndroid Build Coastguard Worker {
379*5e7646d2SAndroid Build Coastguard Worker /*
380*5e7646d2SAndroid Build Coastguard Worker * Just copy the model string, since it has the manufacturer...
381*5e7646d2SAndroid Build Coastguard Worker */
382*5e7646d2SAndroid Build Coastguard Worker
383*5e7646d2SAndroid Build Coastguard Worker _ppdNormalizeMakeAndModel(mdl, make_model, make_model_size);
384*5e7646d2SAndroid Build Coastguard Worker }
385*5e7646d2SAndroid Build Coastguard Worker else
386*5e7646d2SAndroid Build Coastguard Worker {
387*5e7646d2SAndroid Build Coastguard Worker /*
388*5e7646d2SAndroid Build Coastguard Worker * Concatenate the make and model...
389*5e7646d2SAndroid Build Coastguard Worker */
390*5e7646d2SAndroid Build Coastguard Worker
391*5e7646d2SAndroid Build Coastguard Worker char temp[1024]; /* Temporary make and model */
392*5e7646d2SAndroid Build Coastguard Worker
393*5e7646d2SAndroid Build Coastguard Worker snprintf(temp, sizeof(temp), "%s %s", mfg, mdl);
394*5e7646d2SAndroid Build Coastguard Worker
395*5e7646d2SAndroid Build Coastguard Worker _ppdNormalizeMakeAndModel(temp, make_model, make_model_size);
396*5e7646d2SAndroid Build Coastguard Worker }
397*5e7646d2SAndroid Build Coastguard Worker }
398*5e7646d2SAndroid Build Coastguard Worker else if ((des = cupsGetOption("DESCRIPTION", num_values, values)) != NULL ||
399*5e7646d2SAndroid Build Coastguard Worker (des = cupsGetOption("DES", num_values, values)) != NULL)
400*5e7646d2SAndroid Build Coastguard Worker {
401*5e7646d2SAndroid Build Coastguard Worker /*
402*5e7646d2SAndroid Build Coastguard Worker * Make sure the description contains something useful, since some
403*5e7646d2SAndroid Build Coastguard Worker * printer manufacturers (HP) apparently don't follow the standards
404*5e7646d2SAndroid Build Coastguard Worker * they helped to define...
405*5e7646d2SAndroid Build Coastguard Worker *
406*5e7646d2SAndroid Build Coastguard Worker * Here we require the description to be 8 or more characters in length,
407*5e7646d2SAndroid Build Coastguard Worker * containing at least one space and one letter.
408*5e7646d2SAndroid Build Coastguard Worker */
409*5e7646d2SAndroid Build Coastguard Worker
410*5e7646d2SAndroid Build Coastguard Worker if (strlen(des) >= 8)
411*5e7646d2SAndroid Build Coastguard Worker {
412*5e7646d2SAndroid Build Coastguard Worker const char *ptr; /* Pointer into description */
413*5e7646d2SAndroid Build Coastguard Worker int letters, /* Number of letters seen */
414*5e7646d2SAndroid Build Coastguard Worker spaces; /* Number of spaces seen */
415*5e7646d2SAndroid Build Coastguard Worker
416*5e7646d2SAndroid Build Coastguard Worker
417*5e7646d2SAndroid Build Coastguard Worker for (ptr = des, letters = 0, spaces = 0; *ptr; ptr ++)
418*5e7646d2SAndroid Build Coastguard Worker {
419*5e7646d2SAndroid Build Coastguard Worker if (isspace(*ptr & 255))
420*5e7646d2SAndroid Build Coastguard Worker spaces ++;
421*5e7646d2SAndroid Build Coastguard Worker else if (isalpha(*ptr & 255))
422*5e7646d2SAndroid Build Coastguard Worker letters ++;
423*5e7646d2SAndroid Build Coastguard Worker
424*5e7646d2SAndroid Build Coastguard Worker if (spaces && letters)
425*5e7646d2SAndroid Build Coastguard Worker break;
426*5e7646d2SAndroid Build Coastguard Worker }
427*5e7646d2SAndroid Build Coastguard Worker
428*5e7646d2SAndroid Build Coastguard Worker if (spaces && letters)
429*5e7646d2SAndroid Build Coastguard Worker _ppdNormalizeMakeAndModel(des, make_model, make_model_size);
430*5e7646d2SAndroid Build Coastguard Worker }
431*5e7646d2SAndroid Build Coastguard Worker }
432*5e7646d2SAndroid Build Coastguard Worker
433*5e7646d2SAndroid Build Coastguard Worker if (!make_model[0])
434*5e7646d2SAndroid Build Coastguard Worker {
435*5e7646d2SAndroid Build Coastguard Worker /*
436*5e7646d2SAndroid Build Coastguard Worker * Use "Unknown" as the printer make and model...
437*5e7646d2SAndroid Build Coastguard Worker */
438*5e7646d2SAndroid Build Coastguard Worker
439*5e7646d2SAndroid Build Coastguard Worker strlcpy(make_model, "Unknown", make_model_size);
440*5e7646d2SAndroid Build Coastguard Worker }
441*5e7646d2SAndroid Build Coastguard Worker
442*5e7646d2SAndroid Build Coastguard Worker cupsFreeOptions(num_values, values);
443*5e7646d2SAndroid Build Coastguard Worker
444*5e7646d2SAndroid Build Coastguard Worker return (0);
445*5e7646d2SAndroid Build Coastguard Worker }
446