xref: /third_party/backends/japi/Sane.c (revision 141cc406)
1/* sane - Scanner Access Now Easy.
2   Copyright (C) 1997 Jeffrey S. Freedman
3   This file is part of the SANE package.
4
5   This program is free software; you can redistribute it and/or
6   modify it under the terms of the GNU General Public License as
7   published by the Free Software Foundation; either version 2 of the
8   License, or (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <https://www.gnu.org/licenses/>.
17
18   As a special exception, the authors of SANE give permission for
19   additional uses of the libraries contained in this release of SANE.
20
21   The exception is that, if you link a SANE library with other files
22   to produce an executable, this does not by itself cause the
23   resulting executable to be covered by the GNU General Public
24   License.  Your use of that executable is in no way restricted on
25   account of linking the SANE library code into it.
26
27   This exception does not, however, invalidate any other reasons why
28   the executable file might be covered by the GNU General Public
29   License.
30
31   If you submit changes to SANE to the maintainers to be included in
32   a subsequent release, you agree by submitting the changes that
33   those changes may be distributed with this exception intact.
34
35   If you write modifications of your own for SANE, it is your choice
36   whether to permit this exception to apply to your modifications.
37   If you do not wish that, delete this exception notice.  */
38
39/**
40 **	Sane.c - Native methods for the SANE Java API.
41 **
42 **	Written: 10/9/97 - JSF
43 **/
44
45#include "Sane.h"
46#include <sane/sane.h>
47#include <string.h>
48
49#include <stdio.h>	/* Debugging */
50
51#ifdef __cplusplus
52extern "C" {
53#endif
54/*
55 * Class:     Sane
56 * Method:    init
57 * Signature: ([I)I
58 */
59JNIEXPORT jint JNICALL Java_Sane_init
60  (JNIEnv *env, jobject jobj, jintArray versionCode)
61	{
62	jsize len;			/* Gets array length. */
63	jint *versionCodeBody;		/* Gets ->array. */
64	SANE_Int version;		/* Gets version. */
65	SANE_Status status;		/* Get SANE return. */
66
67	status = sane_init(&version, 0);
68	len = (*env)->GetArrayLength(env, versionCode);
69	versionCodeBody = (*env)->GetIntArrayElements(env, versionCode, 0);
70	if (len > 0)			/* Return version. */
71		versionCodeBody[0] = version;
72	(*env)->ReleaseIntArrayElements(env, versionCode, versionCodeBody, 0);
73	return (status);
74	}
75/*
76 * Class:     Sane
77 * Method:    exit
78 * Signature: ()V
79 */
80JNIEXPORT void JNICALL Java_Sane_exit
81  (JNIEnv *env, jobject jobj)
82	{
83	sane_exit();
84	}
85
86
87/*
88 * Class:     Sane
89 * Method:    getDevices
90 * Signature: ([LSaneDevice;Z)I
91 */
92JNIEXPORT jint JNICALL Java_Sane_getDevicesNative
93  (JNIEnv *env, jobject jobj, jobjectArray devList, jboolean localOnly)
94	{
95					/* Gets device list. */
96	const SANE_Device **device_list;
97	SANE_Status status;		/* Gets status. */
98	int devListLen;			/* Gets length of devList. */
99	jobject devObj;			/* Gets each SaneDevice object. */
100	jclass devClass;		/* Gets SaneDevice class. */
101	jfieldID fid;			/* Gets each field ID. */
102	int i;
103
104					/* Get the list. */
105	status = sane_get_devices(&device_list, localOnly);
106	if (status != SANE_STATUS_GOOD)
107		return (status);
108					/* Get length of Java array. */
109	devListLen = (*env)->GetArrayLength(env, devList);
110					/* Return devices to user. */
111	for (i = 0; i < devListLen - 1 && device_list[i]; i++)
112		{
113					/* Get Java object, class. */
114		devObj = (*env)->GetObjectArrayElement(env, devList, i);
115		devClass = (*env)->GetObjectClass(env, devObj);
116					/* Fill in each member. */
117		fid = (*env)->GetFieldID(env, devClass, "name",
118							"Ljava/lang/String;");
119		(*env)->SetObjectField(env, devObj, fid,
120			(*env)->NewStringUTF(env, device_list[i]->name));
121		fid = (*env)->GetFieldID(env, devClass, "vendor",
122							"Ljava/lang/String;");
123		(*env)->SetObjectField(env, devObj, fid,
124			(*env)->NewStringUTF(env, device_list[i]->vendor));
125		fid = (*env)->GetFieldID(env, devClass, "model",
126							"Ljava/lang/String;");
127		(*env)->SetObjectField(env, devObj, fid,
128			(*env)->NewStringUTF(env, device_list[i]->model));
129		fid = (*env)->GetFieldID(env, devClass, "type",
130							"Ljava/lang/String;");
131		(*env)->SetObjectField(env, devObj, fid,
132			(*env)->NewStringUTF(env, device_list[i]->type));
133		}
134					/* End list with a null. */
135	(*env)->SetObjectArrayElement(env, devList, i, 0);
136	return (status);
137	}
138
139/*
140 * Class:     Sane
141 * Method:    open
142 * Signature: (Ljava/lang/String;[J)I
143 */
144JNIEXPORT jint JNICALL Java_Sane_open
145  (JNIEnv *env, jobject jobj, jstring deviceName, jintArray handle)
146	{
147	SANE_Handle sane_handle;	/* Gets handle. */
148	jint s_handle;
149	const char *device_name;	/* Gets dev. name. */
150	int status;			/* Gets return code. */
151
152	device_name = (*env)->GetStringUTFChars(env, deviceName, 0);
153					/* Open it. */
154	status = sane_open(device_name, &sane_handle);
155	(*env)->ReleaseStringUTFChars(env, deviceName, device_name);
156					/* Return handle. */
157	s_handle = (jint) sane_handle;
158	(*env)->SetIntArrayRegion(env, handle, 0, 1, &s_handle);
159	return (status);
160	}
161
162/*
163 * Class:     Sane
164 * Method:    close
165 * Signature: (J)V
166 */
167JNIEXPORT void JNICALL Java_Sane_close
168  (JNIEnv *env, jobject jobj, jint handle)
169	{
170	sane_close((SANE_Handle) handle);
171	}
172
173/*
174 * Class:     Sane
175 * Method:    getOptionNative
176 * Signature: (IILSaneOption;)V
177 */
178JNIEXPORT void JNICALL Java_Sane_getOptionNative
179  (JNIEnv *env, jobject jobj, jint handle, jint option, jobject optObj)
180	{
181	jclass optClass;		/* Gets its class. */
182	jfieldID fid;			/* Gets each field ID. */
183	jstring str;			/* Gets strings. */
184
185					/* Get info from sane. */
186	const SANE_Option_Descriptor *sopt = sane_get_option_descriptor(
187			(SANE_Handle) handle, option);
188					/* Get class info. */
189	optClass = (*env)->GetObjectClass(env, optObj);
190					/* Fill in each member. */
191	fid = (*env)->GetFieldID(env, optClass, "name", "Ljava/lang/String;");
192	if (!sopt)			/* Failed. */
193		{			/* Set name to null. */
194		(*env)->SetObjectField(env, optObj, fid, 0);
195		return;
196		}
197					/* Return name. */
198	(*env)->SetObjectField(env, optObj, fid,
199				(*env)->NewStringUTF(env, sopt->name));
200					/* Return title. */
201	fid = (*env)->GetFieldID(env, optClass, "title", "Ljava/lang/String;");
202	str = sopt->title ? (*env)->NewStringUTF(env, sopt->title) : 0;
203	(*env)->SetObjectField(env, optObj, fid, str);
204					/* Return descr. */
205	fid = (*env)->GetFieldID(env, optClass, "desc", "Ljava/lang/String;");
206	(*env)->SetObjectField(env, optObj, fid,
207				(*env)->NewStringUTF(env, sopt->desc));
208					/* Return type. */
209	fid = (*env)->GetFieldID(env, optClass, "type", "I");
210	(*env)->SetIntField(env, optObj, fid, sopt->type);
211					/* Return unit. */
212	fid = (*env)->GetFieldID(env, optClass, "unit", "I");
213	(*env)->SetIntField(env, optObj, fid, sopt->unit);
214					/* Return size. */
215	fid = (*env)->GetFieldID(env, optClass, "size", "I");
216	(*env)->SetIntField(env, optObj, fid, sopt->size);
217					/* Return cap. */
218	fid = (*env)->GetFieldID(env, optClass, "cap", "I");
219	(*env)->SetIntField(env, optObj, fid, sopt->cap);
220					/* Return constraint_type. */
221	fid = (*env)->GetFieldID(env, optClass, "constraintType", "I");
222	(*env)->SetIntField(env, optObj, fid, sopt->constraint_type);
223	/*
224	 *	Now for the constraint itself.
225	 */
226	if (sopt->constraint_type == SANE_CONSTRAINT_RANGE)
227		{
228					/* Create range object. */
229		jclass rangeClass = (*env)->FindClass(env, "SaneRange");
230		jobject range = (*env)->AllocObject(env, rangeClass);
231					/* Fill in fields. */
232		fid = (*env)->GetFieldID(env, rangeClass, "min", "I");
233		(*env)->SetIntField(env, range, fid,
234						sopt->constraint.range->min);
235		fid = (*env)->GetFieldID(env, rangeClass, "max", "I");
236		(*env)->SetIntField(env, range, fid,
237						sopt->constraint.range->max);
238		fid = (*env)->GetFieldID(env, rangeClass, "quant", "I");
239		(*env)->SetIntField(env, range, fid,
240						sopt->constraint.range->quant);
241		fid = (*env)->GetFieldID(env, optClass, "rangeConstraint",
242						"LSaneRange;");
243					/* Store range. */
244		(*env)->SetObjectField(env, optObj, fid, range);
245		}
246	else if (sopt->constraint_type == SANE_CONSTRAINT_WORD_LIST)
247		{			/* Get array of integers. */
248		jintArray wordList;
249		jint *elements;
250		int i;
251					/* First word. is the length.	*/
252		wordList = (*env)->NewIntArray(env,
253				sopt->constraint.word_list[0]);
254					/* Copy in the integers.	*/
255		elements = (*env)->GetIntArrayElements(env, wordList, 0);
256		for (i = 0; i < sopt->constraint.word_list[0]; i++)
257			elements[i] = sopt->constraint.word_list[i];
258		(*env)->ReleaseIntArrayElements(env, wordList, elements, 0);
259					/* Set the field. */
260		fid = (*env)->GetFieldID(env, optClass, "wordListConstraint",
261									"[I");
262		(*env)->SetObjectField(env, optObj, fid, wordList);
263		}
264	else if (sopt->constraint_type == SANE_CONSTRAINT_STRING_LIST)
265		{
266		jclass stringClass = (*env)->FindClass(env, "java/lang/String");
267		jobjectArray stringList;
268		int len;		/* Gets # elements */
269		int i;
270
271		for (len = 0; sopt->constraint.string_list[len]; len++)
272			;
273		stringList = (*env)->NewObjectArray(env, len + 1,
274							stringClass, 0);
275					/* Add each string. */
276		for (i = 0; i < len; i++)
277			{
278			(*env)->SetObjectArrayElement(env, stringList, i,
279				(*env)->NewStringUTF(env,
280					sopt->constraint.string_list[i]));
281			}
282					/* 0 at end. */
283		(*env)->SetObjectArrayElement(env, stringList, len, 0);
284					/* Set the field. */
285		fid = (*env)->GetFieldID(env, optClass,
286			"stringListConstraint", "[Ljava/lang/String;");
287		(*env)->SetObjectField(env, optObj, fid, stringList);
288		}
289	}
290
291/*
292 * Class:     Sane
293 * Method:    getControlOption
294 * Signature: (II[I[I)I
295 */
296JNIEXPORT jint JNICALL Java_Sane_getControlOption__II_3I_3I
297  (JNIEnv *env, jobject jobj, jint handle, jint option, jintArray value,
298						jintArray info)
299	{
300	SANE_Status status;		/* Gets status. */
301	SANE_Int i;			/* Gets info. passed back. */
302	int v;
303
304	status = sane_control_option((SANE_Handle) handle, option,
305			SANE_ACTION_GET_VALUE, &v, &i);
306	if (value)
307		(*env)->SetIntArrayRegion(env, value, 0, 1, &v);
308	if (info)
309		(*env)->SetIntArrayRegion(env, info, 0, 1, &i);
310	return (status);
311	}
312
313/*
314 * Class:     Sane
315 * Method:    getControlOption
316 * Signature: (II[B[I)I
317 */
318JNIEXPORT jint JNICALL Java_Sane_getControlOption__II_3B_3I
319  (JNIEnv *env, jobject jobj, jint handle, jint option, jbyteArray value,
320						jintArray info)
321	{
322	SANE_Status status;		/* Gets status. */
323	SANE_Int i;			/* Gets info. passed back. */
324	char *str;
325
326	str = (*env)->GetByteArrayElements(env, value, 0);
327	status = sane_control_option((SANE_Handle) handle, option,
328			SANE_ACTION_GET_VALUE, str, &i);
329	(*env)->ReleaseByteArrayElements(env, value, str, 0);
330	if (info)
331		(*env)->SetIntArrayRegion(env, info, 0, 1, &i);
332	return (status);
333	}
334
335/*
336 * Class:     Sane
337 * Method:    setControlOption
338 * Signature: (IIII[I)I
339 */
340JNIEXPORT jint JNICALL Java_Sane_setControlOption__IIII_3I
341  (JNIEnv *env, jobject jobj, jint handle, jint option, jint action,
342				jint value, jintArray info)
343	{
344	SANE_Status status;		/* Gets status. */
345	SANE_Int i;			/* Gets info. passed back. */
346	status = sane_control_option((SANE_Handle) handle, option, action,
347					&value, &i);
348	if (info)
349		(*env)->SetIntArrayRegion(env, info, 0, 1, &i);
350	return (status);
351	}
352
353/*
354 *	Get string length.  This exists because sometimes strings seem to be
355 *	padded with negatives.
356 */
357
358static int String_length
359	(
360	const char *str
361	)
362	{
363	const char *ptr;
364	for (ptr = str; *ptr > 0; ptr++)
365		;
366	return ((int) (ptr - str));
367	}
368
369/*
370 * Class:     Sane
371 * Method:    setControlOption
372 * Signature: (IIILjava/lang/String;[I)I
373 */
374JNIEXPORT jint JNICALL Java_Sane_setControlOption__IIILjava_lang_String_2_3I
375  (JNIEnv *env, jobject jobj, jint handle, jint option, jint action,
376				jstring value, jintArray info)
377	{
378	SANE_Status status;		/* Gets status. */
379	SANE_Int i;			/* Gets info. passed back. */
380	const char *valuep;
381	char buf[512];			/* Hope this is big enough. */
382	int len;			/* Gets string length. */
383
384	valuep = (*env)->GetStringUTFChars(env, value, 0);
385	len = String_length(valuep);
386	if (len >= sizeof(buf))
387		len = sizeof(buf) - 1;
388	strncpy(buf, valuep, len);
389	buf[len] = 0;			/* Insure it's 0-delimited. */
390	status = sane_control_option((SANE_Handle) handle, option, action,
391					(void *) &buf[0], &i);
392					/* +++++++Want to return new val? */
393	(*env)->ReleaseStringUTFChars(env, value, valuep);
394	if (info)
395		(*env)->SetIntArrayRegion(env, info, 0, 1, &i);
396	return (status);
397	}
398
399/*
400 * Class:     Sane
401 * Method:    getParameters
402 * Signature: (ILSaneParameters;)I
403 */
404JNIEXPORT jint JNICALL Java_Sane_getParameters
405  (JNIEnv *env, jobject jobj, jint handle, jobject paramsObj)
406	{
407	SANE_Status status;		/* Gets status.	*/
408	SANE_Parameters params;		/* Gets params. */
409	jclass paramsClass;		/* Gets its class. */
410	jfieldID fid;			/* Gets each field ID. */
411
412	status = sane_get_parameters((SANE_Handle) handle, &params);
413					/* Get class info. */
414	paramsClass = (*env)->GetObjectClass(env, paramsObj);
415					/* Fill in each member. */
416	fid = (*env)->GetFieldID(env, paramsClass, "format", "I");
417	(*env)->SetIntField(env, paramsObj, fid, params.format);
418	fid = (*env)->GetFieldID(env, paramsClass, "lastFrame", "Z");
419	(*env)->SetBooleanField(env, paramsObj, fid, params.last_frame);
420	fid = (*env)->GetFieldID(env, paramsClass, "bytesPerLine", "I");
421	(*env)->SetIntField(env, paramsObj, fid, params.bytes_per_line);
422	fid = (*env)->GetFieldID(env, paramsClass, "pixelsPerLine", "I");
423	(*env)->SetIntField(env, paramsObj, fid, params.pixels_per_line);
424	fid = (*env)->GetFieldID(env, paramsClass, "lines", "I");
425	(*env)->SetIntField(env, paramsObj, fid, params.lines);
426	fid = (*env)->GetFieldID(env, paramsClass, "depth", "I");
427	(*env)->SetIntField(env, paramsObj, fid, params.depth);
428	return (status);
429	}
430
431/*
432 * Class:     Sane
433 * Method:    start
434 * Signature: (I)I
435 */
436JNIEXPORT jint JNICALL Java_Sane_start
437  (JNIEnv *env, jobject jobj, jint handle)
438	{
439	return (sane_start((SANE_Handle) handle));
440	}
441
442/*
443 * Class:     Sane
444 * Method:    read
445 * Signature: (I[BI[I)I
446 */
447JNIEXPORT jint JNICALL Java_Sane_read
448  (JNIEnv *env, jobject jobj, jint handle, jbyteArray data, jint maxLength,
449					jintArray length)
450	{
451	int status;
452	jbyte *dataElements;
453	int read_len;			/* # bytes read. */
454
455					/* Get actual data ptr. */
456	dataElements = (*env)->GetByteArrayElements(env, data, 0);
457					/* Do the read. */
458	status = sane_read((SANE_Handle) handle, dataElements,
459						maxLength, &read_len);
460	(*env)->ReleaseByteArrayElements(env, data, dataElements, 0);
461					/* Return # bytes read. */
462	(*env)->SetIntArrayRegion(env, length, 0, 1, &read_len);
463	return (status);
464	}
465
466/*
467 * Class:     Sane
468 * Method:    cancel
469 * Signature: (I)V
470 */
471JNIEXPORT void JNICALL Java_Sane_cancel
472  (JNIEnv *env, jobject jobj, jint handle)
473	{
474	sane_cancel((SANE_Handle) handle);
475	}
476
477/*
478 * Class:     Sane
479 * Method:    strstatus
480 * Signature: (I)Ljava/lang/String;
481 */
482JNIEXPORT jstring JNICALL Java_Sane_strstatus
483  (JNIEnv *env, jobject jobj, jint status)
484	{
485	const char *str = sane_strstatus(status);
486	return ((*env)->NewStringUTF(env, str));
487	}
488
489#ifdef __cplusplus
490}
491#endif
492