ben-arduino-usb

Annotated test.c

20:d64ec78641fc
2013-02-24 Paul Boddie Added clearing of the handshake/timeout interrupt. Fixed previously erroneous/deficient communication by moving address register setting out of individual functions and making sure it only gets set once per transaction, adding initialisation of the data toggle for the inbound control transfer associated with the device descriptor, testing for the HRSLT status and not inadvertently exiting the loop waiting for received data. Added a timeout for waiting for received data. Fixed the display of descriptor information. Fixed the data receiving function to be capable of being called more than once.
paul@0 1
/*
paul@0 2
 * Ben NanoNote and Arduino USB Host shield communication.
paul@0 3
 *
paul@0 4
 * Copyright 2013 Paul Boddie
paul@0 5
 *
paul@0 6
 * SPI functions derived from those in lib/atben.c by Werner Almesberger:
paul@0 7
 *
paul@0 8
 * Copyright 2010-2011 Werner Almesberger
paul@0 9
 *
paul@0 10
 * This program is free software; you can redistribute it and/or modify
paul@0 11
 * it under the terms of the GNU General Public License as published by
paul@0 12
 * the Free Software Foundation; either version 2 of the License, or
paul@0 13
 * (at your option) any later version.
paul@0 14
 */
paul@0 15
paul@0 16
#include <ubb/ubb.h>
paul@0 17
#include <stdio.h>
paul@8 18
#include <signal.h>
paul@8 19
#include <stdlib.h>
paul@13 20
#include <usb.h>
paul@15 21
#include <unistd.h>
paul@19 22
#include <string.h>
paul@20 23
#include <endian.h>
paul@13 24
paul@13 25
/* Found in Python's asdl.h. */
paul@13 26
paul@13 27
#ifndef __cplusplus
paul@13 28
typedef enum {false, true} bool;
paul@13 29
#endif
paul@0 30
paul@15 31
/* Initialisation states. */
paul@15 32
paul@15 33
typedef enum
paul@15 34
{
paul@15 35
    MAX_DEVSTATE_INIT = 0,
paul@15 36
    MAX_DEVSTATE_CONNECTED = 1,
paul@15 37
    MAX_DEVSTATE_RESET = 2,
paul@19 38
    MAX_DEVSTATE_INSPECTED = 3,
paul@19 39
    MAX_DEVSTATE_RESET_AGAIN = 4,
paul@19 40
    MAX_DEVSTATE_READY = 5
paul@15 41
} max_devstate;
paul@15 42
paul@19 43
/* Device details. */
paul@19 44
paul@19 45
typedef struct
paul@19 46
{
paul@19 47
    bool in_toggle, out_toggle;
paul@19 48
    struct usb_device_descriptor desc;
paul@19 49
} max_device;
paul@19 50
paul@0 51
/* Pin assignments:
paul@0 52
 *
paul@0 53
 * Sniffer  UBB   Shield
paul@0 54
 * -------  ----  ------
paul@0 55
 * DAT2     DAT2       9 (INT)
paul@0 56
 * CD       DAT3      10 (SS)
paul@0 57
 * CMD      CMD        7 (RESET)
paul@0 58
 * VCC      VDD      VIN
paul@0 59
 * CLK      CLK       13 (SCLK)
paul@0 60
 * GND      GND      GND
paul@0 61
 * DAT0     DAT0      11 (MOSI)
paul@0 62
 * DAT1     DAT1      12 (MISO)
paul@0 63
 *                     8 (GPX) (not assigned)
paul@0 64
 */
paul@0 65
paul@0 66
#define MAX_RESET UBB_CMD
paul@0 67
#define MAX_SCLK  UBB_CLK
paul@0 68
#define MAX_MOSI  UBB_DAT0
paul@0 69
#define MAX_MISO  UBB_DAT1
paul@0 70
#define MAX_INT   UBB_DAT2
paul@0 71
#define MAX_SS    UBB_DAT3
paul@0 72
paul@0 73
/* MAX3421E definitions. */
paul@0 74
paul@0 75
#define MAX_REG_READ                0x00
paul@0 76
#define MAX_REG_WRITE               0x02
paul@0 77
paul@13 78
#define MAX_REG_RCVFIFO             1
paul@13 79
#define MAX_REG_SNDFIFO             2
paul@13 80
#define MAX_REG_SUDFIFO             4
paul@13 81
#define MAX_REG_RCVBC               6
paul@13 82
#define MAX_REG_SNDBC               7
paul@4 83
#define MAX_REG_USBIRQ              13
paul@7 84
#define MAX_REG_USBIEN              14
paul@0 85
#define MAX_REG_USBCTL              15
paul@7 86
#define MAX_REG_CPUCTL              16
paul@0 87
#define MAX_REG_PINCTL              17
paul@0 88
#define MAX_REG_REVISION            18
paul@7 89
#define MAX_REG_HIRQ                25
paul@7 90
#define MAX_REG_HIEN                26
paul@0 91
#define MAX_REG_MODE                27
paul@13 92
#define MAX_REG_PERADDR             28
paul@7 93
#define MAX_REG_HCTL                29
paul@13 94
#define MAX_REG_HXFR                30
paul@0 95
#define MAX_REG_HRSL                31
paul@0 96
paul@4 97
#define MAX_USBIRQ_OSCOKIRQ         1
paul@4 98
#define MAX_USBIRQ_NOVBUSIRQ        32
paul@4 99
#define MAX_USBIRQ_VBUSIRQ          64
paul@4 100
paul@0 101
#define MAX_USBCTL_PWRDOWN          16
paul@0 102
#define MAX_USBCTL_CHIPRES          32
paul@0 103
paul@7 104
#define MAX_CPUCTL_IE               1
paul@7 105
paul@0 106
#define MAX_PINCTL_POSINT_LOW       0
paul@0 107
#define MAX_PINCTL_POSINT_HIGH      4
paul@0 108
#define MAX_PINCTL_INTLEVEL_EDGE    0
paul@0 109
#define MAX_PINCTL_INTLEVEL_LEVEL   8
paul@0 110
#define MAX_PINCTL_FDUPSPI_HALF     0
paul@0 111
#define MAX_PINCTL_FDUPSPI_FULL     16
paul@0 112
paul@7 113
#define MAX_HIRQ_BUSEVENTIRQ        1
paul@7 114
#define MAX_HIRQ_RWUIRQ             2
paul@7 115
#define MAX_HIRQ_RCVDAVIRQ          4
paul@7 116
#define MAX_HIRQ_SNDBAVIRQ          8
paul@7 117
#define MAX_HIRQ_SUSDNIRQ           16
paul@7 118
#define MAX_HIRQ_CONDETIRQ          32
paul@7 119
#define MAX_HIRQ_FRAMEIRQ           64
paul@7 120
#define MAX_HIRQ_HXFRDNIRQ          128
paul@7 121
paul@15 122
#define MAX_HIEN_BUSEVENTIE         1
paul@7 123
#define MAX_HIEN_CONDETIE           32
paul@15 124
#define MAX_HIEN_FRAMEIE            64
paul@7 125
paul@0 126
#define MAX_MODE_PERIPHERAL         0
paul@0 127
#define MAX_MODE_HOST               1
paul@7 128
#define MAX_MODE_LOWSPEED           2
paul@7 129
#define MAX_MODE_SOFKAENAB          8
paul@0 130
#define MAX_MODE_SEPIRQ_OFF         0
paul@0 131
#define MAX_MODE_SEPIRQ_ON          16
paul@0 132
#define MAX_MODE_DMPULLDN           64
paul@0 133
#define MAX_MODE_DPPULLDN           128
paul@0 134
paul@12 135
#define MAX_MODE_HOST_ENABLED       MAX_MODE_HOST | MAX_MODE_SEPIRQ_OFF | MAX_MODE_DMPULLDN | MAX_MODE_DPPULLDN
paul@12 136
#define MAX_MODE_HOST_FULLSPEED     MAX_MODE_HOST_ENABLED
paul@12 137
#define MAX_MODE_HOST_LOWSPEED      MAX_MODE_HOST_ENABLED | MAX_MODE_LOWSPEED
paul@12 138
paul@15 139
#define MAX_HCTL_BUSRST             1
paul@7 140
#define MAX_HCTL_SAMPLEBUS          4
paul@13 141
#define MAX_HCTL_RCVTOG0            16
paul@13 142
#define MAX_HCTL_RCVTOG1            32
paul@13 143
#define MAX_HCTL_SNDTOG0            64
paul@13 144
#define MAX_HCTL_SNDTOG1            128
paul@13 145
paul@13 146
#define MAX_HXFR_SETUP              16
paul@13 147
#define MAX_HXFR_OUTNIN             32
paul@13 148
#define MAX_HXFR_HS                 128
paul@7 149
paul@7 150
#define MAX_HRSL_JSTATUS            128
paul@7 151
#define MAX_HRSL_KSTATUS            64
paul@13 152
#define MAX_HRSL_SNDTOGRD           32
paul@13 153
#define MAX_HRSL_RCVTOGRD           16
paul@13 154
#define MAX_HRSL_HRSLT              15
paul@7 155
paul@0 156
#define max_reg(n) ((uint8_t) (n << 3))
paul@0 157
#define max_reg_read(n) (max_reg(n) | MAX_REG_READ)
paul@0 158
#define max_reg_write(n) (max_reg(n) | MAX_REG_WRITE)
paul@0 159
paul@0 160
void spi_begin()
paul@0 161
{
paul@0 162
    CLR(MAX_SS);
paul@0 163
}
paul@0 164
paul@0 165
void spi_end()
paul@0 166
{
paul@0 167
    SET(MAX_SS);
paul@0 168
}
paul@0 169
paul@0 170
/**
paul@0 171
 * Send the given value via MOSI while receiving a value via MISO.
paul@0 172
 * This requires full-duplex SPI and will produce a status value for the first
paul@0 173
 * value sent (the command).
paul@0 174
 */
paul@0 175
uint8_t spi_sendrecv(uint8_t v)
paul@0 176
{
paul@0 177
    uint8_t result = 0;
paul@0 178
    uint8_t mask;
paul@0 179
paul@0 180
    for (mask = 0x80; mask; mask >>= 1)
paul@0 181
    {
paul@0 182
        if (v & mask)
paul@0 183
        {
paul@7 184
            #ifdef DEBUG
paul@0 185
            printf("1");
paul@7 186
            #endif
paul@0 187
            SET(MAX_MOSI);
paul@0 188
        }
paul@0 189
        else
paul@0 190
        {
paul@7 191
            #ifdef DEBUG
paul@0 192
            printf("0");
paul@7 193
            #endif
paul@0 194
            CLR(MAX_MOSI);
paul@0 195
        }
paul@0 196
paul@0 197
        /* Wait for stable output signal. */
paul@0 198
paul@0 199
        SET(MAX_SCLK);
paul@0 200
paul@0 201
        if (PIN(MAX_MISO))
paul@0 202
            result |= mask;
paul@0 203
paul@0 204
        CLR(MAX_SCLK);
paul@0 205
    }
paul@0 206
paul@7 207
    #ifdef DEBUG
paul@0 208
    printf("\n");
paul@7 209
    #endif
paul@0 210
    return result;
paul@0 211
}
paul@0 212
paul@6 213
uint8_t max_read(uint8_t reg, uint8_t *status)
paul@6 214
{
paul@6 215
    uint8_t result = 0, tmpstatus = 0;
paul@6 216
paul@6 217
    tmpstatus = 0;
paul@6 218
paul@6 219
    spi_begin();
paul@6 220
    tmpstatus = spi_sendrecv(max_reg_read(reg));
paul@6 221
    result = spi_sendrecv(0);
paul@6 222
    spi_end();
paul@6 223
paul@6 224
    if (status != NULL)
paul@6 225
        *status = tmpstatus;
paul@6 226
paul@6 227
    return result;
paul@6 228
}
paul@6 229
paul@6 230
uint8_t max_write(uint8_t reg, uint8_t value)
paul@6 231
{
paul@6 232
    uint8_t status = 0;
paul@6 233
paul@6 234
    spi_begin();
paul@6 235
    status = spi_sendrecv(max_reg_write(reg));
paul@6 236
    spi_sendrecv(value);
paul@6 237
    spi_end();
paul@6 238
paul@6 239
    return status;
paul@6 240
}
paul@6 241
paul@13 242
/**
paul@13 243
 * Return whether data can be sent.
paul@13 244
 */
paul@15 245
bool max_can_send(uint8_t *status)
paul@13 246
{
paul@15 247
    if (status == NULL)
paul@15 248
        return max_read(MAX_REG_HIRQ, NULL) & MAX_HIRQ_SNDBAVIRQ;
paul@15 249
    else
paul@15 250
        return *status & MAX_HIRQ_SNDBAVIRQ;
paul@13 251
}
paul@13 252
paul@13 253
/**
paul@13 254
 * Set the sending data toggle.
paul@13 255
 */
paul@13 256
void max_set_send_toggle(bool toggle)
paul@13 257
{
paul@13 258
    max_write(MAX_REG_HCTL, toggle ? MAX_HCTL_SNDTOG1 : MAX_HCTL_SNDTOG0);
paul@13 259
}
paul@13 260
paul@13 261
/**
paul@13 262
 * Return the sending data toggle.
paul@13 263
 */
paul@13 264
bool max_get_send_toggle()
paul@13 265
{
paul@13 266
    return (max_read(MAX_REG_HRSL, NULL) & MAX_HRSL_SNDTOGRD) != 0;
paul@13 267
}
paul@13 268
paul@13 269
/**
paul@13 270
 * Set the receiving data toggle.
paul@13 271
 */
paul@13 272
void max_set_recv_toggle(bool toggle)
paul@13 273
{
paul@13 274
    max_write(MAX_REG_HCTL, toggle ? MAX_HCTL_RCVTOG1 : MAX_HCTL_RCVTOG0);
paul@13 275
}
paul@13 276
paul@13 277
/**
paul@13 278
 * Return the receiving data toggle.
paul@13 279
 */
paul@13 280
bool max_get_recv_toggle()
paul@13 281
{
paul@13 282
    return (max_read(MAX_REG_HRSL, NULL) & MAX_HRSL_RCVTOGRD) != 0;
paul@13 283
}
paul@13 284
paul@13 285
/**
paul@13 286
 * Wait for handshake/timeout after a transfer.
paul@13 287
 */
paul@13 288
uint8_t max_wait_transfer(uint8_t status)
paul@13 289
{
paul@13 290
    while (!(status & MAX_HIRQ_HXFRDNIRQ))
paul@13 291
    {
paul@13 292
        status = max_read(MAX_REG_HIRQ, NULL);
paul@13 293
    }
paul@13 294
paul@20 295
    max_write(MAX_REG_HIRQ, MAX_HIRQ_HXFRDNIRQ);
paul@20 296
    return max_read(MAX_REG_HIRQ, NULL);
paul@13 297
}
paul@13 298
paul@13 299
/**
paul@13 300
 * Write the given data to the FIFO.
paul@13 301
 */
paul@13 302
void max_write_fifo(uint8_t endpoint, uint8_t *data, uint8_t len)
paul@13 303
{
paul@13 304
    uint8_t count;
paul@13 305
paul@13 306
    for (count = 0; count < len; count++)
paul@13 307
    {
paul@13 308
        max_write(endpoint ? MAX_REG_SNDFIFO : MAX_REG_SUDFIFO, data[count]);
paul@13 309
    }
paul@13 310
paul@13 311
    if (endpoint)
paul@13 312
        max_write(MAX_REG_SNDBC, len);
paul@13 313
}
paul@13 314
paul@13 315
/**
paul@13 316
 * Read the data from the FIFO.
paul@13 317
 */
paul@20 318
void max_read_fifo(uint8_t **data, uint8_t *len, uint8_t *datalimit)
paul@13 319
{
paul@13 320
    uint8_t count, received = max_read(MAX_REG_RCVBC, NULL);
paul@20 321
    printf("Received %d bytes.\n", received);
paul@13 322
paul@13 323
    *len += received;
paul@13 324
paul@20 325
    for (count = 0; (count < received) && (*data < datalimit); count++)
paul@13 326
    {
paul@20 327
        *((*data)++) = max_read(MAX_REG_RCVFIFO, NULL);
paul@13 328
    }
paul@13 329
}
paul@13 330
paul@13 331
/**
paul@20 332
 * Send a control request consisting of the given setup data.
paul@14 333
 */
paul@20 334
uint8_t max_control(uint8_t *setup)
paul@14 335
{
paul@17 336
    uint8_t status, hrsl;
paul@14 337
paul@14 338
    max_write_fifo(0, setup, 8);
paul@14 339
paul@14 340
    /* Initiate the transfer. */
paul@14 341
paul@14 342
    do
paul@14 343
    {
paul@14 344
        status = max_write(MAX_REG_HXFR, MAX_HXFR_SETUP);
paul@14 345
        status = max_wait_transfer(status);
paul@14 346
        hrsl = max_read(MAX_REG_HRSL, &status);
paul@17 347
    }
paul@17 348
    while (hrsl & MAX_HRSL_HRSLT);
paul@17 349
paul@17 350
    return status;
paul@17 351
}
paul@17 352
paul@17 353
/**
paul@17 354
 * Perform a status transaction as part of a larger control transaction.
paul@17 355
 * The out parameter is used to indicate the kind of status transfer to be
paul@17 356
 * performed and should be the inverse of the control transfer direction.
paul@17 357
 */
paul@17 358
uint8_t max_control_status(bool out)
paul@17 359
{
paul@17 360
    uint8_t status, hrsl;
paul@17 361
paul@17 362
    do
paul@17 363
    {
paul@17 364
        status = max_write(MAX_REG_HXFR, MAX_HXFR_HS | (out ? MAX_HXFR_OUTNIN : 0));
paul@17 365
        status = max_wait_transfer(status);
paul@17 366
        hrsl = max_read(MAX_REG_HRSL, &status);
paul@14 367
    }
paul@15 368
    while (hrsl & MAX_HRSL_HRSLT);
paul@14 369
paul@14 370
    return status;
paul@14 371
}
paul@14 372
paul@14 373
/**
paul@20 374
 * Send a request to the given endpoint, using the supplied data payload with
paul@20 375
 * the given length, indicating the preserved toggle state of the endpoint
paul@20 376
 * (which will be updated).
paul@13 377
 */
paul@20 378
uint8_t max_send(uint8_t endpoint, uint8_t *data, uint8_t len, bool *toggle)
paul@13 379
{
paul@13 380
    uint8_t status, hrsl = 0;
paul@13 381
paul@13 382
    max_write_fifo(endpoint, data, len);
paul@13 383
paul@20 384
    max_set_send_toggle(*toggle);
paul@13 385
paul@13 386
    /* Initiate the transfer. */
paul@13 387
paul@13 388
    do
paul@13 389
    {
paul@14 390
        status = max_write(MAX_REG_HXFR, endpoint | MAX_HXFR_OUTNIN);
paul@13 391
        status = max_wait_transfer(status);
paul@13 392
paul@13 393
        /* Test for usable data. */
paul@13 394
paul@20 395
        if (status & MAX_HIRQ_SNDBAVIRQ)
paul@20 396
        {
paul@20 397
            hrsl = max_read(MAX_REG_HRSL, &status);
paul@13 398
paul@20 399
            if (!(hrsl & MAX_HRSL_HRSLT))
paul@20 400
                break;
paul@20 401
        }
paul@13 402
    }
paul@20 403
    while (true);
paul@13 404
paul@20 405
    *toggle = max_get_send_toggle();
paul@13 406
paul@13 407
    return status;
paul@13 408
}
paul@13 409
paul@13 410
/**
paul@20 411
 * Make a request for data from the given endpoint, collecting it in the
paul@20 412
 * supplied buffer with the given length, indicating the preserved toggle state
paul@20 413
 * of the endpoint (which will be updated). The length will be updated to
paul@14 414
 * indicate the total length of the received data.
paul@13 415
 */
paul@20 416
bool max_recv(uint8_t endpoint, uint8_t *data, uint8_t *len, bool *toggle)
paul@13 417
{
paul@13 418
    uint8_t *datalimit = data + *len;
paul@13 419
    uint8_t status, hrsl = 0;
paul@20 420
    uint16_t attempt = 1024;
paul@13 421
paul@20 422
    max_set_recv_toggle(*toggle);
paul@13 423
paul@13 424
    /* Initiate the transfer. */
paul@13 425
paul@13 426
    do
paul@13 427
    {
paul@13 428
        status = max_write(MAX_REG_HXFR, endpoint);
paul@13 429
        status = max_wait_transfer(status);
paul@13 430
paul@13 431
        /* Test for usable data. */
paul@13 432
paul@20 433
        hrsl = max_read(MAX_REG_HRSL, &status);
paul@13 434
paul@20 435
        attempt--;
paul@13 436
    }
paul@20 437
    while ((hrsl & MAX_HRSL_HRSLT) && attempt);
paul@13 438
paul@20 439
    if (!attempt)
paul@13 440
    {
paul@20 441
        printf("HRSL is %x\n", hrsl);
paul@20 442
        return false;
paul@20 443
    }
paul@20 444
paul@20 445
    while (status & MAX_HIRQ_RCVDAVIRQ)
paul@20 446
    {
paul@20 447
        max_read_fifo(&data, len, datalimit);
paul@13 448
paul@13 449
        /* Indicate that all data has been read. */
paul@13 450
paul@20 451
        max_write(MAX_REG_HIRQ, MAX_HIRQ_RCVDAVIRQ);
paul@20 452
        status = max_read(MAX_REG_HIRQ, NULL);
paul@13 453
    }
paul@13 454
paul@20 455
    *toggle = max_get_recv_toggle();
paul@13 456
paul@20 457
    return true;
paul@13 458
}
paul@13 459
paul@3 460
void chipreset()
paul@3 461
{
paul@3 462
    printf("Resetting...\n");
paul@6 463
    max_write(MAX_REG_USBCTL, MAX_USBCTL_CHIPRES);
paul@3 464
paul@3 465
    printf("Clearing the reset...\n");
paul@6 466
    max_write(MAX_REG_USBCTL, 0);
paul@3 467
}
paul@3 468
paul@4 469
uint8_t check()
paul@4 470
{
paul@6 471
    uint8_t oscillator;
paul@4 472
paul@6 473
    oscillator = max_read(MAX_REG_USBIRQ, NULL);
paul@4 474
paul@4 475
    return (oscillator & ~(MAX_USBIRQ_NOVBUSIRQ | MAX_USBIRQ_VBUSIRQ)) == MAX_USBIRQ_OSCOKIRQ;
paul@4 476
}
paul@4 477
paul@7 478
uint8_t wait()
paul@7 479
{
paul@7 480
    uint16_t timeout = 1024;
paul@7 481
paul@7 482
    /* Wait for the oscillator before performing USB activity. */
paul@7 483
paul@7 484
    printf("Waiting...\n");
paul@7 485
paul@7 486
    while ((timeout > 0) && (!check()))
paul@7 487
    {
paul@7 488
        timeout--;
paul@7 489
    }
paul@7 490
paul@7 491
    printf("Iterations remaining: %d\n", timeout);
paul@7 492
paul@7 493
    return timeout;
paul@7 494
}
paul@7 495
paul@18 496
/**
paul@18 497
 * Return whether the bus is ready to be sampled. The application note claims
paul@18 498
 * that the SAMPLEBUS bit is cleared, but this does not seem to be the case.
paul@18 499
 */
paul@11 500
uint8_t samplebusready()
paul@7 501
{
paul@7 502
    uint8_t result;
paul@7 503
paul@7 504
    result = max_read(MAX_REG_HCTL, NULL);
paul@18 505
    return result & MAX_HCTL_SAMPLEBUS;
paul@7 506
}
paul@7 507
paul@11 508
void samplebus()
paul@11 509
{
paul@11 510
    max_write(MAX_REG_HCTL, MAX_HCTL_SAMPLEBUS);
paul@11 511
    while (!samplebusready());
paul@11 512
}
paul@11 513
paul@13 514
/**
paul@13 515
 * Handle the connection or disconnection of a device, returning true if the
paul@19 516
 * device is now connected or false otherwise. If the device is connected, a
paul@19 517
 * bus reset is performed.
paul@13 518
 */
paul@13 519
bool devicechanged()
paul@11 520
{
paul@11 521
    uint8_t hrsl, mode;
paul@11 522
paul@11 523
    hrsl = max_read(MAX_REG_HRSL, NULL);
paul@11 524
    mode = max_read(MAX_REG_MODE, NULL);
paul@11 525
paul@11 526
    if ((hrsl & MAX_HRSL_JSTATUS) && (hrsl & MAX_HRSL_KSTATUS))
paul@11 527
    {
paul@11 528
        printf("Bad device status.\n");
paul@11 529
    }
paul@11 530
    else if (!(hrsl & MAX_HRSL_JSTATUS) && !(hrsl & MAX_HRSL_KSTATUS))
paul@11 531
    {
paul@11 532
        printf("Device disconnected.\n");
paul@11 533
    }
paul@11 534
    else
paul@11 535
    {
paul@11 536
        printf("Device connected.\n");
paul@11 537
paul@11 538
        /* Low speed device when J and lowspeed have the same level.
paul@11 539
           Since J and K should have opposing levels, K can be tested when
paul@11 540
           lowspeed is low. */
paul@11 541
paul@11 542
        if (((hrsl & MAX_HRSL_JSTATUS) && (mode & MAX_MODE_LOWSPEED)) ||
paul@11 543
            ((hrsl & MAX_HRSL_KSTATUS) && !(mode & MAX_MODE_LOWSPEED)))
paul@11 544
        {
paul@11 545
            printf("Device is low speed.\n");
paul@12 546
            max_write(MAX_REG_MODE, MAX_MODE_HOST_LOWSPEED);
paul@11 547
        }
paul@11 548
        else
paul@11 549
        {
paul@11 550
            printf("Device is full speed.\n");
paul@12 551
            max_write(MAX_REG_MODE, MAX_MODE_HOST_FULLSPEED);
paul@11 552
        }
paul@13 553
paul@15 554
        /* Reset the device. */
paul@15 555
paul@15 556
        max_write(MAX_REG_HCTL, MAX_HCTL_BUSRST);
paul@13 557
        return true;
paul@11 558
    }
paul@13 559
paul@13 560
    return false;
paul@13 561
}
paul@13 562
paul@13 563
void setup_packet(uint8_t *setup, uint8_t request_type, uint8_t request, uint16_t value, uint16_t index, uint16_t length)
paul@13 564
{
paul@13 565
    setup[0] = request_type;
paul@13 566
    setup[1] = request;
paul@13 567
    setup[2] = value & 0xff;
paul@13 568
    setup[3] = value >> 8;
paul@13 569
    setup[4] = index & 0xff;
paul@13 570
    setup[5] = index >> 8;
paul@13 571
    setup[6] = length & 0xff;
paul@13 572
    setup[7] = length >> 8;
paul@11 573
}
paul@11 574
paul@19 575
bool max_init_device(max_device *device)
paul@15 576
{
paul@15 577
    uint8_t data[64], len = 64, setup[8];
paul@15 578
paul@15 579
    printf("Sending control request to address 0, endpoint 0...\n");
paul@20 580
paul@20 581
    max_write(MAX_REG_PERADDR, 0);
paul@20 582
    setup_packet(setup, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, USB_DT_DEVICE << 8, 0, USB_DT_DEVICE_SIZE);
paul@20 583
    max_control(setup);
paul@20 584
    device->in_toggle = true;
paul@20 585
    if (!max_recv(0, data, &len, &device->in_toggle))
paul@20 586
        return false;
paul@17 587
    max_control_status(true);
paul@15 588
paul@15 589
    if (len >= sizeof(struct usb_device_descriptor))
paul@15 590
    {
paul@19 591
        memcpy(&device->desc, data, sizeof(struct usb_device_descriptor));
paul@20 592
        device->desc.bcdUSB = le16toh(device->desc.bcdUSB);
paul@20 593
        device->desc.idVendor = le16toh(device->desc.idVendor);
paul@20 594
        device->desc.idProduct = le16toh(device->desc.idProduct);
paul@20 595
        device->desc.bcdDevice = le16toh(device->desc.bcdDevice);
paul@20 596
paul@19 597
        printf("bLength: %d\n", device->desc.bLength);
paul@19 598
        printf("bDescriptorType: %d\n", device->desc.bDescriptorType);
paul@20 599
        printf("bcdUSB: %04x\n", device->desc.bcdUSB);
paul@19 600
        printf("bDeviceClass: %d\n", device->desc.bDeviceClass);
paul@19 601
        printf("bDeviceSubClass: %d\n", device->desc.bDeviceSubClass);
paul@19 602
        printf("bDeviceProtocol: %d\n", device->desc.bDeviceProtocol);
paul@19 603
        printf("bMaxPacketSize0: %d\n", device->desc.bMaxPacketSize0);
paul@20 604
        printf("idVendor: %04x\n", device->desc.idVendor);
paul@20 605
        printf("idProduct: %04x\n", device->desc.idProduct);
paul@20 606
        printf("bcdDevice: %04x\n", device->desc.bcdDevice);
paul@19 607
        printf("iManufacturer: %d\n", device->desc.iManufacturer);
paul@19 608
        printf("iProduct: %d\n", device->desc.iProduct);
paul@19 609
        printf("iSerialNumber: %d\n", device->desc.iSerialNumber);
paul@19 610
        printf("bNumConfigurations: %d\n", device->desc.bNumConfigurations);
paul@19 611
paul@19 612
        /* Reset the device. */
paul@19 613
paul@19 614
        max_write(MAX_REG_HCTL, MAX_HCTL_BUSRST);
paul@15 615
        return true;
paul@15 616
    }
paul@15 617
paul@15 618
    return false;
paul@15 619
}
paul@15 620
paul@8 621
void shutdown(int signum)
paul@8 622
{
paul@8 623
    printf("Closing...\n");
paul@8 624
    ubb_close(0);
paul@8 625
    exit(1);
paul@8 626
}
paul@8 627
paul@0 628
int main(int argc, char *argv[])
paul@0 629
{
paul@8 630
    uint8_t status = 0, revision = 0;
paul@7 631
    uint16_t count;
paul@19 632
    bool bus_event, data_event, suspended_event, connection_event, frame_event;
paul@19 633
    max_device device;
paul@15 634
    max_devstate devstate = MAX_DEVSTATE_INIT;
paul@0 635
paul@19 636
    device.in_toggle = false;
paul@19 637
    device.out_toggle = false;
paul@19 638
paul@8 639
    signal(SIGINT, &shutdown);
paul@8 640
paul@0 641
    if (ubb_open(0) < 0) {
paul@0 642
        perror("ubb_open");
paul@0 643
        return 1;
paul@0 644
    }
paul@0 645
paul@0 646
    ubb_power(1);
paul@0 647
    printf("Power on.\n");
paul@0 648
paul@0 649
    OUT(MAX_SS);
paul@0 650
    OUT(MAX_MOSI);
paul@0 651
    OUT(MAX_SCLK);
paul@0 652
    OUT(MAX_RESET);
paul@0 653
    IN(MAX_INT);
paul@0 654
    IN(MAX_MISO);
paul@0 655
paul@0 656
    /* Initialise SPI. */
paul@7 657
    /* Set SS# to 1. */
paul@0 658
paul@0 659
    SET(MAX_SS);
paul@0 660
    CLR(MAX_MOSI);
paul@0 661
    CLR(MAX_SCLK);
paul@7 662
    SET(MAX_RESET);
paul@0 663
paul@0 664
    /* Initialise the MAX3421E. */
paul@0 665
paul@0 666
    /* Set full-duplex, interrupt signalling. */
paul@0 667
paul@0 668
    printf("Setting pin control...\n");
paul@6 669
    max_write(MAX_REG_PINCTL, MAX_PINCTL_INTLEVEL_LEVEL | MAX_PINCTL_FDUPSPI_FULL);
paul@0 670
paul@3 671
    chipreset();
paul@7 672
    printf("Ready? %d\n", wait());
paul@7 673
paul@7 674
    /* Check various registers. */
paul@7 675
paul@7 676
    printf("Mode: %x\n", max_read(MAX_REG_MODE, &status));
paul@7 677
    printf("IRQ: %x\n", max_read(MAX_REG_HIRQ, &status));
paul@0 678
paul@0 679
    /* Set host mode. */
paul@0 680
paul@0 681
    printf("Setting mode...\n");
paul@12 682
    status = max_write(MAX_REG_MODE, MAX_MODE_HOST_ENABLED);
paul@7 683
paul@7 684
    printf("Setting INT signalling...\n");
paul@7 685
    status = max_write(MAX_REG_CPUCTL, MAX_CPUCTL_IE);
paul@7 686
paul@15 687
    printf("Setting event signalling...\n");
paul@15 688
    status = max_write(MAX_REG_HIEN, MAX_HIEN_CONDETIE | MAX_HIEN_FRAMEIE | MAX_HIEN_BUSEVENTIE);
paul@7 689
paul@7 690
    /* Check various registers. */
paul@7 691
paul@7 692
    printf("Mode: %x\n", max_read(MAX_REG_MODE, &status));
paul@7 693
    printf("IRQ: %x\n", max_read(MAX_REG_HIRQ, &status));
paul@7 694
    printf("IE: %x\n", max_read(MAX_REG_HIEN, &status));
paul@7 695
    printf("CPU: %x\n", max_read(MAX_REG_CPUCTL, &status));
paul@7 696
    printf("Pin: %x\n", max_read(MAX_REG_PINCTL, &status));
paul@7 697
    printf("USBIRQ: %x\n", max_read(MAX_REG_USBIRQ, &status));
paul@7 698
    printf("USBIE: %x\n", max_read(MAX_REG_USBIEN, &status));
paul@0 699
paul@0 700
    /* Read from the REVISION register. */
paul@0 701
paul@0 702
    printf("Reading...\n");
paul@6 703
    revision = max_read(MAX_REG_REVISION, &status);
paul@0 704
    printf("Revision = %x\n", revision);
paul@7 705
paul@18 706
    /* Sample the bus for any devices that are already connected. */
paul@18 707
paul@18 708
    samplebus();
paul@18 709
paul@18 710
    if (devicechanged())
paul@18 711
    {
paul@18 712
        devstate = MAX_DEVSTATE_CONNECTED;
paul@18 713
    }
paul@18 714
paul@18 715
    /* Enter the main processing loop. */
paul@18 716
paul@8 717
    for (count = 0; count <= 65535; count++)
paul@7 718
    {
paul@8 719
        if (!PIN(MAX_INT))
paul@7 720
        {
paul@19 721
            /* Obtain interrupt conditions. */
paul@19 722
paul@9 723
            status = max_read(MAX_REG_HIRQ, NULL);
paul@9 724
paul@19 725
            bus_event = status & MAX_HIRQ_BUSEVENTIRQ;
paul@19 726
            data_event = status & MAX_HIRQ_RCVDAVIRQ;
paul@19 727
            suspended_event = status & MAX_HIRQ_SUSDNIRQ;
paul@19 728
            connection_event = status & MAX_HIRQ_CONDETIRQ;
paul@16 729
            frame_event = status & MAX_HIRQ_FRAMEIRQ;
paul@19 730
paul@19 731
            #ifdef DEBUG
paul@19 732
            if (bus_event) printf("Bus ");
paul@19 733
            if (data_event) printf("Data ");
paul@19 734
            if (suspended_event) printf("Suspended ");
paul@19 735
            if (connection_event) printf("Connection ");
paul@19 736
            if (frame_event) printf("Frame ");
paul@15 737
            printf("\n");
paul@19 738
            #endif
paul@19 739
paul@19 740
            /* Acknowledge the interrupts. */
paul@15 741
paul@16 742
            max_write(MAX_REG_HIRQ, status);
paul@16 743
paul@15 744
            /* Detect device connection/disconnection. */
paul@15 745
paul@16 746
            if ((devstate == MAX_DEVSTATE_INIT) && connection_event && devicechanged())
paul@13 747
            {
paul@15 748
                devstate = MAX_DEVSTATE_CONNECTED;
paul@19 749
                printf("CONNECTED\n");
paul@13 750
            }
paul@15 751
paul@15 752
            /* Handle device reset initiation. */
paul@15 753
paul@16 754
            else if ((devstate == MAX_DEVSTATE_CONNECTED) && bus_event)
paul@15 755
            {
paul@16 756
                max_write(MAX_REG_MODE, max_read(MAX_REG_MODE, NULL) | MAX_MODE_SOFKAENAB);
paul@15 757
                devstate = MAX_DEVSTATE_RESET;
paul@19 758
                printf("RESET\n");
paul@15 759
            }
paul@15 760
paul@19 761
            /* Handle device reset completion, getting device details and
paul@19 762
               initiating a second reset. */
paul@15 763
paul@16 764
            else if ((devstate == MAX_DEVSTATE_RESET) && frame_event && max_can_send(&status))
paul@15 765
            {
paul@20 766
                if (max_init_device(&device))
paul@20 767
                {
paul@20 768
                    devstate = MAX_DEVSTATE_INSPECTED;
paul@20 769
                    printf("INSPECTED\n");
paul@20 770
                }
paul@20 771
                else
paul@20 772
                    printf("FAILED: RESET -> INSPECTED\n");
paul@19 773
            }
paul@19 774
paul@19 775
            /* Handle the second device reset initiation. */
paul@19 776
paul@19 777
            else if ((devstate == MAX_DEVSTATE_INSPECTED) && bus_event)
paul@19 778
            {
paul@19 779
                devstate = MAX_DEVSTATE_RESET_AGAIN;
paul@19 780
                printf("RESET AGAIN\n");
paul@19 781
            }
paul@19 782
paul@19 783
            /* Handle the second device reset completion, initiating communications. */
paul@19 784
paul@19 785
            else if ((devstate == MAX_DEVSTATE_RESET_AGAIN) && frame_event && max_can_send(&status))
paul@19 786
            {
paul@19 787
                max_write(MAX_REG_MODE, max_read(MAX_REG_MODE, NULL) & ~MAX_MODE_SOFKAENAB);
paul@15 788
                devstate = MAX_DEVSTATE_READY;
paul@19 789
                printf("READY\n");
paul@15 790
            }
paul@7 791
paul@16 792
            /* Handle device disconnection. */
paul@16 793
paul@16 794
            else if ((devstate != MAX_DEVSTATE_INIT) && connection_event)
paul@16 795
            {
paul@16 796
                devstate = MAX_DEVSTATE_INIT;
paul@19 797
                printf("INIT\n");
paul@16 798
            }
paul@7 799
        }
paul@7 800
    }
paul@0 801
paul@0 802
    printf("Closing...\n");
paul@0 803
    ubb_close(0);
paul@0 804
paul@0 805
    return 0;
paul@0 806
}