142a7bdedSjacobs /***************************************************************************
242a7bdedSjacobs  *
3*bbf21555SRichard Lowe  * probe-printer.c : Probe for prnio(4I) printer device information
442a7bdedSjacobs  *
542a7bdedSjacobs  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
642a7bdedSjacobs  * Use is subject to license terms.
742a7bdedSjacobs  *
842a7bdedSjacobs  * Licensed under the Academic Free License version 2.1
942a7bdedSjacobs  *
1042a7bdedSjacobs  **************************************************************************/
1142a7bdedSjacobs 
1242a7bdedSjacobs #ifdef HAVE_CONFIG_H
134e9cfc9aSjacobs #include <config.h>
1442a7bdedSjacobs #endif
1542a7bdedSjacobs 
1642a7bdedSjacobs #include <errno.h>
1742a7bdedSjacobs #include <string.h>
1842a7bdedSjacobs #include <strings.h>
1942a7bdedSjacobs #include <ctype.h>
2042a7bdedSjacobs #include <stdlib.h>
2142a7bdedSjacobs #include <stdio.h>
224e9cfc9aSjacobs #include <sys/param.h>
234e9cfc9aSjacobs #include <sys/types.h>
244e9cfc9aSjacobs #include <dirent.h>
2542a7bdedSjacobs #include <sys/ioctl.h>
2642a7bdedSjacobs #include <sys/prnio.h>
2742a7bdedSjacobs #include <fcntl.h>
2842a7bdedSjacobs #include <unistd.h>
2942a7bdedSjacobs #include <ctype.h>
3042a7bdedSjacobs 
3142a7bdedSjacobs #include <libhal.h>
3242a7bdedSjacobs #include <logger.h>
3342a7bdedSjacobs 
344e9cfc9aSjacobs #include "printer.h"
3542a7bdedSjacobs 
3642a7bdedSjacobs static int
prnio_printer_info(char * device_file,char ** manufacturer,char ** model,char ** description,char ** serial_number,char *** command_set)374e9cfc9aSjacobs prnio_printer_info(char *device_file, char **manufacturer, char **model,
384e9cfc9aSjacobs 		char **description, char **serial_number, char ***command_set)
3942a7bdedSjacobs {
4042a7bdedSjacobs 	struct prn_1284_device_id id;
4142a7bdedSjacobs 	char buf[BUFSIZ];
424e9cfc9aSjacobs 	int fd = -1, rc = -1;
4342a7bdedSjacobs 
4442a7bdedSjacobs 	memset(&id, 0, sizeof (id));
4542a7bdedSjacobs 	memset(&buf, 0, sizeof (buf));
4642a7bdedSjacobs 	id.id_data = buf;
4742a7bdedSjacobs 	id.id_len = sizeof (buf);
4842a7bdedSjacobs 
494e9cfc9aSjacobs 	if ((fd = open (device_file, O_RDONLY | O_NONBLOCK)) < 0) {
504e9cfc9aSjacobs 		goto prnio_out;
514e9cfc9aSjacobs 	}
524e9cfc9aSjacobs 
5342a7bdedSjacobs 	if (ioctl(fd, PRNIOC_GET_1284_DEVID, &id) < 0) {
544e9cfc9aSjacobs 		goto prnio_out;
5542a7bdedSjacobs 	}
5642a7bdedSjacobs 
574e9cfc9aSjacobs 	HAL_DEBUG(("IEEE-1284 DeviceId = %s", buf));
5842a7bdedSjacobs 
594e9cfc9aSjacobs 	rc = ieee1284_devid_to_printer_info(buf, manufacturer, model,
604e9cfc9aSjacobs 			description, NULL, serial_number, command_set);
6142a7bdedSjacobs 
624e9cfc9aSjacobs prnio_out:
634e9cfc9aSjacobs 	if (fd != -1)
644e9cfc9aSjacobs 		close(fd);
6542a7bdedSjacobs 
664e9cfc9aSjacobs 	return (rc);
674e9cfc9aSjacobs }
6842a7bdedSjacobs 
694e9cfc9aSjacobs /*
70*bbf21555SRichard Lowe  * It is assumed that all devices that support prnio(4I), also have a link
71*bbf21555SRichard Lowe  * in /dev/printers.
724e9cfc9aSjacobs  */
734e9cfc9aSjacobs static char *
prnio_device_name(void)744e9cfc9aSjacobs prnio_device_name(void)
754e9cfc9aSjacobs {
764e9cfc9aSjacobs 	char *result = NULL;
774e9cfc9aSjacobs 	char *devfs_path;
784e9cfc9aSjacobs 	DIR *dp;
794e9cfc9aSjacobs 
804e9cfc9aSjacobs 	if (((devfs_path = getenv("HAL_PROP_SOLARIS_DEVFS_PATH")) != NULL) &&
814e9cfc9aSjacobs 	    ((dp = opendir("/dev/printers")) != NULL)) {
824e9cfc9aSjacobs 		struct dirent *ep;
834e9cfc9aSjacobs 
844e9cfc9aSjacobs 		while ((ep = readdir(dp)) != NULL) {
854e9cfc9aSjacobs 			char path[MAXPATHLEN], lpath[MAXPATHLEN];
864e9cfc9aSjacobs 
874e9cfc9aSjacobs 			snprintf(path, sizeof (path), "/dev/printers/%s",
884e9cfc9aSjacobs 					ep->d_name);
894e9cfc9aSjacobs 			memset(lpath, 0, sizeof (lpath));
904e9cfc9aSjacobs 			if ((readlink(path, lpath, sizeof (lpath)) > 0) &&
914e9cfc9aSjacobs 			    (strstr(lpath, devfs_path) != NULL)) {
924e9cfc9aSjacobs 				result = strdup(path);
934e9cfc9aSjacobs 				break;
9442a7bdedSjacobs 			}
9542a7bdedSjacobs 		}
964e9cfc9aSjacobs 		closedir(dp);
9742a7bdedSjacobs 	}
9842a7bdedSjacobs 
994e9cfc9aSjacobs 	return (result);
10042a7bdedSjacobs }
10142a7bdedSjacobs 
1024e9cfc9aSjacobs int
main(int argc,char * argv[])1034e9cfc9aSjacobs main(int argc, char *argv[])
10442a7bdedSjacobs {
10542a7bdedSjacobs 	int ret = 1;
10642a7bdedSjacobs 	char *udi;
10742a7bdedSjacobs 	char *device_file;
1084e9cfc9aSjacobs 	char *manufacturer = NULL,
1094e9cfc9aSjacobs 	     *model = NULL,
1104e9cfc9aSjacobs 	     *serial_number = NULL,
1114e9cfc9aSjacobs 	     *description = NULL,
1124e9cfc9aSjacobs 	     **command_set = NULL;
11342a7bdedSjacobs 	DBusError error;
11442a7bdedSjacobs 	LibHalContext *ctx = NULL;
11542a7bdedSjacobs 	LibHalChangeSet *cs = NULL;
11642a7bdedSjacobs 
1174e9cfc9aSjacobs 	if ((udi = getenv("UDI")) == NULL)
11842a7bdedSjacobs 		goto out;
1194e9cfc9aSjacobs 	if ((device_file = getenv("HAL_PROP_PRINTER_DEVICE")) == NULL)
1204e9cfc9aSjacobs 		device_file = prnio_device_name();
1214e9cfc9aSjacobs 
1224e9cfc9aSjacobs 	if (device_file == NULL)
12342a7bdedSjacobs 		goto out;
12442a7bdedSjacobs 
1254e9cfc9aSjacobs 	setup_logger();
12642a7bdedSjacobs 
1274e9cfc9aSjacobs 	dbus_error_init(&error);
1284e9cfc9aSjacobs 	if ((ctx = libhal_ctx_init_direct(&error)) == NULL)
12942a7bdedSjacobs 		goto out;
13042a7bdedSjacobs 
1314e9cfc9aSjacobs 	if ((cs = libhal_device_new_changeset(udi)) == NULL) {
1324e9cfc9aSjacobs 		HAL_DEBUG(("Cannot allocate changeset"));
13342a7bdedSjacobs 		goto out;
13442a7bdedSjacobs 	}
13542a7bdedSjacobs 
136*bbf21555SRichard Lowe 	/* Probe the printer for characteristics via prnio(4I) */
1374e9cfc9aSjacobs 	ret = prnio_printer_info(device_file, &manufacturer, &model,
1384e9cfc9aSjacobs 			&description, &serial_number, &command_set);
1394e9cfc9aSjacobs 	if (ret < 0) {
1404e9cfc9aSjacobs 		HAL_DEBUG(("Cannot get prnio data for %s: %s",
1414e9cfc9aSjacobs 				device_file, strerror(errno)));
14242a7bdedSjacobs 		goto out;
14342a7bdedSjacobs 	}
14442a7bdedSjacobs 
1454e9cfc9aSjacobs 	/* Add printer characteristics to the HAL device tree */
1464e9cfc9aSjacobs 	ret = add_printer_info(cs, udi, manufacturer, model, description,
1474e9cfc9aSjacobs 			serial_number, command_set, device_file);
1484e9cfc9aSjacobs 	if (ret < 0) {
1494e9cfc9aSjacobs 		HAL_DEBUG(("Cannot add printer data for %s to %s: %s",
1504e9cfc9aSjacobs 				device_file, udi, strerror(errno)));
15142a7bdedSjacobs 		goto out;
15242a7bdedSjacobs 	}
15342a7bdedSjacobs 
1544e9cfc9aSjacobs 	libhal_device_commit_changeset(ctx, cs, &error);
15542a7bdedSjacobs 
15642a7bdedSjacobs 	ret = 0;
15742a7bdedSjacobs 
15842a7bdedSjacobs out:
15942a7bdedSjacobs 	if (cs != NULL) {
1604e9cfc9aSjacobs 		libhal_device_free_changeset(cs);
16142a7bdedSjacobs 	}
16242a7bdedSjacobs 
16342a7bdedSjacobs 	if (ctx != NULL) {
16442a7bdedSjacobs 		if (dbus_error_is_set(&error)) {
1654e9cfc9aSjacobs 			dbus_error_free(&error);
16642a7bdedSjacobs 		}
1674e9cfc9aSjacobs 		libhal_ctx_shutdown(ctx, &error);
1684e9cfc9aSjacobs 		libhal_ctx_free(ctx);
16942a7bdedSjacobs 	}
17042a7bdedSjacobs 
1714e9cfc9aSjacobs 	return (ret);
17242a7bdedSjacobs }
173