Add a simple usb_mode_switch clone for am7xxx devices
authorAntonio Ospite <ospite@studenti.unina.it>
Fri, 11 May 2012 19:50:36 +0000 (21:50 +0200)
committerAntonio Ospite <ospite@studenti.unina.it>
Fri, 11 May 2012 19:50:36 +0000 (21:50 +0200)
Add am7xxx_mode_switch, this is will be used on systems where
usb_mode_switch is not easily available (e.g. MS Windows).

examples/CMakeLists.txt
examples/am7xxx_mode_switch.c [new file with mode: 0644]

index b7941ab..7e7b455 100644 (file)
@@ -49,3 +49,17 @@ if(BUILD_AM7XXX-PLAY)
   install(TARGETS am7xxx-play
     DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
 endif()
+
+# Build a simple usb_mode_switch clone for am7xxx devices
+option(BUILD_AM7XXX_MODE_SWITCH "Build a simple usb_mode_switch clone for am7xxx devices" TRUE)
+if(BUILD_AM7XXX_MODE_SWITCH)
+
+  find_package(libusb-1.0 REQUIRED)
+  include_directories(${LIBUSB_1_INCLUDE_DIRS})
+
+  add_executable(am7xxx_mode_switch am7xxx_mode_switch.c)
+  target_link_libraries(am7xxx_mode_switch ${LIBUSB_1_LIBRARIES})
+  install(TARGETS am7xxx_mode_switch
+    DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
+endif()
+
diff --git a/examples/am7xxx_mode_switch.c b/examples/am7xxx_mode_switch.c
new file mode 100644 (file)
index 0000000..7509981
--- /dev/null
@@ -0,0 +1,97 @@
+/* am7xxx_mode_switch - a simple usb_mode_switch for am7xxx devices
+ *
+ * Copyright (C) 2012  Antonio Ospite <ospite@studenti.unina.it>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <libusb.h>
+
+#define AM7XXX_STORAGE_VID           0x1de1
+#define AM7XXX_STORAGE_PID           0x1101
+#define AM7XXX_STORAGE_CONFIGURATION 1
+#define AM7XXX_STORAGE_INTERFACE     0
+#define AM7XXX_STORAGE_OUT_EP        0x01
+
+static unsigned char switch_command[] =
+       "\x55\x53\x42\x43\x08\x70\x52\x89\x00\x00\x00\x00\x00\x00"
+       "\x0c\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+
+int main(void)
+{
+       int ret;
+       int transferred;
+       libusb_device_handle *usb_device = NULL;
+
+       unsigned int len;
+
+       ret = libusb_init(NULL);
+       if (ret < 0)
+               goto out;
+
+       libusb_set_debug(NULL, 3);
+
+       usb_device = libusb_open_device_with_vid_pid(NULL,
+                                                    AM7XXX_STORAGE_VID,
+                                                    AM7XXX_STORAGE_PID);
+       if (usb_device == NULL) {
+               fprintf(stderr, "cannot open the device: %d.\n", errno);
+               ret = -errno;
+               goto out;
+       }
+
+       if (libusb_kernel_driver_active(usb_device, AM7XXX_STORAGE_INTERFACE)) {
+               ret = libusb_detach_kernel_driver(usb_device,
+                                                 AM7XXX_STORAGE_INTERFACE);
+               if (ret < 0)
+                       fprintf(stderr, "Warning: cannot detach kernel driver.\n");
+       } else {
+               fprintf(stderr, "kernel driver not active.\n");
+       }
+
+       ret = libusb_set_configuration(usb_device, AM7XXX_STORAGE_CONFIGURATION);
+       if (ret < 0) {
+               fprintf(stderr, "cannot set configuration.\n");
+               goto out_libusb_close;
+       }
+
+       ret = libusb_claim_interface(usb_device, AM7XXX_STORAGE_INTERFACE);
+       if (ret < 0) {
+               fprintf(stderr, "cannot claim interface.\n");
+               goto out_libusb_close;
+       }
+
+       len = sizeof(switch_command);
+       transferred = 0;
+       ret = libusb_bulk_transfer(usb_device, AM7XXX_STORAGE_OUT_EP,
+                                  switch_command, len, &transferred, 0);
+       if (ret != 0 || (unsigned int)transferred != len) {
+               fprintf(stderr, "ret: %d\ttransferred: %d (expected %u)\n",
+                     ret, transferred, len);
+               goto out_libusb_close;
+       }
+
+       fprintf(stderr, "OK, command sent!\n");
+
+out_libusb_close:
+       libusb_release_interface(usb_device, AM7XXX_STORAGE_INTERFACE);
+       libusb_close(usb_device);
+       usb_device = NULL;
+
+out:
+       libusb_exit(NULL);
+       return ret;
+}