summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/device.c95
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
51enum mux_protocol { 51enum 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
76struct version_header 81struct 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
120static struct collection device_list; 128static 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
563static 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);