UNSOLVED

sredniv

updated

10 years ago

S

sredniv

4 Posts

0

12817

October 25th, 2016 16:00

P4317Q, RS232 interface

Has anyone worked with the RS232 interface for the P4317Q monitor? I'm trying to get some basic queries of information working and I seem to be having trouble with the checksum values. The documentation (see below) isn't very clear on how the checksum is calculated and I've tried a couple methods for doing it without 100% success. I'd be interested in hearing if anyone has written any code to interface with the RS232 on this monitor and might be willing to share? Or, if there's a bit more in-depth sample code from Dell on the subject?

Thanks,

Jason

P4317Q RS232 Protocol Document

  • swamped1

    234 Posts

    8718

    0

    Posted October 28th, 2016 06:00

    Just a guess - the docs give this example message:

    Example: Get Monitor Name (Maximum 10 characters)

    [From PC to Monitor] = S, 37a, 51a, 02a, EBa, 01a, CHKp

    Try using this message instead:

    [From PC to Monitor] = S, 37a, 51a, 02a, EBa, 01a, 8Ep

    if CHK=8E doesn't work, try E1.

  • sredniv

    4 Posts

    8718

    0

    Posted October 28th, 2016 09:00

    Thanks for the reply.

    I've realized that I can't tell if those values for checksum are valid on the way to the monitor because it doesn't seem to do any checking.  For the 8E value, I can't use the basic XOR method to validate the checksum in the response from the monitor.  I'm not sure how you got E1.  What was the method for arriving at E1?

    The following is the entire response I get back from the monitor:

       6f:37:0f:02:00:01:44:65:6c:6c:20:50:34:33:31:37:51:00:0d

    As you can see, the checksum on that is 0D, but I can't figure out what method the monitor has used to generate that value.  Simple XOR results in 55.

    I would like to figure out how to validate these checksums, but at the end of the day, it seems to not be necessary.  The monitor obviously isn't insisting on them being correct, and my use of the responses doesn't depend on them either.

    Thanks!

  • swamped1

    234 Posts

    8718

    0

    Posted October 29th, 2016 05:00

    The checksum in your reply appears to be the XORed result of the payload excluding the header.

    0F:02:00:01:44:65:6C:6C:20:50:34:33:31:37:51:00 = 0D

    If that's so, the checksum for the command message would be:

    02:EB:01 = E8

  • 8718

    0

    Posted December 13th, 2016 08:00

    Sorry to hijack your thread but I'm also trying to use the RS232 port to remotely administer my P4317Q and am having trouble.

    Did you use a straight-through or null modem cable?

    (If using Linux) how did you determine which /dev/ttyS* was being used?

    For writing to the serial port, what did you send to the monitor get the monitor name? e.g.:

    echo -ne ' S, \x37a, \x51a, \x02a, \xEBa, \x01a' > /dev/ttyS*

    How did you go about viewing the response from the monitor? e.g.:

    cat -v < /dev/ttyS*

    Thanks.

  • rafir

    3 Posts

    8727

    0

    Posted February 4th, 2017 09:00

    What are the significance of "S" and "p"?

  • kevinf28

    5 Posts

    8757

    2

    Posted March 29th, 2017 09:00

    S, a, p seem to be some sort of notation in their API documentation, but not used.

    They do mention the pinout, but it is non-standard, in that both my workstation and monitor have female DB-9 connectors, which suggests the use of a Null-Modem cable. That is wrong. I got it working with straight cable and a M-M gender changer adapter. Dell, please use Male connectors on future monitors or swap your TX/RX. I tested with firmware M2C103.

    There are also many errors and omissions, incorrect lengths, and misleading formats in the documentation, eg:

    Example itself implies it will return this: o7????P4317Q

    I ran the cmd: 375102eb018e
    it returned: o7\0x0f\0x02\0x00\0x01Dell P4317Q\0x00

    So much for the "Maximum 10 characters", "Dell P4317Q" is 11.

    GetBacklightHours returned LSB first (0x02f6 aka 758 hrs is correct).
    6f 37 05 02 00 04 f6 02 f7

    PBP sub-inputs are missing, here they are:
    01:Mhl1
    02:Mhl2
    08:DP
    10:mDP
    40:VGA

    Checksum value can be excluded, or simply 00

    Extra trailing 00s are safe.

    If you get 'Len' incorrect, no response is returned at all.

    As per documentation GetPxPSubInput takes no parameters and returns 4 values. In reality, first param is the subinput window: 0-3. Response for fetching top left corner (2) returns 10 (mDP)

    sent: 375102eb710200
    returned: 6f 37 07 02 00 71 10 00   00 00 64

    Errors look like: 6f 37 03 02 ff 71 8f  (trying to get subwindow > 3)

    I planned on creating a whole Java program to query / set arbitrary CMDs, but based on the inaccuracies in this document, that will be a painful process.

    Here are two bash scripts I made instead.


    #!/bin/bash
    # This script enables quadsplit PBP and sets each subinput
    # on my system, DP1 = mDP, DP2 = DP, both connected to workstation
    # uses xrandr to set the resolution of my workstation to 1920x2160
    # reference guide: dell-p4317q-monitor_reference guide_rs232_api_en-us.pdf

    export DISPLAY=:0

    #SetPxPMode |  Head0 Head1 Len R/W Cmd Data Chksum
    echo -ne '\x37\x51\x02\xea\x70\x08\x00' > /dev/ttyUSB0

    # set DP on bottom left
    echo -ne '\x37\x51\x03\xea\x71\x01\x08\x00' > /dev/ttyUSB0
    sleep 3
    # set VGA on bottom right
    echo -ne '\x37\x51\x03\xea\x71\x00\x40\x00' > /dev/ttyUSB0
    sleep 3
    # set mDP on top left
    echo -ne '\x37\x51\x03\xea\x71\x02\x10\x00' > /dev/ttyUSB0
    sleep 3
    # set MHL1 on top right
    echo -ne '\x37\x51\x03\xea\x71\x03\x01\x00' > /dev/ttyUSB0
    sleep 3

    # set MHL2 on top right
    # echo -ne '\x37\x51\x03\xea\x71\x03\x02\x00' > /dev/ttyUSB0

    chvt 7
    sleep 3
    xrandr --auto
    xrandr --output DP1 --mode 1920x1080
    xrandr --output DP2 --mode 1920x1080
    xrandr --output DP2 --below DP1


    #!/bin/bash
    # This script disables any PBP settings, and sets mDP to 4k
    # on my system, DP1 = mDP, DP2 = DP, both connected
    # reference guide: dell-p4317q-monitor_reference guide_rs232_api_en-us.pdf

    export DISPLAY=:0

    # disable quadsplit (Dell resets input to VGA, even with autoselect off)
    echo -ne '\x37\x51\x02\xea\x70\x00\x00' > /dev/ttyUSB0
    sleep 3

    # set primary input to mDP
    echo -ne '\x37\x51\x03\xea\x62\x10\x00\x00' > /dev/ttyUSB0
    sleep 3

    # force 4k resolution on mDP, disable DP
    xrandr --auto
    xrandr --output DP1 --mode 3840x2160
    xrandr --output DP2 --off


    Hope that helps you fine folks. This is an amazing monitor, even though the API is frustrating, the control via RS-232 is great.

  • kevinf28

    5 Posts

    8757

    1

    Posted March 31st, 2017 14:00

    Seems like the update to M2C104 broke the API.

    from my notes:

    ---
    the LED works though! proves the checksum is not needed, even for set operation
    375103ea210000 turned off the LED
    375103ea210100 turned on the LED
    ---

    no longer works :(

  • rafir

    3 Posts

    8757

    0

    Posted April 10th, 2017 14:00

    Thanks kevinf28.  Tried the commands you posted earlier and for the first time saw anything from my monitor, yay!  Once that worked, I suspect one thing that might have gone wrong earlier is that I was testing with commands that were failing silently (like polling for the asset tag)?  Hard to say.

    But I should note that I was seeing some strange behaviors where some responses were being buffered (I'm not sure whether that was in the computer or monitor).  And the some of the commands I tried playing with were not following the documented format, particularly the length field.

    So, naturally I updated to 104 and things stopped working.  More interesting is that the monitor started responding to every command, both sets and gets.  And it's even giving response codes for why things are failing.

    At this point, I'm only seeing 02 (parameter errors) and 01 (timeout).  Seems like something of an improvement.  I suspect that it might actually be checking the checksums.  Time to write a quite parser and play around with potential checksums.

  • sredniv

    4 Posts

    8757

    0

    Posted April 10th, 2017 17:00

    The following is the python program I put together to query and set values in the monitor.  It's not super beautiful, but it works well.  You likely will need to change the name of the serial port in the  p4317q_handle_command function.  Also, it relies on PySerial, so you need that, too.

    I've been using it for several months now and it has served well.  I haven't upgraded to the 104 firmware, either.  Not sure I'll do that if it breaks everything.  :)

    #!/usr/bin/python

    import sys

    import struct

    import serial

    import binascii

    debug=False

    CMD_HEADER=bytearray([0x37, 0x51])

    CMD_READ=0xEB

    CMD_WRITE=0xEA

    # Only get commands have a response.

    RSP_HEADER=bytearray([0x6F, 0x37])

    RSP_REPLY_CODE=0x02

    def print_debug(message):

       "Debug print message"

       if (debug == True):

           print message

    def print_usage():

       "Print program usage"

       print sys.argv[0] + " usage:"

       print sys.argv[0] + "{get|set|reset} {command} [parameter]"

       print ""

       print "get   - Retrieves information from the monitor"

       print "set   - Sets a value in the monitor"

       print "reset - Resets a monitor capability"

       print ""

       print " parameter is required only for set commands"

       print ""

       print "get commands:"

       print "    assettag, monitorname, monitorserial, backlighthours"

       print "    powerstate, powerled, powerusb"

       print "    brightness, contrast, aspectratio, sharpness"

       print "    inputcolorformat, colorpresetcaps, colorpreset, customcolor"

       print "    autoselect, videoinputcaps, videoinput"

       print "    pxpmode, pxpsubinput, pxplocation"

       print "    osdtransparency, osdlanguage, osdtimer, osdbuttonlock"

       print "    versionfirmware, ddcci, lcdconditioning"

       print ""

       print "set commands:"

       print "    powerstate, powerled, powerusb"

       print "    brightness, contrast, aspectratio, sharpness"

       print "    inputcolorformat, colorpreset, customcolor"

       print "    autoselect, videoinput"

       print "       Video Input Names:"

       print "           vga, dp, mdp, hdmi1, hdmi2"

       print "    pxpmode, pxpsubinput, pxplocation"

       print "       PxP modes:"

       print "           4k:        3840x2160 full screen"

       print "           smallPip:  3840x2160 full screen (primary video input)"

       print "                      small inset picture-in-picture"

       print "           bigPip:    3840x2160 full screen (primary video input)"

       print "                      large inset picture-in-picture"

       print "           4x4:       four 1920x1080 panes"

       print "           1x2:       one 3840x1080 window over 2x 1920x1080"

       print "           2x1:       one 1920x2160 window right of 2x 1920x1080"

       print "           SxS:       two 1920x2160 panes"

       print "       PiP Locations:"

       print "           topRight, topLeft, bottomRight, bottomLeft"

       print "    osdtransparency, osdlanguage, osdtimer, osdbuttonlock"

       print "       OSD Languages:"

       print "           english, spanish, french, german, portugese,"

       print "           russian, chinese, japanese"

       print "    ddcci, lcdconditioning"

       print ""

       print "reset commands:"

       print "    power, color, osd, factory"

    def dump_info():

       commands = ["monitorname", "monitorserial", "backlighthours", "powerstate", "powerled", "powerusb", "brightness", "contrast", "aspectratio", "sharpness", "inputcolorformat", "colorpresetcaps", "colorpreset", "customcolor", "autoselect", "videoinputcaps", "videoinput", "pxpmode", "pxpsubinput", "pxplocation", "osdtransparency", "osdlanguage", "osdtimer", "osdbuttonlock", "versionfirmware", "ddcci", "lcdconditioning"]

       for command in commands:

           if (command == "pxpsubinput"):

               for index in range(0,4):

                   p4317q_handle_command("get", command, index)

           else:

               param = None

               if (command == "customcolor"):

                   param = 0

               p4317q_handle_command("get", command, param)

    def p4317q_hex_format(message):

       "Create a hex-ascii string representation of message"

       hex = binascii.b2a_hex(message)

       formatted_hex = ':'.join(hex[i:i+2] for i in range(0, len(hex), 2))

       return formatted_hex

    def p4317q_checksum(message, begin, length):

       "Calculate the single byte checksum of the input data"

       total = 0 #x58^length

       for index in range(begin,begin+length):

           #total += message[index]

           total ^= message[index]

           #total &= 0xFF

           print_debug("DB:  total ^ 0x" + p4317q_hex_format(bytearray([message[index]])) + " = 0x" + p4317q_hex_format(bytearray([total&0xff])))

       total &= 0xFF

       print_debug("DB:  " + str(total)+ " 0x" + p4317q_hex_format(bytearray([total])))

       # Compute 2's complement of the sum.  Comment out if this isn't needed

       #total = (~total+1) & 0xFF

       print_debug("DB:  " + str(total)+ " 0x" + p4317q_hex_format(bytearray([total])))

       return total

    #0x6E, 0x51, 0x02, 0xEB, 0x01, D7p

    def p4317q_build_command(action, value, param):

       "Build a command to be sent to the monitor.  Assumed that param is a bytearray of the correct length"

       cmd_tag = (ACTIONS_MAP[action])[value]

       cmd_len = (ACTIONS_MAP[action])[value+"_len"]

       print_debug("DEBUG:  Param is [" + str(param) + "].  Type is [" + str(type(param)) + "].")

       command = CMD_HEADER + bytearray([cmd_len])

       if (action == "set"):

           cmd_act = CMD_WRITE

           command = command + bytearray([cmd_act]) + bytearray([cmd_tag])

           if (isinstance(param, bytearray)):

               command += param

           else:

               command += bytearray([param])

       else:

           cmd_act = CMD_READ

           command = command + bytearray([cmd_act]) + bytearray([cmd_tag])

           if (param is not None): command += bytearray([param])

       # compute the checksum and add that to the end

       checksum = p4317q_checksum(command, 2, cmd_len+1)

       command = command + bytearray([checksum])

       return command

    def p4317q_send_command(ser_port, command):

       ser_port.write(command)

    def p4317q_parse_response(response, command):

       response_data = bytearray(response)

       hex = p4317q_hex_format(bytearray([command]))

       print_debug("Parsing response.  Expecting command [" + hex + "].")

       print_debug("Response data:\n    " + p4317q_hex_format(response_data))

       print_debug("Verifying checksum.")

       ckdata = bytearray([len(response_data)-1]) + response_data

       #chksum = p4317q_checksum(response_data,0,len(response_data)-1)

       chksum = p4317q_checksum(ckdata,0,len(ckdata)-1)

       if (chksum != response_data[len(response_data)-1]):

           print_debug("ERROR.  CheckSum does not verify.  Calculated == " + p4317q_hex_format(bytearray([chksum])) + ".")

           # Checksum verification doesn't seem to matter (or work)

           return None

       else:

           print_debug("Checksum verified.")

       if (response_data[0] != RSP_REPLY_CODE):

           print "ERROR.  Reply code incorrect."

           return None

       print_debug("Result code = " + p4317q_hex_format(bytearray([response_data[1]])))

       # Probably could do with some operation on the result code here...

       if (response_data[2] != command):

           print_debug("DEBUG " + str(response_data[2]) + " == " + str(command) + ".")

           print "ERROR.  Received incorrect command response."

           return None

       else:

           print_debug("Command response is correct.")

       print_debug("Response Data:        " + p4317q_hex_format(response_data[3:-1]))

       if (command in (CMD_G_MONITOR_NAME_C, CMD_G_ASSET_TAG_C, CMD_G_MONITOR_SERIAL_C, CMD_G_VERSION_FIRMWARE_C)):

           print_debug("ASCII Response Data:  " + response_data[3:-1])

       print_debug("Done parsing.")

       return response_data[3:-1]

    def p4317q_read_response(ser_port):

       # Read 2 bytes, make sure they're == RSP_HEADER

       resp_header = ser_port.read(2)

       print_debug("DEBUG:  Response header received has " + str(len(resp_header)) + " bytes.")

       print_debug("DEBUG:  Received response header = [" + p4317q_hex_format(resp_header) + "]")

       print_debug("DEBUG:  Expected response header = [" + p4317q_hex_format(RSP_HEADER) + "]")

       if (ord(resp_header[0]) != RSP_HEADER[0]):

           print_debug(str(ord(resp_header[0])) + " == " + str(RSP_HEADER[0]))

           print_debug("DEBUG:  1st byte of response header does not match " + p4317q_hex_format(RSP_HEADER))

           return None

       if (ord(resp_header[1]) != RSP_HEADER[1]):

           print_debug("DEBUG:  2nd byte of response header does not match " + p4317q_hex_format(RSP_HEADER))

           return None

       # Read 1 byte of len

       resp_len = ord(ser_port.read(1))

       print_debug("DEBUG:  Received data length of " + str(resp_len))

       # Read resp_len+1 bytes (message + checksum)

       response = ser_port.read(resp_len+1)

       return response

    def p4317q_handle_command(action, command, param):

       cmd = p4317q_build_command(action, command, param)

       print_debug("DEBUG:  Command:  [" + p4317q_hex_format(cmd) + "]")

       port = serial.Serial("/dev/cu.usbserial")

       p4317q_send_command(port, cmd)

       response = p4317q_read_response(port)

       port.close()

       if (response is not None):

           print_debug("Response = [" + p4317q_hex_format(response) + "]")

           parsedResponse = p4317q_parse_response(response, (ACTIONS_MAP[action])[command])

       if (parsedResponse is not None and action == "get"):

           format_response(command, parsedResponse, param)

    def format_response(command, response, param):

       if   (command == "assettag"):

           print ""

       elif (command == "monitorname"):

           print "Monitor Name         = " + str(response)

       elif (command == "monitorserial"):

           print "Monitor Serial #     = " + str(response)

       elif (command == "backlighthours"):

           print "Backlight Hours      = " + str(struct.unpack("

       elif (command == "powerstate"):

           print "Power State          = " + ("ON" if response[0]==1 else "OFF")

       elif (command == "powerled"):

           print "Power LED            = " + ("ON" if response[0]==1 else "OFF")

       elif (command == "powerusb"):

           print "Power USB            = " + ("ON" if response[0]==1 else "OFF")

       elif (command == "brightness"):

           print "Brightness           = " + str(response[0])

       elif (command == "contrast"):

           print "Contrast             = " + str(response[0])

       elif (command == "aspectratio"):

           ratios = { v: k for k, v in aspect_ratios.items() }

           print "Aspect Ratio         = " + ratios[response[0]]

       elif (command == "sharpness"):

           print "Sharpness            = " + str(response[0])

       elif (command == "inputcolorformat"):

           formats = { v: k for k, v in input_color_formats.items() }

           print "Input Color Format   = " + formats[response[0]]

       elif (command == "colorpresetcaps"):

           print "Color Preset Caps    = " + p4317q_hex_format(response)

       elif (command == "colorpreset"):

           print "Color Preset         = " + color_preset_inv[struct.unpack("

       elif (command == "customcolor"):

           print "Custom Color [R:G:B] = [" + str(response[0]) + ":" + str(response[1]) + ":" + str(response[2]) + "]"

       elif (command == "autoselect"):

           print "Input Auto Select    = " + ("ON" if response[0]==1 else "OFF")

       elif (command == "videoinputcaps"):

           print "Video Input Caps     = " + p4317q_hex_format(response)

       elif (command == "videoinput"):

           inputs = { v[0]: k for k, v in pxp_input.items() }

           print "Video Input          = " + inputs[int(response[0])]

       elif (command == "pxpmode"):

           modes = { v: k for k, v in pxp_mode.items() }

           print "PxP/PiP Mode         = " + modes[response[0]]

       elif (command == "pxpsubinput"):

           inputs = { v[0]: k for k, v in pxp_input.items() }

           print "PxP/PiP Sub Input[" + str(param+1) + "] = " + inputs[int(response[0])]

       elif (command == "pxplocation"):

           locations = { v: k for k, v in pxp_locations.items() }

           print "PiP Window Location  = " + locations[int(response[0])]

       elif (command == "osdtransparency"):

           print "OSD Transparency     = " + str(response[0])

       elif (command == "osdlanguage"):

           languages = { v: k for k, v in osd_language.items() }

           print "OSD Language         = " + languages[int(response[0])]

       elif (command == "osdtimer"):

           print "OSD Timer            = " + str(response[0])

       elif (command == "osdbuttonlock"):

           print "OSD Button Lock      = " + ("ON" if response[0]==1 else "OFF")

       elif (command == "versionfirmware"):

           print "Firmware Version     = " + response

       elif (command == "ddcci"):

           print "DDC/CI               = " + ("ON" if response[0]==1 else "OFF")

       elif (command == "lcdconditioning"):

           print "LCD Conditioning     = " + ("ON" if response[0]==1 else "OFF")

       return

    # MONITOR MANAGEMENT

    CMD_G_ASSET_TAG_L=0x02

    CMD_G_ASSET_TAG_C=0x00

    CMD_G_ASSET_TAG_RESP_L=0x0D

    CMD_G_MONITOR_NAME_L=0x02

    CMD_G_MONITOR_NAME_C=0x01

    CMD_G_MONITOR_NAME_RESP_L=0x0D

    CMD_G_MONITOR_SERIAL_L=0x02

    CMD_G_MONITOR_SERIAL_C=0x02

    CMD_G_MONITOR_SERIAL_RESP_L=0x0D

    CMD_G_BACKLIGHT_HOURS_L=0x02

    CMD_G_BACKLIGHT_HOURS_C=0x04

    CMD_G_BACKLIGHT_HOURS_RESP_L=0x05

    # POWER MANAGEMENT

    CMD_G_POWER_STATE_L=0x02

    CMD_G_POWER_STATE_C=0x20

    CMD_G_POWER_STATE_RESP_L=0x04

    CMD_S_POWER_STATE_L=0x03

    CMD_S_POWER_STATE_C=0x20

    CMD_G_POWER_LED_L=0x02

    CMD_G_POWER_LED_C=0x21

    CMD_G_POWER_LED_RESP_L=0x04

    CMD_S_POWER_LED_L=0x03

    CMD_S_POWER_LED_C=0x21

    CMD_G_POWER_USB_L=0x02

    CMD_G_POWER_USB_C=0x22

    CMD_G_POWER_USB_RESP_L=0x04

    CMD_S_POWER_USB_L=0x03

    CMD_S_POWER_USB_C=0x22

    CMD_RESET_POWER_L=0x02

    CMD_RESET_POWER_C=0x2F

    # IMAGE ADJUSTMENT

    CMD_G_BRIGHTNESS_L=0x02

    CMD_G_BRIGHTNESS_C=0x30

    CMD_G_BRIGHTNESS_RESP_L=0x04

    CMD_S_BRIGHTNESS_L=0x03

    CMD_S_BRIGHTNESS_C=0x30

    CMD_G_CONTRAST_L=0x02

    CMD_G_CONTRAST_C=0x31

    CMD_G_CONTRAST_RESP_L=0x04

    CMD_S_CONTRAST_L=0x03

    CMD_S_CONTRAST_C=0x31

    CMD_G_ASPECT_RATIO_L=0x02

    CMD_G_ASPECT_RATIO_C=0x33

    CMD_G_ASPECT_RATIO_RESP_L=0x04

    CMD_S_ASPECT_RATIO_L=0x03

    CMD_S_ASPECT_RATIO_C=0x33

    CMD_G_SHARPNESS_L=0x02

    CMD_G_SHARPNESS_C=0x34

    CMD_G_SHARPNESS_RESP_L=0x04

    CMD_S_SHARPNESS_L=0x03

    CMD_S_SHARPNESS_C=0x34

    aspect_ratios = { "16x9": 0,

                     "4x3":  2,

                     "5x4":  4 }

    # COLOR MANAGEMENT

    CMD_G_INPUT_COLOR_FORMAT_L=0x02

    CMD_G_INPUT_COLOR_FORMAT_C=0x46

    CMD_G_INPUT_COLOR_FORMAT_RESP_L=0x04

    CMD_S_INPUT_COLOR_FORMAT_L=0x03

    CMD_S_INPUT_COLOR_FORMAT_C=0x46

    CMD_G_COLOR_PRESET_CAPS_L=0x02

    CMD_G_COLOR_PRESET_CAPS_C=0x47

    CMD_G_COLOR_PRESET_CAPS_RESP_L=0x07

    CMD_G_COLOR_PRESET_L=0x02

    CMD_G_COLOR_PRESET_C=0x48

    CMD_G_COLOR_PRESET_RESP_L=0x07

    CMD_S_COLOR_PRESET_L=0x06

    CMD_S_COLOR_PRESET_C=0x48

    CMD_G_CUSTOM_COLOR_L=0x03

    CMD_G_CUSTOM_RESP_L=0x09

    CMD_G_CUSTOM_COLOR_C=0x49

    CMD_G_CUSTOM_COLOR_RESP_L=0x09

    CMD_S_CUSTOM_COLOR_L=0x09

    CMD_S_CUSTOM_COLOR_C=0x49

    CMD_RESET_COLOR_L=0x02

    CMD_RESET_COLOR_C=0x4F

    input_color_formats = { "RGB": 0,

                           "YPbPr": 1 }

    color_presets = { "standard": bytearray([0x01, 0x00, 0x00, 0x00]),

                     "paper":    bytearray([0x10, 0x00, 0x00, 0x00]),

                     "warm":     bytearray([0x00, 0x01, 0x00, 0x00]),

                     "cool":     bytearray([0x00, 0x02, 0x00, 0x00]),

                     "custom":   bytearray([0x80, 0x00, 0x00, 0x00]) }

    color_preset_inv = { struct.unpack("

                        struct.unpack("

                        struct.unpack("

                        struct.unpack("

                        struct.unpack("

    # VIDEO INPUT MANAGEMENT

    CMD_G_AUTO_SELECT_L=0x02

    CMD_G_AUTO_SELECT_C=0x60

    CMD_G_AUTO_SELECT_RESP_L=0x04

    CMD_S_AUTO_SELECT_L=0x03

    CMD_S_AUTO_SELECT_C=0x60

    CMD_G_VIDEO_INPUT_CAPS_L=0x02

    CMD_G_VIDEO_INPUT_CAPS_C=0x61

    CMD_G_VIDEO_INPUT_CAPS_RESP_L=0x07

    CMD_G_VIDEO_INPUT_L=0x02

    CMD_G_VIDEO_INPUT_C=0x62

    CMD_G_VIDEO_INPUT_RESP_L=0x07

    CMD_S_VIDEO_INPUT_L=0x06

    CMD_S_VIDEO_INPUT_C=0x62

    # PIP/PBP MANAGEMENT

    CMD_G_PXP_MODE_L=0x02

    CMD_G_PXP_MODE_C=0x70

    CMD_G_PXP_MODE_RESP_L=0x04

    CMD_S_PXP_MODE_L=0x03

    CMD_S_PXP_MODE_C=0x70

    CMD_G_PXP_SUBINPUT_L=0x03

    CMD_G_PXP_SUBINPUT_C=0x71

    CMD_G_PXP_SUBINPUT_RESP_L=0x07

    CMD_S_PXP_SUBINPUT_L=0x06

    CMD_S_PXP_SUBINPUT_C=0x71

    CMD_G_PXP_LOCATION_L=0x02

    CMD_G_PXP_LOCATION_C=0x72

    CMD_G_PXP_LOCATION_RESP_L=0x04

    CMD_S_PXP_LOCATION_L=0x03

    CMD_S_PXP_LOCATION_C=0x72

    pxp_mode = { "4k": 0,

                "smallPip": 1,

                "bigPip": 2,

                "SxS": 3,

                "stretchSxS": 4,

                "2x1": 6,

                "1x2": 7,

                "4x4": 8 }

    pxp_input = { "vga":   bytearray([0x40, 0x00, 0x00, 0x00]),

                 "dp":    bytearray([0x08, 0x00, 0x00, 0x00]),

                 "mdp":   bytearray([0x10, 0x00, 0x00, 0x00]),

                 "hdmi1": bytearray([0x01, 0x00, 0x00, 0x00]),

                 "hdmi2": bytearray([0x02, 0x00, 0x00, 0x00]) }

    pxp_locations = { "topRight": 0,

                     "topLeft": 1,

                     "bottomRight": 2,

                     "bottomLeft": 3 }

    # PxP Locations (PiP Location)

    # 0 - Top Right

    # 1 - Top Left

    # 2 - Bottom Right

    # 3 - Bottom Left

    # OSD MANAGEMENT

    CMD_S_OSD_TRANSPARENCY_L=0x03

    CMD_S_OSD_TRANSPARENCY_C=0x80

    CMD_G_OSD_TRANSPARENCY_L=0x02

    CMD_G_OSD_TRANSPARENCY_C=0x80

    CMD_G_OSD_TRANSPARENCY_RESP_L=0x04

    CMD_S_OSD_LANGUAGE_L=0x03

    CMD_S_OSD_LANGUAGE_C=0x81

    CMD_G_OSD_LANGUAGE_L=0x02

    CMD_G_OSD_LANGUAGE_C=0x81

    CMD_G_OSD_LANGUAGE_RESP_L=0x04

    CMD_S_OSD_TIMER_L=0x03

    CMD_S_OSD_TIMER_C=0x83

    CMD_G_OSD_TIMER_L=0x02

    CMD_G_OSD_TIMER_C=0x83

    CMD_G_OSD_TIMER_RESP_L=0x04

    CMD_S_OSD_BUTTON_LOCK_L=0x03

    CMD_S_OSD_BUTTON_LOCK_C=0x84

    CMD_G_OSD_BUTTON_LOCK_L=0x02

    CMD_G_OSD_BUTTON_LOCK_C=0x84

    CMD_G_OSD_BUTTON_LOCK_RESP_L=0x04

    CMD_RESET_OSD_L=0x02

    CMD_RESET_OSD_C=0x8F

    osd_language = { "english": 0,

                    "spanish": 1,

                    "french": 2,

                    "german": 3,

                    "portugese": 4,

                    "russian": 5,

                    "chinese": 6,

                    "japanese": 7 }

    # OSD Languages

    # 0 - English

    # 1 - Spanish

    # 2 - French

    # 3 - German

    # 4 - Portugese

    # 5 - Russian

    # 6 - Chinese ?

    # 7 - Japanese ?

    # SYSTEM MANAGEMENT

    CMD_G_VERSION_FIRMWARE_L=0x02

    CMD_G_VERSION_FIRMWARE_C=0xA0

    CMD_G_VERSION_FIRMWARE_RESP_L=0x05

    CMD_G_DDCCI_L=0x02

    CMD_G_DDCCI_C=0xA2

    CMD_G_DDCCI_RESP_L=0x04

    CMD_S_DDCCI_L=0x03

    CMD_S_DDCCI_C=0xA2

    CMD_G_LCD_CONDITIONING_L=0x02

    CMD_G_LCD_CONDITIONING_C=0xA3

    CMD_G_LCD_CONDITIONING_RESP_L=0x04

    CMD_S_LCD_CONDITIONING_L=0x03

    CMD_S_LCD_CONDITIONING_C=0xA3

    CMD_FACTORY_RESET_L=0x02

    CMD_FACTORY_RESET_C=0xAF

    GET_ACTIONS = {

       "assettag": CMD_G_ASSET_TAG_C                  , "assettag_len": CMD_G_ASSET_TAG_L,

       "assettag_resplen": CMD_G_ASSET_TAG_RESP_L,

       "monitorname": CMD_G_MONITOR_NAME_C            , "monitorname_len": CMD_G_MONITOR_NAME_L,

       "monitorname_resplen": CMD_G_MONITOR_NAME_RESP_L,

       "monitorserial": CMD_G_MONITOR_SERIAL_C        , "monitorserial_len": CMD_G_MONITOR_SERIAL_L,

       "monitorserial_resplen": CMD_G_MONITOR_SERIAL_RESP_L,

       "backlighthours": CMD_G_BACKLIGHT_HOURS_C      , "backlighthours_len": CMD_G_BACKLIGHT_HOURS_L,

       "backlighthours_resplen": CMD_G_BACKLIGHT_HOURS_RESP_L,

       "powerstate": CMD_G_POWER_STATE_C              , "powerstate_len": CMD_G_POWER_STATE_L,

       "powerstate_resplen": CMD_G_POWER_STATE_RESP_L,

       "powerled": CMD_G_POWER_LED_C                  , "powerled_len": CMD_G_POWER_LED_L,

       "powerled_resplen": CMD_G_POWER_LED_RESP_L,

       "powerusb": CMD_G_POWER_USB_C                  , "powerusb_len": CMD_G_POWER_USB_L,

       "powerusb_resplen": CMD_G_POWER_USB_RESP_L,

       "brightness": CMD_G_BRIGHTNESS_C               , "brightness_len": CMD_G_BRIGHTNESS_L,

       "brightness_resplen": CMD_G_BRIGHTNESS_RESP_L,

       "contrast": CMD_G_CONTRAST_C                   , "contrast_len": CMD_G_CONTRAST_L,

       "contrast_resplen": CMD_G_CONTRAST_RESP_L,

       "aspectratio": CMD_G_ASPECT_RATIO_C            , "aspectratio_len": CMD_G_ASPECT_RATIO_L,

       "aspectratio_resplen": CMD_G_ASPECT_RATIO_RESP_L,

       "sharpness": CMD_G_SHARPNESS_C                 , "sharpness_len": CMD_G_SHARPNESS_L,

       "sharpness_resplen": CMD_G_SHARPNESS_RESP_L,

       "inputcolorformat": CMD_G_INPUT_COLOR_FORMAT_C , "inputcolorformat_len": CMD_G_INPUT_COLOR_FORMAT_L,

       "inputcolorformat_resplen": CMD_G_INPUT_COLOR_FORMAT_RESP_L,

       "colorpresetcaps": CMD_G_COLOR_PRESET_CAPS_C   , "colorpresetcaps_len": CMD_G_COLOR_PRESET_CAPS_L,

       "colorpresetcaps_resplen": CMD_G_COLOR_PRESET_CAPS_RESP_L,

       "colorpreset": CMD_G_COLOR_PRESET_C            , "colorpreset_len": CMD_G_COLOR_PRESET_L,

       "colorpreset_resplen": CMD_G_COLOR_PRESET_RESP_L,

       "customcolor": CMD_G_CUSTOM_COLOR_C            , "customcolor_len": CMD_G_CUSTOM_COLOR_L,

       "customcolor_resplen": CMD_G_CUSTOM_COLOR_RESP_L,

       "autoselect": CMD_G_AUTO_SELECT_C              , "autoselect_len": CMD_G_AUTO_SELECT_L,

       "autoselect_resplen": CMD_G_AUTO_SELECT_RESP_L,

       "videoinputcaps": CMD_G_VIDEO_INPUT_CAPS_C     , "videoinputcaps_len": CMD_G_VIDEO_INPUT_CAPS_L,

       "videoinputcaps_resplen": CMD_G_VIDEO_INPUT_CAPS_RESP_L,

       "videoinput": CMD_G_VIDEO_INPUT_C              , "videoinput_len": CMD_G_VIDEO_INPUT_L,

       "videoinput_resplen": CMD_G_VIDEO_INPUT_RESP_L,

       "pxpmode": CMD_G_PXP_MODE_C                    , "pxpmode_len": CMD_G_PXP_MODE_L,

       "pxpmode_resplen": CMD_G_PXP_MODE_RESP_L,

       "pxpsubinput": CMD_G_PXP_SUBINPUT_C            , "pxpsubinput_len": CMD_G_PXP_SUBINPUT_L,

       "pxpsubinput_resplen": CMD_G_PXP_SUBINPUT_RESP_L,

       "pxplocation": CMD_G_PXP_LOCATION_C            , "pxplocation_len": CMD_G_PXP_LOCATION_L,

       "pxplocation_resplen": CMD_G_PXP_LOCATION_RESP_L,

       "osdtransparency": CMD_G_OSD_TRANSPARENCY_C    , "osdtransparency_len": CMD_G_OSD_TRANSPARENCY_L,

       "osdtransparency_resplen": CMD_G_OSD_TRANSPARENCY_RESP_L,

       "osdlanguage": CMD_G_OSD_LANGUAGE_C            , "osdlanguage_len": CMD_G_OSD_LANGUAGE_L,

       "osdlanguage_resplen": CMD_G_OSD_LANGUAGE_RESP_L,

       "osdtimer": CMD_G_OSD_TIMER_C                  , "osdtimer_len": CMD_G_OSD_TIMER_L,

       "osdtimer_resplen": CMD_G_OSD_TIMER_RESP_L,

       "osdbuttonlock": CMD_G_OSD_BUTTON_LOCK_C       , "osdbuttonlock_len": CMD_G_OSD_BUTTON_LOCK_L,

       "osdbuttonlock_resplen": CMD_G_OSD_BUTTON_LOCK_RESP_L,

       "versionfirmware": CMD_G_VERSION_FIRMWARE_C    , "versionfirmware_len": CMD_G_VERSION_FIRMWARE_L,

       "versionfirmware_resplen": CMD_G_VERSION_FIRMWARE_RESP_L,

       "ddcci": CMD_G_DDCCI_C                         , "ddcci_len": CMD_G_DDCCI_L,

       "ddcci_resplen": CMD_G_DDCCI_RESP_L,

       "lcdconditioning": CMD_G_LCD_CONDITIONING_C    , "lcdconditioning_len": CMD_G_LCD_CONDITIONING_L,

       "lcdconditioning_resplen": CMD_G_LCD_CONDITIONING_RESP_L

    }

    SET_ACTIONS = {

       "powerstate": CMD_S_POWER_STATE_C              , "powerstate_len": CMD_S_POWER_STATE_L,

       "powerled": CMD_S_POWER_LED_C                  , "powerled_len": CMD_S_POWER_LED_L,

       "powerusb": CMD_S_POWER_USB_C                  , "powerusb_len": CMD_S_POWER_USB_L,

       "brightness": CMD_S_BRIGHTNESS_C               , "brightness_len": CMD_S_BRIGHTNESS_L,

       "contrast": CMD_S_CONTRAST_C                   , "contrast_len": CMD_S_CONTRAST_L,

       "aspectratio": CMD_S_ASPECT_RATIO_C            , "aspectratio_len": CMD_S_ASPECT_RATIO_L,

       "sharpness": CMD_S_SHARPNESS_C                 , "sharpness_len": CMD_S_SHARPNESS_L,

       "inputcolorformat": CMD_S_INPUT_COLOR_FORMAT_C , "inputcolorformat_len": CMD_S_INPUT_COLOR_FORMAT_L,

       "colorpreset": CMD_S_COLOR_PRESET_C            , "colorpreset_len": CMD_S_COLOR_PRESET_L,

       "customcolor": CMD_S_CUSTOM_COLOR_C            , "customcolor_len": CMD_S_CUSTOM_COLOR_L,

       "autoselect": CMD_S_AUTO_SELECT_C              , "autoselect_len": CMD_S_AUTO_SELECT_L,

       "videoinput": CMD_S_VIDEO_INPUT_C              , "videoinput_len": CMD_S_VIDEO_INPUT_L,

       "pxpmode": CMD_S_PXP_MODE_C                    , "pxpmode_len": CMD_S_PXP_MODE_L,

       "pxpsubinput": CMD_S_PXP_SUBINPUT_C            , "pxpsubinput_len": CMD_S_PXP_SUBINPUT_L,

       "pxplocation": CMD_S_PXP_LOCATION_C            , "pxplocation_len": CMD_S_PXP_LOCATION_L,

       "osdtransparency": CMD_S_OSD_TRANSPARENCY_C    , "osdtransparency_len": CMD_S_OSD_TRANSPARENCY_L,

       "osdlanguage": CMD_S_OSD_LANGUAGE_C            , "osdlanguage_len": CMD_S_OSD_LANGUAGE_L,

       "osdtimer": CMD_S_OSD_TIMER_C                  , "osdtimer_len": CMD_S_OSD_TIMER_L,

       "osdbuttonlock": CMD_S_OSD_BUTTON_LOCK_C       , "osdbuttonlock_len": CMD_S_OSD_BUTTON_LOCK_L,

       "ddcci": CMD_S_DDCCI_C                         , "ddcci_len": CMD_S_DDCCI_L,

       "lcdconditioning": CMD_S_LCD_CONDITIONING_C    , "lcdconditioning_len": CMD_S_LCD_CONDITIONING_L

    }

    RESET_ACTIONS = {

       "power": CMD_RESET_POWER_C                     , "power_len": CMD_RESET_POWER_L,

       "color": CMD_RESET_COLOR_C                     , "color_len": CMD_RESET_COLOR_L,

       "osd": CMD_RESET_OSD_C                         , "osd_len": CMD_RESET_OSD_L,

       "factory": CMD_FACTORY_RESET_C                 , "factory_len": CMD_FACTORY_RESET_L

    }

    ACTIONS_MAP = { "get": GET_ACTIONS, "set": SET_ACTIONS, "reset": RESET_ACTIONS }

    print_debug("len(sys.argv) = " + str(len(sys.argv)))

    print_debug("args = " + str(sys.argv))

    if (len(sys.argv) < 2 or len(sys.argv) > 5):

       print_usage()

       exit()

    if (sys.argv[1] == "dump"):

       dump_info()

       exit()

    if (sys.argv[1] in ("get", "set", "reset")):

       keys = ACTIONS_MAP[sys.argv[1]].keys()

       if (sys.argv[2] not in keys):

           print "ERROR:  Invalid command specified"

           exit()

    else:

       print "ERROR:  Invalid action specified"

       exit()

    param = None

    if (len(sys.argv) >= 4):

       if (sys.argv[1] == "set"):

           if   (sys.argv[2] == "osdlanguage"):

               param = osd_language[sys.argv[3]]

           elif (sys.argv[2] == "pxplocation"):

               param = pxp_locations[sys.argv[3]]

           elif (sys.argv[2] == "pxpmode"):

               param = pxp_mode[sys.argv[3]]

           elif (sys.argv[2] == "videoinput"):

               param = pxp_input[sys.argv[3]]

           elif (sys.argv[2] == "pxpsubinput"):

               print "pxpsubinput"

               param = bytearray([int(sys.argv[3])-1])

               param += pxp_input[sys.argv[4]]

               print "param:  " + p4317q_hex_format(param)

           else:

               param = int(sys.argv[3])

       else:

           param = int(sys.argv[3])

    output = p4317q_handle_command(sys.argv[1], sys.argv[2], param)

  • kevinf28

    5 Posts

    2064

    0

    Posted April 12th, 2017 10:00

    Thanks sredniv but please post long code fragments on gist or pastebin. Specially with Python's strict indentation rules. I look forward to trying your script.

    Really, we need to push Dell for updated Reference guide based off 104 firmware. Evidently the current guide is already years old.