Commit abb8a13918ecc1e8160aa78582de9d5224ea70df
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("usb-serial: " fmt , ##args); } while (0) | @@ -47,9 +47,10 @@ do { printf("usb-serial: " fmt , ##args); } while (0) | ||
| 47 | 47 | ||
| 48 | /* SET_MDM_CTRL */ | 48 | /* SET_MDM_CTRL */ |
| 49 | 49 | ||
| 50 | -#define FTDI_MDM_CTRL 3 | ||
| 51 | #define FTDI_DTR 1 | 50 | #define FTDI_DTR 1 |
| 51 | +#define FTDI_SET_DTR (FTDI_DTR << 8) | ||
| 52 | #define FTDI_RTS 2 | 52 | #define FTDI_RTS 2 |
| 53 | +#define FTDI_SET_RTS (FTDI_RTS << 8) | ||
| 53 | 54 | ||
| 54 | /* SET_FLOW_CTRL */ | 55 | /* SET_FLOW_CTRL */ |
| 55 | 56 | ||
| @@ -99,7 +100,6 @@ typedef struct { | @@ -99,7 +100,6 @@ typedef struct { | ||
| 99 | uint8_t event_chr; | 100 | uint8_t event_chr; |
| 100 | uint8_t error_chr; | 101 | uint8_t error_chr; |
| 101 | uint8_t event_trigger; | 102 | uint8_t event_trigger; |
| 102 | - uint8_t lines; | ||
| 103 | QEMUSerialSetParams params; | 103 | QEMUSerialSetParams params; |
| 104 | int latency; /* ms */ | 104 | int latency; /* ms */ |
| 105 | CharDriverState *cs; | 105 | CharDriverState *cs; |
| @@ -178,7 +178,6 @@ static void usb_serial_reset(USBSerialState *s) | @@ -178,7 +178,6 @@ static void usb_serial_reset(USBSerialState *s) | ||
| 178 | s->recv_ptr = 0; | 178 | s->recv_ptr = 0; |
| 179 | s->recv_used = 0; | 179 | s->recv_used = 0; |
| 180 | /* TODO: purge in char driver */ | 180 | /* TODO: purge in char driver */ |
| 181 | - s->lines &= ~(FTDI_DTR|FTDI_RTS); | ||
| 182 | } | 181 | } |
| 183 | 182 | ||
| 184 | static void usb_serial_handle_reset(USBDevice *dev) | 183 | static void usb_serial_handle_reset(USBDevice *dev) |
| @@ -191,6 +190,27 @@ static void usb_serial_handle_reset(USBDevice *dev) | @@ -191,6 +190,27 @@ static void usb_serial_handle_reset(USBDevice *dev) | ||
| 191 | /* TODO: Reset char device, send BREAK? */ | 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 | static int usb_serial_handle_control(USBDevice *dev, int request, int value, | 214 | static int usb_serial_handle_control(USBDevice *dev, int request, int value, |
| 195 | int index, int length, uint8_t *data) | 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,8 +326,24 @@ static int usb_serial_handle_control(USBDevice *dev, int request, int value, | ||
| 306 | } | 326 | } |
| 307 | break; | 327 | break; |
| 308 | case DeviceOutVendor | FTDI_SET_MDM_CTRL: | 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 | break; | 345 | break; |
| 346 | + } | ||
| 311 | case DeviceOutVendor | FTDI_SET_FLOW_CTRL: | 347 | case DeviceOutVendor | FTDI_SET_FLOW_CTRL: |
| 312 | /* TODO: ioctl */ | 348 | /* TODO: ioctl */ |
| 313 | break; | 349 | break; |
| @@ -357,9 +393,9 @@ static int usb_serial_handle_control(USBDevice *dev, int request, int value, | @@ -357,9 +393,9 @@ static int usb_serial_handle_control(USBDevice *dev, int request, int value, | ||
| 357 | /* TODO: TX ON/OFF */ | 393 | /* TODO: TX ON/OFF */ |
| 358 | break; | 394 | break; |
| 359 | case DeviceInVendor | FTDI_GET_MDM_ST: | 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 | break; | 399 | break; |
| 364 | case DeviceOutVendor | FTDI_SET_EVENT_CHR: | 400 | case DeviceOutVendor | FTDI_SET_EVENT_CHR: |
| 365 | /* TODO: handle it */ | 401 | /* TODO: handle it */ |
| @@ -409,8 +445,8 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p) | @@ -409,8 +445,8 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p) | ||
| 409 | ret = USB_RET_NAK; | 445 | ret = USB_RET_NAK; |
| 410 | break; | 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 | *data++ = 0; | 450 | *data++ = 0; |
| 415 | len -= 2; | 451 | len -= 2; |
| 416 | if (len > s->recv_used) | 452 | if (len > s->recv_used) |