summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--utils/MTP/beastpatcher/Makefile52
-rw-r--r--utils/MTP/beastpatcher/README61
-rw-r--r--utils/MTP/beastpatcher/TODO17
-rw-r--r--utils/MTP/beastpatcher/beastpatcher.c221
-rw-r--r--utils/MTP/beastpatcher/mtp_common.h71
-rw-r--r--utils/MTP/beastpatcher/mtp_libmtp.c174
6 files changed, 596 insertions, 0 deletions
diff --git a/utils/MTP/beastpatcher/Makefile b/utils/MTP/beastpatcher/Makefile
new file mode 100644
index 0000000000..edd08b1248
--- /dev/null
+++ b/utils/MTP/beastpatcher/Makefile
@@ -0,0 +1,52 @@
1CFLAGS=-Wall -W
2
3ifeq ($(findstring CYGWIN,$(shell uname)),CYGWIN)
4OUTPUT=beastpatcher.exe
5CROSS=
6else
7OUTPUT=beastpatcher
8CROSS=i586-mingw32msvc-
9endif
10
11ifeq ($(OUTPUT),beastpatcher)
12LIBS = /usr/lib/libmtp.a /usr/lib/libusb.a
13CFLAGS += $(shell printf \
14 '\#include <libmtp.h>\nlibmtp version: LIBMTP_VERSION\n' | \
15 gcc -E -P - -o - | grep -q '^libmtp version: 0\.2' && echo '-DOLDMTP')
16else
17CFLAGS+=-mno-cygwin
18LIBS = ../MTP_DLL.dll
19endif
20
21NATIVECC = gcc
22CC = $(CROSS)gcc
23
24all: $(OUTPUT)
25
26beastpatcher: beastpatcher.c bootimg.c mtp_common.h mtp_libmtp.c
27 gcc $(CFLAGS) -o beastpatcher beastpatcher.c bootimg.c mtp_libmtp.c $(LIBS)
28 strip beastpatcher
29
30beastpatcher.exe: beastpatcher.c bootimg.c mtp_common.h mtp_win32.c $(LIBS)
31 $(CROSS)$(CC) $(CFLAGS) $(LIBS) -o beastpatcher.exe beastpatcher.c bootimg.c
32 $(CROSS)strip beastpatcher.exe
33
34beastpatcher-mac: beastpatcher-i386 beastpatcher-ppc
35 lipo -create beastpatcher-ppc beastpatcher-i386 -output beastpatcher-mac
36
37beastpatcher-i386: beastpatcher.c bootimg.c usb.h libusb-i386.a
38 $(CC) -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 -framework iokit -framework coreservices -arch i386 $(CFLAGS) -o beastpatcher-i386 beastpatcher.c bootimg.c -I. libusb-i386.a
39 strip beastpatcher-i386
40
41beastpatcher-ppc: beastpatcher.c bootimg.c usb.h libusb-ppc.a
42 $(CC) -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 -framework iokit -framework coreservices -arch ppc $(CFLAGS) -o beastpatcher-ppc beastpatcher.c bootimg.c -I. libusb-ppc.a
43 strip beastpatcher-ppc
44
45bin2c: ../../../rbutil/sansapatcher/bin2c.c
46 $(NATIVECC) $(CFLAGS) -o bin2c ../../../rbutil/sansapatcher/bin2c.c
47
48bootimg.c: bootloader.bin bin2c
49 ./bin2c bootloader.bin bootimg
50
51clean:
52 rm -f beastpatcher.exe beastpatcher-mac beastpatcher-i386 beastpatcher-ppc beastpatcher bin2c bootimg.c bootimg.h *~
diff --git a/utils/MTP/beastpatcher/README b/utils/MTP/beastpatcher/README
new file mode 100644
index 0000000000..85a039268a
--- /dev/null
+++ b/utils/MTP/beastpatcher/README
@@ -0,0 +1,61 @@
1beastpatcher - a tool for installing the Rockbox bootloader on the Gigabeat S
2
3Unlike most other parts of the Rockbox project, this tool is
4distributed under the BSD license. This is due to the fact that the
5Windows version links with the Microsoft MTP library.
6
7
8
9Building instructions - All OSes
10--------------------------------
11
12For all versions, you need to copy a "bootloader.bin" file (containing
13the Rockbox bootloader) into this directory.
14
15This can be built from the Rockbox source by selecting "41" and then
16"B" when running tools/configure.
17
18You need the Rockbox toolchain to build any Rockbox target binaries -
19this can be downloaded and built with the tools/rockboxdev.sh script.
20
21The latest officially released bootloader can always be downloaded from:
22
23http://download.rockbox.org/bootloader/gigabeat-s/
24
25
26
27Linux
28-----
29
30The Unix versions requires libmtp, which in turn requires libusb.
31
32beastpatcher is built to statically link to these libraries and
33expects them to exist as /usr/lib/libmtp.a and /usr/lib/libusb.a
34respectively. Change the definition of LIBS in the Makefile if this
35is not the case for your system.
36
37After this, just type "make" to get a
38
39
40
41OS X
42----
43
44[Not yet implemented]
45
46The OS X build is a universal binary statically linked with libusb and libmtp.
47
48
49
50Windows
51-------
52
53[Not yet implemented]
54
55The MTP_DLL.dll requires VC2005 to compile - see instructions in
56MTP_DLL/README
57
58To compile beastpatcher itself, you can either cross-compile from
59Linux using the mingw32 package, or compile in Cygwin. Just type
60"make beastpatcher.exe" (in Linux) or "make" (in Cygwin).
61
diff --git a/utils/MTP/beastpatcher/TODO b/utils/MTP/beastpatcher/TODO
new file mode 100644
index 0000000000..717a77e7c8
--- /dev/null
+++ b/utils/MTP/beastpatcher/TODO
@@ -0,0 +1,17 @@
1Basic implementation:
2
3* Windows support - need to expand API provided by MTP_DLL.dll
4* OS X support - need to statically link against libusb and libmtp
5* Load bootloader.bin from a file
6
7Ideas for future features:
8
9* Dual-boot. Look for nk.bin in current directory, and check its
10 md5sum to confirm it's an original firmware. Possibly include
11 override for user-modified OFs, and option for user to specify an
12 alternate location.
13
14 This will give the user three options - rockbox only, OF only
15 (i.e. uninstall) or dual-boot. It would be easy to give the choice
16 of two boot orders (RB on hold or OF on hold) if that was desired.
17
diff --git a/utils/MTP/beastpatcher/beastpatcher.c b/utils/MTP/beastpatcher/beastpatcher.c
new file mode 100644
index 0000000000..8043ebadc2
--- /dev/null
+++ b/utils/MTP/beastpatcher/beastpatcher.c
@@ -0,0 +1,221 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * $Id:$
10 *
11 * Copyright (c) 2009, Dave Chapman
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met:
17 *
18 * * Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * * Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials provided
24 * with the distribution.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 *
38 ****************************************************************************/
39
40#include <stdio.h>
41#include <unistd.h>
42#include <fcntl.h>
43#include <string.h>
44#include <stdlib.h>
45#include <inttypes.h>
46#include <sys/types.h>
47#include <sys/stat.h>
48
49#include "mtp_common.h"
50#include "bootimg.h"
51
52#define VERSION "1.0 with v1 bootloader"
53
54void print_usage(void)
55{
56 fprintf(stderr,"Usage: beastpatcher [action]\n");
57 fprintf(stderr,"\n");
58 fprintf(stderr,"Where [action] is one of the following options:\n");
59 fprintf(stderr," --install (default)\n");
60 fprintf(stderr," -?, --help\n");
61 fprintf(stderr,"\n");
62}
63
64/* Code to create a single-boot bootloader.
65 Based on tools/gigabeats.c by Will Robertson.
66*/
67
68/* Entry point (and load address) for the main Rockbox bootloader */
69#define BL_ENTRY_POINT 0x8a000000
70
71static void put_uint32le(uint32_t x, unsigned char* p)
72{
73 p[0] = x & 0xff;
74 p[1] = (x >> 8) & 0xff;
75 p[2] = (x >> 16) & 0xff;
76 p[3] = (x >> 24) & 0xff;
77}
78
79static uint32_t calc_csum(const unsigned char* pb, int cb)
80{
81 uint32_t l = 0;
82 while (cb--)
83 l += *pb++;
84 return l;
85}
86
87static void create_single_boot(unsigned char* boot, int bootlen,
88 unsigned char** fwbuf, int* fwsize)
89{
90 unsigned char* buf;
91
92 /* 15 bytes for header, 16 for signature bypass,
93 * 12 for record header, size of bootloader, 12 for footer */
94 *fwsize = 15 + 16 + 12 + bootlen + 12;
95 *fwbuf = malloc(*fwsize);
96
97 if(buf == NULL) {
98 fprintf(stderr, "[ERR] Cannot allocate memory.\n" );
99 *fwbuf = NULL;
100 *fwsize = 0;
101 return;
102 }
103
104 buf = *fwbuf;
105
106 /* Copy bootloader image. */
107 memcpy(buf + 43, boot, bootlen);
108
109 /* Step 2: Create the file header */
110 sprintf((char *)buf, "B000FF\n");
111 put_uint32le(0x88200000, buf+7);
112
113 /* If the value below is too small, the update will attempt to flash.
114 * Be careful when changing this (leaving it as is won't cause issues) */
115 put_uint32le(0xCC0CD8, buf+11);
116
117 /* Step 3: Add the signature bypass record */
118 put_uint32le(0x88065A10, buf+15);
119 put_uint32le(4, buf+19);
120 put_uint32le(0xE3A00001, buf+27);
121 put_uint32le(calc_csum(buf+27,4), buf+23);
122
123 /* Step 4: Create a record for the actual code */
124 put_uint32le(BL_ENTRY_POINT, buf+31);
125 put_uint32le(bootlen, buf+35);
126 put_uint32le(calc_csum(buf + 43, bootlen), buf+39);
127
128 /* Step 5: Write the footer */
129 put_uint32le(0, buf+*fwsize-12);
130 put_uint32le(BL_ENTRY_POINT, buf+*fwsize-8);
131 put_uint32le(0, buf+*fwsize-4);
132
133 return;
134}
135
136int beastpatcher(int argc, char* argv[])
137{
138 char yesno[4];
139 unsigned char* fwbuf;
140 int fwsize;
141 struct mtp_info_t mtp_info;
142
143 (void)argv;
144
145 fprintf(stderr,"beastpatcher v" VERSION " - (C) 2009 by the Rockbox developers\n");
146 fprintf(stderr,"This is free software; see the source for copying conditions. There is NO\n");
147 fprintf(stderr,"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
148
149 /* No options are currently implemented, so just display help if any are
150 provided. */
151
152 if (argc > 1) {
153 print_usage();
154 return 1;
155 }
156
157 if (mtp_init(&mtp_info) < 0) {
158 fprintf(stderr,"[ERR] Can not init MTP\n");
159 return 1;
160 }
161
162 /* Scan for attached MTP devices. */
163 if (mtp_scan(&mtp_info) < 0)
164 {
165 fprintf(stderr,"[ERR] No devices found\n");
166 return 1;
167 }
168
169 printf("[INFO] Found device \"%s - %s\"\n", mtp_info.manufacturer,
170 mtp_info.modelname);
171 printf("[INFO] Device version: \"%s\"\n",mtp_info.version);
172
173
174 printf("\nEnter i to install the Rockbox bootloader or c to cancel and do nothing (i/c): ");
175
176 if (fgets(yesno,4,stdin))
177 {
178 if (yesno[0]=='i')
179 {
180 /* Create a single-boot bootloader from the embedded bootloader */
181 create_single_boot(bootimg, LEN_bootimg, &fwbuf, &fwsize);
182
183 if (fwbuf == NULL)
184 return 1;
185
186 if (mtp_send_firmware(&mtp_info, fwbuf, fwsize) == 0)
187 {
188 fprintf(stderr,"[INFO] Bootloader installed successfully.\n");
189 }
190 else
191 {
192 fprintf(stderr,"[ERR] Bootloader install failed.\n");
193 }
194
195 /* We are now done with the firmware image */
196 free(fwbuf);
197 }
198 else
199 {
200 fprintf(stderr,"[INFO] Installation cancelled.\n");
201 }
202 }
203
204 mtp_finished(&mtp_info);
205
206 return 0;
207}
208
209
210int main(int argc, char* argv[])
211{
212 int res;
213 char yesno[4];
214
215 res = beastpatcher(argc, argv);
216
217 printf("\nPress ENTER to exit beastpatcher: ");
218 fgets(yesno,4,stdin);
219
220 return res;
221}
diff --git a/utils/MTP/beastpatcher/mtp_common.h b/utils/MTP/beastpatcher/mtp_common.h
new file mode 100644
index 0000000000..2fb52a9e81
--- /dev/null
+++ b/utils/MTP/beastpatcher/mtp_common.h
@@ -0,0 +1,71 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * $Id:$
10 *
11 * Copyright (c) 2009, Dave Chapman
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met:
17 *
18 * * Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * * Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials provided
24 * with the distribution.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 *
38 ****************************************************************************/
39
40#ifndef _MTP_COMMON_H
41#define _MTP_COMMON_H
42
43#ifdef __WIN32__
44#error Windows support not yet implemented
45#else
46#include "libmtp.h"
47#endif
48
49struct mtp_info_t
50{
51 /* Generic data */
52 char manufacturer[200];
53 char modelname[200];
54 char version[200];
55
56 /* OS-Specific data */
57#ifdef __WIN32__
58#else
59 LIBMTP_mtpdevice_t *device;
60#endif
61};
62
63/* Common functions for both libMTP and win32 */
64
65int mtp_init(struct mtp_info_t* mtp_info);
66int mtp_finished(struct mtp_info_t* mtp_info);
67int mtp_scan(struct mtp_info_t* mtp_info);
68int mtp_send_firmware(struct mtp_info_t* mtp_info, unsigned char* fwbuf,
69 int fwsize);
70
71#endif /* !_MTP_COMMON_H */
diff --git a/utils/MTP/beastpatcher/mtp_libmtp.c b/utils/MTP/beastpatcher/mtp_libmtp.c
new file mode 100644
index 0000000000..7e8579ac99
--- /dev/null
+++ b/utils/MTP/beastpatcher/mtp_libmtp.c
@@ -0,0 +1,174 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * $Id:$
10 *
11 * Copyright (c) 2009, Dave Chapman
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met:
17 *
18 * * Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * * Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials provided
24 * with the distribution.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 *
38 *
39 ****************************************************************************/
40
41#include <string.h>
42#include <libgen.h>
43#include <sys/stat.h>
44#include <sys/types.h>
45#include <fcntl.h>
46#include <inttypes.h>
47#include "libmtp.h"
48#include "mtp_common.h"
49
50int mtp_init(struct mtp_info_t* mtp_info)
51{
52 /* Fill the info struct with zeros - mainly for the strings */
53 memset(mtp_info, 0, sizeof(struct mtp_info_t));
54
55 LIBMTP_Init();
56
57 return 0;
58
59}
60
61int mtp_finished(struct mtp_info_t* mtp_info)
62{
63 LIBMTP_Release_Device(mtp_info->device);
64
65 return 0;
66}
67
68int mtp_scan(struct mtp_info_t* mtp_info)
69{
70 char* str;
71
72 mtp_info->device = LIBMTP_Get_First_Device();
73
74 if (mtp_info->device == NULL)
75 {
76 return -1;
77 }
78 else
79 {
80 /* NOTE: These strings are filled with zeros in mtp_init() */
81
82 if ((str = LIBMTP_Get_Manufacturername(mtp_info->device)))
83 {
84 strncpy(mtp_info->manufacturer, str, sizeof(mtp_info->manufacturer)-1);
85 }
86
87 if ((str = LIBMTP_Get_Modelname(mtp_info->device)))
88 {
89 strncpy(mtp_info->modelname, str, sizeof(mtp_info->modelname)-1);
90 }
91
92 if ((str = LIBMTP_Get_Deviceversion(mtp_info->device)))
93 {
94 strncpy(mtp_info->version, str, sizeof(mtp_info->version)-1);
95 }
96
97 return 0;
98 }
99}
100
101static int progress(uint64_t const sent, uint64_t const total,
102 void const *const data)
103{
104 (void)data;
105
106 int percent = (sent * 100) / total;
107#ifdef __WIN32__
108 printf("Progress: %I64u of %I64u (%d%%)\r", sent, total, percent);
109#else
110 printf("Progress: %"PRIu64" of %"PRIu64" (%d%%)\r", sent, total, percent);
111#endif
112 fflush(stdout);
113 return 0;
114}
115
116
117int mtp_send_firmware(struct mtp_info_t* mtp_info, unsigned char* fwbuf,
118 int fwsize)
119{
120 LIBMTP_file_t *genfile;
121 int ret;
122 size_t n;
123 FILE* fwfile;
124
125 /* Open a temporary file - this will be automatically deleted when closed */
126 fwfile = tmpfile();
127
128 if (fwfile == NULL)
129 {
130 fprintf(stderr,"[ERR] Could not create temporary file.\n");
131 return -1;
132 }
133
134 n = fwrite(fwbuf, 1, fwsize, fwfile);
135 if ((int)n < fwsize)
136 {
137 fprintf(stderr,"[ERR] Could not write to temporary file - n = %d.\n",(int)n);
138 fclose(fwfile);
139 return -1;
140 }
141
142 /* Reset file pointer */
143 fseek(fwfile, SEEK_SET, 0);
144
145 /* Prepare for uploading firmware */
146 genfile = LIBMTP_new_file_t();
147 genfile->filetype = LIBMTP_FILETYPE_FIRMWARE;
148 genfile->filename = strdup("nk.bin");
149 genfile->filesize = fwsize;
150
151#ifdef OLDMTP
152 ret = LIBMTP_Send_File_From_File_Descriptor(mtp_info->device,
153 fileno(fwfile), genfile, progress, NULL, 0);
154#else
155 ret = LIBMTP_Send_File_From_File_Descriptor(mtp_info->device,
156 fileno(fwfile), genfile, progress, NULL);
157#endif
158
159 /* Keep the progress line onscreen */
160 printf("\n");
161
162 /* NOTE: According to the docs, a value of ret != 0 means error, but libMTP
163 seems to return that even when successful. So we can't check the return
164 code.
165 */
166
167 /* Cleanup */
168 LIBMTP_destroy_file_t(genfile);
169
170 /* Close the temporary file - this also deletes it. */
171 fclose(fwfile);
172
173 return 0;
174}