Commit abb8a13918ecc1e8160aa78582de9d5224ea70df

Authored by aurel32
1 parent f88e4b91

usb-serial: add support for modem lines

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4998 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 45 additions and 9 deletions
hw/usb-serial.c
... ... @@ -47,9 +47,10 @@ do { printf(&quot;usb-serial: &quot; fmt , ##args); } while (0)
47 47  
48 48 /* SET_MDM_CTRL */
49 49  
50   -#define FTDI_MDM_CTRL 3
51 50 #define FTDI_DTR 1
  51 +#define FTDI_SET_DTR (FTDI_DTR << 8)
52 52 #define FTDI_RTS 2
  53 +#define FTDI_SET_RTS (FTDI_RTS << 8)
53 54  
54 55 /* SET_FLOW_CTRL */
55 56  
... ... @@ -99,7 +100,6 @@ typedef struct {
99 100 uint8_t event_chr;
100 101 uint8_t error_chr;
101 102 uint8_t event_trigger;
102   - uint8_t lines;
103 103 QEMUSerialSetParams params;
104 104 int latency; /* ms */
105 105 CharDriverState *cs;
... ... @@ -178,7 +178,6 @@ static void usb_serial_reset(USBSerialState *s)
178 178 s->recv_ptr = 0;
179 179 s->recv_used = 0;
180 180 /* TODO: purge in char driver */
181   - s->lines &= ~(FTDI_DTR|FTDI_RTS);
182 181 }
183 182  
184 183 static void usb_serial_handle_reset(USBDevice *dev)
... ... @@ -191,6 +190,27 @@ static void usb_serial_handle_reset(USBDevice *dev)
191 190 /* TODO: Reset char device, send BREAK? */
192 191 }
193 192  
  193 +static 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 +
194 214 static int usb_serial_handle_control(USBDevice *dev, int request, int value,
195 215 int index, int length, uint8_t *data)
196 216 {
... ... @@ -306,8 +326,24 @@ static int usb_serial_handle_control(USBDevice *dev, int request, int value,
306 326 }
307 327 break;
308 328 case DeviceOutVendor | FTDI_SET_MDM_CTRL:
309   - s->lines = value & FTDI_MDM_CTRL;
  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);
310 345 break;
  346 + }
311 347 case DeviceOutVendor | FTDI_SET_FLOW_CTRL:
312 348 /* TODO: ioctl */
313 349 break;
... ... @@ -357,9 +393,9 @@ static int usb_serial_handle_control(USBDevice *dev, int request, int value,
357 393 /* TODO: TX ON/OFF */
358 394 break;
359 395 case DeviceInVendor | FTDI_GET_MDM_ST:
360   - /* TODO: return modem status */
361   - data[0] = 0;
362   - ret = 1;
  396 + data[0] = usb_get_modem_lines(s) | 1;
  397 + data[1] = 0;
  398 + ret = 2;
363 399 break;
364 400 case DeviceOutVendor | FTDI_SET_EVENT_CHR:
365 401 /* TODO: handle it */
... ... @@ -409,8 +445,8 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
409 445 ret = USB_RET_NAK;
410 446 break;
411 447 }
412   - /* TODO: Report serial line status */
413   - *data++ = 0;
  448 + *data++ = usb_get_modem_lines(s) | 1;
  449 + /* We do not have the uart details */
414 450 *data++ = 0;
415 451 len -= 2;
416 452 if (len > s->recv_used)
... ...