@johntalton/ftdi 1.0.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.
Files changed (82) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +89 -0
  3. package/lib/consts.d.ts +33 -0
  4. package/lib/consts.d.ts.map +1 -0
  5. package/lib/consts.js +42 -0
  6. package/lib/consts.js.map +1 -0
  7. package/lib/eeprom.d.ts +129 -0
  8. package/lib/eeprom.d.ts.map +1 -0
  9. package/lib/eeprom.js +495 -0
  10. package/lib/eeprom.js.map +1 -0
  11. package/lib/ft232h.d.ts +37 -0
  12. package/lib/ft232h.d.ts.map +1 -0
  13. package/lib/ft232h.js +204 -0
  14. package/lib/ft232h.js.map +1 -0
  15. package/lib/ftdi.d.ts +37 -0
  16. package/lib/ftdi.d.ts.map +1 -0
  17. package/lib/ftdi.js +204 -0
  18. package/lib/ftdi.js.map +1 -0
  19. package/lib/i2c/i2c-template.d.ts +10 -0
  20. package/lib/i2c/i2c-template.d.ts.map +1 -0
  21. package/lib/i2c/i2c-template.js +122 -0
  22. package/lib/i2c/i2c-template.js.map +1 -0
  23. package/lib/i2c/i2c.d.ts +29 -0
  24. package/lib/i2c/i2c.d.ts.map +1 -0
  25. package/lib/i2c/i2c.js +169 -0
  26. package/lib/i2c/i2c.js.map +1 -0
  27. package/lib/i2c/index.d.ts +5 -0
  28. package/lib/i2c/index.d.ts.map +1 -0
  29. package/lib/i2c/index.js +5 -0
  30. package/lib/i2c/index.js.map +1 -0
  31. package/lib/i2c/range.d.ts +2 -0
  32. package/lib/i2c/range.d.ts.map +1 -0
  33. package/lib/i2c/range.js +6 -0
  34. package/lib/i2c/range.js.map +1 -0
  35. package/lib/index.d.ts +9 -0
  36. package/lib/index.d.ts.map +1 -0
  37. package/lib/index.js +9 -0
  38. package/lib/index.js.map +1 -0
  39. package/lib/mpsse/clock.d.ts +16 -0
  40. package/lib/mpsse/clock.d.ts.map +1 -0
  41. package/lib/mpsse/clock.js +34 -0
  42. package/lib/mpsse/clock.js.map +1 -0
  43. package/lib/mpsse/command.d.ts +66 -0
  44. package/lib/mpsse/command.d.ts.map +1 -0
  45. package/lib/mpsse/command.js +89 -0
  46. package/lib/mpsse/command.js.map +1 -0
  47. package/lib/mpsse/index.d.ts +7 -0
  48. package/lib/mpsse/index.d.ts.map +1 -0
  49. package/lib/mpsse/index.js +7 -0
  50. package/lib/mpsse/index.js.map +1 -0
  51. package/lib/mpsse/mpsse-template.d.ts +19 -0
  52. package/lib/mpsse/mpsse-template.d.ts.map +1 -0
  53. package/lib/mpsse/mpsse-template.js +81 -0
  54. package/lib/mpsse/mpsse-template.js.map +1 -0
  55. package/lib/mpsse/mpsse.d.ts +18 -0
  56. package/lib/mpsse/mpsse.d.ts.map +1 -0
  57. package/lib/mpsse/mpsse.js +77 -0
  58. package/lib/mpsse/mpsse.js.map +1 -0
  59. package/lib/status.d.ts +39 -0
  60. package/lib/status.d.ts.map +1 -0
  61. package/lib/status.js +62 -0
  62. package/lib/status.js.map +1 -0
  63. package/lib/util.d.ts +26 -0
  64. package/lib/util.d.ts.map +1 -0
  65. package/lib/util.js +57 -0
  66. package/lib/util.js.map +1 -0
  67. package/package.json +38 -0
  68. package/src/consts.ts +57 -0
  69. package/src/eeprom.ts +663 -0
  70. package/src/ftdi.ts +215 -0
  71. package/src/i2c/i2c-template.ts +156 -0
  72. package/src/i2c/i2c.ts +210 -0
  73. package/src/i2c/index.ts +4 -0
  74. package/src/i2c/range.ts +6 -0
  75. package/src/index.ts +8 -0
  76. package/src/mpsse/clock.ts +36 -0
  77. package/src/mpsse/command.ts +113 -0
  78. package/src/mpsse/index.ts +6 -0
  79. package/src/mpsse/mpsse-template.ts +96 -0
  80. package/src/mpsse/mpsse.ts +95 -0
  81. package/src/status.ts +94 -0
  82. package/src/util.ts +72 -0
package/src/eeprom.ts ADDED
@@ -0,0 +1,663 @@
1
+ /** biome-ignore-all lint/performance/noAwaitInLoops: <explanation> */
2
+ /** biome-ignore-all lint/nursery/noMisleadingReturnType: <explanation> */
3
+ /** biome-ignore-all lint/style/useConsistentArrayType: <explanation> */
4
+ /** biome-ignore-all lint/style/noExcessiveLinesPerFile: <explanation> */
5
+ /** biome-ignore-all lint/style/useDestructuring: <explanation> */
6
+ import type { FTDIDevice } from './ftdi.ts'
7
+ import {
8
+ type ChipInfo,
9
+ USB_MAJOR_TYPE_232H,
10
+ USB_MAJOR_TYPE_2232H,
11
+ USB_MAJOR_TYPE_R,
12
+ } from './util.ts'
13
+
14
+ export const MASK_16 = 0xFF_FF
15
+ export const MASK_8 = 0xFF
16
+ export const MASK_4 = 0x0F
17
+ export const MASK_3 = 0b0111
18
+
19
+
20
+ export const MAX_POWER_MILLIAMP_PER_UNIT = 2
21
+ export const USB_DESCRIPTOR_TYPE_STRING = 0x03
22
+
23
+ export const CONFIG_RESERVED_MASK = 0b1000_0000
24
+ export const CONFIG_SELF_POWERED_MASK = 0b0100_0000
25
+ export const CONFIG_REMOTE_WAKE_MASK = 0b0010_0000
26
+
27
+ export const CONFIG_IN_ISOCHRONOUS_MASK = 0b0000_0001
28
+ export const CONFIG_OUT_ISOCHRONOUS_MASK = 0b0000_0010
29
+ export const CONFIG_SUSPEND_PULL_DOWN = 0b0000_0100
30
+ export const CONFIG_USE_SERIAL = 0b0000_1000
31
+ export const CONFIG_USE_USB_VERSION = 0b0001_0000
32
+
33
+ export const CHANNEL_TYPE: Record<number, string> = {
34
+ 0: 'UART',
35
+ 1: 'FIFO',
36
+ 2: 'OPTO',
37
+ 4: 'CPU',
38
+ 8: 'FT1284'
39
+ }
40
+
41
+ export const GROUP_DRIVE: Record<number, GroupDriveInfo> = {
42
+ 0: { name: '4mA', mA: 4 },
43
+ 1: { name: '8mA', mA: 8 },
44
+ 2: { name: '12mA', mA: 12 },
45
+ 3: { name: '16mA', mA: 16 }
46
+ }
47
+
48
+ export const CBUS_FUNC_NAME_H: Record<number, string> = {
49
+ 0: 'TRISTATE',
50
+ 1: 'TXLED',
51
+ 2: 'RXLED',
52
+ 3: 'TXRXLED',
53
+ 4: 'PWREN',
54
+ 5: 'SLEEP',
55
+ 6: 'DRIVE0',
56
+ 7: 'DRIVE1',
57
+ 8: 'GPIO',
58
+ 9: 'TXDEN',
59
+ 10: 'CLK30',
60
+ 11: 'CLK15',
61
+ 12: 'CLK7_5'
62
+ }
63
+
64
+ export const CBUS_FUNC_NAME_R: Record<number, string> = {
65
+ 0: 'TXDEN',
66
+ 1: 'PWREN',
67
+ 2: 'RXLED',
68
+ 3: 'TXLED',
69
+ 4: 'TX+RXLED',
70
+ 5: 'SLEEP',
71
+ 6: 'CLK48',
72
+ 7: 'CLK24',
73
+ 8: 'CLK12',
74
+ 9: 'CLK6',
75
+ 10: 'IOMODE',
76
+ 11: 'BB_WR',
77
+ 12: 'BB_RD"'
78
+ }
79
+
80
+ export const GROUP_DRIVE_MASK = 0b0000_0011
81
+ export const SLOW_SLEW_MASK = 0b0000_0100
82
+ export const IS_SCHMITT_MASK = 0b0000_1000
83
+
84
+ export const EEPROM_CHIP_TYPE_ID = {
85
+ LC_46: 0x46, // 64 x 16-bit
86
+ LC_56: 0x56, // 128 x 16-bit
87
+ LC_66: 0x66 // 256 x 16-bit
88
+ } as const
89
+
90
+ export type EEPROMChipType = typeof EEPROM_CHIP_TYPE_ID[keyof typeof EEPROM_CHIP_TYPE_ID]
91
+
92
+ export interface EEPROMChipInfo {
93
+ id: EEPROMChipType | 0
94
+ name: string
95
+ byteLength: number
96
+ }
97
+
98
+ export const EEPROM_CHIP_TYPE_INFO: Record<string, EEPROMChipInfo> = {
99
+ [EEPROM_CHIP_TYPE_ID.LC_46]: { id: EEPROM_CHIP_TYPE_ID.LC_46, name: '93LC46 64 x 16-bit', byteLength: 128 },
100
+ [EEPROM_CHIP_TYPE_ID.LC_56]: { id: EEPROM_CHIP_TYPE_ID.LC_56, name: '93LC56 128 x 16-bit', byteLength: 256 },
101
+ [EEPROM_CHIP_TYPE_ID.LC_66]: { id: EEPROM_CHIP_TYPE_ID.LC_66, name: '93LC66 256 x 16-bit', byteLength: 512 }
102
+ }
103
+
104
+ export function eepromTypeFromValue(chipInfo: ChipInfo, value: number|undefined): EEPROMChipInfo|undefined {
105
+ if(chipInfo.major === USB_MAJOR_TYPE_R) { return { id: 0, name: 'Built-in 64 x 16-bit', byteLength: 128 } }
106
+
107
+ if(value === undefined) { return undefined }
108
+ return EEPROM_CHIP_TYPE_INFO[value]
109
+ }
110
+
111
+
112
+ export interface EEPROMInfo {
113
+ vendorId: number
114
+ productId: number
115
+ chipVersion: {
116
+ chipMajor: number
117
+ chipMinor: number
118
+ },
119
+
120
+ chipInfo: ChipInfo
121
+
122
+ eepromType: EEPROMChipInfo|undefined
123
+
124
+ config: {
125
+ _reservedHigh: boolean
126
+ selfPowered: boolean
127
+ remoteWake: boolean
128
+ maxPower: number
129
+ },
130
+
131
+ chipConfig: {
132
+ isInIsochronous: boolean
133
+ isOutIsochronous: boolean
134
+ suspendPullDowns: boolean
135
+ useSerial: boolean
136
+ useUSBVersion: boolean
137
+ },
138
+
139
+ manufacture: string|undefined
140
+ product: string|undefined
141
+ serial: string|undefined
142
+
143
+ checksumCalculated: number
144
+ checksum: number|undefined
145
+ }
146
+
147
+ export interface GroupDriveInfo {
148
+ name: string
149
+ mA: number
150
+ }
151
+
152
+ export interface GroupItem {
153
+ name: string
154
+ drive: GroupDriveInfo | undefined
155
+ isSchmitt: boolean
156
+ slowSlew: boolean
157
+ }
158
+
159
+ export const CHANNEL_DRIVE_D2XX = 'D2xx'
160
+ export const CHANNEL_DRIVE_VCP = 'VCP'
161
+
162
+ export type ChannelDrive = typeof CHANNEL_DRIVE_D2XX | typeof CHANNEL_DRIVE_VCP
163
+
164
+ export interface EEPROMInfo2232H {
165
+ channelADrive: ChannelDrive
166
+ channelAType: string | undefined
167
+
168
+ channelBDrive: ChannelDrive
169
+ channelBType: string | undefined
170
+
171
+ suspendDBUS7: boolean
172
+
173
+ group: [ GroupItem, GroupItem, GroupItem, GroupItem ],
174
+ }
175
+
176
+ export interface EEPROMInfo232H {
177
+ channelADrive: ChannelDrive
178
+ channelAType: string | undefined
179
+ clockPolarityHigh: boolean
180
+ lsbData: boolean
181
+ flowcontrol: boolean
182
+ powersave: boolean
183
+
184
+ group: [ GroupItem, GroupItem ],
185
+
186
+ cbusFunction: Array<string|undefined>
187
+
188
+ }
189
+
190
+ export interface EEPROMInfo232R {
191
+ channelADrive: ChannelDrive
192
+ highCurrent: boolean
193
+ externalOscillator: boolean
194
+
195
+ invert: {
196
+ TXD: boolean
197
+ RXD: boolean
198
+ RTS: boolean
199
+ CTS: boolean
200
+ DTR: boolean
201
+ DSR: boolean
202
+ DCD: boolean
203
+ RI: boolean
204
+ }
205
+
206
+ cbusFunction: Array<string|undefined>
207
+ }
208
+
209
+ export type ChipSpecificInfo = EEPROMInfo2232H | EEPROMInfo232H | EEPROMInfo232R | undefined
210
+
211
+ export function eepromTypeOffset(chipInfo: ChipInfo): number|undefined {
212
+ // if(chipInfo.major === USB_MAJOR_TYPE_2232C) { return 10 }// 2232C 0x14 -> 10
213
+ // this is wrong? if(major === USB_MAJOR_TYPE_R) { return 11 } // R 0x16 -> 11
214
+ if(chipInfo.major === USB_MAJOR_TYPE_2232H) { return 12 } // 2232H / 4232H 0x18 -> 12
215
+ // if(chipInfo.major === USB_MAJOR_TYPE_4232H) { return 12 } // 2232H / 4232H 0x18 -> 12
216
+ if(chipInfo.major === USB_MAJOR_TYPE_232H) { return 15 } // 232H 0x1e -> 15
217
+
218
+ return undefined
219
+ }
220
+
221
+ export class FTDIEEPROM {
222
+
223
+ static async readEEPROMBulk(device: FTDIDevice, eepromSize16: number): Promise<ArrayBufferView<ArrayBuffer>> {
224
+ const result16 = new Uint16Array(eepromSize16)
225
+ for(let i = 0; i < eepromSize16; i += 1) {
226
+ const result = await device.readEEPROM(i, 2)
227
+ result16.set([result.getUint16(0, true)], i)
228
+ }
229
+
230
+ // const buf = Uint16Array.from([
231
+ // 0x03_12,
232
+ // ...('🧟 ❤️ 🧠'.split('').map(c => c.charCodeAt(0)))
233
+ // ])
234
+ // result16.set(buf, 80)
235
+
236
+ // checksum
237
+ // const csbuf = Uint16Array.from([ 42791 ])
238
+ // result16.set(csbuf, eepromSize16 - 1)
239
+
240
+ // console.log('read eeprom result', result16)
241
+
242
+ return result16
243
+ }
244
+
245
+ static calculateChecksum(buffer16: Uint16Array, size16: number): number {
246
+ const CHECKSUM_INITIAL_VALUE = 0xAA_AA
247
+ let checksum = CHECKSUM_INITIAL_VALUE
248
+
249
+ for(let i = 0; i < (size16 - 1); i += 1) {
250
+ const value = buffer16[i]
251
+ checksum ^= value ?? 0
252
+ checksum = ((checksum << 1) | (checksum >>> (16 - 1))) & MASK_16 // rotate16
253
+ }
254
+ return checksum
255
+ }
256
+
257
+ static parseEEPROMDescriptorString(info: number, buffer16: Uint16Array, eepromSize16: number, decoder = new TextDecoder('utf-16LE')): string|undefined {
258
+ // info offset suffer from wrap-around indexing
259
+ // mask off the bits of the size to make sure index
260
+ // is withing the size.
261
+ const DESCRIPTOR_OFFSET_MASK = (eepromSize16 * 2) - 1
262
+
263
+ // info contains offset/length to the descriptor
264
+ const offset16 = (info & DESCRIPTOR_OFFSET_MASK) / 2
265
+ const length = (info >> 8) / 2
266
+
267
+ //
268
+ const prefix = buffer16[offset16]
269
+ if(prefix === undefined) {
270
+ console.warn('undefined prefix value', offset16)
271
+ return undefined
272
+ }
273
+
274
+ // descriptors have length and USB descriptor type (length includes prefix)
275
+ const prefixLength = (prefix & MASK_8) / 2
276
+ const prefixDescriptorType = prefix >> 8
277
+
278
+ if(length !== prefixLength) {
279
+ console.warn('prefix length disagrees with info length', prefixLength, length)
280
+ return undefined
281
+ }
282
+
283
+ if(prefixDescriptorType !== USB_DESCRIPTOR_TYPE_STRING) {
284
+ console.warn('USB Descriptor type is not String', prefixDescriptorType)
285
+ return undefined
286
+ }
287
+
288
+ // skip the string prefix (reduce size by one)
289
+ const begin = offset16 + 1
290
+ const end = begin + length - 1
291
+ const buffer = buffer16.subarray(begin, end)
292
+
293
+ // decode utf-16le
294
+ return decoder.decode(buffer)
295
+ }
296
+
297
+ static parseEEPROM_FT2232H(buffer: ArrayBufferView<ArrayBuffer>|ArrayBuffer, _chipInfo: ChipInfo): EEPROMInfo2232H | undefined {
298
+ const u16 = ArrayBuffer.isView(buffer) ?
299
+ new Uint16Array(buffer.buffer, buffer.byteOffset) :
300
+ new Uint16Array(buffer)
301
+
302
+ const DRIVE_MASK = 0b0000_1000
303
+ const SUSPEND_DBUS_7_MASK = 0b1000_0000
304
+
305
+ const control = u16[0]
306
+ const groupConfig = u16[6]
307
+
308
+ if(control === undefined) { return undefined }
309
+ if(groupConfig === undefined) { return undefined }
310
+
311
+ const controlH = (control >> 8) & MASK_8 // 1
312
+ const controlL = control & MASK_8 // 0
313
+
314
+ const channelAType = CHANNEL_TYPE[controlL & MASK_3]
315
+ const channelBType = CHANNEL_TYPE[controlH & MASK_3]
316
+
317
+ const channelADrive = ((controlL & DRIVE_MASK) === DRIVE_MASK) ? CHANNEL_DRIVE_VCP : CHANNEL_DRIVE_D2XX
318
+ const channelBDrive = ((controlH & DRIVE_MASK) === DRIVE_MASK) ? CHANNEL_DRIVE_VCP : CHANNEL_DRIVE_D2XX
319
+
320
+ const suspendDBUS7 = (controlH & SUSPEND_DBUS_7_MASK) === SUSPEND_DBUS_7_MASK
321
+
322
+ const groupConfigH = (groupConfig >> 8) & MASK_8 // d
323
+ const groupConfigL = groupConfig & MASK_8 // c
324
+
325
+ const groupConfigHH = (groupConfigH >> 4) & MASK_4 // 3
326
+ const groupConfigHL = groupConfigH & MASK_4 // 2
327
+ const groupConfigLH = (groupConfigL >> 4) & MASK_4 // 1
328
+ const groupConfigLL = groupConfigL & MASK_4 // 0
329
+
330
+ const group: [ GroupItem, GroupItem, GroupItem, GroupItem ] = [
331
+ {
332
+ name: 'AL',
333
+ drive: GROUP_DRIVE[(groupConfigLL & GROUP_DRIVE_MASK)],
334
+ isSchmitt: (groupConfigLL & IS_SCHMITT_MASK) === IS_SCHMITT_MASK,
335
+ slowSlew: (groupConfigLL & SLOW_SLEW_MASK) === SLOW_SLEW_MASK
336
+ },
337
+ {
338
+ name: 'AH',
339
+ drive: GROUP_DRIVE[(groupConfigLH & GROUP_DRIVE_MASK)],
340
+ isSchmitt: (groupConfigLH & IS_SCHMITT_MASK) === IS_SCHMITT_MASK,
341
+ slowSlew: (groupConfigLH & SLOW_SLEW_MASK) === SLOW_SLEW_MASK
342
+ },
343
+ {
344
+ name: 'BL',
345
+ drive: GROUP_DRIVE[(groupConfigHL & GROUP_DRIVE_MASK)],
346
+ isSchmitt: (groupConfigHL & IS_SCHMITT_MASK) === IS_SCHMITT_MASK,
347
+ slowSlew: (groupConfigHL & SLOW_SLEW_MASK) === SLOW_SLEW_MASK
348
+ },
349
+ {
350
+ name: 'BH',
351
+ drive: GROUP_DRIVE[(groupConfigHH & GROUP_DRIVE_MASK)],
352
+ isSchmitt: (groupConfigHH & IS_SCHMITT_MASK) === IS_SCHMITT_MASK,
353
+ slowSlew: (groupConfigHH & SLOW_SLEW_MASK) === SLOW_SLEW_MASK
354
+ }
355
+ ]
356
+
357
+ return {
358
+ channelAType,
359
+ channelBType,
360
+ channelADrive,
361
+ channelBDrive,
362
+
363
+ suspendDBUS7,
364
+
365
+ group
366
+ }
367
+ }
368
+
369
+ static parseEEPROM_232H(buffer: ArrayBufferView<ArrayBuffer>|ArrayBuffer, _chipInfo: ChipInfo): EEPROMInfo232H | undefined {
370
+ const u16 = ArrayBuffer.isView(buffer) ?
371
+ new Uint16Array(buffer.buffer, buffer.byteOffset) :
372
+ new Uint16Array(buffer)
373
+
374
+ const DRIVE_H_MASK = 0b0001_0000
375
+ const FT1284_CLOCK_STATE_MASK = 0b0000_0001
376
+ const FT1284_DATA_LSB_MASK = 0b0000_0010
377
+ const FT1284_FLOW_CONTROL_MASK = 0b0000_0100
378
+ const POWER_SAVE_DISABLE_H_MASK = 0b0000_1000
379
+
380
+ const control = u16[0]
381
+ const groupConfig = u16[6]
382
+
383
+ const cbusFunction0123 = u16[12] // 3 2 1 0
384
+ const cbusFunction4567 = u16[13] // 7 6 5 4
385
+ const cbusFunction89 = u16[14] // x x 9 8
386
+
387
+ if(control === undefined) { return undefined }
388
+ if(groupConfig === undefined) { return undefined }
389
+ if(cbusFunction0123 === undefined) { return undefined }
390
+ if(cbusFunction4567 === undefined) { return undefined }
391
+ if(cbusFunction89 === undefined) { return undefined }
392
+
393
+ const controlH = (control >> 8) & MASK_8 // 1
394
+ const controlL = control & MASK_8 // 0
395
+
396
+ const channelADrive = ((controlL & DRIVE_H_MASK) === DRIVE_H_MASK) ? CHANNEL_DRIVE_VCP : CHANNEL_DRIVE_D2XX
397
+ const channelAType = CHANNEL_TYPE[controlL & MASK_4]
398
+
399
+ const clockPolarityHigh = (controlH & FT1284_CLOCK_STATE_MASK) === FT1284_CLOCK_STATE_MASK
400
+ const lsbData = (controlH & FT1284_DATA_LSB_MASK) === FT1284_DATA_LSB_MASK
401
+ const flowcontrol = (controlH & FT1284_FLOW_CONTROL_MASK) === FT1284_FLOW_CONTROL_MASK
402
+ const powersave = (controlH & POWER_SAVE_DISABLE_H_MASK) === POWER_SAVE_DISABLE_H_MASK
403
+
404
+ const groupConfigH = (groupConfig >> 8) & MASK_8 // d
405
+ const groupConfigL = groupConfig & MASK_8 // c
406
+
407
+ const group: [ GroupItem, GroupItem ] = [
408
+ {
409
+ name: 'ACBUS',
410
+ drive: GROUP_DRIVE[(groupConfigL & GROUP_DRIVE_MASK)],
411
+ isSchmitt: (groupConfigL & IS_SCHMITT_MASK) === IS_SCHMITT_MASK,
412
+ slowSlew: (groupConfigL & SLOW_SLEW_MASK) === SLOW_SLEW_MASK
413
+ },
414
+ {
415
+ name: 'ADBUS',
416
+ drive: GROUP_DRIVE[(groupConfigH & GROUP_DRIVE_MASK)],
417
+ isSchmitt: (groupConfigH & IS_SCHMITT_MASK) === IS_SCHMITT_MASK,
418
+ slowSlew: (groupConfigH & SLOW_SLEW_MASK) === SLOW_SLEW_MASK
419
+ }
420
+ ]
421
+
422
+ const cbusFunc0 = (cbusFunction0123 >> 0) & MASK_4
423
+ const cbusFunc1 = (cbusFunction0123 >> 4) & MASK_4
424
+ const cbusFunc2 = (cbusFunction0123 >> 8) & MASK_4
425
+ const cbusFunc3 = (cbusFunction0123 >> 12) & MASK_4
426
+
427
+ const cbusFunc4 = (cbusFunction4567 >> 0) & MASK_4
428
+ const cbusFunc5 = (cbusFunction4567 >> 4) & MASK_4
429
+ const cbusFunc6 = (cbusFunction4567 >> 8) & MASK_4
430
+ const cbusFunc7 = (cbusFunction4567 >> 12) & MASK_4
431
+
432
+ const cbusFunc8 = (cbusFunction89 >> 0) & MASK_4
433
+ const cbusFunc9 = (cbusFunction89 >> 4) & MASK_4
434
+
435
+ return {
436
+ channelADrive,
437
+ channelAType,
438
+ clockPolarityHigh,
439
+ lsbData,
440
+ flowcontrol,
441
+ powersave,
442
+
443
+ group,
444
+
445
+ cbusFunction: [
446
+ CBUS_FUNC_NAME_H[cbusFunc0],
447
+ CBUS_FUNC_NAME_H[cbusFunc1],
448
+ CBUS_FUNC_NAME_H[cbusFunc2],
449
+ CBUS_FUNC_NAME_H[cbusFunc3],
450
+ CBUS_FUNC_NAME_H[cbusFunc4],
451
+ CBUS_FUNC_NAME_H[cbusFunc5],
452
+ CBUS_FUNC_NAME_H[cbusFunc6],
453
+ CBUS_FUNC_NAME_H[cbusFunc7],
454
+ CBUS_FUNC_NAME_H[cbusFunc8],
455
+ CBUS_FUNC_NAME_H[cbusFunc9]
456
+ ]
457
+ }
458
+ }
459
+
460
+ static parseEEPROM_232R(buffer: ArrayBufferView<ArrayBuffer>|ArrayBuffer, _chipInfo: ChipInfo): EEPROMInfo232R | undefined {
461
+ const u16 = ArrayBuffer.isView(buffer) ?
462
+ new Uint16Array(buffer.buffer, buffer.byteOffset) :
463
+ new Uint16Array(buffer)
464
+
465
+ const DRIVE_MASK = 0b0000_1000
466
+ const HIGH_CURRENT_MASK = 0b0000_0100
467
+ const EXTERNAL_OSCILLATOR_MASK = 0b0000_0010
468
+
469
+ // const ENDPOINT_SIZE_MASK = 0b0100_0000
470
+
471
+ const INVERT_TXD_MASK = 0b0000_0001
472
+ const INVERT_RXD_MASK = 0b0000_0010
473
+ const INVERT_RTS_MASK = 0b0000_0100
474
+ const INVERT_CTS_MASK = 0b0000_1000
475
+ const INVERT_DTR_MASK = 0b0001_0000
476
+ const INVERT_DSR_MASK = 0b0010_0000
477
+ const INVERT_DCD_MASK = 0b0100_0000
478
+ const INVERT_RI_MASK = 0b1000_0000
479
+
480
+ const control = u16[0]
481
+ const config = u16[5]
482
+
483
+ const cbusFunction0123 = u16[10] // 3 2 1 0
484
+ const cbusFunction4 = u16[11] // x x x 4
485
+
486
+ if(control === undefined) { return undefined }
487
+ if(config === undefined) { return undefined }
488
+ if(cbusFunction0123 === undefined) { return undefined }
489
+ if(cbusFunction4 === undefined) { return undefined }
490
+
491
+ const controlH = (control >> 8) & MASK_8 // 1
492
+ const controlL = control & MASK_8 // 0
493
+
494
+ const invertH = (config >> 8) & MASK_8 // 11
495
+
496
+ const channelADrive = ((controlL & DRIVE_MASK) === DRIVE_MASK) ? CHANNEL_DRIVE_D2XX : CHANNEL_DRIVE_VCP
497
+ const highCurrent = (controlH & HIGH_CURRENT_MASK) === HIGH_CURRENT_MASK
498
+ const externalOscillator = (controlH & EXTERNAL_OSCILLATOR_MASK) === EXTERNAL_OSCILLATOR_MASK
499
+
500
+ // const endpointSize = (controlL & ENDPOINT_SIZE_MASK) === ENDPOINT_SIZE_MASK
501
+
502
+ const invert = {
503
+ TXD: (invertH & INVERT_TXD_MASK) === INVERT_TXD_MASK,
504
+ RXD: (invertH & INVERT_RXD_MASK) === INVERT_RXD_MASK,
505
+ RTS: (invertH & INVERT_RTS_MASK) === INVERT_RTS_MASK,
506
+ CTS: (invertH & INVERT_CTS_MASK) === INVERT_CTS_MASK,
507
+ DTR: (invertH & INVERT_DTR_MASK) === INVERT_DTR_MASK,
508
+ DSR: (invertH & INVERT_DSR_MASK) === INVERT_DSR_MASK,
509
+ DCD: (invertH & INVERT_DCD_MASK) === INVERT_DCD_MASK,
510
+ RI: (invertH & INVERT_RI_MASK) === INVERT_RI_MASK
511
+ }
512
+
513
+ const cbusFunc0 = (cbusFunction0123 >> 0) & MASK_4
514
+ const cbusFunc1 = (cbusFunction0123 >> 4) & MASK_4
515
+ const cbusFunc2 = (cbusFunction0123 >> 8) & MASK_4
516
+ const cbusFunc3 = (cbusFunction0123 >> 12) & MASK_4
517
+
518
+ const cbusFunc4 = (cbusFunction4 >> 0) & MASK_4
519
+
520
+ return {
521
+ channelADrive,
522
+ highCurrent,
523
+ externalOscillator,
524
+
525
+ invert,
526
+
527
+ cbusFunction: [
528
+ CBUS_FUNC_NAME_R[cbusFunc0],
529
+ CBUS_FUNC_NAME_R[cbusFunc1],
530
+ CBUS_FUNC_NAME_R[cbusFunc2],
531
+ CBUS_FUNC_NAME_R[cbusFunc3],
532
+ CBUS_FUNC_NAME_R[cbusFunc4]
533
+ ]
534
+ }
535
+ }
536
+
537
+ static parseEEPROM_ChipSpecific(buffer: ArrayBufferView<ArrayBuffer|ArrayBuffer>, chipInfo: ChipInfo): ChipSpecificInfo {
538
+ // if(chipInfo.major === USB_MAJOR_TYPE_BM) { return FTDIEEPROM.parseEEPROM_FT2232BM(buffer, chipInfo) }
539
+ if(chipInfo.major === USB_MAJOR_TYPE_R) { return FTDIEEPROM.parseEEPROM_232R(buffer, chipInfo) }
540
+ if(chipInfo.major === USB_MAJOR_TYPE_2232H) { return FTDIEEPROM.parseEEPROM_FT2232H(buffer, chipInfo) }
541
+ if(chipInfo.major === USB_MAJOR_TYPE_232H) { return FTDIEEPROM.parseEEPROM_232H(buffer, chipInfo) }
542
+
543
+ return undefined
544
+ }
545
+
546
+ static parseEEPROM(buffer: ArrayBufferView<ArrayBuffer|ArrayBuffer>, chipInfo: ChipInfo): EEPROMInfo|undefined {
547
+ const u16 = ArrayBuffer.isView(buffer) ?
548
+ new Uint16Array(buffer.buffer, buffer.byteOffset) :
549
+ new Uint16Array(buffer)
550
+
551
+ // cache the chip info as it will be updated
552
+ // to reflect the values used when parsing
553
+ const usedChipInfo = { ...chipInfo }
554
+
555
+ usedChipInfo.eepromSize = chipInfo.eepromSize ?? u16.length
556
+ console.log('using eepromSize16', usedChipInfo.eepromSize)
557
+ console.log('with u16 array length', u16.length)
558
+
559
+ const checksumCalculated = FTDIEEPROM.calculateChecksum(u16, usedChipInfo.eepromSize)
560
+ const checksum = u16[usedChipInfo.eepromSize - 1]
561
+
562
+ // const header = u16[0]
563
+ const vendorId = u16[1]
564
+ const productId = u16[2]
565
+ const type = u16[3]
566
+ const config = u16[4]
567
+ const chipConfig = u16[5]
568
+ // const _groupConfig = u16[6]
569
+ const manufactureInfo = u16[7]
570
+ const productInfo = u16[8]
571
+ const serialInfo = u16[9]
572
+
573
+ //
574
+ if(type === undefined) { return undefined }
575
+ const chipMajor = type >> 8 // 7
576
+ const chipMinor = type & MASK_8 // 6
577
+
578
+ //
579
+ usedChipInfo.major = usedChipInfo.major ?? chipMajor
580
+ usedChipInfo.minor = usedChipInfo.minor ?? chipMinor
581
+
582
+ //
583
+ const chipOffset = eepromTypeOffset(usedChipInfo)
584
+ const eepromType = eepromTypeFromValue(usedChipInfo, chipOffset ? u16[chipOffset]: undefined)
585
+
586
+ if(eepromType !== undefined && ((eepromType.byteLength/2) !== usedChipInfo.eepromSize)) {
587
+ console.log('Used ChipInfo byteLength does not match Detected EEPROM byteLength', eepromType.byteLength/2, usedChipInfo.eepromSize)
588
+ }
589
+
590
+ //
591
+ if(vendorId === undefined) { return undefined }
592
+ if(productId === undefined) { return undefined }
593
+ if(config === undefined) { return undefined }
594
+ if(chipConfig === undefined) { return undefined }
595
+ if(manufactureInfo === undefined) { return undefined }
596
+ if(productInfo === undefined) { return undefined }
597
+ if(serialInfo === undefined) { return undefined }
598
+
599
+ //
600
+ const configH = config >> 8 // 9
601
+ const configL = config & MASK_8 // 8
602
+ const _reservedHigh = (configL & CONFIG_RESERVED_MASK) === CONFIG_RESERVED_MASK
603
+ const selfPowered = (configL & CONFIG_SELF_POWERED_MASK) === CONFIG_SELF_POWERED_MASK
604
+ const remoteWake = (configL & CONFIG_REMOTE_WAKE_MASK) === CONFIG_REMOTE_WAKE_MASK
605
+
606
+ const maxPower = configH * MAX_POWER_MILLIAMP_PER_UNIT
607
+
608
+ //
609
+ // const chipConfigH = chipConfig >> 8 // 11
610
+ const chipConfigL = chipConfig & MASK_8 // 10
611
+ const isInIsochronous = (chipConfigL & CONFIG_IN_ISOCHRONOUS_MASK) === CONFIG_IN_ISOCHRONOUS_MASK
612
+ const isOutIsochronous = (chipConfigL & CONFIG_OUT_ISOCHRONOUS_MASK) === CONFIG_OUT_ISOCHRONOUS_MASK
613
+ const suspendPullDowns = (chipConfigL & CONFIG_SUSPEND_PULL_DOWN) === CONFIG_SUSPEND_PULL_DOWN
614
+ const useSerial = (chipConfigL & CONFIG_USE_SERIAL) === CONFIG_USE_SERIAL
615
+ const useUSBVersion = (chipConfigL & CONFIG_USE_USB_VERSION) === CONFIG_USE_USB_VERSION
616
+
617
+ //
618
+ const decoder = new TextDecoder('utf-16le') // per-USB descriptor spec
619
+ const manufactureStr = FTDIEEPROM.parseEEPROMDescriptorString(manufactureInfo, u16, usedChipInfo.eepromSize, decoder)
620
+ const productStr = FTDIEEPROM.parseEEPROMDescriptorString(productInfo, u16, usedChipInfo.eepromSize, decoder)
621
+ const serialStr = FTDIEEPROM.parseEEPROMDescriptorString(serialInfo, u16, usedChipInfo.eepromSize, decoder)
622
+
623
+ //
624
+ const chipSpecificInfo = FTDIEEPROM.parseEEPROM_ChipSpecific(buffer, usedChipInfo) ?? {}
625
+
626
+ return {
627
+ vendorId,
628
+ productId,
629
+
630
+ chipVersion: {
631
+ chipMajor,
632
+ chipMinor,
633
+ },
634
+ chipInfo: usedChipInfo,
635
+
636
+ eepromType,
637
+
638
+ config: {
639
+ _reservedHigh,
640
+ selfPowered,
641
+ remoteWake,
642
+ maxPower
643
+ },
644
+
645
+ chipConfig: {
646
+ isInIsochronous,
647
+ isOutIsochronous,
648
+ suspendPullDowns,
649
+ useSerial,
650
+ useUSBVersion
651
+ },
652
+
653
+ manufacture: manufactureStr,
654
+ product: productStr,
655
+ serial: serialStr,
656
+
657
+ ...chipSpecificInfo,
658
+
659
+ checksumCalculated,
660
+ checksum
661
+ }
662
+ }
663
+ }