Advertisement
kevinf28

Dell P4317Q Windows Script

Sep 6th, 2017
344
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.72 KB | None | 0 0
  1. #!/usr/bin/python
  2. # Requires Dell P4317Q monitor at firmware M2C104, tested with Python2.7
  3. # Special thanks to sredniv for inspiration to port my Bash scripts to Python
  4. # http://en.community.dell.com/support-forums/peripherals/f/3529/t/19995591
  5. # API reference guide
  6. # http://downloads.dell.com/manuals/all-products/esuprt_display_projector/esuprt_display/dell-p4317q-monitor_Reference%20Guide2_en-us.pdf
  7. # Examples
  8. # http://downloads.dell.com/manuals/all-products/esuprt_display_projector/esuprt_display/dell-p4317q-monitor_Reference%20Guide3_en-us.pdf
  9. # Thanks to the helpful folks at https://hardforum.com/threads/dell-43-ultra-hd-4k-multi-client-monitor-p4317q.1897889/
  10.  
  11. # Send: [H0][H1][Len][R/W][Cmd][Data0]...[DataN][CHK]
  12. # turn off LED: 375103ea2100ae
  13. # turn on LED: 375103ea2101af
  14. # Checksum using SpeedCrunch: xor(0x37;0x51;0x03;0xea;0x21;01) = 0xAF
  15. # using console calc: 0x37@0x51@0x03@0xea@0x21@0x01
  16.  
  17. # Receive: [H2][H3][Len][Reply][RC][Cmd][Data0]...[DataN][CHK]
  18. # GetPxPSubInput valid: 6f 37 07 02 00 71 10 00 00 00 64
  19. # GetPxPSubInput error: 6f 37 03 02 ff 71 8f
  20.  
  21. import sys
  22. from binascii import b2a_hex
  23. from time import sleep
  24. import subprocess
  25.  
  26. # 3rd party
  27. import serial
  28.  
  29. CMD_HEADER = bytearray([0x37, 0x51])
  30. RSP_HEADER = bytearray([0x6F, 0x37])
  31. CMD_READ = 0xEB
  32. CMD_WRITE = 0xEA
  33. COM_PORT = "com1"
  34.  
  35. CMD_LED_OFF = bytearray([0x37, 0x51, 0x03, 0xEA, 0x21, 0x00, 0xAE])
  36. CMD_LED_ON = bytearray([0x37, 0x51, 0x03, 0xEA, 0x21, 0x01, 0xAF])
  37. CMD_PBP_OFF = bytearray([0x37, 0x51, 0x03, 0xEA, 0x70, 0x00, 0xFF])
  38. CMD_PBP_QUAD = bytearray([0x37, 0x51, 0x03, 0xEA, 0x70, 0x08, 0xF7])
  39. CMD_AUTOSEL_OFF = bytearray([0x37, 0x51, 0x03, 0xEA, 0x60, 0x00, 0xEF])
  40. CMD_WARM_MODE = bytearray([0x37, 0x51, 0x06, 0xEA, 0x48, 0x00, 0x01, 0x00, 0x00, 0xC3])
  41. CMD_MDP_PRIMARY = bytearray([0x37, 0x51, 0x06, 0xEA, 0x62, 0x10, 0x00, 0x00, 0x00, 0xF8])
  42. CMD_DP_PRIMARY = bytearray([0x37, 0x51, 0x06, 0xEA, 0x62, 0x08, 0x00, 0x00, 0x00, 0xE0])
  43. CMD_HD2_PRIMARY = bytearray([0x37, 0x51, 0x06, 0xEA, 0x62, 0x02, 0x00, 0x00, 0x00, 0xEA])
  44. CMD_PBP_HD2_BR = bytearray([0x37, 0x51, 0x07, 0xEA, 0x71, 0x00, 0x02, 0x00, 0x00, 0x00, 0xF8])
  45. CMD_PBP_MDP_BL = bytearray([0x37, 0x51, 0x07, 0xEA, 0x71, 0x01, 0x10, 0x00, 0x00, 0x00, 0xEB])
  46. CMD_PBP_DP_BL = bytearray([0x37, 0x51, 0x07, 0xEA, 0x71, 0x01, 0x08, 0x00, 0x00, 0x00, 0xF3])
  47. CMD_PBP_DP_TL = bytearray([0x37, 0x51, 0x07, 0xEA, 0x71, 0x02, 0x08, 0x00, 0x00, 0x00, 0xF0])
  48. CMD_PBP_HD1_TL = bytearray([0x37, 0x51, 0x07, 0xEA, 0x71, 0x02, 0x01, 0x00, 0x00, 0x00, 0xF9])
  49. CMD_PBP_HD1_TR = bytearray([0x37, 0x51, 0x07, 0xEA, 0x71, 0x03, 0x01, 0x00, 0x00, 0x00, 0xF8])
  50. CMD_PBP_MDP_TR = bytearray([0x37, 0x51, 0x07, 0xEA, 0x71, 0x03, 0x10, 0x00, 0x00, 0x00, 0xE9])
  51.  
  52. COMMANDS_WORKSTATION = [CMD_LED_OFF, CMD_AUTOSEL_OFF, CMD_PBP_OFF, CMD_DP_PRIMARY, CMD_WARM_MODE, CMD_LED_ON]
  53. COMMANDS_RYZEN = [CMD_LED_OFF, CMD_AUTOSEL_OFF, CMD_PBP_OFF, CMD_HD2_PRIMARY, CMD_WARM_MODE, CMD_LED_ON]
  54. COMMANDS_QUAD = [CMD_LED_OFF, CMD_AUTOSEL_OFF, CMD_PBP_QUAD, CMD_PBP_HD1_TL, CMD_PBP_MDP_TR, CMD_PBP_DP_BL, CMD_PBP_HD2_BR, CMD_WARM_MODE, CMD_LED_ON]
  55.  
  56. def hex_format(message):
  57.     hex = b2a_hex(message)
  58.     return ':'.join(hex[i:i+2] for i in range(0, len(hex), 2))
  59.  
  60. if __name__ == "__main__":
  61.  
  62.     if len(sys.argv) != 2 or sys.argv[1] not in ["QUAD", "WORK", "RYZEN"]:
  63.         print("Usage: QUAD|4K")
  64.         exit(1)
  65.  
  66.     ser_port = serial.Serial(COM_PORT)
  67.     if (sys.argv[1] == "WORK"):
  68.         commands = COMMANDS_WORKSTATION
  69.     elif (sys.argv[1] == "RYZEN"):
  70.         commands = COMMANDS_RYZEN
  71.     elif (sys.argv[1] == "QUAD"):
  72.         commands = COMMANDS_QUAD
  73.  
  74.     for cmd in commands:
  75.         ser_port.write(cmd)
  76.  
  77.         resp_header = ser_port.read(2)
  78.         if ord(resp_header[0]) != RSP_HEADER[0] or ord(resp_header[1]) != RSP_HEADER[1]:
  79.             print("ERROR: Response is corrupt, aborting")
  80.             exit(1)
  81.  
  82.         resp_len = ord(ser_port.read(1))
  83.  
  84.         ord(ser_port.read(1)) # always 02 (reply)
  85.  
  86.         resp_code = ord(ser_port.read(1))
  87.         if resp_code != 0:
  88.             print("Response error: %d" % resp_code)
  89.  
  90.         # resp_len excludes checksum and we already read reply / code (-2)
  91.         response = ser_port.read(resp_len - 2)
  92.         checksum = ser_port.read(1)
  93.         print("Response data: %s, checksum: %s" % (hex_format(response), hex_format(checksum)))
  94.  
  95.         sleep(1)
  96.  
  97.     # give time for display to settle
  98.     sleep(2)
  99.  
  100.     # set appropriate resolution
  101.     if (sys.argv[1] == "WORK"):
  102.         # note the escaped backslashes
  103.         # before SLS setup
  104.         # subprocess.call("dc64cmd.exe -monitor=\\\\.\\DISPLAY2 -detach")
  105.         pass
  106.         # SLS does not allow resolution 4k
  107.         # subprocess.call("dc64cmd.exe -monitor=\\\\.\\DISPLAY1 -width=3840 -height=2160 -refresh=max -depth=max -primary")
  108.     elif (sys.argv[1] == "RYZEN"):
  109.         pass
  110.         #subprocess.call("PsExec64 \\\\ryzen -u user -p \"\" -n 5 -c -f -accepteula -nobanner C:\\Users\\user\\Documents\\scripts\\dc64cmd.exe -monitor=\\\\.\\DISPLAY1 -width=3840 -height=2160 -refresh=max -depth=max -primary")
  111.     elif (sys.argv[1] == "QUAD"):
  112.         # before SLS setup
  113.         #subprocess.call("dc64cmd.exe -monitor=\\\\.\\DISPLAY1 -width=1920 -height=1080 -refresh=max -depth=max -primary -more")
  114.         #subprocess.call("dc64cmd.exe -monitor=\\\\.\\DISPLAY2 -width=1920 -height=1080 -refresh=max -depth=max -seconday -above -apply")
  115.         subprocess.call("dc64cmd.exe -monitor=\\\\.\\DISPLAY1 -width=1920 -height=2160 -refresh=max -depth=max -primary")
  116.         #subprocess.call("PsExec64 \\\\ryzen -u user -p \"\" -n 5 -c -f -accepteula -nobanner C:\\Users\\user\\Documents\\scripts\\dc64cmd.exe -monitor=\\\\.\\DISPLAY1 -width=1920 -height=1080 -refresh=max -depth=max -primary")
  117.  
  118.     ser_port.close()
  119.  
  120.     sleep(20)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement