networkwm-js 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +339 -0
- package/README.MD +110 -0
- package/dist/bytemanip.d.ts +12 -0
- package/dist/bytemanip.d.ts.map +1 -0
- package/dist/bytemanip.js +71 -0
- package/dist/database-abstraction.d.ts +39 -0
- package/dist/database-abstraction.d.ts.map +1 -0
- package/dist/database-abstraction.js +288 -0
- package/dist/databases.d.ts +85 -0
- package/dist/databases.d.ts.map +1 -0
- package/dist/databases.js +303 -0
- package/dist/devices.d.ts +6 -0
- package/dist/devices.d.ts.map +1 -0
- package/dist/devices.js +9 -0
- package/dist/encryption.d.ts +16 -0
- package/dist/encryption.d.ts.map +1 -0
- package/dist/encryption.js +123 -0
- package/dist/errors.d.ts +4 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +10 -0
- package/dist/filesystem/index.d.ts +2 -0
- package/dist/filesystem/index.d.ts.map +1 -0
- package/dist/filesystem/index.js +17 -0
- package/dist/filesystem/usb-mass-storage-webusb-filesystem.d.ts +44 -0
- package/dist/filesystem/usb-mass-storage-webusb-filesystem.d.ts.map +1 -0
- package/dist/filesystem/usb-mass-storage-webusb-filesystem.js +187 -0
- package/dist/functions.d.ts +12 -0
- package/dist/functions.d.ts.map +1 -0
- package/dist/functions.js +73 -0
- package/dist/helpers.d.ts +9 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +47 -0
- package/dist/id3.d.ts +18 -0
- package/dist/id3.d.ts.map +1 -0
- package/dist/id3.js +137 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/init-data.d.ts +16 -0
- package/dist/init-data.d.ts.map +1 -0
- package/dist/init-data.js +18 -0
- package/dist/initialization.d.ts +4 -0
- package/dist/initialization.d.ts.map +1 -0
- package/dist/initialization.js +32 -0
- package/dist/sort.d.ts +13 -0
- package/dist/sort.d.ts.map +1 -0
- package/dist/sort.js +62 -0
- package/dist/tables.d.ts +19 -0
- package/dist/tables.d.ts.map +1 -0
- package/dist/tables.js +101 -0
- package/dist/tagged-oma.d.ts +12 -0
- package/dist/tagged-oma.d.ts.map +1 -0
- package/dist/tagged-oma.js +175 -0
- package/dist/utils.d.ts +9 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +90 -0
- package/package.json +43 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devices.d.ts","sourceRoot":"","sources":["../src/devices.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,EAK3E,CAAC"}
|
package/dist/devices.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DeviceIds = void 0;
|
|
4
|
+
exports.DeviceIds = [
|
|
5
|
+
{ vendorId: 0x054c, productId: 0x01ad, name: 'Sony NW-HD1 / NW-HD2' },
|
|
6
|
+
{ vendorId: 0x054c, productId: 0x0210, name: 'Sony NW-HD3' },
|
|
7
|
+
{ vendorId: 0x054c, productId: 0x0233, name: 'Sony NW-HD5' },
|
|
8
|
+
{ vendorId: 0x054c, productId: 0x0269, name: 'Sony NW-A3000' },
|
|
9
|
+
];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import Crypto from '@originjs/crypto-js-wasm';
|
|
2
|
+
export declare function initCrypto(): Promise<void>;
|
|
3
|
+
export declare const EKBROOTS: {
|
|
4
|
+
[key: number]: Uint8Array;
|
|
5
|
+
};
|
|
6
|
+
export declare function importKeys(rawKeysContents: Uint8Array): void;
|
|
7
|
+
export declare function getMP3EncryptionKey(discId: Uint8Array, trackNumber: number): Uint8Array;
|
|
8
|
+
export declare function createTrackKeyForKeyring(ekbNum: number, verificationKey: Uint8Array, trackKey: Uint8Array): Uint8Array;
|
|
9
|
+
export declare function createMaclistValue(ekbNum: number, verificationKey: Uint8Array, contents: Uint8Array): Uint8Array;
|
|
10
|
+
export declare function retailMac(message: Uint8Array, key: Uint8Array): Uint8Array;
|
|
11
|
+
export declare function createIcvMac(icvAndHeader: Uint8Array, sessionKey: Uint8Array): Uint8Array;
|
|
12
|
+
export declare function encryptTrackKey(trackKey: Uint8Array): Uint8Array;
|
|
13
|
+
export declare function createTrackMac2(trackKeyWa: Crypto.lib.WordArray, trackEntry: Uint8Array): Uint8Array;
|
|
14
|
+
export declare function createTrackMac(trackKey: Uint8Array, trackEntry: Uint8Array): Uint8Array;
|
|
15
|
+
export declare function desDecrypt(data: Uint8Array, key: Uint8Array): Uint8Array;
|
|
16
|
+
//# sourceMappingURL=encryption.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../src/encryption.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,0BAA0B,CAAC;AAK9C,wBAAsB,UAAU,kBAG/B;AAGD,eAAO,MAAM,QAAQ,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAAA;CAExC,CAAC;AAEX,wBAAgB,UAAU,CAAC,eAAe,EAAE,UAAU,QAQrD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,cAG1E;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,cAsBzG;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,cAenG;AAID,wBAAgB,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,cAgB7D;AAED,wBAAgB,YAAY,CAAC,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,cAM5E;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,UAAU,cAKnD;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,EAAE,UAAU,cAQvF;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,cAG1E;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,cAE3D"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.desDecrypt = exports.createTrackMac = exports.createTrackMac2 = exports.encryptTrackKey = exports.createIcvMac = exports.retailMac = exports.createMaclistValue = exports.createTrackKeyForKeyring = exports.getMP3EncryptionKey = exports.importKeys = exports.EKBROOTS = exports.initCrypto = void 0;
|
|
7
|
+
const crypto_js_wasm_1 = __importDefault(require("@originjs/crypto-js-wasm"));
|
|
8
|
+
const bytemanip_1 = require("./bytemanip");
|
|
9
|
+
const errors_1 = require("./errors");
|
|
10
|
+
const utils_1 = require("./utils");
|
|
11
|
+
async function initCrypto() {
|
|
12
|
+
await crypto_js_wasm_1.default.TripleDES.loadWasm();
|
|
13
|
+
await crypto_js_wasm_1.default.DES.loadWasm();
|
|
14
|
+
}
|
|
15
|
+
exports.initCrypto = initCrypto;
|
|
16
|
+
// prettier-ignore
|
|
17
|
+
exports.EKBROOTS = {
|
|
18
|
+
// <Redacted>
|
|
19
|
+
};
|
|
20
|
+
function importKeys(rawKeysContents) {
|
|
21
|
+
let offset = 0;
|
|
22
|
+
const dataView = new DataView(rawKeysContents.buffer);
|
|
23
|
+
while (offset < rawKeysContents.length) {
|
|
24
|
+
let ekbid;
|
|
25
|
+
[ekbid, offset] = (0, bytemanip_1.readUint32)(dataView, offset);
|
|
26
|
+
exports.EKBROOTS[ekbid] = rawKeysContents.slice(offset, offset += 3 * 8);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.importKeys = importKeys;
|
|
30
|
+
function getMP3EncryptionKey(discId, trackNumber) {
|
|
31
|
+
const key = (trackNumber * 0x6953b2ed + 0x6baab1) ^ (0, bytemanip_1.getUint32)(discId, 12);
|
|
32
|
+
return (0, bytemanip_1.writeUint32)(key);
|
|
33
|
+
}
|
|
34
|
+
exports.getMP3EncryptionKey = getMP3EncryptionKey;
|
|
35
|
+
function createTrackKeyForKeyring(ekbNum, verificationKey, trackKey) {
|
|
36
|
+
if (!(ekbNum in exports.EKBROOTS)) {
|
|
37
|
+
throw new errors_1.NWJSError('Requested decription with an unknown EKB');
|
|
38
|
+
}
|
|
39
|
+
const rootKeyC = crypto_js_wasm_1.default.lib.WordArray.create(exports.EKBROOTS[ekbNum]);
|
|
40
|
+
const verificationKeyC = crypto_js_wasm_1.default.lib.CipherParams.create({
|
|
41
|
+
ciphertext: crypto_js_wasm_1.default.lib.WordArray.create(verificationKey),
|
|
42
|
+
});
|
|
43
|
+
const trackKeyC = crypto_js_wasm_1.default.lib.CipherParams.create({
|
|
44
|
+
ciphertext: crypto_js_wasm_1.default.lib.WordArray.create(trackKey),
|
|
45
|
+
});
|
|
46
|
+
// Step 1: get real verification key
|
|
47
|
+
const decryptedVerificationKey = crypto_js_wasm_1.default.TripleDES.decrypt(verificationKeyC, rootKeyC, {
|
|
48
|
+
mode: crypto_js_wasm_1.default.mode.ECB,
|
|
49
|
+
});
|
|
50
|
+
// Step 2: get "encrypted" track key - so decrypt it
|
|
51
|
+
const decryptedTrackKey = crypto_js_wasm_1.default.TripleDES.decrypt(trackKeyC, decryptedVerificationKey, {
|
|
52
|
+
mode: crypto_js_wasm_1.default.mode.ECB,
|
|
53
|
+
});
|
|
54
|
+
return (0, utils_1.wordArrayToByteArray)(decryptedTrackKey, 8);
|
|
55
|
+
}
|
|
56
|
+
exports.createTrackKeyForKeyring = createTrackKeyForKeyring;
|
|
57
|
+
function createMaclistValue(ekbNum, verificationKey, contents) {
|
|
58
|
+
if (!(ekbNum in exports.EKBROOTS)) {
|
|
59
|
+
throw new errors_1.NWJSError('Requested decription with an unknown EKB');
|
|
60
|
+
}
|
|
61
|
+
const rootKeyC = crypto_js_wasm_1.default.lib.WordArray.create(exports.EKBROOTS[ekbNum]);
|
|
62
|
+
const verificationKeyC = crypto_js_wasm_1.default.lib.CipherParams.create({
|
|
63
|
+
ciphertext: crypto_js_wasm_1.default.lib.WordArray.create(verificationKey),
|
|
64
|
+
});
|
|
65
|
+
// Step 1: get real verification key
|
|
66
|
+
const decryptedVerificationKey = crypto_js_wasm_1.default.TripleDES.decrypt(verificationKeyC, rootKeyC, {
|
|
67
|
+
mode: crypto_js_wasm_1.default.mode.ECB,
|
|
68
|
+
});
|
|
69
|
+
return createTrackMac2(decryptedVerificationKey, contents);
|
|
70
|
+
}
|
|
71
|
+
exports.createMaclistValue = createMaclistValue;
|
|
72
|
+
const NO_PADDING = { pad: (a) => a, unpad: (a) => a };
|
|
73
|
+
function retailMac(message, key) {
|
|
74
|
+
const keyA = key.subarray(0, 8);
|
|
75
|
+
const keyB = key.subarray(8, 16);
|
|
76
|
+
const messageWa = crypto_js_wasm_1.default.lib.WordArray.create(message);
|
|
77
|
+
const keyAWa = crypto_js_wasm_1.default.lib.WordArray.create(keyA);
|
|
78
|
+
const keyBWa = crypto_js_wasm_1.default.lib.WordArray.create(keyB);
|
|
79
|
+
const zeroWa = crypto_js_wasm_1.default.lib.WordArray.create(new Uint8Array(8).fill(0));
|
|
80
|
+
const encA = crypto_js_wasm_1.default.DES.encrypt(messageWa, keyAWa, { padding: NO_PADDING, mode: crypto_js_wasm_1.default.mode.CBC, iv: zeroWa }).ciphertext;
|
|
81
|
+
const messageBFull = (0, utils_1.wordArrayToByteArray)(encA);
|
|
82
|
+
const messageB = messageBFull.subarray(messageBFull.length - 8);
|
|
83
|
+
const messageBWa = crypto_js_wasm_1.default.lib.CipherParams.create({
|
|
84
|
+
ciphertext: crypto_js_wasm_1.default.lib.WordArray.create(messageB),
|
|
85
|
+
});
|
|
86
|
+
const encB = crypto_js_wasm_1.default.DES.decrypt(messageBWa, keyBWa, { padding: NO_PADDING, mode: crypto_js_wasm_1.default.mode.ECB });
|
|
87
|
+
const final = crypto_js_wasm_1.default.DES.encrypt(encB, keyAWa, { padding: NO_PADDING, mode: crypto_js_wasm_1.default.mode.ECB }).ciphertext;
|
|
88
|
+
return (0, utils_1.wordArrayToByteArray)(final);
|
|
89
|
+
}
|
|
90
|
+
exports.retailMac = retailMac;
|
|
91
|
+
function createIcvMac(icvAndHeader, sessionKey) {
|
|
92
|
+
const icvWa = crypto_js_wasm_1.default.lib.WordArray.create(icvAndHeader);
|
|
93
|
+
const sessionKeyWa = crypto_js_wasm_1.default.lib.WordArray.create(sessionKey);
|
|
94
|
+
const zeroWa = crypto_js_wasm_1.default.lib.WordArray.create(new Uint8Array(8).fill(0));
|
|
95
|
+
const result = crypto_js_wasm_1.default.DES.encrypt(icvWa, sessionKeyWa, { mode: crypto_js_wasm_1.default.mode.CBC, iv: zeroWa, padding: NO_PADDING });
|
|
96
|
+
return (0, utils_1.wordArrayToByteArray)(result.ciphertext).subarray(-8);
|
|
97
|
+
}
|
|
98
|
+
exports.createIcvMac = createIcvMac;
|
|
99
|
+
function encryptTrackKey(trackKey) {
|
|
100
|
+
const trackKeyWa = crypto_js_wasm_1.default.lib.WordArray.create(trackKey);
|
|
101
|
+
const keyWa = crypto_js_wasm_1.default.lib.WordArray.create(exports.EKBROOTS[0x00010012]);
|
|
102
|
+
const encrypted = crypto_js_wasm_1.default.TripleDES.encrypt(trackKeyWa, keyWa, { mode: crypto_js_wasm_1.default.mode.ECB, padding: NO_PADDING });
|
|
103
|
+
return (0, utils_1.wordArrayToByteArray)(encrypted.ciphertext);
|
|
104
|
+
}
|
|
105
|
+
exports.encryptTrackKey = encryptTrackKey;
|
|
106
|
+
function createTrackMac2(trackKeyWa, trackEntry) {
|
|
107
|
+
const trackEntryWa = crypto_js_wasm_1.default.lib.WordArray.create(trackEntry);
|
|
108
|
+
const macKeySourceWa = crypto_js_wasm_1.default.lib.WordArray.create(new Uint8Array(8).fill(0));
|
|
109
|
+
const macKey = crypto_js_wasm_1.default.DES.encrypt(macKeySourceWa, trackKeyWa, { mode: crypto_js_wasm_1.default.mode.ECB, padding: NO_PADDING }).ciphertext;
|
|
110
|
+
const zeroWa = crypto_js_wasm_1.default.lib.WordArray.create(new Uint8Array(8).fill(0));
|
|
111
|
+
const mac = crypto_js_wasm_1.default.DES.encrypt(trackEntryWa, macKey, { mode: crypto_js_wasm_1.default.mode.CBC, iv: zeroWa, padding: NO_PADDING });
|
|
112
|
+
return (0, utils_1.wordArrayToByteArray)(mac.ciphertext).subarray(-8);
|
|
113
|
+
}
|
|
114
|
+
exports.createTrackMac2 = createTrackMac2;
|
|
115
|
+
function createTrackMac(trackKey, trackEntry) {
|
|
116
|
+
const trackKeyWa = crypto_js_wasm_1.default.lib.WordArray.create(trackKey);
|
|
117
|
+
return createTrackMac2(trackKeyWa, trackEntry);
|
|
118
|
+
}
|
|
119
|
+
exports.createTrackMac = createTrackMac;
|
|
120
|
+
function desDecrypt(data, key) {
|
|
121
|
+
return (0, utils_1.wordArrayToByteArray)(crypto_js_wasm_1.default.TripleDES.decrypt(crypto_js_wasm_1.default.lib.CipherParams.create({ ciphertext: crypto_js_wasm_1.default.lib.WordArray.create(data) }), crypto_js_wasm_1.default.lib.WordArray.create(key), { mode: crypto_js_wasm_1.default.mode.ECB, iv: crypto_js_wasm_1.default.lib.WordArray.create(new Uint8Array(8).fill(0)) }), data.length);
|
|
122
|
+
}
|
|
123
|
+
exports.desDecrypt = desDecrypt;
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,SAAU,SAAQ,KAAK;gBACpB,CAAC,EAAE,MAAM;CAIxB"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NWJSError = void 0;
|
|
4
|
+
class NWJSError extends Error {
|
|
5
|
+
constructor(m) {
|
|
6
|
+
super(m);
|
|
7
|
+
Object.setPrototypeOf(this, NWJSError.prototype);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.NWJSError = NWJSError;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/filesystem/index.ts"],"names":[],"mappings":"AAAA,cAAc,sCAAsC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./usb-mass-storage-webusb-filesystem"), exports);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { HiMDFile, HiMDFilesystem, SonyVendorUSMCDriver, UMSCHiMDFilesystem } from 'himd-js';
|
|
2
|
+
import { WebUSBDevice } from 'usb';
|
|
3
|
+
export declare class SonyVendorNWJSUSMCDriver extends SonyVendorUSMCDriver {
|
|
4
|
+
protected drmRead(param: number, length: number): Promise<Uint8Array>;
|
|
5
|
+
protected drmWrite(param: number, data: Uint8Array): Promise<void>;
|
|
6
|
+
writeHostLeafID(leafID: Uint8Array, hostNonce: Uint8Array): Promise<void>;
|
|
7
|
+
getAuthenticationStage2Info(): Promise<{
|
|
8
|
+
discId: Uint8Array;
|
|
9
|
+
mac: Uint8Array;
|
|
10
|
+
deviceLeafId: Uint8Array;
|
|
11
|
+
deviceNonce: Uint8Array;
|
|
12
|
+
}>;
|
|
13
|
+
writeAuthenticationStage3Info(hostMac: Uint8Array): Promise<void>;
|
|
14
|
+
readMasterKey(): Promise<{
|
|
15
|
+
header: Uint8Array;
|
|
16
|
+
masterKey: Uint8Array;
|
|
17
|
+
}>;
|
|
18
|
+
writeMasterKeyAndMac(generation: number, masterKey: Uint8Array, mac: Uint8Array, sessionKey: Uint8Array): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export declare class UMSCNWJSSession {
|
|
21
|
+
protected driver: SonyVendorNWJSUSMCDriver;
|
|
22
|
+
protected fs: HiMDFilesystem;
|
|
23
|
+
hostNonce: Uint8Array;
|
|
24
|
+
hostLeafId: Uint8Array;
|
|
25
|
+
deviceNonce?: Uint8Array;
|
|
26
|
+
discId?: Uint8Array;
|
|
27
|
+
deviceLeafId?: Uint8Array;
|
|
28
|
+
currentIcv?: Uint8Array;
|
|
29
|
+
currentIcvHeader?: Uint8Array;
|
|
30
|
+
sessionKey?: Uint8Array;
|
|
31
|
+
mclistHandle?: HiMDFile;
|
|
32
|
+
currentGeneration?: number;
|
|
33
|
+
allMacs?: Uint8Array;
|
|
34
|
+
constructor(driver: SonyVendorNWJSUSMCDriver, fs: HiMDFilesystem);
|
|
35
|
+
performAuthorization(): Promise<void>;
|
|
36
|
+
finalizeSession(): Promise<void>;
|
|
37
|
+
writeTrackMac(trackNumber: number, mac: Uint8Array): void;
|
|
38
|
+
}
|
|
39
|
+
export declare class UMSCNWJSFilesystem extends UMSCHiMDFilesystem {
|
|
40
|
+
driver: SonyVendorNWJSUSMCDriver;
|
|
41
|
+
constructor(webUSB: WebUSBDevice);
|
|
42
|
+
protected initFS(bypassCoherencyChecks?: boolean | undefined): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=usb-mass-storage-webusb-filesystem.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usb-mass-storage-webusb-filesystem.d.ts","sourceRoot":"","sources":["../../src/filesystem/usb-mass-storage-webusb-filesystem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAI7F,OAAO,EAAE,YAAY,EAAE,MAAM,KAAK,CAAC;AAGnC,qBAAa,wBAAyB,SAAQ,oBAAoB;cAC9C,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;cAuBrC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU;IA2BlD,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU;IASzD,2BAA2B;;;;;;IAoB3B,6BAA6B,CAAC,OAAO,EAAE,UAAU;IAyBjD,aAAa;;;;IAWb,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU;CAuBhH;AAED,qBAAa,eAAe;IAgBZ,SAAS,CAAC,MAAM,EAAE,wBAAwB;IAAE,SAAS,CAAC,EAAE,EAAE,cAAc;IAfpF,SAAS,aAAuB;IAChC,UAAU,aAAoE;IAE9E,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,YAAY,CAAC,EAAE,UAAU,CAAC;IAC1B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,gBAAgB,CAAC,EAAE,UAAU,CAAC;IAC9B,UAAU,CAAC,EAAE,UAAU,CAAC;IAExB,YAAY,CAAC,EAAE,QAAQ,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,OAAO,CAAC,EAAE,UAAU,CAAC;gBAEC,MAAM,EAAE,wBAAwB,EAAY,EAAE,EAAE,cAAc;IAEvE,oBAAoB;IAkBpB,eAAe;IAYrB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU;CAG5D;AAED,qBAAa,kBAAmB,SAAQ,kBAAkB;IACtD,MAAM,EAAE,wBAAwB,CAAC;gBACrB,MAAM,EAAE,YAAY;cAKhB,MAAM,CAAC,qBAAqB,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;CAYrF"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UMSCNWJSFilesystem = exports.UMSCNWJSSession = exports.SonyVendorNWJSUSMCDriver = void 0;
|
|
4
|
+
const himd_js_1 = require("himd-js");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
const bytemanip_1 = require("../bytemanip");
|
|
7
|
+
const encryption_1 = require("../encryption");
|
|
8
|
+
const nufatfs_1 = require("nufatfs");
|
|
9
|
+
class SonyVendorNWJSUSMCDriver extends himd_js_1.SonyVendorUSMCDriver {
|
|
10
|
+
async drmRead(param, length) {
|
|
11
|
+
const command = new Uint8Array([
|
|
12
|
+
0xa4,
|
|
13
|
+
0x00,
|
|
14
|
+
0x00,
|
|
15
|
+
0x00,
|
|
16
|
+
0x00,
|
|
17
|
+
0x00,
|
|
18
|
+
0x00,
|
|
19
|
+
0xbc,
|
|
20
|
+
(length >> 8) & 0xff,
|
|
21
|
+
length & 0xff,
|
|
22
|
+
param,
|
|
23
|
+
0x00,
|
|
24
|
+
0x00,
|
|
25
|
+
0x00,
|
|
26
|
+
0x00,
|
|
27
|
+
0x00,
|
|
28
|
+
]);
|
|
29
|
+
const result = await this.sendCommandInGetResult(command, length, false, command.length);
|
|
30
|
+
return result.result.subarray(2);
|
|
31
|
+
}
|
|
32
|
+
async drmWrite(param, data) {
|
|
33
|
+
const newData = new Uint8Array(data.length + 2);
|
|
34
|
+
newData.set((0, bytemanip_1.writeUint16)(data.length), 0);
|
|
35
|
+
newData.set(data, 2);
|
|
36
|
+
const length = newData.length;
|
|
37
|
+
const command = new Uint8Array([
|
|
38
|
+
0xa3,
|
|
39
|
+
0x00,
|
|
40
|
+
0x00,
|
|
41
|
+
0x00,
|
|
42
|
+
0x00,
|
|
43
|
+
0x00,
|
|
44
|
+
0x00,
|
|
45
|
+
0xbc,
|
|
46
|
+
(length >> 8) & 0xff,
|
|
47
|
+
length & 0xff,
|
|
48
|
+
param,
|
|
49
|
+
0x00,
|
|
50
|
+
0x00,
|
|
51
|
+
0x00,
|
|
52
|
+
0x00,
|
|
53
|
+
0x00,
|
|
54
|
+
]);
|
|
55
|
+
await this.sendCommandOutGetResult(command, newData, command.length);
|
|
56
|
+
}
|
|
57
|
+
async writeHostLeafID(leafID, hostNonce) {
|
|
58
|
+
(0, utils_1.assert)(leafID.length === 8, 'Wrong length of leaf id');
|
|
59
|
+
const finalBuffer = new Uint8Array(2 + 8 + 8);
|
|
60
|
+
finalBuffer.fill(0);
|
|
61
|
+
finalBuffer.set(leafID, 2);
|
|
62
|
+
finalBuffer.set(hostNonce, 10);
|
|
63
|
+
await this.drmWrite(0x30, finalBuffer);
|
|
64
|
+
}
|
|
65
|
+
async getAuthenticationStage2Info() {
|
|
66
|
+
const data = await this.drmRead(0x31, 0x43c);
|
|
67
|
+
let _current = 2;
|
|
68
|
+
const read = (len) => data.subarray(_current, (_current += len));
|
|
69
|
+
const discId = read(16);
|
|
70
|
+
const mac = read(8);
|
|
71
|
+
const deviceLeafId = read(8);
|
|
72
|
+
const deviceNonce = read(8);
|
|
73
|
+
// // EKB info begin
|
|
74
|
+
// const keyType = read(4);
|
|
75
|
+
// const keyLevel = read(4);
|
|
76
|
+
// const ekbid = read(4);
|
|
77
|
+
// const zero = read(4);
|
|
78
|
+
// const key = read(16);
|
|
79
|
+
return { discId, mac, deviceLeafId, deviceNonce };
|
|
80
|
+
}
|
|
81
|
+
async writeAuthenticationStage3Info(hostMac) {
|
|
82
|
+
const finalBuffer = new Uint8Array(0x41a);
|
|
83
|
+
finalBuffer.fill(0);
|
|
84
|
+
finalBuffer.set(hostMac, 2);
|
|
85
|
+
// Send own configuration
|
|
86
|
+
// Key type 1
|
|
87
|
+
// Key level 8
|
|
88
|
+
// EKB 00010021
|
|
89
|
+
// Encrypted Node Key: 0xf0, 0x5c, 0xb7, 0xfe, 0xde, 0x3c, 0x94, 0x01, 0x78, 0x4a, 0x71, 0x8d, 0x9f, 0xf7, 0xf4, 0xb1
|
|
90
|
+
finalBuffer.set([
|
|
91
|
+
0x00, 0x00, 0x00, 0x01,
|
|
92
|
+
0x00, 0x00, 0x00, 0x08,
|
|
93
|
+
0x00, 0x01, 0x00, 0x21,
|
|
94
|
+
0x00, 0x00, 0x00, 0x00,
|
|
95
|
+
0xf0, 0x5c, 0xb7, 0xfe, 0xde, 0x3c, 0x94, 0x01,
|
|
96
|
+
0x78, 0x4a, 0x71, 0x8d, 0x9f, 0xf7, 0xf4, 0xb1,
|
|
97
|
+
], 10);
|
|
98
|
+
await this.drmWrite(0x32, finalBuffer);
|
|
99
|
+
}
|
|
100
|
+
async readMasterKey() {
|
|
101
|
+
const data = await this.drmRead(0x33, 0x404);
|
|
102
|
+
let _current = 2;
|
|
103
|
+
const read = (len) => data.subarray(_current, (_current += len));
|
|
104
|
+
const header = read(8);
|
|
105
|
+
// Zeros
|
|
106
|
+
_current += 4;
|
|
107
|
+
const masterKey = read(16);
|
|
108
|
+
return { header, masterKey };
|
|
109
|
+
}
|
|
110
|
+
async writeMasterKeyAndMac(generation, masterKey, mac, sessionKey) {
|
|
111
|
+
// masterKey = 0xe0, 0xaa, 0x0b, 0x24, 0xd5, 0x1f, 0x97, 0x1d, 0x57, 0xaa, 0x7a, 0x3f, 0x8f, 0x93, 0xe7, 0xb3
|
|
112
|
+
// mac = 0x9e, 0x29, 0xe4, 0xa3, 0x4f, 0x8d, 0x43, 0xc7
|
|
113
|
+
const generationBytes = (0, bytemanip_1.writeUint32)(generation);
|
|
114
|
+
const theSonySoup = new Uint8Array([
|
|
115
|
+
0x00, 0x20, 0x00, 0x98,
|
|
116
|
+
...generationBytes,
|
|
117
|
+
0x00, 0x00, 0x00, 0x00,
|
|
118
|
+
0x00, 0x01, 0x00, 0x21,
|
|
119
|
+
...masterKey,
|
|
120
|
+
...mac,
|
|
121
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
122
|
+
]);
|
|
123
|
+
theSonySoup.set((0, bytemanip_1.writeUint32)(generation), 4);
|
|
124
|
+
const newMac = (0, encryption_1.createIcvMac)(theSonySoup, sessionKey);
|
|
125
|
+
const finalBuffer = new Uint8Array(0x402).fill(0);
|
|
126
|
+
finalBuffer.set(newMac, 2 + theSonySoup.length);
|
|
127
|
+
finalBuffer.set(theSonySoup, 2);
|
|
128
|
+
await this.drmWrite(0x34, finalBuffer);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
exports.SonyVendorNWJSUSMCDriver = SonyVendorNWJSUSMCDriver;
|
|
132
|
+
class UMSCNWJSSession {
|
|
133
|
+
constructor(driver, fs) {
|
|
134
|
+
this.driver = driver;
|
|
135
|
+
this.fs = fs;
|
|
136
|
+
this.hostNonce = (0, utils_1.createRandomBytes)();
|
|
137
|
+
this.hostLeafId = new Uint8Array([0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
|
138
|
+
}
|
|
139
|
+
async performAuthorization() {
|
|
140
|
+
await this.driver.writeHostLeafID(this.hostLeafId, this.hostNonce);
|
|
141
|
+
const resultsStage2 = await this.driver.getAuthenticationStage2Info();
|
|
142
|
+
this.discId = resultsStage2.discId;
|
|
143
|
+
this.deviceLeafId = resultsStage2.deviceLeafId;
|
|
144
|
+
this.deviceNonce = resultsStage2.deviceNonce;
|
|
145
|
+
// Disregard device mac
|
|
146
|
+
const ekb10021Root = encryption_1.EKBROOTS[0x00010021];
|
|
147
|
+
const hostMac = (0, encryption_1.retailMac)((0, utils_1.concatUint8Arrays)([resultsStage2.discId, resultsStage2.deviceNonce, this.hostNonce]), ekb10021Root);
|
|
148
|
+
await this.driver.writeAuthenticationStage3Info(hostMac);
|
|
149
|
+
const { header, masterKey: anyKey } = await this.driver.readMasterKey();
|
|
150
|
+
this.sessionKey = (0, encryption_1.retailMac)((0, utils_1.concatUint8Arrays)([resultsStage2.discId, resultsStage2.mac, hostMac]), ekb10021Root);
|
|
151
|
+
this.currentGeneration = (0, bytemanip_1.getUint32)(header, 4);
|
|
152
|
+
this.mclistHandle = await this.fs.open("/OMGAUDIO/MACLIST0.DAT", "rw");
|
|
153
|
+
this.allMacs = await this.mclistHandle.read();
|
|
154
|
+
}
|
|
155
|
+
async finalizeSession() {
|
|
156
|
+
const ekb10021Root = encryption_1.EKBROOTS[0x00010021];
|
|
157
|
+
this.currentGeneration += 1;
|
|
158
|
+
const masterKey = new TextEncoder().encode('.DRMisBadForYou.');
|
|
159
|
+
const mac = (0, encryption_1.retailMac)((0, utils_1.concatUint8Arrays)([this.discId, this.allMacs]), (0, encryption_1.desDecrypt)(masterKey, ekb10021Root));
|
|
160
|
+
await this.driver.writeMasterKeyAndMac(this.currentGeneration, masterKey, mac, this.sessionKey);
|
|
161
|
+
await this.mclistHandle.seek(0);
|
|
162
|
+
await this.mclistHandle.write(this.allMacs);
|
|
163
|
+
await this.mclistHandle.close();
|
|
164
|
+
}
|
|
165
|
+
// trackNumber starts from 0
|
|
166
|
+
writeTrackMac(trackNumber, mac) {
|
|
167
|
+
this.allMacs.set(mac, trackNumber * 8);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
exports.UMSCNWJSSession = UMSCNWJSSession;
|
|
171
|
+
class UMSCNWJSFilesystem extends himd_js_1.UMSCHiMDFilesystem {
|
|
172
|
+
constructor(webUSB) {
|
|
173
|
+
super(webUSB);
|
|
174
|
+
this.driver = new SonyVendorNWJSUSMCDriver(webUSB, 0x06);
|
|
175
|
+
}
|
|
176
|
+
async initFS(bypassCoherencyChecks) {
|
|
177
|
+
await this.driver.inquiry();
|
|
178
|
+
await this.driver.testUnitReady();
|
|
179
|
+
const partInfo = await this.driver.getCapacity();
|
|
180
|
+
console.log(partInfo);
|
|
181
|
+
const baseDriver = await this.driver.createNUFatFSVolumeDriverFromMBRPart(0, true);
|
|
182
|
+
this.fsUncachedDriver = this.fsDriver = (0, nufatfs_1.createChunkingDriver)(baseDriver, 240, partInfo.blockSize);
|
|
183
|
+
this.fatfs = await nufatfs_1.FatFilesystem.create(this.fsDriver, bypassCoherencyChecks);
|
|
184
|
+
this.volumeSize = partInfo.deviceSize;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
exports.UMSCNWJSFilesystem = UMSCNWJSFilesystem;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CodecInfo } from "himd-js";
|
|
2
|
+
import { WebUSBDevice } from "usb";
|
|
3
|
+
import { TrackMetadata } from "./databases";
|
|
4
|
+
import { UMSCNWJSFilesystem, UMSCNWJSSession } from "./filesystem";
|
|
5
|
+
import { DatabaseAbstraction } from "./database-abstraction";
|
|
6
|
+
export declare function uploadTrack(database: DatabaseAbstraction, session: UMSCNWJSSession, trackInfo: TrackMetadata, codec: CodecInfo, rawData: Uint8Array, callback?: (done: number, outOf: number) => void): Promise<void>;
|
|
7
|
+
export declare function createNWJSFS(webUsbDevice: WebUSBDevice, bypassCoherencyChecks: boolean): Promise<UMSCNWJSFilesystem>;
|
|
8
|
+
export declare function openNewDeviceNode(): Promise<{
|
|
9
|
+
dev: WebUSBDevice;
|
|
10
|
+
name: string;
|
|
11
|
+
} | null>;
|
|
12
|
+
//# sourceMappingURL=functions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../src/functions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,YAAY,EAAa,MAAM,KAAK,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAInE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAO7D,wBAAsB,WAAW,CAC7B,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE,eAAe,EACxB,SAAS,EAAE,aAAa,EACxB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,UAAU,EACnB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,iBA2BnD;AAED,wBAAsB,YAAY,CAAC,YAAY,EAAE,YAAY,EAAE,qBAAqB,EAAE,OAAO,+BAO5F;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC;IAAE,GAAG,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA2B7F"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.openNewDeviceNode = exports.createNWJSFS = exports.uploadTrack = void 0;
|
|
4
|
+
const usb_1 = require("usb");
|
|
5
|
+
const filesystem_1 = require("./filesystem");
|
|
6
|
+
const tagged_oma_1 = require("./tagged-oma");
|
|
7
|
+
const utils_1 = require("./utils");
|
|
8
|
+
const devices_1 = require("./devices");
|
|
9
|
+
const initialization_1 = require("./initialization");
|
|
10
|
+
function resolvePathFromGlobalIndex(globalTrackIndex) {
|
|
11
|
+
return (0, utils_1.join)('OMGAUDIO', '10F00', '1000' + globalTrackIndex.toString(16).padStart(4, '0').toUpperCase() + '.OMA');
|
|
12
|
+
}
|
|
13
|
+
async function uploadTrack(database, session, trackInfo, codec, rawData, callback) {
|
|
14
|
+
// Step 1 - Create the encrypted OMA which will later be written to the device's storage
|
|
15
|
+
const encryptedOMA = (0, tagged_oma_1.createTaggedEncryptedOMA)(rawData, trackInfo, codec);
|
|
16
|
+
// Step 2 - write track to the database
|
|
17
|
+
const globalTrackIndex = database.addNewTrack({
|
|
18
|
+
...trackInfo,
|
|
19
|
+
trackDuration: encryptedOMA.duration,
|
|
20
|
+
}, codec);
|
|
21
|
+
// Step 3 - write track to the filesystem
|
|
22
|
+
const fh = await database.database.filesystem.open(resolvePathFromGlobalIndex(globalTrackIndex), 'rw');
|
|
23
|
+
const data = encryptedOMA.data;
|
|
24
|
+
let remaining = data.length;
|
|
25
|
+
let i = 0;
|
|
26
|
+
callback === null || callback === void 0 ? void 0 : callback(i, data.length);
|
|
27
|
+
while (remaining) {
|
|
28
|
+
const toWrite = Math.min(2048, remaining);
|
|
29
|
+
await fh.write(data.slice(i, i + toWrite));
|
|
30
|
+
i += toWrite;
|
|
31
|
+
remaining -= toWrite;
|
|
32
|
+
callback === null || callback === void 0 ? void 0 : callback(i, data.length);
|
|
33
|
+
}
|
|
34
|
+
await fh.close();
|
|
35
|
+
// Step 4 - write MAC
|
|
36
|
+
session.writeTrackMac(globalTrackIndex - 1, encryptedOMA.maclistValue);
|
|
37
|
+
}
|
|
38
|
+
exports.uploadTrack = uploadTrack;
|
|
39
|
+
async function createNWJSFS(webUsbDevice, bypassCoherencyChecks) {
|
|
40
|
+
// Connect into the HiMD codebase
|
|
41
|
+
const fs = new filesystem_1.UMSCNWJSFilesystem(webUsbDevice);
|
|
42
|
+
await fs.init();
|
|
43
|
+
await (0, initialization_1.initializeIfNeeded)(fs);
|
|
44
|
+
return fs;
|
|
45
|
+
}
|
|
46
|
+
exports.createNWJSFS = createNWJSFS;
|
|
47
|
+
async function openNewDeviceNode() {
|
|
48
|
+
let legacyDevice, devName = null;
|
|
49
|
+
for (let dev of devices_1.DeviceIds) {
|
|
50
|
+
legacyDevice = (0, usb_1.findByIds)(dev.vendorId, dev.productId);
|
|
51
|
+
if (legacyDevice) {
|
|
52
|
+
devName = dev.name;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (!legacyDevice) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
legacyDevice.open();
|
|
60
|
+
await new Promise(res => legacyDevice.reset(res));
|
|
61
|
+
const iface = legacyDevice.interface(0);
|
|
62
|
+
try {
|
|
63
|
+
if (iface.isKernelDriverActive())
|
|
64
|
+
iface.detachKernelDriver();
|
|
65
|
+
}
|
|
66
|
+
catch (ex) {
|
|
67
|
+
// console.log("Couldn't detach the kernel driver. Expected on Windows.");
|
|
68
|
+
}
|
|
69
|
+
const webUsbDevice = (await usb_1.WebUSBDevice.createInstance(legacyDevice));
|
|
70
|
+
await webUsbDevice.open();
|
|
71
|
+
return { dev: webUsbDevice, name: devName };
|
|
72
|
+
}
|
|
73
|
+
exports.openNewDeviceNode = openNewDeviceNode;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { WebUSBDevice } from "usb";
|
|
2
|
+
import { UMSCNWJSFilesystem } from "./filesystem";
|
|
3
|
+
export declare function resolvePathFromGlobalIndex(globalTrackIndex: number): string;
|
|
4
|
+
export declare function createNWJSFS(webUsbDevice: WebUSBDevice, bypassCoherencyChecks: boolean): Promise<UMSCNWJSFilesystem>;
|
|
5
|
+
export declare function openNewDeviceNode(): Promise<{
|
|
6
|
+
dev: WebUSBDevice;
|
|
7
|
+
name: string;
|
|
8
|
+
} | null>;
|
|
9
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAkB,MAAM,KAAK,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAKlD,wBAAgB,0BAA0B,CAAC,gBAAgB,EAAE,MAAM,UAElE;AAED,wBAAsB,YAAY,CAAC,YAAY,EAAE,YAAY,EAAE,qBAAqB,EAAE,OAAO,+BAO5F;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC;IAAE,GAAG,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA2B7F"}
|
package/dist/helpers.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.openNewDeviceNode = exports.createNWJSFS = exports.resolvePathFromGlobalIndex = void 0;
|
|
4
|
+
const usb_1 = require("usb");
|
|
5
|
+
const filesystem_1 = require("./filesystem");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
const devices_1 = require("./devices");
|
|
8
|
+
const initialization_1 = require("./initialization");
|
|
9
|
+
function resolvePathFromGlobalIndex(globalTrackIndex) {
|
|
10
|
+
return (0, utils_1.join)('OMGAUDIO', '10F00', '1000' + globalTrackIndex.toString(16).padStart(4, '0').toUpperCase() + '.OMA');
|
|
11
|
+
}
|
|
12
|
+
exports.resolvePathFromGlobalIndex = resolvePathFromGlobalIndex;
|
|
13
|
+
async function createNWJSFS(webUsbDevice, bypassCoherencyChecks) {
|
|
14
|
+
// Connect into the HiMD codebase
|
|
15
|
+
const fs = new filesystem_1.UMSCNWJSFilesystem(webUsbDevice);
|
|
16
|
+
await fs.init();
|
|
17
|
+
await (0, initialization_1.initializeIfNeeded)(fs);
|
|
18
|
+
return fs;
|
|
19
|
+
}
|
|
20
|
+
exports.createNWJSFS = createNWJSFS;
|
|
21
|
+
async function openNewDeviceNode() {
|
|
22
|
+
let legacyDevice = undefined, devName = null;
|
|
23
|
+
for (let dev of devices_1.DeviceIds) {
|
|
24
|
+
legacyDevice = (0, usb_1.findByIds)(dev.vendorId, dev.productId);
|
|
25
|
+
if (legacyDevice) {
|
|
26
|
+
devName = dev.name;
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (!legacyDevice) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
legacyDevice.open();
|
|
34
|
+
await new Promise(res => legacyDevice.reset(res));
|
|
35
|
+
const iface = legacyDevice.interface(0);
|
|
36
|
+
try {
|
|
37
|
+
if (iface.isKernelDriverActive())
|
|
38
|
+
iface.detachKernelDriver();
|
|
39
|
+
}
|
|
40
|
+
catch (ex) {
|
|
41
|
+
// console.log("Couldn't detach the kernel driver. Expected on Windows.");
|
|
42
|
+
}
|
|
43
|
+
const webUsbDevice = (await usb_1.WebUSBDevice.createInstance(legacyDevice));
|
|
44
|
+
await webUsbDevice.open();
|
|
45
|
+
return { dev: webUsbDevice, name: devName };
|
|
46
|
+
}
|
|
47
|
+
exports.openNewDeviceNode = openNewDeviceNode;
|
package/dist/id3.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ID3Tag {
|
|
2
|
+
id: string;
|
|
3
|
+
flags: number;
|
|
4
|
+
contents: Uint8Array;
|
|
5
|
+
}
|
|
6
|
+
export interface ID3Tags {
|
|
7
|
+
version: {
|
|
8
|
+
minor: number;
|
|
9
|
+
major: number;
|
|
10
|
+
};
|
|
11
|
+
tags: ID3Tag[];
|
|
12
|
+
flags: number;
|
|
13
|
+
}
|
|
14
|
+
export declare function readSynchsafeInt32(data: DataView, offset: number): [number, number];
|
|
15
|
+
export declare function parse(buffer: Uint8Array): ID3Tags;
|
|
16
|
+
export declare function serialize(tags: ID3Tags): Uint8Array;
|
|
17
|
+
export declare function encodeUTF16BEStringEA3(source: string, includeType?: boolean): Uint8Array;
|
|
18
|
+
//# sourceMappingURL=id3.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"id3.d.ts","sourceRoot":"","sources":["../src/id3.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,MAAM;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,OAAO;IACpB,OAAO,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAYnF;AAKD,wBAAgB,KAAK,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CA+CjD;AAWD,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,CAuCnD;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,UAAO,cAgCxE"}
|