xref: /haiku/src/tests/add-ons/print/transports/main.cpp (revision 7749d0bb0c358a3279b1b9cc76d8376e900130a5)
1 #include <getopt.h>
2 #include <stdio.h>
3 
4 #include <Application.h>
5 #include <DataIO.h>
6 #include <Directory.h>
7 #include <File.h>
8 #include <FindDirectory.h>
9 #include <image.h>
10 #include <Message.h>
11 #include <Path.h>
12 #include <PrintTransportAddOn.h>
13 
14 static struct option longopts[] = {
15     { "help",		no_argument,		NULL, 'h' },
16     { "verbose",	no_argument,		NULL, 'v' },
17     { "list-ports",	no_argument,		NULL, 'p' },
18     { NULL,		0,			NULL, 0   }
19 };
20 
21 static int verbose = 0;
22 
23 
24 static void
25 usage(int argc, char** argv)
26 {
27     fprintf(stderr,
28 		"Usage: %s [OPTIONS...] transport-addon-name [file to send]\n"
29 		"\n"
30 		"  -p, --list-ports   print ports detected by the transport add-on\n"
31 		"  -v, --verbose      tell me more. Use multiple times for more details\n"
32 		"  -h, --help         display this help and exit\n"
33 		"\n", argv[0]
34 );
35 }
36 
37 
38 int main (int argc, char *argv[])
39 {
40 	int c;
41 	bool list_ports = false;
42 
43 	while ((c = getopt_long(argc, argv, "hvp", longopts, 0)) > 0) {
44 		switch (c) {
45 		case 'p':
46 	    	list_ports = true;
47 		    break;
48 		case 'v':
49 		    verbose++;
50 		    break;
51 		default:
52 		    usage(argc, argv);
53 		    return 0;
54 		}
55 	}
56     argc -= optind;
57     argv += optind;
58 
59     if (argc < 1) {
60 		usage(argc, argv);
61 		return -1;
62     }
63 
64 	new BApplication("application/x-vnd-Haiku-print_transport_tester");
65 
66 	image_id addon = -1;
67 	char *transport = argv[0];
68 
69 	printf("Looking for %s transport addon:\n", transport);
70 
71 	directory_which which[] = {
72 		B_USER_ADDONS_DIRECTORY,
73 		B_COMMON_ADDONS_DIRECTORY,
74 		B_SYSTEM_ADDONS_DIRECTORY
75 	};
76 	BPath path;
77 	for (uint32 i = 0; i <sizeof(which) / sizeof(which[0]); i++) {
78 		if (find_directory(which[i], &path, false) != B_OK)
79 			continue;
80 
81 		path.Append("Print/transport");
82 		path.Append(transport);
83 
84 		printf("\t%s ?\n", path.Path());
85 		addon = load_add_on(path.Path());
86 		if (addon >= B_OK)
87 			break;
88 	}
89 
90 	if (addon == B_ERROR) {
91 		// failed to load transport add-on
92 		printf("Failed to load \"%s\" print transport add-on!\n", transport);
93 		return -1;
94 	}
95 
96 	printf("Add-on %d = \"%s\" loaded from %s.\n", (int) addon,
97 		transport, path.Path());
98 
99 	// get init & exit proc
100 	BDataIO* (*transport_init_proc)(BMessage*) = NULL;
101 	void (*transport_exit_proc)(void) = NULL;
102 	status_t (*list_transport_ports)(BMessage*) = NULL;
103 	int* transport_features_ptr = NULL;
104 
105 	get_image_symbol(addon, "init_transport", B_SYMBOL_TYPE_TEXT, (void **) &transport_init_proc);
106 	get_image_symbol(addon, "exit_transport", B_SYMBOL_TYPE_TEXT, (void **) &transport_exit_proc);
107 
108 	get_image_symbol(addon, B_TRANSPORT_LIST_PORTS_SYMBOL, B_SYMBOL_TYPE_TEXT,
109 		(void **) &list_transport_ports);
110 	get_image_symbol(addon, B_TRANSPORT_FEATURES_SYMBOL, B_SYMBOL_TYPE_DATA,
111 		(void **) &transport_features_ptr);
112 
113 	if (transport_init_proc == NULL || transport_exit_proc == NULL) {
114 		// transport add-on has not the proper interface
115 		printf("Invalid print transport add-on API!\n");
116 		unload_add_on(addon);
117 		return B_ERROR;
118 	}
119 
120 	if (list_ports) {
121 		printf("Ports list:\n");
122 
123 		if (list_transport_ports == NULL)
124 			printf("Transport \"%s\" don't support this feature!\n", transport);
125 		else {
126 			BMessage ports;
127 			snooze(1000000);	// give some time for ports discovery
128 			status_t status = (*list_transport_ports)(&ports);
129 			if (status == B_OK)
130 				ports.PrintToStream();
131 			else
132 				printf("failed!\n");
133 		}
134 	}
135 
136 	printf("Initing %s: ", transport);
137 
138 	// now, initialize the transport add-on
139 	// request BDataIO object from transport add-on
140 	BMessage msg('TRIN');
141 	// TODO: create on the fly a temporary printer folder for testing purpose only
142 	msg.AddString("printer_file", "/boot/home/config/settings/printers/test");
143 	BDataIO *io = (*transport_init_proc)(&msg);
144 
145 	if (io) {
146 		printf("done.\nTransport parameters msg =>\n");
147 		msg.PrintToStream();
148 	} else
149 		printf("failed!\n");
150 
151 
152 	if (argc > 1) {
153 		BFile data(argv[1], B_READ_ONLY);
154 		if (data.InitCheck() == B_OK) {
155 			uint8 buffer[B_PAGE_SIZE];
156 			ssize_t total = 0;
157 			ssize_t sz;
158 
159 			printf("Sending data read from %s file...\n", argv[2]);
160 			while((sz = data.Read(buffer, sizeof(buffer))) > 0) {
161 				if (io->Write(buffer, sz) < 0) {
162 					printf("Error writting on the print transport stream!\n");
163 					break;
164 				}
165 				total += sz;
166 			}	// while
167 			printf("%ld data bytes sent.\n", total);
168 		}	// data valid file
169 	}	// optional data file
170 
171 	if (transport_exit_proc) {
172 		printf("Exiting %s...\n", transport);
173 		(*transport_exit_proc)();
174 	}
175 
176 	unload_add_on(addon);
177 	printf("%s unloaded.\n", transport);
178 
179 	return B_OK;
180 }
181 
182