Fix some warnings that would be generated by gcc -Wmissing-prototypes
[qemu/mini2440.git] / hw / usb-serial.c
blob92d6dfdd42b26dd97dcc4e87d09262f75d93d687
1 /*
2 * FTDI FT232BM Device emulation
4 * Copyright (c) 2006 CodeSourcery.
5 * Copyright (c) 2008 Samuel Thibault <samuel.thibault@ens-lyon.org>
6 * Written by Paul Brook, reused for FTDI by Samuel Thibault
8 * This code is licenced under the LGPL.
9 */
11 #include "qemu-common.h"
12 #include "usb.h"
13 #include "qemu-char.h"
15 //#define DEBUG_Serial
17 #ifdef DEBUG_Serial
18 #define DPRINTF(fmt, args...) \
19 do { printf("usb-serial: " fmt , ##args); } while (0)
20 #else
21 #define DPRINTF(fmt, args...) do {} while(0)
22 #endif
24 #define RECV_BUF 384
25 #define SEND_BUF 128 // Not used for now
27 /* Commands */
28 #define FTDI_RESET 0
29 #define FTDI_SET_MDM_CTRL 1
30 #define FTDI_SET_FLOW_CTRL 2
31 #define FTDI_SET_BAUD 3
32 #define FTDI_SET_DATA 4
33 #define FTDI_GET_MDM_ST 5
34 #define FTDI_SET_EVENT_CHR 6
35 #define FTDI_SET_ERROR_CHR 7
36 #define FTDI_SET_LATENCY 9
37 #define FTDI_GET_LATENCY 10
39 #define DeviceOutVendor ((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8)
40 #define DeviceInVendor ((USB_DIR_IN |USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8)
42 /* RESET */
44 #define FTDI_RESET_SIO 0
45 #define FTDI_RESET_RX 1
46 #define FTDI_RESET_TX 2
48 /* SET_MDM_CTRL */
50 #define FTDI_DTR 1
51 #define FTDI_SET_DTR (FTDI_DTR << 8)
52 #define FTDI_RTS 2
53 #define FTDI_SET_RTS (FTDI_RTS << 8)
55 /* SET_FLOW_CTRL */
57 #define FTDI_RTS_CTS_HS 1
58 #define FTDI_DTR_DSR_HS 2
59 #define FTDI_XON_XOFF_HS 4
61 /* SET_DATA */
63 #define FTDI_PARITY (0x7 << 8)
64 #define FTDI_ODD (0x1 << 8)
65 #define FTDI_EVEN (0x2 << 8)
66 #define FTDI_MARK (0x3 << 8)
67 #define FTDI_SPACE (0x4 << 8)
69 #define FTDI_STOP (0x3 << 11)
70 #define FTDI_STOP1 (0x0 << 11)
71 #define FTDI_STOP15 (0x1 << 11)
72 #define FTDI_STOP2 (0x2 << 11)
74 /* GET_MDM_ST */
75 /* TODO: should be sent every 40ms */
76 #define FTDI_CTS (1<<4) // CTS line status
77 #define FTDI_DSR (1<<5) // DSR line status
78 #define FTDI_RI (1<<6) // RI line status
79 #define FTDI_RLSD (1<<7) // Receive Line Signal Detect
81 /* Status */
83 #define FTDI_DR (1<<0) // Data Ready
84 #define FTDI_OE (1<<1) // Overrun Err
85 #define FTDI_PE (1<<2) // Parity Err
86 #define FTDI_FE (1<<3) // Framing Err
87 #define FTDI_BI (1<<4) // Break Interrupt
88 #define FTDI_THRE (1<<5) // Transmitter Holding Register
89 #define FTDI_TEMT (1<<6) // Transmitter Empty
90 #define FTDI_FIFO (1<<7) // Error in FIFO
92 typedef struct {
93 USBDevice dev;
94 uint16_t vendorid;
95 uint16_t productid;
96 uint8_t recv_buf[RECV_BUF];
97 uint8_t recv_ptr;
98 uint8_t recv_used;
99 uint8_t send_buf[SEND_BUF];
100 uint8_t event_chr;
101 uint8_t error_chr;
102 uint8_t event_trigger;
103 QEMUSerialSetParams params;
104 int latency; /* ms */
105 CharDriverState *cs;
106 } USBSerialState;
108 static const uint8_t qemu_serial_dev_descriptor[] = {
109 0x12, /* u8 bLength; */
110 0x01, /* u8 bDescriptorType; Device */
111 0x00, 0x02, /* u16 bcdUSB; v2.0 */
113 0x00, /* u8 bDeviceClass; */
114 0x00, /* u8 bDeviceSubClass; */
115 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
116 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
118 /* Vendor and product id are arbitrary. */
119 0x03, 0x04, /* u16 idVendor; */
120 0x00, 0xFF, /* u16 idProduct; */
121 0x00, 0x04, /* u16 bcdDevice */
123 0x01, /* u8 iManufacturer; */
124 0x02, /* u8 iProduct; */
125 0x03, /* u8 iSerialNumber; */
126 0x01 /* u8 bNumConfigurations; */
129 static const uint8_t qemu_serial_config_descriptor[] = {
131 /* one configuration */
132 0x09, /* u8 bLength; */
133 0x02, /* u8 bDescriptorType; Configuration */
134 0x20, 0x00, /* u16 wTotalLength; */
135 0x01, /* u8 bNumInterfaces; (1) */
136 0x01, /* u8 bConfigurationValue; */
137 0x00, /* u8 iConfiguration; */
138 0x80, /* u8 bmAttributes;
139 Bit 7: must be set,
140 6: Self-powered,
141 5: Remote wakeup,
142 4..0: resvd */
143 100/2, /* u8 MaxPower; */
145 /* one interface */
146 0x09, /* u8 if_bLength; */
147 0x04, /* u8 if_bDescriptorType; Interface */
148 0x00, /* u8 if_bInterfaceNumber; */
149 0x00, /* u8 if_bAlternateSetting; */
150 0x02, /* u8 if_bNumEndpoints; */
151 0xff, /* u8 if_bInterfaceClass; Vendor Specific */
152 0xff, /* u8 if_bInterfaceSubClass; Vendor Specific */
153 0xff, /* u8 if_bInterfaceProtocol; Vendor Specific */
154 0x02, /* u8 if_iInterface; */
156 /* Bulk-In endpoint */
157 0x07, /* u8 ep_bLength; */
158 0x05, /* u8 ep_bDescriptorType; Endpoint */
159 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
160 0x02, /* u8 ep_bmAttributes; Bulk */
161 0x40, 0x00, /* u16 ep_wMaxPacketSize; */
162 0x00, /* u8 ep_bInterval; */
164 /* Bulk-Out endpoint */
165 0x07, /* u8 ep_bLength; */
166 0x05, /* u8 ep_bDescriptorType; Endpoint */
167 0x02, /* u8 ep_bEndpointAddress; OUT Endpoint 2 */
168 0x02, /* u8 ep_bmAttributes; Bulk */
169 0x40, 0x00, /* u16 ep_wMaxPacketSize; */
170 0x00 /* u8 ep_bInterval; */
173 static void usb_serial_reset(USBSerialState *s)
175 /* TODO: Set flow control to none */
176 s->event_chr = 0x0d;
177 s->event_trigger = 0;
178 s->recv_ptr = 0;
179 s->recv_used = 0;
180 /* TODO: purge in char driver */
183 static void usb_serial_handle_reset(USBDevice *dev)
185 USBSerialState *s = (USBSerialState *)dev;
187 DPRINTF("Reset\n");
189 usb_serial_reset(s);
190 /* TODO: Reset char device, send BREAK? */
193 static uint8_t usb_get_modem_lines(USBSerialState *s)
195 int flags;
196 uint8_t ret;
198 if (qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP)
199 return FTDI_CTS|FTDI_DSR|FTDI_RLSD;
201 ret = 0;
202 if (flags & CHR_TIOCM_CTS)
203 ret |= FTDI_CTS;
204 if (flags & CHR_TIOCM_DSR)
205 ret |= FTDI_DSR;
206 if (flags & CHR_TIOCM_RI)
207 ret |= FTDI_RI;
208 if (flags & CHR_TIOCM_CAR)
209 ret |= FTDI_RLSD;
211 return ret;
214 static int usb_serial_handle_control(USBDevice *dev, int request, int value,
215 int index, int length, uint8_t *data)
217 USBSerialState *s = (USBSerialState *)dev;
218 int ret = 0;
220 //DPRINTF("got control %x, value %x\n",request, value);
221 switch (request) {
222 case DeviceRequest | USB_REQ_GET_STATUS:
223 data[0] = (0 << USB_DEVICE_SELF_POWERED) |
224 (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
225 data[1] = 0x00;
226 ret = 2;
227 break;
228 case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
229 if (value == USB_DEVICE_REMOTE_WAKEUP) {
230 dev->remote_wakeup = 0;
231 } else {
232 goto fail;
234 ret = 0;
235 break;
236 case DeviceOutRequest | USB_REQ_SET_FEATURE:
237 if (value == USB_DEVICE_REMOTE_WAKEUP) {
238 dev->remote_wakeup = 1;
239 } else {
240 goto fail;
242 ret = 0;
243 break;
244 case DeviceOutRequest | USB_REQ_SET_ADDRESS:
245 dev->addr = value;
246 ret = 0;
247 break;
248 case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
249 switch(value >> 8) {
250 case USB_DT_DEVICE:
251 memcpy(data, qemu_serial_dev_descriptor,
252 sizeof(qemu_serial_dev_descriptor));
253 data[8] = s->vendorid & 0xff;
254 data[9] = ((s->vendorid) >> 8) & 0xff;
255 data[10] = s->productid & 0xff;
256 data[11] = ((s->productid) >> 8) & 0xff;
257 ret = sizeof(qemu_serial_dev_descriptor);
258 break;
259 case USB_DT_CONFIG:
260 memcpy(data, qemu_serial_config_descriptor,
261 sizeof(qemu_serial_config_descriptor));
262 ret = sizeof(qemu_serial_config_descriptor);
263 break;
264 case USB_DT_STRING:
265 switch(value & 0xff) {
266 case 0:
267 /* language ids */
268 data[0] = 4;
269 data[1] = 3;
270 data[2] = 0x09;
271 data[3] = 0x04;
272 ret = 4;
273 break;
274 case 1:
275 /* vendor description */
276 ret = set_usb_string(data, "QEMU " QEMU_VERSION);
277 break;
278 case 2:
279 /* product description */
280 ret = set_usb_string(data, "QEMU USB SERIAL");
281 break;
282 case 3:
283 /* serial number */
284 ret = set_usb_string(data, "1");
285 break;
286 default:
287 goto fail;
289 break;
290 default:
291 goto fail;
293 break;
294 case DeviceRequest | USB_REQ_GET_CONFIGURATION:
295 data[0] = 1;
296 ret = 1;
297 break;
298 case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
299 ret = 0;
300 break;
301 case DeviceRequest | USB_REQ_GET_INTERFACE:
302 data[0] = 0;
303 ret = 1;
304 break;
305 case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
306 ret = 0;
307 break;
308 case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
309 ret = 0;
310 break;
312 /* Class specific requests. */
313 case DeviceOutVendor | FTDI_RESET:
314 switch (value) {
315 case FTDI_RESET_SIO:
316 usb_serial_reset(s);
317 break;
318 case FTDI_RESET_RX:
319 s->recv_ptr = 0;
320 s->recv_used = 0;
321 /* TODO: purge from char device */
322 break;
323 case FTDI_RESET_TX:
324 /* TODO: purge from char device */
325 break;
327 break;
328 case DeviceOutVendor | FTDI_SET_MDM_CTRL:
330 static int flags;
331 qemu_chr_ioctl(s->cs,CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
332 if (value & FTDI_SET_RTS) {
333 if (value & FTDI_RTS)
334 flags |= CHR_TIOCM_RTS;
335 else
336 flags &= ~CHR_TIOCM_RTS;
338 if (value & FTDI_SET_DTR) {
339 if (value & FTDI_DTR)
340 flags |= CHR_TIOCM_DTR;
341 else
342 flags &= ~CHR_TIOCM_DTR;
344 qemu_chr_ioctl(s->cs,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
345 break;
347 case DeviceOutVendor | FTDI_SET_FLOW_CTRL:
348 /* TODO: ioctl */
349 break;
350 case DeviceOutVendor | FTDI_SET_BAUD: {
351 static const int subdivisors8[8] = { 0, 4, 2, 1, 3, 5, 6, 7 };
352 int subdivisor8 = subdivisors8[((value & 0xc000) >> 14)
353 | ((index & 1) << 2)];
354 int divisor = value & 0x3fff;
356 /* chip special cases */
357 if (divisor == 1 && subdivisor8 == 0)
358 subdivisor8 = 4;
359 if (divisor == 0 && subdivisor8 == 0)
360 divisor = 1;
362 s->params.speed = (48000000 / 2) / (8 * divisor + subdivisor8);
363 qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
364 break;
366 case DeviceOutVendor | FTDI_SET_DATA:
367 switch (value & FTDI_PARITY) {
368 case 0:
369 s->params.parity = 'N';
370 break;
371 case FTDI_ODD:
372 s->params.parity = 'O';
373 break;
374 case FTDI_EVEN:
375 s->params.parity = 'E';
376 break;
377 default:
378 DPRINTF("unsupported parity %d\n", value & FTDI_PARITY);
379 goto fail;
381 switch (value & FTDI_STOP) {
382 case FTDI_STOP1:
383 s->params.stop_bits = 1;
384 break;
385 case FTDI_STOP2:
386 s->params.stop_bits = 2;
387 break;
388 default:
389 DPRINTF("unsupported stop bits %d\n", value & FTDI_STOP);
390 goto fail;
392 qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
393 /* TODO: TX ON/OFF */
394 break;
395 case DeviceInVendor | FTDI_GET_MDM_ST:
396 data[0] = usb_get_modem_lines(s) | 1;
397 data[1] = 0;
398 ret = 2;
399 break;
400 case DeviceOutVendor | FTDI_SET_EVENT_CHR:
401 /* TODO: handle it */
402 s->event_chr = value;
403 break;
404 case DeviceOutVendor | FTDI_SET_ERROR_CHR:
405 /* TODO: handle it */
406 s->error_chr = value;
407 break;
408 case DeviceOutVendor | FTDI_SET_LATENCY:
409 s->latency = value;
410 break;
411 case DeviceInVendor | FTDI_GET_LATENCY:
412 data[0] = s->latency;
413 ret = 1;
414 break;
415 default:
416 fail:
417 DPRINTF("got unsupported/bogus control %x, value %x\n", request, value);
418 ret = USB_RET_STALL;
419 break;
421 return ret;
424 static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
426 USBSerialState *s = (USBSerialState *)dev;
427 int ret = 0;
428 uint8_t devep = p->devep;
429 uint8_t *data = p->data;
430 int len = p->len;
431 int first_len;
433 switch (p->pid) {
434 case USB_TOKEN_OUT:
435 if (devep != 2)
436 goto fail;
437 qemu_chr_write(s->cs, data, len);
438 break;
440 case USB_TOKEN_IN:
441 if (devep != 1)
442 goto fail;
443 first_len = RECV_BUF - s->recv_ptr;
444 if (len <= 2) {
445 ret = USB_RET_NAK;
446 break;
448 *data++ = usb_get_modem_lines(s) | 1;
449 /* We do not have the uart details */
450 *data++ = 0;
451 len -= 2;
452 if (len > s->recv_used)
453 len = s->recv_used;
454 if (!len) {
455 ret = USB_RET_NAK;
456 break;
458 if (first_len > len)
459 first_len = len;
460 memcpy(data, s->recv_buf + s->recv_ptr, first_len);
461 if (len > first_len)
462 memcpy(data + first_len, s->recv_buf, len - first_len);
463 s->recv_used -= len;
464 s->recv_ptr = (s->recv_ptr + len) % RECV_BUF;
465 ret = len + 2;
466 break;
468 default:
469 DPRINTF("Bad token\n");
470 fail:
471 ret = USB_RET_STALL;
472 break;
475 return ret;
478 static void usb_serial_handle_destroy(USBDevice *dev)
480 USBSerialState *s = (USBSerialState *)dev;
482 qemu_chr_close(s->cs);
483 qemu_free(s);
486 static int usb_serial_can_read(void *opaque)
488 USBSerialState *s = opaque;
489 return RECV_BUF - s->recv_used;
492 static void usb_serial_read(void *opaque, const uint8_t *buf, int size)
494 USBSerialState *s = opaque;
495 int first_size = RECV_BUF - s->recv_ptr;
496 if (first_size > size)
497 first_size = size;
498 memcpy(s->recv_buf + s->recv_ptr + s->recv_used, buf, first_size);
499 if (size > first_size)
500 memcpy(s->recv_buf, buf + first_size, size - first_size);
501 s->recv_used += size;
504 static void usb_serial_event(void *opaque, int event)
506 USBSerialState *s = opaque;
508 switch (event) {
509 case CHR_EVENT_BREAK:
510 /* TODO: Send Break to USB */
511 break;
512 case CHR_EVENT_FOCUS:
513 break;
514 case CHR_EVENT_RESET:
515 usb_serial_reset(s);
516 /* TODO: Reset USB port */
517 break;
521 USBDevice *usb_serial_init(const char *filename)
523 USBSerialState *s;
524 CharDriverState *cdrv;
525 unsigned short vendorid = 0x0403, productid = 0x6001;
527 while (*filename && *filename != ':') {
528 const char *p;
529 char *e;
530 if (strstart(filename, "vendorid=", &p)) {
531 vendorid = strtol(p, &e, 16);
532 if (e == p || (*e && *e != ',' && *e != ':')) {
533 printf("bogus vendor ID %s\n", p);
534 return NULL;
536 filename = e;
537 } else if (strstart(filename, "productid=", &p)) {
538 productid = strtol(p, &e, 16);
539 if (e == p || (*e && *e != ',' && *e != ':')) {
540 printf("bogus product ID %s\n", p);
541 return NULL;
543 filename = e;
544 } else {
545 printf("unrecognized serial USB option %s\n", filename);
546 return NULL;
548 while(*filename == ',')
549 filename++;
551 if (!*filename) {
552 printf("character device specification needed\n");
553 return NULL;
555 filename++;
556 s = qemu_mallocz(sizeof(USBSerialState));
557 if (!s)
558 return NULL;
560 cdrv = qemu_chr_open(filename);
561 if (!cdrv)
562 goto fail;
563 s->cs = cdrv;
564 qemu_chr_add_handlers(cdrv, usb_serial_can_read, usb_serial_read, usb_serial_event, s);
566 s->dev.speed = USB_SPEED_FULL;
567 s->dev.handle_packet = usb_generic_handle_packet;
569 s->dev.handle_reset = usb_serial_handle_reset;
570 s->dev.handle_control = usb_serial_handle_control;
571 s->dev.handle_data = usb_serial_handle_data;
572 s->dev.handle_destroy = usb_serial_handle_destroy;
574 s->vendorid = vendorid;
575 s->productid = productid;
577 snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Serial(%.16s)",
578 filename);
580 usb_serial_handle_reset((USBDevice *)s);
581 return (USBDevice *)s;
582 fail:
583 qemu_free(s);
584 return NULL;