2 * Windows MTP Firmware Uploading Implementation
4 * Based on http://opensource.creative.com/mtp_xfer.html
5 * Edited by Maurus Cuelenaere for Rockbox
7 * Copyright (c) 2009, Maurus Cuelenaere
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * * Neither the name of the <organization> nor the
18 * names of its contributors may be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY MAURUS CUELENAERE ''AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL MAURUS CUELENAERE BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 #include "progresshelper.h"
44 * Compilation requirements:
46 * Download the Windows Media Format 9.5 SDK
47 * Add "c:\wmsdk\wmfsdk95\include,c:\wmsdk\wmfsdk95\wmdm\inc" to your inclusion path
48 * Add "c:\wmsdk\wmfsdk95\lib,c:\wmsdk\wmfsdk95\wmdm\lib" to your library inclusion path
49 * Link to "mssachlp.lib"
54 IComponentAuthenticate
* pICompAuth
;
55 CSecureChannelClient
*pSacClient
;
56 IWMDeviceManager3
* pIdvMgr
;
62 static int mtp_init(struct mtp_if
* mtp
)
65 mtp
->pSacClient
= new CSecureChannelClient
;
67 mtp
->initialized
= false;
69 /* these are generic keys */
70 BYTE abPVK
[] = {0x00};
71 BYTE abCert
[] = {0x00};
75 /* get an authentication interface */
76 hr
= CoCreateInstance(CLSID_MediaDevMgr
, NULL
, CLSCTX_ALL
,
77 IID_IComponentAuthenticate
, (void **)&mtp
->pICompAuth
);
80 /* create a secure channel client certificate */
81 hr
= mtp
->pSacClient
->SetCertificate(SAC_CERT_V1
, (BYTE
*) abCert
,
82 sizeof(abCert
), (BYTE
*) abPVK
, sizeof(abPVK
));
85 /* bind the authentication interface to the secure channel client */
86 mtp
->pSacClient
->SetInterface(mtp
->pICompAuth
);
88 /* trigger communication */
89 hr
= mtp
->pSacClient
->Authenticate(SAC_PROTOCOL_V1
);
92 /* get main interface to media device manager */
93 hr
= mtp
->pICompAuth
->QueryInterface(IID_IWMDeviceManager2
,
94 (void**)&mtp
->pIdvMgr
);
97 mtp
->initialized
= true;
105 return mtp
->initialized
;
109 static int mtp_close(struct mtp_if
* mtp
)
113 mtp
->pIdvMgr
->Release();
114 mtp
->pICompAuth
->Release();
116 mtp
->initialized
= false;
121 MTP_DLL_API
int mtp_description(wchar_t* name
, wchar_t* manufacturer
, DWORD
* version
)
126 /* zero mtp structure */
127 memset(&mtp
, 0, sizeof(struct mtp_if
));
129 /* initialize interface */
131 if(mtp
.initialized
== false) {
135 /* we now have a media device manager interface... */
136 /* enumerate devices... */
137 IWMDMEnumDevice
*pIEnumDev
;
138 wchar_t pwsString
[256];
139 hr
= mtp
.pIdvMgr
->EnumDevices2(&pIEnumDev
);
141 hr
= pIEnumDev
->Reset(); /* Next will now return the first device */
143 IWMDMDevice3
* pIDevice
;
144 unsigned long ulNumFetched
;
145 hr
= pIEnumDev
->Next(1, (IWMDMDevice
**)&pIDevice
, &ulNumFetched
);
146 while (SUCCEEDED(hr
) && (hr
!= S_FALSE
)) {
147 /* output device name */
148 hr
= pIDevice
->GetName(pwsString
, 256);
150 wcsncpy_s(name
, 256, pwsString
, _TRUNCATE
);
153 /* device manufacturer */
154 hr
= pIDevice
->GetManufacturer(pwsString
, 256);
156 wcsncpy_s(manufacturer
, 256, pwsString
, _TRUNCATE
);
158 /* device version -- optional interface so might fail. */
160 hr
= pIDevice
->GetVersion(&ver
);
168 /* move to next device */
169 hr
= pIEnumDev
->Next(1, (IWMDMDevice
**)&pIDevice
, &ulNumFetched
);
171 pIEnumDev
->Release();
175 return (num
> 0) ? num
: -1;
178 MTP_DLL_API
int mtp_sendnk(LPWSTR file
, int filesize
, void (*callback
)(unsigned int progress
, unsigned int max
))
181 bool return_value
= false;
183 /* zero mtp structure */
184 memset(&mtp
, 0, sizeof(struct mtp_if
));
186 /* initialize interface */
188 if(mtp
.initialized
== false) {
191 /* enumerate devices... */
192 IWMDMEnumDevice
*pIEnumDev
;
193 hr
= mtp
.pIdvMgr
->EnumDevices2(&pIEnumDev
);
196 hr
= pIEnumDev
->Reset(); /* Next will now return the first device */
199 IWMDMDevice3
* pIDevice
;
200 unsigned long ulNumFetched
;
201 hr
= pIEnumDev
->Next(1, (IWMDMDevice
**)&pIDevice
, &ulNumFetched
);
202 while (SUCCEEDED(hr
) && (hr
!= S_FALSE
))
204 /* get storage info */
206 pIDevice
->GetType(&tempDW
);
207 if (tempDW
& WMDM_DEVICE_TYPE_STORAGE
)
209 IWMDMEnumStorage
*pIEnumStorage
= NULL
;
210 IWMDMStorage
*pIStorage
= NULL
;
211 IWMDMStorage3
*pIFileStorage
= NULL
;
212 hr
= pIDevice
->EnumStorage(&pIEnumStorage
);
215 pIEnumStorage
->Reset();
216 hr
= pIEnumStorage
->Next(1, (IWMDMStorage
**)&pIStorage
, &ulNumFetched
);
217 while (SUCCEEDED(hr
) && (hr
!= S_FALSE
))
219 IWMDMStorage3
*pNewStorage
;
220 hr
= pIStorage
->QueryInterface(IID_IWMDMStorage3
, (void **)&pNewStorage
);
223 IWMDMStorageControl3
*pIWMDMStorageControl
;
224 hr
= pNewStorage
->QueryInterface(IID_IWMDMStorageControl3
,
225 (void**)&pIWMDMStorageControl
);
228 IWMDMMetaData
*pIWMDMMetaData
= NULL
;
229 hr
= pNewStorage
->CreateEmptyMetadataObject(&pIWMDMMetaData
);
232 DWORD dw
= WMDM_FORMATCODE_UNDEFINEDFIRMWARE
;
233 hr
= pIWMDMMetaData
->AddItem(WMDM_TYPE_DWORD
, g_wszWMDMFormatCode
, (BYTE
*)&dw
, sizeof(dw
));
234 hr
= pIWMDMMetaData
->AddItem(WMDM_TYPE_STRING
, g_wszWMDMFileName
, (BYTE
*)L
"nk.bin", 32);
238 hr
= pIWMDMMetaData
->AddItem(WMDM_TYPE_QWORD
, g_wszWMDMFileSize
, (BYTE
*)ow
, 2 * sizeof(dw
));
241 IWMDMStorage
*pNewObject
= NULL
;
242 CProgressHelper
*progress
= new CProgressHelper(callback
);
244 hr
= pIWMDMStorageControl
->Insert3(
245 WMDM_MODE_BLOCK
| WMDM_CONTENT_FILE
| WMDM_MODE_PROGRESS
,
250 (callback
== NULL
? NULL
: (IWMDMProgress
*)progress
),
253 (IWMDMStorage
**)&pNewObject
);
256 || hr
== WMDM_S_NOT_ALL_PROPERTIES_APPLIED
257 || hr
== WMDM_S_NOT_ALL_PROPERTIES_RETRIEVED
)
268 pIEnumStorage
->Release();
271 /* move to next device */
273 hr
= pIEnumDev
->Next(1, (IWMDMDevice
**)&pIDevice
, &ulNumFetched
);
275 pIEnumDev
->Release();
279 return return_value
? 1 : 0;