diff --git a/pos/is4c-nf/cc-modules/BasicCCModule.php b/pos/is4c-nf/cc-modules/BasicCCModule.php index a523c25b4d..4c5782579f 100644 --- a/pos/is4c-nf/cc-modules/BasicCCModule.php +++ b/pos/is4c-nf/cc-modules/BasicCCModule.php @@ -341,7 +341,7 @@ function soapify($action,$objs,$namespace="",$encode_tags=True){ function desoapify($action,$soaptext){ preg_match("/<$action.*?>(.*?)<\/$action>/s", $soaptext,$groups); - return $groups[1]; + return isset($groups[1]) ? $groups[1] : ""; } /** diff --git a/pos/is4c-nf/graphics/ccInLit.gif b/pos/is4c-nf/graphics/ccInLit.gif new file mode 100755 index 0000000000..c631a65250 Binary files /dev/null and b/pos/is4c-nf/graphics/ccInLit.gif differ diff --git a/pos/is4c-nf/graphics/ccTestLit.gif b/pos/is4c-nf/graphics/ccTestLit.gif new file mode 100755 index 0000000000..ac5b87da7b Binary files /dev/null and b/pos/is4c-nf/graphics/ccTestLit.gif differ diff --git a/pos/is4c-nf/gui-class-lib/BasicPage.php b/pos/is4c-nf/gui-class-lib/BasicPage.php index 4130c6ec5e..bb63db9bb9 100644 --- a/pos/is4c-nf/gui-class-lib/BasicPage.php +++ b/pos/is4c-nf/gui-class-lib/BasicPage.php @@ -57,8 +57,7 @@ function BasicPage(){ if ($this->preprocess()){ ob_start(); $this->print_page(); - while (ob_get_level() > 0) - ob_end_flush(); + ob_end_flush(); } } @@ -239,10 +238,16 @@ function betterDate() { } if($CORE_LOCAL->get("CCintegrate") == 1 && $CORE_LOCAL->get("ccLive") == 1 && $CORE_LOCAL->get("training") == 0){ - echo " "; + if ($CORE_LOCAL->get("CachePanEncBlock")=="") + echo " "; + else + echo " "; }elseif($CORE_LOCAL->get("CCintegrate") == 1 && ($CORE_LOCAL->get("training") == 1 || $CORE_LOCAL->get("ccLive") == 0)){ - echo " "; + if ($CORE_LOCAL->get("CachePanEncBlock")=="") + echo " "; + else + echo " "; } echo "".$time."\n"; diff --git a/pos/is4c-nf/gui-modules/paycardSuccess.php b/pos/is4c-nf/gui-modules/paycardSuccess.php index 56c5cca69a..f8709adc6e 100755 --- a/pos/is4c-nf/gui-modules/paycardSuccess.php +++ b/pos/is4c-nf/gui-modules/paycardSuccess.php @@ -72,6 +72,7 @@ function preprocess(){ } PaycardLib::paycard_reset(); + UdpComm::udpSend("termReset"); $CORE_LOCAL->set("strRemembered","TO"); $CORE_LOCAL->set("msgrepeat",1); @@ -188,6 +189,7 @@ function body_content(){ echo DisplayLib::boxMsg($CORE_LOCAL->get("boxMsg"),"",True); $CORE_LOCAL->set("msgrepeat",2); //UdpComm::udpSend('goodBeep'); + UdpComm::udpSend('termApproved'); ?> WriteToScale($CORE_LOCAL->get("ccTermOut")); PaycardLib::paycard_reset(); + $CORE_LOCAL->set("CachePanEncBlock",""); + $CORE_LOCAL->set("CachePinEncBlock",""); + $CORE_LOCAL->set("CacheCardType",""); + UdpComm::udpSend("termReset"); $this->change_page($this->page_url."gui-modules/pos2.php"); return False; } @@ -100,7 +104,10 @@ function body_content(){ echo PaycardLib::paycard_msgBox($type,"Invalid Amount", "Enter a lesser amount","[clear] to cancel"); } else if( $amt > 0) { - echo PaycardLib::paycard_msgBox($type,"Tender ".PaycardLib::paycard_moneyFormat($amt)."?","","[enter] to continue if correct
Enter a different amount if incorrect
[clear] to cancel"); + $msg = "Tender ".PaycardLib::paycard_moneyFormat($amt); + if ($CORE_LOCAL->get("CacheCardType") != "") + $msg .= " as ".$CORE_LOCAL->get("CacheCardType"); + echo PaycardLib::paycard_msgBox($type,$msg."?","","[enter] to continue if correct
Enter a different amount if incorrect
[clear] to cancel"); } else if( $amt < 0) { echo PaycardLib::paycard_msgBox($type,"Refund ".PaycardLib::paycard_moneyFormat($amt)."?","","[enter] to continue if correct
Enter a different amount if incorrect
[clear] to cancel"); } else { diff --git a/pos/is4c-nf/gui-modules/pos2.php b/pos/is4c-nf/gui-modules/pos2.php index fdf5473369..57e6ca6dd8 100644 --- a/pos/is4c-nf/gui-modules/pos2.php +++ b/pos/is4c-nf/gui-modules/pos2.php @@ -194,8 +194,7 @@ function receiptFetch(r_type){ }); } function inputRetry(str){ - $('#reginput').val(str); - submitWrapper(); + parseWrapper(str); } set("ccRemoteServerUp",1); $CORE_LOCAL->set("search_or_list",0); $CORE_LOCAL->set("ccTermOut","idle"); - $td = SigCapture::term_object(); - if (is_object($td)) - $td->WriteToScale("reset"); } /** @@ -145,6 +142,10 @@ static public function transReset() { $CORE_LOCAL->set("warned",0); $CORE_LOCAL->set("warnBoxType",""); $CORE_LOCAL->set("requestType",""); + + $CORE_LOCAL->set("CachePanEncBlock",""); + $CORE_LOCAL->set("CachePinEncBlock",""); + $CORE_LOCAL->set("CacheCardType",""); } /** diff --git a/pos/is4c-nf/parser-class-lib/parse/SigTermCommands.php b/pos/is4c-nf/parser-class-lib/parse/SigTermCommands.php index 8d096780b9..1c27c44bc9 100644 --- a/pos/is4c-nf/parser-class-lib/parse/SigTermCommands.php +++ b/pos/is4c-nf/parser-class-lib/parse/SigTermCommands.php @@ -25,12 +25,33 @@ class SigTermCommands extends Parser { function check($str){ global $CORE_LOCAL; - if ($str == "TRESET"){ - $CORE_LOCAL->set("ccTermOut","reset"); + if ($str == "TERMMANUAL"){ + UdpComm::udpSend("termManual"); return True; } - if ($str == "TSIG"){ - $CORE_LOCAL->set("ccTermOut","sig"); + elseif ($str == "TERMRESET"){ + UdpComm::udpSend("termReset"); + return True; + } + elseif ($str == "CCFROMCACHE"){ + return True; + } + else if (substr($str,0,9) == "PANCACHE:"){ + $CORE_LOCAL->set("CachePanEncBlock",substr($str,9)); + return True; + } + else if (substr($str,0,9) == "PINCACHE:"){ + $CORE_LOCAL->set("CachePinEncBlock",substr($str,9)); + return True; + } + else if ($str == "TERMCLEARALL"){ + $CORE_LOCAL->set("CachePanEncBlock",""); + $CORE_LOCAL->set("CachePinEncBlock",""); + $CORE_LOCAL->set("CacheCardType",""); + return True; + } + else if (substr($str,0,5) == "TERM:"){ + $CORE_LOCAL->set("CacheCardType",substr($str,5)); return True; } return False; @@ -39,9 +60,9 @@ function check($str){ function parse($str){ global $CORE_LOCAL; $ret = $this->default_json(); - $ret['udpmsg'] = $CORE_LOCAL->get("ccTermOut"); - if ($ret['udpmsg'] == "sig") - $ret['main_frame'] = MiscLib::base_url().'gui-modules/paycardSignature.php'; + if ($str == "CCFROMCACHE"){ + $ret['retry'] = $CORE_LOCAL->get("CachePanEncBlock"); + } return $ret; } @@ -51,13 +72,26 @@ function doc(){ InputResult - WAKEUP - Try to coax a stuck scale back - into operation + TERMMANUAL + + Send CC terminal to manual entry mode + + + + TERMRESET + Reset CC terminal to begin transaction + + + CCFROMCACHE + Charge the card cached earlier + + + PANCACHE: + Cache an encrypted block on swipe - WAKEUP2 - Different method, same goal + PINCACHE: + Cache an encrypted block on PIN entry "; } diff --git a/pos/is4c-nf/scale-drivers/drivers/NewMagellan/SPH_SignAndPay_USB.cs b/pos/is4c-nf/scale-drivers/drivers/NewMagellan/SPH_SignAndPay_USB.cs index 7ebaf23a71..57bf909f73 100755 --- a/pos/is4c-nf/scale-drivers/drivers/NewMagellan/SPH_SignAndPay_USB.cs +++ b/pos/is4c-nf/scale-drivers/drivers/NewMagellan/SPH_SignAndPay_USB.cs @@ -56,12 +56,36 @@ public class SPH_SignAndPay_USB : SerialPortHandler { private FileStream usb_fs; private int usb_report_size; + private const int LCD_X_RES = 320; + private const int LCD_Y_RES = 240; + + private const int STATE_START_TRANSACTION = 1; + private const int STATE_SELECT_CARD_TYPE = 2; + private const int STATE_ENTER_PIN = 3; + private const int STATE_WAIT_FOR_CASHIER = 4; + private const int STATE_SELECT_EBT_TYPE = 5; + private const int STATE_MANUAL_PAN = 11; + private const int STATE_MANUAL_EXP = 12; + private const int STATE_MANUAL_CVV = 13; + + private const int BUTTON_CREDIT = 5; + private const int BUTTON_DEBIT = 6; + private const int BUTTON_EBT = 7; + private const int BUTTON_GIFT = 8; + private const int BUTTON_EBT_FOOD = 9; + private const int BUTTON_EBT_CASH = 10; + private const int BUTTON_HARDWARE_BUTTON = 0xff; + + private int current_state; + private int ack_counter; + private string usb_devicefile; public SPH_SignAndPay_USB(string p) : base(p){ read_continues = false; long_length = 0; long_pos = 0; + ack_counter = 0; #if MONO usb_devicefile = p; @@ -85,9 +109,110 @@ public override void Read(){ System.Console.WriteLine("No device"); else System.Console.WriteLine("USB device found"); - byte[] version = BuildCommand(new byte[]{0x78,0x46,0x01}); - SendReport(version); + //SendReport(BuildCommand(LcdSetBacklightTimeout(0))); ReRead(); + SetStateStart(); + //SetStateCardType(); + } + + private void SetStateStart(){ + PushOutput("TERMCLEARALL"); + SendReport(BuildCommand(LcdStopCapture())); + SendReport(BuildCommand(PinpadCancelGetPIN())); + SendReport(BuildCommand(LcdFillColor(0xff,0xff,0xff))); + SendReport(BuildCommand(LcdFillRectangle(0,0,LCD_X_RES-1,LCD_Y_RES-1))); + + SendReport(BuildCommand(LcdTextFont(3,12,14))); + SendReport(BuildCommand(LcdTextColor(0,0,0))); + SendReport(BuildCommand(LcdTextBackgroundColor(0xff,0xff,0xff))); + SendReport(BuildCommand(LcdTextBackgroundMode(false))); + SendReport(BuildCommand(LcdDrawText("andy is awesome",5,5))); + SendReport(BuildCommand(LcdDrawText("swipe card",75,100))); + + current_state = STATE_START_TRANSACTION; + } + + private void SetStateCardType(){ + SendReport(BuildCommand(LcdFillColor(0xff,0xff,0xff))); + SendReport(BuildCommand(LcdFillRectangle(0,0,LCD_X_RES-1,LCD_Y_RES-1))); + + SendReport(BuildCommand(LcdStopCapture())); + SendReport(BuildCommand(LcdClearSignature())); + SendReport(BuildCommand(LcdSetClipArea(0,0,1,1))); + SendReport(BuildCommand(LcdCreateButton(BUTTON_CREDIT,"Credit",5,5,95,95))); + SendReport(BuildCommand(LcdCreateButton(BUTTON_DEBIT,"Debit",224,5,314,95))); + SendReport(BuildCommand(LcdCreateButton(BUTTON_EBT,"EBT",5,144,95,234))); + //SendReport(BuildCommand(LcdCreateButton(BUTTON_GIFT,"Gift",224,144,314,234))); + SendReport(BuildCommand(LcdStartCapture(4))); + + current_state = STATE_SELECT_CARD_TYPE; + } + + private void SetStateEbtType(){ + SendReport(BuildCommand(LcdFillColor(0xff,0xff,0xff))); + SendReport(BuildCommand(LcdFillRectangle(0,0,LCD_X_RES-1,LCD_Y_RES-1))); + + SendReport(BuildCommand(LcdStopCapture())); + SendReport(BuildCommand(LcdClearSignature())); + SendReport(BuildCommand(LcdSetClipArea(0,0,1,1))); + SendReport(BuildCommand(LcdCreateButton(BUTTON_EBT_FOOD,"Food Side",5,5,115,95))); + SendReport(BuildCommand(LcdCreateButton(BUTTON_EBT_CASH,"Cash Side",204,5,314,95))); + SendReport(BuildCommand(LcdStartCapture(4))); + + current_state = STATE_SELECT_EBT_TYPE; + } + + private void SetStateGetPin(){ + SendReport(BuildCommand(LcdStopCapture())); + ack_counter = 0; + + SendReport(BuildCommand(PinpadGetPIN())); + current_state = STATE_ENTER_PIN; + } + + private void SetStateWaitForCashier(){ + SendReport(BuildCommand(LcdStopCapture())); + SendReport(BuildCommand(LcdFillColor(0xff,0xff,0xff))); + SendReport(BuildCommand(LcdFillRectangle(0,0,LCD_X_RES-1,LCD_Y_RES-1))); + + SendReport(BuildCommand(LcdTextFont(3,12,14))); + SendReport(BuildCommand(LcdTextColor(0,0,0))); + SendReport(BuildCommand(LcdTextBackgroundColor(0xff,0xff,0xff))); + SendReport(BuildCommand(LcdTextBackgroundMode(false))); + SendReport(BuildCommand(LcdDrawText("wait for cashier",75,100))); + + current_state = STATE_WAIT_FOR_CASHIER; + } + + private void SetStateApproved(){ + SendReport(BuildCommand(LcdStopCapture())); + SendReport(BuildCommand(LcdFillColor(0xff,0xff,0xff))); + SendReport(BuildCommand(LcdFillRectangle(0,0,LCD_X_RES-1,LCD_Y_RES-1))); + + SendReport(BuildCommand(LcdTextFont(3,12,14))); + SendReport(BuildCommand(LcdTextColor(0,0,0))); + SendReport(BuildCommand(LcdTextBackgroundColor(0xff,0xff,0xff))); + SendReport(BuildCommand(LcdTextBackgroundMode(false))); + SendReport(BuildCommand(LcdDrawText("approved",75,100))); + } + + private void SetStateGetManualPan(){ + SendReport(BuildCommand(LcdStopCapture())); + ack_counter = 0; + SendReport(BuildCommand(ManualEntryPAN())); + current_state = STATE_MANUAL_PAN; + } + + private void SetStateGetManualExp(){ + ack_counter = 0; + SendReport(BuildCommand(ManualEntryExp())); + current_state = STATE_MANUAL_EXP; + } + + private void SetStateGetManualCVV(){ + ack_counter = 0; + SendReport(BuildCommand(ManualEntryCVV())); + current_state = STATE_MANUAL_CVV; } private void ReadCallback(IAsyncResult iar){ @@ -97,8 +222,6 @@ private void ReadCallback(IAsyncResult iar){ } catch (Exception ex){} - // prepend extra byte if report size is 64 - // then parsing is identical for win32/linux if (usb_report_size == 64){ byte[] temp_in = new byte[65]; temp_in[0] = 0; @@ -109,10 +232,10 @@ private void ReadCallback(IAsyncResult iar){ /* Data received, as bytes System.Console.WriteLine(""); - System.Console.WriteLine(""); + System.Console.WriteLine("IN BYTES:"); for(int i=0;i0 && i %16==0) System.Console.WriteLine(""); - System.Console.Write(input[i]+" "); + System.Console.Write("{0:x} ",input[i]); } System.Console.WriteLine(""); System.Console.WriteLine(""); @@ -127,11 +250,12 @@ private void ReadCallback(IAsyncResult iar){ if ( (input[1] & 0x80) != 0) read_continues = true; - if (report_length > 3){ + byte[] data = null; + if (report_length > 3 && (long_pos > 0 || input[2] == 0x02)){ // protcol messages int data_length = input[3] + (input[4] << 8); int d_start = 5; - if (input[d_start] == 0x6){ + if (input[d_start] == 0x6 && data_length > 1){ d_start++; // ACK byte data_length--; } @@ -154,7 +278,7 @@ private void ReadCallback(IAsyncResult iar){ if (data_length > report_length) data_length = report_length; - byte[] data = new byte[data_length]; + data = new byte[data_length]; for (int i=0; i 3){ // non-protcol messages + data = new byte[report_length]; + for(int i=0; i0 && i %16==0) System.Console.WriteLine(""); - System.Console.Write(long_buffer[i]+" "); - } - */ + + HandleDeviceMessage(long_buffer); + } + else { + HandleDeviceMessage(data); } read_continues = false; long_length = 0; @@ -211,12 +331,136 @@ private void ReadCallback(IAsyncResult iar){ ReRead(); } + private void HandleDeviceMessage(byte[] msg){ + System.Console.Write("DMSG: {0}: ",current_state); + foreach(byte b in msg) + System.Console.Write("{0:x} ",b); + System.Console.WriteLine(); + switch(current_state){ + case STATE_SELECT_CARD_TYPE: + if (msg.Length == 4 && msg[0] == 0x7a){ + if (msg[1] == BUTTON_CREDIT){ + PushOutput("TERM:Credit"); + SetStateWaitForCashier(); + } + else if (msg[1] == BUTTON_DEBIT){ + PushOutput("TERM:Debit"); + SetStateGetPin(); + } + else if (msg[1] == BUTTON_EBT){ + SetStateEbtType(); + } + else if (msg[1] == BUTTON_GIFT){ + PushOutput("TERM:Gift"); + SetStateWaitForCashier(); + } + else if (msg[1] == BUTTON_HARDWARE_BUTTON && msg[3] == 0x43){ + SetStateStart(); + } + } + break; + case STATE_SELECT_EBT_TYPE: + if (msg.Length == 4 && msg[0] == 0x7a){ + if (msg[1] == BUTTON_EBT_FOOD){ + PushOutput("TERM:EbtFood"); + SetStateGetPin(); + } + else if (msg[1] == BUTTON_EBT_CASH){ + PushOutput("TERM:EbtCash"); + SetStateGetPin(); + } + else if (msg[1] == BUTTON_HARDWARE_BUTTON && msg[3] == 0x43){ + SetStateStart(); + } + } + break; + case STATE_ENTER_PIN: + if (msg.Length == 3 && msg[0] == 0x15){ + SetStateStart(); + } + else if (msg.Length == 36){ + string pinhex = ""; + foreach(byte b in msg) + pinhex += ((char)b); + PushOutput("PINCACHE:"+pinhex); + SetStateWaitForCashier(); + } + break; + case STATE_MANUAL_PAN: + if (msg.Length == 1 && msg[0] == 0x6){ + ack_counter++; + System.Console.WriteLine(ack_counter); + if (ack_counter == 2) + SetStateGetManualExp(); + } + else if (msg.Length == 3 && msg[0] == 0x15){ + SetStateStart(); + } + break; + case STATE_MANUAL_EXP: + if (msg.Length == 1 && msg[0] == 0x6){ + ack_counter++; + System.Console.WriteLine(ack_counter); + if (ack_counter == 2) + SetStateGetManualCVV(); + } + else if (msg.Length == 3 && msg[0] == 0x15){ + SetStateStart(); + } + break; + case STATE_MANUAL_CVV: + if (msg.Length > 63 && msg[0] == 0x80 && msg[1] == 0x1f){ + string block = FixupCardBlock(msg); + PushOutput("PANCACHE:"+block); + SetStateCardType(); + } + else if (msg.Length == 3 && msg[0] == 0x15){ + SetStateStart(); + } + break; + case STATE_START_TRANSACTION: + if (msg.Length > 63 && msg[0] == 0x80 && msg[1] == 0x1f){ + string block = FixupCardBlock(msg); + PushOutput("PANCACHE:"+block); + SetStateCardType(); + } + else if (msg.Length > 1) + System.Console.WriteLine(msg.Length+" "+msg[0]+" "+msg[1]); + break; + default: + break; + } + } + + /** + * Convert encrypted card block to a hex string + * and add the serial protcol controcl characters back + * to the beginning and end. PHP-side software expects + * this format + */ + private string FixupCardBlock(byte[] data){ + string hex = BitConverter.ToString(data).Replace("-",""); + hex = "02E600"+hex+"XXXX03"; + return hex; + } + private void ReRead(){ byte[] buf = new byte[usb_report_size]; usb_fs.BeginRead(buf, 0, usb_report_size, new AsyncCallback(ReadCallback), buf); } public override void HandleMsg(string msg){ + switch(msg){ + case "termReset": + SetStateStart(); + break; + case "termManual": + SetStateGetManualPan(); + break; + case "termApproved": + SetStateApproved(); + break; + } } /** @@ -287,6 +531,15 @@ private byte LrcXor(byte[] data){ * Write to device in formatted reports */ private void SendReport(byte[] data){ + System.Console.WriteLine("Full Report "+data.Length); + for(int j=0;j 0) + System.Console.WriteLine(""); + System.Console.Write("{0:x} ",data[j]); + } + System.Console.WriteLine(""); + System.Console.WriteLine(""); + byte[] report = new byte[usb_report_size]; int size_field = (usb_report_size == 65) ? 1 : 0; @@ -296,22 +549,36 @@ private void SendReport(byte[] data){ for (int i=0;i 0 && i % 63 == 0){ report[size_field] = 63 | 0x80; + + /* + for(int j=0;j 0) + System.Console.WriteLine(""); + System.Console.Write(report[j]+" "); + } + System.Console.WriteLine(""); + */ + usb_fs.Write(report,0,usb_report_size); + for(int j=0;j 0) System.Console.WriteLine(""); System.Console.Write(report[i]+" "); } System.Console.WriteLine(""); + */ usb_fs.Write(report,0,usb_report_size); + System.Threading.Thread.Sleep(50); } private void PushOutput(string s){ @@ -328,6 +595,725 @@ private void PushOutput(string s){ MAGELLAN_OUTPUT_DIR+sep+ticks); } + /** + * Device Command Functions + */ + + private byte[] LcdTextFont(int charset, int width, int height){ + byte[] ret = new byte[9]; + + // command head + ret[0] = 0x8a; + ret[1] = 0x46; + ret[2] = 0x40; + + ret[3] = (byte)(0xff & height); + ret[4] = (byte)(0xff & width); + ret[5] = 0x0; // bold + ret[6] = 0x0; // italic + ret[7] = 0x0; // underlined + ret[8] = (charset > 6) ? (byte)6 : (byte)charset; + + return ret; + } + + private byte[] LcdTextColor(int red, int green, int blue){ + byte[] ret = new byte[6]; + + // Command head + ret[0] = 0x8a; + ret[1] = 0x46; + ret[2] = 0x41; + + ret[3] = (byte)(red & 0xff); + ret[4] = (byte)(green & 0xff); + ret[5] = (byte)(blue & 0xff); + + return ret; + } + + private byte[] LcdTextBackgroundColor(int red, int green, int blue){ + byte[] ret = new byte[6]; + + // Command head + ret[0] = 0x8a; + ret[1] = 0x46; + ret[2] = 0x42; + + ret[3] = (byte)(red & 0xff); + ret[4] = (byte)(green & 0xff); + ret[5] = (byte)(blue & 0xff); + + return ret; + } + + private byte[] LcdTextBackgroundMode(bool is_transparent){ + byte[] ret = new byte[4]; + + // Command head + ret[0] = 0x8a; + ret[1] = 0x46; + ret[2] = 0x43; + + ret[3] = (is_transparent) ? (byte)1 : (byte)0; + + return ret; + } + + private byte[] LcdDrawText(string text, int x, int y){ + byte[] ret = new byte[9 + text.Length]; + + // Command head + ret[0] = 0x8a; + ret[1] = 0x46; + ret[2] = 0x4f; + + ret[3] = (byte)(x & 0xff); + ret[4] = (byte)( (x >> 8) & 0xff); + + ret[5] = (byte)(y & 0xff); + ret[6] = (byte)( (y >> 8) & 0xff); + + ret[7] = (byte)(text.Length & 0xff); + ret[8] = (byte)( (text.Length >> 8) & 0xff); + + int pos = 9; + foreach(byte b in System.Text.Encoding.ASCII.GetBytes(text)){ + ret[pos] = b; + pos++; + } + + return ret; + } + + private byte[] LcdDrawTextInRectangle(string text, int x_top_left, int y_top_left, + int x_bottom_right, int y_bottom_right){ + + byte[] ret = new byte[13 + text.Length]; + + // Command head + ret[0] = 0x8a; + ret[1] = 0x46; + ret[2] = 0x4e; + + ret[3] = (byte)(x_top_left & 0xff); + ret[4] = (byte)( (x_top_left >> 8) & 0xff); + + ret[5] = (byte)(y_top_left & 0xff); + ret[6] = (byte)( (y_top_left >> 8) & 0xff); + + ret[7] = (byte)(x_bottom_right & 0xff); + ret[8] = (byte)( (x_bottom_right >> 8) & 0xff); + + ret[9] = (byte)(y_bottom_right & 0xff); + ret[10] = (byte)( (y_bottom_right >> 8) & 0xff); + + ret[11] = (byte)(text.Length & 0xff); + ret[12] = (byte)( (text.Length >> 8) & 0xff); + + int pos = 13; + foreach(byte b in System.Text.Encoding.ASCII.GetBytes(text)){ + ret[pos] = b; + pos++; + } + + return ret; + } + + private byte[] LcdFillColor(int red, int green, int blue){ + byte[] ret = new byte[6]; + + // Command head + ret[0] = 0x8a; + ret[1] = 0x46; + ret[2] = 0x20; + + ret[3] = (byte)(0xff & red); + ret[4] = (byte)(0xff & green); + ret[5] = (byte)(0xff & blue); + + return ret; + } + + private byte[] LcdFillRectangle(int x_top_left, int y_top_left, + int x_bottom_right, int y_bottom_right){ + byte[] ret = new byte[11]; + + // Command head + ret[0] = 0x8a; + ret[1] = 0x46; + ret[2] = 0x22; + + ret[3] = (byte)(x_top_left & 0xff); + ret[4] = (byte)( (x_top_left >> 8) & 0xff); + + ret[5] = (byte)(y_top_left & 0xff); + ret[6] = (byte)( (y_top_left >> 8) & 0xff); + + ret[7] = (byte)(x_bottom_right & 0xff); + ret[8] = (byte)( (x_bottom_right >> 8) & 0xff); + + ret[9] = (byte)(y_bottom_right & 0xff); + ret[10] = (byte)( (y_bottom_right >> 8) & 0xff); + + return ret; + } + + /** + * @param interval is five second periods. + * 1=> 5 seconds, 2=> 10 seconds, etc + * 0=> always on + */ + private byte[] LcdSetBacklightTimeout(int interval){ + byte[] ret = new byte[5]; + + // Command head + ret[0] = 0x8a; + ret[1] = 0x53; + ret[2] = 0x80; + + ret[3] = 0x1; + ret[4] = (byte)(interval & 0xff); + + return ret; + } + + private byte[] LcdSetClipArea(int x_top_left, int y_top_left, int x_bottom_right, int y_bottom_right){ + byte[] ret = new byte[15]; + + // Command head + ret[0] = 0x7a; + ret[1] = 0x46; + ret[2] = 0x03; + + ret[3] = (byte)(x_top_left & 0xff); + ret[4] = (byte)( (x_top_left >> 8) & 0xff); + + ret[5] = (byte)(y_top_left & 0xff); + ret[6] = (byte)( (y_top_left >> 8) & 0xff); + + ret[7] = (byte)(x_bottom_right & 0xff); + ret[8] = (byte)( (x_bottom_right >> 8) & 0xff); + + ret[9] = (byte)(y_bottom_right & 0xff); + ret[10] = (byte)( (y_bottom_right >> 8) & 0xff); + + ret[11] = 0x0; // don't show lines around area + + // rgb for border lines + ret[12] = 0x0; + ret[13] = 0x0; + ret[14] = 0x0; + + return ret; + } + + private byte[] LcdCreateButton(int id, string label, int x_top_left, int y_top_left, + int x_bottom_right, int y_bottom_right){ + + byte[] ret = new byte[16 + label.Length]; + + // Command head + ret[0] = 0x7a; + ret[1] = 0x46; + ret[2] = 0x04; + + ret[3] = (byte)(id & 0xff); + ret[4] = 0x1; // button is type 1 + ret[5] = 0xf; + + ret[6] = (byte)(x_top_left & 0xff); + ret[7] = (byte)( (x_top_left >> 8) & 0xff); + + ret[8] = (byte)(y_top_left & 0xff); + ret[9] = (byte)( (y_top_left >> 8) & 0xff); + + ret[10] = (byte)(x_bottom_right & 0xff); + ret[11] = (byte)( (x_bottom_right >> 8) & 0xff); + + ret[12] = (byte)(y_bottom_right & 0xff); + ret[13] = (byte)( (y_bottom_right >> 8) & 0xff); + + ret[14] = (byte)(label.Length & 0xff); + ret[15] = (byte)( (label.Length >> 8) & 0xff); + + int pos = 16; + foreach(byte b in System.Text.Encoding.ASCII.GetBytes(label)){ + ret[pos] = b; + pos++; + } + + return ret; + } + + private byte[] LcdCalibrateTouch(){ + return new byte[3]{ 0x7a, 0x46, 0x1 }; + } + + /** + * Mode 5 => buffered + * Mode < 5 => streaming data + */ + private byte[] LcdStartCapture(int mode){ + byte[] ret = new byte[11]; + + ret[0] = 0x7a; + ret[1] = 0x46; + ret[2] = 0x10; + + ret[3] = (byte)(0xff & mode); + + ret[4] = 0x7a; + + ret[5] = 0x0; + ret[6] = 0x0; + ret[7] = 0x0; + + ret[8] = 0xff; + ret[9] = 0xff; + ret[10] = 0xff; + + return ret; + } + + private byte[] LcdClearSignature(){ + return new byte[3]{ 0x7a, 0x46, 0x19 }; + } + + private byte[] LcdStopCapture(){ + return new byte[3]{ 0x7a, 0x46, 0x1f }; + } + + private byte[] PinpadGetPIN(){ + byte[] ret = new byte[112]; + int pos = 0; + + // Command head + ret[pos++] = 0x75; + ret[pos++] = 0x46; + ret[pos++] = 0x07; + + ret[pos++] = 0x31; // key type DUKPT + ret[pos++] = 0xc; // max pin length + ret[pos++] = 0x4; // min pin length + ret[pos++] = 0x0; // no account # + ret[pos++] = 0x3; // clear display, show messages + + // background color + ret[pos++] = 0xff; + ret[pos++] = 0xff; + ret[pos++] = 0xcc; + + // font setting + ret[pos++] = 0x16; + ret[pos++] = 0x18; + ret[pos++] = 0; + ret[pos++] = 0; + ret[pos++] = 0; + ret[pos++] = 5; + + // color for something + ret[pos++] = 0; + ret[pos++] = 0; + ret[pos++] = 0; + + ret[pos++] = 0x1; // transparent + + // text color + ret[pos++] = 0xff; + ret[pos++] = 0xff; + ret[pos++] = 0xff; + + // xy set 1 + ret[pos++] = 0x20; + ret[pos++] = 0; + ret[pos++] = 0x60; + ret[pos++] = 0; + + // xy set 2 + ret[pos++] = 0x10; + ret[pos++] = 0x1; + ret[pos++] = 0x90; + ret[pos++] = 0; + + ret[pos++] = 0xf; // show 4 lines + ret[pos++] = 2; // 2 messages follow + ret[pos++] = 0; + ret[pos++] = 0x1f; // message length + ret[pos++] = 0; + + // another font + ret[pos++] = 0x10; + ret[pos++] = 0x10; + ret[pos++] = 0x0; + ret[pos++] = 0x0; + ret[pos++] = 0x0; + ret[pos++] = 0x3; + + // text rgb + ret[pos++] = 0x0; + ret[pos++] = 0x0; + ret[pos++] = 0xff; + + ret[pos++] = 0x1; // transparent + + // background rgb + ret[pos++] = 0xff; + ret[pos++] = 0xff; + ret[pos++] = 0xff; + + // text xy + ret[pos++] = 0x40; + ret[pos++] = 0x0; + ret[pos++] = 0x20; + ret[pos++] = 0x0; + + // text length + ret[pos++] = 0xa; + ret[pos++] = 0; + + string msg = "Enter PIN:"; + foreach(byte b in System.Text.Encoding.ASCII.GetBytes(msg)){ + ret[pos] = b; + pos++; + } + + // next message length + ret[pos++] = 0x2e; + ret[pos++] = 0x0; + + // another font + ret[pos++] = 0xc; + ret[pos++] = 0xc; + ret[pos++] = 0x0; + ret[pos++] = 0x0; + ret[pos++] = 0x0; + ret[pos++] = 0x3; + + // another rgb + ret[pos++] = 0x0; + ret[pos++] = 0x0; + ret[pos++] = 0xff; + + ret[pos++] = 1; // transparent + + // background rgb + ret[pos++] = 0xff; + ret[pos++] = 0xff; + ret[pos++] = 0xff; + + // xy + ret[pos++] = 0x6; + ret[pos++] = 0x0; + ret[pos++] = 0xb4; + ret[pos++] = 0x0; + + // text length + ret[pos++] = 0x19; + ret[pos++] = 0x0; + + msg = "Press Enter Key When Done"; + + foreach(byte b in System.Text.Encoding.ASCII.GetBytes(msg)){ + ret[pos] = b; + pos++; + } + + return ret; + } + + private byte[] PinpadCancelGetPIN(){ + return new byte[3]{ 0x75, 0x46, 0x9 }; + } + + private byte[] ManualEntryPAN(){ + byte[] ret = new byte[68]; + + int pos = 0; + ret[pos++] = 0x75; + ret[pos++] = 0x46; + ret[pos++] = 0x40; + + ret[pos++] = 0x0; // card type + ret[pos++] = 0x1; // PAN mode + ret[pos++] = 23; // max length + ret[pos++] = 6; // min length + ret[pos++] = 0x3; // redraw screen + + // rgb background + ret[pos++] = 0xff; + ret[pos++] = 0xff; + ret[pos++] = 0xff; + + // font setting + ret[pos++] = 0x16; + ret[pos++] = 0x18; + ret[pos++] = 0; + ret[pos++] = 0; + ret[pos++] = 0; + ret[pos++] = 5; + + // color for something + ret[pos++] = 0; + ret[pos++] = 0; + ret[pos++] = 0; + + ret[pos++] = 0x1; // transparent + + // text color + ret[pos++] = 0xff; + ret[pos++] = 0xff; + ret[pos++] = 0xff; + + // xy set 1 + ret[pos++] = 0x20; + ret[pos++] = 0; + ret[pos++] = 0x60; + ret[pos++] = 0; + + // xy set 2 + ret[pos++] = 0x10; + ret[pos++] = 0x1; + ret[pos++] = 0x90; + ret[pos++] = 0; + + ret[pos++] = 0xf; // show 4 lines + ret[pos++] = 1; // 1 messages follow + ret[pos++] = 0; + ret[pos++] = 33; + ret[pos++] = 0; + + // another font + ret[pos++] = 0x10; + ret[pos++] = 0x10; + ret[pos++] = 0x0; + ret[pos++] = 0x0; + ret[pos++] = 0x0; + ret[pos++] = 0x3; + + // text rgb + ret[pos++] = 0x0; + ret[pos++] = 0x0; + ret[pos++] = 0xff; + + ret[pos++] = 0x1; // transparent + + // background rgb + ret[pos++] = 0xff; + ret[pos++] = 0xff; + ret[pos++] = 0xff; + + // text xy + ret[pos++] = 0x40; + ret[pos++] = 0x0; + ret[pos++] = 0x20; + ret[pos++] = 0x0; + + string msg = "Enter Card #"; + ret[pos++] = 12; + ret[pos++] = 0; + + foreach(byte b in System.Text.Encoding.ASCII.GetBytes(msg)){ + ret[pos] = b; + pos++; + } + + return ret; + } + + private byte[] ManualEntryExp(){ + byte[] ret = new byte[70]; + + int pos = 0; + ret[pos++] = 0x75; + ret[pos++] = 0x46; + ret[pos++] = 0x40; + + ret[pos++] = 0x0; // card type + ret[pos++] = 0x2; // exp mode + ret[pos++] = 4; // max length + ret[pos++] = 4; // min length + ret[pos++] = 0x3; // redraw screen + + // rgb background + ret[pos++] = 0xff; + ret[pos++] = 0xff; + ret[pos++] = 0xff; + + // font setting + ret[pos++] = 0x16; + ret[pos++] = 0x18; + ret[pos++] = 0; + ret[pos++] = 0; + ret[pos++] = 0; + ret[pos++] = 5; + + // color for something + ret[pos++] = 0; + ret[pos++] = 0; + ret[pos++] = 0; + + ret[pos++] = 0x1; // transparent + + // text color + ret[pos++] = 0xff; + ret[pos++] = 0xff; + ret[pos++] = 0xff; + + // xy set 1 + ret[pos++] = 0x20; + ret[pos++] = 0; + ret[pos++] = 0x60; + ret[pos++] = 0; + + // xy set 2 + ret[pos++] = 0x10; + ret[pos++] = 0x1; + ret[pos++] = 0x90; + ret[pos++] = 0; + + ret[pos++] = 0xf; // show 4 lines + ret[pos++] = 1; // 1 messages follow + ret[pos++] = 0; + ret[pos++] = 35; + ret[pos++] = 0; + + // another font + ret[pos++] = 0x10; + ret[pos++] = 0x10; + ret[pos++] = 0x0; + ret[pos++] = 0x0; + ret[pos++] = 0x0; + ret[pos++] = 0x3; + + // text rgb + ret[pos++] = 0x0; + ret[pos++] = 0x0; + ret[pos++] = 0xff; + + ret[pos++] = 0x1; // transparent + + // background rgb + ret[pos++] = 0xff; + ret[pos++] = 0xff; + ret[pos++] = 0xff; + + // text xy + ret[pos++] = 0x40; + ret[pos++] = 0x0; + ret[pos++] = 0x20; + ret[pos++] = 0x0; + + string msg = "Enter Exp MMYY"; + ret[pos++] = 14; + ret[pos++] = 0; + + foreach(byte b in System.Text.Encoding.ASCII.GetBytes(msg)){ + ret[pos] = b; + pos++; + } + + return ret; + } + + private byte[] ManualEntryCVV(){ + byte[] ret = new byte[75]; + + int pos = 0; + ret[pos++] = 0x75; + ret[pos++] = 0x46; + ret[pos++] = 0x40; + + ret[pos++] = 0x0; // card type + ret[pos++] = 0x3; // CVV mode + ret[pos++] = 4; // max length + ret[pos++] = 3; // min length + ret[pos++] = 0x3; // redraw screen + + // rgb background + ret[pos++] = 0xff; + ret[pos++] = 0xff; + ret[pos++] = 0xff; + + // font setting + ret[pos++] = 0x16; + ret[pos++] = 0x18; + ret[pos++] = 0; + ret[pos++] = 0; + ret[pos++] = 0; + ret[pos++] = 5; + + // color for something + ret[pos++] = 0; + ret[pos++] = 0; + ret[pos++] = 0; + + ret[pos++] = 0x1; // transparent + + // text color + ret[pos++] = 0xff; + ret[pos++] = 0xff; + ret[pos++] = 0xff; + + // xy set 1 + ret[pos++] = 0x20; + ret[pos++] = 0; + ret[pos++] = 0x60; + ret[pos++] = 0; + + // xy set 2 + ret[pos++] = 0x10; + ret[pos++] = 0x1; + ret[pos++] = 0x90; + ret[pos++] = 0; + + ret[pos++] = 0xf; // show 4 lines + ret[pos++] = 1; // 1 messages follow + ret[pos++] = 0; + ret[pos++] = 40; + ret[pos++] = 0; + + // another font + ret[pos++] = 0x10; + ret[pos++] = 0x10; + ret[pos++] = 0x0; + ret[pos++] = 0x0; + ret[pos++] = 0x0; + ret[pos++] = 0x3; + + // text rgb + ret[pos++] = 0x0; + ret[pos++] = 0x0; + ret[pos++] = 0xff; + + ret[pos++] = 0x1; // transparent + + // background rgb + ret[pos++] = 0xff; + ret[pos++] = 0xff; + ret[pos++] = 0xff; + + // text xy + ret[pos++] = 0x40; + ret[pos++] = 0x0; + ret[pos++] = 0x20; + ret[pos++] = 0x0; + + string msg = "Enter Security Code"; + ret[pos++] = 19; + ret[pos++] = 0; + + foreach(byte b in System.Text.Encoding.ASCII.GetBytes(msg)){ + ret[pos] = b; + pos++; + } + + return ret; + } + + private byte[] ResetDevice(){ + return new byte[7]{0x78, 0x46, 0x0a, 0x49, 0x52, 0x46, 0x57}; + } } }