blob: 7db941eeb95dff536b8727164ac914b5ff063ae6 [file] [log] [blame]
Sylvain Munautf5d7bf22020-09-14 10:23:50 +02001/*
2 * fw_app.c
3 *
4 * Copyright (C) 2019-2020 Sylvain Munaut <tnt@246tNt.com>
5 * SPDX-License-Identifier: GPL-3.0-or-later
6 */
7
8#include <stdint.h>
9#include <stdbool.h>
10#include <string.h>
11
12#include <no2usb/usb.h>
13#include <no2usb/usb_dfu_rt.h>
14
15#include "console.h"
16#include "e1.h"
17#include "led.h"
18#include "misc.h"
19#include "mini-printf.h"
20#include "spi.h"
Sylvain Munaut632a3002020-10-29 13:25:45 +010021#include "usb_e1.h"
Sylvain Munautf5d7bf22020-09-14 10:23:50 +020022#include "utils.h"
23
24
25extern const struct usb_stack_descriptors app_stack_desc;
26
Sylvain Munautf5d7bf22020-09-14 10:23:50 +020027static void
28serial_no_init()
29{
30 uint8_t buf[8];
31 char *id, *desc;
32 int i;
33
34 flash_manuf_id(buf);
35 printf("Flash Manufacturer : %s\n", hexstr(buf, 3, true));
36
37 flash_unique_id(buf);
38 printf("Flash Unique ID : %s\n", hexstr(buf, 8, true));
39
40 /* Overwrite descriptor string */
41 /* In theory in rodata ... but nothing is ro here */
42 id = hexstr(buf, 8, false);
43 desc = (char*)app_stack_desc.str[1];
44 for (i=0; i<16; i++)
45 desc[2 + (i << 1)] = id[i];
46}
47
48static void
49boot_dfu(void)
50{
51 /* Force re-enumeration */
52 usb_disconnect();
53
54 /* Boot firmware */
Sylvain Munaut46d6b412020-10-29 13:19:05 +010055 reboot(1);
Sylvain Munautf5d7bf22020-09-14 10:23:50 +020056}
57
58void
59usb_dfu_rt_cb_reboot(void)
60{
61 boot_dfu();
62}
63
64
65
66static uint8_t
67liu_read_reg(unsigned chan, uint8_t reg)
68{
69 uint8_t cmd = reg | 0x20;
70 uint8_t rv;
71 struct spi_xfer_chunk xfer[2] = {
72 { .data = (void*)&cmd, .len = 1, .read = false, .write = true, },
73 { .data = (void*)&rv, .len = 1, .read = true, .write = false, },
74 };
75 spi_xfer(SPI_CS_LIU(chan), xfer, 2);
76 return rv;
77}
78
79static void
80liu_write_reg(unsigned chan, uint8_t reg, uint8_t val)
81{
82 uint8_t cmd[2] = { reg, val };
83 struct spi_xfer_chunk xfer[2] = {
84 { .data = (void*)cmd, .len = 2, .read = false, .write = true, },
85 };
86 spi_xfer(SPI_CS_LIU(chan), xfer, 1);
87}
88
89
90
91#define USB_RT_LIU_REG_WRITE ((1 << 8) | 0x42)
92#define USB_RT_LIU_REG_READ ((2 << 8) | 0xc2)
93
94
95static bool
96_liu_reg_write_done_cb(struct usb_xfer *xfer)
97{
98 struct usb_ctrl_req *req = xfer->cb_ctx;
99 unsigned chan = req->wIndex - 0x81;
100
101 liu_write_reg(chan, req->wValue, xfer->data[0]);
102
103 return true;
104}
105
106static enum usb_fnd_resp
107_liu_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer)
108{
109 unsigned chan;
110
111 /* If this a vendor request for the E1 endpoints */
112 if (USB_REQ_RCPT(req) != USB_REQ_RCPT_EP)
113 return USB_FND_CONTINUE;
114
115 if (req->wIndex < 0x81 || req->wIndex > 0x82)
116 return USB_FND_CONTINUE;
117
118 if (USB_REQ_TYPE(req) != USB_REQ_TYPE_VENDOR)
119 return USB_FND_CONTINUE;
120
121 chan = req->wIndex - 0x81;
122
123 /* */
124 switch (req->wRequestAndType)
125 {
126 case USB_RT_LIU_REG_WRITE:
127 xfer->len = 1;
128 xfer->cb_done = _liu_reg_write_done_cb;
129 xfer->cb_ctx = req;
130 break;
131
132 case USB_RT_LIU_REG_READ:
133 xfer->len = 1;
134 xfer->data[0] = liu_read_reg(chan, req->wValue);
135 break;
136
137 default:
138 goto error;
139 }
140
141 return USB_FND_SUCCESS;
142
143error:
144 return USB_FND_ERROR;
145}
146
147static struct usb_fn_drv _liu_drv = {
148 .ctrl_req = _liu_ctrl_req,
149};
150
151
152
153void main()
154{
155 int cmd = 0;
156
157 /* Init console IO */
158 console_init();
159 puts("Booting App image..\n");
160
161 /* LED */
162 led_init();
163 led_state(true);
164
165 /* SPI */
166 spi_init();
167
Sylvain Munautf5d7bf22020-09-14 10:23:50 +0200168 /* Enable USB directly */
169 serial_no_init();
170 usb_init(&app_stack_desc);
171 usb_dfu_rt_init();
172 usb_register_function_driver(&_liu_drv);
173 usb_e1_init();
174
175 usb_connect();
176 e1_init();
177
178 /* Main loop */
179 while (1)
180 {
181 /* Prompt ? */
182 if (cmd >= 0)
183 printf("Command> ");
184
185 /* Poll for command */
186 cmd = getchar_nowait();
187
188 if (cmd >= 0) {
189 if (cmd > 32 && cmd < 127) {
190 putchar(cmd);
191 putchar('\r');
192 putchar('\n');
193 }
194
195 switch (cmd)
196 {
197 case 'u':
198 usb_debug_print();
199 break;
200 case 'e':
201 e1_debug_print(false);
202 break;
203 case 'E':
204 e1_debug_print(true);
205 break;
206 default:
207 break;
208 }
209 }
210
211 /* USB poll */
212 usb_poll();
213
214 /* E1 poll */
215 e1_poll();
216 usb_e1_run();
217 }
218}