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_NONPACKAGED_ADDONS_DIRECTORY,
73		B_USER_ADDONS_DIRECTORY,
74		B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY,
75		B_SYSTEM_ADDONS_DIRECTORY
76	};
77	BPath path;
78	for (uint32 i = 0; i <sizeof(which) / sizeof(which[0]); i++) {
79		if (find_directory(which[i], &path, false) != B_OK)
80			continue;
81
82		path.Append("Print/transport");
83		path.Append(transport);
84
85		printf("\t%s ?\n", path.Path());
86		addon = load_add_on(path.Path());
87		if (addon >= B_OK)
88			break;
89	}
90
91	if (addon == B_ERROR) {
92		// failed to load transport add-on
93		printf("Failed to load \"%s\" print transport add-on!\n", transport);
94		return -1;
95	}
96
97	printf("Add-on %d = \"%s\" loaded from %s.\n", (int) addon,
98		transport, path.Path());
99
100	// get init & exit proc
101	BDataIO* (*transport_init_proc)(BMessage*) = NULL;
102	void (*transport_exit_proc)(void) = NULL;
103	status_t (*list_transport_ports)(BMessage*) = NULL;
104	int* transport_features_ptr = NULL;
105
106	get_image_symbol(addon, "init_transport", B_SYMBOL_TYPE_TEXT, (void **) &transport_init_proc);
107	get_image_symbol(addon, "exit_transport", B_SYMBOL_TYPE_TEXT, (void **) &transport_exit_proc);
108
109	get_image_symbol(addon, B_TRANSPORT_LIST_PORTS_SYMBOL, B_SYMBOL_TYPE_TEXT,
110		(void **) &list_transport_ports);
111	get_image_symbol(addon, B_TRANSPORT_FEATURES_SYMBOL, B_SYMBOL_TYPE_DATA,
112		(void **) &transport_features_ptr);
113
114	if (transport_init_proc == NULL || transport_exit_proc == NULL) {
115		// transport add-on has not the proper interface
116		printf("Invalid print transport add-on API!\n");
117		unload_add_on(addon);
118		return B_ERROR;
119	}
120
121	if (list_ports) {
122		printf("Ports list:\n");
123
124		if (list_transport_ports == NULL)
125			printf("Transport \"%s\" don't support this feature!\n", transport);
126		else {
127			BMessage ports;
128			snooze(1000000);	// give some time for ports discovery
129			status_t status = (*list_transport_ports)(&ports);
130			if (status == B_OK)
131				ports.PrintToStream();
132			else
133				printf("failed!\n");
134		}
135	}
136
137	printf("Initing %s: ", transport);
138
139	// now, initialize the transport add-on
140	// request BDataIO object from transport add-on
141	BMessage msg('TRIN');
142	// TODO: create on the fly a temporary printer folder for testing purpose only
143	msg.AddString("printer_file", "/boot/home/config/settings/printers/test");
144	BDataIO *io = (*transport_init_proc)(&msg);
145
146	if (io) {
147		printf("done.\nTransport parameters msg =>\n");
148		msg.PrintToStream();
149	} else
150		printf("failed!\n");
151
152
153	if (argc > 1) {
154		BFile data(argv[1], B_READ_ONLY);
155		if (data.InitCheck() == B_OK) {
156			uint8 buffer[B_PAGE_SIZE];
157			ssize_t total = 0;
158			ssize_t sz;
159
160			printf("Sending data read from %s file...\n", argv[2]);
161			while((sz = data.Read(buffer, sizeof(buffer))) > 0) {
162				if (io->Write(buffer, sz) < 0) {
163					printf("Error writting on the print transport stream!\n");
164					break;
165				}
166				total += sz;
167			}	// while
168			printf("%ld data bytes sent.\n", total);
169		}	// data valid file
170	}	// optional data file
171
172	if (transport_exit_proc) {
173		printf("Exiting %s...\n", transport);
174		(*transport_exit_proc)();
175	}
176
177	unload_add_on(addon);
178	printf("%s unloaded.\n", transport);
179
180	return B_OK;
181}
182
183