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
14static 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
21static int verbose = 0;
22
23
24static void
25usage(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
38int 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