Commit | Line | Data |
---|---|---|
47b0bbd2 MM |
1 | /* Copyright (c) 2010-2011 mbed.org, MIT License\r |
2 | *\r | |
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software\r | |
4 | * and associated documentation files (the "Software"), to deal in the Software without\r | |
5 | * restriction, including without limitation the rights to use, copy, modify, merge, publish,\r | |
6 | * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the\r | |
7 | * Software is furnished to do so, subject to the following conditions:\r | |
8 | *\r | |
9 | * The above copyright notice and this permission notice shall be included in all copies or\r | |
10 | * substantial portions of the Software.\r | |
11 | *\r | |
12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\r | |
13 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r | |
14 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\r | |
15 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r | |
16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r | |
17 | */\r | |
18 | \r | |
19 | #include <cstdint>\r | |
20 | #include <cstdio>\r | |
21 | \r | |
22 | #include "USBSerial.h"\r | |
23 | \r | |
ca5e9a57 MM |
24 | #include "libs/Kernel.h"\r |
25 | #include "libs/SerialMessage.h"\r | |
26 | \r | |
47b0bbd2 MM |
27 | // extern void setled(int, bool);\r |
28 | #define setled(a, b) do {} while (0)\r | |
29 | \r | |
6de6340d | 30 | // #define iprintf(...)\r |
47b0bbd2 MM |
31 | \r |
32 | USBSerial::USBSerial(USB *u): USBCDC(u), rxbuf(128), txbuf(128)\r | |
33 | {\r | |
34 | usb = u;\r | |
ca5e9a57 | 35 | nl_in_rx = 0;\r |
47b0bbd2 MM |
36 | }\r |
37 | \r | |
38 | int USBSerial::_putc(int c)\r | |
39 | {\r | |
40 | // send((uint8_t *)&c, 1);\r | |
41 | if (txbuf.free())\r | |
42 | txbuf.queue(c);\r | |
43 | \r | |
44 | usb->endpointSetInterrupt(CDC_BulkIn.bEndpointAddress, true);\r | |
45 | // usb->endpointTriggerInterrupt(CDC_BulkIn.bEndpointAddress);\r | |
46 | return 1;\r | |
47 | }\r | |
48 | \r | |
49 | int USBSerial::_getc()\r | |
50 | {\r | |
ca5e9a57 | 51 | uint8_t c = 0;\r |
47b0bbd2 MM |
52 | setled(4, 1); while (rxbuf.isEmpty()); setled(4, 0);\r |
53 | rxbuf.dequeue(&c);\r | |
54 | if (rxbuf.free() == MAX_PACKET_SIZE_EPBULK)\r | |
55 | {\r | |
56 | usb->endpointSetInterrupt(CDC_BulkOut.bEndpointAddress, true);\r | |
57 | iprintf("rxbuf has room for another packet, interrupt enabled\n");\r | |
58 | // usb->endpointTriggerInterrupt(CDC_BulkOut.bEndpointAddress);\r | |
59 | }\r | |
6de6340d MM |
60 | if (nl_in_rx > 0)\r |
61 | if (c == '\n')\r | |
62 | nl_in_rx--;\r | |
ca5e9a57 | 63 | \r |
47b0bbd2 MM |
64 | return c;\r |
65 | }\r | |
66 | \r | |
67 | uint16_t USBSerial::writeBlock(uint8_t * buf, uint16_t size)\r | |
68 | {\r | |
69 | if (size > txbuf.free())\r | |
70 | {\r | |
71 | size = txbuf.free();\r | |
72 | }\r | |
73 | if (size > 0)\r | |
74 | {\r | |
75 | for (uint8_t i = 0; i < size; i++)\r | |
76 | {\r | |
77 | txbuf.queue(buf[i]);\r | |
78 | }\r | |
79 | usb->endpointSetInterrupt(CDC_BulkIn.bEndpointAddress, true);\r | |
80 | }\r | |
81 | return size;\r | |
82 | }\r | |
83 | \r | |
84 | bool USBSerial::USBEvent_EPIn(uint8_t bEP, uint8_t bEPStatus)\r | |
85 | {\r | |
86 | /*\r | |
87 | * Called in ISR context\r | |
88 | */\r | |
89 | \r | |
90 | // static bool needToSendNull = false;\r | |
91 | \r | |
92 | bool r = true;\r | |
93 | \r | |
94 | if (bEP != CDC_BulkIn.bEndpointAddress)\r | |
95 | return false;\r | |
96 | \r | |
97 | iprintf("USBSerial:EpIn: 0x%02X\n", bEPStatus);\r | |
98 | \r | |
99 | uint8_t b[MAX_PACKET_SIZE_EPBULK];\r | |
100 | \r | |
101 | int l = txbuf.available();\r | |
102 | iprintf("%d bytes queued\n", l);\r | |
103 | if (l > 0)\r | |
104 | {\r | |
105 | if (l > MAX_PACKET_SIZE_EPBULK)\r | |
106 | l = MAX_PACKET_SIZE_EPBULK;\r | |
107 | iprintf("Sending %d bytes:\n\t", l);\r | |
108 | int i;\r | |
109 | for (i = 0; i < l; i++) {\r | |
110 | txbuf.dequeue(&b[i]);\r | |
111 | if (b[i] >= 32 && b[i] < 128)\r | |
112 | iprintf("%c", b[i]);\r | |
113 | else {\r | |
114 | iprintf("\\x%02X", b[i]);\r | |
115 | }\r | |
116 | }\r | |
117 | iprintf("\nSending...\n");\r | |
118 | send(b, l);\r | |
119 | iprintf("Sent\n");\r | |
120 | // if (l == 64 && txbuf.available() == 0)\r | |
121 | // needToSendNull = true;\r | |
122 | if (txbuf.available() == 0)\r | |
123 | r = false;\r | |
124 | }\r | |
125 | else\r | |
126 | {\r | |
127 | // if (needToSendNull)\r | |
128 | // {\r | |
129 | // send(NULL, 0);\r | |
130 | // needToSendNull = false;\r | |
131 | // }\r | |
132 | // else\r | |
133 | // {\r | |
134 | r = false;\r | |
135 | // }\r | |
136 | // usb->endpointSetInterrupt(bEP, false);\r | |
137 | }\r | |
138 | iprintf("USBSerial:EpIn Complete\n");\r | |
139 | return r;\r | |
140 | }\r | |
141 | \r | |
142 | bool USBSerial::USBEvent_EPOut(uint8_t bEP, uint8_t bEPStatus)\r | |
143 | {\r | |
144 | /*\r | |
145 | * Called in ISR context\r | |
146 | */\r | |
147 | \r | |
148 | bool r = true;\r | |
149 | \r | |
150 | iprintf("USBSerial:EpOut\n");\r | |
151 | if (bEP != CDC_BulkOut.bEndpointAddress)\r | |
152 | return false;\r | |
153 | \r | |
154 | if (rxbuf.free() < MAX_PACKET_SIZE_EPBULK)\r | |
155 | {\r | |
156 | // usb->endpointSetInterrupt(bEP, false);\r | |
157 | return false;\r | |
158 | }\r | |
159 | \r | |
160 | uint8_t c[MAX_PACKET_SIZE_EPBULK];\r | |
161 | uint32_t size = 64;\r | |
162 | \r | |
163 | //we read the packet received and put it on the circular buffer\r | |
164 | readEP(c, &size);\r | |
165 | iprintf("Read %ld bytes:\n\t", size);\r | |
166 | for (uint8_t i = 0; i < size; i++) {\r | |
167 | rxbuf.queue(c[i]);\r | |
168 | if (c[i] >= 32 && c[i] < 128)\r | |
ca5e9a57 | 169 | {\r |
47b0bbd2 | 170 | iprintf("%c", c[i]);\r |
ca5e9a57 MM |
171 | }\r |
172 | else\r | |
173 | {\r | |
47b0bbd2 MM |
174 | iprintf("\\x%02X", c[i]);\r |
175 | }\r | |
ca5e9a57 MM |
176 | if (c[i] == '\n')\r |
177 | nl_in_rx++;\r | |
47b0bbd2 MM |
178 | }\r |
179 | iprintf("\nQueued, %d empty\n", rxbuf.free());\r | |
180 | \r | |
181 | if (rxbuf.free() < MAX_PACKET_SIZE_EPBULK)\r | |
182 | {\r | |
183 | // usb->endpointSetInterrupt(bEP, false);\r | |
184 | r = false;\r | |
185 | }\r | |
186 | \r | |
187 | usb->readStart(CDC_BulkOut.bEndpointAddress, MAX_PACKET_SIZE_EPBULK);\r | |
188 | iprintf("USBSerial:EpOut Complete\n");\r | |
189 | return r;\r | |
190 | }\r | |
191 | \r | |
192 | /*\r | |
193 | bool USBSerial::EpCallback(uint8_t bEP, uint8_t bEPStatus) {\r | |
194 | if (bEP == CDC_BulkOut.bEndpointAddress) {\r | |
195 | uint8_t c[65];\r | |
196 | uint32_t size = 0;\r | |
197 | \r | |
198 | //we read the packet received and put it on the circular buffer\r | |
199 | readEP(c, &size);\r | |
200 | for (uint8_t i = 0; i < size; i++) {\r | |
201 | buf.queue(c[i]);\r | |
202 | }\r | |
203 | \r | |
204 | //call a potential handler\r | |
205 | rx.call();\r | |
206 | \r | |
207 | // We reactivate the endpoint to receive next characters\r | |
208 | usb->readStart(CDC_BulkOut.bEndpointAddress, MAX_PACKET_SIZE_EPBULK);\r | |
209 | return true;\r | |
210 | }\r | |
211 | return false;\r | |
212 | }*/\r | |
213 | \r | |
ca5e9a57 MM |
214 | uint8_t USBSerial::available()\r |
215 | {\r | |
47b0bbd2 MM |
216 | return rxbuf.available();\r |
217 | }\r | |
ca5e9a57 MM |
218 | \r |
219 | void USBSerial::on_module_loaded()\r | |
220 | {\r | |
221 | this->register_for_event(ON_MAIN_LOOP);\r | |
222 | // this->kernel->streams->append_stream(this);\r | |
223 | }\r | |
224 | \r | |
0bdcabe6 | 225 | void USBSerial::on_main_loop(void *argument)\r |
ca5e9a57 | 226 | {\r |
75ec4e6c | 227 | // this->kernel->streams->printf("!");\r |
ca5e9a57 MM |
228 | if (nl_in_rx)\r |
229 | {\r | |
230 | string received;\r | |
231 | while (available())\r | |
232 | {\r | |
233 | char c = _getc();\r | |
234 | if( c == '\n' )\r | |
235 | {\r | |
236 | struct SerialMessage message;\r | |
237 | message.message = received;\r | |
238 | message.stream = this;\r | |
239 | this->kernel->call_event(ON_CONSOLE_LINE_RECEIVED, &message );\r | |
240 | return;\r | |
241 | }\r | |
242 | else\r | |
243 | {\r | |
244 | received += c;\r | |
245 | }\r | |
246 | }\r | |
247 | }\r | |
248 | }\r | |
249 | \r | |
250 | void USBSerial::on_attach()\r | |
251 | {\r | |
252 | this->kernel->streams->append_stream(this);\r | |
253 | writeBlock((uint8_t *) "Smoothie\nok\n", 12);\r | |
254 | }\r | |
255 | \r | |
256 | void USBSerial::on_detach()\r | |
257 | {\r | |
258 | this->kernel->streams->remove_stream(this);\r | |
259 | txbuf.flush();\r | |
260 | rxbuf.flush();\r | |
261 | nl_in_rx = 0;\r | |
262 | }\r |