libam7xxx  0.1
Communication library for Actions Micro AM7XXX based USB projectors and DPFs
am7xxx-modeswitch.c
1 /* am7xxx-modeswitch - a simple usb-modeswitch for am7xxx devices
2  *
3  * Copyright (C) 2012-2014 Antonio Ospite <ao2@ao2.it>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include <stdio.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <libusb.h>
23 
24 #define AM7XXX_STORAGE_VID 0x1de1
25 #define AM7XXX_STORAGE_PID 0x1101
26 #define AM7XXX_STORAGE_CONFIGURATION 1
27 #define AM7XXX_STORAGE_INTERFACE 0
28 #define AM7XXX_STORAGE_OUT_EP 0x01
29 
30 static unsigned char switch_command[] =
31  "\x55\x53\x42\x43\x08\x70\x52\x89\x00\x00\x00\x00\x00\x00"
32  "\x10\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
33 
34 int main(void)
35 {
36  int ret;
37  libusb_device_handle *usb_device;
38  int current_configuration;
39  unsigned int len;
40  int transferred;
41 
42  ret = libusb_init(NULL);
43  if (ret < 0) {
44  fprintf(stderr, "libusb_init failed: %s\n",
45  libusb_error_name(ret));
46  goto out;
47  }
48 
49  libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_INFO);
50 
51  usb_device = libusb_open_device_with_vid_pid(NULL,
52  AM7XXX_STORAGE_VID,
53  AM7XXX_STORAGE_PID);
54  if (usb_device == NULL) {
55  fprintf(stderr, "libusb_open failed: %s\n", strerror(errno));
56  ret = -errno;
57  goto out;
58  }
59 
60  current_configuration = -1;
61  ret = libusb_get_configuration(usb_device, &current_configuration);
62  if (ret < 0) {
63  fprintf(stderr, "libusb_get_configuration failed: %s\n",
64  libusb_error_name(ret));
65  goto out_libusb_close;
66  }
67 
68  if (current_configuration != AM7XXX_STORAGE_CONFIGURATION) {
69  ret = libusb_set_configuration(usb_device,
70  AM7XXX_STORAGE_CONFIGURATION);
71  if (ret < 0) {
72  fprintf(stderr, "libusb_set_configuration failed: %s\n",
73  libusb_error_name(ret));
74  fprintf(stderr, "Cannot set configuration %d\n",
75  AM7XXX_STORAGE_CONFIGURATION);
76  goto out_libusb_close;
77  }
78  }
79 
80  libusb_set_auto_detach_kernel_driver(usb_device, 1);
81 
82  ret = libusb_claim_interface(usb_device, AM7XXX_STORAGE_INTERFACE);
83  if (ret < 0) {
84  fprintf(stderr, "libusb_claim_interface failed: %s\n",
85  libusb_error_name(ret));
86  fprintf(stderr, "Cannot claim interface %d\n",
87  AM7XXX_STORAGE_INTERFACE);
88  goto out_libusb_close;
89  }
90 
91  /*
92  * Checking that the configuration has not changed, as suggested in
93  * http://libusb.sourceforge.net/api-1.0/caveats.html
94  */
95  current_configuration = -1;
96  ret = libusb_get_configuration(usb_device, &current_configuration);
97  if (ret < 0) {
98  fprintf(stderr, "libusb_get_configuration after claim failed: %s\n",
99  libusb_error_name(ret));
100  goto out_libusb_release_interface;
101  }
102 
103  if (current_configuration != AM7XXX_STORAGE_CONFIGURATION) {
104  fprintf(stderr, "libusb configuration changed (expected: %d, current: %d)\n",
105  AM7XXX_STORAGE_CONFIGURATION, current_configuration);
106  ret = -EINVAL;
107  goto out_libusb_release_interface;
108  }
109 
110  len = sizeof(switch_command);
111 
112  transferred = 0;
113  ret = libusb_bulk_transfer(usb_device, AM7XXX_STORAGE_OUT_EP,
114  switch_command, len, &transferred, 0);
115  if (ret != 0 || (unsigned int)transferred != len) {
116  fprintf(stderr, "ret: %d\ttransferred: %d (expected %u)\n",
117  ret, transferred, len);
118  goto out_libusb_release_interface;
119  }
120 
121  fprintf(stderr, "OK, command sent!\n");
122 
123 out_libusb_release_interface:
124  libusb_release_interface(usb_device, AM7XXX_STORAGE_INTERFACE);
125 out_libusb_close:
126  libusb_close(usb_device);
127  usb_device = NULL;
128 out:
129  libusb_exit(NULL);
130  return ret;
131 }