~mimose/+junk/hplip-3.16.11

« back to all changes in this revision

Viewing changes to scan/sane/scl.c

  • Committer: guoyalong
  • Date: 2017-09-20 10:13:05 UTC
  • Revision ID: guoyalong@kylinos.cn-20170920101305-82zaolzpv1qghz29
Modified debian/control & debian/rules.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/************************************************************************************\
 
2
 
 
3
  scl.c - HP SANE backend for multi-function peripherals (libsane-hpaio)
 
4
 
 
5
  (c) 2001-2006 Copyright HP Development Company, LP
 
6
 
 
7
  Permission is hereby granted, free of charge, to any person obtaining a copy 
 
8
  of this software and associated documentation files (the "Software"), to deal 
 
9
  in the Software without restriction, including without limitation the rights 
 
10
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
 
11
  of the Software, and to permit persons to whom the Software is furnished to do 
 
12
  so, subject to the following conditions:
 
13
 
 
14
  The above copyright notice and this permission notice shall be included in all
 
15
  copies or substantial portions of the Software.
 
16
 
 
17
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 
18
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 
 
19
  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
 
20
  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
 
21
  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
 
22
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
23
 
 
24
  Contributing Authors: David Paschal, Don Welch, David Suffield 
 
25
 
 
26
\************************************************************************************/
 
27
 
 
28
#include <errno.h>
 
29
#include <stdio.h>
 
30
#include <string.h>
 
31
#include "hpmud.h"
 
32
#include "io.h"
 
33
#include "common.h"
 
34
#include "scl.h"
 
35
#include "hpaio.h"
 
36
 
 
37
#define DEBUG_DECLARE_ONLY
 
38
#include "sanei_debug.h"
 
39
 
 
40
static int SclBufferIsPartialReply( void * dataptr, int datalen )
 
41
{
 
42
    int i = 0, value = 0;
 
43
    unsigned char * const data = dataptr;
 
44
    unsigned int d;
 
45
 
 
46
    if( i >= datalen )
 
47
    {
 
48
        return 0;
 
49
    }
 
50
    if( data[i++] != 27 )
 
51
    {
 
52
        return 0;
 
53
    }
 
54
    if( i >= datalen )
 
55
    {
 
56
        return 0;
 
57
    }
 
58
    if( data[i++] != '*' )
 
59
    {
 
60
        return 0;
 
61
    }
 
62
    if( i >= datalen )
 
63
    {
 
64
        return 0;
 
65
    }
 
66
    if( data[i++] != 's' )
 
67
    {
 
68
        return 0;
 
69
    }
 
70
    while( 42 )
 
71
    {
 
72
        if( i >= datalen )
 
73
        {
 
74
            return 0;
 
75
        }
 
76
        d = data[i] - '0';
 
77
        if( d > 9 )
 
78
        {
 
79
            break;
 
80
        }
 
81
        i++;
 
82
    }
 
83
    d = data[i++];
 
84
    if( d<'a' || d>'z' )
 
85
    {
 
86
        return 0;
 
87
    }
 
88
    while( 42 )
 
89
    {
 
90
        if( i >= datalen )
 
91
        {
 
92
            return 0;
 
93
        }
 
94
        d = data[i] - '0';
 
95
        if( d > 9 )
 
96
        {
 
97
            break;
 
98
        }
 
99
        i++;
 
100
        value = ( value * 10 ) + d;
 
101
    }
 
102
    if( i >= datalen )
 
103
    {
 
104
        return 0;
 
105
    }
 
106
    if( data[i++] != 'W' )
 
107
    {
 
108
        return 0;
 
109
    }
 
110
    value = i + value - datalen;
 
111
    if( value < 0 )
 
112
    {
 
113
        value = 0;
 
114
    }
 
115
    return value;
 
116
}
 
117
 
 
118
 
 
119
static int SclChannelRead(int deviceid, int channelid, char * buffer, int countdown, int isSclResponse)
 
120
{
 
121
    char * bufferStart = buffer;
 
122
    int bufferLen = countdown, countup = 0, len;
 
123
    enum HPMUD_RESULT stat;
 
124
 
 
125
    if(!isSclResponse)
 
126
    {
 
127
        stat = hpmud_read_channel(deviceid, channelid, buffer, bufferLen, EXCEPTION_TIMEOUT, &len);  
 
128
        return len;
 
129
    }
 
130
 
 
131
    while(1)
 
132
    {
 
133
        stat = hpmud_read_channel(deviceid, channelid, buffer, countdown, EXCEPTION_TIMEOUT, &len);                                      
 
134
 
 
135
        if(stat != HPMUD_R_OK)
 
136
        {
 
137
            break;
 
138
        }
 
139
        countup += len;
 
140
 
 
141
        countdown = SclBufferIsPartialReply( (unsigned char *)bufferStart, countup );
 
142
        
 
143
        if( countup + countdown > bufferLen )
 
144
        {
 
145
            countdown = bufferLen - countup;
 
146
        }
 
147
        if( countdown <= 0 )
 
148
        {
 
149
            break;
 
150
        }
 
151
 
 
152
        buffer += len;
 
153
        //startTimeout = continueTimeout;
 
154
    }
 
155
 
 
156
    if(!countup)
 
157
    {
 
158
        return len;
 
159
    }
 
160
    return countup;
 
161
 
 
162
}
 
163
 
 
164
SANE_Status __attribute__ ((visibility ("hidden"))) SclSendCommand(int deviceid, int channelid, int cmd, int param)
 
165
{
 
166
    char buffer[LEN_SCL_BUFFER];
 
167
    int datalen, len;
 
168
    char punc = SCL_CMD_PUNC( cmd );
 
169
    char letter1 = SCL_CMD_LETTER1( cmd),letter2 = SCL_CMD_LETTER2( cmd );
 
170
 
 
171
    if( cmd == SCL_CMD_RESET )
 
172
    {
 
173
        datalen = snprintf( buffer, LEN_SCL_BUFFER, "\x1B%c", letter2 );
 
174
    }
 
175
    else
 
176
    {
 
177
        if( cmd == SCL_CMD_CLEAR_ERROR_STACK )
 
178
        {
 
179
            datalen = snprintf( buffer,
 
180
                                LEN_SCL_BUFFER,
 
181
                                "\x1B%c%c%c",
 
182
                                punc,
 
183
                                letter1,
 
184
                                letter2 );
 
185
        }
 
186
        else
 
187
        {
 
188
            datalen = snprintf( buffer,
 
189
                                LEN_SCL_BUFFER,
 
190
                                "\x1B%c%c%d%c",
 
191
                                punc,
 
192
                                letter1,
 
193
                                param,
 
194
                                letter2 );
 
195
        }
 
196
    }
 
197
 
 
198
    hpmud_write_channel(deviceid, channelid, buffer, datalen, EXCEPTION_TIMEOUT, &len);
 
199
 
 
200
    DBG(6, "SclSendCommand: size=%d bytes_wrote=%d: %s %d\n", datalen, len, __FILE__, __LINE__);
 
201
    if (DBG_LEVEL >= 6)
 
202
       sysdump(buffer, datalen);
 
203
 
 
204
    if(len != datalen)
 
205
    {
 
206
        return SANE_STATUS_IO_ERROR;
 
207
    }
 
208
 
 
209
    return SANE_STATUS_GOOD;
 
210
}
 
211
 
 
212
SANE_Status __attribute__ ((visibility ("hidden"))) SclInquire(int deviceid, int channelid, int cmd, int param, int * pValue, char * buffer, int maxlen)
 
213
{
 
214
    SANE_Status retcode;
 
215
    int lenResponse, len, value;
 
216
    char _response[LEN_SCL_BUFFER + 1], * response = _response;
 
217
    char expected[LEN_SCL_BUFFER], expectedChar;
 
218
 
 
219
    if( !pValue )
 
220
    {
 
221
        pValue = &value;
 
222
    }
 
223
    if( buffer && maxlen > 0 )
 
224
    {
 
225
        memset( buffer, 0, maxlen );
 
226
    }
 
227
    memset( _response, 0, LEN_SCL_BUFFER + 1 );
 
228
 
 
229
    /* Send inquiry command. */
 
230
    if( ( retcode = SclSendCommand( deviceid, channelid, cmd, param ) ) != SANE_STATUS_GOOD )
 
231
    {
 
232
        return retcode;
 
233
    }
 
234
 
 
235
    /* Figure out what format of response we expect. */
 
236
    expectedChar = SCL_CMD_LETTER2( cmd ) - 'A' + 'a' - 1;
 
237
    if( expectedChar == 'q' )
 
238
    {
 
239
        expectedChar--;
 
240
    }
 
241
    len = snprintf( expected,
 
242
                    LEN_SCL_BUFFER,
 
243
                    "\x1B%c%c%d%c",
 
244
                    SCL_CMD_PUNC( cmd ),
 
245
                    SCL_CMD_LETTER1( cmd ),
 
246
                    param,
 
247
                    expectedChar );
 
248
 
 
249
    /* Read the response. */
 
250
    lenResponse = SclChannelRead( deviceid, channelid, response, LEN_SCL_BUFFER, 1 );
 
251
                                      
 
252
    DBG(6, "SclChannelRead: len=%d: %s %d\n", lenResponse, __FILE__, __LINE__);
 
253
    if (DBG_LEVEL >= 6)
 
254
       sysdump(response, lenResponse);
 
255
 
 
256
    /* Validate the first part of the response. */
 
257
    if( lenResponse <= len || memcmp( response, expected, len ) )
 
258
    {
 
259
        bug("invalid SclInquire(cmd=%x,param=%d) exp(len=%d)/act(len=%d): %s %d\n", cmd, param, len, lenResponse, __FILE__, __LINE__);
 
260
        bug("exp:\n");
 
261
        bugdump(expected, len);
 
262
        bug("act:\n");
 
263
        bugdump(response, lenResponse);
 
264
        return SANE_STATUS_IO_ERROR;
 
265
    }
 
266
    response += len;
 
267
    lenResponse -= len;
 
268
 
 
269
    /* Null response? */
 
270
    if( response[0] == 'N' )
 
271
    {
 
272
        DBG(6, "SclInquire null response. %s %d\n", __FILE__, __LINE__);
 
273
        return SANE_STATUS_UNSUPPORTED;
 
274
    }
 
275
 
 
276
    /* Parse integer part of non-null response.
 
277
     * If this is a binary-data response, then this value is the
 
278
     * length of the binary-data portion. */
 
279
    if( sscanf( response, "%d%n", pValue, &len ) != 1 )
 
280
    {
 
281
        bug("invalid SclInquire(cmd=%x,param=%d) integer response: %s %d\n", cmd, param, __FILE__, __LINE__);
 
282
        return SANE_STATUS_IO_ERROR;
 
283
    }
 
284
 
 
285
    /* Integer response? */
 
286
    if( response[len] == 'V' )
 
287
    {
 
288
        return SANE_STATUS_GOOD;
 
289
    }
 
290
 
 
291
    /* Binary-data response? */
 
292
    if( response[len] != 'W' )
 
293
    {
 
294
        bug("invalid SclInquire(cmd=%x,param=%d) unexpected character '%c': %s %d\n", cmd, param, response[len], __FILE__, __LINE__);
 
295
        return SANE_STATUS_IO_ERROR;
 
296
    }
 
297
    response += len + 1;
 
298
    lenResponse -= len + 1;
 
299
 
 
300
    /* Make sure we got the right length of binary data. */
 
301
    if( lenResponse<0 || lenResponse != *pValue || lenResponse>maxlen )
 
302
    {
 
303
        bug("invalid SclInquire(cmd=%x,param=%d) binary data lenResponse=%d *pValue=%d maxlen=%d: %s %d\n", 
 
304
                             cmd, param, lenResponse, *pValue, maxlen, __FILE__, __LINE__);
 
305
        return SANE_STATUS_IO_ERROR;
 
306
    }
 
307
 
 
308
    /* Copy binary data into user's buffer. */
 
309
    if( buffer )
 
310
    {
 
311
        maxlen = *pValue;
 
312
        memcpy( buffer, response, maxlen );
 
313
    }
 
314
 
 
315
    return SANE_STATUS_GOOD;
 
316
}
 
317
 
 
318
/*
 
319
 * Phase 2 partial rewrite. des 9/26/07
 
320
 */
 
321
 
 
322
SANE_Status __attribute__ ((visibility ("hidden"))) scl_send_cmd(HPAIO_RECORD *hpaio, const char *buf, int size)
 
323
{
 
324
    int len;
 
325
    
 
326
    hpmud_write_channel(hpaio->deviceid, hpaio->scan_channelid, buf, size, EXCEPTION_TIMEOUT, &len);
 
327
 
 
328
    DBG(6, "scl cmd sent size=%d bytes_wrote=%d: %s %d\n", size, len, __FILE__, __LINE__);
 
329
    if (DBG_LEVEL >= 6)
 
330
       sysdump(buf, size);
 
331
 
 
332
    if(len != size)
 
333
    {
 
334
        return SANE_STATUS_IO_ERROR;
 
335
    }
 
336
 
 
337
    return SANE_STATUS_GOOD;
 
338
}
 
339
 
 
340
SANE_Status __attribute__ ((visibility ("hidden"))) scl_query_int(HPAIO_RECORD *hpaio, const char *buf, int size, int *result)
 
341
{
 
342
    char rbuf[256];
 
343
    int len, stat;
 
344
    char *tail;
 
345
 
 
346
    *result=0;
 
347
 
 
348
    if ((stat = scl_send_cmd(hpaio, buf, size)) != SANE_STATUS_GOOD)
 
349
    {
 
350
        return stat;
 
351
    }
 
352
 
 
353
    if ((stat = hpmud_read_channel(hpaio->deviceid, hpaio->scan_channelid, rbuf, sizeof(rbuf), EXCEPTION_TIMEOUT, &len)) != HPMUD_R_OK)
 
354
    {
 
355
        return SANE_STATUS_IO_ERROR;
 
356
    }
 
357
 
 
358
    DBG(6, "scl response size=%d: %s %d\n", len, __FILE__, __LINE__);
 
359
    if (DBG_LEVEL >= 6)
 
360
       sysdump(buf, size);
 
361
 
 
362
    /* Null response? */
 
363
    if(rbuf[len-1] == 'N')
 
364
    {
 
365
        DBG(6, "scl null response: %s %d\n", __FILE__, __LINE__);
 
366
        return SANE_STATUS_UNSUPPORTED;
 
367
    }
 
368
        
 
369
    /* Integer response? */
 
370
    if(rbuf[len-1] != 'V' )
 
371
    {
 
372
        bug("invalid scl integer response: %s %d\n", __FILE__, __LINE__);
 
373
        return SANE_STATUS_IO_ERROR;
 
374
    }
 
375
 
 
376
    *result = strtol(&rbuf[size], &tail, 10);
 
377
 
 
378
    return SANE_STATUS_GOOD;
 
379
}
 
380