]> git.proxmox.com Git - qemu.git/blame - hw/usb-serial.c
Enable ld flag --warn-common
[qemu.git] / hw / usb-serial.c
CommitLineData
a7954218
AZ
1/*
2 * FTDI FT232BM Device emulation
3 *
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
7 *
8 * This code is licenced under the LGPL.
9 */
10
11#include "qemu-common.h"
12#include "usb.h"
13#include "qemu-char.h"
14
15//#define DEBUG_Serial
16
17#ifdef DEBUG_Serial
18#define DPRINTF(fmt, args...) \
19do { printf("usb-serial: " fmt , ##args); } while (0)
20#else
21#define DPRINTF(fmt, args...) do {} while(0)
22#endif
23
24#define RECV_BUF 384
25#define SEND_BUF 128 // Not used for now
26
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
38
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)
41
42/* RESET */
43
44#define FTDI_RESET_SIO 0
45#define FTDI_RESET_RX 1
46#define FTDI_RESET_TX 2
47
48/* SET_MDM_CTRL */
49
a7954218 50#define FTDI_DTR 1
abb8a139 51#define FTDI_SET_DTR (FTDI_DTR << 8)
a7954218 52#define FTDI_RTS 2
abb8a139 53#define FTDI_SET_RTS (FTDI_RTS << 8)
a7954218
AZ
54
55/* SET_FLOW_CTRL */
56
57#define FTDI_RTS_CTS_HS 1
58#define FTDI_DTR_DSR_HS 2
59#define FTDI_XON_XOFF_HS 4
60
61/* SET_DATA */
62
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)
68
69#define FTDI_STOP (0x3 << 11)
70#define FTDI_STOP1 (0x0 << 11)
71#define FTDI_STOP15 (0x1 << 11)
72#define FTDI_STOP2 (0x2 << 11)
73
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
80
81/* Status */
82
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
91
92typedef 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;
a7954218
AZ
103 QEMUSerialSetParams params;
104 int latency; /* ms */
105 CharDriverState *cs;
106} USBSerialState;
107
108static const uint8_t qemu_serial_dev_descriptor[] = {
109 0x12, /* u8 bLength; */
110 0x01, /* u8 bDescriptorType; Device */
111 0x00, 0x02, /* u16 bcdUSB; v2.0 */
112
113 0x00, /* u8 bDeviceClass; */
114 0x00, /* u8 bDeviceSubClass; */
115 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
116 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
117
118 /* Vendor and product id are arbitrary. */
119 0x03, 0x04, /* u16 idVendor; */
120 0x00, 0xFF, /* u16 idProduct; */
121 0x00, 0x04, /* u16 bcdDevice */
122
123 0x01, /* u8 iManufacturer; */
124 0x02, /* u8 iProduct; */
125 0x03, /* u8 iSerialNumber; */
126 0x01 /* u8 bNumConfigurations; */
127};
128
129static const uint8_t qemu_serial_config_descriptor[] = {
130
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; */
144
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; */
155
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; */
163
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; */
171};
172
173static void usb_serial_reset(USBSerialState *s)
174{
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 */
a7954218
AZ
181}
182
183static void usb_serial_handle_reset(USBDevice *dev)
184{
185 USBSerialState *s = (USBSerialState *)dev;
186
187 DPRINTF("Reset\n");
188
189 usb_serial_reset(s);
190 /* TODO: Reset char device, send BREAK? */
191}
192
abb8a139
AJ
193static uint8_t usb_get_modem_lines(USBSerialState *s)
194{
195 int flags;
196 uint8_t ret;
197
198 if (qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP)
199 return FTDI_CTS|FTDI_DSR|FTDI_RLSD;
200
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;
210
211 return ret;
212}
213
a7954218
AZ
214static int usb_serial_handle_control(USBDevice *dev, int request, int value,
215 int index, int length, uint8_t *data)
216{
217 USBSerialState *s = (USBSerialState *)dev;
218 int ret = 0;
219
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;
233 }
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;
241 }
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;
288 }
289 break;
290 default:
291 goto fail;
292 }
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;
311
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;
326 }
327 break;
328 case DeviceOutVendor | FTDI_SET_MDM_CTRL:
abb8a139
AJ
329 {
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;
337 }
338 if (value & FTDI_SET_DTR) {
339 if (value & FTDI_DTR)
340 flags |= CHR_TIOCM_DTR;
341 else
342 flags &= ~CHR_TIOCM_DTR;
343 }
344 qemu_chr_ioctl(s->cs,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
a7954218 345 break;
abb8a139 346 }
a7954218
AZ
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;
355
356 /* chip special cases */
357 if (divisor == 1 && subdivisor8 == 0)
358 subdivisor8 = 4;
359 if (divisor == 0 && subdivisor8 == 0)
360 divisor = 1;
361
362 s->params.speed = (48000000 / 2) / (8 * divisor + subdivisor8);
363 qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
364 break;
365 }
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;
380 }
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;
391 }
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:
abb8a139
AJ
396 data[0] = usb_get_modem_lines(s) | 1;
397 data[1] = 0;
398 ret = 2;
a7954218
AZ
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;
420 }
421 return ret;
422}
423
424static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
425{
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;
432
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;
439
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;
447 }
abb8a139
AJ
448 *data++ = usb_get_modem_lines(s) | 1;
449 /* We do not have the uart details */
a7954218
AZ
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;
457 }
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;
467
468 default:
469 DPRINTF("Bad token\n");
470 fail:
471 ret = USB_RET_STALL;
472 break;
473 }
474
475 return ret;
476}
477
478static void usb_serial_handle_destroy(USBDevice *dev)
479{
480 USBSerialState *s = (USBSerialState *)dev;
481
482 qemu_chr_close(s->cs);
483 qemu_free(s);
484}
485
8fcd3692 486static int usb_serial_can_read(void *opaque)
a7954218
AZ
487{
488 USBSerialState *s = opaque;
489 return RECV_BUF - s->recv_used;
490}
491
8fcd3692 492static void usb_serial_read(void *opaque, const uint8_t *buf, int size)
a7954218
AZ
493{
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;
502}
503
8fcd3692 504static void usb_serial_event(void *opaque, int event)
a7954218
AZ
505{
506 USBSerialState *s = opaque;
507
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;
518 }
519}
520
521USBDevice *usb_serial_init(const char *filename)
522{
523 USBSerialState *s;
524 CharDriverState *cdrv;
a11d070e 525 unsigned short vendorid = 0x0403, productid = 0x6001;
a7954218
AZ
526
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;
535 }
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;
542 }
543 filename = e;
544 } else {
545 printf("unrecognized serial USB option %s\n", filename);
546 return NULL;
547 }
548 while(*filename == ',')
549 filename++;
550 }
551 if (!*filename) {
552 printf("character device specification needed\n");
553 return NULL;
554 }
555 filename++;
556 s = qemu_mallocz(sizeof(USBSerialState));
557 if (!s)
558 return NULL;
559
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);
565
566 s->dev.speed = USB_SPEED_FULL;
567 s->dev.handle_packet = usb_generic_handle_packet;
568
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;
573
574 s->vendorid = vendorid;
575 s->productid = productid;
576
577 snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Serial(%.16s)",
578 filename);
579
580 usb_serial_handle_reset((USBDevice *)s);
581 return (USBDevice *)s;
582 fail:
583 qemu_free(s);
584 return NULL;
585}