Root/labsw/fw/ep0.c

Source at commit a27d1958fb3a238dcdc9fe15e0d0649448409129 created 5 years 11 months ago.
By Werner Almesberger, ircstat/ML: update for 12/2013
1/*
2 * labsw/ep0.c - EP0 extension protocol
3 *
4 * Written 2008-2011 by Werner Almesberger
5 * Copyright 2008-2011 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 "labsw/ep0.h"
23#include "io.h"
24#include "version.h"
25
26
27extern int local;
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    EP0LABSW_MAJOR, EP0LABSW_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
66static __bit my_setup(struct setup_request *setup) __reentrant
67{
68    uint32_t tmp;
69    uint8_t size, i;
70
71    switch (setup->bmRequestType | setup->bRequest << 8) {
72    case LABSW_FROM_DEV(LABSW_ID):
73        size = setup->wLength;
74        if (size > 3)
75            size = 3;
76        id[2] = 0; /* hardware type */
77        usb_send(&ep0, id, size, NULL, NULL);
78        return 1;
79    case LABSW_FROM_DEV(LABSW_BUILD):
80        tmp = build_number;
81        for (i = BUILD_OFFSET-2; tmp; i--) {
82            buf[i] = (tmp % 10)+'0';
83            tmp /= 10;
84        }
85        buf[i] = '#';
86        buf[BUILD_OFFSET-1] = ' ';
87        for (size = 0; build_date[size]; size++)
88            buf[BUILD_OFFSET+size] = build_date[size];
89        size += BUILD_OFFSET-i+1;
90        SDCC_FORCE_EVAL(uint8_t, setup->bRequest);
91        if (size > setup->wLength)
92            return 0;
93        usb_send(&ep0, buf+i, size, NULL, NULL);
94        return 1;
95
96    case LABSW_TO_DEV(LABSW_RESET):
97        RSTSRC = SWRSF;
98        while (1);
99
100    case LABSW_FROM_DEV(LABSW_GET):
101        size = setup->wLength;
102        if (size > 2)
103            size = 2;
104        buf[0] =
105            (IN_1 ? 0 : LABSW_IN1) |
106            (IN_2 ? 0 : LABSW_IN2) |
107            (IN_3 ? 0 : LABSW_IN3) |
108            (IN_4 ? 0 : LABSW_IN4);
109        buf[1] =
110            (BUT_MAIN ? 0 : LABSW_BUT_MAIN) |
111            (BUT_CH1 ? 0 : LABSW_BUT_CH1) |
112            (BUT_CH2 ? 0 : LABSW_BUT_CH2);
113        usb_send(&ep0, buf, size, NULL, NULL);
114        return 1;
115
116    case LABSW_TO_DEV(LABSW_SET):
117        local = !setup->wIndex;
118
119        if (setup->wIndex & LABSW_CH1_RELAY)
120            CH1_RELAY = setup->wValue & LABSW_CH1_RELAY ? 1 : 0;
121        if (setup->wIndex & LABSW_CH1_OPT)
122            CH1_OPT = setup->wValue & LABSW_CH1_OPT ? 0 : 1;
123        if (setup->wIndex & LABSW_CH2_RELAY)
124            CH2_RELAY = setup->wValue & LABSW_CH2_RELAY ? 1 : 0;
125        if (setup->wIndex & LABSW_CH2_OPT)
126            CH2_OPT = setup->wValue & LABSW_CH2_OPT ? 0 : 1;
127        
128        if (setup->wIndex & LABSW_OUT1)
129            OUT_1 = setup->wValue & LABSW_OUT1 ? 0 : 1;
130        if (setup->wIndex & LABSW_OUT2)
131            OUT_2 = setup->wValue & LABSW_OUT2 ? 0 : 1;
132        if (setup->wIndex & LABSW_OUT3)
133            OUT_3 = setup->wValue & LABSW_OUT3 ? 0 : 1;
134        if (setup->wIndex & LABSW_OUT4)
135            OUT_4 = setup->wValue & LABSW_OUT4 ? 0 : 1;
136
137        if (setup->wIndex & LABSW_MAIN_R)
138            LED_MAIN_R = setup->wValue & LABSW_MAIN_R ? 1 : 0;
139        if (setup->wIndex & LABSW_MAIN_G)
140            LED_MAIN_G = setup->wValue & LABSW_MAIN_G ? 1 : 0;
141        if (setup->wIndex & LABSW_CH1_R)
142            LED_CH1_R = setup->wValue & LABSW_CH1_R ? 1 : 0;
143        if (setup->wIndex & LABSW_CH1_G)
144            LED_CH1_G = setup->wValue & LABSW_CH1_G ? 1 : 0;
145        if (setup->wIndex & LABSW_CH2_R)
146            LED_CH2_R = setup->wValue & LABSW_CH2_R ? 1 : 0;
147        if (setup->wIndex & LABSW_CH2_G)
148            LED_CH2_G = setup->wValue & LABSW_CH2_G ? 1 : 0;
149        return 1;
150
151    default:
152        return 0;
153    }
154}
155
156
157void ep0_init(void)
158{
159    user_setup = my_setup;
160}
161

Archive Download this file

Branches:
master



interactive