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, ¶ms);
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