summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlibdlo <libdlo@displaylink.com>2009-05-29 09:15:45 -0700
committerlibdlo <libdlo@displaylink.com>2009-05-29 09:15:45 -0700
commitf5673eb2765d72718b961ae76899e37932a89fe0 (patch)
tree88e54be831506710164ffbab737a33cf3c022590
parent1c47e4dbe05ea5b2a153b1c584a6ac23b50d7218 (diff)
Clean up those pesky newlines to ease patching, etc.
-rw-r--r--src/dlo_base.h114
-rw-r--r--src/dlo_data.h1414
-rw-r--r--src/dlo_defs.h316
-rw-r--r--src/dlo_grfx.c1686
-rw-r--r--src/dlo_grfx.h186
-rw-r--r--src/dlo_mode.c1852
-rw-r--r--src/dlo_mode.h254
-rw-r--r--src/dlo_structs.h184
-rw-r--r--src/dlo_usb.c1122
-rw-r--r--src/dlo_usb.h268
-rw-r--r--src/exported_symbols28
-rw-r--r--src/libdlo.c1786
-rw-r--r--src/libdlo.h1500
13 files changed, 5355 insertions, 5355 deletions
diff --git a/src/dlo_base.h b/src/dlo_base.h
index 3ce2ba4..c515ec0 100644
--- a/src/dlo_base.h
+++ b/src/dlo_base.h
@@ -1,57 +1,57 @@
-/** @file dlo_base.h
- *
- * @brief Global header file for the core functions of libdlo.
- *
- * This file defines anything which is not a part of the API that libdlo publishes
- * up to software using the library (in libdlo.h). It is intended that any functions,
- * variables and structures defined herein are only for internal use by the libdlo
- * sources.
- *
- * DisplayLink Open Source Software (libdlo)
- * Copyright (C) 2009, DisplayLink
- * www.displaylink.com
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Library General Public License as published by the Free
- * Software Foundation; LGPL version 2, dated June 1991.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef DLO_BASE_H
-#define DLO_BASE_H /**< Avoid multiple inclusion. */
-
-#include "dlo_structs.h"
-
-
-/** Claim and initialise a new device structure.
- *
- * @param type Device type.
- * @param serial Pointer to serial number string for the device (assumed to be unique to each device).
- *
- * @return Pointer to new @a dlo_device_t structure or NULL if failed.
- */
-extern dlo_device_t *dlo_new_device(const dlo_devtype_t type, const char * const serial);
-
-
-/** Given a unique ID for a device, see if we have it in our device list @a dev_list.
- *
- * @param serial Pointer to serial number string for the device (assumed to be unique to each device).
- *
- * @return Pointer to @a dlo_device_t structure or NULL if not in @a dev_list.
- *
- * A side-effect of this call is to update the @a dev->check variable to the current value
- * of @a check_state so that any devices on @a dev_list which weren't added or looked-up by
- * the end of an enumeration call can be spotted.
- */
-extern dlo_device_t *dlo_device_lookup(const char * const serial);
-
-
-#endif
+/** @file dlo_base.h
+ *
+ * @brief Global header file for the core functions of libdlo.
+ *
+ * This file defines anything which is not a part of the API that libdlo publishes
+ * up to software using the library (in libdlo.h). It is intended that any functions,
+ * variables and structures defined herein are only for internal use by the libdlo
+ * sources.
+ *
+ * DisplayLink Open Source Software (libdlo)
+ * Copyright (C) 2009, DisplayLink
+ * www.displaylink.com
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by the Free
+ * Software Foundation; LGPL version 2, dated June 1991.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef DLO_BASE_H
+#define DLO_BASE_H /**< Avoid multiple inclusion. */
+
+#include "dlo_structs.h"
+
+
+/** Claim and initialise a new device structure.
+ *
+ * @param type Device type.
+ * @param serial Pointer to serial number string for the device (assumed to be unique to each device).
+ *
+ * @return Pointer to new @a dlo_device_t structure or NULL if failed.
+ */
+extern dlo_device_t *dlo_new_device(const dlo_devtype_t type, const char * const serial);
+
+
+/** Given a unique ID for a device, see if we have it in our device list @a dev_list.
+ *
+ * @param serial Pointer to serial number string for the device (assumed to be unique to each device).
+ *
+ * @return Pointer to @a dlo_device_t structure or NULL if not in @a dev_list.
+ *
+ * A side-effect of this call is to update the @a dev->check variable to the current value
+ * of @a check_state so that any devices on @a dev_list which weren't added or looked-up by
+ * the end of an enumeration call can be spotted.
+ */
+extern dlo_device_t *dlo_device_lookup(const char * const serial);
+
+
+#endif
diff --git a/src/dlo_data.h b/src/dlo_data.h
index dd7fa90..231e847 100644
--- a/src/dlo_data.h
+++ b/src/dlo_data.h
@@ -1,707 +1,707 @@
-/** @file dlo_data.h
- *
- * @brief Hard-wired screen mode-related data blocks.
- *
- * DisplayLink Open Source Software (libdlo)
- * Copyright (C) 2009, DisplayLink
- * www.displaylink.com
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Library General Public License as published by the Free
- * Software Foundation; LGPL version 2, dated June 1991.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef DLO_DLODATA_H
-#define DLO_DLODATA_H /**< Avoid multiple inclusion. */
-
-
-/** Screen mode 640x480 (at 60 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_640_480_60_24_0 "" \
- "\x79\x7C\xAD\x97\xAD\xFE\x4B\xDE\x1A\x2F\xA2\x94\x2C\xD5\xD3\x5C"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_640_480_60_24_0 "" \
- "\xE5\xDF\xC0\x52\x4F\xE1\xE6\xB4\xE3\xED\xC4\x21\x5E\x56\xC2\x53" \
- "\x35\x1C\xE8\xF2\xDF\xEF\x7F\x37\xF5\xA5\x4B\x56\xEB\xED\x34\x7B" \
- "\xFB\x89\xA3\x17\xE4\x69\xFF\x39\xD2\xAE\x09\xB6\xC0\xBE\x4D\xBC" \
- "\x84\x6D\x99\xDA\x6B\x28\xBD\xE1\x0E\xC2\xDD\xB0\xDB\x63\xAE\x27" \
- "\x17\x9C\xD6\xD8\xCC\xC5\x44\xFD\x1C\xEF\x49\x9B\xE8\x69\x69\xCA" \
- "\xA5\x9E\xC5\x6B\xF9\x71\xC1\x1B\x8F\x8C\x41\x6B\xC4\xBE\x2A\x6F" \
- "\x56\x82\x37\xC8\x83\x92\x27\x20\x08\x62\x76\x24\x41\xEE\x38\x33" \
- "\x20\x5C\xAA\xA7\x04\x95\xFA\x8F\xE9\xBA\xEE\xD4\x6C\x8F\x82\x42" \
- "\x4E\x0F\xB3\xFC\x5D\x25\x9D\x33\xB4\x6F\xBF\x54\xB7\xEB\x16\xF3" \
- "\xE9\x7C"
-
-/** Screen mode 640x480 (at 73 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_640_480_73_24_0 "" \
- "\xA7\xA6\x78\x54\xA4\xC3\x33\xBF\xF3\xD5\x53\x1F\xAA\x27\x7B\x91"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_640_480_73_24_0 "" \
- "\x61\x1A\x38\x7B\x68\x45\x20\x90\x34\x5D\x1D\x6C\x9D\xC4\xA6\x0E" \
- "\xA3\xEA\x7F\xD9\x70\xAD\xE5\x53\xBE\xB4\x0B\xEC\xB5\xE4\xA1\xAC" \
- "\x5D\x7D\x06\x9A\x97\xE8\x3D\xFC\x7E\x81\x02\x07\xB1\x30\xC1\xAB" \
- "\x9C\xC3\x08\xEA\x79\xAA\xBD\x8F\xC1\x2B\xAA\x69\xD5\x17\xF3\x60" \
- "\x3B\x9F\x86\x86\x2C\x88\x02\x3F\x60\xF4\xA9\xFC\xD6\x8D\x41\x2E" \
- "\xDE\x64\x6F\xA2\x1F\x33\xB2\x76\x95\xF9\x89\xCC\x71\xEC\x00\x5E" \
- "\xFC\x9F\xC6\x32\xE3\xAB\x8D\xCA\xC6\x3D\xC9\x4E\xD2\xD5\x83\x7B" \
- "\x2F\x0C\x78\xE7\x3E\xE3\xEE\xD6\xCB\x95\x54\x02\x83\x46\x01\x78" \
- "\x1B\x33\xF7\x12\x47\x16\x05\xAF\x99\x56\x87\xF9\xFA\x3F\x93\x0C" \
- "\x79\xA6"
-
-/** Screen mode 640x480 (at 75 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_640_480_75_24_0 "" \
- "\xBC\xD1\x26\x61\x95\x59\x20\x88\x2E\x73\xA7\xD9\x9A\x22\x6A\xFB"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_640_480_75_24_0 "" \
- "\xAA\xCE\xFB\xD4\xC3\x07\xC1\xBF\xAD\xA3\xEF\xA9\x2B\x77\xBD\x5D" \
- "\x03\xBE\x67\xF4\x99\xA1\xA3\x53\x25\x5B\x50\x6D\x0C\x3A\xA7\x4C" \
- "\xB0\x86\x04\x60\x01\x8C\xED\xBC\x5A\xF9\x3A\x0E\x1B\x10\xFF\x55" \
- "\x8B\x23\xAC\xDE\xEA\xB2\x2E\x8B\x02\x4E\xF1\x67\x9C\x85\x5D\x3B" \
- "\xE1\xC1\xAC\x3B\x26\xE2\xC3\x13\x25\xF4\xCC\xBC\xF0\xD9\x1F\x27" \
- "\x0C\xF0\x42\x6C\x18\x3B\x20\xC6\x29\xD7\x6C\x0A\x4B\xDC\x44\x3C" \
- "\x46\xDB\x6E\x78\xEB\xAB\x7A\xF5\x63\xE2\xAD\x77\x03\xA0\x9F\xCB" \
- "\x22\x4D\x03\x66\x0B\xF8\xE7\x26\xA4\x15\xF4\xF9\x13\xE7\x14\x97" \
- "\xF1\x98\xD0\x8B\x4E\xDB\xA5\xC6\x4E\x74\x19\x2C\xB2\x97\x55\xA4" \
- "\x0E\x61"
-
-/** Screen mode 640x480 (at 85 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_640_480_85_24_0 "" \
- "\x6D\x0D\x6A\x02\x66\x8A\x8A\x94\xFD\x31\x6D\x98\x53\xD7\x93\x25"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_640_480_85_24_0 "" \
- "\xC6\x8C\x42\x4C\x95\xDA\xB4\x2F\xBD\xD9\x9E\x7C\x8F\x7B\x69\xA8" \
- "\x1B\xDA\x06\x96\x23\x9E\x94\xE2\xC2\xE9\xBB\xD3\x13\x6B\x9B\x21" \
- "\xC1\x4E\xD8\x3F\x81\x49\x6E\xD1\xAF\xB2\x4E\x8C\x24\x1A\xA8\xB6" \
- "\x4E\x11\x75\xB3\xE6\xC9\x3D\x36\x9A\xCC\x3B\xAA\x1F\xC4\x97\xD5" \
- "\x4A\x9D\xAA\xE0\x04\xF0\xB6\x2C\xBD\xE4\x41\x19\xF8\xA2\x77\x7C" \
- "\x46\x9D\x3A\xBD\x73\xC0\x64\x70\x84\x2B\xD7\x11\xF3\x43\xB5\xFB" \
- "\xE9\x0B\xB3\x4B\x2B\x80\x98\xEF\xDC\xDA\x46\xD6\xEC\xBD\x0B\x4D" \
- "\x64\x20\xF7\x17\x17\x33\x75\xB5\x30\x26\xDD\x0A\xA0\x99\x23\x11" \
- "\xF1\xDE\x80\xB0\xD6\xB0\xB7\x5A\xA9\xBD\x6D\x29\x42\x74\x75\x73" \
- "\xC5\x27"
-
-/** Screen mode 720x400 (at 70 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_720_400_70_24_0 "" \
- "\x9C\xC5\x1C\x02\x4F\xA6\x97\x4D\xD7\x04\xE5\x2A\xDC\x78\x4F\x24"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_720_400_70_24_0 "" \
- "\xC4\x2C\x84\x13\xDD\xB8\x82\xCB\x62\xA3\x40\xFA\x41\x8B\x5E\x1B" \
- "\x74\x02\x11\xDD\x90\xB8\x14\x51\xE1\x28\x7E\x3B\x42\x6A\x6B\x9C" \
- "\x7E\x4B\xFC\x8A\x19\x8D\xF4\x23\xB4\x98\x96\x55\x68\x8F\xDA\x88" \
- "\x9C\xE0\x20\x5D\xB5\x9F\x34\x9B\xB2\xCF\x10\x6B\x2D\x66\x63\x0B" \
- "\xDE\x3C\xC4\x90\x3C\xB4\x23\xF9\x5C\x93\x6F\x43\x29\x20\x54\x90" \
- "\x94\xB8\x78\xED\x33\xC7\xDD\x8B\xAA\xD0\xF6\xDC\x78\xEB\x50\x23" \
- "\x83\x00\x6F\x42\x83\x58\xD7\x1C\xA0\xDF\x41\x9E\x69\xB5\xA4\x3A" \
- "\x31\x79\xCB\xDF\x59\x5E\x76\xFB\x89\x32\x2B\x00\xE5\xDF\x16\x52" \
- "\x4F\xE1\xCC\xB7\xE3\xED\xEE\xC1\x5E\x56\xDF\x4E\x35\x1C\x14\x99" \
- "\xDF\x6F"
-
-/** Screen mode 720x400 (at 85 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_720_400_85_24_0 "" \
- "\x4E\xEB\x46\x9D\x91\xDD\xEA\x68\xE2\xCF\x92\xBE\x47\xE1\xE2\x7C"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_720_400_85_24_0 "" \
- "\xE6\x20\x16\xD8\xFE\x44\x88\xBF\x44\x7B\xBE\x98\xA3\xC9\x56\x4E" \
- "\xBC\x98\x6B\x8B\xCD\x50\xB0\xB8\x4D\x95\x32\xF7\xB8\xDE\x45\x3D" \
- "\x87\xD4\x13\xBF\x42\xE6\xC5\x86\x4E\x9D\xD7\x11\xD6\x1F\x1E\x11" \
- "\x55\x5E\xD5\x2E\xFE\x02\xD4\xB0\xDC\x10\xA0\x45\x44\x00\x2E\x0B" \
- "\x4C\x7B\x47\x1B\x06\x16\x20\x18\x6D\xED\x65\xC9\xC0\x11\xDD\x76" \
- "\x78\x8E\x2D\x5D\xD7\x5E\xF7\x6E\x17\x75\x14\x74\xA8\x4D\xFC\x6F" \
- "\x47\x50\x69\x15\x01\x3D\x92\xF5\x1D\xF6\x03\x4A\x89\xC5\x2D\x1E" \
- "\x3A\xBB\x25\x83\x3A\xFD\x72\xBD\xA2\x96\x61\x84\x45\x5F\x19\x21" \
- "\xB5\xBC\x3A\xF4\x7E\xFA\xBF\x0A\x5E\x82\xC8\xF6\x26\x4D\xA4\x06" \
- "\xD9\x97"
-
-/** Screen mode 800x480 (at 60 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_800_480_60_24_0 "" \
- "\x7A\x12\x36\x0B\xEF\x21\x74\xD1\xF0\x06\x8F\x38\xE8\x71\xB4\xCE"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_800_480_60_24_0 "" \
- "\x78\x67\x19\xF3\xB3\xD6\x5D\x7B\x4C\xCA\x26\x78\x41\x19\x19\xAC" \
- "\xFF\x38\xB3\x10\x71\x89\x6A\xEC\xA8\xC1\x4F\x1F\x77\x86\x5D\x7E" \
- "\xCE\xAF\x65\x7D\xFC\x30\x51\x67\x1F\x48\x30\x8E\x7A\x4B\x8A\xD4" \
- "\xCB\x62\x45\x58\x5C\x22\x1D\x56\x6E\x2F\x60\xE2\x06\x6D\xA1\xE3" \
- "\x82\x5F\x67\x95\x7A\x9F\x87\x43\xD8\x33\xEF\x0B\x5A\xDA\x09\x4F" \
- "\xD7\x25\x6F\xBC\xF8\xC7\x09\x9C\x12\xC3\xA7\x6F\xE7\xED\xA8\x70" \
- "\x8C\xB9\x65\x53\xDD\xA6\x7D\xDE\xD9\x4F\xDD\xD4\x6F\x28\xD6\x14" \
- "\xDC\x2D\x41\x53\x33\xD9\x0A\x86\x11\x3C\x41\x5A\x56\x48\xF9\x85" \
- "\x2B\x2F\x22\x66\x20\x39\xDA\xA1\x50\xCB\x5A\x58\x7D\x97\xFA\x2C" \
- "\x64\x9D"
-
-/** Screen mode 800x600 (at 56 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_800_600_56_24_0 "" \
- "\x19\xFC\x59\x09\x1D\xCD\xDA\x0D\xD3\x6A\x45\xBB\xDB\xF9\x8A\x57"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_800_600_56_24_0 "" \
- "\xD7\x63\xD3\x78\x60\xAC\x0F\xFE\xF5\x0A\xC7\xF0\x17\x0E\x9C\x6C" \
- "\x47\xFF\xF5\x36\xFD\xDE\x22\xE6\xA1\x80\x4F\x0D\x90\x72\xE6\xAD" \
- "\x49\x95\x4B\xD4\x6A\x31\xF9\x6E\x6F\x6E\x93\xF5\x44\x46\x7A\x84" \
- "\xD4\x10\x51\x7A\xE1\xDF\x48\x32\x9D\x0E\x59\xD9\x0B\x57\x45\x7C" \
- "\x58\xF6\x72\x8D\xAF\x91\x7F\xBE\xE8\x2F\x3A\x7F\x3D\xF5\xD6\x39" \
- "\x1E\xB8\xB2\x1D\x7F\x6F\x60\xBC\x0F\xF8\xAD\x43\x76\xFA\x75\x19" \
- "\xFB\x5D\xA4\xCD\xF7\x38\x5F\x11\xD4\x56\x11\x9E\x79\xB4\x4A\x4D" \
- "\x7A\xC7\x03\xAC\xFB\xB4\x4F\x98\x93\xB0\xDC\xE2\x8F\xE9\x05\xB2" \
- "\x90\xE0\x8D\x41\xC2\xAF\xC5\xEE\x8B\x00\x90\x7C\x26\x87\x54\x4A" \
- "\x71\x2A"
-
-/** Screen mode 800x600 (at 60 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_800_600_60_24_0 "" \
- "\x02\x18\xF5\x1F\xE5\xCF\x2C\xB9\x39\x72\x74\x15\x6B\xFE\x6C\x71"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_800_600_60_24_0 "" \
- "\xC0\x2C\xFF\x8C\x0F\x57\x30\xD7\x8A\x19\xCE\xB2\x47\x2B\xE3\xFA" \
- "\xEE\x8F\x95\xF7\xA7\x78\x44\x39\x29\x78\xF4\x0C\xB7\x3F\xF8\xD4" \
- "\xFA\xAD\x2C\xB8\xF2\x1C\xBB\x16\x10\xCC\xF5\xD5\x53\x6C\x2E\x4E" \
- "\xEF\xB5\xF5\x81\x0A\xE1\x8F\x32\xC5\xB9\x96\xAB\x8C\xC2\xE3\xA7" \
- "\x32\x14\x76\xD5\x63\xC1\x8E\xD6\xCF\x95\x1B\x0C\x51\xA9\x88\xEB" \
- "\xF3\x89\x40\xB7\x41\xB6\x87\x10\x03\xDB\x09\xFE\xCD\xFF\x2A\x7C" \
- "\xB1\x76\x8C\x27\x04\xA8\x09\x3B\x9E\x63\xDE\xE0\x31\xC8\x9B\x5E" \
- "\x1E\x51\x5A\xB3\x1B\xE7\xEE\xAE\x54\x47\xBB\xF0\x9F\xAE\xBB\xF6" \
- "\x43\x35\x57\xAE\x87\x8C\x88\x8B\x61\x61\x47\xA9\x87\xF7\xC3\x86" \
- "\x8E\x53"
-
-/** Screen mode 800x600 (at 72 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_800_600_72_24_0 "" \
- "\x81\x59\xC0\x67\x29\xEC\x20\x62\x5E\x94\x77\xCA\x93\xE3\x3B\xA5"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_800_600_72_24_0 "" \
- "\x3B\xD9\x26\xBF\xB4\xE3\x00\x22\x87\x3D\xCD\xDE\x26\x6E\x71\x13" \
- "\x15\x22\xFB\xA0\x3F\x4B\xE1\x33\xED\x36\x15\x71\x8E\xB6\x3A\xE5" \
- "\x69\x27\xF8\x8E\xBA\x43\x42\xC3\xB8\x6F\x25\xCD\xC0\xDB\x35\xE6" \
- "\xD0\x33\x02\xF8\xFF\x05\x73\x60\x06\x50\x6D\xB0\xF5\x86\x68\xC3" \
- "\x27\xD8\xB4\x63\x88\x6D\x0E\x55\x1C\x18\x76\xDF\x37\x0D\x50\x62" \
- "\xD0\x82\x75\x66\xB8\x0A\x40\x2D\x94\x85\xB1\x04\x44\x1E\xD1\xCA" \
- "\xF7\x97\xD8\x21\x28\xB5\xBE\x91\xC5\xC2\x1F\x48\x63\x70\xED\x4F" \
- "\x88\x9A\x02\xD0\xC3\x7C\x7A\x6A\x42\x11\xD7\xEA\x91\xF9\xCE\xAC" \
- "\xA3\x03\x8E\xBE\x14\x25\x74\x4B\xE5\x0B\x37\xEA\x5C\xB0\xA9\xD5" \
- "\xE5\x95"
-
-/** Screen mode 800x600 (at 75 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_800_600_75_24_0 "" \
- "\x3F\xDB\xEE\x68\xC7\x0E\xCA\x26\xA3\x42\xF0\x36\x25\x2B\xDB\x48"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_800_600_75_24_0 "" \
- "\xB5\x2E\xA8\x75\xF5\xC0\x36\xD8\xBF\xB3\xA8\x4F\x6F\xA4\x68\x06" \
- "\xEC\xFB\x44\x53\xFC\x4B\xC2\x44\xF0\xFA\x20\x47\xC0\xC5\xDE\xB1" \
- "\x6B\xDF\x89\x24\xD1\xA6\xE1\x86\xAE\x7F\x19\xA5\x56\xE7\x52\xBC" \
- "\xD7\xCC\xAF\xED\x9C\x4F\xAF\x77\x49\x7C\x99\xA9\x0E\xB9\x41\xAE" \
- "\x34\xD1\xB3\x33\xAD\x12\x91\xFC\x6C\x78\x85\xD5\x91\x6B\xB2\x1E" \
- "\x28\x39\x15\x41\xF5\x14\x35\x9E\xAC\xE2\x0C\x9C\x69\x5C\x76\x86" \
- "\x55\xF1\x41\x36\x02\xE1\x6C\xAA\x60\x66\xE4\x1F\x5D\xB7\xED\x16" \
- "\x3F\x55\x21\x57\x56\xDA\xB3\x00\xA0\x15\x8F\x26\xC1\x08\xA6\x8B" \
- "\x19\x22\x5E\xD2\x48\x7B\x18\xA6\xD4\xF9\x9D\xD4\x85\x57\x05\xD9" \
- "\xC6\x31"
-
-/** Screen mode 800x600 (at 85 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_800_600_85_24_0 "" \
- "\x51\x11\x2B\x19\x1F\xF6\x3F\xC2\x38\x2F\xF8\x5D\x5A\xD3\xA6\x0D"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_800_600_85_24_0 "" \
- "\x87\x1E\x1B\x28\xEA\x5B\xFA\xAB\x66\xC6\x43\x53\xC7\x3A\x77\xF4" \
- "\x08\x95\x51\x50\x9E\x8A\x19\x38\x55\x40\x3C\x31\x45\xEE\x59\xBA" \
- "\xF2\xB3\x3C\xFD\xEC\x2F\x58\xED\xEF\x1A\x7F\xDB\xF6\x02\x25\xCA" \
- "\x79\xCF\xC2\x7C\x95\x75\x30\xBB\x41\x3A\x3E\x27\x33\x0D\x37\x48" \
- "\x02\x6D\xDB\x86\x50\xB0\xCA\xAA\x92\x25\x08\xB7\xDE\x93\x51\x87" \
- "\xC0\x57\x8C\xA1\xE0\xE5\x38\xC1\x30\x97\x82\x6B\xE7\x96\x37\xA5" \
- "\x63\x0B\x79\xB8\x67\x28\x25\x60\x79\xF2\x1D\x98\xE2\xAC\x2E\x1B" \
- "\x1C\x7D\x3C\x9B\x63\x53\xFD\x73\x44\xAF\x8D\xDE\xB0\x98\xCD\x6E" \
- "\xBA\x60\x48\xC2\x74\x5A\x8E\x9A\xB3\x3F\x9A\x2B\x28\x42\x66\x93" \
- "\x1A\x26"
-
-/** Screen mode 848x480 (at 60 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_848_480_60_24_0 "" \
- "\x06\x53\xBC\x25\x49\xFB\xE8\x81\x2A\xE0\xDF\x85\xB4\x85\x92\x4C"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_848_480_60_24_0 "" \
- "\x27\x9E\x14\x5B\x10\x06\x0C\xE8\xFB\xD1\x12\x84\xC7\xEE\x60\x2E" \
- "\x1B\xC4\xE1\xE0\x98\x72\x13\xE1\xEC\x4A\x2D\xC2\xBB\x44\xEB\xCC" \
- "\x62\x2F\xE6\xC1\x71\x5D\x71\xD9\xBB\x90\xF3\xCC\x71\x7E\x5B\x71" \
- "\x77\xA5\x78\xCF\x02\x9A\xE7\xDF\x8F\xD4\xEE\xCF\xE7\x39\xA7\x75" \
- "\x9F\xE8\xCD\xCE\xDB\x5E\x7F\x61\x60\x45\xC6\x97\x91\x82\x6A\xFD" \
- "\x4C\xB1\xAB\xAA\xAE\xAB\x13\x92\x45\xB6\xFD\x8F\xD1\x34\xB8\x34" \
- "\x25\x45\xA5\xD7\xB7\xD6\x3E\x05\x9E\x25\x8E\xC5\xA9\xA3\x89\xC7" \
- "\xF9\x98\x2E\xB6\xEB\x04\xCE\x79\x9F\x01\x3F\x3C\xBF\xD6\xF8\xDA" \
- "\x3B\xFA\xDB\xA1\x78\xD6\xA2\x3D\xF4\xD9\x69\x37\xDE\x1F\x1C\x70" \
- "\xF0\x01"
-
-/** Screen mode 1024x768 (at 60 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1024_768_60_24_0 "" \
- "\xB6\xF8\xFC\x00\xF3\xE4\x81\x1E\xC5\x60\xA3\x79\xE5\x35\xC5\x15"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1024_768_60_24_0 "" \
- "\xDD\x2A\x3A\x49\xE9\x99\xE3\xC8\xA0\xBA\x23\x3A\x3D\xEB\x21\xE4" \
- "\xA5\x54\x25\x0D\x51\xCC\xE6\x52\xA7\xD7\xCD\xFA\xD5\x9B\x5B\x41" \
- "\x0B\x49\xAB\xC6\xE3\x1A\xF2\x87\x81\x32\xF0\x3E\x40\x00\x51\x40" \
- "\x9E\x94\xF1\x22\xEE\xAC\xB2\xA2\x6B\x4D\xC4\x41\x5A\x9C\x45\x62" \
- "\x4F\x4E\x61\xDB\x1F\x0E\x79\x66\xE2\x20\x83\x9E\x2C\xAB\x28\x38" \
- "\xAC\xC1\x22\x81\xA5\x69\xFD\xFB\x26\x15\xF9\xC9\xFA\x90\xF2\x66" \
- "\x85\xC5\xAA\xA6\x4D\x8B\xC8\xA6\x03\x32\xDF\x98\xA9\x77\x9E\x57" \
- "\xEA\xC9\x9E\x29\xED\xFC\xC4\x78\x26\x0B\x2E\xC2\x41\x7C\x4A\xA3" \
- "\xAB\x66\x01\xA0\xE5\xA4\x8B\x80\xA0\x53\xE5\x5D\x59\x63\x62\xE8" \
- "\xFE\x6B"
-
-/** Screen mode 1024x768 (at 70 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1024_768_70_24_0 "" \
- "\x2B\x71\x0C\x1F\x55\x8E\x3D\x1A\xEE\xE0\x93\xD4\x15\x58\xE9\x00"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1024_768_70_24_0 "" \
- "\xE9\x15\xBC\xBE\x90\x6C\x07\x34\xF2\x79\xCA\x43\x44\x92\x65\x9A" \
- "\xC7\x41\xE9\x56\xE7\x27\x4A\x9C\x24\x04\x40\x97\xF5\xFD\xFF\x99" \
- "\xC8\x6A\xA0\xF3\x32\xE3\x4E\x40\xBC\xA5\xAE\x37\xBA\x89\xB0\xDD" \
- "\x10\xD2\x10\x76\xE8\x80\xAF\x15\xC1\x16\x65\x80\xA2\xCE\xFD\x14" \
- "\x66\xD8\xAA\x83\x7C\xD6\xE2\xF2\x26\x36\xD5\xF2\x36\xA5\x7F\x4D" \
- "\xF6\x21\x14\x58\xB5\xFA\x54\x07\xE6\x91\x93\xB9\xB9\x4B\xB5\x0C" \
- "\xD6\xAE\x6C\x2D\x12\x51\xED\x13\x6C\xD7\x07\x15\x6D\x88\x10\x62" \
- "\x94\x4F\x77\xB7\xEC\xA3\xD4\xAD\xDF\xCC\x76\x2D\x39\x90\xEE\xB1" \
- "\x98\x09\xA2\x28\x03\xF8\x1F\x1C\x01\xCA\xAA\xC0\xC2\x92\xDE\xD8" \
- "\xFC\x59"
-
-/** Screen mode 1024x768 (at 75 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1024_768_75_24_0 "" \
- "\x10\xFC\xF8\x65\x8A\x35\x80\x78\x15\x13\x4C\x2A\x6C\x35\x2B\x74"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1024_768_75_24_0 "" \
- "\xE6\xB2\x51\x5B\x75\x7E\x2A\xBC\xA5\x4A\xC0\xC0\xEA\x20\x67\xCC" \
- "\x89\x74\x5D\x3B\x7D\xB4\x29\x82\xA8\x28\x97\x86\x13\x0E\xE3\xCC" \
- "\x95\x10\x43\x65\x15\x64\xA0\xF9\xA7\x20\xFE\x61\x0A\xFF\x6E\xEC" \
- "\x7E\x55\x17\x4F\xA2\x61\x77\x7E\x9A\x3B\x04\xFF\xC0\xA0\xAE\x82" \
- "\x3F\x81\x1A\xEB\x45\x8B\x37\x99\xA6\xED\xB1\x66\x78\x02\x8C\xB3" \
- "\xE7\x88\xD5\x57\xD8\xE7\xFD\x7F\x49\x8B\xBE\xC6\xD1\xDD\x60\xB5" \
- "\x41\xCD\x1B\x3E\xEC\x69\x18\xE9\x77\x71\x7F\x0E\x11\xCB\x47\x82" \
- "\x89\x2C\xCA\x54\x5E\x33\x9C\x60\x61\x42\x55\xB4\x4B\xC2\x9C\x37" \
- "\xFD\x37\xD4\x47\xC5\x08\xDF\x14\xCB\xCD\xD9\xCD\xA0\xC1\x42\x21" \
- "\xD2\xD9"
-
-/** Screen mode 1024x768 (at 85 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1024_768_85_24_0 "" \
- "\x02\x10\x92\x8C\x45\x12\x05\x5A\x25\x51\x85\x91\x87\xB0\x05\x8C"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1024_768_85_24_0 "" \
- "\xA7\xC9\xD0\x6E\x6E\x77\xDA\xD3\x25\xEA\x3B\xA4\x4B\x35\x88\x4E" \
- "\x22\x53\xC4\x82\xB0\x14\x40\x54\x8A\xB6\x42\xF2\xBB\xC8\x4B\x24" \
- "\x52\xF9\xC3\x37\xBE\xCF\x99\x01\x5A\x56\xB2\xA8\xE7\xF3\x53\x7B" \
- "\x37\x55\xFE\x97\xF3\x05\xFF\xC0\x71\x60\xBB\xD9\xCC\x49\xFA\x73" \
- "\x2C\x39\x72\x25\x27\xFB\x83\x7D\x44\x58\x86\x5D\x6F\xFC\xCF\xD4" \
- "\xCF\x7C\xC1\x33\x35\x21\x30\x70\xA8\x36\x60\xBB\xA8\xE2\x74\x05" \
- "\xBB\xB3\xC5\x60\xBD\x4B\xC0\x6C\x04\x41\xD2\xE6\xFA\xEB\x67\x02" \
- "\x6A\x77\x82\x4D\xF7\x05\xAC\xA8\xA3\x8F\x21\xCA\x24\xF3\x53\x52" \
- "\x2A\x99\xEA\xE5\xBD\x76\x3C\x85\x73\x98\xD8\x46\xA7\xAC\xA8\xB7" \
- "\x3A\xA9"
-
-/** Screen mode 1152x864 (at 75 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1152_864_75_24_0 "" \
- "\xAE\xFE\x44\xF3\x10\x49\x4E\x35\x9B\xD3\xC7\x22\x83\xCC\xAE\x40"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1152_864_75_24_0 "" \
- "\x65\xB5\xCB\x8E\x46\x49\x3E\xFB\x60\x91\xC1\x32\x82\xD3\xCA\x2F" \
- "\x4A\x49\xB1\xA8\x17\xA1\x12\x37\xBB\x1C\x5F\x69\x41\xA8\x72\xB2" \
- "\xB8\x37\x9C\x7E\xE3\x5C\xA2\xD3\x19\x59\xE2\x75\xA7\xC9\x25\xBB" \
- "\x6E\x77\xD1\x2D\x25\xEA\x36\x43\x4B\x35\x87\xB3\x22\x53\xC9\xB5" \
- "\xB0\x14\x4B\x1D\x8A\xB6\x57\x78\xBB\xC8\x5C\x3B\x52\xF9\xD6\x3C" \
- "\xBE\xCF\x82\xCB\x5A\x56\xAF\x2E\xE7\xF3\x4C\x85\x37\x55\xE3\x91" \
- "\xF3\x05\xE4\x3C\x71\x60\xAE\xB6\xCC\x49\xEF\x6A\x2C\x39\x61\x75" \
- "\x27\xFB\xB0\x7D\x44\x58\xB3\x32\x6F\xFC\xF8\xBF\xCF\x7C\xFB\xCC" \
- "\x35\x21\x0E\x8B\xA8\x36\x5E\xC4\xA8\xE2\x7D\xFC\xBB\xB3\x2D\x9C" \
- "\xBD\xCB"
-
-/** Screen mode 1280x768 (at 60 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1280_768_60_24_0 "" \
- "\x73\x9D\x25\x83\xE6\x73\xB8\x81\x46\x7F\xA3\xC9\x4C\x52\x09\xB4"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1280_768_60_24_0 "" \
- "\xB0\x52\xEB\x22\x12\xDD\x55\x65\x5C\x01\x38\xD9\xA2\x1A\xE6\x1F" \
- "\x75\x89\x16\x6E\x7A\x2E\xFC\x28\x9F\x3C\xD0\xE6\xC8\x0F\xD9\xCE" \
- "\x66\xBD\xDA\xE1\x28\x88\x61\x5B\xB2\x1B\x03\x5B\x3E\x37\xD7\x54" \
- "\xD8\xC4\xCA\xBC\x85\xBE\x2E\x50\xA2\x39\xC1\xB1\xB9\xBC\x92\xA9" \
- "\x09\xCA\x4D\xFA\x67\x4D\x55\x1E\x2D\xAC\x8C\xBB\x76\x81\xEE\xEE" \
- "\x14\xEF\xBC\xD8\x4D\xB6\x0B\xB0\x74\xEB\xDF\xDB\xF4\x30\xB8\xF2" \
- "\xBA\x97\x4A\x67\xAB\x3E\x84\x6B\xC6\x23\x2E\x3A\x69\x39\x04\x67" \
- "\x01\xAF\xEE\xE6\x96\xCC\x9E\xFF\x68\xF4\x6A\x0F\x73\x52\x1E\x0A" \
- "\x0F\x11\x4A\xE8\x12\x72\xF6\x0E\xA0\xE2\x8A\xC3\x1E\x6C\x49\xA5" \
- "\x6C\xBE"
-
-/** Screen mode 1280x1024 (at 60 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1280_1024_60_24_0 "" \
- "\x6A\xF0\x37\x50\x63\xEF\xD2\xA9\x6F\x75\x72\xBB\xC7\x7B\x6F\x1A"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1280_1024_60_24_0 "" \
- "\x23\x4A\x78\x7C\xD1\xB8\x0E\x6B\x15\x93\x96\x77\x78\x44\xCC\x16" \
- "\x7F\xE3\xD7\x39\x3F\x2E\x99\xD2\xB9\x68\x8E\xC4\x1A\x9B\xF4\x35" \
- "\x61\xB5\x48\x5C\x94\xA6\x84\xB2\x88\x2B\x47\x84\x84\x73\x7F\x2C" \
- "\xD0\xC4\x3D\x5D\x20\x61\x4A\xB1\x73\x4C\xDD\x6A\xB4\xFD\xE9\x94" \
- "\x3C\xD1\x44\x0A\x08\xCD\xF5\xE5\xBD\x0D\x99\xCD\x9C\x2A\xC9\x06" \
- "\x1D\x22\x1C\xB1\x9A\x94\x95\x65\x3C\x43\x19\x73\x83\xF7\x51\x1F" \
- "\x5C\x3C\xE1\x59\xD5\xC3\xF2\x27\x28\xCE\x22\x7B\x2A\x70\x04\xE4" \
- "\xD9\xFE\x8A\x6E\x28\x27\xC5\x40\x4E\xF8\x83\x5B\x82\x41\xA6\x62" \
- "\xC1\x73\x3A\x5C\xF6\x90\x43\x39\xF2\xF5\x74\x80\x74\x44\xBD\xB1" \
- "\x08\x53"
-
-/** Screen mode 1280x1024 (at 75 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1280_1024_75_24_0 "" \
- "\xDB\xCF\xE1\x3F\xBE\xB3\xE8\x2D\x29\x5B\xE8\xF0\xD6\x57\x0B\xFF"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1280_1024_75_24_0 "" \
- "\xBA\x89\x45\x90\x10\xD2\x1B\x50\xE8\x80\xA2\xE9\xC1\x16\x6A\x6D" \
- "\xA2\xCE\xF0\xD4\x66\xD8\xA1\x18\x7C\xD6\xF7\xD8\x26\x36\xC2\x7E" \
- "\x36\xA5\x6A\x9A\xF6\x21\x0F\xF3\xB5\xFA\x49\x07\xE6\x91\x8C\x4B" \
- "\xB9\x4B\xA8\x0C\xD6\xAE\x77\xD1\x12\x51\xF8\x21\x6C\xD7\x12\xED" \
- "\x6D\x88\x03\x5D\x94\x4F\x44\xB7\xEC\xA3\xE1\x3F\xDF\xCC\x41\x85" \
- "\x39\x90\xD4\x4E\x98\x09\x9C\xD3\x03\xF8\x21\xE3\x01\xCA\xA3\x39" \
- "\xC2\x92\x36\x23\xFC\xD9\x99\x08\x7B\xC0\x9C\xCE\x21\xF4\xBA\xBE" \
- "\x22\x36\x9C\xB4\xE4\x4A\xFB\xC1\x1E\x9B\xAC\xFF\xB3\x5A\xD4\x0D" \
- "\x7C\x1C\x28\xBB\x8E\x8B\xD8\x8E\x1E\xFE\xEE\xD9\xE7\x04\x99\x20" \
- "\xE8\xB1"
-
-/** Screen mode 1280x1024 (at 85 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1280_1024_85_24_0 "" \
- "\xE4\xE9\xAF\xA2\x9D\x98\xD0\xC6\xF3\xB8\xB6\xC9\x10\xC1\xC8\xA6"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1280_1024_85_24_0 "" \
- "\x93\xB0\x06\xA2\x8F\xE9\x2C\xB3\x90\xE0\xA6\x66\xC2\xAF\xEC\x00" \
- "\x8B\x00\x8C\x0B\x26\x87\xAF\x8A\x71\xAA\x43\x0F\x64\xF4\xC5\xF3" \
- "\x04\x62\xE6\x7A\x36\xDE\xFA\x1A\x19\x93\x12\xD1\x0F\x74\x12\xAF" \
- "\x46\x2C\x4D\x23\x34\xCF\x57\x3B\x16\xFE\x0B\xDC\x42\xDB\x0C\x80" \
- "\x39\x44\xDF\x0C\x8B\x58\x28\xB3\x05\x00\x2F\xB9\xB8\xC0\xB6\xA1" \
- "\x3C\x38\x80\xA1\x6C\x45\x4F\xF1\xE6\xB2\xBB\xA4\x75\x7E\x3C\x44" \
- "\xA5\x4A\xD6\x28\xEA\x20\x7D\x78\x89\x74\x45\x97\x7D\xB4\x31\xB5" \
- "\xA8\x28\xB1\xB0\x13\x0E\xC1\xCC\x95\x10\x61\x62\x15\x64\x81\x4A" \
- "\xA7\x20\xDD\x3A\x0A\xFF\x4F\x39\x7E\x55\x03\xB0\xA2\x61\x84\x7E" \
- "\x9A\xBB"
-
-/** Screen mode 1280x768 (at 75 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1280_768_75_24_0 "" \
- "\x87\x94\x88\x24\x2C\x58\xEA\x1F\x10\xA1\xE9\x20\x62\xB1\xC6\x43"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1280_768_75_24_0 "" \
- "\x20\x5C\x76\xA7\x04\x95\xDE\x8B\xE9\xBA\xCA\x66\x6C\x8F\xA9\x5B" \
- "\x4E\x0F\x9A\xCA\x5D\x25\xB2\x6C\xB4\x6F\xA5\xE4\xB7\xEB\xEF\x58" \
- "\xE9\xFC\x9C\xD2\xF4\xE4\xB1\x47\xA9\xC6\xE4\xF6\xAD\xC6\x9C\x38" \
- "\x7F\x29\x2F\x59\x97\x93\xA6\x07\x91\x33\x1A\x1F\x0B\xBE\x9D\xE7" \
- "\x3C\x7E\xCC\x60\xF4\x2E\x59\x92\x01\x7B\xCB\xB2\x85\x9D\x18\xA7" \
- "\x6E\x0C\x56\xFF\xCA\x58\x32\xAB\xF1\xBB\xC7\x6B\x82\xEE\x11\x9C" \
- "\x3D\x90\xAB\x2D\x4A\xE6\x22\x30\xEB\x42\xA1\xA6\x07\x6A\x14\x4F" \
- "\x58\x1F\x86\xDF\xCB\x19\xF5\x7F\xB3\x90\x28\x41\xD4\xA1\x1C\x1B" \
- "\xA6\xD0\x45\x85\x0F\xDB\xBB\xA1\xBA\xCF\xF5\xAB\x88\xB9\xF6\x32" \
- "\x0F\xC9"
-
-/** Screen mode 1280x768 (at 85 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1280_768_85_24_0 "" \
- "\x74\xE4\x58\xA1\x3C\x43\xC0\x4D\xE4\xA9\x6D\x46\x5B\x34\x89\xE5"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1280_768_85_24_0 "" \
- "\x5B\xA6\xDC\x6E\xE2\xD7\xAD\xE3\xF3\xCF\x02\x6D\xD9\xDD\x83\xEB" \
- "\xE4\x12\x6B\xC6\x3D\x1C\x18\x54\x7A\x30\x1A\x0C\x24\xD0\x54\x05" \
- "\xE6\xAC\x4E\x76\xCE\x92\xA5\x1D\x8B\xE9\x5E\x53\x42\x0F\x1F\x9C" \
- "\x2A\x15\x6B\xB1\x8D\xA0\x3E\x8E\xBC\x0A\x22\xB2\x46\x6A\x18\x18" \
- "\xAC\xA4\x46\x5D\xF1\x37\x62\xE3\xB2\x38\x33\xFD\xF2\x02\x46\xF2" \
- "\xAB\x20\x68\x60\x7D\xCF\xA6\xE3\x47\x9A\x9B\xA7\xA9\x80\xAB\x54" \
- "\x35\xAD\x93\xFB\x98\xE0\x48\x7D\x67\x70\x91\x3B\x5A\x75\x8F\x97" \
- "\x2B\xC6\xF3\x34\x44\xB1\x6B\x60\x0B\x74\x46\x54\x94\xC3\xDD\xC0" \
- "\xDC\x75\xFF\x99\x10\x5E\x90\x26\xD8\x56\x99\x1E\x0E\x84\x7F\x8B" \
- "\x43\x88"
-
-/** Screen mode 1280x800 (at 60 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1280_800_60_24_0 "" \
- "\x59\xFF\xC3\x96\x42\x84\xE3\x26\x2D\x50\x6C\x88\x84\xF6\x6E\x2A"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1280_800_60_24_0 "" \
- "\x55\x5E\x21\x5E\xFE\x02\xD8\x84\xDC\x10\xAC\xF6\x44\x00\x22\x46" \
- "\x4C\x7B\x4B\xCC\x06\x16\x34\xFC\x6D\xED\x71\x58\xC0\x11\xC9\xA4" \
- "\x78\x8E\x39\xC3\xD7\x5E\xEB\x67\x17\x75\x08\x14\xA8\x4D\xE0\x5C" \
- "\x47\x50\x75\x35\x01\x3D\x86\x42\x1D\xF6\x15\x09\x89\xC5\x3F\xFA" \
- "\x3A\xBB\x09\x86\x3A\xFD\x46\xB8\xA2\x96\x55\x2B\x45\x5F\x22\x94" \
- "\xB5\xBC\x03\x09\x7E\xFA\x80\x25\x5E\x82\xC2\x09\x26\x4D\x4D\x33" \
- "\xD9\x17\x66\x3C\x4C\xAF\x47\x81\x15\x47\x9B\x39\x6B\x15\x62\x30" \
- "\x79\x1B\xFD\x3B\x86\x24\xA8\xD1\x47\xC2\x1C\x97\x8A\x07\x01\x66" \
- "\xFC\xC7\x4C\xF9\xC0\x2C\x2B\x8C\x0F\x57\x2F\xD6\x8A\x19\x30\x6D" \
- "\x47\xAB"
-
-/** Screen mode 1280x960 (at 60 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1280_960_60_24_0 "" \
- "\x42\xAB\xE3\x84\x2F\xC6\xAA\x5D\x17\x17\xE5\x9B\x0D\x53\xC5\xA6"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1280_960_60_24_0 "" \
- "\x3D\xAD\x8C\xC7\x3D\x3F\x34\x45\xB6\x05\x97\xE1\x57\x34\xEA\x4E" \
- "\x1E\xDD\xDA\x98\x2B\x31\xEB\xEF\x9B\xD5\x73\xB1\x7E\x68\xD5\xCC" \
- "\xD5\xB8\x72\xBD\xC7\x7C\x2D\x07\x90\xFE\x49\xD7\x79\x43\x63\x49" \
- "\xA5\xA3\x12\x82\x8E\xA8\xD7\x6C\xD2\xCB\x75\x03\x94\xE0\xD2\x9E" \
- "\x10\x40\x53\xD7\x63\xBA\x11\x24\x20\x27\x07\xE4\xEB\x27\xD0\x8A" \
- "\x53\x34\x80\x2D\xCC\x32\x7F\x27\xC3\x8B\x74\x36\x9D\x75\xDD\x82" \
- "\xE4\xE5\x40\xA2\xE2\x78\x3D\x48\x0F\x2C\xB4\x64\x65\xAB\xCF\x2E" \
- "\xFD\xA5\x9A\xC0\x4E\x32\x72\x1D\x2A\xFC\x9D\xC7\xE9\x28\xA5\x57" \
- "\xE7\xB5\x23\x44\xAF\x3E\xCC\xF4\x14\xCC\x98\x3A\x81\x83\x69\xFE" \
- "\x07\x8F"
-
-/** Screen mode 1280x960 (at 85 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1280_960_85_24_0 "" \
- "\xF6\x75\x37\x25\x3C\xE1\x82\x53\xF8\x68\xEE\x05\xBB\xB4\xAB\xBC"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1280_960_85_24_0 "" \
- "\x58\x1F\x5A\xDF\xCB\x19\xD1\x74\xB3\x90\x0C\x65\xD4\xA1\x37\xD5" \
- "\xA6\xD0\x6C\xF7\x0F\xDB\x94\x9E\xBA\xCF\xEF\x01\x88\xB9\x0F\x2B" \
- "\x0F\x49\xD0\x81\x31\xF5\x40\x7E\x69\x88\x7E\x59\x46\xA0\xEC\xCF" \
- "\x04\x19\x75\x02\xD9\x6C\xE2\x12\xA3\x1D\x4E\x73\xAF\xC9\xD6\x37" \
- "\xCB\xA8\xB1\xEE\xF4\x9F\x36\x0C\x46\x74\xE0\x54\x17\x48\xDC\xCE" \
- "\xDF\x94\xF7\x1D\x1A\x17\x46\xE8\x51\x63\x7F\xD7\x5B\x34\x72\x14" \
- "\x69\xED\x18\xE2\x12\xFE\x65\xB9\x90\x34\xAB\xFE\xD1\xFE\x42\x25" \
- "\x8D\xF8\xA6\x73\x9F\x8D\x9E\xE1\x8F\x00\xD1\xE3\xF4\x68\x30\xA9" \
- "\x99\x10\xE2\xC7\x62\x54\x55\x6F\x9E\xEF\x7A\xD7\x01\x1E\x5D\x87" \
- "\xD1\x43"
-
-/** Screen mode 1360x768 (at 60 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1360_768_60_24_0 "" \
- "\x84\x36\xDB\xC0\x18\x5D\x13\x10\xC5\x02\x16\x81\xB6\xC1\x3D\xA6"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1360_768_60_24_0 "" \
- "\x99\xDA\xC7\x8E\xCA\xE9\x49\xCB\xB6\xB4\xF8\x21\x10\x3B\xC1\x42" \
- "\x8C\x08\x1E\x52\x9A\xA9\x4A\x17\x4B\x9A\x07\x0A\xDE\xB0\x6D\x89" \
- "\x0C\x62\x11\x38\x93\x01\x9E\x33\xC8\xE6\x0E\x17\x02\x35\x69\x2B" \
- "\x73\x37\x44\xD3\x5B\x4F\xF7\xC0\x86\x5F\x1E\x9D\xA8\x70\x2B\x3C" \
- "\x30\x89\x7F\x65\x5C\x7A\xB6\x36\x4D\xA8\xE9\xFB\xCF\x07\x5F\x65" \
- "\xDA\x93\x2B\x98\x12\xB8\x39\xBD\x08\x5F\xB7\x99\x36\x37\x3C\x9E" \
- "\x7D\x1B\xB2\xA7\x54\xCB\x26\xC7\xAF\x78\xAC\x03\x8C\xA7\x89\xE4" \
- "\x66\x4A\xC1\x04\xF7\xEC\x74\xFB\xC7\x07\x9F\x81\x7F\x4C\x75\x5E" \
- "\xC3\xCD\x1B\xF7\x05\x1E\xF2\xB7\x03\x2C\x3C\xA4\x12\x9B\xFA\xA0" \
- "\xC4\xEA"
-
-/** Screen mode 1366x768 (at 60 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1366_768_60_24_0 "" \
- "\x6E\xF3\xC9\x86\x50\xDD\x97\x16\xDF\xAD\x97\x95\x6E\xD4\x3B\x46"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1366_768_60_24_0 "" \
- "\x2A\x70\xE7\xB0\xD9\xFE\xA9\x6F\x28\x27\xE0\x53\x4E\xF8\xA4\x45" \
- "\x82\x41\x8C\x7D\xC1\x73\x14\xE9\xF6\x90\x6D\xAA\xF2\xF5\x6D\xE0" \
- "\x74\x44\x45\x0E\x08\xD3\x0A\x6A\x06\xE1\x06\x5B\xB2\x89\x47\x47" \
- "\xB5\x0D\x74\x4F\x39\xF5\xB3\xA5\xCC\x57\x1E\x01\x97\xD5\xF4\xE4" \
- "\x09\x58\x0A\x79\xEC\x77\xF7\x4B\xCC\x9D\xF2\xB1\x3F\x68\xDF\x67" \
- "\x21\x03\x8A\x8D\xFD\x52\x92\x9A\x91\x56\x7A\x3A\x5F\xE0\x1E\x6D" \
- "\xA8\x53\x1A\x61\xFC\xBC\xE1\x2E\x2F\x9E\x07\xFE\xB5\xD9\x74\x92" \
- "\x2A\xA4\x2C\x08\xCA\xAF\x3D\xFB\x2E\xDF\xCE\xE9\xF7\xF2\x9E\x05" \
- "\x7C\xEB\x17\x1E\x51\xEF\xE1\x09\x6B\xE2\x5E\xD4\xA6\x7F\x18\x15" \
- "\xF3\xB8"
-
-/** Screen mode 1400x1050 (at 60 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1400_1050_60_24_0 "" \
- "\x95\xCB\x91\xE5\xA8\x28\xFB\x87\xD5\x92\x1C\x44\x66\x57\x8A\x98"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1400_1050_60_24_0 "" \
- "\xC6\x8C\x42\x4C\x95\xDA\xB4\x2F\xBD\xD9\x9E\xAD\x8F\x7B\x69\x15" \
- "\x1B\xDA\x06\x79\x23\x9E\x94\xF2\xC2\xE9\xBB\x34\x13\x6B\x9B\xB2" \
- "\xC1\x4E\xD8\x69\x81\x49\x6E\x64\xAF\xB2\x4E\x69\x24\x1A\xA8\xBB" \
- "\x4E\x11\x75\x38\xE6\xC9\x3D\xE9\x9A\xCC\x3B\xAA\x1F\xC4\x97\xD5" \
- "\x4A\x9D\xAA\xE7\x04\xF0\xB6\xD4\xBD\xE4\x41\xCF\xF8\xA2\x77\x0B" \
- "\x46\x9D\x3A\xBD\x73\xC0\x64\x76\x84\x2B\xD7\x11\xF3\x43\xB5\xF6" \
- "\xE9\x0B\xB3\x4E\x2B\x80\x98\x15\xDC\xDA\x46\xE8\xEC\xBD\x0B\x0E" \
- "\x64\x20\xF7\x17\x17\x33\x75\xBA\x30\x26\xDD\xFA\xA0\x99\x23\x11" \
- "\xF1\xDE\x80\xB7\xD6\xB0\xB7\xA2\xA9\xBD\x6D\x29\x42\x74\x75\x73" \
- "\xC5\x27"
-
-/** Screen mode 1400x1050 (at 60 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1400_1050_60_24_1 "" \
- "\xCB\xA2\x00\x73\xCB\xFC\xFB\xA0\x8E\x17\xE4\xF5\x6F\x6F\x8D\x1D"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1400_1050_60_24_1 "" \
- "\xDA\x01\x80\xE4\x99\x82\x8F\x40\xE9\x6E\xDD\xA6\x7F\xDE\x19\xFC" \
- "\x48\xF7\x90\x61\xE4\x2F\xA3\x72\x4A\xC5\x17\xBE\x27\x77\x35\x6A" \
- "\x74\x8E\xB5\x45\xA0\x6E\x3D\x58\x2E\xBA\x9A\xB6\xA3\xAC\x26\xD4" \
- "\xE8\xC6\xF8\xE3\x59\x7D\x76\x1C\x45\x07\x8A\x82\x96\x3B\x8B\x45" \
- "\xB7\x90\x79\xDB\x06\x4E\x97\x7F\x4E\x6A\xF0\xE7\x09\x7B\x3F\x05" \
- "\x20\x42\x7D\xAC\xBF\x79\x4D\x42\xC7\x19\x48\x2A\xC4\xA0\xCD\x9B" \
- "\xED\x6E\xB0\xF7\xAD\x31\xB1\xDB\xA0\x4D\x06\x41\xE2\x8F\x06\x63" \
- "\xD0\x48\xB5\xD5\x10\xB7\x47\x7D\xBC\xDE\x1D\x05\x55\x3B\x8F\x78" \
- "\xAA\x5C\x69\x52\x48\x3D\x48\xC5\x4C\x92\x8F\x48\x62\x9E\x71\xDC" \
- "\x36\xD2"
-
-/** Screen mode 1400x1050 (at 75 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1400_1050_75_24_0 "" \
- "\x8E\x2F\xD0\x59\x2B\xCB\xFA\xB9\xE2\xDE\xAE\x51\x4D\x3C\x6E\x4D"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1400_1050_75_24_0 "" \
- "\x25\xF4\x22\x48\xF0\xD9\x0D\xA9\x0C\xF0\x50\x5D\x18\x3B\x36\x2D" \
- "\x29\xD7\x7A\x1D\x4B\xDC\x56\xA2\x46\xDB\x7C\x33\xEB\xAB\x64\xBB" \
- "\x63\xE2\xB1\x4C\x03\xA0\x8B\xBB\x22\x4D\x29\x10\x0B\xF8\xC9\x3F" \
- "\xA4\x15\xDA\xCB\x13\xE7\x31\xF7\xF1\x98\xF7\x76\x4E\xDB\x80\xB9" \
- "\x4E\x74\x09\x29\xB2\x97\xBA\x23\x0E\xE1\xE9\x69\x17\x56\x3B\xD0" \
- "\x64\x78\x70\x27\x34\xB4\xD0\xE9\xF9\x4C\x0F\xF1\xF8\x55\x4C\x12" \
- "\x99\xF9\x07\x97\x06\xDC\xD8\x9E\xC5\x50\x58\x3B\xE8\x4A\x4F\x12" \
- "\x69\xAB\x7C\xDA\x8A\x95\x4B\xEF\x77\xFD\xE1\x0F\x21\x1D\x57\x86" \
- "\x46\xBE\x2B\x5A\xBF\xF5\xD2\xBF\xF7\xCF\x67\xEC\x0B\x32\xCC\x90" \
- "\x0C\x28"
-
-/** Screen mode 1400x1050 (at 85 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1400_1050_85_24_0 "" \
- "\x66\xC2\x92\x91\x8D\x8C\x4A\x6F\x6A\xF9\xC1\xB8\x35\x2F\x05\xD7"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1400_1050_85_24_0 "" \
- "\x73\x98\x38\x46\xA7\xAC\x57\x49\x3A\x29\x40\xA6\xB1\xC7\xF6\xC8" \
- "\x43\xA7\x39\x93\x0C\xB6\x05\xD3\x80\x50\x23\x08\xCE\x1E\x0B\x6B" \
- "\xBB\x3F\x75\xCE\x8D\x9D\xF5\x67\xCB\xD3\x28\x29\x1B\x2D\x30\x40" \
- "\xFC\xFA\xA2\x75\xB7\xF5\x02\xC2\x52\x10\x11\x2A\xDA\x47\x21\x20" \
- "\x01\xE9\x92\xD8\x0E\xA7\xB8\x11\x8F\x3D\x2A\xDB\x83\xB1\x05\x48" \
- "\xC4\x57\xF7\x3E\x32\x0A\x8A\xDD\xD8\x2D\x0C\x33\xE1\x36\x8A\x6E" \
- "\xF9\x86\xFD\x46\x50\xE8\x75\x5F\xB1\xA2\x97\xA1\x17\xF9\xBD\x70" \
- "\x98\x9B\xEC\xAF\x88\xC2\xB2\x15\xE0\xFB\xEE\x3A\x8B\x7B\x39\xAE" \
- "\xC9\x35\x9D\x58\xCB\x24\x35\xE4\xC4\x49\x1C\x35\x89\xE6\xE6\xE7" \
- "\xF6\x0E"
-
-/* DL160 modes... */
-
-/** Screen mode 1600x1200 (at 60 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1600_1200_60_24_0 "" \
- "\x3C\x79\x81\x0F\xF2\xAB\x85\xC7\x3A\xE8\xEB\xCB\xF3\x32\x12\x9C"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1600_1200_60_24_0 "" \
- "\x85\x2C\x9A\xF4\x29\x03\x6E\x4C\x58\x8D\xE3\x93\x40\x23\x71\xD2" \
- "\x52\xA1\x70\x77\x9D\x48\x00\xDC\x93\x3C\x5C\x80\xBF\x3F\x0F\xF8" \
- "\x5F\x72\x48\x38\x23\x69\xA7\x4A\x1D\x8D\x8E\x55\x66\x77\x27\xBF" \
- "\x80\x35\x55\x7A\x9A\x40\x9A\xDD\x2F\x12\xB1\xFD\x85\x0F\x43\x23" \
- "\xE5\x36\xE8\x05\x2B\x69\x48\x1E\xB8\x52\xF2\xFF\xB7\x02\x23\x0A" \
- "\x8D\x74\x36\xFB\xAF\x5B\x8B\x2D\x40\x92\x09\x17\x15\xAE\x4E\xFF" \
- "\x0F\x9D\xD7\x9E\x22\xA4\xE0\x87\x6F\x70\x66\x58\xFF\xAA\xEB\x8B" \
- "\xFA\xB3\xEF\x84\x49\xF0\x10\xE7\x3E\x6F\x4F\x24\xFB\x43\x7D\x3B" \
- "\x4C\xD4\xEA\x75\xFA\xF5\xB7\xFF\xD1\x9B\x39\x77\xD9\xA6\xE1\x5E" \
- "\x0B\x20"
-
-/** Screen mode 1920x1080 (at 60 Hz, 24 bpp).
- */
-#define DLO_MODE_ENABLE_1920_1080_60_24_0 "" \
- "\xC1\xCA\xC3\xB3\x75\x48\x7A\xAF\x30\x65\x7B\x24\x97\x8D\xC0\x64"
-
-/** Mode data.
- */
-#define DLO_MODE_DATA_1920_1080_60_24_0 "" \
- "\x0D\x58\x81\xE3\x3E\x98\x55\x00\x24\x27\x6C\x99\x39\xC8\x72\xD8" \
- "\xBB\x8E\x1E\xA2\xCA\x92\xD2\xAB\x59\x06\xE0\x65\xAA\xB5\x9D\xAC" \
- "\x2C\xB5\xDA\x17\x17\x2D\xBE\x19\x8B\xCA\x76\x3D\x8E\x3A\x96\x8F" \
- "\x59\xF1\xD1\xA6\x75\xD1\xAE\xB7\x59\xA9\x60\xA4\x56\x56\x39\x8E" \
- "\x90\xC3\x80\x58\x0E\x9A\x77\x00\xF8\xE4\x24\x74\xDE\xF6\x29\x34" \
- "\x94\x09\x17\x73\x74\xC8\xF6\xC0\x38\x05\x32\xD7\xC9\x73\xF1\x99" \
- "\x53\x4F\x1B\x04\x23\x80\x6F\x08\x79\x05\x22\x2F\x3D\xC8\x17\x9D" \
- "\x69\x61\x8C\x96\x22\x28\x7C\x4F\x5F\xA6\x7D\xF1\x30\x38\x36\xFE" \
- "\x1B\x75\xA7\x2C\xDF\x7D\x17\x33\x7E\x9F\xF3\xFC\x0A\xDC\xB3\xDB" \
- "\xB2\xE0"
-
-/** Data to send after a mode change.
- */
-#define DLO_MODE_POSTAMBLE "\x57\xCD\xDC\xA7\x1C\x88\x5E\x15\x60\xFE\xC6\x97\x16\x3D\x47\xF2"
-
-/** Number of entries in the @a dlo_mode_data array.
- */
-#define DLO_MODE_DATA_NUM (35u)
-
-/** Lowest mode number supported by the DL120.
- */
-#define DLO_DL120_MODES (2u)
-
-
-#endif
+/** @file dlo_data.h
+ *
+ * @brief Hard-wired screen mode-related data blocks.
+ *
+ * DisplayLink Open Source Software (libdlo)
+ * Copyright (C) 2009, DisplayLink
+ * www.displaylink.com
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by the Free
+ * Software Foundation; LGPL version 2, dated June 1991.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef DLO_DLODATA_H
+#define DLO_DLODATA_H /**< Avoid multiple inclusion. */
+
+
+/** Screen mode 640x480 (at 60 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_640_480_60_24_0 "" \
+ "\x79\x7C\xAD\x97\xAD\xFE\x4B\xDE\x1A\x2F\xA2\x94\x2C\xD5\xD3\x5C"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_640_480_60_24_0 "" \
+ "\xE5\xDF\xC0\x52\x4F\xE1\xE6\xB4\xE3\xED\xC4\x21\x5E\x56\xC2\x53" \
+ "\x35\x1C\xE8\xF2\xDF\xEF\x7F\x37\xF5\xA5\x4B\x56\xEB\xED\x34\x7B" \
+ "\xFB\x89\xA3\x17\xE4\x69\xFF\x39\xD2\xAE\x09\xB6\xC0\xBE\x4D\xBC" \
+ "\x84\x6D\x99\xDA\x6B\x28\xBD\xE1\x0E\xC2\xDD\xB0\xDB\x63\xAE\x27" \
+ "\x17\x9C\xD6\xD8\xCC\xC5\x44\xFD\x1C\xEF\x49\x9B\xE8\x69\x69\xCA" \
+ "\xA5\x9E\xC5\x6B\xF9\x71\xC1\x1B\x8F\x8C\x41\x6B\xC4\xBE\x2A\x6F" \
+ "\x56\x82\x37\xC8\x83\x92\x27\x20\x08\x62\x76\x24\x41\xEE\x38\x33" \
+ "\x20\x5C\xAA\xA7\x04\x95\xFA\x8F\xE9\xBA\xEE\xD4\x6C\x8F\x82\x42" \
+ "\x4E\x0F\xB3\xFC\x5D\x25\x9D\x33\xB4\x6F\xBF\x54\xB7\xEB\x16\xF3" \
+ "\xE9\x7C"
+
+/** Screen mode 640x480 (at 73 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_640_480_73_24_0 "" \
+ "\xA7\xA6\x78\x54\xA4\xC3\x33\xBF\xF3\xD5\x53\x1F\xAA\x27\x7B\x91"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_640_480_73_24_0 "" \
+ "\x61\x1A\x38\x7B\x68\x45\x20\x90\x34\x5D\x1D\x6C\x9D\xC4\xA6\x0E" \
+ "\xA3\xEA\x7F\xD9\x70\xAD\xE5\x53\xBE\xB4\x0B\xEC\xB5\xE4\xA1\xAC" \
+ "\x5D\x7D\x06\x9A\x97\xE8\x3D\xFC\x7E\x81\x02\x07\xB1\x30\xC1\xAB" \
+ "\x9C\xC3\x08\xEA\x79\xAA\xBD\x8F\xC1\x2B\xAA\x69\xD5\x17\xF3\x60" \
+ "\x3B\x9F\x86\x86\x2C\x88\x02\x3F\x60\xF4\xA9\xFC\xD6\x8D\x41\x2E" \
+ "\xDE\x64\x6F\xA2\x1F\x33\xB2\x76\x95\xF9\x89\xCC\x71\xEC\x00\x5E" \
+ "\xFC\x9F\xC6\x32\xE3\xAB\x8D\xCA\xC6\x3D\xC9\x4E\xD2\xD5\x83\x7B" \
+ "\x2F\x0C\x78\xE7\x3E\xE3\xEE\xD6\xCB\x95\x54\x02\x83\x46\x01\x78" \
+ "\x1B\x33\xF7\x12\x47\x16\x05\xAF\x99\x56\x87\xF9\xFA\x3F\x93\x0C" \
+ "\x79\xA6"
+
+/** Screen mode 640x480 (at 75 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_640_480_75_24_0 "" \
+ "\xBC\xD1\x26\x61\x95\x59\x20\x88\x2E\x73\xA7\xD9\x9A\x22\x6A\xFB"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_640_480_75_24_0 "" \
+ "\xAA\xCE\xFB\xD4\xC3\x07\xC1\xBF\xAD\xA3\xEF\xA9\x2B\x77\xBD\x5D" \
+ "\x03\xBE\x67\xF4\x99\xA1\xA3\x53\x25\x5B\x50\x6D\x0C\x3A\xA7\x4C" \
+ "\xB0\x86\x04\x60\x01\x8C\xED\xBC\x5A\xF9\x3A\x0E\x1B\x10\xFF\x55" \
+ "\x8B\x23\xAC\xDE\xEA\xB2\x2E\x8B\x02\x4E\xF1\x67\x9C\x85\x5D\x3B" \
+ "\xE1\xC1\xAC\x3B\x26\xE2\xC3\x13\x25\xF4\xCC\xBC\xF0\xD9\x1F\x27" \
+ "\x0C\xF0\x42\x6C\x18\x3B\x20\xC6\x29\xD7\x6C\x0A\x4B\xDC\x44\x3C" \
+ "\x46\xDB\x6E\x78\xEB\xAB\x7A\xF5\x63\xE2\xAD\x77\x03\xA0\x9F\xCB" \
+ "\x22\x4D\x03\x66\x0B\xF8\xE7\x26\xA4\x15\xF4\xF9\x13\xE7\x14\x97" \
+ "\xF1\x98\xD0\x8B\x4E\xDB\xA5\xC6\x4E\x74\x19\x2C\xB2\x97\x55\xA4" \
+ "\x0E\x61"
+
+/** Screen mode 640x480 (at 85 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_640_480_85_24_0 "" \
+ "\x6D\x0D\x6A\x02\x66\x8A\x8A\x94\xFD\x31\x6D\x98\x53\xD7\x93\x25"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_640_480_85_24_0 "" \
+ "\xC6\x8C\x42\x4C\x95\xDA\xB4\x2F\xBD\xD9\x9E\x7C\x8F\x7B\x69\xA8" \
+ "\x1B\xDA\x06\x96\x23\x9E\x94\xE2\xC2\xE9\xBB\xD3\x13\x6B\x9B\x21" \
+ "\xC1\x4E\xD8\x3F\x81\x49\x6E\xD1\xAF\xB2\x4E\x8C\x24\x1A\xA8\xB6" \
+ "\x4E\x11\x75\xB3\xE6\xC9\x3D\x36\x9A\xCC\x3B\xAA\x1F\xC4\x97\xD5" \
+ "\x4A\x9D\xAA\xE0\x04\xF0\xB6\x2C\xBD\xE4\x41\x19\xF8\xA2\x77\x7C" \
+ "\x46\x9D\x3A\xBD\x73\xC0\x64\x70\x84\x2B\xD7\x11\xF3\x43\xB5\xFB" \
+ "\xE9\x0B\xB3\x4B\x2B\x80\x98\xEF\xDC\xDA\x46\xD6\xEC\xBD\x0B\x4D" \
+ "\x64\x20\xF7\x17\x17\x33\x75\xB5\x30\x26\xDD\x0A\xA0\x99\x23\x11" \
+ "\xF1\xDE\x80\xB0\xD6\xB0\xB7\x5A\xA9\xBD\x6D\x29\x42\x74\x75\x73" \
+ "\xC5\x27"
+
+/** Screen mode 720x400 (at 70 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_720_400_70_24_0 "" \
+ "\x9C\xC5\x1C\x02\x4F\xA6\x97\x4D\xD7\x04\xE5\x2A\xDC\x78\x4F\x24"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_720_400_70_24_0 "" \
+ "\xC4\x2C\x84\x13\xDD\xB8\x82\xCB\x62\xA3\x40\xFA\x41\x8B\x5E\x1B" \
+ "\x74\x02\x11\xDD\x90\xB8\x14\x51\xE1\x28\x7E\x3B\x42\x6A\x6B\x9C" \
+ "\x7E\x4B\xFC\x8A\x19\x8D\xF4\x23\xB4\x98\x96\x55\x68\x8F\xDA\x88" \
+ "\x9C\xE0\x20\x5D\xB5\x9F\x34\x9B\xB2\xCF\x10\x6B\x2D\x66\x63\x0B" \
+ "\xDE\x3C\xC4\x90\x3C\xB4\x23\xF9\x5C\x93\x6F\x43\x29\x20\x54\x90" \
+ "\x94\xB8\x78\xED\x33\xC7\xDD\x8B\xAA\xD0\xF6\xDC\x78\xEB\x50\x23" \
+ "\x83\x00\x6F\x42\x83\x58\xD7\x1C\xA0\xDF\x41\x9E\x69\xB5\xA4\x3A" \
+ "\x31\x79\xCB\xDF\x59\x5E\x76\xFB\x89\x32\x2B\x00\xE5\xDF\x16\x52" \
+ "\x4F\xE1\xCC\xB7\xE3\xED\xEE\xC1\x5E\x56\xDF\x4E\x35\x1C\x14\x99" \
+ "\xDF\x6F"
+
+/** Screen mode 720x400 (at 85 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_720_400_85_24_0 "" \
+ "\x4E\xEB\x46\x9D\x91\xDD\xEA\x68\xE2\xCF\x92\xBE\x47\xE1\xE2\x7C"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_720_400_85_24_0 "" \
+ "\xE6\x20\x16\xD8\xFE\x44\x88\xBF\x44\x7B\xBE\x98\xA3\xC9\x56\x4E" \
+ "\xBC\x98\x6B\x8B\xCD\x50\xB0\xB8\x4D\x95\x32\xF7\xB8\xDE\x45\x3D" \
+ "\x87\xD4\x13\xBF\x42\xE6\xC5\x86\x4E\x9D\xD7\x11\xD6\x1F\x1E\x11" \
+ "\x55\x5E\xD5\x2E\xFE\x02\xD4\xB0\xDC\x10\xA0\x45\x44\x00\x2E\x0B" \
+ "\x4C\x7B\x47\x1B\x06\x16\x20\x18\x6D\xED\x65\xC9\xC0\x11\xDD\x76" \
+ "\x78\x8E\x2D\x5D\xD7\x5E\xF7\x6E\x17\x75\x14\x74\xA8\x4D\xFC\x6F" \
+ "\x47\x50\x69\x15\x01\x3D\x92\xF5\x1D\xF6\x03\x4A\x89\xC5\x2D\x1E" \
+ "\x3A\xBB\x25\x83\x3A\xFD\x72\xBD\xA2\x96\x61\x84\x45\x5F\x19\x21" \
+ "\xB5\xBC\x3A\xF4\x7E\xFA\xBF\x0A\x5E\x82\xC8\xF6\x26\x4D\xA4\x06" \
+ "\xD9\x97"
+
+/** Screen mode 800x480 (at 60 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_800_480_60_24_0 "" \
+ "\x7A\x12\x36\x0B\xEF\x21\x74\xD1\xF0\x06\x8F\x38\xE8\x71\xB4\xCE"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_800_480_60_24_0 "" \
+ "\x78\x67\x19\xF3\xB3\xD6\x5D\x7B\x4C\xCA\x26\x78\x41\x19\x19\xAC" \
+ "\xFF\x38\xB3\x10\x71\x89\x6A\xEC\xA8\xC1\x4F\x1F\x77\x86\x5D\x7E" \
+ "\xCE\xAF\x65\x7D\xFC\x30\x51\x67\x1F\x48\x30\x8E\x7A\x4B\x8A\xD4" \
+ "\xCB\x62\x45\x58\x5C\x22\x1D\x56\x6E\x2F\x60\xE2\x06\x6D\xA1\xE3" \
+ "\x82\x5F\x67\x95\x7A\x9F\x87\x43\xD8\x33\xEF\x0B\x5A\xDA\x09\x4F" \
+ "\xD7\x25\x6F\xBC\xF8\xC7\x09\x9C\x12\xC3\xA7\x6F\xE7\xED\xA8\x70" \
+ "\x8C\xB9\x65\x53\xDD\xA6\x7D\xDE\xD9\x4F\xDD\xD4\x6F\x28\xD6\x14" \
+ "\xDC\x2D\x41\x53\x33\xD9\x0A\x86\x11\x3C\x41\x5A\x56\x48\xF9\x85" \
+ "\x2B\x2F\x22\x66\x20\x39\xDA\xA1\x50\xCB\x5A\x58\x7D\x97\xFA\x2C" \
+ "\x64\x9D"
+
+/** Screen mode 800x600 (at 56 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_800_600_56_24_0 "" \
+ "\x19\xFC\x59\x09\x1D\xCD\xDA\x0D\xD3\x6A\x45\xBB\xDB\xF9\x8A\x57"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_800_600_56_24_0 "" \
+ "\xD7\x63\xD3\x78\x60\xAC\x0F\xFE\xF5\x0A\xC7\xF0\x17\x0E\x9C\x6C" \
+ "\x47\xFF\xF5\x36\xFD\xDE\x22\xE6\xA1\x80\x4F\x0D\x90\x72\xE6\xAD" \
+ "\x49\x95\x4B\xD4\x6A\x31\xF9\x6E\x6F\x6E\x93\xF5\x44\x46\x7A\x84" \
+ "\xD4\x10\x51\x7A\xE1\xDF\x48\x32\x9D\x0E\x59\xD9\x0B\x57\x45\x7C" \
+ "\x58\xF6\x72\x8D\xAF\x91\x7F\xBE\xE8\x2F\x3A\x7F\x3D\xF5\xD6\x39" \
+ "\x1E\xB8\xB2\x1D\x7F\x6F\x60\xBC\x0F\xF8\xAD\x43\x76\xFA\x75\x19" \
+ "\xFB\x5D\xA4\xCD\xF7\x38\x5F\x11\xD4\x56\x11\x9E\x79\xB4\x4A\x4D" \
+ "\x7A\xC7\x03\xAC\xFB\xB4\x4F\x98\x93\xB0\xDC\xE2\x8F\xE9\x05\xB2" \
+ "\x90\xE0\x8D\x41\xC2\xAF\xC5\xEE\x8B\x00\x90\x7C\x26\x87\x54\x4A" \
+ "\x71\x2A"
+
+/** Screen mode 800x600 (at 60 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_800_600_60_24_0 "" \
+ "\x02\x18\xF5\x1F\xE5\xCF\x2C\xB9\x39\x72\x74\x15\x6B\xFE\x6C\x71"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_800_600_60_24_0 "" \
+ "\xC0\x2C\xFF\x8C\x0F\x57\x30\xD7\x8A\x19\xCE\xB2\x47\x2B\xE3\xFA" \
+ "\xEE\x8F\x95\xF7\xA7\x78\x44\x39\x29\x78\xF4\x0C\xB7\x3F\xF8\xD4" \
+ "\xFA\xAD\x2C\xB8\xF2\x1C\xBB\x16\x10\xCC\xF5\xD5\x53\x6C\x2E\x4E" \
+ "\xEF\xB5\xF5\x81\x0A\xE1\x8F\x32\xC5\xB9\x96\xAB\x8C\xC2\xE3\xA7" \
+ "\x32\x14\x76\xD5\x63\xC1\x8E\xD6\xCF\x95\x1B\x0C\x51\xA9\x88\xEB" \
+ "\xF3\x89\x40\xB7\x41\xB6\x87\x10\x03\xDB\x09\xFE\xCD\xFF\x2A\x7C" \
+ "\xB1\x76\x8C\x27\x04\xA8\x09\x3B\x9E\x63\xDE\xE0\x31\xC8\x9B\x5E" \
+ "\x1E\x51\x5A\xB3\x1B\xE7\xEE\xAE\x54\x47\xBB\xF0\x9F\xAE\xBB\xF6" \
+ "\x43\x35\x57\xAE\x87\x8C\x88\x8B\x61\x61\x47\xA9\x87\xF7\xC3\x86" \
+ "\x8E\x53"
+
+/** Screen mode 800x600 (at 72 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_800_600_72_24_0 "" \
+ "\x81\x59\xC0\x67\x29\xEC\x20\x62\x5E\x94\x77\xCA\x93\xE3\x3B\xA5"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_800_600_72_24_0 "" \
+ "\x3B\xD9\x26\xBF\xB4\xE3\x00\x22\x87\x3D\xCD\xDE\x26\x6E\x71\x13" \
+ "\x15\x22\xFB\xA0\x3F\x4B\xE1\x33\xED\x36\x15\x71\x8E\xB6\x3A\xE5" \
+ "\x69\x27\xF8\x8E\xBA\x43\x42\xC3\xB8\x6F\x25\xCD\xC0\xDB\x35\xE6" \
+ "\xD0\x33\x02\xF8\xFF\x05\x73\x60\x06\x50\x6D\xB0\xF5\x86\x68\xC3" \
+ "\x27\xD8\xB4\x63\x88\x6D\x0E\x55\x1C\x18\x76\xDF\x37\x0D\x50\x62" \
+ "\xD0\x82\x75\x66\xB8\x0A\x40\x2D\x94\x85\xB1\x04\x44\x1E\xD1\xCA" \
+ "\xF7\x97\xD8\x21\x28\xB5\xBE\x91\xC5\xC2\x1F\x48\x63\x70\xED\x4F" \
+ "\x88\x9A\x02\xD0\xC3\x7C\x7A\x6A\x42\x11\xD7\xEA\x91\xF9\xCE\xAC" \
+ "\xA3\x03\x8E\xBE\x14\x25\x74\x4B\xE5\x0B\x37\xEA\x5C\xB0\xA9\xD5" \
+ "\xE5\x95"
+
+/** Screen mode 800x600 (at 75 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_800_600_75_24_0 "" \
+ "\x3F\xDB\xEE\x68\xC7\x0E\xCA\x26\xA3\x42\xF0\x36\x25\x2B\xDB\x48"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_800_600_75_24_0 "" \
+ "\xB5\x2E\xA8\x75\xF5\xC0\x36\xD8\xBF\xB3\xA8\x4F\x6F\xA4\x68\x06" \
+ "\xEC\xFB\x44\x53\xFC\x4B\xC2\x44\xF0\xFA\x20\x47\xC0\xC5\xDE\xB1" \
+ "\x6B\xDF\x89\x24\xD1\xA6\xE1\x86\xAE\x7F\x19\xA5\x56\xE7\x52\xBC" \
+ "\xD7\xCC\xAF\xED\x9C\x4F\xAF\x77\x49\x7C\x99\xA9\x0E\xB9\x41\xAE" \
+ "\x34\xD1\xB3\x33\xAD\x12\x91\xFC\x6C\x78\x85\xD5\x91\x6B\xB2\x1E" \
+ "\x28\x39\x15\x41\xF5\x14\x35\x9E\xAC\xE2\x0C\x9C\x69\x5C\x76\x86" \
+ "\x55\xF1\x41\x36\x02\xE1\x6C\xAA\x60\x66\xE4\x1F\x5D\xB7\xED\x16" \
+ "\x3F\x55\x21\x57\x56\xDA\xB3\x00\xA0\x15\x8F\x26\xC1\x08\xA6\x8B" \
+ "\x19\x22\x5E\xD2\x48\x7B\x18\xA6\xD4\xF9\x9D\xD4\x85\x57\x05\xD9" \
+ "\xC6\x31"
+
+/** Screen mode 800x600 (at 85 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_800_600_85_24_0 "" \
+ "\x51\x11\x2B\x19\x1F\xF6\x3F\xC2\x38\x2F\xF8\x5D\x5A\xD3\xA6\x0D"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_800_600_85_24_0 "" \
+ "\x87\x1E\x1B\x28\xEA\x5B\xFA\xAB\x66\xC6\x43\x53\xC7\x3A\x77\xF4" \
+ "\x08\x95\x51\x50\x9E\x8A\x19\x38\x55\x40\x3C\x31\x45\xEE\x59\xBA" \
+ "\xF2\xB3\x3C\xFD\xEC\x2F\x58\xED\xEF\x1A\x7F\xDB\xF6\x02\x25\xCA" \
+ "\x79\xCF\xC2\x7C\x95\x75\x30\xBB\x41\x3A\x3E\x27\x33\x0D\x37\x48" \
+ "\x02\x6D\xDB\x86\x50\xB0\xCA\xAA\x92\x25\x08\xB7\xDE\x93\x51\x87" \
+ "\xC0\x57\x8C\xA1\xE0\xE5\x38\xC1\x30\x97\x82\x6B\xE7\x96\x37\xA5" \
+ "\x63\x0B\x79\xB8\x67\x28\x25\x60\x79\xF2\x1D\x98\xE2\xAC\x2E\x1B" \
+ "\x1C\x7D\x3C\x9B\x63\x53\xFD\x73\x44\xAF\x8D\xDE\xB0\x98\xCD\x6E" \
+ "\xBA\x60\x48\xC2\x74\x5A\x8E\x9A\xB3\x3F\x9A\x2B\x28\x42\x66\x93" \
+ "\x1A\x26"
+
+/** Screen mode 848x480 (at 60 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_848_480_60_24_0 "" \
+ "\x06\x53\xBC\x25\x49\xFB\xE8\x81\x2A\xE0\xDF\x85\xB4\x85\x92\x4C"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_848_480_60_24_0 "" \
+ "\x27\x9E\x14\x5B\x10\x06\x0C\xE8\xFB\xD1\x12\x84\xC7\xEE\x60\x2E" \
+ "\x1B\xC4\xE1\xE0\x98\x72\x13\xE1\xEC\x4A\x2D\xC2\xBB\x44\xEB\xCC" \
+ "\x62\x2F\xE6\xC1\x71\x5D\x71\xD9\xBB\x90\xF3\xCC\x71\x7E\x5B\x71" \
+ "\x77\xA5\x78\xCF\x02\x9A\xE7\xDF\x8F\xD4\xEE\xCF\xE7\x39\xA7\x75" \
+ "\x9F\xE8\xCD\xCE\xDB\x5E\x7F\x61\x60\x45\xC6\x97\x91\x82\x6A\xFD" \
+ "\x4C\xB1\xAB\xAA\xAE\xAB\x13\x92\x45\xB6\xFD\x8F\xD1\x34\xB8\x34" \
+ "\x25\x45\xA5\xD7\xB7\xD6\x3E\x05\x9E\x25\x8E\xC5\xA9\xA3\x89\xC7" \
+ "\xF9\x98\x2E\xB6\xEB\x04\xCE\x79\x9F\x01\x3F\x3C\xBF\xD6\xF8\xDA" \
+ "\x3B\xFA\xDB\xA1\x78\xD6\xA2\x3D\xF4\xD9\x69\x37\xDE\x1F\x1C\x70" \
+ "\xF0\x01"
+
+/** Screen mode 1024x768 (at 60 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1024_768_60_24_0 "" \
+ "\xB6\xF8\xFC\x00\xF3\xE4\x81\x1E\xC5\x60\xA3\x79\xE5\x35\xC5\x15"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1024_768_60_24_0 "" \
+ "\xDD\x2A\x3A\x49\xE9\x99\xE3\xC8\xA0\xBA\x23\x3A\x3D\xEB\x21\xE4" \
+ "\xA5\x54\x25\x0D\x51\xCC\xE6\x52\xA7\xD7\xCD\xFA\xD5\x9B\x5B\x41" \
+ "\x0B\x49\xAB\xC6\xE3\x1A\xF2\x87\x81\x32\xF0\x3E\x40\x00\x51\x40" \
+ "\x9E\x94\xF1\x22\xEE\xAC\xB2\xA2\x6B\x4D\xC4\x41\x5A\x9C\x45\x62" \
+ "\x4F\x4E\x61\xDB\x1F\x0E\x79\x66\xE2\x20\x83\x9E\x2C\xAB\x28\x38" \
+ "\xAC\xC1\x22\x81\xA5\x69\xFD\xFB\x26\x15\xF9\xC9\xFA\x90\xF2\x66" \
+ "\x85\xC5\xAA\xA6\x4D\x8B\xC8\xA6\x03\x32\xDF\x98\xA9\x77\x9E\x57" \
+ "\xEA\xC9\x9E\x29\xED\xFC\xC4\x78\x26\x0B\x2E\xC2\x41\x7C\x4A\xA3" \
+ "\xAB\x66\x01\xA0\xE5\xA4\x8B\x80\xA0\x53\xE5\x5D\x59\x63\x62\xE8" \
+ "\xFE\x6B"
+
+/** Screen mode 1024x768 (at 70 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1024_768_70_24_0 "" \
+ "\x2B\x71\x0C\x1F\x55\x8E\x3D\x1A\xEE\xE0\x93\xD4\x15\x58\xE9\x00"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1024_768_70_24_0 "" \
+ "\xE9\x15\xBC\xBE\x90\x6C\x07\x34\xF2\x79\xCA\x43\x44\x92\x65\x9A" \
+ "\xC7\x41\xE9\x56\xE7\x27\x4A\x9C\x24\x04\x40\x97\xF5\xFD\xFF\x99" \
+ "\xC8\x6A\xA0\xF3\x32\xE3\x4E\x40\xBC\xA5\xAE\x37\xBA\x89\xB0\xDD" \
+ "\x10\xD2\x10\x76\xE8\x80\xAF\x15\xC1\x16\x65\x80\xA2\xCE\xFD\x14" \
+ "\x66\xD8\xAA\x83\x7C\xD6\xE2\xF2\x26\x36\xD5\xF2\x36\xA5\x7F\x4D" \
+ "\xF6\x21\x14\x58\xB5\xFA\x54\x07\xE6\x91\x93\xB9\xB9\x4B\xB5\x0C" \
+ "\xD6\xAE\x6C\x2D\x12\x51\xED\x13\x6C\xD7\x07\x15\x6D\x88\x10\x62" \
+ "\x94\x4F\x77\xB7\xEC\xA3\xD4\xAD\xDF\xCC\x76\x2D\x39\x90\xEE\xB1" \
+ "\x98\x09\xA2\x28\x03\xF8\x1F\x1C\x01\xCA\xAA\xC0\xC2\x92\xDE\xD8" \
+ "\xFC\x59"
+
+/** Screen mode 1024x768 (at 75 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1024_768_75_24_0 "" \
+ "\x10\xFC\xF8\x65\x8A\x35\x80\x78\x15\x13\x4C\x2A\x6C\x35\x2B\x74"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1024_768_75_24_0 "" \
+ "\xE6\xB2\x51\x5B\x75\x7E\x2A\xBC\xA5\x4A\xC0\xC0\xEA\x20\x67\xCC" \
+ "\x89\x74\x5D\x3B\x7D\xB4\x29\x82\xA8\x28\x97\x86\x13\x0E\xE3\xCC" \
+ "\x95\x10\x43\x65\x15\x64\xA0\xF9\xA7\x20\xFE\x61\x0A\xFF\x6E\xEC" \
+ "\x7E\x55\x17\x4F\xA2\x61\x77\x7E\x9A\x3B\x04\xFF\xC0\xA0\xAE\x82" \
+ "\x3F\x81\x1A\xEB\x45\x8B\x37\x99\xA6\xED\xB1\x66\x78\x02\x8C\xB3" \
+ "\xE7\x88\xD5\x57\xD8\xE7\xFD\x7F\x49\x8B\xBE\xC6\xD1\xDD\x60\xB5" \
+ "\x41\xCD\x1B\x3E\xEC\x69\x18\xE9\x77\x71\x7F\x0E\x11\xCB\x47\x82" \
+ "\x89\x2C\xCA\x54\x5E\x33\x9C\x60\x61\x42\x55\xB4\x4B\xC2\x9C\x37" \
+ "\xFD\x37\xD4\x47\xC5\x08\xDF\x14\xCB\xCD\xD9\xCD\xA0\xC1\x42\x21" \
+ "\xD2\xD9"
+
+/** Screen mode 1024x768 (at 85 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1024_768_85_24_0 "" \
+ "\x02\x10\x92\x8C\x45\x12\x05\x5A\x25\x51\x85\x91\x87\xB0\x05\x8C"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1024_768_85_24_0 "" \
+ "\xA7\xC9\xD0\x6E\x6E\x77\xDA\xD3\x25\xEA\x3B\xA4\x4B\x35\x88\x4E" \
+ "\x22\x53\xC4\x82\xB0\x14\x40\x54\x8A\xB6\x42\xF2\xBB\xC8\x4B\x24" \
+ "\x52\xF9\xC3\x37\xBE\xCF\x99\x01\x5A\x56\xB2\xA8\xE7\xF3\x53\x7B" \
+ "\x37\x55\xFE\x97\xF3\x05\xFF\xC0\x71\x60\xBB\xD9\xCC\x49\xFA\x73" \
+ "\x2C\x39\x72\x25\x27\xFB\x83\x7D\x44\x58\x86\x5D\x6F\xFC\xCF\xD4" \
+ "\xCF\x7C\xC1\x33\x35\x21\x30\x70\xA8\x36\x60\xBB\xA8\xE2\x74\x05" \
+ "\xBB\xB3\xC5\x60\xBD\x4B\xC0\x6C\x04\x41\xD2\xE6\xFA\xEB\x67\x02" \
+ "\x6A\x77\x82\x4D\xF7\x05\xAC\xA8\xA3\x8F\x21\xCA\x24\xF3\x53\x52" \
+ "\x2A\x99\xEA\xE5\xBD\x76\x3C\x85\x73\x98\xD8\x46\xA7\xAC\xA8\xB7" \
+ "\x3A\xA9"
+
+/** Screen mode 1152x864 (at 75 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1152_864_75_24_0 "" \
+ "\xAE\xFE\x44\xF3\x10\x49\x4E\x35\x9B\xD3\xC7\x22\x83\xCC\xAE\x40"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1152_864_75_24_0 "" \
+ "\x65\xB5\xCB\x8E\x46\x49\x3E\xFB\x60\x91\xC1\x32\x82\xD3\xCA\x2F" \
+ "\x4A\x49\xB1\xA8\x17\xA1\x12\x37\xBB\x1C\x5F\x69\x41\xA8\x72\xB2" \
+ "\xB8\x37\x9C\x7E\xE3\x5C\xA2\xD3\x19\x59\xE2\x75\xA7\xC9\x25\xBB" \
+ "\x6E\x77\xD1\x2D\x25\xEA\x36\x43\x4B\x35\x87\xB3\x22\x53\xC9\xB5" \
+ "\xB0\x14\x4B\x1D\x8A\xB6\x57\x78\xBB\xC8\x5C\x3B\x52\xF9\xD6\x3C" \
+ "\xBE\xCF\x82\xCB\x5A\x56\xAF\x2E\xE7\xF3\x4C\x85\x37\x55\xE3\x91" \
+ "\xF3\x05\xE4\x3C\x71\x60\xAE\xB6\xCC\x49\xEF\x6A\x2C\x39\x61\x75" \
+ "\x27\xFB\xB0\x7D\x44\x58\xB3\x32\x6F\xFC\xF8\xBF\xCF\x7C\xFB\xCC" \
+ "\x35\x21\x0E\x8B\xA8\x36\x5E\xC4\xA8\xE2\x7D\xFC\xBB\xB3\x2D\x9C" \
+ "\xBD\xCB"
+
+/** Screen mode 1280x768 (at 60 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1280_768_60_24_0 "" \
+ "\x73\x9D\x25\x83\xE6\x73\xB8\x81\x46\x7F\xA3\xC9\x4C\x52\x09\xB4"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1280_768_60_24_0 "" \
+ "\xB0\x52\xEB\x22\x12\xDD\x55\x65\x5C\x01\x38\xD9\xA2\x1A\xE6\x1F" \
+ "\x75\x89\x16\x6E\x7A\x2E\xFC\x28\x9F\x3C\xD0\xE6\xC8\x0F\xD9\xCE" \
+ "\x66\xBD\xDA\xE1\x28\x88\x61\x5B\xB2\x1B\x03\x5B\x3E\x37\xD7\x54" \
+ "\xD8\xC4\xCA\xBC\x85\xBE\x2E\x50\xA2\x39\xC1\xB1\xB9\xBC\x92\xA9" \
+ "\x09\xCA\x4D\xFA\x67\x4D\x55\x1E\x2D\xAC\x8C\xBB\x76\x81\xEE\xEE" \
+ "\x14\xEF\xBC\xD8\x4D\xB6\x0B\xB0\x74\xEB\xDF\xDB\xF4\x30\xB8\xF2" \
+ "\xBA\x97\x4A\x67\xAB\x3E\x84\x6B\xC6\x23\x2E\x3A\x69\x39\x04\x67" \
+ "\x01\xAF\xEE\xE6\x96\xCC\x9E\xFF\x68\xF4\x6A\x0F\x73\x52\x1E\x0A" \
+ "\x0F\x11\x4A\xE8\x12\x72\xF6\x0E\xA0\xE2\x8A\xC3\x1E\x6C\x49\xA5" \
+ "\x6C\xBE"
+
+/** Screen mode 1280x1024 (at 60 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1280_1024_60_24_0 "" \
+ "\x6A\xF0\x37\x50\x63\xEF\xD2\xA9\x6F\x75\x72\xBB\xC7\x7B\x6F\x1A"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1280_1024_60_24_0 "" \
+ "\x23\x4A\x78\x7C\xD1\xB8\x0E\x6B\x15\x93\x96\x77\x78\x44\xCC\x16" \
+ "\x7F\xE3\xD7\x39\x3F\x2E\x99\xD2\xB9\x68\x8E\xC4\x1A\x9B\xF4\x35" \
+ "\x61\xB5\x48\x5C\x94\xA6\x84\xB2\x88\x2B\x47\x84\x84\x73\x7F\x2C" \
+ "\xD0\xC4\x3D\x5D\x20\x61\x4A\xB1\x73\x4C\xDD\x6A\xB4\xFD\xE9\x94" \
+ "\x3C\xD1\x44\x0A\x08\xCD\xF5\xE5\xBD\x0D\x99\xCD\x9C\x2A\xC9\x06" \
+ "\x1D\x22\x1C\xB1\x9A\x94\x95\x65\x3C\x43\x19\x73\x83\xF7\x51\x1F" \
+ "\x5C\x3C\xE1\x59\xD5\xC3\xF2\x27\x28\xCE\x22\x7B\x2A\x70\x04\xE4" \
+ "\xD9\xFE\x8A\x6E\x28\x27\xC5\x40\x4E\xF8\x83\x5B\x82\x41\xA6\x62" \
+ "\xC1\x73\x3A\x5C\xF6\x90\x43\x39\xF2\xF5\x74\x80\x74\x44\xBD\xB1" \
+ "\x08\x53"
+
+/** Screen mode 1280x1024 (at 75 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1280_1024_75_24_0 "" \
+ "\xDB\xCF\xE1\x3F\xBE\xB3\xE8\x2D\x29\x5B\xE8\xF0\xD6\x57\x0B\xFF"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1280_1024_75_24_0 "" \
+ "\xBA\x89\x45\x90\x10\xD2\x1B\x50\xE8\x80\xA2\xE9\xC1\x16\x6A\x6D" \
+ "\xA2\xCE\xF0\xD4\x66\xD8\xA1\x18\x7C\xD6\xF7\xD8\x26\x36\xC2\x7E" \
+ "\x36\xA5\x6A\x9A\xF6\x21\x0F\xF3\xB5\xFA\x49\x07\xE6\x91\x8C\x4B" \
+ "\xB9\x4B\xA8\x0C\xD6\xAE\x77\xD1\x12\x51\xF8\x21\x6C\xD7\x12\xED" \
+ "\x6D\x88\x03\x5D\x94\x4F\x44\xB7\xEC\xA3\xE1\x3F\xDF\xCC\x41\x85" \
+ "\x39\x90\xD4\x4E\x98\x09\x9C\xD3\x03\xF8\x21\xE3\x01\xCA\xA3\x39" \
+ "\xC2\x92\x36\x23\xFC\xD9\x99\x08\x7B\xC0\x9C\xCE\x21\xF4\xBA\xBE" \
+ "\x22\x36\x9C\xB4\xE4\x4A\xFB\xC1\x1E\x9B\xAC\xFF\xB3\x5A\xD4\x0D" \
+ "\x7C\x1C\x28\xBB\x8E\x8B\xD8\x8E\x1E\xFE\xEE\xD9\xE7\x04\x99\x20" \
+ "\xE8\xB1"
+
+/** Screen mode 1280x1024 (at 85 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1280_1024_85_24_0 "" \
+ "\xE4\xE9\xAF\xA2\x9D\x98\xD0\xC6\xF3\xB8\xB6\xC9\x10\xC1\xC8\xA6"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1280_1024_85_24_0 "" \
+ "\x93\xB0\x06\xA2\x8F\xE9\x2C\xB3\x90\xE0\xA6\x66\xC2\xAF\xEC\x00" \
+ "\x8B\x00\x8C\x0B\x26\x87\xAF\x8A\x71\xAA\x43\x0F\x64\xF4\xC5\xF3" \
+ "\x04\x62\xE6\x7A\x36\xDE\xFA\x1A\x19\x93\x12\xD1\x0F\x74\x12\xAF" \
+ "\x46\x2C\x4D\x23\x34\xCF\x57\x3B\x16\xFE\x0B\xDC\x42\xDB\x0C\x80" \
+ "\x39\x44\xDF\x0C\x8B\x58\x28\xB3\x05\x00\x2F\xB9\xB8\xC0\xB6\xA1" \
+ "\x3C\x38\x80\xA1\x6C\x45\x4F\xF1\xE6\xB2\xBB\xA4\x75\x7E\x3C\x44" \
+ "\xA5\x4A\xD6\x28\xEA\x20\x7D\x78\x89\x74\x45\x97\x7D\xB4\x31\xB5" \
+ "\xA8\x28\xB1\xB0\x13\x0E\xC1\xCC\x95\x10\x61\x62\x15\x64\x81\x4A" \
+ "\xA7\x20\xDD\x3A\x0A\xFF\x4F\x39\x7E\x55\x03\xB0\xA2\x61\x84\x7E" \
+ "\x9A\xBB"
+
+/** Screen mode 1280x768 (at 75 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1280_768_75_24_0 "" \
+ "\x87\x94\x88\x24\x2C\x58\xEA\x1F\x10\xA1\xE9\x20\x62\xB1\xC6\x43"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1280_768_75_24_0 "" \
+ "\x20\x5C\x76\xA7\x04\x95\xDE\x8B\xE9\xBA\xCA\x66\x6C\x8F\xA9\x5B" \
+ "\x4E\x0F\x9A\xCA\x5D\x25\xB2\x6C\xB4\x6F\xA5\xE4\xB7\xEB\xEF\x58" \
+ "\xE9\xFC\x9C\xD2\xF4\xE4\xB1\x47\xA9\xC6\xE4\xF6\xAD\xC6\x9C\x38" \
+ "\x7F\x29\x2F\x59\x97\x93\xA6\x07\x91\x33\x1A\x1F\x0B\xBE\x9D\xE7" \
+ "\x3C\x7E\xCC\x60\xF4\x2E\x59\x92\x01\x7B\xCB\xB2\x85\x9D\x18\xA7" \
+ "\x6E\x0C\x56\xFF\xCA\x58\x32\xAB\xF1\xBB\xC7\x6B\x82\xEE\x11\x9C" \
+ "\x3D\x90\xAB\x2D\x4A\xE6\x22\x30\xEB\x42\xA1\xA6\x07\x6A\x14\x4F" \
+ "\x58\x1F\x86\xDF\xCB\x19\xF5\x7F\xB3\x90\x28\x41\xD4\xA1\x1C\x1B" \
+ "\xA6\xD0\x45\x85\x0F\xDB\xBB\xA1\xBA\xCF\xF5\xAB\x88\xB9\xF6\x32" \
+ "\x0F\xC9"
+
+/** Screen mode 1280x768 (at 85 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1280_768_85_24_0 "" \
+ "\x74\xE4\x58\xA1\x3C\x43\xC0\x4D\xE4\xA9\x6D\x46\x5B\x34\x89\xE5"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1280_768_85_24_0 "" \
+ "\x5B\xA6\xDC\x6E\xE2\xD7\xAD\xE3\xF3\xCF\x02\x6D\xD9\xDD\x83\xEB" \
+ "\xE4\x12\x6B\xC6\x3D\x1C\x18\x54\x7A\x30\x1A\x0C\x24\xD0\x54\x05" \
+ "\xE6\xAC\x4E\x76\xCE\x92\xA5\x1D\x8B\xE9\x5E\x53\x42\x0F\x1F\x9C" \
+ "\x2A\x15\x6B\xB1\x8D\xA0\x3E\x8E\xBC\x0A\x22\xB2\x46\x6A\x18\x18" \
+ "\xAC\xA4\x46\x5D\xF1\x37\x62\xE3\xB2\x38\x33\xFD\xF2\x02\x46\xF2" \
+ "\xAB\x20\x68\x60\x7D\xCF\xA6\xE3\x47\x9A\x9B\xA7\xA9\x80\xAB\x54" \
+ "\x35\xAD\x93\xFB\x98\xE0\x48\x7D\x67\x70\x91\x3B\x5A\x75\x8F\x97" \
+ "\x2B\xC6\xF3\x34\x44\xB1\x6B\x60\x0B\x74\x46\x54\x94\xC3\xDD\xC0" \
+ "\xDC\x75\xFF\x99\x10\x5E\x90\x26\xD8\x56\x99\x1E\x0E\x84\x7F\x8B" \
+ "\x43\x88"
+
+/** Screen mode 1280x800 (at 60 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1280_800_60_24_0 "" \
+ "\x59\xFF\xC3\x96\x42\x84\xE3\x26\x2D\x50\x6C\x88\x84\xF6\x6E\x2A"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1280_800_60_24_0 "" \
+ "\x55\x5E\x21\x5E\xFE\x02\xD8\x84\xDC\x10\xAC\xF6\x44\x00\x22\x46" \
+ "\x4C\x7B\x4B\xCC\x06\x16\x34\xFC\x6D\xED\x71\x58\xC0\x11\xC9\xA4" \
+ "\x78\x8E\x39\xC3\xD7\x5E\xEB\x67\x17\x75\x08\x14\xA8\x4D\xE0\x5C" \
+ "\x47\x50\x75\x35\x01\x3D\x86\x42\x1D\xF6\x15\x09\x89\xC5\x3F\xFA" \
+ "\x3A\xBB\x09\x86\x3A\xFD\x46\xB8\xA2\x96\x55\x2B\x45\x5F\x22\x94" \
+ "\xB5\xBC\x03\x09\x7E\xFA\x80\x25\x5E\x82\xC2\x09\x26\x4D\x4D\x33" \
+ "\xD9\x17\x66\x3C\x4C\xAF\x47\x81\x15\x47\x9B\x39\x6B\x15\x62\x30" \
+ "\x79\x1B\xFD\x3B\x86\x24\xA8\xD1\x47\xC2\x1C\x97\x8A\x07\x01\x66" \
+ "\xFC\xC7\x4C\xF9\xC0\x2C\x2B\x8C\x0F\x57\x2F\xD6\x8A\x19\x30\x6D" \
+ "\x47\xAB"
+
+/** Screen mode 1280x960 (at 60 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1280_960_60_24_0 "" \
+ "\x42\xAB\xE3\x84\x2F\xC6\xAA\x5D\x17\x17\xE5\x9B\x0D\x53\xC5\xA6"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1280_960_60_24_0 "" \
+ "\x3D\xAD\x8C\xC7\x3D\x3F\x34\x45\xB6\x05\x97\xE1\x57\x34\xEA\x4E" \
+ "\x1E\xDD\xDA\x98\x2B\x31\xEB\xEF\x9B\xD5\x73\xB1\x7E\x68\xD5\xCC" \
+ "\xD5\xB8\x72\xBD\xC7\x7C\x2D\x07\x90\xFE\x49\xD7\x79\x43\x63\x49" \
+ "\xA5\xA3\x12\x82\x8E\xA8\xD7\x6C\xD2\xCB\x75\x03\x94\xE0\xD2\x9E" \
+ "\x10\x40\x53\xD7\x63\xBA\x11\x24\x20\x27\x07\xE4\xEB\x27\xD0\x8A" \
+ "\x53\x34\x80\x2D\xCC\x32\x7F\x27\xC3\x8B\x74\x36\x9D\x75\xDD\x82" \
+ "\xE4\xE5\x40\xA2\xE2\x78\x3D\x48\x0F\x2C\xB4\x64\x65\xAB\xCF\x2E" \
+ "\xFD\xA5\x9A\xC0\x4E\x32\x72\x1D\x2A\xFC\x9D\xC7\xE9\x28\xA5\x57" \
+ "\xE7\xB5\x23\x44\xAF\x3E\xCC\xF4\x14\xCC\x98\x3A\x81\x83\x69\xFE" \
+ "\x07\x8F"
+
+/** Screen mode 1280x960 (at 85 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1280_960_85_24_0 "" \
+ "\xF6\x75\x37\x25\x3C\xE1\x82\x53\xF8\x68\xEE\x05\xBB\xB4\xAB\xBC"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1280_960_85_24_0 "" \
+ "\x58\x1F\x5A\xDF\xCB\x19\xD1\x74\xB3\x90\x0C\x65\xD4\xA1\x37\xD5" \
+ "\xA6\xD0\x6C\xF7\x0F\xDB\x94\x9E\xBA\xCF\xEF\x01\x88\xB9\x0F\x2B" \
+ "\x0F\x49\xD0\x81\x31\xF5\x40\x7E\x69\x88\x7E\x59\x46\xA0\xEC\xCF" \
+ "\x04\x19\x75\x02\xD9\x6C\xE2\x12\xA3\x1D\x4E\x73\xAF\xC9\xD6\x37" \
+ "\xCB\xA8\xB1\xEE\xF4\x9F\x36\x0C\x46\x74\xE0\x54\x17\x48\xDC\xCE" \
+ "\xDF\x94\xF7\x1D\x1A\x17\x46\xE8\x51\x63\x7F\xD7\x5B\x34\x72\x14" \
+ "\x69\xED\x18\xE2\x12\xFE\x65\xB9\x90\x34\xAB\xFE\xD1\xFE\x42\x25" \
+ "\x8D\xF8\xA6\x73\x9F\x8D\x9E\xE1\x8F\x00\xD1\xE3\xF4\x68\x30\xA9" \
+ "\x99\x10\xE2\xC7\x62\x54\x55\x6F\x9E\xEF\x7A\xD7\x01\x1E\x5D\x87" \
+ "\xD1\x43"
+
+/** Screen mode 1360x768 (at 60 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1360_768_60_24_0 "" \
+ "\x84\x36\xDB\xC0\x18\x5D\x13\x10\xC5\x02\x16\x81\xB6\xC1\x3D\xA6"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1360_768_60_24_0 "" \
+ "\x99\xDA\xC7\x8E\xCA\xE9\x49\xCB\xB6\xB4\xF8\x21\x10\x3B\xC1\x42" \
+ "\x8C\x08\x1E\x52\x9A\xA9\x4A\x17\x4B\x9A\x07\x0A\xDE\xB0\x6D\x89" \
+ "\x0C\x62\x11\x38\x93\x01\x9E\x33\xC8\xE6\x0E\x17\x02\x35\x69\x2B" \
+ "\x73\x37\x44\xD3\x5B\x4F\xF7\xC0\x86\x5F\x1E\x9D\xA8\x70\x2B\x3C" \
+ "\x30\x89\x7F\x65\x5C\x7A\xB6\x36\x4D\xA8\xE9\xFB\xCF\x07\x5F\x65" \
+ "\xDA\x93\x2B\x98\x12\xB8\x39\xBD\x08\x5F\xB7\x99\x36\x37\x3C\x9E" \
+ "\x7D\x1B\xB2\xA7\x54\xCB\x26\xC7\xAF\x78\xAC\x03\x8C\xA7\x89\xE4" \
+ "\x66\x4A\xC1\x04\xF7\xEC\x74\xFB\xC7\x07\x9F\x81\x7F\x4C\x75\x5E" \
+ "\xC3\xCD\x1B\xF7\x05\x1E\xF2\xB7\x03\x2C\x3C\xA4\x12\x9B\xFA\xA0" \
+ "\xC4\xEA"
+
+/** Screen mode 1366x768 (at 60 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1366_768_60_24_0 "" \
+ "\x6E\xF3\xC9\x86\x50\xDD\x97\x16\xDF\xAD\x97\x95\x6E\xD4\x3B\x46"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1366_768_60_24_0 "" \
+ "\x2A\x70\xE7\xB0\xD9\xFE\xA9\x6F\x28\x27\xE0\x53\x4E\xF8\xA4\x45" \
+ "\x82\x41\x8C\x7D\xC1\x73\x14\xE9\xF6\x90\x6D\xAA\xF2\xF5\x6D\xE0" \
+ "\x74\x44\x45\x0E\x08\xD3\x0A\x6A\x06\xE1\x06\x5B\xB2\x89\x47\x47" \
+ "\xB5\x0D\x74\x4F\x39\xF5\xB3\xA5\xCC\x57\x1E\x01\x97\xD5\xF4\xE4" \
+ "\x09\x58\x0A\x79\xEC\x77\xF7\x4B\xCC\x9D\xF2\xB1\x3F\x68\xDF\x67" \
+ "\x21\x03\x8A\x8D\xFD\x52\x92\x9A\x91\x56\x7A\x3A\x5F\xE0\x1E\x6D" \
+ "\xA8\x53\x1A\x61\xFC\xBC\xE1\x2E\x2F\x9E\x07\xFE\xB5\xD9\x74\x92" \
+ "\x2A\xA4\x2C\x08\xCA\xAF\x3D\xFB\x2E\xDF\xCE\xE9\xF7\xF2\x9E\x05" \
+ "\x7C\xEB\x17\x1E\x51\xEF\xE1\x09\x6B\xE2\x5E\xD4\xA6\x7F\x18\x15" \
+ "\xF3\xB8"
+
+/** Screen mode 1400x1050 (at 60 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1400_1050_60_24_0 "" \
+ "\x95\xCB\x91\xE5\xA8\x28\xFB\x87\xD5\x92\x1C\x44\x66\x57\x8A\x98"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1400_1050_60_24_0 "" \
+ "\xC6\x8C\x42\x4C\x95\xDA\xB4\x2F\xBD\xD9\x9E\xAD\x8F\x7B\x69\x15" \
+ "\x1B\xDA\x06\x79\x23\x9E\x94\xF2\xC2\xE9\xBB\x34\x13\x6B\x9B\xB2" \
+ "\xC1\x4E\xD8\x69\x81\x49\x6E\x64\xAF\xB2\x4E\x69\x24\x1A\xA8\xBB" \
+ "\x4E\x11\x75\x38\xE6\xC9\x3D\xE9\x9A\xCC\x3B\xAA\x1F\xC4\x97\xD5" \
+ "\x4A\x9D\xAA\xE7\x04\xF0\xB6\xD4\xBD\xE4\x41\xCF\xF8\xA2\x77\x0B" \
+ "\x46\x9D\x3A\xBD\x73\xC0\x64\x76\x84\x2B\xD7\x11\xF3\x43\xB5\xF6" \
+ "\xE9\x0B\xB3\x4E\x2B\x80\x98\x15\xDC\xDA\x46\xE8\xEC\xBD\x0B\x0E" \
+ "\x64\x20\xF7\x17\x17\x33\x75\xBA\x30\x26\xDD\xFA\xA0\x99\x23\x11" \
+ "\xF1\xDE\x80\xB7\xD6\xB0\xB7\xA2\xA9\xBD\x6D\x29\x42\x74\x75\x73" \
+ "\xC5\x27"
+
+/** Screen mode 1400x1050 (at 60 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1400_1050_60_24_1 "" \
+ "\xCB\xA2\x00\x73\xCB\xFC\xFB\xA0\x8E\x17\xE4\xF5\x6F\x6F\x8D\x1D"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1400_1050_60_24_1 "" \
+ "\xDA\x01\x80\xE4\x99\x82\x8F\x40\xE9\x6E\xDD\xA6\x7F\xDE\x19\xFC" \
+ "\x48\xF7\x90\x61\xE4\x2F\xA3\x72\x4A\xC5\x17\xBE\x27\x77\x35\x6A" \
+ "\x74\x8E\xB5\x45\xA0\x6E\x3D\x58\x2E\xBA\x9A\xB6\xA3\xAC\x26\xD4" \
+ "\xE8\xC6\xF8\xE3\x59\x7D\x76\x1C\x45\x07\x8A\x82\x96\x3B\x8B\x45" \
+ "\xB7\x90\x79\xDB\x06\x4E\x97\x7F\x4E\x6A\xF0\xE7\x09\x7B\x3F\x05" \
+ "\x20\x42\x7D\xAC\xBF\x79\x4D\x42\xC7\x19\x48\x2A\xC4\xA0\xCD\x9B" \
+ "\xED\x6E\xB0\xF7\xAD\x31\xB1\xDB\xA0\x4D\x06\x41\xE2\x8F\x06\x63" \
+ "\xD0\x48\xB5\xD5\x10\xB7\x47\x7D\xBC\xDE\x1D\x05\x55\x3B\x8F\x78" \
+ "\xAA\x5C\x69\x52\x48\x3D\x48\xC5\x4C\x92\x8F\x48\x62\x9E\x71\xDC" \
+ "\x36\xD2"
+
+/** Screen mode 1400x1050 (at 75 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1400_1050_75_24_0 "" \
+ "\x8E\x2F\xD0\x59\x2B\xCB\xFA\xB9\xE2\xDE\xAE\x51\x4D\x3C\x6E\x4D"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1400_1050_75_24_0 "" \
+ "\x25\xF4\x22\x48\xF0\xD9\x0D\xA9\x0C\xF0\x50\x5D\x18\x3B\x36\x2D" \
+ "\x29\xD7\x7A\x1D\x4B\xDC\x56\xA2\x46\xDB\x7C\x33\xEB\xAB\x64\xBB" \
+ "\x63\xE2\xB1\x4C\x03\xA0\x8B\xBB\x22\x4D\x29\x10\x0B\xF8\xC9\x3F" \
+ "\xA4\x15\xDA\xCB\x13\xE7\x31\xF7\xF1\x98\xF7\x76\x4E\xDB\x80\xB9" \
+ "\x4E\x74\x09\x29\xB2\x97\xBA\x23\x0E\xE1\xE9\x69\x17\x56\x3B\xD0" \
+ "\x64\x78\x70\x27\x34\xB4\xD0\xE9\xF9\x4C\x0F\xF1\xF8\x55\x4C\x12" \
+ "\x99\xF9\x07\x97\x06\xDC\xD8\x9E\xC5\x50\x58\x3B\xE8\x4A\x4F\x12" \
+ "\x69\xAB\x7C\xDA\x8A\x95\x4B\xEF\x77\xFD\xE1\x0F\x21\x1D\x57\x86" \
+ "\x46\xBE\x2B\x5A\xBF\xF5\xD2\xBF\xF7\xCF\x67\xEC\x0B\x32\xCC\x90" \
+ "\x0C\x28"
+
+/** Screen mode 1400x1050 (at 85 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1400_1050_85_24_0 "" \
+ "\x66\xC2\x92\x91\x8D\x8C\x4A\x6F\x6A\xF9\xC1\xB8\x35\x2F\x05\xD7"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1400_1050_85_24_0 "" \
+ "\x73\x98\x38\x46\xA7\xAC\x57\x49\x3A\x29\x40\xA6\xB1\xC7\xF6\xC8" \
+ "\x43\xA7\x39\x93\x0C\xB6\x05\xD3\x80\x50\x23\x08\xCE\x1E\x0B\x6B" \
+ "\xBB\x3F\x75\xCE\x8D\x9D\xF5\x67\xCB\xD3\x28\x29\x1B\x2D\x30\x40" \
+ "\xFC\xFA\xA2\x75\xB7\xF5\x02\xC2\x52\x10\x11\x2A\xDA\x47\x21\x20" \
+ "\x01\xE9\x92\xD8\x0E\xA7\xB8\x11\x8F\x3D\x2A\xDB\x83\xB1\x05\x48" \
+ "\xC4\x57\xF7\x3E\x32\x0A\x8A\xDD\xD8\x2D\x0C\x33\xE1\x36\x8A\x6E" \
+ "\xF9\x86\xFD\x46\x50\xE8\x75\x5F\xB1\xA2\x97\xA1\x17\xF9\xBD\x70" \
+ "\x98\x9B\xEC\xAF\x88\xC2\xB2\x15\xE0\xFB\xEE\x3A\x8B\x7B\x39\xAE" \
+ "\xC9\x35\x9D\x58\xCB\x24\x35\xE4\xC4\x49\x1C\x35\x89\xE6\xE6\xE7" \
+ "\xF6\x0E"
+
+/* DL160 modes... */
+
+/** Screen mode 1600x1200 (at 60 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1600_1200_60_24_0 "" \
+ "\x3C\x79\x81\x0F\xF2\xAB\x85\xC7\x3A\xE8\xEB\xCB\xF3\x32\x12\x9C"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1600_1200_60_24_0 "" \
+ "\x85\x2C\x9A\xF4\x29\x03\x6E\x4C\x58\x8D\xE3\x93\x40\x23\x71\xD2" \
+ "\x52\xA1\x70\x77\x9D\x48\x00\xDC\x93\x3C\x5C\x80\xBF\x3F\x0F\xF8" \
+ "\x5F\x72\x48\x38\x23\x69\xA7\x4A\x1D\x8D\x8E\x55\x66\x77\x27\xBF" \
+ "\x80\x35\x55\x7A\x9A\x40\x9A\xDD\x2F\x12\xB1\xFD\x85\x0F\x43\x23" \
+ "\xE5\x36\xE8\x05\x2B\x69\x48\x1E\xB8\x52\xF2\xFF\xB7\x02\x23\x0A" \
+ "\x8D\x74\x36\xFB\xAF\x5B\x8B\x2D\x40\x92\x09\x17\x15\xAE\x4E\xFF" \
+ "\x0F\x9D\xD7\x9E\x22\xA4\xE0\x87\x6F\x70\x66\x58\xFF\xAA\xEB\x8B" \
+ "\xFA\xB3\xEF\x84\x49\xF0\x10\xE7\x3E\x6F\x4F\x24\xFB\x43\x7D\x3B" \
+ "\x4C\xD4\xEA\x75\xFA\xF5\xB7\xFF\xD1\x9B\x39\x77\xD9\xA6\xE1\x5E" \
+ "\x0B\x20"
+
+/** Screen mode 1920x1080 (at 60 Hz, 24 bpp).
+ */
+#define DLO_MODE_ENABLE_1920_1080_60_24_0 "" \
+ "\xC1\xCA\xC3\xB3\x75\x48\x7A\xAF\x30\x65\x7B\x24\x97\x8D\xC0\x64"
+
+/** Mode data.
+ */
+#define DLO_MODE_DATA_1920_1080_60_24_0 "" \
+ "\x0D\x58\x81\xE3\x3E\x98\x55\x00\x24\x27\x6C\x99\x39\xC8\x72\xD8" \
+ "\xBB\x8E\x1E\xA2\xCA\x92\xD2\xAB\x59\x06\xE0\x65\xAA\xB5\x9D\xAC" \
+ "\x2C\xB5\xDA\x17\x17\x2D\xBE\x19\x8B\xCA\x76\x3D\x8E\x3A\x96\x8F" \
+ "\x59\xF1\xD1\xA6\x75\xD1\xAE\xB7\x59\xA9\x60\xA4\x56\x56\x39\x8E" \
+ "\x90\xC3\x80\x58\x0E\x9A\x77\x00\xF8\xE4\x24\x74\xDE\xF6\x29\x34" \
+ "\x94\x09\x17\x73\x74\xC8\xF6\xC0\x38\x05\x32\xD7\xC9\x73\xF1\x99" \
+ "\x53\x4F\x1B\x04\x23\x80\x6F\x08\x79\x05\x22\x2F\x3D\xC8\x17\x9D" \
+ "\x69\x61\x8C\x96\x22\x28\x7C\x4F\x5F\xA6\x7D\xF1\x30\x38\x36\xFE" \
+ "\x1B\x75\xA7\x2C\xDF\x7D\x17\x33\x7E\x9F\xF3\xFC\x0A\xDC\xB3\xDB" \
+ "\xB2\xE0"
+
+/** Data to send after a mode change.
+ */
+#define DLO_MODE_POSTAMBLE "\x57\xCD\xDC\xA7\x1C\x88\x5E\x15\x60\xFE\xC6\x97\x16\x3D\x47\xF2"
+
+/** Number of entries in the @a dlo_mode_data array.
+ */
+#define DLO_MODE_DATA_NUM (35u)
+
+/** Lowest mode number supported by the DL120.
+ */
+#define DLO_DL120_MODES (2u)
+
+
+#endif
diff --git a/src/dlo_defs.h b/src/dlo_defs.h
index 08baf21..974c295 100644
--- a/src/dlo_defs.h
+++ b/src/dlo_defs.h
@@ -1,158 +1,158 @@
-/** @file dlo_defs.h
- *
- * @brief This file defines common macros and so on for the DisplayLink libdlo library.
- *
- * DisplayLink Open Source Software (libdlo)
- * Copyright (C) 2009, DisplayLink
- * www.displaylink.com
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Library General Public License as published by the Free
- * Software Foundation; LGPL version 2, dated June 1991.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef DLO_DLOCOMMON_H
-#define DLO_DLOCOMMON_H /**< Avoid multiple inclusion. */
-
-#include <stdint.h>
-#include <stdio.h>
-
-#ifdef DEBUG
-
-/** Assert that a given expression evaluates to a non-zero number.
- *
- * @param expr The expression to test.
- */
-#define ASSERT(expr) if (!(expr)) { printf("<%s:%u>\n Assertion '%s' failed.\n", __FILE__, __LINE__, #expr); exit(1); }
-
-/** Variadic debugging printf() implementation.
- *
- * @param fmt Format string for printed output.
- */
-#define DPRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)
-
-#else
-
-/** Non-debug assert - does nothing.
- *
- * @param expr The expression to test.
- */
-#define ASSERT(expr)
-
-/** Non-debug printf - does nothing.
- *
- * @param fmt Format string for printed output.
- */
-#define DPRINTF(fmt, ...)
-
-#endif
-
-/** Get a couple of required attributes into a handy format. */
-#if __GNUC__ >= 3
-
-/* Check for portable attribute definitions and create them if they are missing */
-#ifndef inline
-#define inline inline __attribute__ ((always_inline))
-#endif
-#ifndef __packed
-#define __packed __attribute__ ((packed))
-#endif
-
-#else
-
-/* Toolchain is too old or doesn't support the attributes we need */
-#ifndef inline
-#define inline TOOLCHAIN_ERROR_NO_INLINE
-#endif
-#ifndef __packed
-#define __packed TOOLCHAIN_ERROR_NO_PACKED
-#endif
-
-#endif
-
-/** Read an unsigned 32 bit value from the address given (may be unaligned). */
-#define RD_L(ptr) (*(__packed uint32_t *)(ptr))
-
-/** Read an unsigned 16 bit value from the address given (may be unaligned). */
-#define RD_S(ptr) (*(__packed uint16_t *)(ptr))
-
-/** Read an unsigned byte from the address given. */
-#define RD_B(ptr) (*(uint8_t *)(ptr))
-
-/** Surpress warnings about unused variables. */
-#define IGNORE(x) do { (void) (x); } while (0)
-
-/** Record the line and source file associated with a particular type of error event. */
-#define REC_ERR() { snprintf(&err_file[0], 1024, "%s", __FILE__); err_line = __LINE__; }
-
-/** If a called function (cmd) returns an error code, return the error code from the calling function. */
-#define ERR(cmd) do { dlo_retcode_t __err = (cmd); if (__err != dlo_ok) return __err; } while(0)
-
-/** If a usb_ function call returns an error code, return an error and store the code in the @a usberr global. */
-#define UERR(cmd) do { usberr = (cmd); if (usberr < 0) return usb_error_grab(); } while (0)
-
-/** If a memory-allocating call returns NULL, return with a memory allocation error code. */
-#define NERR(ptr) do { if (!(ptr)) { REC_ERR(); return dlo_err_memory; } } while (0)
-
-/** If a function call (cmd) returns an error code, jump to the "error" label. Requires variable declaration: dlo_retcode_t err; */
-#define ERR_GOTO(cmd) do { err = (cmd); if (err != dlo_ok) goto error; } while(0)
-
-/** If a usb_ function call returns an error code, jump to the "error" label and store the usb error code in the @a usberr global. */
-#define UERR_GOTO(cmd) do { usberr = (cmd); if (usberr < 0) { err = usb_error_grab(); goto error; } } while(0)
-
-/** If a memory-allocating call returns NULL, jump to the "error" label with a memory allocation error code. */
-#define NERR_GOTO(ptr) do { if (!(ptr)) { REC_ERR(); err = dlo_err_memory; goto error; } } while(0)
-
-/** Return the size of a hash-defined string, excluding the terminator (unlike strlen(), it does count null bytes in the string). */
-#define DSIZEOF(str) (sizeof(str) - 1)
-
-/** Swap two integer values (assumes they are the same size). */
-#define SWAP(a, b) do { (a) = (a) ^ (b); (b) = (a) ^ (b); (a) = (a) ^ (b); } while (0)
-
-/** Magic macro for calling functions from pointer tables (after first checking the device structure pointer and the function pointer). */
-#define CALL(dev, fn, ...) dev ? ( dev->fn ? dev->fn(dev, ##__VA_ARGS__) : dlo_err_unsupported ) : dlo_err_bad_device
-
-/** Number of bytes per 16 bpp pixel! */
-#define BYTES_PER_16BPP (2)
-
-/** Number of bytes per 8 bpp pixel! */
-#define BYTES_PER_8BPP (1)
-
-/** Convert a framebuffer pixel format into a number of bytes per pixel. */
-#define FORMAT_TO_BYTES_PER_PIXEL(fmt) ((unsigned int)fmt > 1023u ? 1 : ((fmt) & DLO_PIXFMT_BYPP_MSK) >> DLO_PIXFMT_BYPP_SFT)
-
-/** Default buffer size for sending commands to the device. */
-#define BUF_SIZE (64*1024u)
-
-/** Threshold (bytes away from being full) for flushing the command buffer before adding any more commands to it. */
-#define BUF_HIGH_WATER_MARK (1*1024u)
-
-/** A 16 bits per pixel colour number (not normally used outside libdlo). */
-typedef uint16_t dlo_col16_t;
-
-/** An 8 bits per pixel colour number (2_rrrggbbb - not normally used outside libdlo). */
-typedef uint8_t dlo_col8_t;
-
-/** Integer used to store error number for last failed call to a dlo_usb_ function. */
-extern int32_t usberr;
-
-/** Integer used to store error number for last failed call to a dlo_eth_ function. */
-extern int32_t etherr;
-
-/** Source file name for the last recorded error event. */
-extern char err_file[1024];
-
-/** Source line number for last recorded error event. */
-extern uint32_t err_line;
-
-
-#endif
+/** @file dlo_defs.h
+ *
+ * @brief This file defines common macros and so on for the DisplayLink libdlo library.
+ *
+ * DisplayLink Open Source Software (libdlo)
+ * Copyright (C) 2009, DisplayLink
+ * www.displaylink.com
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by the Free
+ * Software Foundation; LGPL version 2, dated June 1991.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef DLO_DLOCOMMON_H
+#define DLO_DLOCOMMON_H /**< Avoid multiple inclusion. */
+
+#include <stdint.h>
+#include <stdio.h>
+
+#ifdef DEBUG
+
+/** Assert that a given expression evaluates to a non-zero number.
+ *
+ * @param expr The expression to test.
+ */
+#define ASSERT(expr) if (!(expr)) { printf("<%s:%u>\n Assertion '%s' failed.\n", __FILE__, __LINE__, #expr); exit(1); }
+
+/** Variadic debugging printf() implementation.
+ *
+ * @param fmt Format string for printed output.
+ */
+#define DPRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)
+
+#else
+
+/** Non-debug assert - does nothing.
+ *
+ * @param expr The expression to test.
+ */
+#define ASSERT(expr)
+
+/** Non-debug printf - does nothing.
+ *
+ * @param fmt Format string for printed output.
+ */
+#define DPRINTF(fmt, ...)
+
+#endif
+
+/** Get a couple of required attributes into a handy format. */
+#if __GNUC__ >= 3
+
+/* Check for portable attribute definitions and create them if they are missing */
+#ifndef inline
+#define inline inline __attribute__ ((always_inline))
+#endif
+#ifndef __packed
+#define __packed __attribute__ ((packed))
+#endif
+
+#else
+
+/* Toolchain is too old or doesn't support the attributes we need */
+#ifndef inline
+#define inline TOOLCHAIN_ERROR_NO_INLINE
+#endif
+#ifndef __packed
+#define __packed TOOLCHAIN_ERROR_NO_PACKED
+#endif
+
+#endif
+
+/** Read an unsigned 32 bit value from the address given (may be unaligned). */
+#define RD_L(ptr) (*(__packed uint32_t *)(ptr))
+
+/** Read an unsigned 16 bit value from the address given (may be unaligned). */
+#define RD_S(ptr) (*(__packed uint16_t *)(ptr))
+
+/** Read an unsigned byte from the address given. */
+#define RD_B(ptr) (*(uint8_t *)(ptr))
+
+/** Surpress warnings about unused variables. */
+#define IGNORE(x) do { (void) (x); } while (0)
+
+/** Record the line and source file associated with a particular type of error event. */
+#define REC_ERR() { snprintf(&err_file[0], 1024, "%s", __FILE__); err_line = __LINE__; }
+
+/** If a called function (cmd) returns an error code, return the error code from the calling function. */
+#define ERR(cmd) do { dlo_retcode_t __err = (cmd); if (__err != dlo_ok) return __err; } while(0)
+
+/** If a usb_ function call returns an error code, return an error and store the code in the @a usberr global. */
+#define UERR(cmd) do { usberr = (cmd); if (usberr < 0) return usb_error_grab(); } while (0)
+
+/** If a memory-allocating call returns NULL, return with a memory allocation error code. */
+#define NERR(ptr) do { if (!(ptr)) { REC_ERR(); return dlo_err_memory; } } while (0)
+
+/** If a function call (cmd) returns an error code, jump to the "error" label. Requires variable declaration: dlo_retcode_t err; */
+#define ERR_GOTO(cmd) do { err = (cmd); if (err != dlo_ok) goto error; } while(0)
+
+/** If a usb_ function call returns an error code, jump to the "error" label and store the usb error code in the @a usberr global. */
+#define UERR_GOTO(cmd) do { usberr = (cmd); if (usberr < 0) { err = usb_error_grab(); goto error; } } while(0)
+
+/** If a memory-allocating call returns NULL, jump to the "error" label with a memory allocation error code. */
+#define NERR_GOTO(ptr) do { if (!(ptr)) { REC_ERR(); err = dlo_err_memory; goto error; } } while(0)
+
+/** Return the size of a hash-defined string, excluding the terminator (unlike strlen(), it does count null bytes in the string). */
+#define DSIZEOF(str) (sizeof(str) - 1)
+
+/** Swap two integer values (assumes they are the same size). */
+#define SWAP(a, b) do { (a) = (a) ^ (b); (b) = (a) ^ (b); (a) = (a) ^ (b); } while (0)
+
+/** Magic macro for calling functions from pointer tables (after first checking the device structure pointer and the function pointer). */
+#define CALL(dev, fn, ...) dev ? ( dev->fn ? dev->fn(dev, ##__VA_ARGS__) : dlo_err_unsupported ) : dlo_err_bad_device
+
+/** Number of bytes per 16 bpp pixel! */
+#define BYTES_PER_16BPP (2)
+
+/** Number of bytes per 8 bpp pixel! */
+#define BYTES_PER_8BPP (1)
+
+/** Convert a framebuffer pixel format into a number of bytes per pixel. */
+#define FORMAT_TO_BYTES_PER_PIXEL(fmt) ((unsigned int)fmt > 1023u ? 1 : ((fmt) & DLO_PIXFMT_BYPP_MSK) >> DLO_PIXFMT_BYPP_SFT)
+
+/** Default buffer size for sending commands to the device. */
+#define BUF_SIZE (64*1024u)
+
+/** Threshold (bytes away from being full) for flushing the command buffer before adding any more commands to it. */
+#define BUF_HIGH_WATER_MARK (1*1024u)
+
+/** A 16 bits per pixel colour number (not normally used outside libdlo). */
+typedef uint16_t dlo_col16_t;
+
+/** An 8 bits per pixel colour number (2_rrrggbbb - not normally used outside libdlo). */
+typedef uint8_t dlo_col8_t;
+
+/** Integer used to store error number for last failed call to a dlo_usb_ function. */
+extern int32_t usberr;
+
+/** Integer used to store error number for last failed call to a dlo_eth_ function. */
+extern int32_t etherr;
+
+/** Source file name for the last recorded error event. */
+extern char err_file[1024];
+
+/** Source line number for last recorded error event. */
+extern uint32_t err_line;
+
+
+#endif
diff --git a/src/dlo_grfx.c b/src/dlo_grfx.c
index cb0dd48..822ec9b 100644
--- a/src/dlo_grfx.c
+++ b/src/dlo_grfx.c
@@ -1,843 +1,843 @@
-/** @file dlo_grfx.c
- *
- * @brief This file implements the graphics primitive operations.
- *
- * DisplayLink Open Source Software (libdlo)
- * Copyright (C) 2009, DisplayLink
- * www.displaylink.com
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Library General Public License as published by the Free
- * Software Foundation; LGPL version 2, dated June 1991.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <string.h>
-#include "dlo_defs.h"
-#include "dlo_grfx.h"
-#include "dlo_usb.h"
-
-
-/* File-scope defines ------------------------------------------------------------------*/
-
-
-/** Maximum number of pixels that can be supplied to a raw write command. */
-#define RAW_MAX_PIXELS (256)
-
-/** Maximum number of pixels that will fit into the scrape buffer. */
-#define SCRAPE_MAX_PIXELS (2048)
-
-/** Simple wrapper around the @c dlo_free() call to first check the pointer and zero it after the free. */
-#define FREE(ptr) { if (ptr) { dlo_free(ptr); ptr = NULL; } }
-
-/** Return red/green component of a 16 bpp colour number. */
-#define DLO_RG16(red, grn) (uint8_t)((((red) & 0xF8) | ((grn) >> 5)) & 0xFF)
-
-/** Return green/blue component of a 16 bpp colour number. */
-#define DLO_GB16(grn, blu) (uint8_t)(((((grn) & 0x1C) << 3) | ((blu) >> 3)) & 0xFF)
-
-/** Return 8 bpp colour number from red, green and blue components. */
-#define DLO_RGB8(red, grn, blu) ((((red) << 5) | (((grn) & 3) << 3) | ((blu) & 7)) & 0xFF)
-
-
-/* File-scope inline functions ---------------------------------------------------------*/
-
-
-/** Build a "plot horizontal line" command in a buffer.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param base Destination address in device for start of line.
- * @param remain Line length.
- * @param col Colour of point to plot.
- *
- * @return Return code, zero for no error.
- */
-inline dlo_retcode_t cmd_hline16(dlo_device_t * const dev, const dlo_ptr_t base, const uint32_t remain, const dlo_col16_t col)
-{
- if (dev->bufend - dev->bufptr < 9)
- return dlo_err_buf_full;
-
- *(dev->bufptr)++ = WRITE_RL16[0];
- *(dev->bufptr)++ = WRITE_RL16[1];
- *(dev->bufptr)++ = (char)(base >> 16);
- *(dev->bufptr)++ = (char)(base >> 8);
- *(dev->bufptr)++ = (char)base;
- *(dev->bufptr)++ = (char)remain;
- *(dev->bufptr)++ = (char)remain;
- *(dev->bufptr)++ = (char)(col >> 8);
- *(dev->bufptr)++ = (char)col;
-
- return dlo_ok;
-}
-
-
-
-/** Build a "plot horizontal line" command in a buffer for fine detail colour space.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param base Destination address in device for start of line.
- * @param remain Line length.
- * @param col Colour of point to plot.
- *
- * @return Return code, zero for no error.
- */
-inline dlo_retcode_t cmd_hline8(dlo_device_t * const dev, const dlo_ptr_t base, const uint32_t remain, const dlo_col8_t col)
-{
- if (dev->bufend - dev->bufptr < 8)
- return dlo_err_buf_full;
-
- *(dev->bufptr)++ = WRITE_RL8[0];
- *(dev->bufptr)++ = WRITE_RL8[1];
- *(dev->bufptr)++ = (char)(base >> 16);
- *(dev->bufptr)++ = (char)(base >> 8);
- *(dev->bufptr)++ = (char)base;
- *(dev->bufptr)++ = (char)remain;
- *(dev->bufptr)++ = (char)remain;
- *(dev->bufptr)++ = (char)col;
-
- return dlo_ok;
-}
-
-
-/** Build a "copy horizontal line" command in a buffer.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param src Source address in device for start of copy.
- * @param len Copy length.
- * @param dest Destination address in device for copy.
- *
- * @return Return code, zero for no error.
- */
-inline dlo_retcode_t cmd_copy16(dlo_device_t * const dev, const dlo_ptr_t src, const uint32_t len, const dlo_ptr_t dest)
-{
- if (dev->bufend - dev->bufptr < 9)
- return dlo_err_buf_full;
-
- *(dev->bufptr)++ = WRITE_COPY16[0];
- *(dev->bufptr)++ = WRITE_COPY16[1];
- *(dev->bufptr)++ = (char)(dest >> 16);
- *(dev->bufptr)++ = (char)(dest >> 8);
- *(dev->bufptr)++ = (char)dest;
- *(dev->bufptr)++ = len == 256 ? '\0' : (char)len;
- *(dev->bufptr)++ = (char)(src >> 16);
- *(dev->bufptr)++ = (char)(src >> 8);
- *(dev->bufptr)++ = (char)src;
-
- return dlo_ok;
-}
-
-
-/** Build a "copy horizontal line" command in a buffer for fine detail colour space.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param src Source address in device for start of copy.
- * @param len Copy length.
- * @param dest Destination address in device for copy.
- *
- * @return Return code, zero for no error.
- */
-inline dlo_retcode_t cmd_copy8(dlo_device_t * const dev, const dlo_ptr_t src, const uint32_t len, const dlo_ptr_t dest)
-{
- if (dev->bufend - dev->bufptr < 9)
- return dlo_err_buf_full;
-
- *(dev->bufptr)++ = WRITE_COPY8[0];
- *(dev->bufptr)++ = WRITE_COPY8[1];
- *(dev->bufptr)++ = (char)(dest >> 16);
- *(dev->bufptr)++ = (char)(dest >> 8);
- *(dev->bufptr)++ = (char)dest;
- *(dev->bufptr)++ = len == 256 ? '\0' : (char)len;
- *(dev->bufptr)++ = (char)(src >> 16);
- *(dev->bufptr)++ = (char)(src >> 8);
- *(dev->bufptr)++ = (char)src;
-
- return dlo_ok;
-}
-
-
-/* Ensure the inline functions get compiled somewhere in case they cannot be inlined */
-extern dlo_retcode_t cmd_hline16(dlo_device_t * const dev, const dlo_ptr_t base, const uint32_t remain, const dlo_col16_t col);
-extern dlo_retcode_t cmd_hline8( dlo_device_t * const dev, const dlo_ptr_t base, const uint32_t remain, const dlo_col8_t col);
-extern dlo_retcode_t cmd_copy16( dlo_device_t * const dev, const dlo_ptr_t src, const uint32_t len, const dlo_ptr_t dest);
-extern dlo_retcode_t cmd_copy8( dlo_device_t * const dev, const dlo_ptr_t src, const uint32_t len, const dlo_ptr_t dest);
-
-
-/* File-scope types --------------------------------------------------------------------*/
-
-
-/** Function pointer for functions to convert a pixel into a colour number.
- *
- * @param ptr Pointer to pixel.
- * @param swap Flag to indicate red and blue components need to be swapped.
- *
- * @return Colour number for read pixel.
- */
-typedef dlo_col32_t (*read_pixel_t) (const uint8_t * const ptr, const bool swap);
-
-
-/* File-scope variables ----------------------------------------------------------------*/
-
-
-/** Look-up table of function pointers for a specified pixel format.
- */
-static read_pixel_t fmt_to_fn[DLO_PIXFMT_MAX];
-
-
-/** Standard look-up table for converting 8 bpp pixels in bgr323 format into colour numbers.
- */
-static dlo_col32_t lut8bpp[256];
-
-
-/** Look-up table to use when reading 8 bpp pixels - required by @c read_pixel_323().
- */
-static dlo_col32_t *lut = lut8bpp;
-
-
-/** Pointer to an array for storing a stripe of 16bpp pixel information.
- */
-static dlo_col16_t *stripe16 = NULL;
-
-
-/** Pointer to an array for storing a stripe of 8bpp pixel information.
- */
-static dlo_col8_t *stripe8 = NULL;
-
-
-/* External-scope variables ------------------------------------------------------------*/
-
-
-/* File-scope function declarations ----------------------------------------------------*/
-
-
-/** Plot a section of horizontal line in the specified colour at 24 bpp.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param base16 Base address of destination 16 bpp pixel data.
- * @param base8 Base address of destination 8 bpp pixel data.
- * @param len Length of the line (pixels).
- * @param col Colour of the line.
- *
- * @return Return code, zero for no error.
- */
-static dlo_retcode_t hline_24bpp(dlo_device_t * const dev, dlo_ptr_t base16, dlo_ptr_t base8, const uint32_t len, const dlo_col32_t col);
-
-
-/** Copy a section of horizontal line from one location to another at 24 bpp.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param src_base16 Base address of source 16 bpp pixel data.
- * @param dest_base16 Base address of destination 16 bpp pixel data.
- * @param src_base8 Base address of source 8 bpp pixel data.
- * @param dest_base8 Base address of destination 8 bpp pixel data.
- * @param len Length of the line (pixels).
- *
- * @return Return code, zero for no error.
- */
-static dlo_retcode_t copy_24bpp(dlo_device_t * const dev, dlo_ptr_t src_base16, dlo_ptr_t dest_base16, dlo_ptr_t src_base8, dlo_ptr_t dest_base8, const uint32_t len);
-
-
-/** Scrape a horizontal line of host-resident pixels at 24 bpp into the device.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param rdpx Pointer to the pixel reading function.
- * @param bypp Bytes per pixel of the source pixels.
- * @param swap Flag: swap the red/blue component order.
- * @param src_base Base address of the source.
- * @param dest_base16 Base address of destination 16 bpp pixel data.
- * @param dest_base8 Base address of destination 8 bpp pixel data.
- * @param width Width of the scrape (pixels).
- *
- * @return Return code, zero for no error.
- */
-static dlo_retcode_t scrape_24bpp(dlo_device_t * const dev, const read_pixel_t rdpx, const uint32_t bypp, const bool swap,
- const uint8_t *src_base, dlo_ptr_t dest_base16, dlo_ptr_t dest_base8, const uint32_t width);
-
-
-/** Dump the contents of the scrape buffers as a horizontal pixel row at 24 bpp.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param base16 Base address of destination 16 bpp pixel data.
- * @param base8 Base address of destination 8 bpp pixel data.
- * @param width Width of the scrape (pixels).
- *
- * @return Return code, zero for no error.
- */
-static dlo_retcode_t cmd_stripe24(dlo_device_t * const dev, dlo_ptr_t base16, dlo_ptr_t base8, const uint32_t width);
-
-
-/** Given a 32 bpp colour number, return an 8 bpp colour number.
- *
- * @param col 32 bpp colour number.
- *
- * @return 8 bpp colour number.
- */
-static dlo_col8_t rgb8(dlo_col32_t col);
-
-
-/** Given a 32 bpp colour number, return a 16 bpp colour number.
- *
- * @param col 32 bpp colour number.
- *
- * @return 16 bpp colour number.
- */
-static dlo_col16_t rgb16(dlo_col32_t col);
-
-
-/** Dummy pixel reading function for an uninitialised entry.
- *
- * @param ptr Pointer to pixel.
- * @param swap Flag to indicate red and blue components need to be swapped.
- *
- * @return Colour number for read pixel.
- */
-static dlo_col32_t read_pixel_NULL(const uint8_t * const ptr, const bool swap);
-
-
-/** Read an 8 bpp pixel in 323 format.
- *
- * @param ptr Pointer to pixel.
- * @param swap Flag to indicate red and blue components need to be swapped.
- *
- * @return Colour number for read pixel.
- */
-static dlo_col32_t read_pixel_323(const uint8_t * const ptr, const bool swap);
-
-
-/** Read a 16 bpp pixel in 565 format.
- *
- * @param ptr Pointer to pixel.
- * @param swap Flag to indicate red and blue components need to be swapped.
- *
- * @return Colour number for read pixel.
- */
-static dlo_col32_t read_pixel_565(const uint8_t * const ptr, const bool swap);
-
-
-/** Read a 16 bpp pixel in 1555 format.
- *
- * @param ptr Pointer to pixel.
- * @param swap Flag to indicate red and blue components need to be swapped.
- *
- * @return Colour number for read pixel.
- */
-static dlo_col32_t read_pixel_1555(const uint8_t * const ptr, const bool swap);
-
-
-/** Read a 24 bpp pixel in 888 format.
- *
- * @param ptr Pointer to pixel.
- * @param swap Flag to indicate red and blue components need to be swapped.
- *
- * @return Colour number for read pixel.
- */
-static dlo_col32_t read_pixel_888(const uint8_t * const ptr, const bool swap);
-
-
-/** Read a 32 bpp pixel in 8888 format.
- *
- * @param ptr Pointer to pixel.
- * @param swap Flag to indicate red and blue components need to be swapped.
- *
- * @return Colour number for read pixel.
- */
-static dlo_col32_t read_pixel_8888(const uint8_t * const ptr, const bool swap);
-
-
-/* Public function definitions ---------------------------------------------------------*/
-
-
-dlo_retcode_t dlo_grfx_init(const dlo_init_t flags)
-{
- uint32_t i;
- uint8_t red, grn, blu;
- uint8_t red8, grn8, blu8;
-
- stripe16 = malloc(SCRAPE_MAX_PIXELS * sizeof(dlo_col16_t));
- NERR(stripe16);
- stripe8 = malloc(SCRAPE_MAX_PIXELS * sizeof(dlo_col8_t));
- NERR(stripe8);
-
- /* Initialise the default look-up table for 8 bpp in bgr323 format */
- for (red = 0; red < 8; red++)
- for (grn = 0; grn < 4; grn++)
- for (blu = 0; blu < 8; blu++)
- {
- uint8_t idx = red + (grn << 3) + (blu << 5);
-
- red8 = (red << 5) | (red << 2) | (red >> 1);
- grn8 = (grn << 6) | (grn << 4) | (grn << 2) | grn;
- blu8 = (blu << 5) | (blu << 2) | (blu >> 1);
- lut8bpp[idx] = DLO_RGB(red8, grn8, blu8);
- }
-
- /* Initialise the look-up table of pixel formats to pixel reading functions */
- for (i = 0; i < DLO_PIXFMT_MAX; i++)
- fmt_to_fn[i] = read_pixel_NULL;
- fmt_to_fn[dlo_pixfmt_bgr323] = read_pixel_323;
- fmt_to_fn[dlo_pixfmt_rgb323] = read_pixel_323;
- fmt_to_fn[dlo_pixfmt_bgr565] = read_pixel_565;
- fmt_to_fn[dlo_pixfmt_rgb565] = read_pixel_565;
- fmt_to_fn[dlo_pixfmt_sbgr1555] = read_pixel_1555;
- fmt_to_fn[dlo_pixfmt_srgb1555] = read_pixel_1555;
- fmt_to_fn[dlo_pixfmt_bgr888] = read_pixel_888;
- fmt_to_fn[dlo_pixfmt_rgb888] = read_pixel_888;
- fmt_to_fn[dlo_pixfmt_abgr8888] = read_pixel_8888;
- fmt_to_fn[dlo_pixfmt_argb8888] = read_pixel_8888;
-
- return dlo_ok;
-}
-
-
-dlo_retcode_t dlo_grfx_final(const dlo_final_t flags)
-{
- FREE(stripe16);
- FREE(stripe8);
-
- return dlo_ok;
-}
-
-
-dlo_retcode_t dlo_grfx_fill_rect(dlo_device_t * const dev, const dlo_area_t * const area, const dlo_col32_t col)
-{
- dlo_ptr_t base16, base8;
- uint32_t end;
-
- ASSERT(dev && area)
- ASSERT(area->view.width && area->view.height);
-
- /* Only 24 bpp is supported */
- if (area->view.bpp != 24)
- return dlo_err_bad_col;
-
- /* Compute some useful values */
- base16 = area->view.base;
- base8 = area->base8;
- end = base16 + (BYTES_PER_16BPP * area->stride * area->view.height);
-
- /* Plot the rectangle, one pixel row at a time */
- for (; base16 < end; base16 += BYTES_PER_16BPP * area->stride)
- {
- ERR(hline_24bpp(dev, base16, base8, area->view.width, col));
- base8 += BYTES_PER_8BPP * area->stride;
- }
- return dlo_usb_write(dev);
-}
-
-
-dlo_retcode_t dlo_grfx_copy_rect(dlo_device_t * const dev, const dlo_area_t * const src_area, const dlo_area_t * const dest_area, const bool overlap)
-{
- dlo_ptr_t src_base16, src_base8;
- dlo_ptr_t dest_base16, dest_base8;
- uint32_t end;
-
- ASSERT(dev && src_area && dest_area);
- ASSERT(src_area->view.width && src_area->view.height);
- ASSERT(src_area->view.width == dest_area->view.width && src_area->view.height == dest_area->view.height);
- ASSERT(src_area->view.bpp == dest_area->view.bpp);
-
- /* Only 24 bpp is supported */
- if (src_area->view.bpp != 24)
- return dlo_err_bad_col;
-
- /* Quick exit if we're copying to and from the same location */
- if (src_area->view.base == dest_area->view.base)
- return dlo_ok;
-
- /* Compute some useful values */
- if (src_area->view.base < dest_area->view.base)
- {
- uint32_t y;
-
- src_base16 = src_area->view.base + (BYTES_PER_16BPP * src_area->stride * src_area->view.height);
- src_base8 = src_area->base8 + (BYTES_PER_8BPP * src_area->stride * src_area->view.height);
- dest_base16 = dest_area->view.base + (BYTES_PER_16BPP * dest_area->stride * dest_area->view.height);
- dest_base8 = dest_area->base8 + (BYTES_PER_8BPP * dest_area->stride * dest_area->view.height);
-
- /* Copy the rectangle, one pixel row at a time */
- for (y = src_area->view.height; y > 0; y--)
- {
- src_base16 -= BYTES_PER_16BPP * src_area->stride;
- src_base8 -= BYTES_PER_8BPP * src_area->stride;
- dest_base16 -= BYTES_PER_16BPP * dest_area->stride;
- dest_base8 -= BYTES_PER_8BPP * dest_area->stride;
- ERR(copy_24bpp(dev, src_base16, dest_base16, src_base8, dest_base8, src_area->view.width));
-// if (overlap)
-// ERR(dlo_usb_write(dev));
- }
- }
- else
- {
- src_base16 = src_area->view.base;
- src_base8 = src_area->base8;
- dest_base16 = dest_area->view.base;
- dest_base8 = dest_area->base8;
- end = src_base16 + (BYTES_PER_16BPP * src_area->stride * src_area->view.height);
-
- /* Copy the rectangle, one pixel row at a time */
- for (; src_base16 < end; src_base16 += BYTES_PER_16BPP * src_area->stride)
- {
- ERR(copy_24bpp(dev, src_base16, dest_base16, src_base8, dest_base8, src_area->view.width));
- src_base8 += BYTES_PER_8BPP * src_area->stride;
- dest_base16 += BYTES_PER_16BPP * dest_area->stride;
- dest_base8 += BYTES_PER_8BPP * dest_area->stride;
-// if (overlap)
-// ERR(dlo_usb_write(dev));
- }
- }
- return dlo_usb_write(dev);
-}
-
-
-dlo_retcode_t dlo_grfx_copy_host_bmp(dlo_device_t * const dev, const dlo_bmpflags_t flags, const dlo_fbuf_t const *fbuf, const dlo_area_t * const area)
-{
- uint8_t *src_base;
- uint8_t *end;
- dlo_ptr_t dest_base16, dest_base8;
- uint32_t bypp;
- read_pixel_t rdpx;
- bool swap;
-
- ASSERT(dev && fbuf && area);
- ASSERT(fbuf->width && fbuf->height && fbuf->base && fbuf->stride);
- ASSERT(fbuf->width == area->view.width && fbuf->height == area->view.height)
-
- /* Only 24 bpp is supported */
- if (area->view.bpp != 24)
- return dlo_err_bad_col;
-
- /* Get a pixel reading function pointer for the fbuf */
- if (fbuf->fmt >> DLO_PIXFMT_PTR_SFT)
- {
- bypp = 1;
- rdpx = read_pixel_323;
- swap = false;
- lut = (dlo_col32_t *)fbuf->fmt;
- }
- else
- {
- if ((int)fbuf->fmt > (int)dlo_pixfmt_argb8888)
- return dlo_err_bad_fmt;
-
- bypp = FORMAT_TO_BYTES_PER_PIXEL(fbuf->fmt);
- rdpx = fmt_to_fn[fbuf->fmt];
- swap = fbuf->fmt & DLO_PIXFMT_SWP ? true : false;
- lut = lut8bpp; /* For unpaletted bitmaps, the LUT is our standard colour palette */
- }
-
- /* Check that a row from the bitmap will fit into the scrape buffers */
- if (fbuf->width > SCRAPE_MAX_PIXELS)
- return dlo_err_big_scrape;
-
- /* Set up the destination pointers in the device memory */
- dest_base16 = area->view.base;
- dest_base8 = area->base8;
-
- /* Either copy down or up the bitmap, depending upon whether we are doing a vertical flip */
- if (flags.v_flip)
- {
- src_base = (uint8_t *)fbuf->base + (bypp * fbuf->stride * (area->view.height - 1));
- end = (uint8_t *)fbuf->base;
-
- for (; src_base >= end; src_base -= bypp * fbuf->stride)
- {
- ERR(scrape_24bpp(dev, rdpx, bypp, swap, src_base, dest_base16, dest_base8, fbuf->width));
- dest_base16 += BYTES_PER_16BPP * area->stride;
- dest_base8 += BYTES_PER_8BPP * area->stride;
- }
- }
- else
- {
- src_base = (uint8_t *)fbuf->base;
- end = src_base + (bypp * fbuf->stride * area->view.height);
-
- for (; src_base < end; src_base += bypp * fbuf->stride)
- {
- ERR(scrape_24bpp(dev, rdpx, bypp, swap, src_base, dest_base16, dest_base8, fbuf->width));
- dest_base16 += BYTES_PER_16BPP * area->stride;
- dest_base8 += BYTES_PER_8BPP * area->stride;
- }
- }
- return dlo_usb_write(dev);
-}
-
-
-/* File-scope function definitions -----------------------------------------------------*/
-
-
-static dlo_retcode_t hline_24bpp(dlo_device_t * const dev, dlo_ptr_t base16, dlo_ptr_t base8, const uint32_t len, const dlo_col32_t col)
-{
- dlo_col16_t col16 = rgb16(col);
- dlo_col8_t col8 = rgb8(col);
- uint32_t rem = len % 256;
-
- /* Flush the command buffer if it's getting full */
- if (dev->bufend - dev->bufptr < BUF_HIGH_WATER_MARK)
- ERR(dlo_usb_write(dev));
-
- /* Is this a short line segment? */
- if (len < 256)
- {
- ERR(cmd_hline16(dev, base16, len, col16));
- ERR(cmd_hline8( dev, base8, len, col8));
- }
- else
- {
- /* Longer line segments require a few commands to complete */
- uint32_t roff16 = base16 + (BYTES_PER_16BPP * (len - rem));
- uint32_t roff8 = base8 + (BYTES_PER_8BPP * (len - rem));
-
- for (; base16 < roff16; base16 += BYTES_PER_16BPP * 256)
- {
- ERR(cmd_hline16(dev, base16, 0, col16));
- ERR(cmd_hline8( dev, base8, 0, col8));
- base8 += BYTES_PER_8BPP * 256;
- }
- if (rem)
- {
- ERR(cmd_hline16(dev, roff16, rem, col16));
- ERR(cmd_hline8( dev, roff8, rem, col8));
- }
- }
- return dlo_ok;
-}
-
-
-static dlo_retcode_t copy_24bpp(dlo_device_t * const dev, dlo_ptr_t src_base16, dlo_ptr_t dest_base16, dlo_ptr_t src_base8, dlo_ptr_t dest_base8, const uint32_t len)
-{
- uint32_t rem = len % 256;
-
- /* Flush the command buffer if it's getting full */
- if (dev->bufend - dev->bufptr < BUF_HIGH_WATER_MARK)
- ERR(dlo_usb_write(dev));
-
- /* Is this a short line segment? */
- if (len < 256)
- {
- ERR(cmd_copy16(dev, src_base16, len, dest_base16));
- ERR(cmd_copy8( dev, src_base8, len, dest_base8));
- }
- else
- {
- /* Longer line segments require a few commands to complete */
- uint32_t src_roff16 = src_base16 + (BYTES_PER_16BPP * (len - rem));
- uint32_t dest_roff16 = dest_base16 + (BYTES_PER_16BPP * (len - rem));
- uint32_t src_roff8 = src_base8 + (BYTES_PER_8BPP * (len - rem));
- uint32_t dest_roff8 = dest_base8 + (BYTES_PER_8BPP * (len - rem));
-
- for (; src_base16 < src_roff16; src_base16 += BYTES_PER_16BPP * 256)
- {
- ERR(cmd_copy16(dev, src_base16, 0, dest_base16));
- ERR(cmd_copy8( dev, src_base8, 0, dest_base8));
- dest_base16 += BYTES_PER_16BPP * 256;
- src_base8 += BYTES_PER_8BPP * 256;
- dest_base8 += BYTES_PER_8BPP * 256;
- }
- if (rem)
- {
- ERR(cmd_copy16(dev, src_roff16, rem, dest_roff16));
- ERR(cmd_copy8( dev, src_roff8, rem, dest_roff8));
- }
- }
- return dlo_ok;
-}
-
-
-static dlo_retcode_t scrape_24bpp(dlo_device_t * const dev, const read_pixel_t rdpx, const uint32_t bypp, const bool swap,
- const uint8_t *src_base, dlo_ptr_t dest_base16, dlo_ptr_t dest_base8, const uint32_t width)
-{
- const uint8_t *end = src_base + (bypp * width);
- dlo_col16_t *ptr_col16 = stripe16;
- dlo_col8_t *ptr_col8 = stripe8;
-
- /* Read a stripe from the source bitmap into the internal colour format */
- for (; src_base < end; src_base += bypp)
- {
- dlo_col32_t col = rdpx(src_base, swap);
-
- *ptr_col16++ = rgb16(col);
- *ptr_col8++ = rgb8(col);
- }
- return cmd_stripe24(dev, dest_base16, dest_base8, width);
-}
-
-
-static dlo_retcode_t cmd_stripe24(dlo_device_t * const dev, dlo_ptr_t base16, dlo_ptr_t base8, const uint32_t width)
-{
- dlo_col16_t *ptr_col16 = stripe16;
- dlo_col8_t *ptr_col8 = stripe8;
- dlo_ptr_t end = base16 + (BYTES_PER_16BPP * width);
- uint32_t rem = width;
- uint32_t pix;
-
- /* Flush the command buffer if it's getting full */
- if (dev->bufend - dev->bufptr < BUF_HIGH_WATER_MARK)
- ERR(dlo_usb_write(dev));
-
- for (; base16 < end; base16 += BYTES_PER_16BPP * RAW_MAX_PIXELS)
- {
- *(dev->bufptr)++ = WRITE_RAW16[0];
- *(dev->bufptr)++ = WRITE_RAW16[1];
- *(dev->bufptr)++ = (char)(base16 >> 16);
- *(dev->bufptr)++ = (char)(base16 >> 8);
- *(dev->bufptr)++ = (char)(base16 & 0xFF);
- *(dev->bufptr)++ = rem >= RAW_MAX_PIXELS ? 0 : rem;
-
- /* Flush the command buffer if it's getting full */
- if (dev->bufend - dev->bufptr - BYTES_PER_16BPP * RAW_MAX_PIXELS < BUF_HIGH_WATER_MARK)
- ERR(dlo_usb_write(dev));
-
- for (pix = 0; pix < (rem >= RAW_MAX_PIXELS ? RAW_MAX_PIXELS : rem); pix++)
- {
- dlo_col16_t col = *ptr_col16++;
-
- *(dev->bufptr)++ = (char)(col >> 8);
- *(dev->bufptr)++ = (char)(col & 0xFF);
- }
- rem -= RAW_MAX_PIXELS;
- }
-
- end = base8 + (BYTES_PER_8BPP * width);
-
- for (; base8 < end; base8 += BYTES_PER_8BPP * RAW_MAX_PIXELS)
- {
- *(dev->bufptr)++ = WRITE_RAW8[0];
- *(dev->bufptr)++ = WRITE_RAW8[1];
- *(dev->bufptr)++ = (char)(base8 >> 16);
- *(dev->bufptr)++ = (char)(base8 >> 8);
- *(dev->bufptr)++ = (char)(base8 & 0xFF);
- *(dev->bufptr)++ = rem >= RAW_MAX_PIXELS ? 0 : rem;
-
- /* Flush the command buffer if it's getting full */
- if (dev->bufend - dev->bufptr - BYTES_PER_8BPP * RAW_MAX_PIXELS < BUF_HIGH_WATER_MARK)
- ERR(dlo_usb_write(dev));
-
- for (pix = 0; pix < (rem >= RAW_MAX_PIXELS ? RAW_MAX_PIXELS : rem); pix++)
- *(dev->bufptr)++ = (char)(*ptr_col8++);
-
- rem -= RAW_MAX_PIXELS;
- }
- return dlo_ok;
-}
-
-
-static dlo_col32_t read_pixel_NULL(const uint8_t * const ptr, const bool swap)
-{
- DPRINTF("grfx: WARNING: unknown dlo_pixfmt_t doesn't map to a read_pixel_*() function\n");
- return DLO_RGB(0, 0, 0);
-}
-
-
-static dlo_col32_t read_pixel_323(const uint8_t * const ptr, const bool swap)
-{
- dlo_col32_t col = lut[*ptr];
-
- if (swap)
- {
- uint8_t red, grn, blu;
-
- red = DLO_RGB_GETRED(col);
- grn = DLO_RGB_GETGRN(col);
- blu = DLO_RGB_GETBLU(col);
- return DLO_RGB(blu, grn, red);
- }
- return col;
-}
-
-
-static dlo_col32_t read_pixel_565(const uint8_t * const ptr, const bool swap)
-{
- dlo_col32_t col;
- uint16_t *pix = (uint16_t *)ptr;
- uint8_t red, grn, blu;
-
- col = *pix;
- red = (col & 0x001F) << 3;
- grn = (col & 0x07E0) >> 3;
- blu = (col & 0xF800) >> 8;
- red = red | (red >> 5);
- grn = grn | (grn >> 5);
- blu = blu | (blu >> 5);
-
- return swap ? DLO_RGB(blu, grn, red) : DLO_RGB(red, grn, blu);
-}
-
-
-static dlo_col32_t read_pixel_1555(const uint8_t * const ptr, const bool swap)
-{
- dlo_col32_t col;
- uint16_t *pix = (uint16_t *)ptr;
- uint8_t red, grn, blu;
-
- col = *pix;
- red = (col & 0x001F) << 3;
- grn = (col & 0x03E0) >> 2;
- blu = (col & 0x7C00) >> 7;
- red = red | (red >> 5);
- grn = grn | (grn >> 5);
- blu = blu | (blu >> 5);
-
- return swap ? DLO_RGB(blu, grn, red) : DLO_RGB(red, grn, blu);
-}
-
-
-static dlo_col32_t read_pixel_888(const uint8_t * const ptr, const bool swap)
-{
- uint8_t red, grn, blu;
-
- red = ptr[0];
- grn = ptr[1];
- blu = ptr[2];
-
- return swap ? DLO_RGB(blu, grn, red) : DLO_RGB(red, grn, blu);
-}
-
-
-static dlo_col32_t read_pixel_8888(const uint8_t * const ptr, const bool swap)
-{
- dlo_col32_t col;
- uint32_t *pix = (uint32_t *)ptr;
-
- col = (dlo_col32_t) *pix;
-
- if (swap)
- {
- uint8_t red, grn, blu;
-
- red = DLO_RGB_GETRED(col);
- grn = DLO_RGB_GETGRN(col);
- blu = DLO_RGB_GETBLU(col);
- return DLO_RGB(blu, grn, red);
- }
- return col;
-}
-
-
-static dlo_col8_t rgb8(dlo_col32_t col)
-{
- uint8_t red = DLO_RGB_GETRED(col);
- uint8_t grn = DLO_RGB_GETGRN(col);
- uint8_t blu = DLO_RGB_GETBLU(col);
-
- return DLO_RGB8(red, grn, blu);
-}
-
-
-static dlo_col16_t rgb16(dlo_col32_t col)
-{
- uint8_t red = DLO_RGB_GETRED(col);
- uint8_t grn = DLO_RGB_GETGRN(col);
- uint8_t blu = DLO_RGB_GETBLU(col);
-
- return (DLO_RG16(red, grn) << 8) + DLO_GB16(grn, blu);
-}
-
-
-/* End of file -------------------------------------------------------------------------*/
+/** @file dlo_grfx.c
+ *
+ * @brief This file implements the graphics primitive operations.
+ *
+ * DisplayLink Open Source Software (libdlo)
+ * Copyright (C) 2009, DisplayLink
+ * www.displaylink.com
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by the Free
+ * Software Foundation; LGPL version 2, dated June 1991.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include "dlo_defs.h"
+#include "dlo_grfx.h"
+#include "dlo_usb.h"
+
+
+/* File-scope defines ------------------------------------------------------------------*/
+
+
+/** Maximum number of pixels that can be supplied to a raw write command. */
+#define RAW_MAX_PIXELS (256)
+
+/** Maximum number of pixels that will fit into the scrape buffer. */
+#define SCRAPE_MAX_PIXELS (2048)
+
+/** Simple wrapper around the @c dlo_free() call to first check the pointer and zero it after the free. */
+#define FREE(ptr) { if (ptr) { dlo_free(ptr); ptr = NULL; } }
+
+/** Return red/green component of a 16 bpp colour number. */
+#define DLO_RG16(red, grn) (uint8_t)((((red) & 0xF8) | ((grn) >> 5)) & 0xFF)
+
+/** Return green/blue component of a 16 bpp colour number. */
+#define DLO_GB16(grn, blu) (uint8_t)(((((grn) & 0x1C) << 3) | ((blu) >> 3)) & 0xFF)
+
+/** Return 8 bpp colour number from red, green and blue components. */
+#define DLO_RGB8(red, grn, blu) ((((red) << 5) | (((grn) & 3) << 3) | ((blu) & 7)) & 0xFF)
+
+
+/* File-scope inline functions ---------------------------------------------------------*/
+
+
+/** Build a "plot horizontal line" command in a buffer.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param base Destination address in device for start of line.
+ * @param remain Line length.
+ * @param col Colour of point to plot.
+ *
+ * @return Return code, zero for no error.
+ */
+inline dlo_retcode_t cmd_hline16(dlo_device_t * const dev, const dlo_ptr_t base, const uint32_t remain, const dlo_col16_t col)
+{
+ if (dev->bufend - dev->bufptr < 9)
+ return dlo_err_buf_full;
+
+ *(dev->bufptr)++ = WRITE_RL16[0];
+ *(dev->bufptr)++ = WRITE_RL16[1];
+ *(dev->bufptr)++ = (char)(base >> 16);
+ *(dev->bufptr)++ = (char)(base >> 8);
+ *(dev->bufptr)++ = (char)base;
+ *(dev->bufptr)++ = (char)remain;
+ *(dev->bufptr)++ = (char)remain;
+ *(dev->bufptr)++ = (char)(col >> 8);
+ *(dev->bufptr)++ = (char)col;
+
+ return dlo_ok;
+}
+
+
+
+/** Build a "plot horizontal line" command in a buffer for fine detail colour space.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param base Destination address in device for start of line.
+ * @param remain Line length.
+ * @param col Colour of point to plot.
+ *
+ * @return Return code, zero for no error.
+ */
+inline dlo_retcode_t cmd_hline8(dlo_device_t * const dev, const dlo_ptr_t base, const uint32_t remain, const dlo_col8_t col)
+{
+ if (dev->bufend - dev->bufptr < 8)
+ return dlo_err_buf_full;
+
+ *(dev->bufptr)++ = WRITE_RL8[0];
+ *(dev->bufptr)++ = WRITE_RL8[1];
+ *(dev->bufptr)++ = (char)(base >> 16);
+ *(dev->bufptr)++ = (char)(base >> 8);
+ *(dev->bufptr)++ = (char)base;
+ *(dev->bufptr)++ = (char)remain;
+ *(dev->bufptr)++ = (char)remain;
+ *(dev->bufptr)++ = (char)col;
+
+ return dlo_ok;
+}
+
+
+/** Build a "copy horizontal line" command in a buffer.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param src Source address in device for start of copy.
+ * @param len Copy length.
+ * @param dest Destination address in device for copy.
+ *
+ * @return Return code, zero for no error.
+ */
+inline dlo_retcode_t cmd_copy16(dlo_device_t * const dev, const dlo_ptr_t src, const uint32_t len, const dlo_ptr_t dest)
+{
+ if (dev->bufend - dev->bufptr < 9)
+ return dlo_err_buf_full;
+
+ *(dev->bufptr)++ = WRITE_COPY16[0];
+ *(dev->bufptr)++ = WRITE_COPY16[1];
+ *(dev->bufptr)++ = (char)(dest >> 16);
+ *(dev->bufptr)++ = (char)(dest >> 8);
+ *(dev->bufptr)++ = (char)dest;
+ *(dev->bufptr)++ = len == 256 ? '\0' : (char)len;
+ *(dev->bufptr)++ = (char)(src >> 16);
+ *(dev->bufptr)++ = (char)(src >> 8);
+ *(dev->bufptr)++ = (char)src;
+
+ return dlo_ok;
+}
+
+
+/** Build a "copy horizontal line" command in a buffer for fine detail colour space.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param src Source address in device for start of copy.
+ * @param len Copy length.
+ * @param dest Destination address in device for copy.
+ *
+ * @return Return code, zero for no error.
+ */
+inline dlo_retcode_t cmd_copy8(dlo_device_t * const dev, const dlo_ptr_t src, const uint32_t len, const dlo_ptr_t dest)
+{
+ if (dev->bufend - dev->bufptr < 9)
+ return dlo_err_buf_full;
+
+ *(dev->bufptr)++ = WRITE_COPY8[0];
+ *(dev->bufptr)++ = WRITE_COPY8[1];
+ *(dev->bufptr)++ = (char)(dest >> 16);
+ *(dev->bufptr)++ = (char)(dest >> 8);
+ *(dev->bufptr)++ = (char)dest;
+ *(dev->bufptr)++ = len == 256 ? '\0' : (char)len;
+ *(dev->bufptr)++ = (char)(src >> 16);
+ *(dev->bufptr)++ = (char)(src >> 8);
+ *(dev->bufptr)++ = (char)src;
+
+ return dlo_ok;
+}
+
+
+/* Ensure the inline functions get compiled somewhere in case they cannot be inlined */
+extern dlo_retcode_t cmd_hline16(dlo_device_t * const dev, const dlo_ptr_t base, const uint32_t remain, const dlo_col16_t col);
+extern dlo_retcode_t cmd_hline8( dlo_device_t * const dev, const dlo_ptr_t base, const uint32_t remain, const dlo_col8_t col);
+extern dlo_retcode_t cmd_copy16( dlo_device_t * const dev, const dlo_ptr_t src, const uint32_t len, const dlo_ptr_t dest);
+extern dlo_retcode_t cmd_copy8( dlo_device_t * const dev, const dlo_ptr_t src, const uint32_t len, const dlo_ptr_t dest);
+
+
+/* File-scope types --------------------------------------------------------------------*/
+
+
+/** Function pointer for functions to convert a pixel into a colour number.
+ *
+ * @param ptr Pointer to pixel.
+ * @param swap Flag to indicate red and blue components need to be swapped.
+ *
+ * @return Colour number for read pixel.
+ */
+typedef dlo_col32_t (*read_pixel_t) (const uint8_t * const ptr, const bool swap);
+
+
+/* File-scope variables ----------------------------------------------------------------*/
+
+
+/** Look-up table of function pointers for a specified pixel format.
+ */
+static read_pixel_t fmt_to_fn[DLO_PIXFMT_MAX];
+
+
+/** Standard look-up table for converting 8 bpp pixels in bgr323 format into colour numbers.
+ */
+static dlo_col32_t lut8bpp[256];
+
+
+/** Look-up table to use when reading 8 bpp pixels - required by @c read_pixel_323().
+ */
+static dlo_col32_t *lut = lut8bpp;
+
+
+/** Pointer to an array for storing a stripe of 16bpp pixel information.
+ */
+static dlo_col16_t *stripe16 = NULL;
+
+
+/** Pointer to an array for storing a stripe of 8bpp pixel information.
+ */
+static dlo_col8_t *stripe8 = NULL;
+
+
+/* External-scope variables ------------------------------------------------------------*/
+
+
+/* File-scope function declarations ----------------------------------------------------*/
+
+
+/** Plot a section of horizontal line in the specified colour at 24 bpp.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param base16 Base address of destination 16 bpp pixel data.
+ * @param base8 Base address of destination 8 bpp pixel data.
+ * @param len Length of the line (pixels).
+ * @param col Colour of the line.
+ *
+ * @return Return code, zero for no error.
+ */
+static dlo_retcode_t hline_24bpp(dlo_device_t * const dev, dlo_ptr_t base16, dlo_ptr_t base8, const uint32_t len, const dlo_col32_t col);
+
+
+/** Copy a section of horizontal line from one location to another at 24 bpp.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param src_base16 Base address of source 16 bpp pixel data.
+ * @param dest_base16 Base address of destination 16 bpp pixel data.
+ * @param src_base8 Base address of source 8 bpp pixel data.
+ * @param dest_base8 Base address of destination 8 bpp pixel data.
+ * @param len Length of the line (pixels).
+ *
+ * @return Return code, zero for no error.
+ */
+static dlo_retcode_t copy_24bpp(dlo_device_t * const dev, dlo_ptr_t src_base16, dlo_ptr_t dest_base16, dlo_ptr_t src_base8, dlo_ptr_t dest_base8, const uint32_t len);
+
+
+/** Scrape a horizontal line of host-resident pixels at 24 bpp into the device.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param rdpx Pointer to the pixel reading function.
+ * @param bypp Bytes per pixel of the source pixels.
+ * @param swap Flag: swap the red/blue component order.
+ * @param src_base Base address of the source.
+ * @param dest_base16 Base address of destination 16 bpp pixel data.
+ * @param dest_base8 Base address of destination 8 bpp pixel data.
+ * @param width Width of the scrape (pixels).
+ *
+ * @return Return code, zero for no error.
+ */
+static dlo_retcode_t scrape_24bpp(dlo_device_t * const dev, const read_pixel_t rdpx, const uint32_t bypp, const bool swap,
+ const uint8_t *src_base, dlo_ptr_t dest_base16, dlo_ptr_t dest_base8, const uint32_t width);
+
+
+/** Dump the contents of the scrape buffers as a horizontal pixel row at 24 bpp.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param base16 Base address of destination 16 bpp pixel data.
+ * @param base8 Base address of destination 8 bpp pixel data.
+ * @param width Width of the scrape (pixels).
+ *
+ * @return Return code, zero for no error.
+ */
+static dlo_retcode_t cmd_stripe24(dlo_device_t * const dev, dlo_ptr_t base16, dlo_ptr_t base8, const uint32_t width);
+
+
+/** Given a 32 bpp colour number, return an 8 bpp colour number.
+ *
+ * @param col 32 bpp colour number.
+ *
+ * @return 8 bpp colour number.
+ */
+static dlo_col8_t rgb8(dlo_col32_t col);
+
+
+/** Given a 32 bpp colour number, return a 16 bpp colour number.
+ *
+ * @param col 32 bpp colour number.
+ *
+ * @return 16 bpp colour number.
+ */
+static dlo_col16_t rgb16(dlo_col32_t col);
+
+
+/** Dummy pixel reading function for an uninitialised entry.
+ *
+ * @param ptr Pointer to pixel.
+ * @param swap Flag to indicate red and blue components need to be swapped.
+ *
+ * @return Colour number for read pixel.
+ */
+static dlo_col32_t read_pixel_NULL(const uint8_t * const ptr, const bool swap);
+
+
+/** Read an 8 bpp pixel in 323 format.
+ *
+ * @param ptr Pointer to pixel.
+ * @param swap Flag to indicate red and blue components need to be swapped.
+ *
+ * @return Colour number for read pixel.
+ */
+static dlo_col32_t read_pixel_323(const uint8_t * const ptr, const bool swap);
+
+
+/** Read a 16 bpp pixel in 565 format.
+ *
+ * @param ptr Pointer to pixel.
+ * @param swap Flag to indicate red and blue components need to be swapped.
+ *
+ * @return Colour number for read pixel.
+ */
+static dlo_col32_t read_pixel_565(const uint8_t * const ptr, const bool swap);
+
+
+/** Read a 16 bpp pixel in 1555 format.
+ *
+ * @param ptr Pointer to pixel.
+ * @param swap Flag to indicate red and blue components need to be swapped.
+ *
+ * @return Colour number for read pixel.
+ */
+static dlo_col32_t read_pixel_1555(const uint8_t * const ptr, const bool swap);
+
+
+/** Read a 24 bpp pixel in 888 format.
+ *
+ * @param ptr Pointer to pixel.
+ * @param swap Flag to indicate red and blue components need to be swapped.
+ *
+ * @return Colour number for read pixel.
+ */
+static dlo_col32_t read_pixel_888(const uint8_t * const ptr, const bool swap);
+
+
+/** Read a 32 bpp pixel in 8888 format.
+ *
+ * @param ptr Pointer to pixel.
+ * @param swap Flag to indicate red and blue components need to be swapped.
+ *
+ * @return Colour number for read pixel.
+ */
+static dlo_col32_t read_pixel_8888(const uint8_t * const ptr, const bool swap);
+
+
+/* Public function definitions ---------------------------------------------------------*/
+
+
+dlo_retcode_t dlo_grfx_init(const dlo_init_t flags)
+{
+ uint32_t i;
+ uint8_t red, grn, blu;
+ uint8_t red8, grn8, blu8;
+
+ stripe16 = malloc(SCRAPE_MAX_PIXELS * sizeof(dlo_col16_t));
+ NERR(stripe16);
+ stripe8 = malloc(SCRAPE_MAX_PIXELS * sizeof(dlo_col8_t));
+ NERR(stripe8);
+
+ /* Initialise the default look-up table for 8 bpp in bgr323 format */
+ for (red = 0; red < 8; red++)
+ for (grn = 0; grn < 4; grn++)
+ for (blu = 0; blu < 8; blu++)
+ {
+ uint8_t idx = red + (grn << 3) + (blu << 5);
+
+ red8 = (red << 5) | (red << 2) | (red >> 1);
+ grn8 = (grn << 6) | (grn << 4) | (grn << 2) | grn;
+ blu8 = (blu << 5) | (blu << 2) | (blu >> 1);
+ lut8bpp[idx] = DLO_RGB(red8, grn8, blu8);
+ }
+
+ /* Initialise the look-up table of pixel formats to pixel reading functions */
+ for (i = 0; i < DLO_PIXFMT_MAX; i++)
+ fmt_to_fn[i] = read_pixel_NULL;
+ fmt_to_fn[dlo_pixfmt_bgr323] = read_pixel_323;
+ fmt_to_fn[dlo_pixfmt_rgb323] = read_pixel_323;
+ fmt_to_fn[dlo_pixfmt_bgr565] = read_pixel_565;
+ fmt_to_fn[dlo_pixfmt_rgb565] = read_pixel_565;
+ fmt_to_fn[dlo_pixfmt_sbgr1555] = read_pixel_1555;
+ fmt_to_fn[dlo_pixfmt_srgb1555] = read_pixel_1555;
+ fmt_to_fn[dlo_pixfmt_bgr888] = read_pixel_888;
+ fmt_to_fn[dlo_pixfmt_rgb888] = read_pixel_888;
+ fmt_to_fn[dlo_pixfmt_abgr8888] = read_pixel_8888;
+ fmt_to_fn[dlo_pixfmt_argb8888] = read_pixel_8888;
+
+ return dlo_ok;
+}
+
+
+dlo_retcode_t dlo_grfx_final(const dlo_final_t flags)
+{
+ FREE(stripe16);
+ FREE(stripe8);
+
+ return dlo_ok;
+}
+
+
+dlo_retcode_t dlo_grfx_fill_rect(dlo_device_t * const dev, const dlo_area_t * const area, const dlo_col32_t col)
+{
+ dlo_ptr_t base16, base8;
+ uint32_t end;
+
+ ASSERT(dev && area)
+ ASSERT(area->view.width && area->view.height);
+
+ /* Only 24 bpp is supported */
+ if (area->view.bpp != 24)
+ return dlo_err_bad_col;
+
+ /* Compute some useful values */
+ base16 = area->view.base;
+ base8 = area->base8;
+ end = base16 + (BYTES_PER_16BPP * area->stride * area->view.height);
+
+ /* Plot the rectangle, one pixel row at a time */
+ for (; base16 < end; base16 += BYTES_PER_16BPP * area->stride)
+ {
+ ERR(hline_24bpp(dev, base16, base8, area->view.width, col));
+ base8 += BYTES_PER_8BPP * area->stride;
+ }
+ return dlo_usb_write(dev);
+}
+
+
+dlo_retcode_t dlo_grfx_copy_rect(dlo_device_t * const dev, const dlo_area_t * const src_area, const dlo_area_t * const dest_area, const bool overlap)
+{
+ dlo_ptr_t src_base16, src_base8;
+ dlo_ptr_t dest_base16, dest_base8;
+ uint32_t end;
+
+ ASSERT(dev && src_area && dest_area);
+ ASSERT(src_area->view.width && src_area->view.height);
+ ASSERT(src_area->view.width == dest_area->view.width && src_area->view.height == dest_area->view.height);
+ ASSERT(src_area->view.bpp == dest_area->view.bpp);
+
+ /* Only 24 bpp is supported */
+ if (src_area->view.bpp != 24)
+ return dlo_err_bad_col;
+
+ /* Quick exit if we're copying to and from the same location */
+ if (src_area->view.base == dest_area->view.base)
+ return dlo_ok;
+
+ /* Compute some useful values */
+ if (src_area->view.base < dest_area->view.base)
+ {
+ uint32_t y;
+
+ src_base16 = src_area->view.base + (BYTES_PER_16BPP * src_area->stride * src_area->view.height);
+ src_base8 = src_area->base8 + (BYTES_PER_8BPP * src_area->stride * src_area->view.height);
+ dest_base16 = dest_area->view.base + (BYTES_PER_16BPP * dest_area->stride * dest_area->view.height);
+ dest_base8 = dest_area->base8 + (BYTES_PER_8BPP * dest_area->stride * dest_area->view.height);
+
+ /* Copy the rectangle, one pixel row at a time */
+ for (y = src_area->view.height; y > 0; y--)
+ {
+ src_base16 -= BYTES_PER_16BPP * src_area->stride;
+ src_base8 -= BYTES_PER_8BPP * src_area->stride;
+ dest_base16 -= BYTES_PER_16BPP * dest_area->stride;
+ dest_base8 -= BYTES_PER_8BPP * dest_area->stride;
+ ERR(copy_24bpp(dev, src_base16, dest_base16, src_base8, dest_base8, src_area->view.width));
+// if (overlap)
+// ERR(dlo_usb_write(dev));
+ }
+ }
+ else
+ {
+ src_base16 = src_area->view.base;
+ src_base8 = src_area->base8;
+ dest_base16 = dest_area->view.base;
+ dest_base8 = dest_area->base8;
+ end = src_base16 + (BYTES_PER_16BPP * src_area->stride * src_area->view.height);
+
+ /* Copy the rectangle, one pixel row at a time */
+ for (; src_base16 < end; src_base16 += BYTES_PER_16BPP * src_area->stride)
+ {
+ ERR(copy_24bpp(dev, src_base16, dest_base16, src_base8, dest_base8, src_area->view.width));
+ src_base8 += BYTES_PER_8BPP * src_area->stride;
+ dest_base16 += BYTES_PER_16BPP * dest_area->stride;
+ dest_base8 += BYTES_PER_8BPP * dest_area->stride;
+// if (overlap)
+// ERR(dlo_usb_write(dev));
+ }
+ }
+ return dlo_usb_write(dev);
+}
+
+
+dlo_retcode_t dlo_grfx_copy_host_bmp(dlo_device_t * const dev, const dlo_bmpflags_t flags, const dlo_fbuf_t const *fbuf, const dlo_area_t * const area)
+{
+ uint8_t *src_base;
+ uint8_t *end;
+ dlo_ptr_t dest_base16, dest_base8;
+ uint32_t bypp;
+ read_pixel_t rdpx;
+ bool swap;
+
+ ASSERT(dev && fbuf && area);
+ ASSERT(fbuf->width && fbuf->height && fbuf->base && fbuf->stride);
+ ASSERT(fbuf->width == area->view.width && fbuf->height == area->view.height)
+
+ /* Only 24 bpp is supported */
+ if (area->view.bpp != 24)
+ return dlo_err_bad_col;
+
+ /* Get a pixel reading function pointer for the fbuf */
+ if (fbuf->fmt >> DLO_PIXFMT_PTR_SFT)
+ {
+ bypp = 1;
+ rdpx = read_pixel_323;
+ swap = false;
+ lut = (dlo_col32_t *)fbuf->fmt;
+ }
+ else
+ {
+ if ((int)fbuf->fmt > (int)dlo_pixfmt_argb8888)
+ return dlo_err_bad_fmt;
+
+ bypp = FORMAT_TO_BYTES_PER_PIXEL(fbuf->fmt);
+ rdpx = fmt_to_fn[fbuf->fmt];
+ swap = fbuf->fmt & DLO_PIXFMT_SWP ? true : false;
+ lut = lut8bpp; /* For unpaletted bitmaps, the LUT is our standard colour palette */
+ }
+
+ /* Check that a row from the bitmap will fit into the scrape buffers */
+ if (fbuf->width > SCRAPE_MAX_PIXELS)
+ return dlo_err_big_scrape;
+
+ /* Set up the destination pointers in the device memory */
+ dest_base16 = area->view.base;
+ dest_base8 = area->base8;
+
+ /* Either copy down or up the bitmap, depending upon whether we are doing a vertical flip */
+ if (flags.v_flip)
+ {
+ src_base = (uint8_t *)fbuf->base + (bypp * fbuf->stride * (area->view.height - 1));
+ end = (uint8_t *)fbuf->base;
+
+ for (; src_base >= end; src_base -= bypp * fbuf->stride)
+ {
+ ERR(scrape_24bpp(dev, rdpx, bypp, swap, src_base, dest_base16, dest_base8, fbuf->width));
+ dest_base16 += BYTES_PER_16BPP * area->stride;
+ dest_base8 += BYTES_PER_8BPP * area->stride;
+ }
+ }
+ else
+ {
+ src_base = (uint8_t *)fbuf->base;
+ end = src_base + (bypp * fbuf->stride * area->view.height);
+
+ for (; src_base < end; src_base += bypp * fbuf->stride)
+ {
+ ERR(scrape_24bpp(dev, rdpx, bypp, swap, src_base, dest_base16, dest_base8, fbuf->width));
+ dest_base16 += BYTES_PER_16BPP * area->stride;
+ dest_base8 += BYTES_PER_8BPP * area->stride;
+ }
+ }
+ return dlo_usb_write(dev);
+}
+
+
+/* File-scope function definitions -----------------------------------------------------*/
+
+
+static dlo_retcode_t hline_24bpp(dlo_device_t * const dev, dlo_ptr_t base16, dlo_ptr_t base8, const uint32_t len, const dlo_col32_t col)
+{
+ dlo_col16_t col16 = rgb16(col);
+ dlo_col8_t col8 = rgb8(col);
+ uint32_t rem = len % 256;
+
+ /* Flush the command buffer if it's getting full */
+ if (dev->bufend - dev->bufptr < BUF_HIGH_WATER_MARK)
+ ERR(dlo_usb_write(dev));
+
+ /* Is this a short line segment? */
+ if (len < 256)
+ {
+ ERR(cmd_hline16(dev, base16, len, col16));
+ ERR(cmd_hline8( dev, base8, len, col8));
+ }
+ else
+ {
+ /* Longer line segments require a few commands to complete */
+ uint32_t roff16 = base16 + (BYTES_PER_16BPP * (len - rem));
+ uint32_t roff8 = base8 + (BYTES_PER_8BPP * (len - rem));
+
+ for (; base16 < roff16; base16 += BYTES_PER_16BPP * 256)
+ {
+ ERR(cmd_hline16(dev, base16, 0, col16));
+ ERR(cmd_hline8( dev, base8, 0, col8));
+ base8 += BYTES_PER_8BPP * 256;
+ }
+ if (rem)
+ {
+ ERR(cmd_hline16(dev, roff16, rem, col16));
+ ERR(cmd_hline8( dev, roff8, rem, col8));
+ }
+ }
+ return dlo_ok;
+}
+
+
+static dlo_retcode_t copy_24bpp(dlo_device_t * const dev, dlo_ptr_t src_base16, dlo_ptr_t dest_base16, dlo_ptr_t src_base8, dlo_ptr_t dest_base8, const uint32_t len)
+{
+ uint32_t rem = len % 256;
+
+ /* Flush the command buffer if it's getting full */
+ if (dev->bufend - dev->bufptr < BUF_HIGH_WATER_MARK)
+ ERR(dlo_usb_write(dev));
+
+ /* Is this a short line segment? */
+ if (len < 256)
+ {
+ ERR(cmd_copy16(dev, src_base16, len, dest_base16));
+ ERR(cmd_copy8( dev, src_base8, len, dest_base8));
+ }
+ else
+ {
+ /* Longer line segments require a few commands to complete */
+ uint32_t src_roff16 = src_base16 + (BYTES_PER_16BPP * (len - rem));
+ uint32_t dest_roff16 = dest_base16 + (BYTES_PER_16BPP * (len - rem));
+ uint32_t src_roff8 = src_base8 + (BYTES_PER_8BPP * (len - rem));
+ uint32_t dest_roff8 = dest_base8 + (BYTES_PER_8BPP * (len - rem));
+
+ for (; src_base16 < src_roff16; src_base16 += BYTES_PER_16BPP * 256)
+ {
+ ERR(cmd_copy16(dev, src_base16, 0, dest_base16));
+ ERR(cmd_copy8( dev, src_base8, 0, dest_base8));
+ dest_base16 += BYTES_PER_16BPP * 256;
+ src_base8 += BYTES_PER_8BPP * 256;
+ dest_base8 += BYTES_PER_8BPP * 256;
+ }
+ if (rem)
+ {
+ ERR(cmd_copy16(dev, src_roff16, rem, dest_roff16));
+ ERR(cmd_copy8( dev, src_roff8, rem, dest_roff8));
+ }
+ }
+ return dlo_ok;
+}
+
+
+static dlo_retcode_t scrape_24bpp(dlo_device_t * const dev, const read_pixel_t rdpx, const uint32_t bypp, const bool swap,
+ const uint8_t *src_base, dlo_ptr_t dest_base16, dlo_ptr_t dest_base8, const uint32_t width)
+{
+ const uint8_t *end = src_base + (bypp * width);
+ dlo_col16_t *ptr_col16 = stripe16;
+ dlo_col8_t *ptr_col8 = stripe8;
+
+ /* Read a stripe from the source bitmap into the internal colour format */
+ for (; src_base < end; src_base += bypp)
+ {
+ dlo_col32_t col = rdpx(src_base, swap);
+
+ *ptr_col16++ = rgb16(col);
+ *ptr_col8++ = rgb8(col);
+ }
+ return cmd_stripe24(dev, dest_base16, dest_base8, width);
+}
+
+
+static dlo_retcode_t cmd_stripe24(dlo_device_t * const dev, dlo_ptr_t base16, dlo_ptr_t base8, const uint32_t width)
+{
+ dlo_col16_t *ptr_col16 = stripe16;
+ dlo_col8_t *ptr_col8 = stripe8;
+ dlo_ptr_t end = base16 + (BYTES_PER_16BPP * width);
+ uint32_t rem = width;
+ uint32_t pix;
+
+ /* Flush the command buffer if it's getting full */
+ if (dev->bufend - dev->bufptr < BUF_HIGH_WATER_MARK)
+ ERR(dlo_usb_write(dev));
+
+ for (; base16 < end; base16 += BYTES_PER_16BPP * RAW_MAX_PIXELS)
+ {
+ *(dev->bufptr)++ = WRITE_RAW16[0];
+ *(dev->bufptr)++ = WRITE_RAW16[1];
+ *(dev->bufptr)++ = (char)(base16 >> 16);
+ *(dev->bufptr)++ = (char)(base16 >> 8);
+ *(dev->bufptr)++ = (char)(base16 & 0xFF);
+ *(dev->bufptr)++ = rem >= RAW_MAX_PIXELS ? 0 : rem;
+
+ /* Flush the command buffer if it's getting full */
+ if (dev->bufend - dev->bufptr - BYTES_PER_16BPP * RAW_MAX_PIXELS < BUF_HIGH_WATER_MARK)
+ ERR(dlo_usb_write(dev));
+
+ for (pix = 0; pix < (rem >= RAW_MAX_PIXELS ? RAW_MAX_PIXELS : rem); pix++)
+ {
+ dlo_col16_t col = *ptr_col16++;
+
+ *(dev->bufptr)++ = (char)(col >> 8);
+ *(dev->bufptr)++ = (char)(col & 0xFF);
+ }
+ rem -= RAW_MAX_PIXELS;
+ }
+
+ end = base8 + (BYTES_PER_8BPP * width);
+
+ for (; base8 < end; base8 += BYTES_PER_8BPP * RAW_MAX_PIXELS)
+ {
+ *(dev->bufptr)++ = WRITE_RAW8[0];
+ *(dev->bufptr)++ = WRITE_RAW8[1];
+ *(dev->bufptr)++ = (char)(base8 >> 16);
+ *(dev->bufptr)++ = (char)(base8 >> 8);
+ *(dev->bufptr)++ = (char)(base8 & 0xFF);
+ *(dev->bufptr)++ = rem >= RAW_MAX_PIXELS ? 0 : rem;
+
+ /* Flush the command buffer if it's getting full */
+ if (dev->bufend - dev->bufptr - BYTES_PER_8BPP * RAW_MAX_PIXELS < BUF_HIGH_WATER_MARK)
+ ERR(dlo_usb_write(dev));
+
+ for (pix = 0; pix < (rem >= RAW_MAX_PIXELS ? RAW_MAX_PIXELS : rem); pix++)
+ *(dev->bufptr)++ = (char)(*ptr_col8++);
+
+ rem -= RAW_MAX_PIXELS;
+ }
+ return dlo_ok;
+}
+
+
+static dlo_col32_t read_pixel_NULL(const uint8_t * const ptr, const bool swap)
+{
+ DPRINTF("grfx: WARNING: unknown dlo_pixfmt_t doesn't map to a read_pixel_*() function\n");
+ return DLO_RGB(0, 0, 0);
+}
+
+
+static dlo_col32_t read_pixel_323(const uint8_t * const ptr, const bool swap)
+{
+ dlo_col32_t col = lut[*ptr];
+
+ if (swap)
+ {
+ uint8_t red, grn, blu;
+
+ red = DLO_RGB_GETRED(col);
+ grn = DLO_RGB_GETGRN(col);
+ blu = DLO_RGB_GETBLU(col);
+ return DLO_RGB(blu, grn, red);
+ }
+ return col;
+}
+
+
+static dlo_col32_t read_pixel_565(const uint8_t * const ptr, const bool swap)
+{
+ dlo_col32_t col;
+ uint16_t *pix = (uint16_t *)ptr;
+ uint8_t red, grn, blu;
+
+ col = *pix;
+ red = (col & 0x001F) << 3;
+ grn = (col & 0x07E0) >> 3;
+ blu = (col & 0xF800) >> 8;
+ red = red | (red >> 5);
+ grn = grn | (grn >> 5);
+ blu = blu | (blu >> 5);
+
+ return swap ? DLO_RGB(blu, grn, red) : DLO_RGB(red, grn, blu);
+}
+
+
+static dlo_col32_t read_pixel_1555(const uint8_t * const ptr, const bool swap)
+{
+ dlo_col32_t col;
+ uint16_t *pix = (uint16_t *)ptr;
+ uint8_t red, grn, blu;
+
+ col = *pix;
+ red = (col & 0x001F) << 3;
+ grn = (col & 0x03E0) >> 2;
+ blu = (col & 0x7C00) >> 7;
+ red = red | (red >> 5);
+ grn = grn | (grn >> 5);
+ blu = blu | (blu >> 5);
+
+ return swap ? DLO_RGB(blu, grn, red) : DLO_RGB(red, grn, blu);
+}
+
+
+static dlo_col32_t read_pixel_888(const uint8_t * const ptr, const bool swap)
+{
+ uint8_t red, grn, blu;
+
+ red = ptr[0];
+ grn = ptr[1];
+ blu = ptr[2];
+
+ return swap ? DLO_RGB(blu, grn, red) : DLO_RGB(red, grn, blu);
+}
+
+
+static dlo_col32_t read_pixel_8888(const uint8_t * const ptr, const bool swap)
+{
+ dlo_col32_t col;
+ uint32_t *pix = (uint32_t *)ptr;
+
+ col = (dlo_col32_t) *pix;
+
+ if (swap)
+ {
+ uint8_t red, grn, blu;
+
+ red = DLO_RGB_GETRED(col);
+ grn = DLO_RGB_GETGRN(col);
+ blu = DLO_RGB_GETBLU(col);
+ return DLO_RGB(blu, grn, red);
+ }
+ return col;
+}
+
+
+static dlo_col8_t rgb8(dlo_col32_t col)
+{
+ uint8_t red = DLO_RGB_GETRED(col);
+ uint8_t grn = DLO_RGB_GETGRN(col);
+ uint8_t blu = DLO_RGB_GETBLU(col);
+
+ return DLO_RGB8(red, grn, blu);
+}
+
+
+static dlo_col16_t rgb16(dlo_col32_t col)
+{
+ uint8_t red = DLO_RGB_GETRED(col);
+ uint8_t grn = DLO_RGB_GETGRN(col);
+ uint8_t blu = DLO_RGB_GETBLU(col);
+
+ return (DLO_RG16(red, grn) << 8) + DLO_GB16(grn, blu);
+}
+
+
+/* End of file -------------------------------------------------------------------------*/
diff --git a/src/dlo_grfx.h b/src/dlo_grfx.h
index 15ce3b9..58147c6 100644
--- a/src/dlo_grfx.h
+++ b/src/dlo_grfx.h
@@ -1,93 +1,93 @@
-/** @file dlo_grfx.h
- *
- * @brief This file defines the external API of the DisplayLink libdlo graphics functions.
- *
- * This API is used by clients of the Bitmap Manager (e.g. other parts of libdlo) to access its
- * features. It is intended that all implementation details are abstracted-away by this interface.
- *
- * DisplayLink Open Source Software (libdlo)
- * Copyright (C) 2009, DisplayLink
- * www.displaylink.com
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Library General Public License as published by the Free
- * Software Foundation; LGPL version 2, dated June 1991.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef DLO_GRFX_H
-#define DLO_GRFX_H /**< Avoid multiple inclusion. */
-
-#include "dlo_structs.h"
-
-
-#define WRITE_RAW8 "\xAF\x60" /**< 8 bit raw write command. */
-#define WRITE_RL8 "\xAF\x61" /**< 8 bit run length write command. */
-#define WRITE_COPY8 "\xAF\x62" /**< 8 bit copy command. */
-#define WRITE_RAW16 "\xAF\x68" /**< 16 bit raw write command. */
-#define WRITE_RL16 "\xAF\x69" /**< 16 bit run length write command. */
-#define WRITE_COPY16 "\xAF\x6A" /**< 16 bit copy command. */
-
-
-/** Initialise the graphics primitive routines.
- *
- * @param flags Initialisation flags word (unused flags ignored).
- *
- * @return Return code, zero for no error.
- */
-extern dlo_retcode_t dlo_grfx_init(const dlo_init_t flags);
-
-
-/** Finalisation call for graphics primitive routines.
- *
- * @param flags Finalisation flags word (unused flags ignored).
- *
- * @return Return code, zero for no error.
- */
-extern dlo_retcode_t dlo_grfx_final(const dlo_final_t flags);
-
-
-/** Plot a filled rectangle into the specified device.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param area Struct pointer: area within device memory to fill.
- * @param col Colour of filled rectangle.
- *
- * @return Return code, zero for no error.
- */
-extern dlo_retcode_t dlo_grfx_fill_rect(dlo_device_t * const dev, const dlo_area_t * const area, const dlo_col32_t col);
-
-
-/** Copy a rectangular area within the device from one location to another.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param src_area Struct pointer: area within device memory to copy from.
- * @param dest_area Struct pointer: area within device memory to copy to.
- * @param overlap true if rectangles overlap or false if not.
- *
- * @return Return code, zero for no error.
- */
-extern dlo_retcode_t dlo_grfx_copy_rect(dlo_device_t * const dev, const dlo_area_t * const src_area, const dlo_area_t * const dest_area, const bool overlap);
-
-
-/** Copy (and translate pixel formats) a rectangular area from host memory into the device.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param flags Flags word indicating special behaviour (unused flags should be zero).
- * @param fbuf Struct pointer: area within host memory to copy from.
- * @param area Struct pointer: area within device memory to copy into.
- *
- * @return Return code, zero for no error.
- */
-extern dlo_retcode_t dlo_grfx_copy_host_bmp(dlo_device_t * const dev, const dlo_bmpflags_t flags, const dlo_fbuf_t const *fbuf, const dlo_area_t * const area);
-
-
-#endif
+/** @file dlo_grfx.h
+ *
+ * @brief This file defines the external API of the DisplayLink libdlo graphics functions.
+ *
+ * This API is used by clients of the Bitmap Manager (e.g. other parts of libdlo) to access its
+ * features. It is intended that all implementation details are abstracted-away by this interface.
+ *
+ * DisplayLink Open Source Software (libdlo)
+ * Copyright (C) 2009, DisplayLink
+ * www.displaylink.com
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by the Free
+ * Software Foundation; LGPL version 2, dated June 1991.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef DLO_GRFX_H
+#define DLO_GRFX_H /**< Avoid multiple inclusion. */
+
+#include "dlo_structs.h"
+
+
+#define WRITE_RAW8 "\xAF\x60" /**< 8 bit raw write command. */
+#define WRITE_RL8 "\xAF\x61" /**< 8 bit run length write command. */
+#define WRITE_COPY8 "\xAF\x62" /**< 8 bit copy command. */
+#define WRITE_RAW16 "\xAF\x68" /**< 16 bit raw write command. */
+#define WRITE_RL16 "\xAF\x69" /**< 16 bit run length write command. */
+#define WRITE_COPY16 "\xAF\x6A" /**< 16 bit copy command. */
+
+
+/** Initialise the graphics primitive routines.
+ *
+ * @param flags Initialisation flags word (unused flags ignored).
+ *
+ * @return Return code, zero for no error.
+ */
+extern dlo_retcode_t dlo_grfx_init(const dlo_init_t flags);
+
+
+/** Finalisation call for graphics primitive routines.
+ *
+ * @param flags Finalisation flags word (unused flags ignored).
+ *
+ * @return Return code, zero for no error.
+ */
+extern dlo_retcode_t dlo_grfx_final(const dlo_final_t flags);
+
+
+/** Plot a filled rectangle into the specified device.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param area Struct pointer: area within device memory to fill.
+ * @param col Colour of filled rectangle.
+ *
+ * @return Return code, zero for no error.
+ */
+extern dlo_retcode_t dlo_grfx_fill_rect(dlo_device_t * const dev, const dlo_area_t * const area, const dlo_col32_t col);
+
+
+/** Copy a rectangular area within the device from one location to another.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param src_area Struct pointer: area within device memory to copy from.
+ * @param dest_area Struct pointer: area within device memory to copy to.
+ * @param overlap true if rectangles overlap or false if not.
+ *
+ * @return Return code, zero for no error.
+ */
+extern dlo_retcode_t dlo_grfx_copy_rect(dlo_device_t * const dev, const dlo_area_t * const src_area, const dlo_area_t * const dest_area, const bool overlap);
+
+
+/** Copy (and translate pixel formats) a rectangular area from host memory into the device.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param flags Flags word indicating special behaviour (unused flags should be zero).
+ * @param fbuf Struct pointer: area within host memory to copy from.
+ * @param area Struct pointer: area within device memory to copy into.
+ *
+ * @return Return code, zero for no error.
+ */
+extern dlo_retcode_t dlo_grfx_copy_host_bmp(dlo_device_t * const dev, const dlo_bmpflags_t flags, const dlo_fbuf_t const *fbuf, const dlo_area_t * const area);
+
+
+#endif
diff --git a/src/dlo_mode.c b/src/dlo_mode.c
index 68d27a4..c5ade6e 100644
--- a/src/dlo_mode.c
+++ b/src/dlo_mode.c
@@ -1,926 +1,926 @@
-/** @file dlo_mode.c
- *
- * @brief Implementation of the screen mode-related functions.
- *
- * See dlo_mode.h for more information.
- *
- * DisplayLink Open Source Software (libdlo)
- * Copyright (C) 2009, DisplayLink
- * www.displaylink.com
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Library General Public License as published by the Free
- * Software Foundation; LGPL version 2, dated June 1991.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include "dlo_defs.h"
-#include "dlo_mode.h"
-#include "dlo_data.h"
-#include "dlo_usb.h"
-
-
-/* File-scope defines ------------------------------------------------------------------*/
-
-
-/** Pre-defined EDID header used to check that data read from a device is valid.
- */
-const uint8_t header[8] =
-{
- 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
-};
-
-/** Constant used for deciding if a host is big- or little endian.
- */
-const uint32_t endian = 1;
-
-/** Unlock video registers command.
- */
-#define WRITE_VIDREG_LOCK "\xAF\x20\xFF\x00"
-
-/** Lock video registers command.
- */
-#define WRITE_VIDREG_UNLOCK "\xAF\x20\xFF\xFF\xAF\xA0"
-
-/** Return non-zero if the host is big endian or zero if the host is little endian.
- */
-#define IS_BIGENDIAN() ((*(char*)&endian) == '\0')
-
-/** Convert a 32 bit little endian value into a host byte-order value.
- *
- * @param val Little-endian 32 bit value to convert.
- *
- * @return Value in host byte order.
- */
-#define LETOHL(val) (IS_BIGENDIAN() ? swap_endian_l(val) : val)
-
-/** Convert a 16 bit little endian value into a host byte-order value.
- *
- * @param val Little-endian 16 bit value to convert.
- *
- * @return Value in host byte order.
- */
-#define LETOHS(val) (IS_BIGENDIAN() ? swap_endian_s(val) : val)
-
-/** Initialise a @a dlo_mode_data array entry.
- *
- * @param idx Array index.
- * @param mwidth Mode width (pixels).
- * @param mheight Mode height (pixels).
- * @param mrefresh Mode refresh rate (Hz).
- * @param mbpp Mode colour depth (bits per pixel).
- */
-#define init_mode(idx, mwidth, mheight, mrefresh, mbpp) \
-{ \
- dlo_mode_data[idx].width = mwidth; \
- dlo_mode_data[idx].height = mheight; \
- dlo_mode_data[idx].refresh = mrefresh; \
- dlo_mode_data[idx].bpp = mbpp; \
- dlo_mode_data[idx].data = DLO_MODE_DATA_##mwidth##_##mheight##_##mrefresh##_##mbpp##_0; \
- dlo_mode_data[idx].data_sz = DSIZEOF(DLO_MODE_DATA_##mwidth##_##mheight##_##mrefresh##_##mbpp##_0); \
- dlo_mode_data[idx].mode_en = DLO_MODE_ENABLE_##mwidth##_##mheight##_##mrefresh##_##mbpp##_0; \
- dlo_mode_data[idx].mode_en_sz = DSIZEOF(DLO_MODE_ENABLE_##mwidth##_##mheight##_##mrefresh##_##mbpp##_0); \
- dlo_mode_data[idx].low_blank = false; \
-}
-
-
-/* External-scope inline functions -----------------------------------------------------*/
-
-
-/** Swap the endianness of a long (four byte) integer.
- *
- * @param val Integer to alter.
- *
- * @return Value with swapped endianness.
- */
-inline uint32_t swap_endian_l(uint32_t val)
-{
- return ((val & 0xFF) << 24) | ((val & 0xFF00) << 8) | ((val & 0xFF0000) >> 8) | (( val >> 24) & 0xFF);
-}
-
-
-/** Swap the endianness of a short (two byte) integer.
- *
- * @param val Integer to alter.
- *
- * @return Value with swapped endianness.
- */
-inline uint16_t swap_endian_s(uint16_t val)
-{
- return ((val >> 8) & 0xFF) | ((val << 8) & 0xFF00);
-}
-
-
-extern uint32_t swap_endian_l(uint32_t val);
-extern uint16_t swap_endian_s(uint16_t val);
-
-
-/* File-scope types --------------------------------------------------------------------*/
-
-
-/** Structure to hold information about a specific screen mode.
- */
-typedef struct dlo_mode_data_s
-{
- uint16_t width; /**< Width (pixels). */
- uint16_t height; /**< Height (pixels). */
- uint8_t refresh; /**< Refresh rate (Hz). */
- uint8_t bpp; /**< Colour depth (bits per pixel). */
- char *data; /**< Block of mode data. */
- size_t data_sz; /**< Size of mode data block (bytes). */
- char *mode_en; /**< Block of mode enable data. */
- size_t mode_en_sz; /**< Size of mode enable data block (bytes). */
- bool low_blank; /**< Screen mode has reduced blanking. */
-} dlo_mode_data_t; /**< A struct @a dlo_mode_data_s. */
-
-
-/** Established timing information, derived from EDID.
- */
-typedef struct est_timing_s
-{
- uint16_t width; /**< Width of mode (pixels). */
- uint16_t height; /**< Height of mode (pixels). */
- uint8_t refresh; /**< Mode refresh rate (Hz). */
-} est_timing_t; /**< A struct @a est_timings_s. */
-
-
-/** Vendor/product information.
- */
-typedef struct edid_prod_id_s
-{
- uint16_t manuf_name; /**< ID manufacturer code. */
- uint16_t prod_code; /**< ID product code. */
- uint32_t serial_num; /**< ID serial number. */
- uint8_t manuf_wk; /**< Week of manufacture. */
- uint8_t manuf_yr; /**< Year of manufacture. */
-} edid_prod_id_t; /**< A struct @a edid_prod_id_s. */
-
-
-/** EDID structure information.
- */
-typedef struct edid_struct_vsn_s
-{
- uint8_t number; /**< Version number. */
- uint8_t revision; /**< Revision number. */
-} edid_struct_vsn_t; /**< A struct @a edid_struct_vsn_s. */
-
-
-/** Basic dislpay parameters/features.
- */
-typedef struct edid_basic_params_s
-{
- uint8_t input_def; /**< Video input definition. */
- uint8_t max_horiz_sz; /**< Maximum horizontal image size (cm). */
- uint8_t max_vert_sz; /**< Maximum vertical image size (cm). */
- float gamma; /**< Display transfer characteristic (gamma). */
- uint8_t features; /**< Feature support. */
-} edid_basic_params_t; /**< A struct @a edid_basic_params_s. */
-
-
-/** Colour characteristics.
- */
-typedef struct edid_colours_s
-{
- uint16_t red_grn_low; /**< Red/green low bits. */
- uint16_t blu_wht_low; /**< Blue/white low bits. */
- uint16_t red_x; /**< Red-x (bits 9-2). */
- uint16_t red_y; /**< Red-y (bits 9-2). */
- uint16_t grn_x; /**< Green-x (bits 9-2). */
- uint16_t grn_y; /**< Green-y (bits 9-2). */
- uint16_t blu_x; /**< Blue-x (bits 9-2). */
- uint16_t blu_y; /**< Blue-y (bits 9-2). */
- uint16_t wht_x; /**< White-x (bits 9-2). */
- uint16_t wht_y; /**< White-y (bits 9-2). */
-} edid_colours_t; /**< A struct @a edid_colours_s. */
-
-
-/** Established timings.
- */
-typedef struct edid_est_timings_s
-{
- uint8_t timings[2]; /**< Bitfields of established timings. */
- uint8_t resvd; /**< Manufacturer's reserved timings. */
-} edid_est_timings_t; /**< A struct @a edid_est_timings_s. */
-
-
-/** Standard timing identification.
- */
-typedef struct edid_std_timing_s
-{
- uint16_t timing_id[8]; /**< Standard timing identification. */
-} edid_std_timing_t; /**< A struct @a edid_std_timing_s. */
-
-
-/** Detailed timing description.
- */
-typedef struct edid_detail_s
-{
- bool is_detail; /**< Flag is set to true - the structure is an @a edid_detail_t. */
- float pixclk; /**< Timing parameter. */
- uint32_t hactl; /**< Timing parameter. */
- uint32_t hblankl; /**< Timing parameter. */
- uint32_t hactblankh; /**< Timing parameter. */
- uint32_t vactl; /**< Timing parameter. */
- uint32_t vblankl; /**< Timing parameter. */
- uint32_t vactblankh; /**< Timing parameter. */
- uint32_t hsyncoffl; /**< Timing parameter. */
- uint32_t hsyncwl; /**< Timing parameter. */
- uint32_t vsyncoffvsyncwl; /**< Timing parameter. */
- uint32_t synch; /**< Timing parameter. */
- uint32_t hsizel; /**< Timing parameter. */
- uint32_t vsizel; /**< Timing parameter. */
- uint32_t hvsizeh; /**< Timing parameter. */
- uint8_t hbord; /**< Timing parameter. */
- uint8_t vbord; /**< Timing parameter. */
- uint8_t flags; /**< Timing parameter. */
-} edid_detail_t; /**< A struct @a edid_detail_s. */
-
-
-/** Monitor descriptor.
- */
-typedef struct edid_monitor_desc_s
-{
- bool is_detail; /**< Flag is set to false - the structure is not an @a edid_detail_t. */
- uint8_t unknown[18]; /**< Contents of block are unknown. */
-} edid_monitor_desc_t; /**< A struct @a edid_monitor_desc_s. */
-
-
-/** A timing description block may be either a @a edid_detail_t or a @a edid_monitor_desc_t.
- */
-typedef union edid_timing_desc_u
-{
- edid_detail_t detail; /**< Either a detailed timing description. */
- edid_monitor_desc_t desc; /**< Or a monitor descriptor. */
-} edid_timing_desc_t; /**< A struct @a edid_timing_desc_s. */
-
-
-/** An EDID extension block.
- */
-typedef struct edid_ext_block_s
-{
- uint8_t unknown[128]; /**< Contents of block are unknown. */
-} edid_ext_block_t; /**< A struct @a edid_ext_block_s. */
-
-
-/** An EDID structure.
- */
-typedef struct edid_format_s
-{
- edid_prod_id_t product; /**< Vendor/product information. */
- edid_struct_vsn_t version; /**< EDID structure information. */
- edid_basic_params_t basic; /**< Basic dislpay parameters/features. */
- edid_colours_t colours; /**< Colour characteristics. */
- edid_est_timings_t est_timings; /**< Established timings. */
- edid_std_timing_t std_timings; /**< Standard timing identification. */
- edid_timing_desc_t timings[4]; /**< Timing descriptions. */
- uint8_t ext_blocks; /**< Number of extension blocks. */
-} edid_format_t; /**< A struct @a edid_format_s. */
-
-
-/* External scope variables ------------------------------------------------------------*/
-
-
-/* File-scope variables ----------------------------------------------------------------*/
-
-
-/** Array of hard-wired screen mode definitions.
- */
-static dlo_mode_data_t dlo_mode_data[DLO_MODE_DATA_NUM];
-
-
-/** Mode information corresponding with flag bits in EDID establisted timings bytes.
- */
-const est_timing_t est_timings[24] =
-{
- { 800, 600, 60 }, /* bit 0 */
- { 800, 600, 56 }, /* bit 1 */
- { 640, 480, 75 }, /* bit 2 */
- { 640, 480, 72 }, /* bit 3 */
- { 640, 480, 67 }, /* bit 4 */
- { 640, 480, 60 }, /* bit 5 */
- { 720, 400, 88 }, /* bit 6 */
- { 720, 400, 70 }, /* bit 7 */
- { 1280, 1024, 75 }, /* bit 8 */
- { 1024, 768, 75 }, /* bit 9 */
- { 1024, 768, 70 }, /* bit 10 */
- { 1024, 768, 60 }, /* bit 11 */
- { 1024, 768, 87 }, /* bit 12 */
- { 832, 624, 75 }, /* bit 13 */
- { 800, 600, 75 }, /* bit 14 */
- { 800, 600, 72 }, /* bit 15 */
- { 0, 0, 0 }, /* bit 16 */
- { 0, 0, 0 }, /* bit 17 */
- { 0, 0, 0 }, /* bit 18 */
- { 0, 0, 0 }, /* bit 19 */
- { 0, 0, 0 }, /* bit 20 */
- { 0, 0, 0 }, /* bit 21 */
- { 0, 0, 0 }, /* bit 22 */
- { 1152, 870, 75 } /* bit 23 */
-};
-
-
-/* File-scope function declarations ----------------------------------------------------*/
-
-
-/** Append a video register setting command onto the specified char block.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param reg Register number (0..255).
- * @param val Value to set (byte).
- *
- * @return Return code, zero for no error.
- */
-static dlo_retcode_t vreg(dlo_device_t * const dev, uint8_t reg, uint8_t val);
-
-
-/** Append a video register setting command onto the specified char block.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param reg Register number (0..255).
- * @param val Value to set (byte).
- *
- * @return Return code, zero for no error.
- */
-static dlo_retcode_t vbuf(dlo_device_t * const dev, const char * const buf, size_t len);
-
-
-/** Check an EDID checksum to see if it is invalid.
- *
- * @param ptr Pointer to base of EDID structure data.
- * @param size Size of data (bytes).
- *
- * @return true if checksum is incorrect, false if OK.
- */
-static bool bad_edid_checksum(const uint8_t * const ptr, const size_t size);
-
-
-/** Parse an EDID detailed timing descriptor/mode descriptor.
- *
- * @param desc Pointer to descriptor structure to initialise.
- * @param ptr Pointer to base of descriptor in EDID data to parse.
- */
-static void parse_edid_detail_desc(edid_timing_desc_t * const desc, const uint8_t * const ptr);
-
-
-/** Parse EDID colour characteristics.
- *
- * @param cols Pointer to colour structure to initialise.
- * @param ptr Pointer to base of colour characteristics block to parse from EDID data.
- */
-static void parse_edid_colours(edid_colours_t * const cols, const uint8_t * const ptr);
-
-
-/** Look for a mode definition amongst the list of known modes.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param width Width of desired display (pixels).
- * @param height Hieght of desired display (pixels) - zero to select first available.
- * @param refresh Desired refresh rate (Hz) - zero to select first available.
- * @param bpp Colour depth (bits per pixel) - zero to select first available.
- *
- * @return Mode number of the best matching mode definition (or @a DLO_INVALID_MODE if none found).
- */
-static dlo_modenum_t get_mode_number(dlo_device_t * const dev, const uint16_t width, const uint16_t height, const uint8_t refresh, const uint8_t bpp);
-
-
-/** Given a bitmap and a mode number, set the current screen mode.
- *
- * @param bmp Bitmap to set as the current rastered display mode.
- * @param mode Mode number for best match to the supplied bitmap.
- *
- * @return Return code, zero for no error.
- */
-static dlo_retcode_t mode_select(dlo_device_t * const dev, const dlo_mode_t * const desc, const dlo_modenum_t mode);
-
-
-/** Look up the specified mode and add to the supported list if found.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param idx Index - incrememnted if the mode was found.
- * @param width Width of the mode to look for (pixels).
- * @param height Height of the mode to look for (pixels).
- * @param refresh Refresh rate of the mode to look for (Hz).
- *
- * @return Updated index (as @a idx if mode not found, else incremented by one).
- */
-static uint16_t add_supported(dlo_device_t * const dev, uint16_t idx, const uint16_t width, const uint16_t height, const uint8_t refresh);
-
-
-/** Build a list of supported modes, based upon the supplied EDID information.
- *
- * @param dev Device to update.
- * @param edid Pointer to structure holding parsed EDID information.
- *
- * @return Return code, zero for no error.
- */
-static dlo_retcode_t lookup_edid_modes(dlo_device_t * const dev, const edid_format_t * const edid);
-
-
-/** Program the base addresses of the video display in the device.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param base Address of the base of the 16 bpp segment.
- * @param base8 Address of the base of the 8 bpp segment.
- *
- * @return Return code, zero for no error.
- *
- * Note: this call first will cause any buffered commands to be sent to the device then
- * the set base commands are sent. The buffer to that device is thus flushed.
- */
-static dlo_retcode_t set_base(dlo_device_t * const dev, const dlo_ptr_t base, const dlo_ptr_t base8);
-
-
-/* Public function definitions ---------------------------------------------------------*/
-
-
-dlo_retcode_t dlo_mode_init(const dlo_init_t flags)
-{
- init_mode(0, 1920, 1080, 60, 24);
- init_mode(1, 1600, 1200, 60, 24);
- init_mode(2, 1400, 1050, 85, 24);
- init_mode(3, 1400, 1050, 75, 24);
- init_mode(4, 1400, 1050, 60, 24);
- init_mode(5, 1400, 1050, 60, 24);
- init_mode(6, 1366, 768, 60, 24);
- init_mode(7, 1360, 768, 60, 24);
- init_mode(8, 1280, 960, 85, 24);
- init_mode(9, 1280, 960, 60, 24);
- init_mode(10, 1280, 800, 60, 24);
- init_mode(11, 1280, 768, 85, 24);
- init_mode(12, 1280, 768, 75, 24);
- init_mode(13, 1280, 1024, 85, 24);
- init_mode(14, 1280, 1024, 75, 24);
- init_mode(15, 1280, 1024, 60, 24);
- init_mode(16, 1280, 768, 60, 24);
- init_mode(17, 1152, 864, 75, 24);
- init_mode(18, 1024, 768, 85, 24);
- init_mode(19, 1024, 768, 75, 24);
- init_mode(20, 1024, 768, 70, 24);
- init_mode(21, 1024, 768, 60, 24);
- init_mode(22, 848, 480, 60, 24);
- init_mode(23, 800, 600, 85, 24);
- init_mode(24, 800, 600, 75, 24);
- init_mode(25, 800, 600, 72, 24);
- init_mode(26, 800, 600, 60, 24);
- init_mode(27, 800, 600, 56, 24);
- init_mode(28, 800, 480, 60, 24);
- init_mode(29, 720, 400, 85, 24);
- init_mode(30, 720, 400, 70, 24);
- init_mode(31, 640, 480, 85, 24);
- init_mode(32, 640, 480, 75, 24);
- init_mode(33, 640, 480, 73, 24);
- init_mode(34, 640, 480, 60, 24);
-
- return dlo_ok;
-}
-
-
-dlo_retcode_t dlo_mode_final(const dlo_final_t flags)
-{
- return dlo_ok;
-}
-
-
-dlo_mode_t *dlo_mode_from_number(const dlo_modenum_t num)
-{
- static dlo_mode_t mode;
-
- if (num < DLO_MODE_DATA_NUM)
- {
- mode.view.width = dlo_mode_data[num].width;
- mode.view.height = dlo_mode_data[num].height;
- mode.view.bpp = dlo_mode_data[num].bpp;
- mode.view.base = 0;
- mode.refresh = dlo_mode_data[num].refresh;
- return &mode;
- }
- return NULL;
-}
-
-
-dlo_modenum_t dlo_mode_lookup(dlo_device_t * const dev, const uint16_t width, const uint16_t height, const uint8_t refresh, uint8_t bpp)
-{
- /* Check that the requested screen mode is supported */
- //DPRINTF("mode: lookup: %ux%u @ %u Hz, %u bpp\n", width, height, refresh, bpp);
- return bpp != 24 ? DLO_INVALID_MODE : get_mode_number(dev, width, height, refresh, bpp);
-}
-
-
-dlo_retcode_t dlo_mode_change(dlo_device_t * const dev, const dlo_mode_t * const desc, dlo_modenum_t mode)
-{
- /* If no mode number was specified on entry, try looking one up for the supplied bitmap */
- if (mode == DLO_INVALID_MODE)
- mode = get_mode_number(dev, desc->view.width, desc->view.height, 0, desc->view.bpp);
-
- /* Change mode or return an error */
- return mode_select(dev, desc, mode);
-}
-
-
-dlo_retcode_t dlo_mode_parse_edid(dlo_device_t * const dev, const uint8_t * const ptr, const size_t size)
-{
- static edid_format_t edid;
- uint32_t i;
-
- /* Copy the header bytes straight into our structure (assumes the structure is correct size!) */
- ASSERT(EDID_STRUCT_SZ == size);
- if (memcmp(header, ptr, sizeof(header)))
- return dlo_err_edid_fail;
-
- if (bad_edid_checksum(ptr, size))
- return dlo_err_edid_fail;
-
-#if (defined(DEBUG) && 0) /* If you really want this verbose debug output, change the 0 to a 1 */
- uint32_t j;
- /* Parse the vendor/product information */
- for (j = 0; j < 128; j += 8)
- {
- DPRINTF("mode: edid: raw: ");
- for (i = 0; i < 8; i++)
- DPRINTF("%02X=%02X ", i + j, RD_B(ptr + i + j));
- DPRINTF("\n");
- }
-#endif
-
- edid.product.manuf_name = LETOHS(RD_S(ptr + 0x08));
- edid.product.prod_code = LETOHS(RD_S(ptr + 0x0A));
- edid.product.serial_num = LETOHL(RD_L(ptr + 0x0C));
- edid.product.manuf_wk = RD_B(ptr + 0x10);
- edid.product.manuf_yr = RD_B(ptr + 0x11);
- //DPRINTF("mode: edid: manuf &%X prod &%X serial &%X wk %u yr %u\n",
- // edid.product.manuf_name, edid.product.prod_code, edid.product.serial_num,
- // edid.product.manuf_wk, edid.product.manuf_yr + 1990);
-
- /* Parse the EDID structure information */
- edid.version.number = RD_B(ptr + 0x12);
- edid.version.revision = RD_B(ptr + 0x13);
- //DPRINTF("edid: version &%02X revision &%02X\n", edid.version.number, edid.version.revision);
-
- /* Parse the basic dislpay parameters/features */
- edid.basic.input_def = RD_B(ptr + 0x14);
- edid.basic.max_horiz_sz = RD_B(ptr + 0x15);
- edid.basic.max_vert_sz = RD_B(ptr + 0x16);
- edid.basic.gamma = (100.0 + RD_B(ptr + 0x17)) / 100.0;
- edid.basic.features = RD_B(ptr + 0x18);
-
- /* Parse the colour characteristics */
- parse_edid_colours(&(edid.colours), ptr + 0x19);
-
- /* Parse the established timings */
- edid.est_timings.timings[0] = RD_B(ptr + 0x23);
- edid.est_timings.timings[1] = RD_B(ptr + 0x24);
- edid.est_timings.resvd = RD_B(ptr + 0x25);
-
- /* Parse the bits at the end of the EDID structure */
- edid.ext_blocks = RD_B(ptr + 0x7E);
-
- /* Parse all of the standard timing identification */
- for (i = 0; i < sizeof(edid.std_timings.timing_id); i++)
- edid.std_timings.timing_id[i] = RD_B(ptr + 0x26 + i);
-
- /* Parse all of the detailed timing descriptions (or monitor descriptors) */
- for (i = 0; i < 4; i++)
- parse_edid_detail_desc(&(edid.timings[i]), ptr + 0x36 + (i * 0x12));
-
- return lookup_edid_modes(dev, &edid);
-}
-
-
-void use_default_modes(dlo_device_t * const dev)
-{
- uint32_t i;
-
- for (i = 0; i < DLO_MODE_DATA_NUM; i++)
- dev->supported[i] = (dlo_modenum_t)i;
-}
-
-
-/* File-scope function definitions -----------------------------------------------------*/
-
-
-static dlo_retcode_t vreg(dlo_device_t * const dev, uint8_t reg, uint8_t val)
-{
- if (dev->bufend - dev->bufptr < 4)
- return dlo_err_buf_full;
-
- *(dev->bufptr)++ = '\xAF';
- *(dev->bufptr)++ = '\x20';
- *(dev->bufptr)++ = reg;
- *(dev->bufptr)++ = val;
-
- return dlo_ok;
-}
-
-
-static dlo_retcode_t vbuf(dlo_device_t * const dev, const char * buf, size_t len)
-{
- if (dev->bufend - dev->bufptr < len)
- return dlo_err_buf_full;
-
- while (len--)
- *(dev->bufptr)++ = *buf++;
-
- return dlo_ok;
-}
-
-
-static dlo_modenum_t get_mode_number(dlo_device_t * const dev, const uint16_t width, const uint16_t height, const uint8_t refresh, const uint8_t bpp)
-{
- dlo_modenum_t idx;
- uint32_t num;
-
- /* Look for all matching modes in our array of video timing structures.
- *
- * Note: if we don't have EDID data for the monitor attached to the device
- * we simply look through all the modes we have, rather than only looking
- * at the supported modes list.
- */
- for (idx = 0; idx < DLO_MODE_DATA_NUM; idx++)
- {
- /* Read the mode number from the device's supported modes array */
- num = dev->supported[idx];
- if (num == DLO_INVALID_MODE)
- break;
-
- /* This sequence of if statements looks odd, take care if you decide to 'optimise' it! */
- if (dlo_mode_data[num].width != width)
- continue;
- if (bpp && dlo_mode_data[num].bpp != bpp)
- continue;
- if (height && dlo_mode_data[num].height != height)
- continue;
- if (refresh && dlo_mode_data[num].refresh != refresh)
- continue;
-
- /* If we're satisfied with the tests above, then return the mode number */
- return num;
- }
-
- /* No matches found, return an invalid mode number */
- return DLO_INVALID_MODE;
-}
-
-
-static dlo_retcode_t mode_select(dlo_device_t * const dev, const dlo_mode_t * const desc, const dlo_modenum_t mode)
-{
- if (mode >= DLO_MODE_DATA_NUM || mode == DLO_INVALID_MODE)
- return dlo_err_bad_mode;
-
- /* Base address must be aligned to a two byte boundary */
- if (desc->view.base & 1)
- return dlo_err_bad_mode;
-
- /* Flush the command buffer */
- if (dlo_ok != dlo_usb_write(dev))
- return DLO_INVALID_MODE;
-
- dev->mode.view.base = desc->view.base;
- dev->base8 = desc->view.base + (BYTES_PER_16BPP * desc->view.width * desc->view.height);
- ERR(set_base(dev, dev->mode.view.base, dev->base8));
-
- /* Only change mode if the new raster bitmap's characteristics differ from the current.
- *
- * Note: don't compare reduced blanking flag because if the rest is the same, we can use the
- * same blanking type. However, there's an outside chance that the low_blank hint was changed
- * since entering the current mode in which case you may well want a mode change to happen but
- * we'll just hope that never happens (seems like a very unlikely scenario).
- */
- if (desc->view.width != dev->mode.view.width ||
- desc->view.height != dev->mode.view.height ||
- desc->view.bpp != dev->mode.view.bpp)
- {
- ERR(dlo_usb_chan_sel(dev, dlo_mode_data[mode].mode_en, dlo_mode_data[mode].mode_en_sz));
- ERR(dlo_usb_write_buf(dev, dlo_mode_data[mode].data, dlo_mode_data[mode].data_sz));
- ERR(dlo_usb_chan_sel(dev, DLO_MODE_POSTAMBLE, DSIZEOF(DLO_MODE_POSTAMBLE)));
- }
-
- /* Update the device with the new mode details */
- dev->mode = *desc;
- dev->mode.refresh = dlo_mode_data[mode].refresh;
- dev->low_blank = dlo_mode_data[mode].low_blank;
-
- //DPRINTF("mode: select: %ux%u @ %u Hz %u bpp (base &%X base8 &%X low? %s)\n",
- // dev->mode.view.width, dev->mode.view.height, dev->mode.refresh, dev->mode.view.bpp,
- // dev->mode.view.base, dev->base8, dev->low_blank ? "yes" : "no");
-
- /* Flush the command buffer */
- ERR(dlo_usb_write(dev));
-
- /* Return a warning for DL160 modes */
- return (mode < DLO_DL120_MODES) ? dlo_warn_dl160_mode : dlo_ok;
-}
-
-
-static uint16_t add_supported(dlo_device_t * const dev, uint16_t idx, const uint16_t width, const uint16_t height, const uint8_t refresh)
-{
- dlo_modenum_t num;
-
- num = get_mode_number(dev, width, height, refresh, 24);
- if (num != DLO_INVALID_MODE)
- dev->supported[idx++] = num;
-
-// DPRINTF("mode: add_supt: %ux%u @ %u Hz, %u bpp = num %u\n", width, height, refresh, 24, (int)num);
-
- return idx;
-}
-
-
-static dlo_retcode_t lookup_edid_modes(dlo_device_t * const dev, const edid_format_t * const edid)
-{
- uint32_t timings, bit;
- uint32_t idx = 0;
-
- /* Clear the native mode information for the device */
- (void) dlo_memset(&dev->native, 0, sizeof(dlo_mode_t));
-
- /* Add mode numbers for any supported established timing modes */
- timings = edid->est_timings.timings[0] | (edid->est_timings.timings[1] << 8) | (edid->est_timings.resvd << 16);
- for (bit = 0; bit < 24; bit++)
- {
- if (est_timings[bit].width)
- idx = add_supported(dev, idx, est_timings[bit].width, est_timings[bit].height, est_timings[bit].refresh);
- }
-
- /* Add further support from the detailed timing descriptions */
- for (timings = 0; timings < 4; timings++)
- {
- const edid_detail_t * const detail = &(edid->timings[timings].detail);
-
- if (detail->is_detail)
- {
- uint8_t hz;
-
- for (hz = 50; hz < 100; hz++)
- {
- uint32_t prev = idx;
- uint32_t width = detail->hactl + ((detail->hactblankh & 0xF0) << 4);
- uint32_t height = detail->vactl + ((detail->vactblankh & 0xF0) << 4);
-
- idx = add_supported(dev, idx, width, height, hz);
-
- /* Have we added a mode definition for the native resolution reported by the display? */
- if (idx != prev)
- {
- dlo_modenum_t num = dev->supported[prev];
-
- dev->native.view.base = 0;
- dev->native.view.width = dlo_mode_data[num].width;
- dev->native.view.height = dlo_mode_data[num].height;
- dev->native.view.bpp = dlo_mode_data[num].bpp;
- dev->native.refresh = dlo_mode_data[num].refresh;
- DPRINTF("mode: lookup: native mode %u (%ux%u @ %u bpp, %uHz base &%X)\n",
- num,
- dev->native.view.width,
- dev->native.view.height,
- dev->native.view.bpp,
- dev->native.refresh,
- (int)dev->native.view.base);
- }
- }
- }
- }
-
- /* Fill any remaining array entries with the invalid mode constant */
- while (idx < DLO_MODE_DATA_NUM - 1)
- dev->supported[idx++] = DLO_INVALID_MODE;
-
- return dlo_ok;
-}
-
-
-static dlo_retcode_t set_base(dlo_device_t * const dev, const dlo_ptr_t base, const dlo_ptr_t base8)
-{
- //DPRINTF("mode: set_base: base=&%X base8=&%X\n", base, base8);
- ERR(vbuf(dev, WRITE_VIDREG_LOCK, DSIZEOF(WRITE_VIDREG_LOCK)));
- ERR(vreg(dev, 0x20, base >> 16));
- ERR(vreg(dev, 0x21, base >> 8));
- ERR(vreg(dev, 0x22, base));
- ERR(vreg(dev, 0x26, base8 >> 16));
- ERR(vreg(dev, 0x27, base8 >> 8));
- ERR(vreg(dev, 0x28, base8));
- ERR(vbuf(dev, WRITE_VIDREG_UNLOCK, DSIZEOF(WRITE_VIDREG_UNLOCK)));
- ERR(dlo_usb_write(dev));
-
- return dlo_ok;
-}
-
-
-static bool bad_edid_checksum(const uint8_t * const ptr, const size_t size)
-{
- uint32_t i;
- uint8_t csum = 0;
-
- for (i = 0; i < size; i++)
- csum += ptr[i];
-
- return 0 != csum;
-}
-
-
-static void parse_edid_detail_desc(edid_timing_desc_t * const desc, const uint8_t * const ptr)
-{
- if (RD_B(ptr) || RD_B(ptr + 1) || RD_B(ptr + 2))
- {
- //DPRINTF("edid: found timing detail (&%04X)\n", LETOHS(RD_S(ptr)));
- desc->detail.is_detail = true;
- desc->detail.pixclk = (float)LETOHS(RD_S(ptr)) / 100.0;
- desc->detail.hactl = RD_B(ptr + 0x02);
- desc->detail.hblankl = RD_B(ptr + 0x03);
- desc->detail.hactblankh = RD_B(ptr + 0x04);
- desc->detail.vactl = RD_B(ptr + 0x05);
- desc->detail.vblankl = RD_B(ptr + 0x06);
- desc->detail.vactblankh = RD_B(ptr + 0x07);
- desc->detail.hsyncoffl = RD_B(ptr + 0x08);
- desc->detail.hsyncwl = RD_B(ptr + 0x09);
- desc->detail.vsyncoffvsyncwl = RD_B(ptr + 0x0A);
- desc->detail.synch = RD_B(ptr + 0x0B);
- desc->detail.hsizel = RD_B(ptr + 0x0C);
- desc->detail.vsizel = RD_B(ptr + 0x0D);
- desc->detail.hvsizeh = RD_B(ptr + 0x0E);
- desc->detail.hbord = RD_B(ptr + 0x0F);
- desc->detail.vbord = RD_B(ptr + 0x10);
- desc->detail.flags = RD_B(ptr + 0x11);
-
- //DPRINTF("edid: Pixel Clock: %f MHz\n", (float)desc->detail.pixclk);
- //DPRINTF("edid: H Active pixels: %d\n", desc->detail.hactl + ((desc->detail.hactblankh & 0xF0) << 4));
- //DPRINTF("edid: H Blank pixels: %d\n", desc->detail.hblankl + ((desc->detail.hactblankh & 0x0F) << 8));
- //DPRINTF("edid: V Active pixels: %d\n", desc->detail.vactl + ((desc->detail.vactblankh & 0xF0) << 4));
- //DPRINTF("edid: V Blank pixels: %d\n", desc->detail.vblankl + ((desc->detail.vactblankh & 0x0F) << 8));
- //DPRINTF("edid: H Sync Off: %d\n", desc->detail.hsyncoffl + ((desc->detail.synch & 0xC0) << 2));
- //DPRINTF("edid: H Sync Width: %d\n", desc->detail.hsyncwl + ((desc->detail.synch & 0x30) << 4));
- //DPRINTF("edid: V Sync Off: %d\n", (desc->detail.vsyncoffvsyncwl >> 4) + ((desc->detail.synch & 0x0C) << 6));
- //DPRINTF("edid: V Sync Width: %d\n", (desc->detail.vsyncoffvsyncwl & 0xF) + ((desc->detail.synch & 0x03) << 8));
- //DPRINTF("edid: H size: %d mm\n", desc->detail.hsizel + ((desc->detail.hvsizeh & 0xF0) << 4));
- //DPRINTF("edid: V size: %d mm\n", desc->detail.vsizel + ((desc->detail.hvsizeh & 0x0F) << 8));
- }
- else
- {
- /* It's a mode descriptor - ignore for now */
- //DPRINTF("edid: found a mode descriptor type &%02X\n", RD_B(ptr+3));
- desc->desc.is_detail = false;
- switch (RD_B(ptr+3))
- {
- case 0xFC:
- case 0xFE:
- case 0xFF:
- {
- char buf[14];
- char *chr;
-
- snprintf(buf, 13, "%s", ptr + 5);
- buf[13] = '\0';
- chr = strchr(buf, '\n');
- if (chr)
- *chr = '\0';
- //DPRINTF("edid: monitor string '%s'\n", buf);
- break;
- }
- default:
- {
- //uint32_t i;
- //DPRINTF("edid: ");
- //for (i = 0; i < 0x12; i++)
- // DPRINTF("%02X ", RD_B(ptr+i));
- //DPRINTF("\n");
- }
- }
- }
-}
-
-static void parse_edid_colours(edid_colours_t * const cols, const uint8_t * const ptr)
-{
- /* Read the raw data */
- cols->red_grn_low = RD_B(ptr + 0x19);
- cols->blu_wht_low = RD_B(ptr + 0x1A);
- cols->red_x = RD_B(ptr + 0x1B);
- cols->red_y = RD_B(ptr + 0x1C);
- cols->grn_x = RD_B(ptr + 0x1D);
- cols->grn_y = RD_B(ptr + 0x1E);
- cols->blu_x = RD_B(ptr + 0x1F);
- cols->blu_y = RD_B(ptr + 0x20);
- cols->wht_x = RD_B(ptr + 0x21);
- cols->wht_y = RD_B(ptr + 0x22);
-
- /* Do the expansion */
- cols->red_x = ((cols->red_grn_low & 0xC0) >> 6) + (cols->red_x << 2);
- cols->red_y = ((cols->red_grn_low & 0x30) >> 4) + (cols->red_y << 2);
- cols->grn_x = ((cols->red_grn_low & 0x0C) >> 2) + (cols->grn_x << 2);
- cols->grn_y = ((cols->red_grn_low & 0x03) >> 0) + (cols->grn_y << 2);
- cols->blu_x = ((cols->blu_wht_low & 0xC0) >> 6) + (cols->blu_x << 2);
- cols->blu_y = ((cols->blu_wht_low & 0x40) >> 4) + (cols->blu_y << 2);
- cols->wht_x = ((cols->blu_wht_low & 0x0C) >> 2) + (cols->wht_y << 2);
- cols->wht_y = ((cols->blu_wht_low & 0x03) >> 0) + (cols->wht_y << 2);
-}
-
-
-/* End of file -------------------------------------------------------------------------*/
+/** @file dlo_mode.c
+ *
+ * @brief Implementation of the screen mode-related functions.
+ *
+ * See dlo_mode.h for more information.
+ *
+ * DisplayLink Open Source Software (libdlo)
+ * Copyright (C) 2009, DisplayLink
+ * www.displaylink.com
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by the Free
+ * Software Foundation; LGPL version 2, dated June 1991.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "dlo_defs.h"
+#include "dlo_mode.h"
+#include "dlo_data.h"
+#include "dlo_usb.h"
+
+
+/* File-scope defines ------------------------------------------------------------------*/
+
+
+/** Pre-defined EDID header used to check that data read from a device is valid.
+ */
+const uint8_t header[8] =
+{
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
+};
+
+/** Constant used for deciding if a host is big- or little endian.
+ */
+const uint32_t endian = 1;
+
+/** Unlock video registers command.
+ */
+#define WRITE_VIDREG_LOCK "\xAF\x20\xFF\x00"
+
+/** Lock video registers command.
+ */
+#define WRITE_VIDREG_UNLOCK "\xAF\x20\xFF\xFF\xAF\xA0"
+
+/** Return non-zero if the host is big endian or zero if the host is little endian.
+ */
+#define IS_BIGENDIAN() ((*(char*)&endian) == '\0')
+
+/** Convert a 32 bit little endian value into a host byte-order value.
+ *
+ * @param val Little-endian 32 bit value to convert.
+ *
+ * @return Value in host byte order.
+ */
+#define LETOHL(val) (IS_BIGENDIAN() ? swap_endian_l(val) : val)
+
+/** Convert a 16 bit little endian value into a host byte-order value.
+ *
+ * @param val Little-endian 16 bit value to convert.
+ *
+ * @return Value in host byte order.
+ */
+#define LETOHS(val) (IS_BIGENDIAN() ? swap_endian_s(val) : val)
+
+/** Initialise a @a dlo_mode_data array entry.
+ *
+ * @param idx Array index.
+ * @param mwidth Mode width (pixels).
+ * @param mheight Mode height (pixels).
+ * @param mrefresh Mode refresh rate (Hz).
+ * @param mbpp Mode colour depth (bits per pixel).
+ */
+#define init_mode(idx, mwidth, mheight, mrefresh, mbpp) \
+{ \
+ dlo_mode_data[idx].width = mwidth; \
+ dlo_mode_data[idx].height = mheight; \
+ dlo_mode_data[idx].refresh = mrefresh; \
+ dlo_mode_data[idx].bpp = mbpp; \
+ dlo_mode_data[idx].data = DLO_MODE_DATA_##mwidth##_##mheight##_##mrefresh##_##mbpp##_0; \
+ dlo_mode_data[idx].data_sz = DSIZEOF(DLO_MODE_DATA_##mwidth##_##mheight##_##mrefresh##_##mbpp##_0); \
+ dlo_mode_data[idx].mode_en = DLO_MODE_ENABLE_##mwidth##_##mheight##_##mrefresh##_##mbpp##_0; \
+ dlo_mode_data[idx].mode_en_sz = DSIZEOF(DLO_MODE_ENABLE_##mwidth##_##mheight##_##mrefresh##_##mbpp##_0); \
+ dlo_mode_data[idx].low_blank = false; \
+}
+
+
+/* External-scope inline functions -----------------------------------------------------*/
+
+
+/** Swap the endianness of a long (four byte) integer.
+ *
+ * @param val Integer to alter.
+ *
+ * @return Value with swapped endianness.
+ */
+inline uint32_t swap_endian_l(uint32_t val)
+{
+ return ((val & 0xFF) << 24) | ((val & 0xFF00) << 8) | ((val & 0xFF0000) >> 8) | (( val >> 24) & 0xFF);
+}
+
+
+/** Swap the endianness of a short (two byte) integer.
+ *
+ * @param val Integer to alter.
+ *
+ * @return Value with swapped endianness.
+ */
+inline uint16_t swap_endian_s(uint16_t val)
+{
+ return ((val >> 8) & 0xFF) | ((val << 8) & 0xFF00);
+}
+
+
+extern uint32_t swap_endian_l(uint32_t val);
+extern uint16_t swap_endian_s(uint16_t val);
+
+
+/* File-scope types --------------------------------------------------------------------*/
+
+
+/** Structure to hold information about a specific screen mode.
+ */
+typedef struct dlo_mode_data_s
+{
+ uint16_t width; /**< Width (pixels). */
+ uint16_t height; /**< Height (pixels). */
+ uint8_t refresh; /**< Refresh rate (Hz). */
+ uint8_t bpp; /**< Colour depth (bits per pixel). */
+ char *data; /**< Block of mode data. */
+ size_t data_sz; /**< Size of mode data block (bytes). */
+ char *mode_en; /**< Block of mode enable data. */
+ size_t mode_en_sz; /**< Size of mode enable data block (bytes). */
+ bool low_blank; /**< Screen mode has reduced blanking. */
+} dlo_mode_data_t; /**< A struct @a dlo_mode_data_s. */
+
+
+/** Established timing information, derived from EDID.
+ */
+typedef struct est_timing_s
+{
+ uint16_t width; /**< Width of mode (pixels). */
+ uint16_t height; /**< Height of mode (pixels). */
+ uint8_t refresh; /**< Mode refresh rate (Hz). */
+} est_timing_t; /**< A struct @a est_timings_s. */
+
+
+/** Vendor/product information.
+ */
+typedef struct edid_prod_id_s
+{
+ uint16_t manuf_name; /**< ID manufacturer code. */
+ uint16_t prod_code; /**< ID product code. */
+ uint32_t serial_num; /**< ID serial number. */
+ uint8_t manuf_wk; /**< Week of manufacture. */
+ uint8_t manuf_yr; /**< Year of manufacture. */
+} edid_prod_id_t; /**< A struct @a edid_prod_id_s. */
+
+
+/** EDID structure information.
+ */
+typedef struct edid_struct_vsn_s
+{
+ uint8_t number; /**< Version number. */
+ uint8_t revision; /**< Revision number. */
+} edid_struct_vsn_t; /**< A struct @a edid_struct_vsn_s. */
+
+
+/** Basic dislpay parameters/features.
+ */
+typedef struct edid_basic_params_s
+{
+ uint8_t input_def; /**< Video input definition. */
+ uint8_t max_horiz_sz; /**< Maximum horizontal image size (cm). */
+ uint8_t max_vert_sz; /**< Maximum vertical image size (cm). */
+ float gamma; /**< Display transfer characteristic (gamma). */
+ uint8_t features; /**< Feature support. */
+} edid_basic_params_t; /**< A struct @a edid_basic_params_s. */
+
+
+/** Colour characteristics.
+ */
+typedef struct edid_colours_s
+{
+ uint16_t red_grn_low; /**< Red/green low bits. */
+ uint16_t blu_wht_low; /**< Blue/white low bits. */
+ uint16_t red_x; /**< Red-x (bits 9-2). */
+ uint16_t red_y; /**< Red-y (bits 9-2). */
+ uint16_t grn_x; /**< Green-x (bits 9-2). */
+ uint16_t grn_y; /**< Green-y (bits 9-2). */
+ uint16_t blu_x; /**< Blue-x (bits 9-2). */
+ uint16_t blu_y; /**< Blue-y (bits 9-2). */
+ uint16_t wht_x; /**< White-x (bits 9-2). */
+ uint16_t wht_y; /**< White-y (bits 9-2). */
+} edid_colours_t; /**< A struct @a edid_colours_s. */
+
+
+/** Established timings.
+ */
+typedef struct edid_est_timings_s
+{
+ uint8_t timings[2]; /**< Bitfields of established timings. */
+ uint8_t resvd; /**< Manufacturer's reserved timings. */
+} edid_est_timings_t; /**< A struct @a edid_est_timings_s. */
+
+
+/** Standard timing identification.
+ */
+typedef struct edid_std_timing_s
+{
+ uint16_t timing_id[8]; /**< Standard timing identification. */
+} edid_std_timing_t; /**< A struct @a edid_std_timing_s. */
+
+
+/** Detailed timing description.
+ */
+typedef struct edid_detail_s
+{
+ bool is_detail; /**< Flag is set to true - the structure is an @a edid_detail_t. */
+ float pixclk; /**< Timing parameter. */
+ uint32_t hactl; /**< Timing parameter. */
+ uint32_t hblankl; /**< Timing parameter. */
+ uint32_t hactblankh; /**< Timing parameter. */
+ uint32_t vactl; /**< Timing parameter. */
+ uint32_t vblankl; /**< Timing parameter. */
+ uint32_t vactblankh; /**< Timing parameter. */
+ uint32_t hsyncoffl; /**< Timing parameter. */
+ uint32_t hsyncwl; /**< Timing parameter. */
+ uint32_t vsyncoffvsyncwl; /**< Timing parameter. */
+ uint32_t synch; /**< Timing parameter. */
+ uint32_t hsizel; /**< Timing parameter. */
+ uint32_t vsizel; /**< Timing parameter. */
+ uint32_t hvsizeh; /**< Timing parameter. */
+ uint8_t hbord; /**< Timing parameter. */
+ uint8_t vbord; /**< Timing parameter. */
+ uint8_t flags; /**< Timing parameter. */
+} edid_detail_t; /**< A struct @a edid_detail_s. */
+
+
+/** Monitor descriptor.
+ */
+typedef struct edid_monitor_desc_s
+{
+ bool is_detail; /**< Flag is set to false - the structure is not an @a edid_detail_t. */
+ uint8_t unknown[18]; /**< Contents of block are unknown. */
+} edid_monitor_desc_t; /**< A struct @a edid_monitor_desc_s. */
+
+
+/** A timing description block may be either a @a edid_detail_t or a @a edid_monitor_desc_t.
+ */
+typedef union edid_timing_desc_u
+{
+ edid_detail_t detail; /**< Either a detailed timing description. */
+ edid_monitor_desc_t desc; /**< Or a monitor descriptor. */
+} edid_timing_desc_t; /**< A struct @a edid_timing_desc_s. */
+
+
+/** An EDID extension block.
+ */
+typedef struct edid_ext_block_s
+{
+ uint8_t unknown[128]; /**< Contents of block are unknown. */
+} edid_ext_block_t; /**< A struct @a edid_ext_block_s. */
+
+
+/** An EDID structure.
+ */
+typedef struct edid_format_s
+{
+ edid_prod_id_t product; /**< Vendor/product information. */
+ edid_struct_vsn_t version; /**< EDID structure information. */
+ edid_basic_params_t basic; /**< Basic dislpay parameters/features. */
+ edid_colours_t colours; /**< Colour characteristics. */
+ edid_est_timings_t est_timings; /**< Established timings. */
+ edid_std_timing_t std_timings; /**< Standard timing identification. */
+ edid_timing_desc_t timings[4]; /**< Timing descriptions. */
+ uint8_t ext_blocks; /**< Number of extension blocks. */
+} edid_format_t; /**< A struct @a edid_format_s. */
+
+
+/* External scope variables ------------------------------------------------------------*/
+
+
+/* File-scope variables ----------------------------------------------------------------*/
+
+
+/** Array of hard-wired screen mode definitions.
+ */
+static dlo_mode_data_t dlo_mode_data[DLO_MODE_DATA_NUM];
+
+
+/** Mode information corresponding with flag bits in EDID establisted timings bytes.
+ */
+const est_timing_t est_timings[24] =
+{
+ { 800, 600, 60 }, /* bit 0 */
+ { 800, 600, 56 }, /* bit 1 */
+ { 640, 480, 75 }, /* bit 2 */
+ { 640, 480, 72 }, /* bit 3 */
+ { 640, 480, 67 }, /* bit 4 */
+ { 640, 480, 60 }, /* bit 5 */
+ { 720, 400, 88 }, /* bit 6 */
+ { 720, 400, 70 }, /* bit 7 */
+ { 1280, 1024, 75 }, /* bit 8 */
+ { 1024, 768, 75 }, /* bit 9 */
+ { 1024, 768, 70 }, /* bit 10 */
+ { 1024, 768, 60 }, /* bit 11 */
+ { 1024, 768, 87 }, /* bit 12 */
+ { 832, 624, 75 }, /* bit 13 */
+ { 800, 600, 75 }, /* bit 14 */
+ { 800, 600, 72 }, /* bit 15 */
+ { 0, 0, 0 }, /* bit 16 */
+ { 0, 0, 0 }, /* bit 17 */
+ { 0, 0, 0 }, /* bit 18 */
+ { 0, 0, 0 }, /* bit 19 */
+ { 0, 0, 0 }, /* bit 20 */
+ { 0, 0, 0 }, /* bit 21 */
+ { 0, 0, 0 }, /* bit 22 */
+ { 1152, 870, 75 } /* bit 23 */
+};
+
+
+/* File-scope function declarations ----------------------------------------------------*/
+
+
+/** Append a video register setting command onto the specified char block.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param reg Register number (0..255).
+ * @param val Value to set (byte).
+ *
+ * @return Return code, zero for no error.
+ */
+static dlo_retcode_t vreg(dlo_device_t * const dev, uint8_t reg, uint8_t val);
+
+
+/** Append a video register setting command onto the specified char block.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param reg Register number (0..255).
+ * @param val Value to set (byte).
+ *
+ * @return Return code, zero for no error.
+ */
+static dlo_retcode_t vbuf(dlo_device_t * const dev, const char * const buf, size_t len);
+
+
+/** Check an EDID checksum to see if it is invalid.
+ *
+ * @param ptr Pointer to base of EDID structure data.
+ * @param size Size of data (bytes).
+ *
+ * @return true if checksum is incorrect, false if OK.
+ */
+static bool bad_edid_checksum(const uint8_t * const ptr, const size_t size);
+
+
+/** Parse an EDID detailed timing descriptor/mode descriptor.
+ *
+ * @param desc Pointer to descriptor structure to initialise.
+ * @param ptr Pointer to base of descriptor in EDID data to parse.
+ */
+static void parse_edid_detail_desc(edid_timing_desc_t * const desc, const uint8_t * const ptr);
+
+
+/** Parse EDID colour characteristics.
+ *
+ * @param cols Pointer to colour structure to initialise.
+ * @param ptr Pointer to base of colour characteristics block to parse from EDID data.
+ */
+static void parse_edid_colours(edid_colours_t * const cols, const uint8_t * const ptr);
+
+
+/** Look for a mode definition amongst the list of known modes.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param width Width of desired display (pixels).
+ * @param height Hieght of desired display (pixels) - zero to select first available.
+ * @param refresh Desired refresh rate (Hz) - zero to select first available.
+ * @param bpp Colour depth (bits per pixel) - zero to select first available.
+ *
+ * @return Mode number of the best matching mode definition (or @a DLO_INVALID_MODE if none found).
+ */
+static dlo_modenum_t get_mode_number(dlo_device_t * const dev, const uint16_t width, const uint16_t height, const uint8_t refresh, const uint8_t bpp);
+
+
+/** Given a bitmap and a mode number, set the current screen mode.
+ *
+ * @param bmp Bitmap to set as the current rastered display mode.
+ * @param mode Mode number for best match to the supplied bitmap.
+ *
+ * @return Return code, zero for no error.
+ */
+static dlo_retcode_t mode_select(dlo_device_t * const dev, const dlo_mode_t * const desc, const dlo_modenum_t mode);
+
+
+/** Look up the specified mode and add to the supported list if found.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param idx Index - incrememnted if the mode was found.
+ * @param width Width of the mode to look for (pixels).
+ * @param height Height of the mode to look for (pixels).
+ * @param refresh Refresh rate of the mode to look for (Hz).
+ *
+ * @return Updated index (as @a idx if mode not found, else incremented by one).
+ */
+static uint16_t add_supported(dlo_device_t * const dev, uint16_t idx, const uint16_t width, const uint16_t height, const uint8_t refresh);
+
+
+/** Build a list of supported modes, based upon the supplied EDID information.
+ *
+ * @param dev Device to update.
+ * @param edid Pointer to structure holding parsed EDID information.
+ *
+ * @return Return code, zero for no error.
+ */
+static dlo_retcode_t lookup_edid_modes(dlo_device_t * const dev, const edid_format_t * const edid);
+
+
+/** Program the base addresses of the video display in the device.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param base Address of the base of the 16 bpp segment.
+ * @param base8 Address of the base of the 8 bpp segment.
+ *
+ * @return Return code, zero for no error.
+ *
+ * Note: this call first will cause any buffered commands to be sent to the device then
+ * the set base commands are sent. The buffer to that device is thus flushed.
+ */
+static dlo_retcode_t set_base(dlo_device_t * const dev, const dlo_ptr_t base, const dlo_ptr_t base8);
+
+
+/* Public function definitions ---------------------------------------------------------*/
+
+
+dlo_retcode_t dlo_mode_init(const dlo_init_t flags)
+{
+ init_mode(0, 1920, 1080, 60, 24);
+ init_mode(1, 1600, 1200, 60, 24);
+ init_mode(2, 1400, 1050, 85, 24);
+ init_mode(3, 1400, 1050, 75, 24);
+ init_mode(4, 1400, 1050, 60, 24);
+ init_mode(5, 1400, 1050, 60, 24);
+ init_mode(6, 1366, 768, 60, 24);
+ init_mode(7, 1360, 768, 60, 24);
+ init_mode(8, 1280, 960, 85, 24);
+ init_mode(9, 1280, 960, 60, 24);
+ init_mode(10, 1280, 800, 60, 24);
+ init_mode(11, 1280, 768, 85, 24);
+ init_mode(12, 1280, 768, 75, 24);
+ init_mode(13, 1280, 1024, 85, 24);
+ init_mode(14, 1280, 1024, 75, 24);
+ init_mode(15, 1280, 1024, 60, 24);
+ init_mode(16, 1280, 768, 60, 24);
+ init_mode(17, 1152, 864, 75, 24);
+ init_mode(18, 1024, 768, 85, 24);
+ init_mode(19, 1024, 768, 75, 24);
+ init_mode(20, 1024, 768, 70, 24);
+ init_mode(21, 1024, 768, 60, 24);
+ init_mode(22, 848, 480, 60, 24);
+ init_mode(23, 800, 600, 85, 24);
+ init_mode(24, 800, 600, 75, 24);
+ init_mode(25, 800, 600, 72, 24);
+ init_mode(26, 800, 600, 60, 24);
+ init_mode(27, 800, 600, 56, 24);
+ init_mode(28, 800, 480, 60, 24);
+ init_mode(29, 720, 400, 85, 24);
+ init_mode(30, 720, 400, 70, 24);
+ init_mode(31, 640, 480, 85, 24);
+ init_mode(32, 640, 480, 75, 24);
+ init_mode(33, 640, 480, 73, 24);
+ init_mode(34, 640, 480, 60, 24);
+
+ return dlo_ok;
+}
+
+
+dlo_retcode_t dlo_mode_final(const dlo_final_t flags)
+{
+ return dlo_ok;
+}
+
+
+dlo_mode_t *dlo_mode_from_number(const dlo_modenum_t num)
+{
+ static dlo_mode_t mode;
+
+ if (num < DLO_MODE_DATA_NUM)
+ {
+ mode.view.width = dlo_mode_data[num].width;
+ mode.view.height = dlo_mode_data[num].height;
+ mode.view.bpp = dlo_mode_data[num].bpp;
+ mode.view.base = 0;
+ mode.refresh = dlo_mode_data[num].refresh;
+ return &mode;
+ }
+ return NULL;
+}
+
+
+dlo_modenum_t dlo_mode_lookup(dlo_device_t * const dev, const uint16_t width, const uint16_t height, const uint8_t refresh, uint8_t bpp)
+{
+ /* Check that the requested screen mode is supported */
+ //DPRINTF("mode: lookup: %ux%u @ %u Hz, %u bpp\n", width, height, refresh, bpp);
+ return bpp != 24 ? DLO_INVALID_MODE : get_mode_number(dev, width, height, refresh, bpp);
+}
+
+
+dlo_retcode_t dlo_mode_change(dlo_device_t * const dev, const dlo_mode_t * const desc, dlo_modenum_t mode)
+{
+ /* If no mode number was specified on entry, try looking one up for the supplied bitmap */
+ if (mode == DLO_INVALID_MODE)
+ mode = get_mode_number(dev, desc->view.width, desc->view.height, 0, desc->view.bpp);
+
+ /* Change mode or return an error */
+ return mode_select(dev, desc, mode);
+}
+
+
+dlo_retcode_t dlo_mode_parse_edid(dlo_device_t * const dev, const uint8_t * const ptr, const size_t size)
+{
+ static edid_format_t edid;
+ uint32_t i;
+
+ /* Copy the header bytes straight into our structure (assumes the structure is correct size!) */
+ ASSERT(EDID_STRUCT_SZ == size);
+ if (memcmp(header, ptr, sizeof(header)))
+ return dlo_err_edid_fail;
+
+ if (bad_edid_checksum(ptr, size))
+ return dlo_err_edid_fail;
+
+#if (defined(DEBUG) && 0) /* If you really want this verbose debug output, change the 0 to a 1 */
+ uint32_t j;
+ /* Parse the vendor/product information */
+ for (j = 0; j < 128; j += 8)
+ {
+ DPRINTF("mode: edid: raw: ");
+ for (i = 0; i < 8; i++)
+ DPRINTF("%02X=%02X ", i + j, RD_B(ptr + i + j));
+ DPRINTF("\n");
+ }
+#endif
+
+ edid.product.manuf_name = LETOHS(RD_S(ptr + 0x08));
+ edid.product.prod_code = LETOHS(RD_S(ptr + 0x0A));
+ edid.product.serial_num = LETOHL(RD_L(ptr + 0x0C));
+ edid.product.manuf_wk = RD_B(ptr + 0x10);
+ edid.product.manuf_yr = RD_B(ptr + 0x11);
+ //DPRINTF("mode: edid: manuf &%X prod &%X serial &%X wk %u yr %u\n",
+ // edid.product.manuf_name, edid.product.prod_code, edid.product.serial_num,
+ // edid.product.manuf_wk, edid.product.manuf_yr + 1990);
+
+ /* Parse the EDID structure information */
+ edid.version.number = RD_B(ptr + 0x12);
+ edid.version.revision = RD_B(ptr + 0x13);
+ //DPRINTF("edid: version &%02X revision &%02X\n", edid.version.number, edid.version.revision);
+
+ /* Parse the basic dislpay parameters/features */
+ edid.basic.input_def = RD_B(ptr + 0x14);
+ edid.basic.max_horiz_sz = RD_B(ptr + 0x15);
+ edid.basic.max_vert_sz = RD_B(ptr + 0x16);
+ edid.basic.gamma = (100.0 + RD_B(ptr + 0x17)) / 100.0;
+ edid.basic.features = RD_B(ptr + 0x18);
+
+ /* Parse the colour characteristics */
+ parse_edid_colours(&(edid.colours), ptr + 0x19);
+
+ /* Parse the established timings */
+ edid.est_timings.timings[0] = RD_B(ptr + 0x23);
+ edid.est_timings.timings[1] = RD_B(ptr + 0x24);
+ edid.est_timings.resvd = RD_B(ptr + 0x25);
+
+ /* Parse the bits at the end of the EDID structure */
+ edid.ext_blocks = RD_B(ptr + 0x7E);
+
+ /* Parse all of the standard timing identification */
+ for (i = 0; i < sizeof(edid.std_timings.timing_id); i++)
+ edid.std_timings.timing_id[i] = RD_B(ptr + 0x26 + i);
+
+ /* Parse all of the detailed timing descriptions (or monitor descriptors) */
+ for (i = 0; i < 4; i++)
+ parse_edid_detail_desc(&(edid.timings[i]), ptr + 0x36 + (i * 0x12));
+
+ return lookup_edid_modes(dev, &edid);
+}
+
+
+void use_default_modes(dlo_device_t * const dev)
+{
+ uint32_t i;
+
+ for (i = 0; i < DLO_MODE_DATA_NUM; i++)
+ dev->supported[i] = (dlo_modenum_t)i;
+}
+
+
+/* File-scope function definitions -----------------------------------------------------*/
+
+
+static dlo_retcode_t vreg(dlo_device_t * const dev, uint8_t reg, uint8_t val)
+{
+ if (dev->bufend - dev->bufptr < 4)
+ return dlo_err_buf_full;
+
+ *(dev->bufptr)++ = '\xAF';
+ *(dev->bufptr)++ = '\x20';
+ *(dev->bufptr)++ = reg;
+ *(dev->bufptr)++ = val;
+
+ return dlo_ok;
+}
+
+
+static dlo_retcode_t vbuf(dlo_device_t * const dev, const char * buf, size_t len)
+{
+ if (dev->bufend - dev->bufptr < len)
+ return dlo_err_buf_full;
+
+ while (len--)
+ *(dev->bufptr)++ = *buf++;
+
+ return dlo_ok;
+}
+
+
+static dlo_modenum_t get_mode_number(dlo_device_t * const dev, const uint16_t width, const uint16_t height, const uint8_t refresh, const uint8_t bpp)
+{
+ dlo_modenum_t idx;
+ uint32_t num;
+
+ /* Look for all matching modes in our array of video timing structures.
+ *
+ * Note: if we don't have EDID data for the monitor attached to the device
+ * we simply look through all the modes we have, rather than only looking
+ * at the supported modes list.
+ */
+ for (idx = 0; idx < DLO_MODE_DATA_NUM; idx++)
+ {
+ /* Read the mode number from the device's supported modes array */
+ num = dev->supported[idx];
+ if (num == DLO_INVALID_MODE)
+ break;
+
+ /* This sequence of if statements looks odd, take care if you decide to 'optimise' it! */
+ if (dlo_mode_data[num].width != width)
+ continue;
+ if (bpp && dlo_mode_data[num].bpp != bpp)
+ continue;
+ if (height && dlo_mode_data[num].height != height)
+ continue;
+ if (refresh && dlo_mode_data[num].refresh != refresh)
+ continue;
+
+ /* If we're satisfied with the tests above, then return the mode number */
+ return num;
+ }
+
+ /* No matches found, return an invalid mode number */
+ return DLO_INVALID_MODE;
+}
+
+
+static dlo_retcode_t mode_select(dlo_device_t * const dev, const dlo_mode_t * const desc, const dlo_modenum_t mode)
+{
+ if (mode >= DLO_MODE_DATA_NUM || mode == DLO_INVALID_MODE)
+ return dlo_err_bad_mode;
+
+ /* Base address must be aligned to a two byte boundary */
+ if (desc->view.base & 1)
+ return dlo_err_bad_mode;
+
+ /* Flush the command buffer */
+ if (dlo_ok != dlo_usb_write(dev))
+ return DLO_INVALID_MODE;
+
+ dev->mode.view.base = desc->view.base;
+ dev->base8 = desc->view.base + (BYTES_PER_16BPP * desc->view.width * desc->view.height);
+ ERR(set_base(dev, dev->mode.view.base, dev->base8));
+
+ /* Only change mode if the new raster bitmap's characteristics differ from the current.
+ *
+ * Note: don't compare reduced blanking flag because if the rest is the same, we can use the
+ * same blanking type. However, there's an outside chance that the low_blank hint was changed
+ * since entering the current mode in which case you may well want a mode change to happen but
+ * we'll just hope that never happens (seems like a very unlikely scenario).
+ */
+ if (desc->view.width != dev->mode.view.width ||
+ desc->view.height != dev->mode.view.height ||
+ desc->view.bpp != dev->mode.view.bpp)
+ {
+ ERR(dlo_usb_chan_sel(dev, dlo_mode_data[mode].mode_en, dlo_mode_data[mode].mode_en_sz));
+ ERR(dlo_usb_write_buf(dev, dlo_mode_data[mode].data, dlo_mode_data[mode].data_sz));
+ ERR(dlo_usb_chan_sel(dev, DLO_MODE_POSTAMBLE, DSIZEOF(DLO_MODE_POSTAMBLE)));
+ }
+
+ /* Update the device with the new mode details */
+ dev->mode = *desc;
+ dev->mode.refresh = dlo_mode_data[mode].refresh;
+ dev->low_blank = dlo_mode_data[mode].low_blank;
+
+ //DPRINTF("mode: select: %ux%u @ %u Hz %u bpp (base &%X base8 &%X low? %s)\n",
+ // dev->mode.view.width, dev->mode.view.height, dev->mode.refresh, dev->mode.view.bpp,
+ // dev->mode.view.base, dev->base8, dev->low_blank ? "yes" : "no");
+
+ /* Flush the command buffer */
+ ERR(dlo_usb_write(dev));
+
+ /* Return a warning for DL160 modes */
+ return (mode < DLO_DL120_MODES) ? dlo_warn_dl160_mode : dlo_ok;
+}
+
+
+static uint16_t add_supported(dlo_device_t * const dev, uint16_t idx, const uint16_t width, const uint16_t height, const uint8_t refresh)
+{
+ dlo_modenum_t num;
+
+ num = get_mode_number(dev, width, height, refresh, 24);
+ if (num != DLO_INVALID_MODE)
+ dev->supported[idx++] = num;
+
+// DPRINTF("mode: add_supt: %ux%u @ %u Hz, %u bpp = num %u\n", width, height, refresh, 24, (int)num);
+
+ return idx;
+}
+
+
+static dlo_retcode_t lookup_edid_modes(dlo_device_t * const dev, const edid_format_t * const edid)
+{
+ uint32_t timings, bit;
+ uint32_t idx = 0;
+
+ /* Clear the native mode information for the device */
+ (void) dlo_memset(&dev->native, 0, sizeof(dlo_mode_t));
+
+ /* Add mode numbers for any supported established timing modes */
+ timings = edid->est_timings.timings[0] | (edid->est_timings.timings[1] << 8) | (edid->est_timings.resvd << 16);
+ for (bit = 0; bit < 24; bit++)
+ {
+ if (est_timings[bit].width)
+ idx = add_supported(dev, idx, est_timings[bit].width, est_timings[bit].height, est_timings[bit].refresh);
+ }
+
+ /* Add further support from the detailed timing descriptions */
+ for (timings = 0; timings < 4; timings++)
+ {
+ const edid_detail_t * const detail = &(edid->timings[timings].detail);
+
+ if (detail->is_detail)
+ {
+ uint8_t hz;
+
+ for (hz = 50; hz < 100; hz++)
+ {
+ uint32_t prev = idx;
+ uint32_t width = detail->hactl + ((detail->hactblankh & 0xF0) << 4);
+ uint32_t height = detail->vactl + ((detail->vactblankh & 0xF0) << 4);
+
+ idx = add_supported(dev, idx, width, height, hz);
+
+ /* Have we added a mode definition for the native resolution reported by the display? */
+ if (idx != prev)
+ {
+ dlo_modenum_t num = dev->supported[prev];
+
+ dev->native.view.base = 0;
+ dev->native.view.width = dlo_mode_data[num].width;
+ dev->native.view.height = dlo_mode_data[num].height;
+ dev->native.view.bpp = dlo_mode_data[num].bpp;
+ dev->native.refresh = dlo_mode_data[num].refresh;
+ DPRINTF("mode: lookup: native mode %u (%ux%u @ %u bpp, %uHz base &%X)\n",
+ num,
+ dev->native.view.width,
+ dev->native.view.height,
+ dev->native.view.bpp,
+ dev->native.refresh,
+ (int)dev->native.view.base);
+ }
+ }
+ }
+ }
+
+ /* Fill any remaining array entries with the invalid mode constant */
+ while (idx < DLO_MODE_DATA_NUM - 1)
+ dev->supported[idx++] = DLO_INVALID_MODE;
+
+ return dlo_ok;
+}
+
+
+static dlo_retcode_t set_base(dlo_device_t * const dev, const dlo_ptr_t base, const dlo_ptr_t base8)
+{
+ //DPRINTF("mode: set_base: base=&%X base8=&%X\n", base, base8);
+ ERR(vbuf(dev, WRITE_VIDREG_LOCK, DSIZEOF(WRITE_VIDREG_LOCK)));
+ ERR(vreg(dev, 0x20, base >> 16));
+ ERR(vreg(dev, 0x21, base >> 8));
+ ERR(vreg(dev, 0x22, base));
+ ERR(vreg(dev, 0x26, base8 >> 16));
+ ERR(vreg(dev, 0x27, base8 >> 8));
+ ERR(vreg(dev, 0x28, base8));
+ ERR(vbuf(dev, WRITE_VIDREG_UNLOCK, DSIZEOF(WRITE_VIDREG_UNLOCK)));
+ ERR(dlo_usb_write(dev));
+
+ return dlo_ok;
+}
+
+
+static bool bad_edid_checksum(const uint8_t * const ptr, const size_t size)
+{
+ uint32_t i;
+ uint8_t csum = 0;
+
+ for (i = 0; i < size; i++)
+ csum += ptr[i];
+
+ return 0 != csum;
+}
+
+
+static void parse_edid_detail_desc(edid_timing_desc_t * const desc, const uint8_t * const ptr)
+{
+ if (RD_B(ptr) || RD_B(ptr + 1) || RD_B(ptr + 2))
+ {
+ //DPRINTF("edid: found timing detail (&%04X)\n", LETOHS(RD_S(ptr)));
+ desc->detail.is_detail = true;
+ desc->detail.pixclk = (float)LETOHS(RD_S(ptr)) / 100.0;
+ desc->detail.hactl = RD_B(ptr + 0x02);
+ desc->detail.hblankl = RD_B(ptr + 0x03);
+ desc->detail.hactblankh = RD_B(ptr + 0x04);
+ desc->detail.vactl = RD_B(ptr + 0x05);
+ desc->detail.vblankl = RD_B(ptr + 0x06);
+ desc->detail.vactblankh = RD_B(ptr + 0x07);
+ desc->detail.hsyncoffl = RD_B(ptr + 0x08);
+ desc->detail.hsyncwl = RD_B(ptr + 0x09);
+ desc->detail.vsyncoffvsyncwl = RD_B(ptr + 0x0A);
+ desc->detail.synch = RD_B(ptr + 0x0B);
+ desc->detail.hsizel = RD_B(ptr + 0x0C);
+ desc->detail.vsizel = RD_B(ptr + 0x0D);
+ desc->detail.hvsizeh = RD_B(ptr + 0x0E);
+ desc->detail.hbord = RD_B(ptr + 0x0F);
+ desc->detail.vbord = RD_B(ptr + 0x10);
+ desc->detail.flags = RD_B(ptr + 0x11);
+
+ //DPRINTF("edid: Pixel Clock: %f MHz\n", (float)desc->detail.pixclk);
+ //DPRINTF("edid: H Active pixels: %d\n", desc->detail.hactl + ((desc->detail.hactblankh & 0xF0) << 4));
+ //DPRINTF("edid: H Blank pixels: %d\n", desc->detail.hblankl + ((desc->detail.hactblankh & 0x0F) << 8));
+ //DPRINTF("edid: V Active pixels: %d\n", desc->detail.vactl + ((desc->detail.vactblankh & 0xF0) << 4));
+ //DPRINTF("edid: V Blank pixels: %d\n", desc->detail.vblankl + ((desc->detail.vactblankh & 0x0F) << 8));
+ //DPRINTF("edid: H Sync Off: %d\n", desc->detail.hsyncoffl + ((desc->detail.synch & 0xC0) << 2));
+ //DPRINTF("edid: H Sync Width: %d\n", desc->detail.hsyncwl + ((desc->detail.synch & 0x30) << 4));
+ //DPRINTF("edid: V Sync Off: %d\n", (desc->detail.vsyncoffvsyncwl >> 4) + ((desc->detail.synch & 0x0C) << 6));
+ //DPRINTF("edid: V Sync Width: %d\n", (desc->detail.vsyncoffvsyncwl & 0xF) + ((desc->detail.synch & 0x03) << 8));
+ //DPRINTF("edid: H size: %d mm\n", desc->detail.hsizel + ((desc->detail.hvsizeh & 0xF0) << 4));
+ //DPRINTF("edid: V size: %d mm\n", desc->detail.vsizel + ((desc->detail.hvsizeh & 0x0F) << 8));
+ }
+ else
+ {
+ /* It's a mode descriptor - ignore for now */
+ //DPRINTF("edid: found a mode descriptor type &%02X\n", RD_B(ptr+3));
+ desc->desc.is_detail = false;
+ switch (RD_B(ptr+3))
+ {
+ case 0xFC:
+ case 0xFE:
+ case 0xFF:
+ {
+ char buf[14];
+ char *chr;
+
+ snprintf(buf, 13, "%s", ptr + 5);
+ buf[13] = '\0';
+ chr = strchr(buf, '\n');
+ if (chr)
+ *chr = '\0';
+ //DPRINTF("edid: monitor string '%s'\n", buf);
+ break;
+ }
+ default:
+ {
+ //uint32_t i;
+ //DPRINTF("edid: ");
+ //for (i = 0; i < 0x12; i++)
+ // DPRINTF("%02X ", RD_B(ptr+i));
+ //DPRINTF("\n");
+ }
+ }
+ }
+}
+
+static void parse_edid_colours(edid_colours_t * const cols, const uint8_t * const ptr)
+{
+ /* Read the raw data */
+ cols->red_grn_low = RD_B(ptr + 0x19);
+ cols->blu_wht_low = RD_B(ptr + 0x1A);
+ cols->red_x = RD_B(ptr + 0x1B);
+ cols->red_y = RD_B(ptr + 0x1C);
+ cols->grn_x = RD_B(ptr + 0x1D);
+ cols->grn_y = RD_B(ptr + 0x1E);
+ cols->blu_x = RD_B(ptr + 0x1F);
+ cols->blu_y = RD_B(ptr + 0x20);
+ cols->wht_x = RD_B(ptr + 0x21);
+ cols->wht_y = RD_B(ptr + 0x22);
+
+ /* Do the expansion */
+ cols->red_x = ((cols->red_grn_low & 0xC0) >> 6) + (cols->red_x << 2);
+ cols->red_y = ((cols->red_grn_low & 0x30) >> 4) + (cols->red_y << 2);
+ cols->grn_x = ((cols->red_grn_low & 0x0C) >> 2) + (cols->grn_x << 2);
+ cols->grn_y = ((cols->red_grn_low & 0x03) >> 0) + (cols->grn_y << 2);
+ cols->blu_x = ((cols->blu_wht_low & 0xC0) >> 6) + (cols->blu_x << 2);
+ cols->blu_y = ((cols->blu_wht_low & 0x40) >> 4) + (cols->blu_y << 2);
+ cols->wht_x = ((cols->blu_wht_low & 0x0C) >> 2) + (cols->wht_y << 2);
+ cols->wht_y = ((cols->blu_wht_low & 0x03) >> 0) + (cols->wht_y << 2);
+}
+
+
+/* End of file -------------------------------------------------------------------------*/
diff --git a/src/dlo_mode.h b/src/dlo_mode.h
index 822cd0a..9932139 100644
--- a/src/dlo_mode.h
+++ b/src/dlo_mode.h
@@ -1,127 +1,127 @@
-/** @file dlo_mode.h
- *
- * @brief Definitions for the screen mode-related functions.
- *
- * These functions have been separated-out into a distinct compilation unit so that
- * it would be possible to build a distribution of the DisplayLink library which
- * inludes the object(s) associated with this unit as pre-built binaries (i.e.
- * without the dlo_mode.c source file included).
- *
- * DisplayLink Open Source Software (libdlo)
- * Copyright (C) 2009, DisplayLink
- * www.displaylink.com
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Library General Public License as published by the Free
- * Software Foundation; LGPL version 2, dated June 1991.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef DLO_MODE_H
-#define DLO_MODE_H /**< Avoid multiple inclusion. */
-
-#include "dlo_structs.h"
-
-
-/** Size of an EDID structure, as read from a device (bytes).
- */
-#define EDID_STRUCT_SZ (128)
-
-
-/** An undefined mode number. Used to indicate a failed look-up or an unknown mode.
- */
-#define DLO_INVALID_MODE ((dlo_modenum_t)-1)
-
-
-/** Initialise the screen mode handling functions.
- *
- * @param flags Initialisation flags word (unused flags ignored).
- *
- * @return Return code, zero for no error.
- */
-extern dlo_retcode_t dlo_mode_init(const dlo_init_t flags);
-
-
-/** Finalisation call for the screen mode handling functions.
- *
- * @param flags Finalisation flags word (unused flags ignored).
- *
- * @return Return code, zero for no error.
- */
-extern dlo_retcode_t dlo_mode_final(const dlo_final_t flags);
-
-
-/** Return a block of mode information for a given mode number.
- *
- * @param num Mode number for best match to the supplied bitmap.
- *
- * @return Pointer to mode information block (in static workspace), or NULL if error.
- */
-extern dlo_mode_t *dlo_mode_from_number(const dlo_modenum_t num);
-
-
-/** Select a display mode given a set of parameters.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param width Width of desired display (pixels).
- * @param height Hieght of desired display (pixels) - zero to select first available.
- * @param refresh Desired refresh rate (Hz) - zero to select first available.
- * @param bpp Colour depth (bits per pixel) - zero to select first available.
- *
- * @return Return code, zero for no error.
- *
- * Will find the best match it can from the VESA timings, given the parameters specified.
- * If no matching mode can be found, an error will be returned and the device's screen
- * mode will not be changed.
- */
-extern dlo_modenum_t dlo_mode_lookup(dlo_device_t * const dev, const uint16_t width, const uint16_t height, const uint8_t refresh, uint8_t bpp);
-
-
-/** Perform a mode change into the specified mode number.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param desc Pointer to mode description structure.
- * @param mode Mode number for best match to the mode descriptor (or @a DLO_INVALID_MODE if not known).
- *
- * @return Return code, zero for no error.
- *
- * This call will change the screen mode into the specified mode number (if one was given)
- * or look for one which matches the specified mode description. Chaging mode does not imply
- * clearing the screen!
- *
- * Note: this call will cause any buffered commands to be sent to the device.
- */
-extern dlo_retcode_t dlo_mode_change(dlo_device_t * const dev, const dlo_mode_t * const desc, dlo_modenum_t mode);
-
-
-/** Parse the EDID structure read from a display device and build a list of supported modes.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param ptr Pointer to EDID structure.
- * @param size Size of EDID structure (bytes).
- *
- * @return Return code, zero for no error.
- *
- * This call updates the @a dlo_device_t structure by constructing a list of supported
- * modes. Any modes which were not supplied in the EDID structure will be refused for
- * that device.
- */
-extern dlo_retcode_t dlo_mode_parse_edid(dlo_device_t * const dev, const uint8_t * const ptr, const size_t size);
-
-
-/** Reset the supported modes array for a device to include all of the default VESA mode timings.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- */
-extern void use_default_modes(dlo_device_t * const dev);
-
-
-#endif
+/** @file dlo_mode.h
+ *
+ * @brief Definitions for the screen mode-related functions.
+ *
+ * These functions have been separated-out into a distinct compilation unit so that
+ * it would be possible to build a distribution of the DisplayLink library which
+ * inludes the object(s) associated with this unit as pre-built binaries (i.e.
+ * without the dlo_mode.c source file included).
+ *
+ * DisplayLink Open Source Software (libdlo)
+ * Copyright (C) 2009, DisplayLink
+ * www.displaylink.com
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by the Free
+ * Software Foundation; LGPL version 2, dated June 1991.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef DLO_MODE_H
+#define DLO_MODE_H /**< Avoid multiple inclusion. */
+
+#include "dlo_structs.h"
+
+
+/** Size of an EDID structure, as read from a device (bytes).
+ */
+#define EDID_STRUCT_SZ (128)
+
+
+/** An undefined mode number. Used to indicate a failed look-up or an unknown mode.
+ */
+#define DLO_INVALID_MODE ((dlo_modenum_t)-1)
+
+
+/** Initialise the screen mode handling functions.
+ *
+ * @param flags Initialisation flags word (unused flags ignored).
+ *
+ * @return Return code, zero for no error.
+ */
+extern dlo_retcode_t dlo_mode_init(const dlo_init_t flags);
+
+
+/** Finalisation call for the screen mode handling functions.
+ *
+ * @param flags Finalisation flags word (unused flags ignored).
+ *
+ * @return Return code, zero for no error.
+ */
+extern dlo_retcode_t dlo_mode_final(const dlo_final_t flags);
+
+
+/** Return a block of mode information for a given mode number.
+ *
+ * @param num Mode number for best match to the supplied bitmap.
+ *
+ * @return Pointer to mode information block (in static workspace), or NULL if error.
+ */
+extern dlo_mode_t *dlo_mode_from_number(const dlo_modenum_t num);
+
+
+/** Select a display mode given a set of parameters.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param width Width of desired display (pixels).
+ * @param height Hieght of desired display (pixels) - zero to select first available.
+ * @param refresh Desired refresh rate (Hz) - zero to select first available.
+ * @param bpp Colour depth (bits per pixel) - zero to select first available.
+ *
+ * @return Return code, zero for no error.
+ *
+ * Will find the best match it can from the VESA timings, given the parameters specified.
+ * If no matching mode can be found, an error will be returned and the device's screen
+ * mode will not be changed.
+ */
+extern dlo_modenum_t dlo_mode_lookup(dlo_device_t * const dev, const uint16_t width, const uint16_t height, const uint8_t refresh, uint8_t bpp);
+
+
+/** Perform a mode change into the specified mode number.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param desc Pointer to mode description structure.
+ * @param mode Mode number for best match to the mode descriptor (or @a DLO_INVALID_MODE if not known).
+ *
+ * @return Return code, zero for no error.
+ *
+ * This call will change the screen mode into the specified mode number (if one was given)
+ * or look for one which matches the specified mode description. Chaging mode does not imply
+ * clearing the screen!
+ *
+ * Note: this call will cause any buffered commands to be sent to the device.
+ */
+extern dlo_retcode_t dlo_mode_change(dlo_device_t * const dev, const dlo_mode_t * const desc, dlo_modenum_t mode);
+
+
+/** Parse the EDID structure read from a display device and build a list of supported modes.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param ptr Pointer to EDID structure.
+ * @param size Size of EDID structure (bytes).
+ *
+ * @return Return code, zero for no error.
+ *
+ * This call updates the @a dlo_device_t structure by constructing a list of supported
+ * modes. Any modes which were not supplied in the EDID structure will be refused for
+ * that device.
+ */
+extern dlo_retcode_t dlo_mode_parse_edid(dlo_device_t * const dev, const uint8_t * const ptr, const size_t size);
+
+
+/** Reset the supported modes array for a device to include all of the default VESA mode timings.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ */
+extern void use_default_modes(dlo_device_t * const dev);
+
+
+#endif
diff --git a/src/dlo_structs.h b/src/dlo_structs.h
index d639a59..35e600d 100644
--- a/src/dlo_structs.h
+++ b/src/dlo_structs.h
@@ -1,92 +1,92 @@
-/** @file dlo_structs.h
- *
- * @brief This file defines all of the internal structures used by libdlo.
- *
- * DisplayLink Open Source Software (libdlo)
- * Copyright (C) 2009, DisplayLink
- * www.displaylink.com
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Library General Public License as published by the Free
- * Software Foundation; LGPL version 2, dated June 1991.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef DLO_STRUCTS_H
-#define DLO_STRUCTS_H /**< Avoid multiple inclusion. */
-
-#include "libdlo.h"
-#include "dlo_data.h"
-
-
-/** Structure holding all of the information specific to a particular device.
- */
-typedef struct dlo_device_s dlo_device_t;
-
-
-/** A mode number used to index a specific mode from the list defined in dlo_mode_data.c.
- */
-typedef uint32_t dlo_modenum_t;
-
-
-/** Structure used internally by dlo_usb.c (stored as dev->cnct in @a dlo_device_t structure).
- *
- * This is required to keep track of which USB device a given @a dlo_device_t structure
- * represents so that our various functions can do their stuff with libusb.
- */
-typedef struct dlo_usb_dev_s
-{
- struct usb_device *udev; /**< Pointer to USB device structure for given device. */
- usb_dev_handle *uhand; /**< USB device handle (once device is "opened"). */
-} dlo_usb_dev_t; /**< A struct @a dlo_usb_dev_s. */
-
-
-/** An internal representation of a viewport within the DisplayLink device.
- *
- * An area is generated from a viewport and a rectangle within that viewport (which
- * has no parts lying outside but may cover the complete extent of the viewport). It
- * has a base address for both the 16 bpp component of a pixel's colour and the 8 bpp
- * fine detail component. It also requires a stride in the case where the rectangle
- * didn't fully occupy the horizontal extent of the viewport.
- */
-typedef struct dlo_area_s
-{
- dlo_view_t view; /**< Viewport information (normalised to a specific rectangle within a viewport). */
- dlo_ptr_t base8; /**< The base address of the 8 bpp fine detail colour information. */
- uint32_t stride; /**< The stride (pixels) from one pixel in the area to the one directly below. */
-} dlo_area_t; /**< A struct @a dlo_area_s. */
-
-
-/** Structure holding all of the information specific to a particular device.
- */
-struct dlo_device_s
-{
- dlo_device_t *prev; /**< Pointer to previous node on device list. */
- dlo_device_t *next; /**< Pointer to next node on device list. */
- dlo_devtype_t type; /**< Type of DisplayLink device. */
- char *serial; /**< Pointer to device serial number string. */
- bool claimed; /**< Has the device been claimed by someone? */
- bool check; /**< Flag is toggled for each enumeration to spot dead nodes in device list. */
- uint32_t timeout; /**< Timeout for bulk communications (milliseconds). */
- uint32_t memory; /**< Total size of storage in the device (bytes). */
- char *buffer; /**< Pointer to the base of the command buffer. */
- char *bufptr; /**< Pointer to the first free byte in the command buffer. */
- char *bufend; /**< Pointer to the byte after the end byte of the command buffer. */
- dlo_usb_dev_t *cnct; /**< Private word for connection specific data or structure pointer. */
- dlo_mode_t mode; /**< Current display mode information. */
- dlo_ptr_t base8; /**< Pointer to the base of the 8bpp segment (if any). */
- bool low_blank; /**< The current raster screen mode has reduced blanking. */
- dlo_mode_t native; /**< Mode number of the display's native screen mode (if any). */
- dlo_modenum_t supported[DLO_MODE_DATA_NUM]; /**< Array of supported mode numbers. */
-};
-
-
-#endif
+/** @file dlo_structs.h
+ *
+ * @brief This file defines all of the internal structures used by libdlo.
+ *
+ * DisplayLink Open Source Software (libdlo)
+ * Copyright (C) 2009, DisplayLink
+ * www.displaylink.com
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by the Free
+ * Software Foundation; LGPL version 2, dated June 1991.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef DLO_STRUCTS_H
+#define DLO_STRUCTS_H /**< Avoid multiple inclusion. */
+
+#include "libdlo.h"
+#include "dlo_data.h"
+
+
+/** Structure holding all of the information specific to a particular device.
+ */
+typedef struct dlo_device_s dlo_device_t;
+
+
+/** A mode number used to index a specific mode from the list defined in dlo_mode_data.c.
+ */
+typedef uint32_t dlo_modenum_t;
+
+
+/** Structure used internally by dlo_usb.c (stored as dev->cnct in @a dlo_device_t structure).
+ *
+ * This is required to keep track of which USB device a given @a dlo_device_t structure
+ * represents so that our various functions can do their stuff with libusb.
+ */
+typedef struct dlo_usb_dev_s
+{
+ struct usb_device *udev; /**< Pointer to USB device structure for given device. */
+ usb_dev_handle *uhand; /**< USB device handle (once device is "opened"). */
+} dlo_usb_dev_t; /**< A struct @a dlo_usb_dev_s. */
+
+
+/** An internal representation of a viewport within the DisplayLink device.
+ *
+ * An area is generated from a viewport and a rectangle within that viewport (which
+ * has no parts lying outside but may cover the complete extent of the viewport). It
+ * has a base address for both the 16 bpp component of a pixel's colour and the 8 bpp
+ * fine detail component. It also requires a stride in the case where the rectangle
+ * didn't fully occupy the horizontal extent of the viewport.
+ */
+typedef struct dlo_area_s
+{
+ dlo_view_t view; /**< Viewport information (normalised to a specific rectangle within a viewport). */
+ dlo_ptr_t base8; /**< The base address of the 8 bpp fine detail colour information. */
+ uint32_t stride; /**< The stride (pixels) from one pixel in the area to the one directly below. */
+} dlo_area_t; /**< A struct @a dlo_area_s. */
+
+
+/** Structure holding all of the information specific to a particular device.
+ */
+struct dlo_device_s
+{
+ dlo_device_t *prev; /**< Pointer to previous node on device list. */
+ dlo_device_t *next; /**< Pointer to next node on device list. */
+ dlo_devtype_t type; /**< Type of DisplayLink device. */
+ char *serial; /**< Pointer to device serial number string. */
+ bool claimed; /**< Has the device been claimed by someone? */
+ bool check; /**< Flag is toggled for each enumeration to spot dead nodes in device list. */
+ uint32_t timeout; /**< Timeout for bulk communications (milliseconds). */
+ uint32_t memory; /**< Total size of storage in the device (bytes). */
+ char *buffer; /**< Pointer to the base of the command buffer. */
+ char *bufptr; /**< Pointer to the first free byte in the command buffer. */
+ char *bufend; /**< Pointer to the byte after the end byte of the command buffer. */
+ dlo_usb_dev_t *cnct; /**< Private word for connection specific data or structure pointer. */
+ dlo_mode_t mode; /**< Current display mode information. */
+ dlo_ptr_t base8; /**< Pointer to the base of the 8bpp segment (if any). */
+ bool low_blank; /**< The current raster screen mode has reduced blanking. */
+ dlo_mode_t native; /**< Mode number of the display's native screen mode (if any). */
+ dlo_modenum_t supported[DLO_MODE_DATA_NUM]; /**< Array of supported mode numbers. */
+};
+
+
+#endif
diff --git a/src/dlo_usb.c b/src/dlo_usb.c
index a2e1bf1..4fbf282 100644
--- a/src/dlo_usb.c
+++ b/src/dlo_usb.c
@@ -1,561 +1,561 @@
-/** @file dlo_usb.c
- *
- * @brief Implements the USB-specific connectivity functions.
- *
- * DisplayLink Open Source Software (libdlo)
- * Copyright (C) 2009, DisplayLink
- * www.displaylink.com
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Library General Public License as published by the Free
- * Software Foundation; LGPL version 2, dated June 1991.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <string.h>
-#include "netinet/in.h"
-#include "dlo_defs.h"
-#include "dlo_usb.h"
-#include "dlo_base.h"
-#include "dlo_mode.h"
-
-
-/* File-scope defines ------------------------------------------------------------------*/
-
-
-#define NR_USB_REQUEST_STATUS_DW (0x06) /**< USB control message: request type. */
-#define NR_USB_REQUEST_CHANNEL (0x12) /**< USB control message: request type. */
-#define NR_USB_REQUEST_I2C_SUB_IO (0x02) /**< USB control message: request type. */
-
-/** USB VendorID for a DisplayLink device.
- */
-#define VENDORID_DISPLAYLINK (0x17E9)
-
-/** Number of milliseconds to wait before timing-out a USB control message.
- */
-#define CTRL_TIMEOUT (100u)
-
-/** Number of milliseconds to wait before timing-out channel selection message.
- */
-#define CHANSEL_TIMEOUT (5000u)
-
-/** Number of milliseconds to wait before timing-out a USB bulk transfer.
- */
-#define WRITE_TIMEOUT (10000u)
-
-/** Number of milliseconds to wait before timing-out a request for the device type.
- */
-#define ID_TIMEOUT (1000u)
-
-/** Byte sequence to send to the device to select the default communication channel.
- */
-#define STD_CHANNEL "\x57\xCD\xDC\xA7\x1C\x88\x5E\x15\x60\xFE\xC6\x97\x16\x3D\x47\xF2"
-
-
-/* File-scope types --------------------------------------------------------------------*/
-
-
-/* External scope variables ------------------------------------------------------------*/
-
-
-int32_t usberr = 0;
-
-
-/* File-scope variables ----------------------------------------------------------------*/
-
-
-/** Pointer to a copy of the last error message string read out of libusb (or NULL).
- */
-static char *usb_err_str = NULL;
-
-
-/* File-scope function declarations ----------------------------------------------------*/
-
-
-/** Connect to a device, read information about it and then disconnect again.
- *
- * @param dev USB device structure pointer.
- *
- * @return Return code, zero for no error.
- */
-static dlo_retcode_t check_device(struct usb_device *dev);
-
-
-/** Attempt to read the EDID structure from the monitor attached to the specified device.
- *
- * @param dev Device structure pointer.
- * @param uhand USB device handle.
- *
- * @return Return code, zero for no error.
- */
-static dlo_retcode_t read_edid(dlo_device_t * const dev, usb_dev_handle *uhand);
-
-
-/** Make a note of any error returned by libusb.
- *
- * @return Return code to indicate a USB-related error.
- *
- * Often, by the time we have returned from a function, the error code stored in libusb
- * has been lost because our tidy-up code will call more libusb functions after an error
- * is spotted. As such, this function is called automatically by the @c UERR() and
- * @c UERR_GOTO() macros in order to make a note of the error number and message from
- * libusb at the moment the error is caught. This information is stored locally for
- * retrieval by @c dlo_usb_strerror().
- */
-static dlo_retcode_t usb_error_grab(void);
-
-
-/* Public function definitions ---------------------------------------------------------*/
-
-
-char *dlo_usb_strerror(void)
-{
- //DPRINTF("usb: error lookup %d\n", usberr);
- return usb_err_str;
-}
-
-
-dlo_retcode_t dlo_usb_init(const dlo_init_t flags)
-{
- /* Initialise libusb */
- //DPRINTF("usb: init\n");
- usb_init();
-
- /* Add nodes onto the device list for any DisplayLink devices we find */
- //DPRINTF("usb: init: enum\n");
- ERR(dlo_usb_enumerate(true));
-
- return dlo_ok;
-}
-
-
-dlo_retcode_t dlo_usb_final(const dlo_final_t flags)
-{
- if (usb_err_str)
- dlo_free(usb_err_str);
-
- return dlo_ok;
-}
-
-dlo_retcode_t dlo_usb_enumerate(const bool init)
-{
- struct usb_bus *bus;
- struct usb_device *dev = NULL;
- int32_t db = usb_find_busses();
- int32_t dd = usb_find_devices();
- DPRINTF("usb: dlo_usb_enumerate\n");
-
- /* We should do this even if it looks like there are no changes on the bus because
- * an open() call might call the above functions just to check it's safe to use the
- * USB device structure pointer. Yuck!
- *
- * If this isn't the first enumeration and there are no changes on the bus, don't touch the list
- *
- * if (!init && !db && !dd)
- * return dlo_ok;
- */
- IGNORE(db);
- IGNORE(dd);
-
- /* Look for all DisplayLink devices on the USB busses */
- for (bus = usb_get_busses(); bus; bus = bus->next)
- for (dev = bus->devices; dev; dev = dev->next)
- ERR(check_device(dev)); /* Check to see if it's a DisplayLink device. If it is, add to or update the dev_list */
-
- return dlo_ok;
-}
-
-
-static dlo_retcode_t check_device(struct usb_device *udev)
-{
- static char string[255];
- usb_dev_handle *uhand = usb_open(udev);
- dlo_retcode_t err = dlo_ok;
- dlo_device_t *dev = NULL;
- bool not_root = false;
- uint8_t buf[4];
- dlo_devtype_t type;
-
- //DPRINTF("usb: check: check dev &%X\n", (int)dev);
-
- if (!uhand) {
- // this may not be our device. We just can't open it
- return dlo_ok;
- }
-
- //DPRINTF("usb: check: uhand &%X vendorID &%X\n", (int)uhand, udev->descriptor.idVendor);
-
- /* Reject devices that don't have the DisplayLink VendorID */
- if (udev->descriptor.idVendor != VENDORID_DISPLAYLINK)
- {
- UERR(usb_close(uhand));
- return dlo_ok;
- }
- //DPRINTF("usb: check: get type\n");
-
- /* Ask the device for some status information */
- not_root = true; /* Special case error handling here */
- UERR_GOTO(usb_control_msg(/* handle */ uhand,
- /* requestType */ USB_ENDPOINT_IN | USB_TYPE_VENDOR,
- /* request */ NR_USB_REQUEST_STATUS_DW,
- /* value */ 0,
- /* index */ 0,
- /* bytes */ (char *)buf,
- /* size */ sizeof(buf),
- /* timeout */ ID_TIMEOUT));
- not_root = false; /* Back to normal error handling */
- //DPRINTF("usb: check: type buf[3] = &%X\n", buf[3]);
-
- /* Determine what type of device we are connected to */
- switch ((buf[3] >> 4) & 0xF)
- {
- case dlo_dev_base:
- type = dlo_dev_base;
- break;
- case dlo_dev_alex:
- type = dlo_dev_alex;
- break;
- default:
- if (buf[3] == dlo_dev_ollie)
- type = dlo_dev_ollie;
- else
- type = dlo_dev_unknown;
- }
-
- /* Read the device serial number as a string */
- UERR_GOTO(usb_get_string_simple(uhand, udev->descriptor.iSerialNumber, string, sizeof(string)));
- //DPRINTF("usb: check: type &%X serial '%s'\n", (int)type, string);
-
- /* See if this device is already in our device list */
- dev = dlo_device_lookup(string);
- if (dev)
- {
- /* Use this opportunity to update the USB device structure pointer, just in
- * case it has moved.
- */
- dev->cnct->udev = udev;
- //DPRINTF("usb: check: already in list\n");
- }
- else
- {
- /* Add a new device to the device list */
- //DPRINTF("usb: check: create new device\n");
- dev = dlo_new_device(type, string);
- NERR_GOTO(dev);
-
- /* It's not. Create and initialise a new list node for the device */
- dev->cnct = (dlo_usb_dev_t *)dlo_malloc(sizeof(dlo_usb_dev_t));
- NERR_GOTO(dev->cnct);
- dev->cnct->udev = udev;
- dev->cnct->uhand = NULL;
- }
- //DPRINTF("usb: check: dlpp node &%X\n", (int)dev);
-
- /* Close our temporary handle for the device. If this errors, we'll have a duff entry in
- * the device list but at least the list integrity will be OK.
- */
- UERR_GOTO(usb_close(uhand));
-
- return dlo_ok;
-
-error:
- /* Free our dev->cnct USB information structure */
- if (dev)
- {
- if (dev->cnct)
- dlo_free(dev->cnct);
- dev->cnct = NULL;
- }
-
- /* Close our temporary handle for the device */
- (void) usb_close(uhand);
-
- /* If the executable wasn't run as root, this is where it normally falls over.
- * So we'll special case that particular error to help indicate this problem.
- */
- if (not_root)
- return dlo_err_not_root;
-
- return err;
-}
-
-
-dlo_retcode_t dlo_usb_open(dlo_device_t * const dev)
-{
- dlo_retcode_t err;
- usb_dev_handle *uhand;
- char* driver_name;
- int usb_configuration;
- int i;
- int32_t db = usb_find_busses();
- int32_t dd = usb_find_devices();
-
- /* Do we trust the USB device pointer? Not if the structures may have changed under us... */
- if (db || dd)
- return dlo_err_reenum;
-
- /* Open the device */
- uhand = usb_open(dev->cnct->udev);
- DPRINTF("usb: open: uhand &%X\n", (int)uhand);
-
- if (!uhand)
- return dlo_err_open;
-
- /* Store the USB device handle in our dev->cnct word */
- dev->cnct->uhand = uhand;
-
- /* Establish the connection with the device */
- //DPRINTF("usb: open: setting config...\n");
-
- /*
- * Because some displaylink devices may report
- * a class code (like HID or MSC) that gets
- * matched by a kernel driver, we must detach
- * those drivers before libusb can successfully
- * set configuration or talk to those devices.
- * For now, we kick everyone off our device,
- * but that includes cases we're intentionally
- * a composite device with HID interfaces that
- * control something (e.g. a button on a dock).
- * And the code below is blindly unloading
- * the kernel HID drivers for those. May want
- * to get more sophisticated in the future.
- */
- driver_name = dlo_malloc(128);
- for (i=0; i < dev->cnct->udev->config->bNumInterfaces; i++)
- {
- memset(driver_name, 0, 128);
- if (usb_get_driver_np(uhand, i, driver_name, 128) == 0)
- {
- DPRINTF("usb: driver (%s) already attached to device\n", driver_name);
-
- // Reports are that this call can return error even if successful
- usb_detach_kernel_driver_np(uhand,i);
- }
- }
-
- UERR(usb_set_configuration(uhand, 1));
-
- //DPRINTF("usb: open: claiming iface...\n");
- UERR(usb_claim_interface(uhand, 0));
-
- /* Mark the device as claimed */
- dev->claimed = true;
-
- /* Allocate a buffer to hold commands before they are sent to the device */
- if (!dev->buffer)
- {
- //DPRINTF("usb: open: alloc buffer...\n");
- dev->buffer = dlo_malloc(BUF_SIZE);
- NERR(dev->buffer);
- dev->bufptr = dev->buffer;
- dev->bufend = dev->buffer + BUF_SIZE;
- }
- //DPRINTF("usb: open: buffer &%X, &%X, &%X\n", (int)dev->buffer, (int)dev->bufptr, (int)dev->bufend);
-
- /* Use the default timeout if none was specified */
- if (!dev->timeout)
- dev->timeout = WRITE_TIMEOUT;
- //DPRINTF("usb: open: timeout %u ms\n", dev->timeout);
-
- /* Initialise the supported modes array for this device to include all our pre-defined modes */
- use_default_modes(dev);
-
- /* Attempt to read the EDID information, to refine the supported modes array contents */
- err = read_edid(dev, uhand);
-#ifdef DEBUG
- if (err != dlo_ok)
- DPRINTF("usb: open: edid error %u '%s'\n", (int)err, dlo_strerror(err));
-#endif
-
- return dlo_ok;
-}
-
-
-dlo_retcode_t dlo_usb_close(dlo_device_t * const dev)
-{
- if (dev->claimed)
- {
- if (dev->buffer)
- {
- dlo_free(dev->buffer);
- dev->buffer = NULL;
- dev->bufptr = NULL;
- dev->bufend = NULL;
- }
- dev->claimed = false;
- UERR(usb_release_interface(dev->cnct->uhand, 0));
- UERR(usb_close(dev->cnct->uhand));
- }
- return dlo_ok;
-}
-
-
-dlo_retcode_t dlo_usb_chan_sel(const dlo_device_t * const dev, const char * const buf, const size_t size)
-{
- if (size)
- UERR(usb_control_msg(/* handle */ dev->cnct->uhand,
- /* requestType */ USB_TYPE_VENDOR,
- /* request */ NR_USB_REQUEST_CHANNEL,
- /* value */ 0,
- /* index */ 0,
- /* bytes */ (char *)buf,
- /* size */ size,
- /* timeout */ CHANSEL_TIMEOUT));
- return dlo_ok;
-}
-
-
-dlo_retcode_t dlo_usb_std_chan(const dlo_device_t * const dev)
-{
- dlo_retcode_t err;
-
- ASSERT(strlen(STD_CHANNEL) == 16);
- err = dlo_usb_chan_sel(dev, STD_CHANNEL, DSIZEOF(STD_CHANNEL));
-
- return err;
-}
-
-
-dlo_retcode_t dlo_usb_write(dlo_device_t * const dev)
-{
- dlo_retcode_t err = dlo_usb_write_buf(dev, dev->buffer, dev->bufptr - dev->buffer);
-
- dev->bufptr = dev->buffer;
-
- return err;
-}
-
-
-dlo_retcode_t dlo_usb_write_buf(dlo_device_t * const dev, char * buf, size_t size)
-{
-#ifdef DEBUG_DUMP
- static char outfile[64];
- static uint32_t outnum = 0;
- FILE *out = NULL;
-#endif
-
- if (!dev->claimed)
- return dlo_err_unclaimed;
-
- if (!size)
- return dlo_ok;
-
-#ifdef WRITE_BUF_BODGE
- /* If the buffer to write is fewer than 513 bytes in size, copy into 513 byte buffer and pad with zeros */
- if (size < WRITE_BUF_BODGE)
- {
- dlo_retcode_t err;
- uint32_t rem = WRITE_BUF_BODGE - size;
- char *cpy = dlo_malloc(WRITE_BUF_BODGE);
-
- NERR(cpy);
- dlo_memcpy(cpy, buf, size);
- dlo_memset(cpy + size, 0, rem);
- err = dlo_usb_write_buf(dev, cpy, size + rem);
- dlo_free(cpy);
-
- return err;
- }
-#endif
-
- while (size)
- {
- size_t num = size > BUF_SIZE ? BUF_SIZE : size;
-
-#ifdef DEBUG_DUMP
- (void) snprintf(outfile, sizeof(outfile), "dump/%02X/bulk%03X.dat", outnum & 0xFF, outnum >> 8);
- outnum++;
- out = fopen(outfile, "wb");
- if (out)
- {
- (void) fwrite(buf, num, 1, out);
- (void) fclose(out);
- out = NULL;
- }
-#endif
-
- UERR(usb_bulk_write(/* handle */ dev->cnct->uhand,
- /* endpoint */ 1,
- /* bytes */ buf,
- /* size */ num,
- /* timeout */ dev->timeout));
- buf += num;
- size -= num;
- }
- return dlo_ok;
-}
-
-
-/* File-scope function definitions -----------------------------------------------------*/
-
-
-static dlo_retcode_t usb_error_grab(void)
-{
- char *str = usb_strerror();
-
- /* If we have a previous USB error message stored, free it */
- if (usb_err_str)
- dlo_free(usb_err_str);
-
- if (str)
- {
- /* Allocate memory for the new error message and store that */
- usb_err_str = dlo_malloc(1 + strlen(str));
- if (usb_err_str)
- strcpy(usb_err_str, str);
- }
-
- /* Always return the generic USB error code */
- return dlo_err_usb;
-}
-
-
-
-static dlo_retcode_t read_edid(dlo_device_t * const dev, usb_dev_handle *uhand)
-{
- dlo_retcode_t err;
- uint32_t i;
- uint8_t buf[2];
- uint8_t *edid;
-
- /* Allocate a buffer to hold the EDID structure */
- edid = dlo_malloc(EDID_STRUCT_SZ);
- NERR(edid);
-
- /* Attempt to read the EDID structure from the device */
- for (i = 0; i < EDID_STRUCT_SZ; i++)
- {
- UERR_GOTO(usb_control_msg(/* handle */ uhand,
- /* requestType */ USB_ENDPOINT_IN | USB_TYPE_VENDOR,
- /* request */ NR_USB_REQUEST_I2C_SUB_IO,
- /* value */ i << 8,
- /* index */ 0xA1,
- /* bytes */ (char *)buf,
- /* size */ sizeof(buf),
- /* timeout */ dev->timeout));
- if (buf[0])
- ERR_GOTO(dlo_err_iic_op);
- //DPRINTF("usb: edid[%u]=&%02X\n", i, buf[1]);
- edid[i] = buf[1];
- }
-
- /* Supply the prospective EDID structure to the parser */
- ERR_GOTO(dlo_mode_parse_edid(dev, edid, EDID_STRUCT_SZ));
-
-error:
- dlo_free(edid);
-
- return err;
-}
-
-
-/* End of file -------------------------------------------------------------------------*/
+/** @file dlo_usb.c
+ *
+ * @brief Implements the USB-specific connectivity functions.
+ *
+ * DisplayLink Open Source Software (libdlo)
+ * Copyright (C) 2009, DisplayLink
+ * www.displaylink.com
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by the Free
+ * Software Foundation; LGPL version 2, dated June 1991.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include "netinet/in.h"
+#include "dlo_defs.h"
+#include "dlo_usb.h"
+#include "dlo_base.h"
+#include "dlo_mode.h"
+
+
+/* File-scope defines ------------------------------------------------------------------*/
+
+
+#define NR_USB_REQUEST_STATUS_DW (0x06) /**< USB control message: request type. */
+#define NR_USB_REQUEST_CHANNEL (0x12) /**< USB control message: request type. */
+#define NR_USB_REQUEST_I2C_SUB_IO (0x02) /**< USB control message: request type. */
+
+/** USB VendorID for a DisplayLink device.
+ */
+#define VENDORID_DISPLAYLINK (0x17E9)
+
+/** Number of milliseconds to wait before timing-out a USB control message.
+ */
+#define CTRL_TIMEOUT (100u)
+
+/** Number of milliseconds to wait before timing-out channel selection message.
+ */
+#define CHANSEL_TIMEOUT (5000u)
+
+/** Number of milliseconds to wait before timing-out a USB bulk transfer.
+ */
+#define WRITE_TIMEOUT (10000u)
+
+/** Number of milliseconds to wait before timing-out a request for the device type.
+ */
+#define ID_TIMEOUT (1000u)
+
+/** Byte sequence to send to the device to select the default communication channel.
+ */
+#define STD_CHANNEL "\x57\xCD\xDC\xA7\x1C\x88\x5E\x15\x60\xFE\xC6\x97\x16\x3D\x47\xF2"
+
+
+/* File-scope types --------------------------------------------------------------------*/
+
+
+/* External scope variables ------------------------------------------------------------*/
+
+
+int32_t usberr = 0;
+
+
+/* File-scope variables ----------------------------------------------------------------*/
+
+
+/** Pointer to a copy of the last error message string read out of libusb (or NULL).
+ */
+static char *usb_err_str = NULL;
+
+
+/* File-scope function declarations ----------------------------------------------------*/
+
+
+/** Connect to a device, read information about it and then disconnect again.
+ *
+ * @param dev USB device structure pointer.
+ *
+ * @return Return code, zero for no error.
+ */
+static dlo_retcode_t check_device(struct usb_device *dev);
+
+
+/** Attempt to read the EDID structure from the monitor attached to the specified device.
+ *
+ * @param dev Device structure pointer.
+ * @param uhand USB device handle.
+ *
+ * @return Return code, zero for no error.
+ */
+static dlo_retcode_t read_edid(dlo_device_t * const dev, usb_dev_handle *uhand);
+
+
+/** Make a note of any error returned by libusb.
+ *
+ * @return Return code to indicate a USB-related error.
+ *
+ * Often, by the time we have returned from a function, the error code stored in libusb
+ * has been lost because our tidy-up code will call more libusb functions after an error
+ * is spotted. As such, this function is called automatically by the @c UERR() and
+ * @c UERR_GOTO() macros in order to make a note of the error number and message from
+ * libusb at the moment the error is caught. This information is stored locally for
+ * retrieval by @c dlo_usb_strerror().
+ */
+static dlo_retcode_t usb_error_grab(void);
+
+
+/* Public function definitions ---------------------------------------------------------*/
+
+
+char *dlo_usb_strerror(void)
+{
+ //DPRINTF("usb: error lookup %d\n", usberr);
+ return usb_err_str;
+}
+
+
+dlo_retcode_t dlo_usb_init(const dlo_init_t flags)
+{
+ /* Initialise libusb */
+ //DPRINTF("usb: init\n");
+ usb_init();
+
+ /* Add nodes onto the device list for any DisplayLink devices we find */
+ //DPRINTF("usb: init: enum\n");
+ ERR(dlo_usb_enumerate(true));
+
+ return dlo_ok;
+}
+
+
+dlo_retcode_t dlo_usb_final(const dlo_final_t flags)
+{
+ if (usb_err_str)
+ dlo_free(usb_err_str);
+
+ return dlo_ok;
+}
+
+dlo_retcode_t dlo_usb_enumerate(const bool init)
+{
+ struct usb_bus *bus;
+ struct usb_device *dev = NULL;
+ int32_t db = usb_find_busses();
+ int32_t dd = usb_find_devices();
+ DPRINTF("usb: dlo_usb_enumerate\n");
+
+ /* We should do this even if it looks like there are no changes on the bus because
+ * an open() call might call the above functions just to check it's safe to use the
+ * USB device structure pointer. Yuck!
+ *
+ * If this isn't the first enumeration and there are no changes on the bus, don't touch the list
+ *
+ * if (!init && !db && !dd)
+ * return dlo_ok;
+ */
+ IGNORE(db);
+ IGNORE(dd);
+
+ /* Look for all DisplayLink devices on the USB busses */
+ for (bus = usb_get_busses(); bus; bus = bus->next)
+ for (dev = bus->devices; dev; dev = dev->next)
+ ERR(check_device(dev)); /* Check to see if it's a DisplayLink device. If it is, add to or update the dev_list */
+
+ return dlo_ok;
+}
+
+
+static dlo_retcode_t check_device(struct usb_device *udev)
+{
+ static char string[255];
+ usb_dev_handle *uhand = usb_open(udev);
+ dlo_retcode_t err = dlo_ok;
+ dlo_device_t *dev = NULL;
+ bool not_root = false;
+ uint8_t buf[4];
+ dlo_devtype_t type;
+
+ //DPRINTF("usb: check: check dev &%X\n", (int)dev);
+
+ if (!uhand) {
+ // this may not be our device. We just can't open it
+ return dlo_ok;
+ }
+
+ //DPRINTF("usb: check: uhand &%X vendorID &%X\n", (int)uhand, udev->descriptor.idVendor);
+
+ /* Reject devices that don't have the DisplayLink VendorID */
+ if (udev->descriptor.idVendor != VENDORID_DISPLAYLINK)
+ {
+ UERR(usb_close(uhand));
+ return dlo_ok;
+ }
+ //DPRINTF("usb: check: get type\n");
+
+ /* Ask the device for some status information */
+ not_root = true; /* Special case error handling here */
+ UERR_GOTO(usb_control_msg(/* handle */ uhand,
+ /* requestType */ USB_ENDPOINT_IN | USB_TYPE_VENDOR,
+ /* request */ NR_USB_REQUEST_STATUS_DW,
+ /* value */ 0,
+ /* index */ 0,
+ /* bytes */ (char *)buf,
+ /* size */ sizeof(buf),
+ /* timeout */ ID_TIMEOUT));
+ not_root = false; /* Back to normal error handling */
+ //DPRINTF("usb: check: type buf[3] = &%X\n", buf[3]);
+
+ /* Determine what type of device we are connected to */
+ switch ((buf[3] >> 4) & 0xF)
+ {
+ case dlo_dev_base:
+ type = dlo_dev_base;
+ break;
+ case dlo_dev_alex:
+ type = dlo_dev_alex;
+ break;
+ default:
+ if (buf[3] == dlo_dev_ollie)
+ type = dlo_dev_ollie;
+ else
+ type = dlo_dev_unknown;
+ }
+
+ /* Read the device serial number as a string */
+ UERR_GOTO(usb_get_string_simple(uhand, udev->descriptor.iSerialNumber, string, sizeof(string)));
+ //DPRINTF("usb: check: type &%X serial '%s'\n", (int)type, string);
+
+ /* See if this device is already in our device list */
+ dev = dlo_device_lookup(string);
+ if (dev)
+ {
+ /* Use this opportunity to update the USB device structure pointer, just in
+ * case it has moved.
+ */
+ dev->cnct->udev = udev;
+ //DPRINTF("usb: check: already in list\n");
+ }
+ else
+ {
+ /* Add a new device to the device list */
+ //DPRINTF("usb: check: create new device\n");
+ dev = dlo_new_device(type, string);
+ NERR_GOTO(dev);
+
+ /* It's not. Create and initialise a new list node for the device */
+ dev->cnct = (dlo_usb_dev_t *)dlo_malloc(sizeof(dlo_usb_dev_t));
+ NERR_GOTO(dev->cnct);
+ dev->cnct->udev = udev;
+ dev->cnct->uhand = NULL;
+ }
+ //DPRINTF("usb: check: dlpp node &%X\n", (int)dev);
+
+ /* Close our temporary handle for the device. If this errors, we'll have a duff entry in
+ * the device list but at least the list integrity will be OK.
+ */
+ UERR_GOTO(usb_close(uhand));
+
+ return dlo_ok;
+
+error:
+ /* Free our dev->cnct USB information structure */
+ if (dev)
+ {
+ if (dev->cnct)
+ dlo_free(dev->cnct);
+ dev->cnct = NULL;
+ }
+
+ /* Close our temporary handle for the device */
+ (void) usb_close(uhand);
+
+ /* If the executable wasn't run as root, this is where it normally falls over.
+ * So we'll special case that particular error to help indicate this problem.
+ */
+ if (not_root)
+ return dlo_err_not_root;
+
+ return err;
+}
+
+
+dlo_retcode_t dlo_usb_open(dlo_device_t * const dev)
+{
+ dlo_retcode_t err;
+ usb_dev_handle *uhand;
+ char* driver_name;
+ int usb_configuration;
+ int i;
+ int32_t db = usb_find_busses();
+ int32_t dd = usb_find_devices();
+
+ /* Do we trust the USB device pointer? Not if the structures may have changed under us... */
+ if (db || dd)
+ return dlo_err_reenum;
+
+ /* Open the device */
+ uhand = usb_open(dev->cnct->udev);
+ DPRINTF("usb: open: uhand &%X\n", (int)uhand);
+
+ if (!uhand)
+ return dlo_err_open;
+
+ /* Store the USB device handle in our dev->cnct word */
+ dev->cnct->uhand = uhand;
+
+ /* Establish the connection with the device */
+ //DPRINTF("usb: open: setting config...\n");
+
+ /*
+ * Because some displaylink devices may report
+ * a class code (like HID or MSC) that gets
+ * matched by a kernel driver, we must detach
+ * those drivers before libusb can successfully
+ * set configuration or talk to those devices.
+ * For now, we kick everyone off our device,
+ * but that includes cases we're intentionally
+ * a composite device with HID interfaces that
+ * control something (e.g. a button on a dock).
+ * And the code below is blindly unloading
+ * the kernel HID drivers for those. May want
+ * to get more sophisticated in the future.
+ */
+ driver_name = dlo_malloc(128);
+ for (i=0; i < dev->cnct->udev->config->bNumInterfaces; i++)
+ {
+ memset(driver_name, 0, 128);
+ if (usb_get_driver_np(uhand, i, driver_name, 128) == 0)
+ {
+ DPRINTF("usb: driver (%s) already attached to device\n", driver_name);
+
+ // Reports are that this call can return error even if successful
+ usb_detach_kernel_driver_np(uhand,i);
+ }
+ }
+
+ UERR(usb_set_configuration(uhand, 1));
+
+ //DPRINTF("usb: open: claiming iface...\n");
+ UERR(usb_claim_interface(uhand, 0));
+
+ /* Mark the device as claimed */
+ dev->claimed = true;
+
+ /* Allocate a buffer to hold commands before they are sent to the device */
+ if (!dev->buffer)
+ {
+ //DPRINTF("usb: open: alloc buffer...\n");
+ dev->buffer = dlo_malloc(BUF_SIZE);
+ NERR(dev->buffer);
+ dev->bufptr = dev->buffer;
+ dev->bufend = dev->buffer + BUF_SIZE;
+ }
+ //DPRINTF("usb: open: buffer &%X, &%X, &%X\n", (int)dev->buffer, (int)dev->bufptr, (int)dev->bufend);
+
+ /* Use the default timeout if none was specified */
+ if (!dev->timeout)
+ dev->timeout = WRITE_TIMEOUT;
+ //DPRINTF("usb: open: timeout %u ms\n", dev->timeout);
+
+ /* Initialise the supported modes array for this device to include all our pre-defined modes */
+ use_default_modes(dev);
+
+ /* Attempt to read the EDID information, to refine the supported modes array contents */
+ err = read_edid(dev, uhand);
+#ifdef DEBUG
+ if (err != dlo_ok)
+ DPRINTF("usb: open: edid error %u '%s'\n", (int)err, dlo_strerror(err));
+#endif
+
+ return dlo_ok;
+}
+
+
+dlo_retcode_t dlo_usb_close(dlo_device_t * const dev)
+{
+ if (dev->claimed)
+ {
+ if (dev->buffer)
+ {
+ dlo_free(dev->buffer);
+ dev->buffer = NULL;
+ dev->bufptr = NULL;
+ dev->bufend = NULL;
+ }
+ dev->claimed = false;
+ UERR(usb_release_interface(dev->cnct->uhand, 0));
+ UERR(usb_close(dev->cnct->uhand));
+ }
+ return dlo_ok;
+}
+
+
+dlo_retcode_t dlo_usb_chan_sel(const dlo_device_t * const dev, const char * const buf, const size_t size)
+{
+ if (size)
+ UERR(usb_control_msg(/* handle */ dev->cnct->uhand,
+ /* requestType */ USB_TYPE_VENDOR,
+ /* request */ NR_USB_REQUEST_CHANNEL,
+ /* value */ 0,
+ /* index */ 0,
+ /* bytes */ (char *)buf,
+ /* size */ size,
+ /* timeout */ CHANSEL_TIMEOUT));
+ return dlo_ok;
+}
+
+
+dlo_retcode_t dlo_usb_std_chan(const dlo_device_t * const dev)
+{
+ dlo_retcode_t err;
+
+ ASSERT(strlen(STD_CHANNEL) == 16);
+ err = dlo_usb_chan_sel(dev, STD_CHANNEL, DSIZEOF(STD_CHANNEL));
+
+ return err;
+}
+
+
+dlo_retcode_t dlo_usb_write(dlo_device_t * const dev)
+{
+ dlo_retcode_t err = dlo_usb_write_buf(dev, dev->buffer, dev->bufptr - dev->buffer);
+
+ dev->bufptr = dev->buffer;
+
+ return err;
+}
+
+
+dlo_retcode_t dlo_usb_write_buf(dlo_device_t * const dev, char * buf, size_t size)
+{
+#ifdef DEBUG_DUMP
+ static char outfile[64];
+ static uint32_t outnum = 0;
+ FILE *out = NULL;
+#endif
+
+ if (!dev->claimed)
+ return dlo_err_unclaimed;
+
+ if (!size)
+ return dlo_ok;
+
+#ifdef WRITE_BUF_BODGE
+ /* If the buffer to write is fewer than 513 bytes in size, copy into 513 byte buffer and pad with zeros */
+ if (size < WRITE_BUF_BODGE)
+ {
+ dlo_retcode_t err;
+ uint32_t rem = WRITE_BUF_BODGE - size;
+ char *cpy = dlo_malloc(WRITE_BUF_BODGE);
+
+ NERR(cpy);
+ dlo_memcpy(cpy, buf, size);
+ dlo_memset(cpy + size, 0, rem);
+ err = dlo_usb_write_buf(dev, cpy, size + rem);
+ dlo_free(cpy);
+
+ return err;
+ }
+#endif
+
+ while (size)
+ {
+ size_t num = size > BUF_SIZE ? BUF_SIZE : size;
+
+#ifdef DEBUG_DUMP
+ (void) snprintf(outfile, sizeof(outfile), "dump/%02X/bulk%03X.dat", outnum & 0xFF, outnum >> 8);
+ outnum++;
+ out = fopen(outfile, "wb");
+ if (out)
+ {
+ (void) fwrite(buf, num, 1, out);
+ (void) fclose(out);
+ out = NULL;
+ }
+#endif
+
+ UERR(usb_bulk_write(/* handle */ dev->cnct->uhand,
+ /* endpoint */ 1,
+ /* bytes */ buf,
+ /* size */ num,
+ /* timeout */ dev->timeout));
+ buf += num;
+ size -= num;
+ }
+ return dlo_ok;
+}
+
+
+/* File-scope function definitions -----------------------------------------------------*/
+
+
+static dlo_retcode_t usb_error_grab(void)
+{
+ char *str = usb_strerror();
+
+ /* If we have a previous USB error message stored, free it */
+ if (usb_err_str)
+ dlo_free(usb_err_str);
+
+ if (str)
+ {
+ /* Allocate memory for the new error message and store that */
+ usb_err_str = dlo_malloc(1 + strlen(str));
+ if (usb_err_str)
+ strcpy(usb_err_str, str);
+ }
+
+ /* Always return the generic USB error code */
+ return dlo_err_usb;
+}
+
+
+
+static dlo_retcode_t read_edid(dlo_device_t * const dev, usb_dev_handle *uhand)
+{
+ dlo_retcode_t err;
+ uint32_t i;
+ uint8_t buf[2];
+ uint8_t *edid;
+
+ /* Allocate a buffer to hold the EDID structure */
+ edid = dlo_malloc(EDID_STRUCT_SZ);
+ NERR(edid);
+
+ /* Attempt to read the EDID structure from the device */
+ for (i = 0; i < EDID_STRUCT_SZ; i++)
+ {
+ UERR_GOTO(usb_control_msg(/* handle */ uhand,
+ /* requestType */ USB_ENDPOINT_IN | USB_TYPE_VENDOR,
+ /* request */ NR_USB_REQUEST_I2C_SUB_IO,
+ /* value */ i << 8,
+ /* index */ 0xA1,
+ /* bytes */ (char *)buf,
+ /* size */ sizeof(buf),
+ /* timeout */ dev->timeout));
+ if (buf[0])
+ ERR_GOTO(dlo_err_iic_op);
+ //DPRINTF("usb: edid[%u]=&%02X\n", i, buf[1]);
+ edid[i] = buf[1];
+ }
+
+ /* Supply the prospective EDID structure to the parser */
+ ERR_GOTO(dlo_mode_parse_edid(dev, edid, EDID_STRUCT_SZ));
+
+error:
+ dlo_free(edid);
+
+ return err;
+}
+
+
+/* End of file -------------------------------------------------------------------------*/
diff --git a/src/dlo_usb.h b/src/dlo_usb.h
index 744375d..84f1532 100644
--- a/src/dlo_usb.h
+++ b/src/dlo_usb.h
@@ -1,134 +1,134 @@
-/** @file dlo_usb.h
- *
- * @brief Header file for the USB-specific connectivity functions.
- *
- * This file defines the API between the libdlo.c and the USB driver implementation. This
- * example implementation uses libusb but it should be simple to replace dlo_usb.c with
- * some alternative implementation.
- *
- * DisplayLink Open Source Software (libdlo)
- * Copyright (C) 2009, DisplayLink
- * www.displaylink.com
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Library General Public License as published by the Free
- * Software Foundation; LGPL version 2, dated June 1991.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef DLO_USB_H
-#define DLO_USB_H /**< Avoid multiple inclusion. */
-
-#include "usb.h"
-#include "dlo_structs.h"
-
-
-/** Return the meaning of the last USB-related error as a human-readable string.
- *
- * @return Pointer to error message string (zero-terminated).
- */
-extern char * dlo_usb_strerror(void);
-
-
-/** Initialise the USB communications routines.
- *
- * @param flags Initialisation flags word (unused flags ignored).
- *
- * @return Return code, zero for no error.
- */
-extern dlo_retcode_t dlo_usb_init(const dlo_init_t flags);
-
-
-/** Finalisation call for USB communications routines.
- *
- * @param flags Finalisation flags word (unused flags ignored).
- *
- * @return Return code, zero for no error.
- */
-extern dlo_retcode_t dlo_usb_final(const dlo_final_t flags);
-
-
-/** Update or create nodes on the device list for any DisplayLink devices found.
- *
- * @param init Is this the first call to the enumeration function?
- *
- * @return Return code, zero for no error.
- *
- * This call will look for any DisplayLink devices which use the particular connection
- * implementation and either add nodes onto the device list or update nodes if they are
- * already present.
- *
- * Once enumeration is complete for all connection types, any nodes on the list which
- * haven't just been added or updated are removed (as the correponding device can no
- * longer be found).
- */
-extern dlo_retcode_t dlo_usb_enumerate(const bool init);
-
-
-/** Open a connection to the specified device.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- *
- * @return Return code, zero for no error.
- */
-extern dlo_retcode_t dlo_usb_open(dlo_device_t * const dev);
-
-
-/** Close the connection with a specified device.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- *
- * @return Return code, zero for no error.
- */
-extern dlo_retcode_t dlo_usb_close(dlo_device_t * const dev);
-
-
-/** Select the input channel in the specified device.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param buf Pointer to the buffer containing the channel information.
- * @param size Size of the buffer (bytes).
- *
- * @return Return code, zero for no error.
- */
-extern dlo_retcode_t dlo_usb_chan_sel(const dlo_device_t * const dev, const char * const buf, const size_t size);
-
-
-/** Switch to the default input channel in the specified device.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- *
- * @return Return code, zero for no error.
- */
-extern dlo_retcode_t dlo_usb_std_chan(const dlo_device_t * const dev);
-
-
-/** Flush the command buffer contents to the specified device.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- *
- * @return Return code, zero for no error.
- */
-extern dlo_retcode_t dlo_usb_write(dlo_device_t * const dev);
-
-
-/** Write the contents of a specified command buffer to the specified device.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param buf Pointer to the buffer containing commands to write.
- * @param size Size of the buffer (bytes).
- *
- * @return Return code, zero for no error.
- */
-extern dlo_retcode_t dlo_usb_write_buf(dlo_device_t * const dev, char * buf, size_t size);
-
-
-#endif
+/** @file dlo_usb.h
+ *
+ * @brief Header file for the USB-specific connectivity functions.
+ *
+ * This file defines the API between the libdlo.c and the USB driver implementation. This
+ * example implementation uses libusb but it should be simple to replace dlo_usb.c with
+ * some alternative implementation.
+ *
+ * DisplayLink Open Source Software (libdlo)
+ * Copyright (C) 2009, DisplayLink
+ * www.displaylink.com
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by the Free
+ * Software Foundation; LGPL version 2, dated June 1991.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef DLO_USB_H
+#define DLO_USB_H /**< Avoid multiple inclusion. */
+
+#include "usb.h"
+#include "dlo_structs.h"
+
+
+/** Return the meaning of the last USB-related error as a human-readable string.
+ *
+ * @return Pointer to error message string (zero-terminated).
+ */
+extern char * dlo_usb_strerror(void);
+
+
+/** Initialise the USB communications routines.
+ *
+ * @param flags Initialisation flags word (unused flags ignored).
+ *
+ * @return Return code, zero for no error.
+ */
+extern dlo_retcode_t dlo_usb_init(const dlo_init_t flags);
+
+
+/** Finalisation call for USB communications routines.
+ *
+ * @param flags Finalisation flags word (unused flags ignored).
+ *
+ * @return Return code, zero for no error.
+ */
+extern dlo_retcode_t dlo_usb_final(const dlo_final_t flags);
+
+
+/** Update or create nodes on the device list for any DisplayLink devices found.
+ *
+ * @param init Is this the first call to the enumeration function?
+ *
+ * @return Return code, zero for no error.
+ *
+ * This call will look for any DisplayLink devices which use the particular connection
+ * implementation and either add nodes onto the device list or update nodes if they are
+ * already present.
+ *
+ * Once enumeration is complete for all connection types, any nodes on the list which
+ * haven't just been added or updated are removed (as the correponding device can no
+ * longer be found).
+ */
+extern dlo_retcode_t dlo_usb_enumerate(const bool init);
+
+
+/** Open a connection to the specified device.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ *
+ * @return Return code, zero for no error.
+ */
+extern dlo_retcode_t dlo_usb_open(dlo_device_t * const dev);
+
+
+/** Close the connection with a specified device.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ *
+ * @return Return code, zero for no error.
+ */
+extern dlo_retcode_t dlo_usb_close(dlo_device_t * const dev);
+
+
+/** Select the input channel in the specified device.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param buf Pointer to the buffer containing the channel information.
+ * @param size Size of the buffer (bytes).
+ *
+ * @return Return code, zero for no error.
+ */
+extern dlo_retcode_t dlo_usb_chan_sel(const dlo_device_t * const dev, const char * const buf, const size_t size);
+
+
+/** Switch to the default input channel in the specified device.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ *
+ * @return Return code, zero for no error.
+ */
+extern dlo_retcode_t dlo_usb_std_chan(const dlo_device_t * const dev);
+
+
+/** Flush the command buffer contents to the specified device.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ *
+ * @return Return code, zero for no error.
+ */
+extern dlo_retcode_t dlo_usb_write(dlo_device_t * const dev);
+
+
+/** Write the contents of a specified command buffer to the specified device.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param buf Pointer to the buffer containing commands to write.
+ * @param size Size of the buffer (bytes).
+ *
+ * @return Return code, zero for no error.
+ */
+extern dlo_retcode_t dlo_usb_write_buf(dlo_device_t * const dev, char * buf, size_t size);
+
+
+#endif
diff --git a/src/exported_symbols b/src/exported_symbols
index d790885..6fe1217 100644
--- a/src/exported_symbols
+++ b/src/exported_symbols
@@ -1,14 +1,14 @@
-dlo_strerror
-dlo_init
-dlo_final
-dlo_lookup_device
-dlo_enumerate_devices
-dlo_claim_device
-dlo_claim_first_device
-dlo_release_device
-dlo_device_info
-dlo_set_mode
-dlo_get_mode
-dlo_fill_rect
-dlo_copy_rect
-dlo_copy_host_bmp
+dlo_strerror
+dlo_init
+dlo_final
+dlo_lookup_device
+dlo_enumerate_devices
+dlo_claim_device
+dlo_claim_first_device
+dlo_release_device
+dlo_device_info
+dlo_set_mode
+dlo_get_mode
+dlo_fill_rect
+dlo_copy_rect
+dlo_copy_host_bmp
diff --git a/src/libdlo.c b/src/libdlo.c
index eef7719..19f7b1e 100644
--- a/src/libdlo.c
+++ b/src/libdlo.c
@@ -1,469 +1,469 @@
-/** @file libdlo.c
- *
- * @brief This file implements the high-level API for the DisplayLink libdlo library.
- *
- * DisplayLink Open Source Software (libdlo)
- * Copyright (C) 2009, DisplayLink
- * www.displaylink.com
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Library General Public License as published by the Free
- * Software Foundation; LGPL version 2, dated June 1991.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <string.h>
-#include "dlo_defs.h"
-#include "dlo_grfx.h"
-#include "dlo_mode.h"
-#include "dlo_usb.h"
-
-
-/* File-scope defines ------------------------------------------------------------------*/
-
-
-/** Structure to hold information about how a rectangle may have been clipped
- */
-typedef struct clip_s
-{
- uint32_t left; /**< Number of pixels clipped from left edge. */
- uint32_t right; /**< Number of pixels clipped from right edge. */
- uint32_t below; /**< Number of pixels clipped from bottom edge. */
- uint32_t above; /**< Number of pixels clipped from top edge. */
-} clip_t; /**< A struct @a clip_s. */
-
-
-/** Return value from function to check source and destination viewports in the rectangle copy function.
- */
-typedef enum
-{
- vstat_good_view = 0, /**< Viewports are both good, not overlapping. */
- vstat_good_overlap, /**< Viewports are both the same. */
- vstat_bad_view, /**< Something is wrong with one or other viewport. */
- vstat_bad_overlap /**< Viewports overlap but are not identical. */
-} vstat_t;
-
-
-/* File-scope inline functions ---------------------------------------------------------*/
-
-
-/* File-scope types --------------------------------------------------------------------*/
-
-
-/* External-scope variables ------------------------------------------------------------*/
-
-
-char err_file[1024] = { '\0' };
-
-
-uint32_t err_line = 0;
-
-
-/* File-scope variables ----------------------------------------------------------------*/
-
-
-/** Pointer to the head node in the device list.
- */
-static dlo_device_t *dev_list = NULL;
-
-
-/** Flag is toggled at each enumeration to spot removed devices.
- */
-static bool check_state = false;
-
-
-/* File-scope function declarations ----------------------------------------------------*/
-
-
-/** Check that the specified device (pointer) corresponds to a current list node.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- *
- * @return true if the device is in the device list, else false.
- *
- * This is a less-than-perfect test because although the device structure may have
- * been removed from the list, a new device structure may have been allocated into
- * the same address at some later point.
- *
- * Ideally, this library should hold structures which themselves point to a device
- * structure and include a flag saying whether the pointer is still valid (which is
- * cleared when the device structure is freed). The UID passed into dlo calls would
- * be a pointer to this (small) structure. The (small) structures are leaked so that
- * it is possible to spot stale pointers from the caller.
- */
-static bool valid_device(const dlo_device_t * const dev);
-
-
-/** Remove the specified device from the device list.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- *
- * @return Return code, zero for no error.
- *
- * This call will delink the specified device structure from the device list
- * and free any resources associated with the device (including "releasing"
- * the device).
- *
- * NOTE: the @a dev_list variable is updated as a side-effect of this function.
- */
-static dlo_retcode_t remove_device(dlo_device_t *dev);
-
-
-/** Initialise an area structure based upon a viewport and rectangle within it.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param view Pointer to the viewport structure (may be NULL).
- * @param rec Pointer to a rectangle structure (may be NULL).
- * @param area Pointer to area structure to initialise from @a view and @a rec.
- * @param clip Pointer to list of offsets that the source rectangle was clipped by.
- *
- * @return true if the area still has extent, false if it was clipped to nothing.
- *
- * Given a viewport and rectangle within that viewport, calculate the corresponding area
- * structure by clipping the rectangle as required so that no part of it lies outside of
- * the viewport.
- *
- * Where the viewport is NULL on entry, the viewport for the current display screen is
- * used. Where the rectangle is NULL on entry, the whole of the viewport is used.
- *
- * This call also updates the contents of the @a clip structure as a side-effect to
- * indicate how many pixels were clipped from each edge of the rectangle in order to
- * arrive at the output area. This is useful if another rectangle needs to be clipped
- * to match the output rectangle.
- */
-static bool sanitise_view_rect(const dlo_device_t * const dev, const dlo_view_t * const view, const dlo_rect_t * const rec, dlo_area_t * const area, clip_t * const clip);
-
-
-/** For the rectangle copy, check that overlapping rectangles have exactly the same viewport.
- *
- * @param dev Pointer to @a dlo_device_t structure.
- * @param src_view Pointer to source viewport structure.
- * @param dest_view Pointer to destination viewport structure.
- *
- * @return true if they don't overlap, or do overlap and are identical. Else returns false.
- */
-static vstat_t check_overlaps(const dlo_device_t * const dev, const dlo_view_t * const src_view, const dlo_view_t * const dest_view);
-
-
-/* Public function definitions ---------------------------------------------------------*/
-
-
-#if 0
-static uint32_t total_alloc = 0;
-
-void *my_malloc(size_t size)
-{
- uint32_t *blk = malloc(size + sizeof(uint32_t));
-
- if (blk)
- {
- *blk = size;
- total_alloc += size;
- blk++;
- }
- DPRINTF("alloc: malloc &%X is %u bytes (total %u)\n", (uint32_t)blk, size, total_alloc);
-
- return (void *)blk;
-}
-
-
-void *my_realloc(void *blk, size_t size)
-{
- uint32_t *myblk = (uint32_t *)blk;
-
- if (myblk)
- {
- myblk--;
- if (size)
- {
- myblk = realloc(myblk, size + sizeof(uint32_t));
- if (myblk)
- {
- total_alloc -= *myblk;
- total_alloc += size;
- *myblk = size;
- myblk++;
- }
- }
- else
- {
- /* Free a block */
- total_alloc -= *myblk;
- myblk = realloc(myblk, 0);
- }
- }
- else
- {
- /* Claim a new block */
- myblk = realloc(NULL, size + sizeof(uint32_t));
- if (myblk)
- {
- *myblk = size;
- total_alloc += size;
- myblk++;
- }
- }
- DPRINTF("alloc: realloc &%X to %u bytes (total %u)\n", (uint32_t)myblk, size, total_alloc);
-
- return (void *)myblk;
-}
-
-
-void my_free(void *blk)
-{
- uint32_t *myblk = (uint32_t *)blk;
-
- myblk--;
- total_alloc -= *myblk;
- free(myblk);
-
- DPRINTF("alloc: free &%X (total %u)\n", (uint32_t)blk, total_alloc);
-}
-
-
-uint32_t my_used(void)
-{
- return total_alloc;
-}
-#endif
-
-
-const char *dlo_strerror(const dlo_retcode_t err)
-{
- static char str[1024];
- char *msg;
-
- switch (err)
- {
- /* Success... */
- case dlo_ok: return "Successful";
- /* Errors... */
- case dlo_err_memory: break;
- case dlo_err_bad_area: return "An invalid area was specified (e.g. of zero width or height)";
- case dlo_err_bad_col: return "Unsupported colour depth";
- case dlo_err_bad_device: return "Unknown device, possibly disconnected or powered down";
- case dlo_err_bad_fbuf: return "Null pointer passed as local bitmap data";
- case dlo_err_bad_fmt: return "Unsupported bitmap pixel format";
- case dlo_err_bad_mode: return "Call to dlo_set_mode() failed due to unsupported mode parameters";
- case dlo_err_bad_view: return "Invalid viewport specified (is screen mode set up?)";
- case dlo_err_big_scrape: return "Bitmap is too wide for copy buffer";
- case dlo_err_buf_full: return "Command buffer is full";
- case dlo_err_claimed: return "Device is already claimed";
- case dlo_err_edid_fail: return "Attempt to access EDID information failed";
- case dlo_err_iic_op: return "IIC operation with device failed";
- case dlo_err_not_root: return "Executable should be run as root (e.g. using 'su root' or 'sudo')";
- case dlo_err_open: return "Attempt to open connection to device failed";
- case dlo_err_overlap: return "Source and destination viewports cannot overlap (unless the same)";
- case dlo_err_reenum: return "Reenumeration required before device can be claimed";
- case dlo_err_unclaimed: return "Device cannot be written to: unclaimed";
- case dlo_err_unsupported: return "Requested feature is not supported";
- case dlo_err_usb: return dlo_usb_strerror();
- /* Warnings... */
- case dlo_warn_dl160_mode: return "This screen mode may not display correctly on DL120 devices";
- default: return "Unknown error";
- }
-
- /* Memory allocation errors should have more information associated with them */
- msg = "A memory claim operation failed; out of memory";
- if (err_file[0])
- snprintf(&str[0], sizeof(str), "%s:%u: %s", &err_file[0], err_line, msg);
- else
- snprintf(&str[0], sizeof(str), "%s", msg);
- err_file[0] = '\0';
- err_line = 0;
- return str;
-}
-
-
-dlo_retcode_t dlo_init(const dlo_init_t flags)
-{
- /* Initialise the graphics primitives */
- DPRINTF("dlo: grfx_init\n");
- ERR(dlo_grfx_init(flags));
-
- /* Initialise the screen mode timings array */
- DPRINTF("dlo: mode_init\n");
- ERR(dlo_mode_init(flags));
-
- /* Initialise the USB comms code and function pointer table */
- DPRINTF("dlo: usb_init\n");
- ERR(dlo_usb_init(flags));
-
- return dlo_ok;
-}
-
-
-dlo_retcode_t dlo_final(const dlo_final_t flags)
-{
- /* Free all claimed structures */
- while (dev_list)
- {
- (void) remove_device(dev_list);
- }
-
- ERR(dlo_grfx_final(flags));
- ERR(dlo_mode_final(flags));
- ERR(dlo_usb_final(flags));
-
- return dlo_ok;
-}
-
-
-dlo_devlist_t *dlo_enumerate_devices(void)
-{
- dlo_devlist_t *out = NULL;
- dlo_device_t *dev;
- dlo_retcode_t err;
- uint32_t num;
-
- check_state = !check_state;
-
- /* Check USB for all DisplayLink devices that we can find. If there is an error returned,
- * then it is likely that the devlist could become out of step with reality. For that
- * reason, after any error, we throw away all unclaimed devices from the devlist to try to
- * minimise the chances.
- */
- //DPRINTF("dlo: enum: enumerating USB devices\n");
- ERR_GOTO(dlo_usb_enumerate(false));
-
- /* Remove all devices which weren't updated or added during this enumeration and
- * build the list of device information to return. Note: if a dlo_malloc() call
- * fails during this operation, we note it and continue otherwise the dev_list could
- * get out of step with reality.
- */
- dev = dev_list;
- out = NULL;
- num = 0;
- while (dev)
- {
- dlo_device_t *next = dev->next;
-
- if (dev->check == check_state)
- {
- dlo_devlist_t *tmp = (dlo_devlist_t *)dlo_malloc(sizeof(dlo_devlist_t));
-
- /* Add a node to the output list */
- if (tmp)
- {
- tmp->next = out;
- tmp->dev.uid = (dlo_dev_t)dev;
- tmp->dev.serial = dev->serial;
- tmp->dev.type = dev->type;
- tmp->dev.claimed = dev->claimed;
- out = tmp;
- num++;
- }
- else
- err = dlo_err_memory;
- }
- else
- {
- // DPRINTF("dlo: enum: removed device &%X (%s)\n", (int)dev, dev->serial);
- (void) remove_device(dev);
- }
- dev = next;
- }
-
- /* Return pointer to output list if operation was successful */
- if (!err)
- {
- // DPRINTF("dlo: enum: return list of %u entries\n", num);
- return out;
- }
-
-error:
- DPRINTF("dlo: enum: error &%X (usberr &%X)\n", err, usberr);
-
- /* Throw the output list away */
- while (out)
- {
- dlo_devlist_t *next = out->next;
-
- dlo_free(out);
- out = next;
- }
-
- /* Remove all unclaimed devices from our list */
- dev = dev_list;
- while (dev)
- {
- dlo_device_t *next = dev->next;
-
- if (!dev->claimed)
- (void) remove_device(dev);
- dev = next;
- }
- return NULL;
-}
-
-
-dlo_dev_t dlo_claim_device(const dlo_dev_t uid, const dlo_claim_t flags, const uint32_t timeout)
-{
- dlo_device_t *dev = (dlo_device_t *)uid;
- dlo_retcode_t err;
-
- if (!dev)
- ERR_GOTO(dlo_err_bad_device);
-
- /* Confirm that the device structure pointer still exists */
- if (!valid_device(dev))
- ERR_GOTO(dlo_err_bad_device);
-
- /* Return error if device has already been claimed */
- if (dev->claimed)
- ERR_GOTO(dlo_err_claimed);
-
- dev->timeout = timeout;
-
- /* Attempt to open a connection to the device */
- err = dlo_usb_open(dev);
- while (err == dlo_err_reenum)
- {
- DPRINTF("dlo_usb_open failed with dlo_err_reenum. Retry\n");
-
- /* If the USB bus devices have changed, do the enumeration again */
- dlo_devlist_t *out = dlo_enumerate_devices();
-
- /* Throw the output list away */
- while (out)
- {
- dlo_devlist_t *next = out->next;
-
- dlo_free(out);
- out = next;
- }
-
- /* Confirm that the device structure pointer still exists */
- if (!valid_device(dev))
- ERR_GOTO(dlo_err_bad_device);
-
- /* Now try opening the connection again */
- err = dlo_usb_open(dev);
- }
- /* Any other errors from opening the connection get returned to the caller */
- ERR_GOTO(err);
-
- /* Select the standard output channel */
- ERR_GOTO(dlo_usb_std_chan(dev));
-
- /* Attempt to change mode into the native resolution of the display (if we have one) */
- if (dev->native.view.width)
- ERR_GOTO(dlo_mode_change(dev, &dev->native, DLO_INVALID_MODE));
-
- return uid;
-
-error:
- DPRINTF("dlo: claim: error %u '%s'\n", (int)err, dlo_strerror(err));
-
- return (dlo_dev_t)0;
+/** @file libdlo.c
+ *
+ * @brief This file implements the high-level API for the DisplayLink libdlo library.
+ *
+ * DisplayLink Open Source Software (libdlo)
+ * Copyright (C) 2009, DisplayLink
+ * www.displaylink.com
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by the Free
+ * Software Foundation; LGPL version 2, dated June 1991.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include "dlo_defs.h"
+#include "dlo_grfx.h"
+#include "dlo_mode.h"
+#include "dlo_usb.h"
+
+
+/* File-scope defines ------------------------------------------------------------------*/
+
+
+/** Structure to hold information about how a rectangle may have been clipped
+ */
+typedef struct clip_s
+{
+ uint32_t left; /**< Number of pixels clipped from left edge. */
+ uint32_t right; /**< Number of pixels clipped from right edge. */
+ uint32_t below; /**< Number of pixels clipped from bottom edge. */
+ uint32_t above; /**< Number of pixels clipped from top edge. */
+} clip_t; /**< A struct @a clip_s. */
+
+
+/** Return value from function to check source and destination viewports in the rectangle copy function.
+ */
+typedef enum
+{
+ vstat_good_view = 0, /**< Viewports are both good, not overlapping. */
+ vstat_good_overlap, /**< Viewports are both the same. */
+ vstat_bad_view, /**< Something is wrong with one or other viewport. */
+ vstat_bad_overlap /**< Viewports overlap but are not identical. */
+} vstat_t;
+
+
+/* File-scope inline functions ---------------------------------------------------------*/
+
+
+/* File-scope types --------------------------------------------------------------------*/
+
+
+/* External-scope variables ------------------------------------------------------------*/
+
+
+char err_file[1024] = { '\0' };
+
+
+uint32_t err_line = 0;
+
+
+/* File-scope variables ----------------------------------------------------------------*/
+
+
+/** Pointer to the head node in the device list.
+ */
+static dlo_device_t *dev_list = NULL;
+
+
+/** Flag is toggled at each enumeration to spot removed devices.
+ */
+static bool check_state = false;
+
+
+/* File-scope function declarations ----------------------------------------------------*/
+
+
+/** Check that the specified device (pointer) corresponds to a current list node.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ *
+ * @return true if the device is in the device list, else false.
+ *
+ * This is a less-than-perfect test because although the device structure may have
+ * been removed from the list, a new device structure may have been allocated into
+ * the same address at some later point.
+ *
+ * Ideally, this library should hold structures which themselves point to a device
+ * structure and include a flag saying whether the pointer is still valid (which is
+ * cleared when the device structure is freed). The UID passed into dlo calls would
+ * be a pointer to this (small) structure. The (small) structures are leaked so that
+ * it is possible to spot stale pointers from the caller.
+ */
+static bool valid_device(const dlo_device_t * const dev);
+
+
+/** Remove the specified device from the device list.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ *
+ * @return Return code, zero for no error.
+ *
+ * This call will delink the specified device structure from the device list
+ * and free any resources associated with the device (including "releasing"
+ * the device).
+ *
+ * NOTE: the @a dev_list variable is updated as a side-effect of this function.
+ */
+static dlo_retcode_t remove_device(dlo_device_t *dev);
+
+
+/** Initialise an area structure based upon a viewport and rectangle within it.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param view Pointer to the viewport structure (may be NULL).
+ * @param rec Pointer to a rectangle structure (may be NULL).
+ * @param area Pointer to area structure to initialise from @a view and @a rec.
+ * @param clip Pointer to list of offsets that the source rectangle was clipped by.
+ *
+ * @return true if the area still has extent, false if it was clipped to nothing.
+ *
+ * Given a viewport and rectangle within that viewport, calculate the corresponding area
+ * structure by clipping the rectangle as required so that no part of it lies outside of
+ * the viewport.
+ *
+ * Where the viewport is NULL on entry, the viewport for the current display screen is
+ * used. Where the rectangle is NULL on entry, the whole of the viewport is used.
+ *
+ * This call also updates the contents of the @a clip structure as a side-effect to
+ * indicate how many pixels were clipped from each edge of the rectangle in order to
+ * arrive at the output area. This is useful if another rectangle needs to be clipped
+ * to match the output rectangle.
+ */
+static bool sanitise_view_rect(const dlo_device_t * const dev, const dlo_view_t * const view, const dlo_rect_t * const rec, dlo_area_t * const area, clip_t * const clip);
+
+
+/** For the rectangle copy, check that overlapping rectangles have exactly the same viewport.
+ *
+ * @param dev Pointer to @a dlo_device_t structure.
+ * @param src_view Pointer to source viewport structure.
+ * @param dest_view Pointer to destination viewport structure.
+ *
+ * @return true if they don't overlap, or do overlap and are identical. Else returns false.
+ */
+static vstat_t check_overlaps(const dlo_device_t * const dev, const dlo_view_t * const src_view, const dlo_view_t * const dest_view);
+
+
+/* Public function definitions ---------------------------------------------------------*/
+
+
+#if 0
+static uint32_t total_alloc = 0;
+
+void *my_malloc(size_t size)
+{
+ uint32_t *blk = malloc(size + sizeof(uint32_t));
+
+ if (blk)
+ {
+ *blk = size;
+ total_alloc += size;
+ blk++;
+ }
+ DPRINTF("alloc: malloc &%X is %u bytes (total %u)\n", (uint32_t)blk, size, total_alloc);
+
+ return (void *)blk;
+}
+
+
+void *my_realloc(void *blk, size_t size)
+{
+ uint32_t *myblk = (uint32_t *)blk;
+
+ if (myblk)
+ {
+ myblk--;
+ if (size)
+ {
+ myblk = realloc(myblk, size + sizeof(uint32_t));
+ if (myblk)
+ {
+ total_alloc -= *myblk;
+ total_alloc += size;
+ *myblk = size;
+ myblk++;
+ }
+ }
+ else
+ {
+ /* Free a block */
+ total_alloc -= *myblk;
+ myblk = realloc(myblk, 0);
+ }
+ }
+ else
+ {
+ /* Claim a new block */
+ myblk = realloc(NULL, size + sizeof(uint32_t));
+ if (myblk)
+ {
+ *myblk = size;
+ total_alloc += size;
+ myblk++;
+ }
+ }
+ DPRINTF("alloc: realloc &%X to %u bytes (total %u)\n", (uint32_t)myblk, size, total_alloc);
+
+ return (void *)myblk;
+}
+
+
+void my_free(void *blk)
+{
+ uint32_t *myblk = (uint32_t *)blk;
+
+ myblk--;
+ total_alloc -= *myblk;
+ free(myblk);
+
+ DPRINTF("alloc: free &%X (total %u)\n", (uint32_t)blk, total_alloc);
+}
+
+
+uint32_t my_used(void)
+{
+ return total_alloc;
+}
+#endif
+
+
+const char *dlo_strerror(const dlo_retcode_t err)
+{
+ static char str[1024];
+ char *msg;
+
+ switch (err)
+ {
+ /* Success... */
+ case dlo_ok: return "Successful";
+ /* Errors... */
+ case dlo_err_memory: break;
+ case dlo_err_bad_area: return "An invalid area was specified (e.g. of zero width or height)";
+ case dlo_err_bad_col: return "Unsupported colour depth";
+ case dlo_err_bad_device: return "Unknown device, possibly disconnected or powered down";
+ case dlo_err_bad_fbuf: return "Null pointer passed as local bitmap data";
+ case dlo_err_bad_fmt: return "Unsupported bitmap pixel format";
+ case dlo_err_bad_mode: return "Call to dlo_set_mode() failed due to unsupported mode parameters";
+ case dlo_err_bad_view: return "Invalid viewport specified (is screen mode set up?)";
+ case dlo_err_big_scrape: return "Bitmap is too wide for copy buffer";
+ case dlo_err_buf_full: return "Command buffer is full";
+ case dlo_err_claimed: return "Device is already claimed";
+ case dlo_err_edid_fail: return "Attempt to access EDID information failed";
+ case dlo_err_iic_op: return "IIC operation with device failed";
+ case dlo_err_not_root: return "Executable should be run as root (e.g. using 'su root' or 'sudo')";
+ case dlo_err_open: return "Attempt to open connection to device failed";
+ case dlo_err_overlap: return "Source and destination viewports cannot overlap (unless the same)";
+ case dlo_err_reenum: return "Reenumeration required before device can be claimed";
+ case dlo_err_unclaimed: return "Device cannot be written to: unclaimed";
+ case dlo_err_unsupported: return "Requested feature is not supported";
+ case dlo_err_usb: return dlo_usb_strerror();
+ /* Warnings... */
+ case dlo_warn_dl160_mode: return "This screen mode may not display correctly on DL120 devices";
+ default: return "Unknown error";
+ }
+
+ /* Memory allocation errors should have more information associated with them */
+ msg = "A memory claim operation failed; out of memory";
+ if (err_file[0])
+ snprintf(&str[0], sizeof(str), "%s:%u: %s", &err_file[0], err_line, msg);
+ else
+ snprintf(&str[0], sizeof(str), "%s", msg);
+ err_file[0] = '\0';
+ err_line = 0;
+ return str;
+}
+
+
+dlo_retcode_t dlo_init(const dlo_init_t flags)
+{
+ /* Initialise the graphics primitives */
+ DPRINTF("dlo: grfx_init\n");
+ ERR(dlo_grfx_init(flags));
+
+ /* Initialise the screen mode timings array */
+ DPRINTF("dlo: mode_init\n");
+ ERR(dlo_mode_init(flags));
+
+ /* Initialise the USB comms code and function pointer table */
+ DPRINTF("dlo: usb_init\n");
+ ERR(dlo_usb_init(flags));
+
+ return dlo_ok;
+}
+
+
+dlo_retcode_t dlo_final(const dlo_final_t flags)
+{
+ /* Free all claimed structures */
+ while (dev_list)
+ {
+ (void) remove_device(dev_list);
+ }
+
+ ERR(dlo_grfx_final(flags));
+ ERR(dlo_mode_final(flags));
+ ERR(dlo_usb_final(flags));
+
+ return dlo_ok;
+}
+
+
+dlo_devlist_t *dlo_enumerate_devices(void)
+{
+ dlo_devlist_t *out = NULL;
+ dlo_device_t *dev;
+ dlo_retcode_t err;
+ uint32_t num;
+
+ check_state = !check_state;
+
+ /* Check USB for all DisplayLink devices that we can find. If there is an error returned,
+ * then it is likely that the devlist could become out of step with reality. For that
+ * reason, after any error, we throw away all unclaimed devices from the devlist to try to
+ * minimise the chances.
+ */
+ //DPRINTF("dlo: enum: enumerating USB devices\n");
+ ERR_GOTO(dlo_usb_enumerate(false));
+
+ /* Remove all devices which weren't updated or added during this enumeration and
+ * build the list of device information to return. Note: if a dlo_malloc() call
+ * fails during this operation, we note it and continue otherwise the dev_list could
+ * get out of step with reality.
+ */
+ dev = dev_list;
+ out = NULL;
+ num = 0;
+ while (dev)
+ {
+ dlo_device_t *next = dev->next;
+
+ if (dev->check == check_state)
+ {
+ dlo_devlist_t *tmp = (dlo_devlist_t *)dlo_malloc(sizeof(dlo_devlist_t));
+
+ /* Add a node to the output list */
+ if (tmp)
+ {
+ tmp->next = out;
+ tmp->dev.uid = (dlo_dev_t)dev;
+ tmp->dev.serial = dev->serial;
+ tmp->dev.type = dev->type;
+ tmp->dev.claimed = dev->claimed;
+ out = tmp;
+ num++;
+ }
+ else
+ err = dlo_err_memory;
+ }
+ else
+ {
+ // DPRINTF("dlo: enum: removed device &%X (%s)\n", (int)dev, dev->serial);
+ (void) remove_device(dev);
+ }
+ dev = next;
+ }
+
+ /* Return pointer to output list if operation was successful */
+ if (!err)
+ {
+ // DPRINTF("dlo: enum: return list of %u entries\n", num);
+ return out;
+ }
+
+error:
+ DPRINTF("dlo: enum: error &%X (usberr &%X)\n", err, usberr);
+
+ /* Throw the output list away */
+ while (out)
+ {
+ dlo_devlist_t *next = out->next;
+
+ dlo_free(out);
+ out = next;
+ }
+
+ /* Remove all unclaimed devices from our list */
+ dev = dev_list;
+ while (dev)
+ {
+ dlo_device_t *next = dev->next;
+
+ if (!dev->claimed)
+ (void) remove_device(dev);
+ dev = next;
+ }
+ return NULL;
+}
+
+
+dlo_dev_t dlo_claim_device(const dlo_dev_t uid, const dlo_claim_t flags, const uint32_t timeout)
+{
+ dlo_device_t *dev = (dlo_device_t *)uid;
+ dlo_retcode_t err;
+
+ if (!dev)
+ ERR_GOTO(dlo_err_bad_device);
+
+ /* Confirm that the device structure pointer still exists */
+ if (!valid_device(dev))
+ ERR_GOTO(dlo_err_bad_device);
+
+ /* Return error if device has already been claimed */
+ if (dev->claimed)
+ ERR_GOTO(dlo_err_claimed);
+
+ dev->timeout = timeout;
+
+ /* Attempt to open a connection to the device */
+ err = dlo_usb_open(dev);
+ while (err == dlo_err_reenum)
+ {
+ DPRINTF("dlo_usb_open failed with dlo_err_reenum. Retry\n");
+
+ /* If the USB bus devices have changed, do the enumeration again */
+ dlo_devlist_t *out = dlo_enumerate_devices();
+
+ /* Throw the output list away */
+ while (out)
+ {
+ dlo_devlist_t *next = out->next;
+
+ dlo_free(out);
+ out = next;
+ }
+
+ /* Confirm that the device structure pointer still exists */
+ if (!valid_device(dev))
+ ERR_GOTO(dlo_err_bad_device);
+
+ /* Now try opening the connection again */
+ err = dlo_usb_open(dev);
+ }
+ /* Any other errors from opening the connection get returned to the caller */
+ ERR_GOTO(err);
+
+ /* Select the standard output channel */
+ ERR_GOTO(dlo_usb_std_chan(dev));
+
+ /* Attempt to change mode into the native resolution of the display (if we have one) */
+ if (dev->native.view.width)
+ ERR_GOTO(dlo_mode_change(dev, &dev->native, DLO_INVALID_MODE));
+
+ return uid;
+
+error:
+ DPRINTF("dlo: claim: error %u '%s'\n", (int)err, dlo_strerror(err));
+
+ return (dlo_dev_t)0;
}
@@ -512,12 +512,12 @@ dlo_dev_t dlo_claim_default_device(int *argc_p, char *argv[],
dlo_devlist_t *node;
dlo_devlist_t *next;
dlo_dev_t uid = 0;
-
- /* Look for a DisplayLink device to connect to - note the first one which is unclaimed */
- node = dlo_enumerate_devices();
-
- // dlo_enumerate_devices allocates memory for each node, which we must free
- while (node)
+
+ /* Look for a DisplayLink device to connect to - note the first one which is unclaimed */
+ node = dlo_enumerate_devices();
+
+ // dlo_enumerate_devices allocates memory for each node, which we must free
+ while (node)
{
dlo_device_t *dev = (dlo_device_t *)node->dev.uid;
@@ -526,424 +526,424 @@ dlo_dev_t dlo_claim_default_device(int *argc_p, char *argv[],
{
uid = dlo_claim_device(node->dev.uid, flags, timeout);
}
-
- /* If we haven't claimed a device, move on to the next one */
- next = node->next;
- dlo_free(node);
- node = next;
- }
- return uid;
-}
-
-
-dlo_retcode_t dlo_release_device(const dlo_dev_t uid)
-{
- dlo_device_t *dev = (dlo_device_t *)uid;
-
- return dev ? dlo_usb_close(dev) : dlo_err_bad_device;
-}
-
-
-dlo_devinfo_t *dlo_device_info(const dlo_dev_t uid)
-{
- static dlo_devinfo_t info;
- dlo_device_t *dev = (dlo_device_t *)uid;
-
- if (!dev)
- return NULL;
-
- info.uid = uid;
- info.serial = dev->serial;
- info.type = dev->type;
- info.claimed = dev->claimed;
-
- return &info;
-}
-
-
-dlo_retcode_t dlo_set_mode(const dlo_dev_t uid, const dlo_mode_t * const desc)
-{
- dlo_device_t *dev = (dlo_device_t *)uid;
- dlo_modenum_t num;
-
- if (!dev)
- return dlo_err_bad_device;
-
- /* See if we can provide a mode which matches the required parameters */
- num = dlo_mode_lookup(dev, desc->view.width, desc->view.height, desc->refresh, desc->view.bpp);
- DPRINTF("dlo: set_mode: lookup %d\n", (int32_t)num);
-
- return num == DLO_INVALID_MODE ? dlo_err_bad_mode : dlo_mode_change(dev, desc, num);
-}
-
-
-dlo_mode_t *dlo_get_mode(const dlo_dev_t uid)
-{
- dlo_device_t *dev = (dlo_device_t *)uid;
-
- return dev ? &(dev->mode) : NULL;
-}
-
-
-dlo_retcode_t dlo_fill_rect(const dlo_dev_t uid, const dlo_view_t * const view, const dlo_rect_t * const rec, const dlo_col32_t col)
-{
- static clip_t clip;
- static dlo_area_t area;
- dlo_device_t * const dev = (dlo_device_t *)uid;
-
- if (!dev)
- return dlo_err_bad_device;
-
- /* Clip the rectangle to its viewport edges */
- if (!sanitise_view_rect(dev, view, rec, &area, &clip))
- return dlo_ok;
-
- return dlo_grfx_fill_rect(dev, &area, col);
-}
-
-
-dlo_retcode_t dlo_copy_rect(const dlo_dev_t uid,
- const dlo_view_t * const src_view, const dlo_rect_t * const src_rec,
- const dlo_view_t * const dest_view, const dlo_dot_t * const dest_pos)
-{
- static clip_t clip;
- static dlo_area_t src_area;
- static dlo_area_t dest_area;
- static dlo_rect_t dest_rec;
- dlo_device_t * const dev = (dlo_device_t *)uid;
- bool overlap = false;
-
- if (!dev)
- return dlo_err_bad_device;
-
- /* Check to see if (and how) the source and destination viewports overlap */
- switch (check_overlaps(dev, src_view, dest_view))
- {
- case vstat_good_view:
- break;
- case vstat_bad_view:
- return dlo_err_bad_view;
- case vstat_bad_overlap:
- return dlo_err_overlap;
- default:
- {
- DPRINTF("dlo: copy_rec: src_view == dest_view... overlap? ");
- overlap = (dest_pos->x + src_rec->width > src_rec->origin.x) &&
- (dest_pos->y + src_rec->height > src_rec->origin.y) &&
- (dest_pos->x < src_rec->origin.x + src_rec->width) &&
- (dest_pos->y < src_rec->origin.y + src_rec->height);
- DPRINTF("%s\n", overlap ? "yes" : "no");
- }
- }
-
- /* Clip the source rectangle to its viewport edges */
- if (!sanitise_view_rect(dev, src_view, src_rec, &src_area, &clip))
- return dlo_ok;
-
- /* Clip the destination rectangle by the same amounts as we needed to clip the source */
- dest_rec.origin.x = dest_pos ? dest_pos->x + clip.left : clip.left;
- dest_rec.origin.y = dest_pos ? dest_pos->y + clip.below : clip.below;
- dest_rec.width = src_area.view.width;
- dest_rec.height = src_area.view.height;
-
- /* Further clip the destination rectangle to its viewport edges */
- if (!sanitise_view_rect(dev, dest_view, &dest_rec, &dest_area, &clip))
- return dlo_ok;
-
- /* Further clip the source area by the same amounts as we needed to clip the destination */
- src_area.view.base += (BYTES_PER_16BPP * clip.left) + (BYTES_PER_16BPP * clip.below * src_area.stride);
- src_area.base8 += (BYTES_PER_8BPP * clip.left) + (BYTES_PER_8BPP * clip.below * src_area.stride);
- src_area.view.width = dest_area.view.width;
- src_area.view.height = dest_area.view.height;
-
- return dlo_grfx_copy_rect(dev, &src_area, &dest_area, overlap);
-}
-
-
-dlo_retcode_t dlo_copy_host_bmp(const dlo_dev_t uid, const dlo_bmpflags_t flags,
- const dlo_fbuf_t * const fbuf,
- const dlo_view_t * const dest_view, const dlo_dot_t * const dest_pos)
-{
- static clip_t clip;
- static dlo_area_t dest_area;
- static dlo_rect_t dest_rec;
- static dlo_fbuf_t src_fbuf;
- dlo_device_t * const dev = (dlo_device_t *)uid;
- uint32_t off;
-
- /* Do some sanity checks */
- if (!dev)
- return dlo_err_bad_device;
-
- if (!fbuf)
- return dlo_err_bad_fbuf;
-
- if (!fbuf->width || !fbuf->height)
- return dlo_ok;
-
- /* Clip the destination rectangle to its viewport edges */
- src_fbuf = *fbuf;
- dest_rec.origin.x = dest_pos ? dest_pos->x : 0;
- dest_rec.origin.y = dest_pos ? dest_pos->y : 0;
- dest_rec.width = src_fbuf.width;
- dest_rec.height = src_fbuf.height;
- if (!sanitise_view_rect(dev, dest_view, &dest_rec, &dest_area, &clip))
- return dlo_ok;
-
- /* Update the source framebuffer information if the destination was clipped */
- off = clip.left + (clip.below * src_fbuf.stride);
- off *= FORMAT_TO_BYTES_PER_PIXEL(src_fbuf.fmt);
- src_fbuf.base = (void *)((unsigned long)src_fbuf.base + (unsigned long)off);
- src_fbuf.width -= clip.left + clip.right;
- src_fbuf.height -= clip.below + clip.above;
-
- return dlo_grfx_copy_host_bmp(dev, flags, &src_fbuf, &dest_area);
-}
-
-
-dlo_device_t *dlo_new_device(const dlo_devtype_t type, const char * const serial)
-{
- dlo_device_t *dev = (dlo_device_t *)dlo_malloc(sizeof(dlo_device_t));
- char *str = NULL;
- dlo_retcode_t err;
-
- NERR_GOTO(dev);
-
- /* Copy the serial number string and keep a pointer to it */
- str = dlo_malloc(1 + strlen(serial));
- NERR_GOTO(str);
- dev->serial = str;
- strcpy(dev->serial, serial);
-
- /* Link into the device list structure */
- dev->prev = NULL;
- dev->next = dev_list;
- dev_list = dev;
- dev->claimed = false;
-
- /* Defaults are for an "Alex" device via USB */
- dev->type = type;
- dev->check = check_state;
- dev->timeout = 0;
-
- /* Mode-dependent attributes and function pointers */
- dev->mode.view.width = 0;
- dev->mode.view.height = 0;
- dev->mode.view.bpp = 0;
- dev->mode.refresh = 0;
- dev->mode.view.base = 0;
- dev->base8 = 0;
- dev->low_blank = false;
-
- /* Device-dependent attributes */
- dev->buffer = NULL;
-
- /* Connection-dependent attributes.
- *
- * It is up to the communications code (re)initialise this values to something which
- * makes sense to it.
- */
- dev->cnct = NULL;
-
- /* Set up some feature flags based upon what we know about DisplayLink device types.
- *
- * NOTE: this section will probably become more refined as more features are added
- * to libdlo. Currently, it assumes all devices are the same.
- */
- dev->memory = 16 * 1024 * 1024;
-
- DPRINTF("dlo: new_device: initialised &%X\n", (int)dev);
-
- return dev;
-
-error:
- if (str)
- dlo_free(str);
- if (dev)
- dlo_free(dev);
-
- return NULL;
-}
-
-
-dlo_device_t *dlo_device_lookup(const char * const serial)
-{
- dlo_device_t *dev = dev_list;
-
- //DPRINTF("dlo: lookup: '%s' dev_list &%X\n", serial, (int)dev_list);
-
- while (dev)
- {
- //DPRINTF("dlo: lookup: dev &%X serial '%s'\n", (int)dev, dev->serial);
- if (0 == strcmp(dev->serial, serial))
- {
- dev->check = check_state;
- return dev;
- }
- dev = dev->next;
- }
- return NULL;
-}
-
-
-/* File-scope function definitions -----------------------------------------------------*/
-
-
-static bool valid_device(const dlo_device_t * const dev)
-{
- dlo_device_t *node = dev_list;
-
- while (node)
- {
- if (node == dev)
- return true;
- node = node->next;
- }
- return false;
-}
-
-
-static dlo_retcode_t remove_device(dlo_device_t *dev)
-{
- dlo_retcode_t err;
- dlo_device_t *prev = dev->prev;
- dlo_device_t *next = dev->next;
-
- /* Delink the device from the device list */
- if (prev)
- prev->next = next;
- else
- dev_list = next;
- if (next)
- next->prev = prev;
-
- /* Disconnect from the device (if connected) */
- if (dev->claimed)
- err = dlo_usb_close(dev);
- else
- err = dlo_ok;
-
- /* Free the structure (and associated data) even if there was an error */
- if (dev->serial)
- dlo_free(dev->serial);
- dlo_free(dev);
-
- return err;
-}
-
-
-static bool sanitise_view_rect(const dlo_device_t * const dev, const dlo_view_t * const view, const dlo_rect_t * const rec, dlo_area_t * const area, clip_t * const clip)
-{
- static dlo_rect_t my_rec;
- const dlo_view_t * const my_view = view ? view : &(dev->mode.view);
- uint32_t pix_off;
-
- /* Exit here if my_view is still NULL (i.e. no screen mode is set up yet) */
- if (!my_view)
- return false;
-
- /* Default the rectangle to the whole of the the view, if none was specified */
- if (rec)
- my_rec = *rec;
- else
- {
- my_rec.origin.x = 0;
- my_rec.origin.y = 0;
- my_rec.width = my_view->width;
- my_rec.height = my_view->height;
- }
-
- /* Exit here if the source rectangle is never going to appear in the viewport */
- if (my_rec.origin.x + (int32_t)my_rec.width < 0 || my_rec.origin.y + (int32_t)my_rec.height < 0)
- return false;
- if (my_rec.origin.x >= (int32_t)my_view->width || my_rec.origin.y >= (int32_t)my_view->height)
- return false;
-
- /* Initialise the clip structure to empty */
- clip->left = 0;
- clip->right = 0;
- clip->below = 0;
- clip->above = 0;
-
- /* Now clip the rectangle to lie within the viewport */
- if (my_rec.origin.x + (int32_t)my_rec.width > (int32_t)my_view->width)
- {
- clip->right = my_rec.width - (my_view->width - my_rec.origin.x);
- my_rec.width = my_view->width - my_rec.origin.x;
- }
- if (my_rec.origin.y + (int32_t)my_rec.height > (int32_t)my_view->height)
- {
- clip->above = my_rec.height - (my_view->height - my_rec.origin.y);
- my_rec.height = my_view->height - my_rec.origin.y;
- }
- if (my_rec.origin.x < 0)
- {
- clip->left = -my_rec.origin.x;
- my_rec.width += my_rec.origin.x;
- my_rec.origin.x = 0;
- }
- if (my_rec.origin.y < 0)
- {
- clip->below = -my_rec.origin.y;
- my_rec.height += my_rec.origin.y;
- my_rec.origin.y = 0;
- }
-
- /* Exit here if we've clipped the rectangle away to nothing */
- if (!my_rec.width || !my_rec.height)
- return false;
-
- /* Create the clipped area structure */
- pix_off = my_rec.origin.x + (my_rec.origin.y * my_view->width);
- area->view.width = my_rec.width;
- area->view.height = my_rec.height;
- area->view.bpp = my_view->bpp;
- area->view.base = my_view->base + (BYTES_PER_16BPP * pix_off);
- area->base8 = my_view->base + (BYTES_PER_16BPP * my_view->width * my_view->height) + pix_off;
- area->stride = my_view->width;
-
- return true;
-}
-
-
-static vstat_t check_overlaps(const dlo_device_t * const dev, const dlo_view_t * const src_view, const dlo_view_t * const dest_view)
-{
- const dlo_view_t * const src = src_view ? src_view : &(dev->mode.view);
- const dlo_view_t * const dest = dest_view ? dest_view : &(dev->mode.view);
- dlo_ptr_t src_end;
- dlo_ptr_t dest_end;
-
- /* If no display mode is set up, we should stop here to avoid null dereferences */
- if (!src || !dest)
- return vstat_bad_view;
-
- /* If base addresses are the same, the other attributes must also be the same */
- if (src->base == dest->base)
- {
- return (src->width == dest->width &&
- src->height == dest->height &&
- src->bpp == dest->bpp) ? vstat_good_overlap : vstat_bad_overlap;
- }
-
- /* Ensure we're happy with the source bits per pixel */
- if (src->bpp != 16 && src->bpp != 24)
- return vstat_bad_view;
-
- /* Ensure we're happy with the destination bits per pixel */
- if (dest->bpp != 16 && dest->bpp != 24)
- return vstat_bad_view;
-
- /* Compute the end addresses of both views */
- src_end = src->base + (BYTES_PER_16BPP * src->width * src->height);
- dest_end = dest->base + (BYTES_PER_16BPP * dest->width * dest->height);
- if (src->bpp == 24)
- src_end += BYTES_PER_8BPP * src->width * src->height;
- if (dest->bpp == 24)
- dest_end += BYTES_PER_8BPP * dest->width * dest->height;
-
- /* Any overlap in address range means we have a problem */
- return (dest_end <= src->base || dest->base >= src_end) ? vstat_good_view : vstat_bad_overlap;
-}
-
-
-/* End of file -------------------------------------------------------------------------*/
+
+ /* If we haven't claimed a device, move on to the next one */
+ next = node->next;
+ dlo_free(node);
+ node = next;
+ }
+ return uid;
+}
+
+
+dlo_retcode_t dlo_release_device(const dlo_dev_t uid)
+{
+ dlo_device_t *dev = (dlo_device_t *)uid;
+
+ return dev ? dlo_usb_close(dev) : dlo_err_bad_device;
+}
+
+
+dlo_devinfo_t *dlo_device_info(const dlo_dev_t uid)
+{
+ static dlo_devinfo_t info;
+ dlo_device_t *dev = (dlo_device_t *)uid;
+
+ if (!dev)
+ return NULL;
+
+ info.uid = uid;
+ info.serial = dev->serial;
+ info.type = dev->type;
+ info.claimed = dev->claimed;
+
+ return &info;
+}
+
+
+dlo_retcode_t dlo_set_mode(const dlo_dev_t uid, const dlo_mode_t * const desc)
+{
+ dlo_device_t *dev = (dlo_device_t *)uid;
+ dlo_modenum_t num;
+
+ if (!dev)
+ return dlo_err_bad_device;
+
+ /* See if we can provide a mode which matches the required parameters */
+ num = dlo_mode_lookup(dev, desc->view.width, desc->view.height, desc->refresh, desc->view.bpp);
+ DPRINTF("dlo: set_mode: lookup %d\n", (int32_t)num);
+
+ return num == DLO_INVALID_MODE ? dlo_err_bad_mode : dlo_mode_change(dev, desc, num);
+}
+
+
+dlo_mode_t *dlo_get_mode(const dlo_dev_t uid)
+{
+ dlo_device_t *dev = (dlo_device_t *)uid;
+
+ return dev ? &(dev->mode) : NULL;
+}
+
+
+dlo_retcode_t dlo_fill_rect(const dlo_dev_t uid, const dlo_view_t * const view, const dlo_rect_t * const rec, const dlo_col32_t col)
+{
+ static clip_t clip;
+ static dlo_area_t area;
+ dlo_device_t * const dev = (dlo_device_t *)uid;
+
+ if (!dev)
+ return dlo_err_bad_device;
+
+ /* Clip the rectangle to its viewport edges */
+ if (!sanitise_view_rect(dev, view, rec, &area, &clip))
+ return dlo_ok;
+
+ return dlo_grfx_fill_rect(dev, &area, col);
+}
+
+
+dlo_retcode_t dlo_copy_rect(const dlo_dev_t uid,
+ const dlo_view_t * const src_view, const dlo_rect_t * const src_rec,
+ const dlo_view_t * const dest_view, const dlo_dot_t * const dest_pos)
+{
+ static clip_t clip;
+ static dlo_area_t src_area;
+ static dlo_area_t dest_area;
+ static dlo_rect_t dest_rec;
+ dlo_device_t * const dev = (dlo_device_t *)uid;
+ bool overlap = false;
+
+ if (!dev)
+ return dlo_err_bad_device;
+
+ /* Check to see if (and how) the source and destination viewports overlap */
+ switch (check_overlaps(dev, src_view, dest_view))
+ {
+ case vstat_good_view:
+ break;
+ case vstat_bad_view:
+ return dlo_err_bad_view;
+ case vstat_bad_overlap:
+ return dlo_err_overlap;
+ default:
+ {
+ DPRINTF("dlo: copy_rec: src_view == dest_view... overlap? ");
+ overlap = (dest_pos->x + src_rec->width > src_rec->origin.x) &&
+ (dest_pos->y + src_rec->height > src_rec->origin.y) &&
+ (dest_pos->x < src_rec->origin.x + src_rec->width) &&
+ (dest_pos->y < src_rec->origin.y + src_rec->height);
+ DPRINTF("%s\n", overlap ? "yes" : "no");
+ }
+ }
+
+ /* Clip the source rectangle to its viewport edges */
+ if (!sanitise_view_rect(dev, src_view, src_rec, &src_area, &clip))
+ return dlo_ok;
+
+ /* Clip the destination rectangle by the same amounts as we needed to clip the source */
+ dest_rec.origin.x = dest_pos ? dest_pos->x + clip.left : clip.left;
+ dest_rec.origin.y = dest_pos ? dest_pos->y + clip.below : clip.below;
+ dest_rec.width = src_area.view.width;
+ dest_rec.height = src_area.view.height;
+
+ /* Further clip the destination rectangle to its viewport edges */
+ if (!sanitise_view_rect(dev, dest_view, &dest_rec, &dest_area, &clip))
+ return dlo_ok;
+
+ /* Further clip the source area by the same amounts as we needed to clip the destination */
+ src_area.view.base += (BYTES_PER_16BPP * clip.left) + (BYTES_PER_16BPP * clip.below * src_area.stride);
+ src_area.base8 += (BYTES_PER_8BPP * clip.left) + (BYTES_PER_8BPP * clip.below * src_area.stride);
+ src_area.view.width = dest_area.view.width;
+ src_area.view.height = dest_area.view.height;
+
+ return dlo_grfx_copy_rect(dev, &src_area, &dest_area, overlap);
+}
+
+
+dlo_retcode_t dlo_copy_host_bmp(const dlo_dev_t uid, const dlo_bmpflags_t flags,
+ const dlo_fbuf_t * const fbuf,
+ const dlo_view_t * const dest_view, const dlo_dot_t * const dest_pos)
+{
+ static clip_t clip;
+ static dlo_area_t dest_area;
+ static dlo_rect_t dest_rec;
+ static dlo_fbuf_t src_fbuf;
+ dlo_device_t * const dev = (dlo_device_t *)uid;
+ uint32_t off;
+
+ /* Do some sanity checks */
+ if (!dev)
+ return dlo_err_bad_device;
+
+ if (!fbuf)
+ return dlo_err_bad_fbuf;
+
+ if (!fbuf->width || !fbuf->height)
+ return dlo_ok;
+
+ /* Clip the destination rectangle to its viewport edges */
+ src_fbuf = *fbuf;
+ dest_rec.origin.x = dest_pos ? dest_pos->x : 0;
+ dest_rec.origin.y = dest_pos ? dest_pos->y : 0;
+ dest_rec.width = src_fbuf.width;
+ dest_rec.height = src_fbuf.height;
+ if (!sanitise_view_rect(dev, dest_view, &dest_rec, &dest_area, &clip))
+ return dlo_ok;
+
+ /* Update the source framebuffer information if the destination was clipped */
+ off = clip.left + (clip.below * src_fbuf.stride);
+ off *= FORMAT_TO_BYTES_PER_PIXEL(src_fbuf.fmt);
+ src_fbuf.base = (void *)((unsigned long)src_fbuf.base + (unsigned long)off);
+ src_fbuf.width -= clip.left + clip.right;
+ src_fbuf.height -= clip.below + clip.above;
+
+ return dlo_grfx_copy_host_bmp(dev, flags, &src_fbuf, &dest_area);
+}
+
+
+dlo_device_t *dlo_new_device(const dlo_devtype_t type, const char * const serial)
+{
+ dlo_device_t *dev = (dlo_device_t *)dlo_malloc(sizeof(dlo_device_t));
+ char *str = NULL;
+ dlo_retcode_t err;
+
+ NERR_GOTO(dev);
+
+ /* Copy the serial number string and keep a pointer to it */
+ str = dlo_malloc(1 + strlen(serial));
+ NERR_GOTO(str);
+ dev->serial = str;
+ strcpy(dev->serial, serial);
+
+ /* Link into the device list structure */
+ dev->prev = NULL;
+ dev->next = dev_list;
+ dev_list = dev;
+ dev->claimed = false;
+
+ /* Defaults are for an "Alex" device via USB */
+ dev->type = type;
+ dev->check = check_state;
+ dev->timeout = 0;
+
+ /* Mode-dependent attributes and function pointers */
+ dev->mode.view.width = 0;
+ dev->mode.view.height = 0;
+ dev->mode.view.bpp = 0;
+ dev->mode.refresh = 0;
+ dev->mode.view.base = 0;
+ dev->base8 = 0;
+ dev->low_blank = false;
+
+ /* Device-dependent attributes */
+ dev->buffer = NULL;
+
+ /* Connection-dependent attributes.
+ *
+ * It is up to the communications code (re)initialise this values to something which
+ * makes sense to it.
+ */
+ dev->cnct = NULL;
+
+ /* Set up some feature flags based upon what we know about DisplayLink device types.
+ *
+ * NOTE: this section will probably become more refined as more features are added
+ * to libdlo. Currently, it assumes all devices are the same.
+ */
+ dev->memory = 16 * 1024 * 1024;
+
+ DPRINTF("dlo: new_device: initialised &%X\n", (int)dev);
+
+ return dev;
+
+error:
+ if (str)
+ dlo_free(str);
+ if (dev)
+ dlo_free(dev);
+
+ return NULL;
+}
+
+
+dlo_device_t *dlo_device_lookup(const char * const serial)
+{
+ dlo_device_t *dev = dev_list;
+
+ //DPRINTF("dlo: lookup: '%s' dev_list &%X\n", serial, (int)dev_list);
+
+ while (dev)
+ {
+ //DPRINTF("dlo: lookup: dev &%X serial '%s'\n", (int)dev, dev->serial);
+ if (0 == strcmp(dev->serial, serial))
+ {
+ dev->check = check_state;
+ return dev;
+ }
+ dev = dev->next;
+ }
+ return NULL;
+}
+
+
+/* File-scope function definitions -----------------------------------------------------*/
+
+
+static bool valid_device(const dlo_device_t * const dev)
+{
+ dlo_device_t *node = dev_list;
+
+ while (node)
+ {
+ if (node == dev)
+ return true;
+ node = node->next;
+ }
+ return false;
+}
+
+
+static dlo_retcode_t remove_device(dlo_device_t *dev)
+{
+ dlo_retcode_t err;
+ dlo_device_t *prev = dev->prev;
+ dlo_device_t *next = dev->next;
+
+ /* Delink the device from the device list */
+ if (prev)
+ prev->next = next;
+ else
+ dev_list = next;
+ if (next)
+ next->prev = prev;
+
+ /* Disconnect from the device (if connected) */
+ if (dev->claimed)
+ err = dlo_usb_close(dev);
+ else
+ err = dlo_ok;
+
+ /* Free the structure (and associated data) even if there was an error */
+ if (dev->serial)
+ dlo_free(dev->serial);
+ dlo_free(dev);
+
+ return err;
+}
+
+
+static bool sanitise_view_rect(const dlo_device_t * const dev, const dlo_view_t * const view, const dlo_rect_t * const rec, dlo_area_t * const area, clip_t * const clip)
+{
+ static dlo_rect_t my_rec;
+ const dlo_view_t * const my_view = view ? view : &(dev->mode.view);
+ uint32_t pix_off;
+
+ /* Exit here if my_view is still NULL (i.e. no screen mode is set up yet) */
+ if (!my_view)
+ return false;
+
+ /* Default the rectangle to the whole of the the view, if none was specified */
+ if (rec)
+ my_rec = *rec;
+ else
+ {
+ my_rec.origin.x = 0;
+ my_rec.origin.y = 0;
+ my_rec.width = my_view->width;
+ my_rec.height = my_view->height;
+ }
+
+ /* Exit here if the source rectangle is never going to appear in the viewport */
+ if (my_rec.origin.x + (int32_t)my_rec.width < 0 || my_rec.origin.y + (int32_t)my_rec.height < 0)
+ return false;
+ if (my_rec.origin.x >= (int32_t)my_view->width || my_rec.origin.y >= (int32_t)my_view->height)
+ return false;
+
+ /* Initialise the clip structure to empty */
+ clip->left = 0;
+ clip->right = 0;
+ clip->below = 0;
+ clip->above = 0;
+
+ /* Now clip the rectangle to lie within the viewport */
+ if (my_rec.origin.x + (int32_t)my_rec.width > (int32_t)my_view->width)
+ {
+ clip->right = my_rec.width - (my_view->width - my_rec.origin.x);
+ my_rec.width = my_view->width - my_rec.origin.x;
+ }
+ if (my_rec.origin.y + (int32_t)my_rec.height > (int32_t)my_view->height)
+ {
+ clip->above = my_rec.height - (my_view->height - my_rec.origin.y);
+ my_rec.height = my_view->height - my_rec.origin.y;
+ }
+ if (my_rec.origin.x < 0)
+ {
+ clip->left = -my_rec.origin.x;
+ my_rec.width += my_rec.origin.x;
+ my_rec.origin.x = 0;
+ }
+ if (my_rec.origin.y < 0)
+ {
+ clip->below = -my_rec.origin.y;
+ my_rec.height += my_rec.origin.y;
+ my_rec.origin.y = 0;
+ }
+
+ /* Exit here if we've clipped the rectangle away to nothing */
+ if (!my_rec.width || !my_rec.height)
+ return false;
+
+ /* Create the clipped area structure */
+ pix_off = my_rec.origin.x + (my_rec.origin.y * my_view->width);
+ area->view.width = my_rec.width;
+ area->view.height = my_rec.height;
+ area->view.bpp = my_view->bpp;
+ area->view.base = my_view->base + (BYTES_PER_16BPP * pix_off);
+ area->base8 = my_view->base + (BYTES_PER_16BPP * my_view->width * my_view->height) + pix_off;
+ area->stride = my_view->width;
+
+ return true;
+}
+
+
+static vstat_t check_overlaps(const dlo_device_t * const dev, const dlo_view_t * const src_view, const dlo_view_t * const dest_view)
+{
+ const dlo_view_t * const src = src_view ? src_view : &(dev->mode.view);
+ const dlo_view_t * const dest = dest_view ? dest_view : &(dev->mode.view);
+ dlo_ptr_t src_end;
+ dlo_ptr_t dest_end;
+
+ /* If no display mode is set up, we should stop here to avoid null dereferences */
+ if (!src || !dest)
+ return vstat_bad_view;
+
+ /* If base addresses are the same, the other attributes must also be the same */
+ if (src->base == dest->base)
+ {
+ return (src->width == dest->width &&
+ src->height == dest->height &&
+ src->bpp == dest->bpp) ? vstat_good_overlap : vstat_bad_overlap;
+ }
+
+ /* Ensure we're happy with the source bits per pixel */
+ if (src->bpp != 16 && src->bpp != 24)
+ return vstat_bad_view;
+
+ /* Ensure we're happy with the destination bits per pixel */
+ if (dest->bpp != 16 && dest->bpp != 24)
+ return vstat_bad_view;
+
+ /* Compute the end addresses of both views */
+ src_end = src->base + (BYTES_PER_16BPP * src->width * src->height);
+ dest_end = dest->base + (BYTES_PER_16BPP * dest->width * dest->height);
+ if (src->bpp == 24)
+ src_end += BYTES_PER_8BPP * src->width * src->height;
+ if (dest->bpp == 24)
+ dest_end += BYTES_PER_8BPP * dest->width * dest->height;
+
+ /* Any overlap in address range means we have a problem */
+ return (dest_end <= src->base || dest->base >= src_end) ? vstat_good_view : vstat_bad_overlap;
+}
+
+
+/* End of file -------------------------------------------------------------------------*/
diff --git a/src/libdlo.h b/src/libdlo.h
index 286cc88..08cdc69 100644
--- a/src/libdlo.h
+++ b/src/libdlo.h
@@ -1,606 +1,606 @@
-/** @file libdlo.h
- *
- * @brief This file defines the high-level API for the DisplayLink libdlo library.
- *
- * It is a simplified abstraction layer to allow programs to talk to DisplayLink
- * compatible devices.
- *
- * DisplayLink Open Source Software (libdlo)
- * Copyright (C) 2009, DisplayLink
- * www.displaylink.com
- *
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Library General Public License as published by the Free
- * Software Foundation; LGPL version 2, dated June 1991.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/** @mainpage DisplayLink Open Source Software (libdlo)
- * @anchor dlppdoxygenmain
- *
- * This documentation covers the DisplayLink Open Source Software (libdlo) library (libdlo).
- * It covers the following items:
- *
- * @li File by file information
- * @li Function by function information
- * @li Global variables, defines and structures
- *
- * <hr>
- *
- * <b>Overview</b>
- *
- * <p>
- * This library is stuctured as illustrated below, in order to help clarify the major
- * functional areas and simplify the task of porting or reimplementing these functions
- * to other platforms. At the very least, it should serve as a reference implementation
- * which can be replaced in its entirety.
- * </p>
- *
- * @image html libdlo.gif "libdlo internal structure"
- *
- * <p>
- * All communications with libdlo are through the API published in libdlo.h. This API
- * allows third party software to find DisplayLink devices, connect to them, perform
- * graphical operations and then disconnect as required. There are a number of graphical
- * primitives available, including rectangle plotting and copying (rectangular) areas of
- * screen.
- * </p>
- *
- * <hr>
- * <b>Implementation Notes: Functions</b>
- *
- * <p>
- * There are primarily three types of function used within all of the libdlo sources:
- * </p>
- *
- * @li A void function or non-error returning function
- * @li A pointer-returning function
- * @li A function returning a return code
- *
- * <p>
- * Void and non-error returning functions are used in situations where there is no
- * possibility or an error being raised or where there would be no value in returning it.
- * Examples might include functions which simply perform a computation or those which
- * dispose of a structure and are expected to fail silently.
- * </p>
- *
- * <p>
- * Pointer returning functions will conventionally return a NULL pointer if there is
- * an error. Normally the error will be due to memory allocation failure (out of
- * memory) but this is not always the case. As a NULL pointer it not very informative
- * about the nature of the failure, the use of pointer-returning functions within
- * libdlo has been kept to a minimum.
- * </p>
- *
- * <p>
- * The majority of functions return an code of type @a dlo_retcode_t to indicate
- * success or the nature of failure. All return codes have an associated textual string
- * so they can be decoded in a human-readable format by calling @c dlo_strerror().
- * </p>
- *
- * <hr>
- * <b>Implementation Notes: Error Handling</b>
- *
- * <p>
- * In order to keep the handling of errors consistent, there are a number of handy
- * macros defined in dlo_defs.h. There are a few which collect any non-zero return
- * value from a given function call and return it from the calling function (there
- * is also a version of this call which checks for NULL pointer returns and converts
- * it into an memory allocation failure return code). These macros are:
- * </p>
- *
- * @li @c ERR()
- * @li @c NERR()
- * @li @c UERR()
- *
- * <p>
- * A second set of macros are defined which, instead of returning a return code from
- * the calling function, they store the error in a local variable "err" and jump to
- * a label called "error". This allows the function to perform whatever tidy-up
- * operations it needs to before returning "err". These macros are:
- * </p>
- *
- * @li @c ERR_GOTO()
- * @li @c NERR_GOTO()
- * @li @c UERR_GOTO()
- *
- * <p>
- * Both of these sets of macros are used throughout the libdlo sources in order to
- * make the handling of errors consistent.
- * </p>
- *
- * <hr>
- * Copyright &copy; 2008, DisplayLink
- * All rights reserved.
- */
-
-#ifndef DLO_LIBDLO_H
-#define DLO_LIBDLO_H /**< Avoid multiple inclusion. */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include "usb.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if 0
-#define dlo_malloc my_malloc
-#define dlo_realloc my_realloc
-#define dlo_free my_free
-
-/** Alternative malloc routine.
- *
- * @param size As per @c malloc().
- *
- * @return As per @c malloc().
- */
-extern void *my_malloc(size_t size);
-
-/** Alternative realloc routine.
- *
- * @param blk As per @c realloc().
- * @param size As per @c realloc().
- *
- * @return As per @c realloc().
- */
-extern void *my_realloc(void *blk, size_t size);
-
-/** Alternative free routine.
- *
- * @param blk As per @c free().
- */
-extern void my_free(void *blk);
-
-/** Return total size of allocated blocks.
- *
- * @return Size of all current allocations (bytes).
- */
-extern uint32_t my_used(void);
-#endif
-
-
-/** Allow the use of the standard C library @a malloc() function to be overridden.
- */
-#ifndef dlo_malloc
-#define dlo_malloc malloc
-#endif
-
-/** Allow the use of the standard C library @a realloc() function to be overridden.
- */
-#ifndef dlo_realloc
-#define dlo_realloc realloc
-#endif
-
-/** Allow the use of the standard C library @a free() function to be overridden.
- */
-#ifndef dlo_free
-#define dlo_free free
-#endif
-
-/** Allow the use of the standard C library @a memset() function to be overridden.
- */
-#ifndef dlo_memset
-#define dlo_memset (void) memset
-#endif
-
-/** Allow the use of the standard C library @a memcpy() function to be overridden.
- */
-#ifndef dlo_memcpy
-#define dlo_memcpy (void) memcpy
-#endif
-
-/** Allow the use of the standard C library @a memmove() function to be overridden.
- */
-#ifndef dlo_memmove
-#define dlo_memmove (void) memmove
-#endif
-
-
-/** An opaque device handle. */
-typedef void *dlo_dev_t;
-
-
-/** Return codes used within the libdlo sources. Note: libdlo will never return top-bit-set return
- * codes so these can safely be allocated within your own programs for your own purposes.
- *
- * Return code 0x00000000 represents a successful return without error or warning.
- * Return codes in the range 0x00000001..0x0FFFFFFF represent an error condition.
- * Return codes in the range 0x10000000..0x7FFFFFFF represent a warning.
- * Return codes in the range 0x80000000..0xFFFFFFFF are free for caller allocation.
- */
-typedef enum
-{
- /* Success... */
- dlo_ok = 0u, /**< Successful. */
- /* Errors... */
- dlo_err_memory = 1u, /**< A memory claim operation failed; out of memory. */
- dlo_err_bad_area, /**< An invalid area was specified (e.g. of zero width or height). */
- dlo_err_bad_col, /**< Unsupported colour depth. */
- dlo_err_bad_device, /**< Unknown device - has been disconnected or powered down. */
- dlo_err_bad_fbuf, /**< Null pointer passed as local bitmap data. */
- dlo_err_bad_fmt, /**< Unsupported bitmap pixel format. */
- dlo_err_bad_mode, /**< Call to @c set_mode() failed due to unsupported mode parameters. */
- dlo_err_bad_view, /**< Invalid viewport specified (is screen mode set up?). */
- dlo_err_big_scrape, /**< Bitmap is too wide for copy buffer.*/
- dlo_err_buf_full, /**< Command buffer is full. */
- dlo_err_claimed, /**< Device cannot be claimed - it's already been claimed. */
- dlo_err_edid_fail, /**< EDID communication with monitor failed. */
- dlo_err_iic_op, /**< An IIC operation with the device failed. */
- dlo_err_not_root, /**< Executable should be run as root (e.g. using 'su root' or 'sudo'). */
- dlo_err_open, /**< Attempt to open a connection to the device failed. */
- dlo_err_overlap, /**< Source and destination viewports cannot overlap (unless the same). */
- dlo_err_reenum, /**< Reenumeration required before device can be claimed. */
- dlo_err_unclaimed, /**< Device cannot be written to: unclaimed. */
- dlo_err_unsupported, /**< Requested feature is not supported. */
- dlo_err_usb, /**< A USB-related error: call @c dlo_usb_strerror() for further info. */
- /* Warnings... */
- dlo_warn_dl160_mode = 0x10000000u, /**< This screen mode may not display correctly on DL120 devices. */
- /* User return codes... */
- dlo_user_example = 0x80000000 /**< Return codes 0x80000000 to 0xFFFFFFFF are free for user allocation. */
-} dlo_retcode_t; /**< Return codes. Used to indicate the success or otherwise of a call to the library. */
-
-
-/** A 32 bits per pixel colour number (0x00bbggrr, little endian). Note: most significant byte is undefined. */
-typedef uint32_t dlo_col32_t;
-
-
-/** Return a 32 bpp colour number when given the three RGB components. */
-#define DLO_RGB(red,grn,blu) (dlo_col32_t)(((red) & 0xFF) | (((grn) & 0xFF) << 8) | (((blu) & 0xFF) << 16))
-
-/** Set the red component (0..255) of a 32 bpp colour. */
-#define DLO_RGB_SETRED(col,red) (dlo_col32_t)(((col) & ~0xFF) | ((red) & 0xFF))
-
-/** Set the green component (0..255) of a 32 bpp colour. */
-#define DLO_RGB_SETGRN(col,grn) (dlo_col32_t)(((col) & ~0xFF00) | (((grn) & 0xFF) << 8))
-
-/** Set the blue component (0..255) of a 32 bpp colour. */
-#define DLO_RGB_SETBLU(col,blu) (dlo_col32_t)(((col) & ~0xFF0000) | (((blu) & 0xFF) << 16))
-
-/** Read the red component (0..255) of a 32 bpp colour. */
-#define DLO_RGB_GETRED(col) (uint8_t)((col) & 0xFF)
-
-/** Read the green component (0..255) of a 32 bpp colour. */
-#define DLO_RGB_GETGRN(col) (uint8_t)(((col) >> 8) & 0xFF)
-
-/** Read the blue component (0..255) of a 32 bpp colour. */
-#define DLO_RGB_GETBLU(col) (uint8_t)(((col) >> 16) & 0xFF)
-
-
-/** Types of DisplayLink device. */
-typedef enum
-{
- dlo_dev_unknown = 0, /**< Unknown device type. */
- dlo_dev_base = 0xB, /**< Base platform. */
- dlo_dev_alex = 0xF, /**< Alex chipset. */
- dlo_dev_ollie = 0xF1 /**< Ollie chipset. */
-} dlo_devtype_t; /**< A struct @a dlo_devtype_s. */
-
-
-/** A structure containing information about a specific device. */
-typedef struct dlo_devinfo_s
-{
- dlo_dev_t uid; /**< Unique ID for referencing the device. */
- char *serial; /**< Pointer to serial number string for device. */
- dlo_devtype_t type; /**< Device type. */
- bool claimed; /**< Flag indicating whether someone has claimed the device. */
-} dlo_devinfo_t; /**< A struct @a dlo_devinfo_s. */
-
-
-/** A list of devices, as returned by the enumeration call. */
-typedef struct dlo_devlist_s dlo_devlist_t;
-
-/** A list of devices, as returned by the enumeration call. */
-struct dlo_devlist_s
-{
- dlo_devlist_t *next; /**< Pointer to next node in the device list (or NULL). */
- dlo_devinfo_t dev; /**< Device information structure. */
-}; /**< A struct @a dlo_devlist_s. */
-
-
-/** Flags word for the initialisation function (no flags defined at present). */
-typedef struct dlo_init_s
-{
- unsigned undef :1; /**< Undefined flag (placeholder). */
-} dlo_init_t; /**< A struct @a dlo_init_s. */
-
-
-/** Flags word for the finalisation function (no flags defined at present). */
-typedef struct dlo_final_s
-{
- unsigned undef :1; /**< Undefined flag (placeholder). */
-} dlo_final_t; /**< A struct @a dlo_final_s. */
-
-
-/** Flags word to configure the device connection (no flags defined at present). */
-typedef struct dlo_claim_s
-{
- unsigned undef :1; /**< Undefined flag (placeholder). */
-} dlo_claim_t; /**< A struct @a dlo_claim_s. */
-
-
-/** Flags word to configure the @c dlo_copy_host_bmp() call. */
-typedef struct dlo_bmpflags_s
-{
- unsigned v_flip :1; /**< Vertically flip the bitmap during the copy. */
-} dlo_bmpflags_t; /**< A struct @a dlo_bmpflags_s. */
-
-
-/** Shift (bits) for position of bytes-per-pixel data in pixel format word.
- */
-#define DLO_PIXFMT_BYPP_SFT (6u)
-
-/** Bit mask for extracting bytes-per-pixel data from pixel format word.
- */
-#define DLO_PIXFMT_BYPP_MSK (0x7 << DLO_PIXFMT_BYPP_SFT)
-
-/** Shift (bits) for position of red/blue swap flag in pixel format word.
- */
-#define DLO_PIXFMT_SWP_SFT (9u)
-
-/** Shift (bits) for position of pointer data (most significant bits).
- */
-#define DLO_PIXFMT_PTR_SFT (10u)
-
-/** Maximum number of pixel format variations.
- */
-#define DLO_PIXFMT_MAX (1u << DLO_PIXFMT_PTR_SFT)
-
-/** Pixel format has one byte per pixel.
- */
-#define DLO_PIXFMT_1BYPP (1u << DLO_PIXFMT_BYPP_SFT)
-
-/** Pixel format has two bytes per pixel.
- */
-#define DLO_PIXFMT_2BYPP (2u << DLO_PIXFMT_BYPP_SFT)
-
-/** Pixel format has three bytes per pixel.
- */
-#define DLO_PIXFMT_3BYPP (3u << DLO_PIXFMT_BYPP_SFT)
-
-/** Pixel format has four bytes per pixel.
- */
-#define DLO_PIXFMT_4BYPP (4u << DLO_PIXFMT_BYPP_SFT)
-
-/** Pixel format has red and blue colour components reversed.
- */
-#define DLO_PIXFMT_SWP (1u << DLO_PIXFMT_SWP_SFT)
-
-/** Supported source pixel format information (e.g. bits per pixel, colour component order, etc).
- *
- * Each value in this enum encodes the pixel RGB vs BGR colour component order and
- * the number of bytes per pixel. There is one function for reading each pixel format
- * (but the RGB vs BGR is passed in as a flag) and the bytes per pixel is required to
- * advance the pixel pointer in a framebuffer after a pixel has been read.
- *
- * Bits 0..5 contain the pixel format code
- * Bits 6..8 contain the number of bytes per pixel
- * Bit 9 contains the swap flag for RGB vs BGR
- * Bits 10.. if non-zero, then the pixel format is actually a pointer to an 8 bit LUT
- *
- * The pixel format can also simply be a pointer to a 256 entry LUT of dlo_col32_t
- * colours in the case where the local framebuffer contains 8bpp bitmap data which
- * uses a palette. Simply cast the LUT pointer to a dlo_pixfmt_t (this assumes that
- * your LUT isn't stored in the bottom 1KB of the logical address space!). E.g.
- *
- * static dlo_col32_t mylut[256]; // this is the palette for my 8bpp bitmap
- * static dlo_pixfmt_t mypixfmt = (dlo_pixfmt_t)mylut;
- */
-typedef enum
-{
- dlo_pixfmt_bgr323 = 0 | DLO_PIXFMT_1BYPP, /**< 8 bit per pixel 2_bbbggrrr. */
- dlo_pixfmt_rgb323 = 0 | DLO_PIXFMT_1BYPP | DLO_PIXFMT_SWP, /**< 8 bit per pixel 2_rrrggbbb. */
- dlo_pixfmt_bgr565 = 1 | DLO_PIXFMT_2BYPP, /**< 16 bit per pixel 2_bbbbbggggggrrrrr. */
- dlo_pixfmt_rgb565 = 1 | DLO_PIXFMT_2BYPP | DLO_PIXFMT_SWP, /**< 16 bit per pixel 2_rrrrrggggggbbbbb. */
- dlo_pixfmt_sbgr1555 = 2 | DLO_PIXFMT_2BYPP, /**< 16 bit per pixel 2_Sbbbbbgggggrrrrr (S is supremacy/transparancy bit). */
- dlo_pixfmt_srgb1555 = 2 | DLO_PIXFMT_2BYPP | DLO_PIXFMT_SWP, /**< 16 bit per pixel 2_Srrrrrgggggbbbbb (S is supremacy/transparancy bit). */
- dlo_pixfmt_bgr888 = 3 | DLO_PIXFMT_3BYPP, /**< 24 bit per pixel 0xbbggrr. */
- dlo_pixfmt_rgb888 = 3 | DLO_PIXFMT_3BYPP | DLO_PIXFMT_SWP, /**< 24 bit per pixel 0xrrggbb. */
- dlo_pixfmt_abgr8888 = 4 | DLO_PIXFMT_4BYPP, /**< 32 bit per pixel 0xaabbggrr. */
- dlo_pixfmt_argb8888 = 4 | DLO_PIXFMT_4BYPP | DLO_PIXFMT_SWP /**< 32 bit per pixel 0xaarrggbb. */
- /* Any value greater than 1023 is assumed to be a pointer to: dlo_col32_t palette[256]
- * for translating paletted 8 bits per pixel data into colour numbers.
- */
-} dlo_pixfmt_t; /**< A struct @a dlo_pixfmt_s. */
-
-
-/** A local (host-resident) bitmap or framebuffer. */
-typedef struct dlo_fbuf_s
-{
- uint16_t width; /**< Width (pixels). */
- uint16_t height; /**< Height (pixels). */
- dlo_pixfmt_t fmt; /**< Pixel format (e.g. bits per pixel, colour component order, etc). */
- void *base; /**< Base address in host memory. */
- uint32_t stride; /**< Stride (pixels) from a pixel to the one directly below. */
-} dlo_fbuf_t; /**< A struct @a dlo_fbuf_s. */
-
-
-/** An pointer to a location in the DisplayLink device logical memory map. */
-typedef uint32_t dlo_ptr_t;
-
-
-/** A viewport (bitmap) in a contiguous block of device memory.
- *
- * A viewport describes the contents of a contiguous block of device memory (of which there
- * is normally 16 MB available). It represents a rectangular bitmap which may be large
- * enough to use as a screen mode or of any other non-zero size.
- *
- * It is the responsibility of the caller to organise one or more viewports in the device
- * memory and use the @c dlo_set_mode() call to determine which is visible on the screen
- * at any given time.
- *
- * When a device is first claimed, the EDID data for any connected display will be
- * read. If successful, then an initial screen mode is set up using the native mode timings
- * of the display. This will result in an initial viewport being defined at base address 0.
- * Details of the initial viewport can be discovered by the caller using the
- * @c dlo_get_mode() call. If no initial mode was set up by libdlo, then the caller must do
- * so by making an appropriate call to @c dlo_set_mode().
- *
- * Setting the screen mode does not result in the screen being cleared; the caller must make
- * a call to @c dlo_fill_rect() to achieve this, e.g.
- *
- * dlo_fill_rect(uid, NULL, NULL, DLO_RGB(0,0,0))
- *
- * to clear the whole of the viewport for the current screen mode to black.
- *
- * Overlapping viewports should be avoided because they do not include the concept of a
- * 'stride' (to get from one pixel to the pixel immediately below). They must also have a
- * base address which starts on a two byte boundary. Aside from these constraints, viewports
- * can be arranged at any locations within the device memory.
- *
- * The caller should not assume anything about the format of the pixels stored in the device
- * memory or how pixels are arranged within a given viewport's address range. It is safe to
- * assume that the pixels will require three bytes each (in a 24 bpp viewport) so a viewport
- * which is 1280 x 1024 pixels in size, starting at base address 0x000000 in the device
- * memory will end at address 1280*1024*3 = 0x3C0000.
- *
- * Thus, the caller may set up two screen banks by maintaining two viewports of the same
- * dimensions, one starting at base address 0x000000 (for example) and another starting at
- * base address 0x3C0000 (assuming they are 1280x1024 pixels in size). These two banks can
- * be plotted to independently of each other and displayed using the @c dlo_set_mode() call.
- */
-typedef struct dlo_view_s
-{
- uint16_t width; /**< Width (pixels). */
- uint16_t height; /**< Height (pixels). */
- uint8_t bpp; /**< Colour depth (bits per pixel). */
- dlo_ptr_t base; /**< Base address in the device memory. */
-} dlo_view_t; /**< A struct @a dlo_view_s. */
-
-
-/** Descriptor for reading or setting the current screen mode. */
-typedef struct dlo_mode_s
-{
- dlo_view_t view; /**< The @a dlo_view_t associated with the screen mode. */
- uint8_t refresh; /**< Refresh rate (Hz). */
-} dlo_mode_t; /**< A struct @a dlo_mode_s. */
-
-
-/** Co-ordinates of a point/pixel relative to the origin, top-left, of a given @a dlo_view_t. */
-typedef struct dlo_dot_s
-{
- int32_t x; /**< X co-ordinate of the dot, pixels from left edge of screen (+ve is right). */
- int32_t y; /**< Y co-ordinate of the dot, pixels down from top edge of screen (-ve is up). */
-} dlo_dot_t; /**< A struct @a dlo_dot_s. */
-
-
-/** A rectangle relative to a given @a dlo_view_t. */
-typedef struct dlo_rect_s
-{
- dlo_dot_t origin; /**< Origin co-ordinates (top-left of the rectangle). */
- uint16_t width; /**< Width (pixels) of rectangle (all pixels from origin.x to origin.x+width-1 inclusive). */
- uint16_t height; /**< Height (pixels) of rectangle (all pixels from origin.y to origin.x+height-1 inclusive). */
-} dlo_rect_t; /**< A struct @a dlo_rect_s. */
-
-
-/** Return the meaning of the specified return code as a human-readable string.
- *
- * @param err Return code.
- *
- * @return Pointer to zero-terminated (error) message string.
- *
- * The string is held in libdlo's static workspace so no attempt should be made
- * by the caller to free it.
- */
-extern const char *dlo_strerror(const dlo_retcode_t err);
-
-
-/** Initialisation call for libdlo.
- *
- * @param flags Initialisation flags word (unused flags should be zero).
- *
- * @return Return code, zero for no error.
- *
- * This function must be called by libdlo users before any other functions
- * are called or they may result in undefined behaviour. It will ignore any
- * flag bits which it does not currently understand.
- *
- * The @a vsn value indicates the library API version number. As the API
- * defined within this header file is evolved, the API version number will
- * be incremented.
- */
-extern dlo_retcode_t dlo_init(const dlo_init_t flags);
-
-
-/** Finalisation call for libdlo.
- *
- * @param flags Finalisation flags word (unused flags should be zero).
- *
- * @return Return code, zero for no error.
- *
- * This function should be called when a program no longer needs to use libdlo
- * (e.g. when it exits) in order to free up any system resources which have been
- * claimed by this library. It will ignore any flag bits which it does not
- * currently understand.
- */
-extern dlo_retcode_t dlo_final(const dlo_final_t flags);
-
-
-/** Map the caller's pointer to a udev structure from libusb to a unique ID in libdlo.
- *
- * @param udev Pointer to USB device structure for given device (from libusb).
- *
- * @return Unique ID of the corresponding device for libdlo calls.
- *
- * This call is intended for use by a caller that has already used libusb in order
- * to identify a particular device that they want to connect to.
- */
-extern dlo_dev_t dlo_lookup_device(struct usb_device *udev);
-
-
-/** Enumerate all connected DisplayLink-compatible devices.
- *
- * @return Pointer to linked list of device information structures (or NULL if none).
- *
- * This function will return a pointer to one or more @a devlist_t structures if
- * there are any active DisplayLink compatible devices connected to the computer.
- * It will return a NULL pointer if none are found or if there was an error during
- * the enumeration process.
- *
- * It is the caller's responsibility to free the memory associated with this list
- * by calling the @c dlo_free() function on each list item (but not for any
- * strings pointed to by items in the list, as these strings are maintained by
- * libdlo).
- */
-extern dlo_devlist_t *dlo_enumerate_devices(void);
-
-
-/** Claim the specified device.
- *
- * @param uid Unique ID of the device to claim.
- * @param flags Flags word describing how the device is to be accessed.
- * @param timeout Timeout in milliseconds (zero for infinite).
- *
- * @return Unique ID of the claimed device (or NULL if failed).
- *
- * Before accessing a device, it should be claimed in order to avoid clashes
- * where multiple programs are trying to write to the same device (however,
- * abstraction of that sort would be implemented above this API).
- *
- * If the device is connected to a display which supports the EDID standard, then
- * this call will also attempt to set up the display mode to the native resolution
- * of the display - equivalent to a call to @c dlo_set_mode(). It will not clear
- * the screen contents; you should call @c dlo_fill_rect() for that.
- *
- * It is possible to specify a @a timeout value for this call. If a non-zero timeout
- * is specified, the same value will be used for any further calls to the device.
- * Passing in a zero timeout means that libdlo should use its default timeouts.
- * The @a timeout value is only used for specific transactions with the device; in
- * some special cases libdlo will still use its own internal timeout values.
- *
- * Devices should be released with a call to @c release_device() when they are no
- * longer required.
- */
+/** @file libdlo.h
+ *
+ * @brief This file defines the high-level API for the DisplayLink libdlo library.
+ *
+ * It is a simplified abstraction layer to allow programs to talk to DisplayLink
+ * compatible devices.
+ *
+ * DisplayLink Open Source Software (libdlo)
+ * Copyright (C) 2009, DisplayLink
+ * www.displaylink.com
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Library General Public License as published by the Free
+ * Software Foundation; LGPL version 2, dated June 1991.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/** @mainpage DisplayLink Open Source Software (libdlo)
+ * @anchor dlppdoxygenmain
+ *
+ * This documentation covers the DisplayLink Open Source Software (libdlo) library (libdlo).
+ * It covers the following items:
+ *
+ * @li File by file information
+ * @li Function by function information
+ * @li Global variables, defines and structures
+ *
+ * <hr>
+ *
+ * <b>Overview</b>
+ *
+ * <p>
+ * This library is stuctured as illustrated below, in order to help clarify the major
+ * functional areas and simplify the task of porting or reimplementing these functions
+ * to other platforms. At the very least, it should serve as a reference implementation
+ * which can be replaced in its entirety.
+ * </p>
+ *
+ * @image html libdlo.gif "libdlo internal structure"
+ *
+ * <p>
+ * All communications with libdlo are through the API published in libdlo.h. This API
+ * allows third party software to find DisplayLink devices, connect to them, perform
+ * graphical operations and then disconnect as required. There are a number of graphical
+ * primitives available, including rectangle plotting and copying (rectangular) areas of
+ * screen.
+ * </p>
+ *
+ * <hr>
+ * <b>Implementation Notes: Functions</b>
+ *
+ * <p>
+ * There are primarily three types of function used within all of the libdlo sources:
+ * </p>
+ *
+ * @li A void function or non-error returning function
+ * @li A pointer-returning function
+ * @li A function returning a return code
+ *
+ * <p>
+ * Void and non-error returning functions are used in situations where there is no
+ * possibility or an error being raised or where there would be no value in returning it.
+ * Examples might include functions which simply perform a computation or those which
+ * dispose of a structure and are expected to fail silently.
+ * </p>
+ *
+ * <p>
+ * Pointer returning functions will conventionally return a NULL pointer if there is
+ * an error. Normally the error will be due to memory allocation failure (out of
+ * memory) but this is not always the case. As a NULL pointer it not very informative
+ * about the nature of the failure, the use of pointer-returning functions within
+ * libdlo has been kept to a minimum.
+ * </p>
+ *
+ * <p>
+ * The majority of functions return an code of type @a dlo_retcode_t to indicate
+ * success or the nature of failure. All return codes have an associated textual string
+ * so they can be decoded in a human-readable format by calling @c dlo_strerror().
+ * </p>
+ *
+ * <hr>
+ * <b>Implementation Notes: Error Handling</b>
+ *
+ * <p>
+ * In order to keep the handling of errors consistent, there are a number of handy
+ * macros defined in dlo_defs.h. There are a few which collect any non-zero return
+ * value from a given function call and return it from the calling function (there
+ * is also a version of this call which checks for NULL pointer returns and converts
+ * it into an memory allocation failure return code). These macros are:
+ * </p>
+ *
+ * @li @c ERR()
+ * @li @c NERR()
+ * @li @c UERR()
+ *
+ * <p>
+ * A second set of macros are defined which, instead of returning a return code from
+ * the calling function, they store the error in a local variable "err" and jump to
+ * a label called "error". This allows the function to perform whatever tidy-up
+ * operations it needs to before returning "err". These macros are:
+ * </p>
+ *
+ * @li @c ERR_GOTO()
+ * @li @c NERR_GOTO()
+ * @li @c UERR_GOTO()
+ *
+ * <p>
+ * Both of these sets of macros are used throughout the libdlo sources in order to
+ * make the handling of errors consistent.
+ * </p>
+ *
+ * <hr>
+ * Copyright &copy; 2008, DisplayLink
+ * All rights reserved.
+ */
+
+#ifndef DLO_LIBDLO_H
+#define DLO_LIBDLO_H /**< Avoid multiple inclusion. */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "usb.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if 0
+#define dlo_malloc my_malloc
+#define dlo_realloc my_realloc
+#define dlo_free my_free
+
+/** Alternative malloc routine.
+ *
+ * @param size As per @c malloc().
+ *
+ * @return As per @c malloc().
+ */
+extern void *my_malloc(size_t size);
+
+/** Alternative realloc routine.
+ *
+ * @param blk As per @c realloc().
+ * @param size As per @c realloc().
+ *
+ * @return As per @c realloc().
+ */
+extern void *my_realloc(void *blk, size_t size);
+
+/** Alternative free routine.
+ *
+ * @param blk As per @c free().
+ */
+extern void my_free(void *blk);
+
+/** Return total size of allocated blocks.
+ *
+ * @return Size of all current allocations (bytes).
+ */
+extern uint32_t my_used(void);
+#endif
+
+
+/** Allow the use of the standard C library @a malloc() function to be overridden.
+ */
+#ifndef dlo_malloc
+#define dlo_malloc malloc
+#endif
+
+/** Allow the use of the standard C library @a realloc() function to be overridden.
+ */
+#ifndef dlo_realloc
+#define dlo_realloc realloc
+#endif
+
+/** Allow the use of the standard C library @a free() function to be overridden.
+ */
+#ifndef dlo_free
+#define dlo_free free
+#endif
+
+/** Allow the use of the standard C library @a memset() function to be overridden.
+ */
+#ifndef dlo_memset
+#define dlo_memset (void) memset
+#endif
+
+/** Allow the use of the standard C library @a memcpy() function to be overridden.
+ */
+#ifndef dlo_memcpy
+#define dlo_memcpy (void) memcpy
+#endif
+
+/** Allow the use of the standard C library @a memmove() function to be overridden.
+ */
+#ifndef dlo_memmove
+#define dlo_memmove (void) memmove
+#endif
+
+
+/** An opaque device handle. */
+typedef void *dlo_dev_t;
+
+
+/** Return codes used within the libdlo sources. Note: libdlo will never return top-bit-set return
+ * codes so these can safely be allocated within your own programs for your own purposes.
+ *
+ * Return code 0x00000000 represents a successful return without error or warning.
+ * Return codes in the range 0x00000001..0x0FFFFFFF represent an error condition.
+ * Return codes in the range 0x10000000..0x7FFFFFFF represent a warning.
+ * Return codes in the range 0x80000000..0xFFFFFFFF are free for caller allocation.
+ */
+typedef enum
+{
+ /* Success... */
+ dlo_ok = 0u, /**< Successful. */
+ /* Errors... */
+ dlo_err_memory = 1u, /**< A memory claim operation failed; out of memory. */
+ dlo_err_bad_area, /**< An invalid area was specified (e.g. of zero width or height). */
+ dlo_err_bad_col, /**< Unsupported colour depth. */
+ dlo_err_bad_device, /**< Unknown device - has been disconnected or powered down. */
+ dlo_err_bad_fbuf, /**< Null pointer passed as local bitmap data. */
+ dlo_err_bad_fmt, /**< Unsupported bitmap pixel format. */
+ dlo_err_bad_mode, /**< Call to @c set_mode() failed due to unsupported mode parameters. */
+ dlo_err_bad_view, /**< Invalid viewport specified (is screen mode set up?). */
+ dlo_err_big_scrape, /**< Bitmap is too wide for copy buffer.*/
+ dlo_err_buf_full, /**< Command buffer is full. */
+ dlo_err_claimed, /**< Device cannot be claimed - it's already been claimed. */
+ dlo_err_edid_fail, /**< EDID communication with monitor failed. */
+ dlo_err_iic_op, /**< An IIC operation with the device failed. */
+ dlo_err_not_root, /**< Executable should be run as root (e.g. using 'su root' or 'sudo'). */
+ dlo_err_open, /**< Attempt to open a connection to the device failed. */
+ dlo_err_overlap, /**< Source and destination viewports cannot overlap (unless the same). */
+ dlo_err_reenum, /**< Reenumeration required before device can be claimed. */
+ dlo_err_unclaimed, /**< Device cannot be written to: unclaimed. */
+ dlo_err_unsupported, /**< Requested feature is not supported. */
+ dlo_err_usb, /**< A USB-related error: call @c dlo_usb_strerror() for further info. */
+ /* Warnings... */
+ dlo_warn_dl160_mode = 0x10000000u, /**< This screen mode may not display correctly on DL120 devices. */
+ /* User return codes... */
+ dlo_user_example = 0x80000000 /**< Return codes 0x80000000 to 0xFFFFFFFF are free for user allocation. */
+} dlo_retcode_t; /**< Return codes. Used to indicate the success or otherwise of a call to the library. */
+
+
+/** A 32 bits per pixel colour number (0x00bbggrr, little endian). Note: most significant byte is undefined. */
+typedef uint32_t dlo_col32_t;
+
+
+/** Return a 32 bpp colour number when given the three RGB components. */
+#define DLO_RGB(red,grn,blu) (dlo_col32_t)(((red) & 0xFF) | (((grn) & 0xFF) << 8) | (((blu) & 0xFF) << 16))
+
+/** Set the red component (0..255) of a 32 bpp colour. */
+#define DLO_RGB_SETRED(col,red) (dlo_col32_t)(((col) & ~0xFF) | ((red) & 0xFF))
+
+/** Set the green component (0..255) of a 32 bpp colour. */
+#define DLO_RGB_SETGRN(col,grn) (dlo_col32_t)(((col) & ~0xFF00) | (((grn) & 0xFF) << 8))
+
+/** Set the blue component (0..255) of a 32 bpp colour. */
+#define DLO_RGB_SETBLU(col,blu) (dlo_col32_t)(((col) & ~0xFF0000) | (((blu) & 0xFF) << 16))
+
+/** Read the red component (0..255) of a 32 bpp colour. */
+#define DLO_RGB_GETRED(col) (uint8_t)((col) & 0xFF)
+
+/** Read the green component (0..255) of a 32 bpp colour. */
+#define DLO_RGB_GETGRN(col) (uint8_t)(((col) >> 8) & 0xFF)
+
+/** Read the blue component (0..255) of a 32 bpp colour. */
+#define DLO_RGB_GETBLU(col) (uint8_t)(((col) >> 16) & 0xFF)
+
+
+/** Types of DisplayLink device. */
+typedef enum
+{
+ dlo_dev_unknown = 0, /**< Unknown device type. */
+ dlo_dev_base = 0xB, /**< Base platform. */
+ dlo_dev_alex = 0xF, /**< Alex chipset. */
+ dlo_dev_ollie = 0xF1 /**< Ollie chipset. */
+} dlo_devtype_t; /**< A struct @a dlo_devtype_s. */
+
+
+/** A structure containing information about a specific device. */
+typedef struct dlo_devinfo_s
+{
+ dlo_dev_t uid; /**< Unique ID for referencing the device. */
+ char *serial; /**< Pointer to serial number string for device. */
+ dlo_devtype_t type; /**< Device type. */
+ bool claimed; /**< Flag indicating whether someone has claimed the device. */
+} dlo_devinfo_t; /**< A struct @a dlo_devinfo_s. */
+
+
+/** A list of devices, as returned by the enumeration call. */
+typedef struct dlo_devlist_s dlo_devlist_t;
+
+/** A list of devices, as returned by the enumeration call. */
+struct dlo_devlist_s
+{
+ dlo_devlist_t *next; /**< Pointer to next node in the device list (or NULL). */
+ dlo_devinfo_t dev; /**< Device information structure. */
+}; /**< A struct @a dlo_devlist_s. */
+
+
+/** Flags word for the initialisation function (no flags defined at present). */
+typedef struct dlo_init_s
+{
+ unsigned undef :1; /**< Undefined flag (placeholder). */
+} dlo_init_t; /**< A struct @a dlo_init_s. */
+
+
+/** Flags word for the finalisation function (no flags defined at present). */
+typedef struct dlo_final_s
+{
+ unsigned undef :1; /**< Undefined flag (placeholder). */
+} dlo_final_t; /**< A struct @a dlo_final_s. */
+
+
+/** Flags word to configure the device connection (no flags defined at present). */
+typedef struct dlo_claim_s
+{
+ unsigned undef :1; /**< Undefined flag (placeholder). */
+} dlo_claim_t; /**< A struct @a dlo_claim_s. */
+
+
+/** Flags word to configure the @c dlo_copy_host_bmp() call. */
+typedef struct dlo_bmpflags_s
+{
+ unsigned v_flip :1; /**< Vertically flip the bitmap during the copy. */
+} dlo_bmpflags_t; /**< A struct @a dlo_bmpflags_s. */
+
+
+/** Shift (bits) for position of bytes-per-pixel data in pixel format word.
+ */
+#define DLO_PIXFMT_BYPP_SFT (6u)
+
+/** Bit mask for extracting bytes-per-pixel data from pixel format word.
+ */
+#define DLO_PIXFMT_BYPP_MSK (0x7 << DLO_PIXFMT_BYPP_SFT)
+
+/** Shift (bits) for position of red/blue swap flag in pixel format word.
+ */
+#define DLO_PIXFMT_SWP_SFT (9u)
+
+/** Shift (bits) for position of pointer data (most significant bits).
+ */
+#define DLO_PIXFMT_PTR_SFT (10u)
+
+/** Maximum number of pixel format variations.
+ */
+#define DLO_PIXFMT_MAX (1u << DLO_PIXFMT_PTR_SFT)
+
+/** Pixel format has one byte per pixel.
+ */
+#define DLO_PIXFMT_1BYPP (1u << DLO_PIXFMT_BYPP_SFT)
+
+/** Pixel format has two bytes per pixel.
+ */
+#define DLO_PIXFMT_2BYPP (2u << DLO_PIXFMT_BYPP_SFT)
+
+/** Pixel format has three bytes per pixel.
+ */
+#define DLO_PIXFMT_3BYPP (3u << DLO_PIXFMT_BYPP_SFT)
+
+/** Pixel format has four bytes per pixel.
+ */
+#define DLO_PIXFMT_4BYPP (4u << DLO_PIXFMT_BYPP_SFT)
+
+/** Pixel format has red and blue colour components reversed.
+ */
+#define DLO_PIXFMT_SWP (1u << DLO_PIXFMT_SWP_SFT)
+
+/** Supported source pixel format information (e.g. bits per pixel, colour component order, etc).
+ *
+ * Each value in this enum encodes the pixel RGB vs BGR colour component order and
+ * the number of bytes per pixel. There is one function for reading each pixel format
+ * (but the RGB vs BGR is passed in as a flag) and the bytes per pixel is required to
+ * advance the pixel pointer in a framebuffer after a pixel has been read.
+ *
+ * Bits 0..5 contain the pixel format code
+ * Bits 6..8 contain the number of bytes per pixel
+ * Bit 9 contains the swap flag for RGB vs BGR
+ * Bits 10.. if non-zero, then the pixel format is actually a pointer to an 8 bit LUT
+ *
+ * The pixel format can also simply be a pointer to a 256 entry LUT of dlo_col32_t
+ * colours in the case where the local framebuffer contains 8bpp bitmap data which
+ * uses a palette. Simply cast the LUT pointer to a dlo_pixfmt_t (this assumes that
+ * your LUT isn't stored in the bottom 1KB of the logical address space!). E.g.
+ *
+ * static dlo_col32_t mylut[256]; // this is the palette for my 8bpp bitmap
+ * static dlo_pixfmt_t mypixfmt = (dlo_pixfmt_t)mylut;
+ */
+typedef enum
+{
+ dlo_pixfmt_bgr323 = 0 | DLO_PIXFMT_1BYPP, /**< 8 bit per pixel 2_bbbggrrr. */
+ dlo_pixfmt_rgb323 = 0 | DLO_PIXFMT_1BYPP | DLO_PIXFMT_SWP, /**< 8 bit per pixel 2_rrrggbbb. */
+ dlo_pixfmt_bgr565 = 1 | DLO_PIXFMT_2BYPP, /**< 16 bit per pixel 2_bbbbbggggggrrrrr. */
+ dlo_pixfmt_rgb565 = 1 | DLO_PIXFMT_2BYPP | DLO_PIXFMT_SWP, /**< 16 bit per pixel 2_rrrrrggggggbbbbb. */
+ dlo_pixfmt_sbgr1555 = 2 | DLO_PIXFMT_2BYPP, /**< 16 bit per pixel 2_Sbbbbbgggggrrrrr (S is supremacy/transparancy bit). */
+ dlo_pixfmt_srgb1555 = 2 | DLO_PIXFMT_2BYPP | DLO_PIXFMT_SWP, /**< 16 bit per pixel 2_Srrrrrgggggbbbbb (S is supremacy/transparancy bit). */
+ dlo_pixfmt_bgr888 = 3 | DLO_PIXFMT_3BYPP, /**< 24 bit per pixel 0xbbggrr. */
+ dlo_pixfmt_rgb888 = 3 | DLO_PIXFMT_3BYPP | DLO_PIXFMT_SWP, /**< 24 bit per pixel 0xrrggbb. */
+ dlo_pixfmt_abgr8888 = 4 | DLO_PIXFMT_4BYPP, /**< 32 bit per pixel 0xaabbggrr. */
+ dlo_pixfmt_argb8888 = 4 | DLO_PIXFMT_4BYPP | DLO_PIXFMT_SWP /**< 32 bit per pixel 0xaarrggbb. */
+ /* Any value greater than 1023 is assumed to be a pointer to: dlo_col32_t palette[256]
+ * for translating paletted 8 bits per pixel data into colour numbers.
+ */
+} dlo_pixfmt_t; /**< A struct @a dlo_pixfmt_s. */
+
+
+/** A local (host-resident) bitmap or framebuffer. */
+typedef struct dlo_fbuf_s
+{
+ uint16_t width; /**< Width (pixels). */
+ uint16_t height; /**< Height (pixels). */
+ dlo_pixfmt_t fmt; /**< Pixel format (e.g. bits per pixel, colour component order, etc). */
+ void *base; /**< Base address in host memory. */
+ uint32_t stride; /**< Stride (pixels) from a pixel to the one directly below. */
+} dlo_fbuf_t; /**< A struct @a dlo_fbuf_s. */
+
+
+/** An pointer to a location in the DisplayLink device logical memory map. */
+typedef uint32_t dlo_ptr_t;
+
+
+/** A viewport (bitmap) in a contiguous block of device memory.
+ *
+ * A viewport describes the contents of a contiguous block of device memory (of which there
+ * is normally 16 MB available). It represents a rectangular bitmap which may be large
+ * enough to use as a screen mode or of any other non-zero size.
+ *
+ * It is the responsibility of the caller to organise one or more viewports in the device
+ * memory and use the @c dlo_set_mode() call to determine which is visible on the screen
+ * at any given time.
+ *
+ * When a device is first claimed, the EDID data for any connected display will be
+ * read. If successful, then an initial screen mode is set up using the native mode timings
+ * of the display. This will result in an initial viewport being defined at base address 0.
+ * Details of the initial viewport can be discovered by the caller using the
+ * @c dlo_get_mode() call. If no initial mode was set up by libdlo, then the caller must do
+ * so by making an appropriate call to @c dlo_set_mode().
+ *
+ * Setting the screen mode does not result in the screen being cleared; the caller must make
+ * a call to @c dlo_fill_rect() to achieve this, e.g.
+ *
+ * dlo_fill_rect(uid, NULL, NULL, DLO_RGB(0,0,0))
+ *
+ * to clear the whole of the viewport for the current screen mode to black.
+ *
+ * Overlapping viewports should be avoided because they do not include the concept of a
+ * 'stride' (to get from one pixel to the pixel immediately below). They must also have a
+ * base address which starts on a two byte boundary. Aside from these constraints, viewports
+ * can be arranged at any locations within the device memory.
+ *
+ * The caller should not assume anything about the format of the pixels stored in the device
+ * memory or how pixels are arranged within a given viewport's address range. It is safe to
+ * assume that the pixels will require three bytes each (in a 24 bpp viewport) so a viewport
+ * which is 1280 x 1024 pixels in size, starting at base address 0x000000 in the device
+ * memory will end at address 1280*1024*3 = 0x3C0000.
+ *
+ * Thus, the caller may set up two screen banks by maintaining two viewports of the same
+ * dimensions, one starting at base address 0x000000 (for example) and another starting at
+ * base address 0x3C0000 (assuming they are 1280x1024 pixels in size). These two banks can
+ * be plotted to independently of each other and displayed using the @c dlo_set_mode() call.
+ */
+typedef struct dlo_view_s
+{
+ uint16_t width; /**< Width (pixels). */
+ uint16_t height; /**< Height (pixels). */
+ uint8_t bpp; /**< Colour depth (bits per pixel). */
+ dlo_ptr_t base; /**< Base address in the device memory. */
+} dlo_view_t; /**< A struct @a dlo_view_s. */
+
+
+/** Descriptor for reading or setting the current screen mode. */
+typedef struct dlo_mode_s
+{
+ dlo_view_t view; /**< The @a dlo_view_t associated with the screen mode. */
+ uint8_t refresh; /**< Refresh rate (Hz). */
+} dlo_mode_t; /**< A struct @a dlo_mode_s. */
+
+
+/** Co-ordinates of a point/pixel relative to the origin, top-left, of a given @a dlo_view_t. */
+typedef struct dlo_dot_s
+{
+ int32_t x; /**< X co-ordinate of the dot, pixels from left edge of screen (+ve is right). */
+ int32_t y; /**< Y co-ordinate of the dot, pixels down from top edge of screen (-ve is up). */
+} dlo_dot_t; /**< A struct @a dlo_dot_s. */
+
+
+/** A rectangle relative to a given @a dlo_view_t. */
+typedef struct dlo_rect_s
+{
+ dlo_dot_t origin; /**< Origin co-ordinates (top-left of the rectangle). */
+ uint16_t width; /**< Width (pixels) of rectangle (all pixels from origin.x to origin.x+width-1 inclusive). */
+ uint16_t height; /**< Height (pixels) of rectangle (all pixels from origin.y to origin.x+height-1 inclusive). */
+} dlo_rect_t; /**< A struct @a dlo_rect_s. */
+
+
+/** Return the meaning of the specified return code as a human-readable string.
+ *
+ * @param err Return code.
+ *
+ * @return Pointer to zero-terminated (error) message string.
+ *
+ * The string is held in libdlo's static workspace so no attempt should be made
+ * by the caller to free it.
+ */
+extern const char *dlo_strerror(const dlo_retcode_t err);
+
+
+/** Initialisation call for libdlo.
+ *
+ * @param flags Initialisation flags word (unused flags should be zero).
+ *
+ * @return Return code, zero for no error.
+ *
+ * This function must be called by libdlo users before any other functions
+ * are called or they may result in undefined behaviour. It will ignore any
+ * flag bits which it does not currently understand.
+ *
+ * The @a vsn value indicates the library API version number. As the API
+ * defined within this header file is evolved, the API version number will
+ * be incremented.
+ */
+extern dlo_retcode_t dlo_init(const dlo_init_t flags);
+
+
+/** Finalisation call for libdlo.
+ *
+ * @param flags Finalisation flags word (unused flags should be zero).
+ *
+ * @return Return code, zero for no error.
+ *
+ * This function should be called when a program no longer needs to use libdlo
+ * (e.g. when it exits) in order to free up any system resources which have been
+ * claimed by this library. It will ignore any flag bits which it does not
+ * currently understand.
+ */
+extern dlo_retcode_t dlo_final(const dlo_final_t flags);
+
+
+/** Map the caller's pointer to a udev structure from libusb to a unique ID in libdlo.
+ *
+ * @param udev Pointer to USB device structure for given device (from libusb).
+ *
+ * @return Unique ID of the corresponding device for libdlo calls.
+ *
+ * This call is intended for use by a caller that has already used libusb in order
+ * to identify a particular device that they want to connect to.
+ */
+extern dlo_dev_t dlo_lookup_device(struct usb_device *udev);
+
+
+/** Enumerate all connected DisplayLink-compatible devices.
+ *
+ * @return Pointer to linked list of device information structures (or NULL if none).
+ *
+ * This function will return a pointer to one or more @a devlist_t structures if
+ * there are any active DisplayLink compatible devices connected to the computer.
+ * It will return a NULL pointer if none are found or if there was an error during
+ * the enumeration process.
+ *
+ * It is the caller's responsibility to free the memory associated with this list
+ * by calling the @c dlo_free() function on each list item (but not for any
+ * strings pointed to by items in the list, as these strings are maintained by
+ * libdlo).
+ */
+extern dlo_devlist_t *dlo_enumerate_devices(void);
+
+
+/** Claim the specified device.
+ *
+ * @param uid Unique ID of the device to claim.
+ * @param flags Flags word describing how the device is to be accessed.
+ * @param timeout Timeout in milliseconds (zero for infinite).
+ *
+ * @return Unique ID of the claimed device (or NULL if failed).
+ *
+ * Before accessing a device, it should be claimed in order to avoid clashes
+ * where multiple programs are trying to write to the same device (however,
+ * abstraction of that sort would be implemented above this API).
+ *
+ * If the device is connected to a display which supports the EDID standard, then
+ * this call will also attempt to set up the display mode to the native resolution
+ * of the display - equivalent to a call to @c dlo_set_mode(). It will not clear
+ * the screen contents; you should call @c dlo_fill_rect() for that.
+ *
+ * It is possible to specify a @a timeout value for this call. If a non-zero timeout
+ * is specified, the same value will be used for any further calls to the device.
+ * Passing in a zero timeout means that libdlo should use its default timeouts.
+ * The @a timeout value is only used for specific transactions with the device; in
+ * some special cases libdlo will still use its own internal timeout values.
+ *
+ * Devices should be released with a call to @c release_device() when they are no
+ * longer required.
+ */
extern dlo_dev_t dlo_claim_device(const dlo_dev_t uid, const dlo_claim_t flags, const uint32_t timeout);
@@ -632,150 +632,150 @@ extern dlo_dev_t dlo_claim_default_device(int *argc_p, char *argv[],
/** Release the specified device.
- *
- * @param uid Unique ID of the device to release.
- *
- * @return Return code, zero for no error.
- *
- * When a program is no longer interested in using a device which it earlier had
- * claimed, it should release it with this call. This should still be called even
- * in the case where communications with a device have failed (because the error
- * may have been temporary). You can ignore errors from this call if you wish.
- */
-extern dlo_retcode_t dlo_release_device(const dlo_dev_t uid);
-
-
-/** Given the device unique ID, return the associated device information structure.
- *
- * @param uid Unique ID of the device to access.
- *
- * @return Pointer to device information structure.
- *
- * Note: the caller should not attempt to free the returned structure as it is
- * maintained by libdlo.
- */
-extern dlo_devinfo_t *dlo_device_info(const dlo_dev_t uid);
-
-
-/** Set the screen mode by selecting the best matching mode available.
- *
- * @param uid Unique ID of the device to access.
- * @param mode Mode descriptor structure pointer.
- *
- * @return Return code, zero for no error.
- *
- * This function will select a screen mode from the list of those supported by
- * the specified device (if the display connected to a device supports EDID,
- * then the supported mode list will be derived from the EDID information).
- *
- * The @a mode parameter describes the desired mode parameters, some of which
- * are optional and may be left as zero/NULL:
- *
- * @li width in pixels (always required)
- * @li height in pixels (or zero to use first available of specified width)
- * @li colour depth in bits per pixel (currently, only 24 is supported)
- * @li base address in the device memory (of the origin of the mode's viewport)
- * @li refresh rate, in Hz (or zero to select the first available)
- *
- * This call will not cause the screen area to be cleared to a 'background'
- * colour.
- */
-extern dlo_retcode_t dlo_set_mode(const dlo_dev_t uid, const dlo_mode_t * const mode);
-
-
-/** Returns a block of information about the current screen mode.
- *
- * @param uid Unique ID of the device to access (or zero).
- *
- * @return Pointer to a mode description structure.
- *
- * This function will return a pointer to a structure describing the current
- * screen mode for the specified device. Note: if no mode has been set since
- * the device was claimed, this structure will be initialised to contain all
- * zeros.
- *
- * Note: the caller should not attempt to free the returned structure as it
- * is maintained by libdlo.
- */
-extern dlo_mode_t *dlo_get_mode(const dlo_dev_t uid);
-
-
-/** Plot a filled rectangle into the specified device.
- *
- * @param uid Unique ID of the device to access.
- * @param view Struct pointer: the destination viewport.
- * @param rec Struct pointer: co-ordinates of rectangle to plot (relative to viewport).
- * @param col Colour of filled rectangle.
- *
- * @return Return code, zero for no error.
- *
- * Plot a filled rectangle in the specified colour into a viewport on the device. The
- * rectangle specified is relative to the viewport's origin and will be clipped if any
- * parts of it lie outside of the viewport's extent. Setting both @a view and @a rec to
- * NULL will effectively clear the current screen to the specified colour.
- *
- * If @a view is NULL, then the current visible screen is used as the destination viewport.
- * If @a rec is NULL, then the whole of the destination viewport is filled.
- */
-extern dlo_retcode_t dlo_fill_rect(const dlo_dev_t uid,
- const dlo_view_t * const view, const dlo_rect_t * const rec,
- const dlo_col32_t col);
-
-
-/** Copy a rectangular area within the device from one location to another.
- *
- * @param uid Unique ID of the device to access.
- * @param src_view Struct pointer: source viewport.
- * @param src_rec Struct pointer: co-ordinates of rectangle to copy (relative to source viewport).
- * @param dest_view Struct pointer: destination viewport.
- * @param dest_pos Struct pointer: origin of copy destination (relative to destination viewport).
- *
- * @return Return code, zero for no error.
- *
- * Copy a rectangular area of pixels from one location in the device to another. The source
- * and destination rectangles may lie in the same viewport or different viewports - it is up
- * to the caller to maintain their own list of how the device memory is organised in terms of
- * viewports.
- *
- * The source and destination viewports must not reference overlapping memory regions in the
- * device, except in the case where both viewports describe exactly the same memory region.
- * There are no constraints relating to whether or not source and destination rectangles
- * overlap.
- *
- * If @a src_view is NULL, then the current visible screen is used as the source viewport.
- * If @a src_rec is NULL, then the whole of the source viewport is used as the source rectangle.
- * If @a dest_view is NULL, then the current visible screen is used as the destination viewport.
- * If @a dest_pos is NULL, then the origin (top-left) of the destination viewport is used.
- */
-extern dlo_retcode_t dlo_copy_rect(const dlo_dev_t uid,
- const dlo_view_t * const src_view, const dlo_rect_t * const src_rec,
- const dlo_view_t * const dest_view, const dlo_dot_t * const dest_pos);
-
-
-/** Copy (and translate pixel formats) a rectangular area from host memory into the device.
- *
- * @param uid Unique ID of the device to access.
- * @param flags Flags word indicating special behaviour (unused flags should be zero).
- * @param fbuf Struct pointer: information about source bitmap in host memory.
- * @param dest_view Struct pointer: destination viewport.
- * @param dest_pos Struct pointer: origin of copy destination (relative to destination viewport).
- *
- * @return Return code, zero for no error.
- *
- * Transfer a bitmap held in the host memory to the device. The bitmap is treated as a rectangular
- * area of pixels, possibly within a larger bitmap/framebuffer and will be plotted at the desired
- * co-ordinates relative to the origin of the specified viewport. If any part of the bitmap falls
- * outside of the viewport's extent, the region will be clipped.
- *
- * If @a dest_view is NULL, then the current visible screen is used as the destination viewport.
- * If @a dest_pos is NULL, then the origin (top-left) of the destination viewport is used.
- */
-extern dlo_retcode_t dlo_copy_host_bmp(const dlo_dev_t uid, const dlo_bmpflags_t flags,
- const dlo_fbuf_t * const fbuf,
- const dlo_view_t * const dest_view, const dlo_dot_t * const dest_pos);
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif
+ *
+ * @param uid Unique ID of the device to release.
+ *
+ * @return Return code, zero for no error.
+ *
+ * When a program is no longer interested in using a device which it earlier had
+ * claimed, it should release it with this call. This should still be called even
+ * in the case where communications with a device have failed (because the error
+ * may have been temporary). You can ignore errors from this call if you wish.
+ */
+extern dlo_retcode_t dlo_release_device(const dlo_dev_t uid);
+
+
+/** Given the device unique ID, return the associated device information structure.
+ *
+ * @param uid Unique ID of the device to access.
+ *
+ * @return Pointer to device information structure.
+ *
+ * Note: the caller should not attempt to free the returned structure as it is
+ * maintained by libdlo.
+ */
+extern dlo_devinfo_t *dlo_device_info(const dlo_dev_t uid);
+
+
+/** Set the screen mode by selecting the best matching mode available.
+ *
+ * @param uid Unique ID of the device to access.
+ * @param mode Mode descriptor structure pointer.
+ *
+ * @return Return code, zero for no error.
+ *
+ * This function will select a screen mode from the list of those supported by
+ * the specified device (if the display connected to a device supports EDID,
+ * then the supported mode list will be derived from the EDID information).
+ *
+ * The @a mode parameter describes the desired mode parameters, some of which
+ * are optional and may be left as zero/NULL:
+ *
+ * @li width in pixels (always required)
+ * @li height in pixels (or zero to use first available of specified width)
+ * @li colour depth in bits per pixel (currently, only 24 is supported)
+ * @li base address in the device memory (of the origin of the mode's viewport)
+ * @li refresh rate, in Hz (or zero to select the first available)
+ *
+ * This call will not cause the screen area to be cleared to a 'background'
+ * colour.
+ */
+extern dlo_retcode_t dlo_set_mode(const dlo_dev_t uid, const dlo_mode_t * const mode);
+
+
+/** Returns a block of information about the current screen mode.
+ *
+ * @param uid Unique ID of the device to access (or zero).
+ *
+ * @return Pointer to a mode description structure.
+ *
+ * This function will return a pointer to a structure describing the current
+ * screen mode for the specified device. Note: if no mode has been set since
+ * the device was claimed, this structure will be initialised to contain all
+ * zeros.
+ *
+ * Note: the caller should not attempt to free the returned structure as it
+ * is maintained by libdlo.
+ */
+extern dlo_mode_t *dlo_get_mode(const dlo_dev_t uid);
+
+
+/** Plot a filled rectangle into the specified device.
+ *
+ * @param uid Unique ID of the device to access.
+ * @param view Struct pointer: the destination viewport.
+ * @param rec Struct pointer: co-ordinates of rectangle to plot (relative to viewport).
+ * @param col Colour of filled rectangle.
+ *
+ * @return Return code, zero for no error.
+ *
+ * Plot a filled rectangle in the specified colour into a viewport on the device. The
+ * rectangle specified is relative to the viewport's origin and will be clipped if any
+ * parts of it lie outside of the viewport's extent. Setting both @a view and @a rec to
+ * NULL will effectively clear the current screen to the specified colour.
+ *
+ * If @a view is NULL, then the current visible screen is used as the destination viewport.
+ * If @a rec is NULL, then the whole of the destination viewport is filled.
+ */
+extern dlo_retcode_t dlo_fill_rect(const dlo_dev_t uid,
+ const dlo_view_t * const view, const dlo_rect_t * const rec,
+ const dlo_col32_t col);
+
+
+/** Copy a rectangular area within the device from one location to another.
+ *
+ * @param uid Unique ID of the device to access.
+ * @param src_view Struct pointer: source viewport.
+ * @param src_rec Struct pointer: co-ordinates of rectangle to copy (relative to source viewport).
+ * @param dest_view Struct pointer: destination viewport.
+ * @param dest_pos Struct pointer: origin of copy destination (relative to destination viewport).
+ *
+ * @return Return code, zero for no error.
+ *
+ * Copy a rectangular area of pixels from one location in the device to another. The source
+ * and destination rectangles may lie in the same viewport or different viewports - it is up
+ * to the caller to maintain their own list of how the device memory is organised in terms of
+ * viewports.
+ *
+ * The source and destination viewports must not reference overlapping memory regions in the
+ * device, except in the case where both viewports describe exactly the same memory region.
+ * There are no constraints relating to whether or not source and destination rectangles
+ * overlap.
+ *
+ * If @a src_view is NULL, then the current visible screen is used as the source viewport.
+ * If @a src_rec is NULL, then the whole of the source viewport is used as the source rectangle.
+ * If @a dest_view is NULL, then the current visible screen is used as the destination viewport.
+ * If @a dest_pos is NULL, then the origin (top-left) of the destination viewport is used.
+ */
+extern dlo_retcode_t dlo_copy_rect(const dlo_dev_t uid,
+ const dlo_view_t * const src_view, const dlo_rect_t * const src_rec,
+ const dlo_view_t * const dest_view, const dlo_dot_t * const dest_pos);
+
+
+/** Copy (and translate pixel formats) a rectangular area from host memory into the device.
+ *
+ * @param uid Unique ID of the device to access.
+ * @param flags Flags word indicating special behaviour (unused flags should be zero).
+ * @param fbuf Struct pointer: information about source bitmap in host memory.
+ * @param dest_view Struct pointer: destination viewport.
+ * @param dest_pos Struct pointer: origin of copy destination (relative to destination viewport).
+ *
+ * @return Return code, zero for no error.
+ *
+ * Transfer a bitmap held in the host memory to the device. The bitmap is treated as a rectangular
+ * area of pixels, possibly within a larger bitmap/framebuffer and will be plotted at the desired
+ * co-ordinates relative to the origin of the specified viewport. If any part of the bitmap falls
+ * outside of the viewport's extent, the region will be clipped.
+ *
+ * If @a dest_view is NULL, then the current visible screen is used as the destination viewport.
+ * If @a dest_pos is NULL, then the origin (top-left) of the destination viewport is used.
+ */
+extern dlo_retcode_t dlo_copy_host_bmp(const dlo_dev_t uid, const dlo_bmpflags_t flags,
+ const dlo_fbuf_t * const fbuf,
+ const dlo_view_t * const dest_view, const dlo_dot_t * const dest_pos);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif