diff options
| author | 2014-05-22 18:25:06 +0200 | |
|---|---|---|
| committer | 2014-05-27 12:57:06 +0200 | |
| commit | 2bd4d61655c2c219627c2e75475e12705453d0f6 (patch) | |
| tree | 699e4e6df7ebf27d79fab1daf78339461a99c707 /src | |
| parent | aede4d06c49a8446e8011ab569c765a4f4ba32e7 (diff) | |
| download | usbmuxd-2bd4d61655c2c219627c2e75475e12705453d0f6.tar.gz usbmuxd-2bd4d61655c2c219627c2e75475e12705453d0f6.tar.bz2 | |
device: Add protocol version 2 support
Diffstat (limited to 'src')
| -rw-r--r-- | src/device.c | 95 |
1 files changed, 83 insertions, 12 deletions
diff --git a/src/device.c b/src/device.c index 1c8ec8c..bb12310 100644 --- a/src/device.c +++ b/src/device.c | |||
| @@ -50,6 +50,8 @@ int next_device_id; | |||
| 50 | 50 | ||
| 51 | enum mux_protocol { | 51 | enum mux_protocol { |
| 52 | MUX_PROTO_VERSION = 0, | 52 | MUX_PROTO_VERSION = 0, |
| 53 | MUX_PROTO_CONTROL = 1, | ||
| 54 | MUX_PROTO_SETUP = 2, | ||
| 53 | MUX_PROTO_TCP = IPPROTO_TCP, | 55 | MUX_PROTO_TCP = IPPROTO_TCP, |
| 54 | }; | 56 | }; |
| 55 | 57 | ||
| @@ -71,6 +73,9 @@ struct mux_header | |||
| 71 | { | 73 | { |
| 72 | uint32_t protocol; | 74 | uint32_t protocol; |
| 73 | uint32_t length; | 75 | uint32_t length; |
| 76 | uint32_t magic; | ||
| 77 | uint16_t tx_seq; | ||
| 78 | uint16_t rx_seq; | ||
| 74 | }; | 79 | }; |
| 75 | 80 | ||
| 76 | struct version_header | 81 | struct version_header |
| @@ -115,6 +120,9 @@ struct mux_device | |||
| 115 | unsigned char *pktbuf; | 120 | unsigned char *pktbuf; |
| 116 | uint32_t pktlen; | 121 | uint32_t pktlen; |
| 117 | void *preflight_cb_data; | 122 | void *preflight_cb_data; |
| 123 | int version; | ||
| 124 | uint16_t rx_seq; | ||
| 125 | uint16_t tx_seq; | ||
| 118 | }; | 126 | }; |
| 119 | 127 | ||
| 120 | static struct collection device_list; | 128 | static struct collection device_list; |
| @@ -183,6 +191,9 @@ static int send_packet(struct mux_device *dev, enum mux_protocol proto, void *he | |||
| 183 | case MUX_PROTO_VERSION: | 191 | case MUX_PROTO_VERSION: |
| 184 | hdrlen = sizeof(struct version_header); | 192 | hdrlen = sizeof(struct version_header); |
| 185 | break; | 193 | break; |
| 194 | case MUX_PROTO_SETUP: | ||
| 195 | hdrlen = 0; | ||
| 196 | break; | ||
| 186 | case MUX_PROTO_TCP: | 197 | case MUX_PROTO_TCP: |
| 187 | hdrlen = sizeof(struct tcphdr); | 198 | hdrlen = sizeof(struct tcphdr); |
| 188 | break; | 199 | break; |
| @@ -192,7 +203,9 @@ static int send_packet(struct mux_device *dev, enum mux_protocol proto, void *he | |||
| 192 | } | 203 | } |
| 193 | usbmuxd_log(LL_SPEW, "send_packet(%d, 0x%x, %p, %p, %d)", dev->id, proto, header, data, length); | 204 | usbmuxd_log(LL_SPEW, "send_packet(%d, 0x%x, %p, %p, %d)", dev->id, proto, header, data, length); |
| 194 | 205 | ||
| 195 | int total = sizeof(struct mux_header) + hdrlen + length; | 206 | int mux_header_size = ((dev->version < 2) ? 8 : sizeof(struct mux_header)); |
| 207 | |||
| 208 | int total = mux_header_size + hdrlen + length; | ||
| 196 | 209 | ||
| 197 | if(total > USB_MTU) { | 210 | if(total > USB_MTU) { |
| 198 | usbmuxd_log(LL_ERROR, "Tried to send packet larger than USB MTU (hdr %d data %d total %d) to device %d", hdrlen, length, total, dev->id); | 211 | usbmuxd_log(LL_ERROR, "Tried to send packet larger than USB MTU (hdr %d data %d total %d) to device %d", hdrlen, length, total, dev->id); |
| @@ -203,9 +216,19 @@ static int send_packet(struct mux_device *dev, enum mux_protocol proto, void *he | |||
| 203 | struct mux_header *mhdr = (struct mux_header *)buffer; | 216 | struct mux_header *mhdr = (struct mux_header *)buffer; |
| 204 | mhdr->protocol = htonl(proto); | 217 | mhdr->protocol = htonl(proto); |
| 205 | mhdr->length = htonl(total); | 218 | mhdr->length = htonl(total); |
| 206 | memcpy(buffer + sizeof(struct mux_header), header, hdrlen); | 219 | if (dev->version >= 2) { |
| 220 | mhdr->magic = htonl(0xfeedface); | ||
| 221 | if (proto == MUX_PROTO_SETUP) { | ||
| 222 | dev->tx_seq = 0; | ||
| 223 | dev->rx_seq = 0xFFFF; | ||
| 224 | } | ||
| 225 | mhdr->tx_seq = htons(dev->tx_seq); | ||
| 226 | mhdr->rx_seq = htons(dev->rx_seq); | ||
| 227 | dev->tx_seq++; | ||
| 228 | } | ||
| 229 | memcpy(buffer + mux_header_size, header, hdrlen); | ||
| 207 | if(data && length) | 230 | if(data && length) |
| 208 | memcpy(buffer + sizeof(struct mux_header) + hdrlen, data, length); | 231 | memcpy(buffer + mux_header_size + hdrlen, data, length); |
| 209 | 232 | ||
| 210 | if((res = usb_send(dev->usbdev, buffer, total)) < 0) { | 233 | if((res = usb_send(dev->usbdev, buffer, total)) < 0) { |
| 211 | usbmuxd_log(LL_ERROR, "usb_send failed while sending packet (len %d) to device %d: %d", total, dev->id, res); | 234 | usbmuxd_log(LL_ERROR, "usb_send failed while sending packet (len %d) to device %d: %d", total, dev->id, res); |
| @@ -512,7 +535,7 @@ static void device_version_input(struct mux_device *dev, struct version_header * | |||
| 512 | } | 535 | } |
| 513 | vh->major = ntohl(vh->major); | 536 | vh->major = ntohl(vh->major); |
| 514 | vh->minor = ntohl(vh->minor); | 537 | vh->minor = ntohl(vh->minor); |
| 515 | if(vh->major != 1 || vh->minor != 0) { | 538 | if(vh->major != 2 && vh->major != 1) { |
| 516 | usbmuxd_log(LL_ERROR, "Device %d has unknown version %d.%d", dev->id, vh->major, vh->minor); | 539 | usbmuxd_log(LL_ERROR, "Device %d has unknown version %d.%d", dev->id, vh->major, vh->minor); |
| 517 | pthread_mutex_lock(&device_list_mutex); | 540 | pthread_mutex_lock(&device_list_mutex); |
| 518 | collection_remove(&device_list, dev); | 541 | collection_remove(&device_list, dev); |
| @@ -520,7 +543,13 @@ static void device_version_input(struct mux_device *dev, struct version_header * | |||
| 520 | free(dev); | 543 | free(dev); |
| 521 | return; | 544 | return; |
| 522 | } | 545 | } |
| 523 | usbmuxd_log(LL_NOTICE, "Connected to v%d.%d device %d on location 0x%x with serial number %s", vh->major, vh->minor, dev->id, usb_get_location(dev->usbdev), usb_get_serial(dev->usbdev)); | 546 | dev->version = vh->major; |
| 547 | |||
| 548 | if (dev->version >= 2) { | ||
| 549 | send_packet(dev, MUX_PROTO_SETUP, NULL, "\x07", 1); | ||
| 550 | } | ||
| 551 | |||
| 552 | usbmuxd_log(LL_NOTICE, "Connected to v%d.%d device %d on location 0x%x with serial number %s", dev->version, vh->minor, dev->id, usb_get_location(dev->usbdev), usb_get_serial(dev->usbdev)); | ||
| 524 | dev->state = MUXDEV_ACTIVE; | 553 | dev->state = MUXDEV_ACTIVE; |
| 525 | collection_init(&dev->connections); | 554 | collection_init(&dev->connections); |
| 526 | struct device_info info; | 555 | struct device_info info; |
| @@ -531,6 +560,38 @@ static void device_version_input(struct mux_device *dev, struct version_header * | |||
| 531 | preflight_worker_device_add(&info); | 560 | preflight_worker_device_add(&info); |
| 532 | } | 561 | } |
| 533 | 562 | ||
| 563 | static void device_control_input(struct mux_device *dev, unsigned char *payload, uint32_t payload_length) | ||
| 564 | { | ||
| 565 | if (payload_length > 0) { | ||
| 566 | switch (payload[0]) { | ||
| 567 | case 3: | ||
| 568 | if (payload_length > 1) { | ||
| 569 | char* buf = malloc(payload_length); | ||
| 570 | strncpy(buf, (char*)payload+1, payload_length-1); | ||
| 571 | buf[payload_length-1] = '\0'; | ||
| 572 | usbmuxd_log(LL_ERROR, "%s: ERROR: %s", __func__, buf); | ||
| 573 | free(buf); | ||
| 574 | } else { | ||
| 575 | usbmuxd_log(LL_ERROR, "%s: Error occured, but empty error message", __func__); | ||
| 576 | } | ||
| 577 | break; | ||
| 578 | case 7: | ||
| 579 | if (payload_length > 1) { | ||
| 580 | char* buf = malloc(payload_length); | ||
| 581 | strncpy(buf, (char*)payload+1, payload_length-1); | ||
| 582 | buf[payload_length-1] = '\0'; | ||
| 583 | usbmuxd_log(LL_INFO, "%s: %s", __func__, buf); | ||
| 584 | free(buf); | ||
| 585 | } | ||
| 586 | break; | ||
| 587 | default: | ||
| 588 | break; | ||
| 589 | } | ||
| 590 | } else { | ||
| 591 | usbmuxd_log(LL_WARNING, "%s: got a type 1 packet without payload", __func__); | ||
| 592 | } | ||
| 593 | } | ||
| 594 | |||
| 534 | /** | 595 | /** |
| 535 | * Handle an incoming TCP packet from the device. | 596 | * Handle an incoming TCP packet from the device. |
| 536 | * | 597 | * |
| @@ -686,7 +747,7 @@ void device_data_input(struct usb_device *usbdev, unsigned char *buffer, uint32_ | |||
| 686 | } | 747 | } |
| 687 | 748 | ||
| 688 | struct mux_header *mhdr = (struct mux_header *)buffer; | 749 | struct mux_header *mhdr = (struct mux_header *)buffer; |
| 689 | 750 | int mux_header_size = ((dev->version < 2) ? 8 : sizeof(struct mux_header)); | |
| 690 | if(ntohl(mhdr->length) != length) { | 751 | if(ntohl(mhdr->length) != length) { |
| 691 | usbmuxd_log(LL_ERROR, "Incoming packet size mismatch (dev %d, expected %d, got %d)", dev->id, ntohl(mhdr->length), length); | 752 | usbmuxd_log(LL_ERROR, "Incoming packet size mismatch (dev %d, expected %d, got %d)", dev->id, ntohl(mhdr->length), length); |
| 692 | return; | 753 | return; |
| @@ -696,23 +757,32 @@ void device_data_input(struct usb_device *usbdev, unsigned char *buffer, uint32_ | |||
| 696 | unsigned char *payload; | 757 | unsigned char *payload; |
| 697 | uint32_t payload_length; | 758 | uint32_t payload_length; |
| 698 | 759 | ||
| 760 | if (dev->version >= 2) { | ||
| 761 | dev->rx_seq = ntohs(mhdr->rx_seq); | ||
| 762 | } | ||
| 763 | |||
| 699 | switch(ntohl(mhdr->protocol)) { | 764 | switch(ntohl(mhdr->protocol)) { |
| 700 | case MUX_PROTO_VERSION: | 765 | case MUX_PROTO_VERSION: |
| 701 | if(length < (sizeof(struct mux_header) + sizeof(struct version_header))) { | 766 | if(length < (mux_header_size + sizeof(struct version_header))) { |
| 702 | usbmuxd_log(LL_ERROR, "Incoming version packet is too small (%d)", length); | 767 | usbmuxd_log(LL_ERROR, "Incoming version packet is too small (%d)", length); |
| 703 | return; | 768 | return; |
| 704 | } | 769 | } |
| 705 | device_version_input(dev, (struct version_header *)(mhdr+1)); | 770 | device_version_input(dev, (struct version_header *)((char*)mhdr+mux_header_size)); |
| 771 | break; | ||
| 772 | case MUX_PROTO_CONTROL: | ||
| 773 | payload = (unsigned char *)(mhdr+1); | ||
| 774 | payload_length = length - mux_header_size; | ||
| 775 | device_control_input(dev, payload, payload_length); | ||
| 706 | break; | 776 | break; |
| 707 | case MUX_PROTO_TCP: | 777 | case MUX_PROTO_TCP: |
| 708 | if(length < (sizeof(struct mux_header) + sizeof(struct tcphdr))) { | 778 | if(length < (mux_header_size + sizeof(struct tcphdr))) { |
| 709 | usbmuxd_log(LL_ERROR, "Incoming TCP packet is too small (%d)", length); | 779 | usbmuxd_log(LL_ERROR, "Incoming TCP packet is too small (%d)", length); |
| 710 | return; | 780 | return; |
| 711 | } | 781 | } |
| 712 | th = (struct tcphdr *)(mhdr+1); | 782 | th = (struct tcphdr *)((char*)mhdr+mux_header_size); |
| 713 | payload = (unsigned char *)(th+1); | 783 | payload = (unsigned char *)(th+1); |
| 714 | payload_length = length - sizeof(struct tcphdr) - sizeof(struct mux_header); | 784 | payload_length = length - sizeof(struct tcphdr) - mux_header_size; |
| 715 | device_tcp_input(dev, (struct tcphdr *)(mhdr+1), payload, payload_length); | 785 | device_tcp_input(dev, th, payload, payload_length); |
| 716 | break; | 786 | break; |
| 717 | default: | 787 | default: |
| 718 | usbmuxd_log(LL_ERROR, "Incoming packet for device %d has unknown protocol 0x%x)", dev->id, ntohl(mhdr->protocol)); | 788 | usbmuxd_log(LL_ERROR, "Incoming packet for device %d has unknown protocol 0x%x)", dev->id, ntohl(mhdr->protocol)); |
| @@ -736,6 +806,7 @@ int device_add(struct usb_device *usbdev) | |||
| 736 | dev->pktbuf = malloc(DEV_MRU); | 806 | dev->pktbuf = malloc(DEV_MRU); |
| 737 | dev->pktlen = 0; | 807 | dev->pktlen = 0; |
| 738 | dev->preflight_cb_data = NULL; | 808 | dev->preflight_cb_data = NULL; |
| 809 | dev->version = 0; | ||
| 739 | struct version_header vh; | 810 | struct version_header vh; |
| 740 | vh.major = htonl(1); | 811 | vh.major = htonl(1); |
| 741 | vh.minor = htonl(0); | 812 | vh.minor = htonl(0); |
