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
52 extern "C" {
53 #endif
54 /*
55  * Class:     Sane
56  * Method:    init
57  * Signature: ([I)I
58  */
Java_Sane_init(JNIEnv *env, jobject jobj, jintArray versionCode)59 JNIEXPORT 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  */
Java_Sane_exit(JNIEnv *env, jobject jobj)80 JNIEXPORT 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  */
Java_Sane_getDevicesNative(JNIEnv *env, jobject jobj, jobjectArray devList, jboolean localOnly)92 JNIEXPORT 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  */
Java_Sane_open(JNIEnv *env, jobject jobj, jstring deviceName, jintArray handle)144 JNIEXPORT 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  */
Java_Sane_close(JNIEnv *env, jobject jobj, jint handle)167 JNIEXPORT 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  */
Java_Sane_getOptionNative(JNIEnv *env, jobject jobj, jint handle, jint option, jobject optObj)178 JNIEXPORT 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  */
Java_Sane_getControlOption__II_3I_3I(JNIEnv *env, jobject jobj, jint handle, jint option, jintArray value, jintArray info)296 JNIEXPORT 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  */
Java_Sane_getControlOption__II_3B_3I(JNIEnv *env, jobject jobj, jint handle, jint option, jbyteArray value, jintArray info)318 JNIEXPORT 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  */
Java_Sane_setControlOption__IIII_3I(JNIEnv *env, jobject jobj, jint handle, jint option, jint action, jint value, jintArray info)340 JNIEXPORT 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 
String_length( const char *str )358 static 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  */
Java_Sane_setControlOption__IIILjava_lang_String_2_3I(JNIEnv *env, jobject jobj, jint handle, jint option, jint action, jstring value, jintArray info)374 JNIEXPORT 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  */
Java_Sane_getParameters(JNIEnv *env, jobject jobj, jint handle, jobject paramsObj)404 JNIEXPORT 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  */
Java_Sane_start(JNIEnv *env, jobject jobj, jint handle)436 JNIEXPORT 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  */
Java_Sane_read(JNIEnv *env, jobject jobj, jint handle, jbyteArray data, jint maxLength, jintArray length)447 JNIEXPORT 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  */
Java_Sane_cancel(JNIEnv *env, jobject jobj, jint handle)471 JNIEXPORT 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  */
Java_Sane_strstatus(JNIEnv *env, jobject jobj, jint status)482 JNIEXPORT 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