Root/cntr/fw/cntr/ep0.c

1/*
2 * cntr/ep0.c - EP0 extension protocol
3 *
4 * Written 2008-2010 by Werner Almesberger
5 * Copyright 2008-2010 Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13
14#include <stdint.h>
15
16#ifndef NULL
17#define NULL 0
18#endif
19
20#include "regs.h"
21#include "usb.h"
22#include "cntr/ep0.h"
23#include "version.h"
24#include "cntr.h"
25
26#define debug(...)
27#define error(...)
28
29
30/*
31 * SDCC 2.8.0 had a number of code generation bugs that appeared in the big
32 * switch statement of my_setup. SDCC_FORCE_UPDATE forced the value of the
33 * "size" variable to be written to memory. This work-around doesn't seem
34 * to be necessary with 2.9.0, but we keep it around, just in case.
35 *
36 * Unfortunately, the setup->bRequest garbling bug is still with us. Without
37 * the evaluation forced with SDCC_FORCE_EVAL, sdcc gets confused about the
38 * value of setup->bRequest and then rejects all SETUP requests.
39 */
40
41#define SDCC_FORCE_EVAL(type, value) \
42    do { \
43    static volatile type foo; \
44    foo = value; \
45    } while (0)
46
47#define SDCC_FORCE_UPDATE(type, var) \
48    do { \
49    volatile type foo; \
50    foo = var; \
51    var = foo; \
52    } while (0)
53
54
55static uint8_t id[3] = {
56    EP0CNTR_MAJOR, EP0CNTR_MINOR,
57    /* hw type is set at run time */
58};
59
60static __xdata uint8_t buf[128];
61
62
63#define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */
64
65
66/* crc32() */
67#include "cntr/crc32.c"
68
69
70static __bit my_setup(struct setup_request *setup) __reentrant
71{
72    uint32_t tmp;
73    uint8_t size, i;
74
75    switch (setup->bmRequestType | setup->bRequest << 8) {
76    case CNTR_FROM_DEV(CNTR_ID):
77        debug("CNTR_ID\n");
78        if (setup->wLength > 3)
79            return 0;
80        id[2] = hw_type;
81        usb_send(&ep0, id, setup->wLength, NULL, NULL);
82        return 1;
83    case CNTR_FROM_DEV(CNTR_BUILD):
84        debug("CNTR_BUILD\n");
85        tmp = build_number;
86        for (i = BUILD_OFFSET-2; tmp; i--) {
87            buf[i] = (tmp % 10)+'0';
88            tmp /= 10;
89        }
90        buf[i] = '#';
91        buf[BUILD_OFFSET-1] = ' ';
92        for (size = 0; build_date[size]; size++)
93            buf[BUILD_OFFSET+size] = build_date[size];
94        size += BUILD_OFFSET-i+1;
95        SDCC_FORCE_EVAL(uint8_t, setup->bRequest);
96        if (size > setup->wLength)
97            return 0;
98        usb_send(&ep0, buf+i, size, NULL, NULL);
99        return 1;
100
101    case CNTR_TO_DEV(CNTR_RESET):
102        debug("CNTR_RESET\n");
103        RSTSRC = SWRSF;
104        while (1);
105
106    case CNTR_FROM_DEV(CNTR_READ):
107        debug("CNTR_READ\n");
108        buf[0] = cntr[0];
109        buf[1] = cntr[1];
110        buf[2] = cntr[2];
111        buf[3] = cntr[3];
112        tmp = (uint32_t) buf[0] | ((uint32_t) buf[1] << 8) |
113            ((uint32_t) buf[2] << 16) | ((uint32_t) buf[3] << 24);
114        tmp = crc32(tmp, 0xffffffff);
115        buf[4] = tmp;
116        buf[5] = tmp >> 8;
117        buf[6] = tmp >> 16;
118        buf[7] = tmp >> 24;
119        buf[8] = ~cntr[0];
120        buf[9] = ~cntr[1];
121        buf[10] = ~cntr[2];
122        buf[11] = ~cntr[3];
123        usb_send(&ep0, buf, 12, NULL, NULL);
124        return 1;
125
126    default:
127        error("Unrecognized SETUP: 0x%02x 0x%02x ...\n",
128            setup->bmRequestType, setup->bRequest);
129        return 0;
130    }
131}
132
133
134void ep0_init(void)
135{
136    user_setup = my_setup;
137}
138

Archive Download this file



interactive