or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

constants-errors.mddata-transfers.mddescriptors.mddevice-communication.mddevice-management.mdevent-handling.mdindex.mdinterfaces-endpoints.mdwebusb-api.md

interfaces-endpoints.mddocs/

0

# Interface and Endpoint Management

1

2

Interface and endpoint management provides methods to claim USB interfaces and manage data endpoints for bulk and interrupt transfers. This includes interface claiming/releasing, alternate setting management, and endpoint access.

3

4

## Capabilities

5

6

### Interface Access

7

8

Access and manage USB interfaces on a device.

9

10

```typescript { .api }

11

/**

12

* Return the interface with the specified interface number

13

* The device must be open to use this method

14

* @param addr - Interface number (default: 0)

15

* @returns Interface object

16

*/

17

interface(addr: number): Interface;

18

19

/**

20

* USB Interface class for device communication

21

*/

22

interface Interface {

23

/** Integer interface number */

24

interfaceNumber: number;

25

26

/** Integer alternate setting number */

27

altSetting: number;

28

29

/** Object with fields from the interface descriptor */

30

descriptor: InterfaceDescriptor;

31

32

/** List of endpoints on this interface: InEndpoint and OutEndpoint objects */

33

endpoints: Endpoint[];

34

}

35

```

36

37

**Usage Examples:**

38

39

```typescript

40

import { findByIds } from 'usb';

41

42

const device = findByIds(0x1234, 0x5678);

43

if (device) {

44

device.open();

45

46

// Get the first interface (interface 0)

47

const interface0 = device.interface(0);

48

console.log(`Interface Number: ${interface0.interfaceNumber}`);

49

console.log(`Alternate Setting: ${interface0.altSetting}`);

50

console.log(`Interface Class: ${interface0.descriptor.bInterfaceClass}`);

51

console.log(`Number of Endpoints: ${interface0.endpoints.length}`);

52

53

// Access interface descriptor properties

54

const desc = interface0.descriptor;

55

console.log('Interface Descriptor:');

56

console.log(` Class: ${desc.bInterfaceClass}`);

57

console.log(` Subclass: ${desc.bInterfaceSubClass}`);

58

console.log(` Protocol: ${desc.bInterfaceProtocol}`);

59

console.log(` Endpoints: ${desc.bNumEndpoints}`);

60

61

device.close();

62

}

63

```

64

65

### Interface Claiming and Releasing

66

67

Claim interfaces for exclusive access and release them when done.

68

69

```typescript { .api }

70

/**

71

* Claims the interface. This method must be called before using any endpoints of this interface.

72

* The device must be open to use this method.

73

*/

74

claim(): void;

75

76

/**

77

* Releases the interface and resets the alternate setting. Calls callback when complete.

78

* It is an error to release an interface with pending transfers.

79

* @param callback - Completion callback

80

*/

81

release(callback?: (error?: LibUSBException) => void): void;

82

83

/**

84

* Releases the interface with optional endpoint stream control

85

* @param closeEndpoints - If true, any active endpoint streams are stopped

86

* @param callback - Completion callback

87

*/

88

release(closeEndpoints?: boolean, callback?: (error?: LibUSBException) => void): void;

89

90

/**

91

* Async version of release

92

*/

93

releaseAsync(): Promise<void>;

94

```

95

96

**Usage Examples:**

97

98

```typescript

99

import { findByIds } from 'usb';

100

101

const device = findByIds(0x1234, 0x5678);

102

if (device) {

103

device.open();

104

105

const interface0 = device.interface(0);

106

107

try {

108

// Claim the interface for exclusive access

109

interface0.claim();

110

console.log('Interface claimed successfully');

111

112

// Now you can use the interface endpoints

113

console.log(`Interface has ${interface0.endpoints.length} endpoints`);

114

115

// Use endpoints here...

116

117

// Release the interface when done (callback version)

118

interface0.release((error) => {

119

if (error) {

120

console.error('Failed to release interface:', error.message);

121

} else {

122

console.log('Interface released successfully');

123

}

124

device.close();

125

});

126

127

} catch (error) {

128

console.error('Failed to claim interface:', error);

129

device.close();

130

}

131

}

132

133

// Using async/await pattern

134

async function useInterfaceAsync() {

135

const device = findByIds(0x1234, 0x5678);

136

if (!device) return;

137

138

device.open();

139

const interface0 = device.interface(0);

140

141

try {

142

interface0.claim();

143

console.log('Interface claimed');

144

145

// Use interface...

146

147

// Release with async

148

await interface0.releaseAsync();

149

console.log('Interface released');

150

151

} catch (error) {

152

console.error('Interface error:', error);

153

} finally {

154

device.close();

155

}

156

}

157

158

// Release with endpoint stream closure

159

const deviceWithStreams = findByIds(0x5678, 0x1234);

160

if (deviceWithStreams) {

161

deviceWithStreams.open();

162

const interface0 = deviceWithStreams.interface(0);

163

164

interface0.claim();

165

166

// ... start some endpoint streams/polling ...

167

168

// Release and stop all endpoint streams

169

interface0.release(true, (error) => {

170

if (!error) {

171

console.log('Interface released and all endpoint streams stopped');

172

}

173

deviceWithStreams.close();

174

});

175

}

176

```

177

178

### Alternate Setting Management

179

180

Manage alternate interface settings.

181

182

```typescript { .api }

183

/**

184

* Sets the alternate setting. It updates the interface.endpoints array

185

* to reflect the endpoints found in the alternate setting.

186

* The device must be open to use this method.

187

* @param altSetting - Alternate setting number

188

* @param callback - Completion callback

189

*/

190

setAltSetting(altSetting: number, callback?: (error?: LibUSBException) => void): void;

191

192

/**

193

* Async version of setAltSetting

194

* @param alternateSetting - Alternate setting number

195

*/

196

setAltSettingAsync(alternateSetting: number): Promise<void>;

197

```

198

199

**Usage Examples:**

200

201

```typescript

202

import { findByIds } from 'usb';

203

204

const device = findByIds(0x1234, 0x5678);

205

if (device) {

206

device.open();

207

const interface0 = device.interface(0);

208

209

interface0.claim();

210

211

console.log(`Current alternate setting: ${interface0.altSetting}`);

212

console.log(`Current endpoints: ${interface0.endpoints.length}`);

213

214

// Set alternate setting 1

215

interface0.setAltSetting(1, (error) => {

216

if (error) {

217

console.error('Failed to set alternate setting:', error.message);

218

return;

219

}

220

221

console.log(`New alternate setting: ${interface0.altSetting}`);

222

console.log(`New endpoints: ${interface0.endpoints.length}`);

223

224

// The endpoints array has been updated to reflect the new setting

225

interface0.endpoints.forEach((endpoint, index) => {

226

console.log(` Endpoint ${index}: 0x${endpoint.address.toString(16)}, ${endpoint.direction}`);

227

});

228

229

interface0.release(() => device.close());

230

});

231

}

232

233

// Using async/await

234

async function setAltSettingAsync() {

235

const device = findByIds(0x1234, 0x5678);

236

if (!device) return;

237

238

device.open();

239

const interface0 = device.interface(0);

240

241

try {

242

interface0.claim();

243

244

// Set alternate setting using async method

245

await interface0.setAltSettingAsync(2);

246

console.log('Alternate setting 2 activated');

247

248

await interface0.releaseAsync();

249

} catch (error) {

250

console.error('Error setting alternate setting:', error);

251

} finally {

252

device.close();

253

}

254

}

255

```

256

257

### Kernel Driver Management

258

259

Manage kernel driver attachment/detachment for interfaces.

260

261

```typescript { .api }

262

/**

263

* Returns false if a kernel driver is not active; true if active.

264

* The device must be open to use this method.

265

*/

266

isKernelDriverActive(): boolean;

267

268

/**

269

* Detaches the kernel driver from the interface.

270

* The device must be open to use this method.

271

*/

272

detachKernelDriver(): void;

273

274

/**

275

* Re-attaches the kernel driver for the interface.

276

* The device must be open to use this method.

277

*/

278

attachKernelDriver(): void;

279

```

280

281

**Usage Examples:**

282

283

```typescript

284

import { findByIds } from 'usb';

285

286

const device = findByIds(0x1234, 0x5678);

287

if (device) {

288

device.open();

289

const interface0 = device.interface(0);

290

291

// Check if kernel driver is active

292

if (interface0.isKernelDriverActive()) {

293

console.log('Kernel driver is active, need to detach');

294

295

try {

296

// Detach kernel driver

297

interface0.detachKernelDriver();

298

console.log('Kernel driver detached');

299

300

// Now we can claim the interface

301

interface0.claim();

302

console.log('Interface claimed after detaching kernel driver');

303

304

// Use interface...

305

306

// Release interface

307

interface0.release((error) => {

308

if (!error) {

309

// Reattach kernel driver

310

try {

311

interface0.attachKernelDriver();

312

console.log('Kernel driver reattached');

313

} catch (attachError) {

314

console.warn('Could not reattach kernel driver:', attachError);

315

}

316

}

317

device.close();

318

});

319

320

} catch (error) {

321

console.error('Failed to detach kernel driver:', error);

322

device.close();

323

}

324

} else {

325

console.log('No kernel driver active');

326

interface0.claim();

327

// ... use interface ...

328

interface0.release(() => device.close());

329

}

330

}

331

332

// Safe kernel driver management pattern

333

function safeInterfaceAccess(device: Device, interfaceNumber: number) {

334

const interface0 = device.interface(interfaceNumber);

335

let kernelDriverWasActive = false;

336

337

try {

338

// Check and detach kernel driver if needed

339

if (interface0.isKernelDriverActive()) {

340

kernelDriverWasActive = true;

341

interface0.detachKernelDriver();

342

console.log('Kernel driver detached');

343

}

344

345

// Claim interface

346

interface0.claim();

347

console.log('Interface claimed');

348

349

return {

350

interface: interface0,

351

cleanup: (callback?: () => void) => {

352

interface0.release((error) => {

353

if (!error && kernelDriverWasActive) {

354

try {

355

interface0.attachKernelDriver();

356

console.log('Kernel driver reattached');

357

} catch (attachError) {

358

console.warn('Could not reattach kernel driver');

359

}

360

}

361

if (callback) callback();

362

});

363

}

364

};

365

366

} catch (error) {

367

console.error('Failed to access interface:', error);

368

throw error;

369

}

370

}

371

```

372

373

### Endpoint Access

374

375

Access and manage endpoints on interfaces.

376

377

```typescript { .api }

378

/**

379

* Return the InEndpoint or OutEndpoint with the specified address.

380

* The device must be open to use this method.

381

* @param addr - Endpoint address

382

* @returns Endpoint object or undefined if not found

383

*/

384

endpoint(addr: number): Endpoint | undefined;

385

386

/**

387

* Base endpoint interface

388

*/

389

interface Endpoint {

390

/** Endpoint address */

391

address: number;

392

393

/** Endpoint direction: "in" or "out" */

394

direction: 'in' | 'out';

395

396

/** Endpoint type: BULK, INTERRUPT, etc. */

397

transferType: number;

398

399

/** Sets the timeout in milliseconds for transfers on this endpoint */

400

timeout: number;

401

402

/** Object with fields from the endpoint descriptor */

403

descriptor: EndpointDescriptor;

404

}

405

```

406

407

**Usage Examples:**

408

409

```typescript

410

import { findByIds, LIBUSB_TRANSFER_TYPE_BULK, LIBUSB_TRANSFER_TYPE_INTERRUPT } from 'usb';

411

412

const device = findByIds(0x1234, 0x5678);

413

if (device) {

414

device.open();

415

const interface0 = device.interface(0);

416

interface0.claim();

417

418

// List all endpoints

419

console.log('Available endpoints:');

420

interface0.endpoints.forEach((endpoint, index) => {

421

console.log(` Endpoint ${index}:`);

422

console.log(` Address: 0x${endpoint.address.toString(16)}`);

423

console.log(` Direction: ${endpoint.direction}`);

424

console.log(` Type: ${endpoint.transferType === LIBUSB_TRANSFER_TYPE_BULK ? 'BULK' :

425

endpoint.transferType === LIBUSB_TRANSFER_TYPE_INTERRUPT ? 'INTERRUPT' : 'OTHER'}`);

426

console.log(` Max Packet Size: ${endpoint.descriptor.wMaxPacketSize}`);

427

});

428

429

// Find specific endpoint by address

430

const endpoint1 = interface0.endpoint(0x81); // IN endpoint 1

431

if (endpoint1) {

432

console.log(`Found IN endpoint: 0x${endpoint1.address.toString(16)}`);

433

console.log(`Direction: ${endpoint1.direction}`);

434

435

// Configure endpoint timeout

436

endpoint1.timeout = 5000; // 5 second timeout

437

console.log(`Set endpoint timeout to ${endpoint1.timeout}ms`);

438

}

439

440

// Find OUT endpoint

441

const outEndpoint = interface0.endpoint(0x02); // OUT endpoint 2

442

if (outEndpoint) {

443

console.log(`Found OUT endpoint: 0x${outEndpoint.address.toString(16)}`);

444

console.log(`Max packet size: ${outEndpoint.descriptor.wMaxPacketSize}`);

445

}

446

447

// Find endpoints by direction

448

const inEndpoints = interface0.endpoints.filter(ep => ep.direction === 'in');

449

const outEndpoints = interface0.endpoints.filter(ep => ep.direction === 'out');

450

451

console.log(`Found ${inEndpoints.length} IN endpoints and ${outEndpoints.length} OUT endpoints`);

452

453

interface0.release(() => device.close());

454

}

455

456

// Helper function to find endpoints by type

457

function findEndpointsByType(interface0: Interface, transferType: number) {

458

return interface0.endpoints.filter(endpoint => endpoint.transferType === transferType);

459

}

460

461

// Usage

462

const device2 = findByIds(0x5678, 0x1234);

463

if (device2) {

464

device2.open();

465

const interface0 = device2.interface(0);

466

interface0.claim();

467

468

// Find all bulk endpoints

469

const bulkEndpoints = findEndpointsByType(interface0, LIBUSB_TRANSFER_TYPE_BULK);

470

console.log(`Found ${bulkEndpoints.length} bulk endpoints`);

471

472

// Find all interrupt endpoints

473

const interruptEndpoints = findEndpointsByType(interface0, LIBUSB_TRANSFER_TYPE_INTERRUPT);

474

console.log(`Found ${interruptEndpoints.length} interrupt endpoints`);

475

476

interface0.release(() => device2.close());

477

}

478

```