X-TOUCH to djay bridge

Dependencies:   mbed mbed-rtos FATFileSystem

Committer:
okini3939
Date:
Wed Jun 05 04:54:37 2019 +0000
Revision:
1:0dac72ab5910
sample

Who changed what in which revision?

UserRevisionLine numberNew contents of line
okini3939 1:0dac72ab5910 1 /* mbed USBHost Library
okini3939 1:0dac72ab5910 2 * Copyright (c) 2006-2013 ARM Limited
okini3939 1:0dac72ab5910 3 *
okini3939 1:0dac72ab5910 4 * Licensed under the Apache License, Version 2.0 (the "License");
okini3939 1:0dac72ab5910 5 * you may not use this file except in compliance with the License.
okini3939 1:0dac72ab5910 6 * You may obtain a copy of the License at
okini3939 1:0dac72ab5910 7 *
okini3939 1:0dac72ab5910 8 * http://www.apache.org/licenses/LICENSE-2.0
okini3939 1:0dac72ab5910 9 *
okini3939 1:0dac72ab5910 10 * Unless required by applicable law or agreed to in writing, software
okini3939 1:0dac72ab5910 11 * distributed under the License is distributed on an "AS IS" BASIS,
okini3939 1:0dac72ab5910 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
okini3939 1:0dac72ab5910 13 * See the License for the specific language governing permissions and
okini3939 1:0dac72ab5910 14 * limitations under the License.
okini3939 1:0dac72ab5910 15 */
okini3939 1:0dac72ab5910 16
okini3939 1:0dac72ab5910 17 #include "USBHostSerial.h"
okini3939 1:0dac72ab5910 18
okini3939 1:0dac72ab5910 19 #if USBHOST_SERIAL
okini3939 1:0dac72ab5910 20
okini3939 1:0dac72ab5910 21 #include "dbg.h"
okini3939 1:0dac72ab5910 22
okini3939 1:0dac72ab5910 23 #define CHECK_INTERFACE(cls,subcls,proto) \
okini3939 1:0dac72ab5910 24 (((cls == 0xFF) && (subcls == 0xFF) && (proto == 0xFF)) /* QUALCOM CDC */ || \
okini3939 1:0dac72ab5910 25 ((cls == SERIAL_CLASS) && (subcls == 0x00) && (proto == 0x00)) /* STANDARD CDC */ )
okini3939 1:0dac72ab5910 26
okini3939 1:0dac72ab5910 27 #if (USBHOST_SERIAL <= 1)
okini3939 1:0dac72ab5910 28
okini3939 1:0dac72ab5910 29 USBHostSerial::USBHostSerial()
okini3939 1:0dac72ab5910 30 {
okini3939 1:0dac72ab5910 31 host = USBHost::getHostInst();
okini3939 1:0dac72ab5910 32 ports_found = 0;
okini3939 1:0dac72ab5910 33 dev_connected = false;
okini3939 1:0dac72ab5910 34 }
okini3939 1:0dac72ab5910 35
okini3939 1:0dac72ab5910 36 bool USBHostSerial::connected()
okini3939 1:0dac72ab5910 37 {
okini3939 1:0dac72ab5910 38 return dev_connected;
okini3939 1:0dac72ab5910 39 }
okini3939 1:0dac72ab5910 40
okini3939 1:0dac72ab5910 41 void USBHostSerial::disconnect(void)
okini3939 1:0dac72ab5910 42 {
okini3939 1:0dac72ab5910 43 ports_found = 0;
okini3939 1:0dac72ab5910 44 dev = NULL;
okini3939 1:0dac72ab5910 45 }
okini3939 1:0dac72ab5910 46
okini3939 1:0dac72ab5910 47 bool USBHostSerial::connect() {
okini3939 1:0dac72ab5910 48
okini3939 1:0dac72ab5910 49 if (dev)
okini3939 1:0dac72ab5910 50 {
okini3939 1:0dac72ab5910 51 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
okini3939 1:0dac72ab5910 52 {
okini3939 1:0dac72ab5910 53 USBDeviceConnected* d = host->getDevice(i);
okini3939 1:0dac72ab5910 54 if (dev == d)
okini3939 1:0dac72ab5910 55 return true;
okini3939 1:0dac72ab5910 56 }
okini3939 1:0dac72ab5910 57 disconnect();
okini3939 1:0dac72ab5910 58 }
okini3939 1:0dac72ab5910 59 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
okini3939 1:0dac72ab5910 60 {
okini3939 1:0dac72ab5910 61 USBDeviceConnected* d = host->getDevice(i);
okini3939 1:0dac72ab5910 62 if (d != NULL) {
okini3939 1:0dac72ab5910 63
okini3939 1:0dac72ab5910 64 USB_DBG("Trying to connect serial device \r\n");
okini3939 1:0dac72ab5910 65 if(host->enumerate(d, this))
okini3939 1:0dac72ab5910 66 break;
okini3939 1:0dac72ab5910 67
okini3939 1:0dac72ab5910 68 USBEndpoint* bulk_in = d->getEndpoint(port_intf, BULK_ENDPOINT, IN);
okini3939 1:0dac72ab5910 69 USBEndpoint* bulk_out = d->getEndpoint(port_intf, BULK_ENDPOINT, OUT);
okini3939 1:0dac72ab5910 70 if (bulk_in && bulk_out)
okini3939 1:0dac72ab5910 71 {
okini3939 1:0dac72ab5910 72 USBHostSerialPort::connect(host,d,port_intf,bulk_in, bulk_out);
okini3939 1:0dac72ab5910 73 dev = d;
okini3939 1:0dac72ab5910 74 dev_connected = true;
okini3939 1:0dac72ab5910 75 }
okini3939 1:0dac72ab5910 76 }
okini3939 1:0dac72ab5910 77 }
okini3939 1:0dac72ab5910 78 return dev != NULL;
okini3939 1:0dac72ab5910 79 }
okini3939 1:0dac72ab5910 80
okini3939 1:0dac72ab5910 81 /*virtual*/ void USBHostSerial::setVidPid(uint16_t vid, uint16_t pid)
okini3939 1:0dac72ab5910 82 {
okini3939 1:0dac72ab5910 83 // we don't check VID/PID for MSD driver
okini3939 1:0dac72ab5910 84 }
okini3939 1:0dac72ab5910 85
okini3939 1:0dac72ab5910 86 /*virtual*/ bool USBHostSerial::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
okini3939 1:0dac72ab5910 87 {
okini3939 1:0dac72ab5910 88 if (!ports_found &&
okini3939 1:0dac72ab5910 89 CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) {
okini3939 1:0dac72ab5910 90 port_intf = intf_nb;
okini3939 1:0dac72ab5910 91 ports_found = true;
okini3939 1:0dac72ab5910 92 return true;
okini3939 1:0dac72ab5910 93 }
okini3939 1:0dac72ab5910 94 return false;
okini3939 1:0dac72ab5910 95 }
okini3939 1:0dac72ab5910 96
okini3939 1:0dac72ab5910 97 /*virtual*/ bool USBHostSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
okini3939 1:0dac72ab5910 98 {
okini3939 1:0dac72ab5910 99 if (ports_found && (intf_nb == port_intf)) {
okini3939 1:0dac72ab5910 100 if (type == BULK_ENDPOINT)
okini3939 1:0dac72ab5910 101 return true;
okini3939 1:0dac72ab5910 102 }
okini3939 1:0dac72ab5910 103 return false;
okini3939 1:0dac72ab5910 104 }
okini3939 1:0dac72ab5910 105
okini3939 1:0dac72ab5910 106 #else // (USBHOST_SERIAL > 1)
okini3939 1:0dac72ab5910 107
okini3939 1:0dac72ab5910 108 //------------------------------------------------------------------------------
okini3939 1:0dac72ab5910 109
okini3939 1:0dac72ab5910 110 USBHostMultiSerial::USBHostMultiSerial()
okini3939 1:0dac72ab5910 111 {
okini3939 1:0dac72ab5910 112 host = USBHost::getHostInst();
okini3939 1:0dac72ab5910 113 dev = NULL;
okini3939 1:0dac72ab5910 114 memset(ports, NULL, sizeof(ports));
okini3939 1:0dac72ab5910 115 ports_found = 0;
okini3939 1:0dac72ab5910 116 dev_connected = false;
okini3939 1:0dac72ab5910 117 }
okini3939 1:0dac72ab5910 118
okini3939 1:0dac72ab5910 119 USBHostMultiSerial::~USBHostMultiSerial()
okini3939 1:0dac72ab5910 120 {
okini3939 1:0dac72ab5910 121 disconnect();
okini3939 1:0dac72ab5910 122 }
okini3939 1:0dac72ab5910 123
okini3939 1:0dac72ab5910 124 bool USBHostMultiSerial::connected()
okini3939 1:0dac72ab5910 125 {
okini3939 1:0dac72ab5910 126 return dev_connected;
okini3939 1:0dac72ab5910 127 }
okini3939 1:0dac72ab5910 128
okini3939 1:0dac72ab5910 129 void USBHostMultiSerial::disconnect(void)
okini3939 1:0dac72ab5910 130 {
okini3939 1:0dac72ab5910 131 for (int port = 0; port < USBHOST_SERIAL; port ++)
okini3939 1:0dac72ab5910 132 {
okini3939 1:0dac72ab5910 133 if (ports[port])
okini3939 1:0dac72ab5910 134 {
okini3939 1:0dac72ab5910 135 delete ports[port];
okini3939 1:0dac72ab5910 136 ports[port] = NULL;
okini3939 1:0dac72ab5910 137 }
okini3939 1:0dac72ab5910 138 }
okini3939 1:0dac72ab5910 139 ports_found = 0;
okini3939 1:0dac72ab5910 140 dev = NULL;
okini3939 1:0dac72ab5910 141 }
okini3939 1:0dac72ab5910 142
okini3939 1:0dac72ab5910 143 bool USBHostMultiSerial::connect() {
okini3939 1:0dac72ab5910 144
okini3939 1:0dac72ab5910 145 if (dev)
okini3939 1:0dac72ab5910 146 {
okini3939 1:0dac72ab5910 147 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
okini3939 1:0dac72ab5910 148 {
okini3939 1:0dac72ab5910 149 USBDeviceConnected* d = host->getDevice(i);
okini3939 1:0dac72ab5910 150 if (dev == d)
okini3939 1:0dac72ab5910 151 return true;
okini3939 1:0dac72ab5910 152 }
okini3939 1:0dac72ab5910 153 disconnect();
okini3939 1:0dac72ab5910 154 }
okini3939 1:0dac72ab5910 155 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++)
okini3939 1:0dac72ab5910 156 {
okini3939 1:0dac72ab5910 157 USBDeviceConnected* d = host->getDevice(i);
okini3939 1:0dac72ab5910 158 if (d != NULL) {
okini3939 1:0dac72ab5910 159
okini3939 1:0dac72ab5910 160 USB_DBG("Trying to connect serial device \r\n");
okini3939 1:0dac72ab5910 161 if(host->enumerate(d, this))
okini3939 1:0dac72ab5910 162 break;
okini3939 1:0dac72ab5910 163
okini3939 1:0dac72ab5910 164 for (int port = 0; port < ports_found; port ++)
okini3939 1:0dac72ab5910 165 {
okini3939 1:0dac72ab5910 166 USBEndpoint* bulk_in = d->getEndpoint(port_intf[port], BULK_ENDPOINT, IN);
okini3939 1:0dac72ab5910 167 USBEndpoint* bulk_out = d->getEndpoint(port_intf[port], BULK_ENDPOINT, OUT);
okini3939 1:0dac72ab5910 168 if (bulk_in && bulk_out)
okini3939 1:0dac72ab5910 169 {
okini3939 1:0dac72ab5910 170 ports[port] = new USBHostSerialPort();
okini3939 1:0dac72ab5910 171 if (ports[port])
okini3939 1:0dac72ab5910 172 {
okini3939 1:0dac72ab5910 173 ports[port]->connect(host,d,port_intf[port],bulk_in, bulk_out);
okini3939 1:0dac72ab5910 174 dev = d;
okini3939 1:0dac72ab5910 175 dev_connected = true;
okini3939 1:0dac72ab5910 176 }
okini3939 1:0dac72ab5910 177 }
okini3939 1:0dac72ab5910 178 }
okini3939 1:0dac72ab5910 179 }
okini3939 1:0dac72ab5910 180 }
okini3939 1:0dac72ab5910 181 return dev != NULL;
okini3939 1:0dac72ab5910 182 }
okini3939 1:0dac72ab5910 183
okini3939 1:0dac72ab5910 184 /*virtual*/ void USBHostMultiSerial::setVidPid(uint16_t vid, uint16_t pid)
okini3939 1:0dac72ab5910 185 {
okini3939 1:0dac72ab5910 186 // we don't check VID/PID for MSD driver
okini3939 1:0dac72ab5910 187 }
okini3939 1:0dac72ab5910 188
okini3939 1:0dac72ab5910 189 /*virtual*/ bool USBHostMultiSerial::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
okini3939 1:0dac72ab5910 190 {
okini3939 1:0dac72ab5910 191 if ((ports_found < USBHOST_SERIAL) &&
okini3939 1:0dac72ab5910 192 CHECK_INTERFACE(intf_class, intf_subclass, intf_protocol)) {
okini3939 1:0dac72ab5910 193 port_intf[ports_found++] = intf_nb;
okini3939 1:0dac72ab5910 194 return true;
okini3939 1:0dac72ab5910 195 }
okini3939 1:0dac72ab5910 196 return false;
okini3939 1:0dac72ab5910 197 }
okini3939 1:0dac72ab5910 198
okini3939 1:0dac72ab5910 199 /*virtual*/ bool USBHostMultiSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
okini3939 1:0dac72ab5910 200 {
okini3939 1:0dac72ab5910 201 if ((ports_found > 0) && (intf_nb == port_intf[ports_found-1])) {
okini3939 1:0dac72ab5910 202 if (type == BULK_ENDPOINT)
okini3939 1:0dac72ab5910 203 return true;
okini3939 1:0dac72ab5910 204 }
okini3939 1:0dac72ab5910 205 return false;
okini3939 1:0dac72ab5910 206 }
okini3939 1:0dac72ab5910 207
okini3939 1:0dac72ab5910 208 #endif
okini3939 1:0dac72ab5910 209
okini3939 1:0dac72ab5910 210 //------------------------------------------------------------------------------
okini3939 1:0dac72ab5910 211
okini3939 1:0dac72ab5910 212 #define SET_LINE_CODING 0x20
okini3939 1:0dac72ab5910 213
okini3939 1:0dac72ab5910 214 USBHostSerialPort::USBHostSerialPort(): circ_buf()
okini3939 1:0dac72ab5910 215 {
okini3939 1:0dac72ab5910 216 init();
okini3939 1:0dac72ab5910 217 }
okini3939 1:0dac72ab5910 218
okini3939 1:0dac72ab5910 219 void USBHostSerialPort::init(void)
okini3939 1:0dac72ab5910 220 {
okini3939 1:0dac72ab5910 221 host = NULL;
okini3939 1:0dac72ab5910 222 dev = NULL;
okini3939 1:0dac72ab5910 223 serial_intf = NULL;
okini3939 1:0dac72ab5910 224 size_bulk_in = 0;
okini3939 1:0dac72ab5910 225 size_bulk_out = 0;
okini3939 1:0dac72ab5910 226 bulk_in = NULL;
okini3939 1:0dac72ab5910 227 bulk_out = NULL;
okini3939 1:0dac72ab5910 228 line_coding.baudrate = 9600;
okini3939 1:0dac72ab5910 229 line_coding.data_bits = 8;
okini3939 1:0dac72ab5910 230 line_coding.parity = None;
okini3939 1:0dac72ab5910 231 line_coding.stop_bits = 1;
okini3939 1:0dac72ab5910 232 circ_buf.flush();
okini3939 1:0dac72ab5910 233 }
okini3939 1:0dac72ab5910 234
okini3939 1:0dac72ab5910 235 void USBHostSerialPort::connect(USBHost* _host, USBDeviceConnected * _dev,
okini3939 1:0dac72ab5910 236 uint8_t _serial_intf, USBEndpoint* _bulk_in, USBEndpoint* _bulk_out)
okini3939 1:0dac72ab5910 237 {
okini3939 1:0dac72ab5910 238 host = _host;
okini3939 1:0dac72ab5910 239 dev = _dev;
okini3939 1:0dac72ab5910 240 serial_intf = _serial_intf;
okini3939 1:0dac72ab5910 241 bulk_in = _bulk_in;
okini3939 1:0dac72ab5910 242 bulk_out = _bulk_out;
okini3939 1:0dac72ab5910 243
okini3939 1:0dac72ab5910 244 USB_INFO("New Serial device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, serial_intf);
okini3939 1:0dac72ab5910 245 dev->setName("Serial", serial_intf);
okini3939 1:0dac72ab5910 246 host->registerDriver(dev, serial_intf, this, &USBHostSerialPort::init);
okini3939 1:0dac72ab5910 247 baud(9600);
okini3939 1:0dac72ab5910 248 size_bulk_in = bulk_in->getSize();
okini3939 1:0dac72ab5910 249 size_bulk_out = bulk_out->getSize();
okini3939 1:0dac72ab5910 250 bulk_in->attach(this, &USBHostSerialPort::rxHandler);
okini3939 1:0dac72ab5910 251 bulk_out->attach(this, &USBHostSerialPort::txHandler);
okini3939 1:0dac72ab5910 252 host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
okini3939 1:0dac72ab5910 253 }
okini3939 1:0dac72ab5910 254
okini3939 1:0dac72ab5910 255 void USBHostSerialPort::rxHandler() {
okini3939 1:0dac72ab5910 256 if (bulk_in) {
okini3939 1:0dac72ab5910 257 int len = bulk_in->getLengthTransferred();
okini3939 1:0dac72ab5910 258 if (bulk_in->getState() == USB_TYPE_IDLE) {
okini3939 1:0dac72ab5910 259 for (int i = 0; i < len; i++) {
okini3939 1:0dac72ab5910 260 circ_buf.queue(buf[i]);
okini3939 1:0dac72ab5910 261 }
okini3939 1:0dac72ab5910 262 rx.call();
okini3939 1:0dac72ab5910 263 host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
okini3939 1:0dac72ab5910 264 }
okini3939 1:0dac72ab5910 265 }
okini3939 1:0dac72ab5910 266 }
okini3939 1:0dac72ab5910 267
okini3939 1:0dac72ab5910 268 void USBHostSerialPort::txHandler() {
okini3939 1:0dac72ab5910 269 if (bulk_out) {
okini3939 1:0dac72ab5910 270 if (bulk_out->getState() == USB_TYPE_IDLE) {
okini3939 1:0dac72ab5910 271 tx.call();
okini3939 1:0dac72ab5910 272 }
okini3939 1:0dac72ab5910 273 }
okini3939 1:0dac72ab5910 274 }
okini3939 1:0dac72ab5910 275
okini3939 1:0dac72ab5910 276 int USBHostSerialPort::_putc(int c) {
okini3939 1:0dac72ab5910 277 if (bulk_out) {
okini3939 1:0dac72ab5910 278 if (host->bulkWrite(dev, bulk_out, (uint8_t *)&c, 1) == USB_TYPE_OK) {
okini3939 1:0dac72ab5910 279 return 1;
okini3939 1:0dac72ab5910 280 }
okini3939 1:0dac72ab5910 281 }
okini3939 1:0dac72ab5910 282 return -1;
okini3939 1:0dac72ab5910 283 }
okini3939 1:0dac72ab5910 284
okini3939 1:0dac72ab5910 285 void USBHostSerialPort::baud(int baudrate) {
okini3939 1:0dac72ab5910 286 line_coding.baudrate = baudrate;
okini3939 1:0dac72ab5910 287 format(line_coding.data_bits, (Parity)line_coding.parity, line_coding.stop_bits);
okini3939 1:0dac72ab5910 288 }
okini3939 1:0dac72ab5910 289
okini3939 1:0dac72ab5910 290 void USBHostSerialPort::format(int bits, Parity parity, int stop_bits) {
okini3939 1:0dac72ab5910 291 line_coding.data_bits = bits;
okini3939 1:0dac72ab5910 292 line_coding.parity = parity;
okini3939 1:0dac72ab5910 293 line_coding.stop_bits = (stop_bits == 1) ? 0 : 2;
okini3939 1:0dac72ab5910 294
okini3939 1:0dac72ab5910 295 // set line coding
okini3939 1:0dac72ab5910 296 host->controlWrite( dev,
okini3939 1:0dac72ab5910 297 USB_RECIPIENT_INTERFACE | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS,
okini3939 1:0dac72ab5910 298 SET_LINE_CODING,
okini3939 1:0dac72ab5910 299 0, serial_intf, (uint8_t *)&line_coding, 7);
okini3939 1:0dac72ab5910 300 }
okini3939 1:0dac72ab5910 301
okini3939 1:0dac72ab5910 302 int USBHostSerialPort::_getc() {
okini3939 1:0dac72ab5910 303 uint8_t c = 0;
okini3939 1:0dac72ab5910 304 if (bulk_in == NULL) {
okini3939 1:0dac72ab5910 305 init();
okini3939 1:0dac72ab5910 306 return -1;
okini3939 1:0dac72ab5910 307 }
okini3939 1:0dac72ab5910 308 while (circ_buf.isEmpty());
okini3939 1:0dac72ab5910 309 circ_buf.dequeue(&c);
okini3939 1:0dac72ab5910 310 return c;
okini3939 1:0dac72ab5910 311 }
okini3939 1:0dac72ab5910 312
okini3939 1:0dac72ab5910 313 int USBHostSerialPort::writeBuf(const char* b, int s)
okini3939 1:0dac72ab5910 314 {
okini3939 1:0dac72ab5910 315 int c = 0;
okini3939 1:0dac72ab5910 316 if (bulk_out)
okini3939 1:0dac72ab5910 317 {
okini3939 1:0dac72ab5910 318 while (c < s)
okini3939 1:0dac72ab5910 319 {
okini3939 1:0dac72ab5910 320 int i = (s < size_bulk_out) ? s : size_bulk_out;
okini3939 1:0dac72ab5910 321 if (host->bulkWrite(dev, bulk_out, (uint8_t *)(b+c), i) == USB_TYPE_OK)
okini3939 1:0dac72ab5910 322 c += i;
okini3939 1:0dac72ab5910 323 }
okini3939 1:0dac72ab5910 324 }
okini3939 1:0dac72ab5910 325 return s;
okini3939 1:0dac72ab5910 326 }
okini3939 1:0dac72ab5910 327
okini3939 1:0dac72ab5910 328 int USBHostSerialPort::readBuf(char* b, int s)
okini3939 1:0dac72ab5910 329 {
okini3939 1:0dac72ab5910 330 int i = 0;
okini3939 1:0dac72ab5910 331 if (bulk_in)
okini3939 1:0dac72ab5910 332 {
okini3939 1:0dac72ab5910 333 for (i = 0; i < s; )
okini3939 1:0dac72ab5910 334 b[i++] = getc();
okini3939 1:0dac72ab5910 335 }
okini3939 1:0dac72ab5910 336 return i;
okini3939 1:0dac72ab5910 337 }
okini3939 1:0dac72ab5910 338
okini3939 1:0dac72ab5910 339 uint8_t USBHostSerialPort::available() {
okini3939 1:0dac72ab5910 340 return circ_buf.available();
okini3939 1:0dac72ab5910 341 }
okini3939 1:0dac72ab5910 342
okini3939 1:0dac72ab5910 343
okini3939 1:0dac72ab5910 344
okini3939 1:0dac72ab5910 345 #endif