Replace 'tap' to 'spaces' to make gbs build succeed
[platform/upstream/hplip.git] / fax / marvellfax.py
1 # -*- coding: utf-8 -*-
2 #
3 # (c) Copyright 2010 Hewlett-Packard Development Company, L.P.
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU 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, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 #
19 # Author: Suma Byrappa
20 #
21
22 # Std Lib
23 import sys
24 import os
25 import os.path
26 import struct
27 import time
28 import threading
29 import cStringIO
30
31 from stat import *
32
33 # Local
34 from base.g import *
35 from base.codes import *
36 from base import device, utils, pml, codes
37 from prnt import cups
38 from fax import *
39 import hpmudext
40
41 try:
42     from ctypes import cdll
43     from ctypes import *
44     import ctypes.util as cu
45 except ImportError:
46     log.error("Marvell fax support requires python-ctypes module. Exiting!")
47     sys.exit(1)
48
49
50 # **************************************************************************** #
51 # Marvell Message Types
52 START_FAX_JOB = 0
53 END_FAX_JOB = 1
54 SEND_FAX_JOB = 2
55 GET_FAX_LOG_ENTRY = 5
56 GET_FAX_SETTINGS = 9
57 SET_FAX_SETTINGS = 10
58 CLEAR_FAX_STATUS = 11
59 REQUEST_FAX_STATUS = 12
60 FAX_DATA_BLOCK = 13
61
62 SUCCESS = 0
63 FAILURE = 1
64
65 FAX_DATA_BLOCK_SIZE = 4096
66
67 # Fax data variant header TTI header control
68 TTI_NONE = 0
69 TTI_PREPENDED_TO_IMAGE = 1
70 TTI_OVERLAYED_ON_IMAGE = 2
71
72 # **************************************************************************** #
73 class MarvellFaxDevice(FaxDevice):
74
75     def __init__(self, device_uri=None, printer_name=None,
76                  callback=None,
77                  fax_type=FAX_TYPE_NONE,
78                  disable_dbus=False):
79
80         FaxDevice.__init__(self, device_uri,
81                            printer_name,
82                            callback, fax_type,
83                            disable_dbus)
84
85         self.send_fax_thread = None
86         self.upload_log_thread = None
87
88         try:
89             sendfax_path = utils.which('hp-sendfax')
90             sendfax_a_path = os.readlink(sendfax_path+"/hp-sendfax")
91             if not os.path.isabs(sendfax_a_path):
92                    sendfax_f_path = os.path.join(sendfax_path, sendfax_a_path)
93             else:
94                    sendfax_f_path = sendfax_a_path
95
96             sendfax_abs_path = os.path.realpath(sendfax_f_path)
97             (head, tail) = os.path.split(sendfax_abs_path)  
98
99             lib_name = head+"/fax/plugins/fax_marvell.so"
100             log.debug("Load the library %s\n" % lib_name)
101             if not os.path.exists(lib_name):
102                 log.error("Loading %s failed. Try after installing plugin libraries\n" %lib_name);
103                 log.info("Run \"hp-plugin\" to installa plugin libraries if you are not automatically prompted\n")
104                 job_id =0;
105                 self.service.SendEvent(device_uri, printer_name, EVENT_FAX_FAILED_MISSING_PLUGIN, os.getenv('USER'), job_id, "Plugin is not installed")
106                 sys.exit(1)
107             else:
108                 self.libfax_marvell = cdll.LoadLibrary(lib_name)
109         except Error, e:
110             log.error("Loading fax_marvell failed (%s)\n" % e.msg);
111             sys.exit(1)
112
113
114     # Creates a message packet for message type given in argument, and sends it to device
115     #
116     # 1. Gets the message packet using fax_marvell.so
117     # 2. Writes the packets to device
118     # 3. Returns the result of send operation
119     def send_packet_for_message(self, msg_type, param1=0, param2=0, status=0, data_len=0):
120         int_array_8 = c_int * 8
121         i_buf = int_array_8(0, 0, 0, 0, 0, 0, 0, 0)
122
123         result = self.libfax_marvell.create_packet(msg_type, param1, param2, status, data_len, byref(i_buf))
124         buf = buffer(i_buf)
125         log.log_data(buf, 32)
126         self.writeMarvellFax(buf)
127 #        self.closeMarvellFax()
128
129         return result
130
131
132     # Reads response message packet from the device for message type given in argument.
133     #       Reads the response from device, and sends the data read to the caller of this method
134     #       No Marvell specific code or info
135     def read_response_for_message(self, msg_type):
136         ret_buf = cStringIO.StringIO()
137         while self.readMarvellFax(32, ret_buf, timeout=10):
138                             pass
139
140         ret_buf = ret_buf.getvalue()
141         #self.closeMarvellFax()
142
143         log.debug("response_for_message (%d): response packet is\n" % msg_type)
144         log.log_data(ret_buf, 32)
145
146         return ret_buf
147
148
149     def setPhoneNum(self, num):
150         log.debug("************************* setPhoneNum (%s) START **************************" % num)
151
152         set_buf = cStringIO.StringIO()
153
154         int_array = c_int * 8
155         i_buf = int_array(0, 0, 0, 0, 0, 0, 0, 0)
156
157         char_array = c_char * 308
158         c_buf = char_array()
159
160         date_array = c_char * 15
161         date_buf = date_array()
162         t = time.localtime()
163         date_buf = "%4d%02d%02d%02d%02d%02d" % (t[0], t[1], t[2], t[3], t[4], t[5])
164         log.debug("Date and Time string is ==>")
165         log.debug(date_buf)
166
167         result = self.libfax_marvell.create_packet(SET_FAX_SETTINGS, 0, 0, 0, 0, byref(i_buf))
168         result = self.libfax_marvell.create_fax_settings_packet(self.station_name, str(num), date_buf, byref(c_buf))
169
170         msg_buf = buffer(i_buf)
171         msg_c_buf = buffer(c_buf)
172
173         for i in range(0, 32):
174             set_buf.write(msg_buf[i])
175         for i in range(0, 308):
176             set_buf.write(msg_c_buf[i])
177
178         set_buf = set_buf.getvalue()
179         log.debug("setPhoneNum: send SET_FAX_SETTINGS message and data ===> ")
180         log.log_data(set_buf, 340)
181
182         self.writeMarvellFax(set_buf)
183         ret_buf = cStringIO.StringIO()
184         while self.readMarvellFax(32, ret_buf, timeout=10):
185                             pass
186         ret_buf = ret_buf.getvalue()
187         self.closeMarvellFax()
188
189         response = self.libfax_marvell.extract_response(ret_buf) 
190         log.debug("setPhoneNum: response is %d" % response)
191  
192         log.debug("************************* setPhoneNum END **************************")
193         return response
194
195
196     def getPhoneNum(self):
197         int_array_8 = c_int * 8
198         i_buf = int_array_8(0, 0, 0, 0, 0, 0, 0, 0)
199         ph_buf = int_array_8(0, 0, 0, 0, 0, 0, 0, 0)
200
201         log.debug("******************** getPhoneNum START **********************")
202
203         result = self.libfax_marvell.create_packet(GET_FAX_SETTINGS, 0, 0, 0, 0, byref(i_buf))
204
205         buf = buffer(i_buf)
206         self.writeMarvellFax(buf)
207         #self.closeMarvellFax()
208         ret_buf = cStringIO.StringIO()
209         while self.readMarvellFax(512, ret_buf, timeout=10):
210                             pass
211         ret_buf = ret_buf.getvalue()
212         self.closeMarvellFax()
213
214         response = self.libfax_marvell.extract_response(ret_buf) 
215         log.debug("create_packet: response is %d" % response)
216  
217         response = self.libfax_marvell.extract_phone_number(ret_buf, ph_buf) 
218         ph_num_buf = cStringIO.StringIO()
219         for i in range(0, 7):
220             if ph_buf[i]:
221                ph_num_buf.write(str(ph_buf[i]))
222
223         ph_num_buf = ph_num_buf.getvalue()
224         log.debug("getPhoneNum: ph_num_buf=%s " % (ph_num_buf))
225
226         log.debug("******************** getPhoneNum END **********************")
227         return ph_num_buf
228
229
230     # Note down the fax (phone) number
231     phone_num = property(getPhoneNum, setPhoneNum)
232
233
234     # Set the station name in the device's settings
235     #
236     def setStationName(self, name):
237         log.debug("************************* setStationName(%s) START **************************" % name)
238
239         int_array = c_int * 8
240         i_buf = int_array(0, 0, 0, 0, 0, 0, 0, 0)
241         set_buf = cStringIO.StringIO()
242
243         char_array = c_char * 308
244         c_buf = char_array()
245
246         date_array = c_char * 15
247         date_buf = date_array()
248         t = time.localtime()
249         date_buf = "%4d%02d%02d%02d%02d%02d" % (t[0], t[1], t[2], t[3], t[4], t[5])
250         log.debug("Date and Time string is ==>")
251         log.debug(date_buf)
252
253         result = self.libfax_marvell.create_packet(SET_FAX_SETTINGS, 0, 0, 0, 0, byref(i_buf))
254         result = self.libfax_marvell.create_fax_settings_packet(str(name), self.phone_num, date_buf, byref(c_buf))
255
256         msg_buf = buffer(i_buf)
257         msg_c_buf = buffer(c_buf)
258
259         for i in range(0, 32):
260             set_buf.write(msg_buf[i])
261         for i in range(0, 308):
262             set_buf.write(msg_c_buf[i])
263         set_buf = set_buf.getvalue()
264         log.debug("setStationName: SET_FAX_SETTINGS message and data ===> ")
265         log.log_data(set_buf, 340)
266
267         self.writeMarvellFax(set_buf)
268         ret_buf = cStringIO.StringIO()
269         while self.readMarvellFax(32, ret_buf, timeout=10):
270                             pass
271         ret_buf = ret_buf.getvalue()
272         self.closeMarvellFax()
273
274         response = self.libfax_marvell.extract_response(ret_buf) 
275         log.debug("setStationName: response is %d" % response)
276  
277         log.debug("************************* setStationName END **************************")
278         return response
279
280
281     def getStationName(self):
282         int_array = c_int * 8
283         i_buf = int_array(0, 0, 0, 0, 0, 0, 0, 0)
284         st_buf = create_string_buffer(128)
285
286         log.debug("************************* getStationName START **************************")
287
288         result = self.libfax_marvell.create_packet(GET_FAX_SETTINGS, 0, 0, 0, 0, byref(i_buf))
289
290         buf = buffer(i_buf)
291         self.writeMarvellFax(buf)
292         #self.closeMarvellFax()
293
294         ret_buf = cStringIO.StringIO()
295         while self.readMarvellFax(512, ret_buf, timeout=10):
296                             pass
297
298         ret_buf = ret_buf.getvalue()
299         self.closeMarvellFax()
300
301         response = self.libfax_marvell.extract_response(ret_buf)
302         log.debug("getStationName: response is %d" % response)
303
304         result = self.libfax_marvell.extract_station_name(ret_buf, st_buf) 
305         log.debug("getStationName: station_name=%s ; result is %d" % (st_buf.value, result))
306  
307         log.debug("************************* getStationName END **************************")
308         return st_buf.value
309
310
311    # Note down the station-name
312     station_name = property(getStationName, setStationName)
313
314
315     # Set date and time in the device's settings
316     #
317     # 1. Gets the message packet and fax_settings packet using fax_marvell.so 
318     # 2. Writes the packets to the device; Reads response from the device
319     # 3. Extracts the status from the device's response
320     def setDateAndTime(self):
321         int_array = c_int * 8
322         i_buf = int_array(0, 0, 0, 0, 0, 0, 0, 0)
323
324         log.debug("************************* setDateAndTime START **************************")
325
326         c_buf = create_string_buffer(308)
327         set_buf = cStringIO.StringIO()
328         ret_buf = cStringIO.StringIO()
329         date_array = c_char * 15
330         date_buf = date_array()
331
332         t = time.localtime()
333
334         date_buf = "%4d%02d%02d%02d%02d%02d" % (t[0], t[1], t[2], t[3], t[4], t[5])
335         log.debug("Date and Time string is ==>")
336         log.debug(date_buf)
337
338         result = self.libfax_marvell.create_packet(SET_FAX_SETTINGS, 0, 0, 0, 0, byref(i_buf))
339         result = create_marvell_faxsettings_pkt(self.phone_num, self.station_name, date_buf, c_buf)
340
341         msg_buf = buffer(i_buf)
342         for i in range(0, 31):
343             set_buf.write(msg_buf[i])
344
345         set_buf.write(c_buf.raw)
346         set_buf = set_buf.getvalue()
347         self.dev.writeMarvellFax(set_buf)
348         while self.dev.readMarvellFax(32, ret_buf, timeout=5):
349                             pass
350         ret_buf = ret_buf.getvalue()
351         self.closeMarvellFax()
352
353         response = self.libfax_marvell.extract_response(ret_buf)
354         log.debug("setDateAndTime: response is %d" % response)
355
356         return response
357
358
359     # Get the state of the device 
360     #
361     # 1. Gets the message packet using fax_marvell.so 
362     # 2. Writes the packet to the device; Reads response from the device
363     # 3. Extracts the response status and device status from the device's response
364     def getFaxDeviceState(self):
365         log.debug("************************* getFaxDeviceState: START **************************")
366
367         int_array = c_int * 8
368         i_buf = int_array(0, 0, 0, 0, 0, 0, 0, 0)
369         param1 = c_int(0)
370
371         result = self.libfax_marvell.create_packet(REQUEST_FAX_STATUS, 0, 0, 0, 0, byref(i_buf))
372         buf = buffer(i_buf)
373         self.writeMarvellFax(buf)
374
375         ret_buf = cStringIO.StringIO()
376         while self.readMarvellFax(32, ret_buf, timeout=5):
377                             pass
378         ret_buf = ret_buf.getvalue()
379         self.closeMarvellFax()
380
381         response = self.libfax_marvell.extract_response(ret_buf)
382         log.debug("getFaxDeviceState: response is %d" % response)
383
384         return response
385
386
387     # Creates a thread which does actual Fax submission the state of the device 
388     #
389     def sendFaxes(self, phone_num_list, fax_file_list, cover_message='', cover_re='',
390                   cover_func=None, preserve_formatting=False, printer_name='',
391                   update_queue=None, event_queue=None):
392
393         if not self.isSendFaxActive():
394
395             self.send_fax_thread = MarvellFaxSendThread(self, self.service, phone_num_list, fax_file_list,
396                                                     cover_message, cover_re, cover_func,
397                                                     preserve_formatting,
398                                                     printer_name, update_queue,
399                                                     event_queue)
400
401             self.send_fax_thread.start()
402             return True
403         else:
404             return False
405
406
407
408 # **************************************************************************** #
409 # Does the actual Fax transmission
410 # **************************************************************************** #
411 class MarvellFaxSendThread(FaxSendThread):
412     def __init__(self, dev, service, phone_num_list, fax_file_list,
413                  cover_message='', cover_re='', cover_func=None, preserve_formatting=False,
414                  printer_name='', update_queue=None, event_queue=None):
415
416         FaxSendThread.__init__(self, dev, service, phone_num_list, fax_file_list,
417              cover_message, cover_re, cover_func, preserve_formatting,
418              printer_name, update_queue, event_queue)
419
420
421     def run(self):
422
423         STATE_DONE = 0
424         STATE_ABORTED = 10
425         STATE_SUCCESS = 20
426         STATE_BUSY = 25
427         STATE_READ_SENDER_INFO = 30
428         STATE_PRERENDER = 40
429         STATE_COUNT_PAGES = 50
430         STATE_NEXT_RECIPIENT = 60
431         STATE_COVER_PAGE = 70
432         STATE_SINGLE_FILE = 80
433         STATE_MERGE_FILES = 90
434         STATE_SINGLE_FILE = 100
435         STATE_SEND_FAX = 110
436         STATE_CLEANUP = 120
437         STATE_ERROR = 130
438
439         next_recipient = self.next_recipient_gen()
440
441         rec_name = None
442         rec_num = None
443
444         state = STATE_READ_SENDER_INFO
445         self.rendered_file_list = []
446
447         while state != STATE_DONE: # --------------------------------- Fax state machine
448             if self.check_for_cancel():
449                 log.debug("***** Job is Cancelled.")
450                 state = STATE_ABORTED
451
452             log.debug("*************** STATE=(%d, 0, 0)" % state)
453
454             if state == STATE_ABORTED: # --------------------------------- Aborted 
455                 log.error("Aborted by user.")
456                 self.write_queue((STATUS_IDLE, 0, ''))
457                 state = STATE_CLEANUP
458
459
460             elif state == STATE_SUCCESS: # --------------------------------- Success 
461                 log.debug("Success.")
462                 self.write_queue((STATUS_COMPLETED, 0, ''))
463                 state = STATE_CLEANUP
464
465
466             elif state == STATE_ERROR: # --------------------------------- Error 
467                 log.error("Error, aborting.")
468                 self.write_queue((STATUS_ERROR, 0, ''))
469                 state = STATE_CLEANUP
470
471
472             elif state == STATE_BUSY: # --------------------------------- Busy 
473                 log.error("Device busy, aborting.")
474                 self.write_queue((STATUS_BUSY, 0, ''))
475                 state = STATE_CLEANUP
476
477
478             elif state == STATE_READ_SENDER_INFO: # --------------------------------- Get sender info 
479                 log.debug("%s State: Get sender info" % ("*"*20))
480                 state = STATE_PRERENDER
481                 try:
482                     try:
483                         self.dev.open()
484                     except Error, e:
485                         log.error("Unable to open device (%s)." % e.msg)
486                         state = STATE_ERROR
487                     else:
488                         try:
489                             self.sender_name = self.dev.station_name
490                             self.sender_fax = self.dev.phone_num
491                         except Error:
492                             log.error("Getting station-name and phone_num failed!")
493                             state = STATE_ERROR
494
495                 finally:
496                     self.dev.close()
497
498
499             elif state == STATE_PRERENDER: # --------------------------------- Pre-render non-G3 files 
500                 log.debug("%s State: Pre-render non-G3 files" % ("*"*20))
501                 state = self.pre_render(STATE_COUNT_PAGES)
502
503
504             elif state == STATE_COUNT_PAGES: # --------------------------------- Get total page count 
505                 log.debug("%s State: Get total page count" % ("*"*20))
506                 state = self.count_pages(STATE_NEXT_RECIPIENT)
507
508
509             elif state == STATE_NEXT_RECIPIENT: # --------------------------------- Loop for multiple recipients
510                 log.debug("%s State: Next recipient" % ("*"*20))
511                 state = STATE_COVER_PAGE
512
513                 try:
514                     recipient = next_recipient.next()
515
516                     self.write_queue((STATUS_SENDING_TO_RECIPIENT, 0, recipient['name']))
517                     
518                     rec_name = recipient['name']
519                     rec_num = recipient['fax'].encode('ascii')
520                     log.debug("recipient is %s num is %s" % (rec_name, rec_num))
521
522                 except StopIteration:
523                     state = STATE_SUCCESS
524                     log.debug("Last recipient.")
525                     continue
526
527                 self.recipient_file_list = self.rendered_file_list[:]
528
529
530             elif state == STATE_COVER_PAGE: # --------------------------------- Create cover page 
531                 log.debug("%s State: Render cover page" % ("*"*20))
532                 state = self.cover_page(recipient)
533
534
535             elif state == STATE_SINGLE_FILE: # --------------------------------- Special case for single file (no merge)
536                 log.debug("%s State: Handle single file" % ("*"*20))
537                 state = self.single_file(STATE_SEND_FAX)
538
539             elif state == STATE_MERGE_FILES: # --------------------------------- Merge multiple G3 files 
540                 log.debug("%s State: Merge multiple files" % ("*"*20))
541                 log.debug("Not merging the files for Marvell support")
542                 state = STATE_SEND_FAX
543
544             elif state == STATE_SEND_FAX: # --------------------------------- Send fax state machine 
545                 log.debug("%s State: Send fax" % ("*"*20))
546                 state = STATE_NEXT_RECIPIENT
547
548                 next_file = self.next_file_gen()
549
550                 FAX_SEND_STATE_DONE = 0
551                 FAX_SEND_STATE_SUCCESS = 10
552                 FAX_SEND_STATE_ABORT = 21
553                 FAX_SEND_STATE_ERROR = 22
554                 FAX_SEND_STATE_BUSY = 25
555                 FAX_SEND_STATE_DEVICE_OPEN = 30
556                 FAX_SEND_STATE_NEXT_FILE = 35
557                 FAX_SEND_STATE_CHECK_IDLE = 40
558                 FAX_SEND_STATE_START_JOB_REQUEST = 50
559                 FAX_SEND_STATE_SEND_JOB_REQUEST = 60
560                 FAX_SEND_STATE_SET_PARAMS = 70
561                 FAX_SEND_STATE_SEND_FAX_HEADER = 80
562                 FAX_SEND_STATE_SEND_FILE_DATA = 90
563                 FAX_SEND_STATE_END_FILE_DATA = 100
564                 FAX_SEND_STATE_END_JOB_REQUEST = 110
565                 FAX_SEND_STATE_GET_LOG_INFORMATION = 120
566
567                 monitor_state = False
568                 current_state = SUCCESS
569                 fax_send_state = FAX_SEND_STATE_DEVICE_OPEN
570
571                 while fax_send_state != FAX_SEND_STATE_DONE:
572
573                     if self.check_for_cancel():
574                         log.error("Fax send aborted.")
575                         fax_send_state = FAX_SEND_STATE_ABORT
576
577                     if monitor_state:
578                         fax_state = self.getFaxDeviceState()
579                         if fax_state != SUCCESS:
580                             log.error("Device is in error state=%d" % fax_state)
581                             fax_send_state = FAX_SEND_STATE_ERROR
582                             state = STATE_ERROR
583
584
585                     log.debug("*********  FAX_SEND_STATE=(%d, %d, %d)" % (STATE_SEND_FAX, fax_send_state, current_state))
586
587                     if fax_send_state == FAX_SEND_STATE_ABORT: # -------------- Abort 
588                         monitor_state = False
589                         fax_send_state = FAX_SEND_STATE_END_JOB_REQUEST
590                         state = STATE_ABORTED
591
592                     elif fax_send_state == FAX_SEND_STATE_ERROR: # -------------- Error 
593                         log.error("Fax send error.")
594                         monitor_state = False
595
596                         fax_send_state = FAX_SEND_STATE_END_JOB_REQUEST
597                         state = STATE_ERROR
598
599                     elif fax_send_state == FAX_SEND_STATE_BUSY: # -------------- Busy 
600                         log.error("Fax device busy.")
601                         monitor_state = False
602                         fax_send_state = FAX_SEND_STATE_END_JOB_REQUEST
603                         state = STATE_BUSY
604
605                     elif fax_send_state == FAX_SEND_STATE_SUCCESS: # -------------- Success 
606                         log.debug("Fax send success.")
607                         monitor_state = False
608                         fax_send_state = FAX_SEND_STATE_END_JOB_REQUEST
609                         state = STATE_NEXT_RECIPIENT
610
611                     elif fax_send_state == FAX_SEND_STATE_DEVICE_OPEN: # -------------- Device open 
612                         log.debug("%s State: Open device" % ("*"*20))
613                         fax_send_state = FAX_SEND_STATE_NEXT_FILE
614                         try:
615                             self.dev.open()
616                         except Error, e:
617                             log.error("Unable to open device (%s)." % e.msg)
618                             fax_send_state = FAX_SEND_STATE_ERROR
619                         else:
620                             if self.dev.device_state == DEVICE_STATE_NOT_FOUND:
621                                 fax_send_state = FAX_SEND_STATE_ERROR
622
623
624                     elif fax_send_state == FAX_SEND_STATE_NEXT_FILE: # -------------- Device open 
625                         log.debug("%s State: Open device" % ("*"*20))
626                         fax_send_state = FAX_SEND_STATE_CHECK_IDLE
627                         try:
628                              fax_file = next_file.next()
629                              self.f = fax_file[0]
630                              log.debug("***** file name is : %s..." % self.f)
631                         except StopIteration:
632                              log.debug("file(s) are sent to the device" )
633                              fax_send_state = FAX_SEND_STATE_DONE
634
635
636                     elif fax_send_state == FAX_SEND_STATE_CHECK_IDLE: # -------------- Check for initial idle
637                         log.debug("%s State: Check idle" % ("*"*20))
638                         fax_send_state = FAX_SEND_STATE_START_JOB_REQUEST
639
640                         try:
641                             ff = file(self.f, 'r')
642                         except IOError:
643                             log.error("Unable to read fax file.")
644                             fax_send_state = FAX_SEND_STATE_ERROR
645                             continue
646
647                         try:
648                             header = ff.read(FILE_HEADER_SIZE)
649                         except IOError:
650                             log.error("Unable to read fax file.")
651                             fax_send_state = FAX_SEND_STATE_ERROR
652                             continue
653
654                         magic, version, total_pages, hort_dpi, vert_dpi, page_size, \
655                             resolution, encoding, reserved1, reserved2 = self.decode_fax_header(header)
656
657                         if magic != 'hplip_g3':
658                             log.error("Invalid file header. Bad magic.")
659                             fax_send_state = FAX_SEND_STATE_ERROR
660                         else:
661                             log.debug("Magic=%s Version=%d Total Pages=%d hDPI=%d vDPI=%d Size=%d Resolution=%d Encoding=%d"
662                             % (magic, version, total_pages, hort_dpi, vert_dpi, page_size, resolution, encoding))
663
664                         dev_state = self.dev.getFaxDeviceState()
665
666                         if (dev_state == 0):
667                            log.debug("State: device status is zero ")
668                         else:
669                            log.debug("State: device status is non-zero ")
670                            fax_send_state = FAX_SEND_STATE_BUSY
671
672
673                     elif fax_send_state == FAX_SEND_STATE_START_JOB_REQUEST: # -------------- Request fax start
674                         log.debug("%s State: Request start" % ("*"*20))
675                         fax_send_state = FAX_SEND_STATE_SEND_JOB_REQUEST
676
677                         file_len = os.stat(self.f)[ST_SIZE]
678                         tx_data_len = file_len - FILE_HEADER_SIZE - (PAGE_HEADER_SIZE*total_pages)
679                         log.debug("#### file_len = %d" % file_len)
680                         log.debug("#### tx_data_len = %d" % tx_data_len)
681                         ret_value = self.dev.send_packet_for_message(START_FAX_JOB, tx_data_len, 0, 0, 0)
682                         if ret_value:
683                            log.debug("Sending start fax request failed with %d" % ret_value)
684                            fax_send_state = FAX_SEND_STATE_ERROR
685                         else:
686                            log.debug("Successfully sent start fax request")
687                            ret_buf = self.dev.read_response_for_message(START_FAX_JOB)
688                            dev_response = self.dev.libfax_marvell.extract_response(ret_buf)
689                            if dev_response:
690                               log.debug("start-fax request failed with %d" % dev_response)
691                               fax_send_state = FAX_SEND_STATE_ERROR
692                            else:
693                               log.debug("start-fax request is successful")
694
695                     elif fax_send_state == FAX_SEND_STATE_SEND_JOB_REQUEST: # -------------- Set data request 
696                         log.debug("%s State: Send data request" % ("*"*20))
697                         fax_send_state = FAX_SEND_STATE_SET_PARAMS 
698
699                         ret_value = self.dev.send_packet_for_message(SEND_FAX_JOB)
700                         if ret_value:
701                            log.debug("Sending send-data request failed with %d" % ret_value)
702                            fax_send_state = FAX_SEND_STATE_ERROR
703                         else:
704                            log.debug("Successfully sent send-fax request")
705
706
707                     elif fax_send_state == FAX_SEND_STATE_SET_PARAMS: # -------------- Set fax send params 
708                         log.debug("%s State: Set params" % ("*"*20))
709                         fax_send_state = FAX_SEND_STATE_SEND_FAX_HEADER
710
711                         c_buf = create_string_buffer(68)
712                         set_buf = cStringIO.StringIO()
713
714                         no_data = None
715                         ret_val = self.dev.libfax_marvell.create_job_settings_packet(no_data, rec_num, c_buf)
716                         set_buf.write(c_buf.raw)
717                         set_buf = set_buf.getvalue()
718
719                         self.dev.writeMarvellFax(set_buf)
720                         #self.dev.closeMarvellFax()
721
722
723                     elif fax_send_state == FAX_SEND_STATE_SEND_FAX_HEADER: # -------------- Fax header 
724                         #   Taken care by the device
725                         fax_send_state = FAX_SEND_STATE_SEND_FILE_DATA
726
727                     elif fax_send_state == FAX_SEND_STATE_SEND_FILE_DATA:  # --------------------------------- Send fax pages state machine 
728                         log.debug("%s State: Send pages" % ("*"*20))
729                         fax_send_state = FAX_SEND_STATE_END_FILE_DATA
730                         current_state = SUCCESS
731                         page = StringIO()
732
733                         file_len = os.stat(self.f)[ST_SIZE]
734                         bytes_to_read = file_len - FILE_HEADER_SIZE - (PAGE_HEADER_SIZE*total_pages)
735
736                         for p in range(total_pages):
737
738                             if self.check_for_cancel():
739                                 current_state = FAILURE
740
741                             if current_state == FAILURE:
742                                 break
743
744                             try:
745                                 header = ff.read(PAGE_HEADER_SIZE)
746                             except IOError:
747                                 log.error("Unable to read fax file.")
748                                 current_state = FAILURE
749                                 continue
750
751                             page_num, ppr, rpp, b_to_read, thumbnail_bytes, reserved2 = \
752                                 self.decode_page_header(header)
753
754                             log.debug("Page=%d PPR=%d RPP=%d BPP=%d Thumb=%d" %
755                                       (page_num, ppr, rpp, b_to_read, thumbnail_bytes))
756
757                             page.write(ff.read(b_to_read))
758                             thumbnail = ff.read(thumbnail_bytes) # thrown away for now (should be 0 read)
759                             page.seek(0)
760                             bytes_to_write = b_to_read
761                             total_read = 0
762                             while (bytes_to_write > 0):
763                                try:
764                                    data = page.read(FAX_DATA_BLOCK_SIZE)
765                                except IOError:
766                                    log.error("Unable to read fax file.")
767                                    current_state = FAILURE
768                                    continue
769
770                                if data == '':
771                                    log.error("No data!")
772                                    current_state = FAILURE
773                                    break
774
775                                if self.check_for_cancel():
776                                    current_state = FAILURE
777                                    log.error("Job is cancelled. Aborting...")
778                                    break
779
780                                total_read += FAX_DATA_BLOCK_SIZE
781
782                                try:
783                                    ret_value = self.dev.send_packet_for_message(FAX_DATA_BLOCK, 0, 0, 0, len(data))
784                                    if ret_value:
785                                       log.debug("Sending fax-data-block request failed with %d" % ret_value)
786                                       current_state = FAILURE
787                                    else:
788                                       log.debug("Successfully sent fax-data-block request")
789
790                                    self.dev.writeMarvellFax(data)
791                                    #self.dev.closeMarvellFax()
792                                except Error:
793                                    log.error("Channel write error.")
794                                    current_state = FAILURE
795                                    break
796
797                                bytes_to_write = bytes_to_write - FAX_DATA_BLOCK_SIZE
798
799                             page.truncate(0)
800                             page.seek(0)
801
802
803                     elif fax_send_state == FAX_SEND_STATE_END_FILE_DATA: # -------------- end-of-data
804                         log.debug("%s State: Send end-of-file-data request" % ("*"*20))
805                         fax_send_state = FAX_SEND_STATE_END_JOB_REQUEST
806
807                         ret_value = self.dev.send_packet_for_message(FAX_DATA_BLOCK, 0, 0, current_state, 0)
808                         if ret_value:
809                            log.debug("Sending fax-data-block packet failed with %d" % ret_value)
810                            current_state = FAILURE
811                         else:
812                            log.debug("Successfully sent fax-data-block request")
813                            ret_buf = self.dev.read_response_for_message(SEND_FAX_JOB)
814                            dev_response = self.dev.libfax_marvell.extract_response(ret_buf)
815                            if dev_response:
816                               log.debug("send-fax request failed with %d" % dev_response)
817                               current_state = FAILURE
818                            else:
819                               log.debug("send-fax request is successful")
820
821                            if current_state:
822                               log.debug("Exiting...")
823                               sys.exit(1)
824
825
826                     elif fax_send_state == FAX_SEND_STATE_END_JOB_REQUEST: # -------------- Wait for complete 
827                         log.debug("%s State: End the job" % ("*"*20))
828                         fax_send_state = FAX_SEND_STATE_NEXT_FILE
829
830                         ret_value = self.dev.send_packet_for_message(END_FAX_JOB, 0, 0, current_state, 0)
831                         if ret_value:
832                            log.debug("Sending end-fax-job packet failed with %d" % ret_value)
833                            current_state = FAILURE
834                         else:
835                            log.debug("Successfully sent end-fax-job request")
836                            ret_buf = self.dev.read_response_for_message(END_FAX_JOB)
837                            dev_response = self.dev.libfax_marvell.extract_response(ret_buf)
838                            if dev_response:
839                               log.debug("end-fax-job request failed with %d" % dev_response)
840                               current_state = FAILURE
841                            else:
842                               log.debug("end-fax-job request is successful")
843
844                         if current_state != SUCCESS:
845                            # There was an error during transmission...
846                            log.error("An error occurred! setting fax_send_state to DONE")
847                            fax_send_state = FAX_SEND_STATE_DONE
848
849                         try:
850                             ff.close()
851                         except NameError:
852                             pass
853
854                         time.sleep(1)
855
856                         self.dev.close()
857
858
859             elif state == STATE_CLEANUP: # --------------------------------- Cleanup 
860                 log.debug("%s State: Cleanup" % ("*"*20))
861
862                 if self.remove_temp_file:
863                     log.debug("Removing merged file: %s" % self.f)
864                     try:
865                         os.remove(self.f)
866                         log.debug("Removed")
867                     except OSError:
868                         log.debug("Not found")
869
870                 state = STATE_DONE
871
872