Revision c0e5750b

b/usb-linux.c
125 125
    uint32_t  iso_urb_count;
126 126
    Notifier  exit;
127 127

  
128
    struct endp_data endp_table[MAX_ENDPOINTS];
128
    struct endp_data ep_in[MAX_ENDPOINTS];
129
    struct endp_data ep_out[MAX_ENDPOINTS];
129 130
    QLIST_HEAD(, AsyncURB) aurbs;
130 131

  
131 132
    /* Host side address */
......
147 148
                            const char *device_file, const char *device_name);
148 149
static int usb_linux_update_endp_table(USBHostDevice *s);
149 150

  
150
static struct endp_data *get_endp(USBHostDevice *s, int ep)
151
static struct endp_data *get_endp(USBHostDevice *s, int pid, int ep)
151 152
{
152
    return s->endp_table + ep - 1;
153
    struct endp_data *eps = pid == USB_TOKEN_IN ? s->ep_in : s->ep_out;
154
    assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT);
155
    assert(ep > 0 && ep <= MAX_ENDPOINTS);
156
    return eps + ep - 1;
153 157
}
154 158

  
155
static int is_isoc(USBHostDevice *s, int ep)
159
static int is_isoc(USBHostDevice *s, int pid, int ep)
156 160
{
157
    return get_endp(s, ep)->type == USBDEVFS_URB_TYPE_ISO;
161
    return get_endp(s, pid, ep)->type == USBDEVFS_URB_TYPE_ISO;
158 162
}
159 163

  
160
static int is_valid(USBHostDevice *s, int ep)
164
static int is_valid(USBHostDevice *s, int pid, int ep)
161 165
{
162
    return get_endp(s, ep)->type != INVALID_EP_TYPE;
166
    return get_endp(s, pid, ep)->type != INVALID_EP_TYPE;
163 167
}
164 168

  
165
static int is_halted(USBHostDevice *s, int ep)
169
static int is_halted(USBHostDevice *s, int pid, int ep)
166 170
{
167
    return get_endp(s, ep)->halted;
171
    return get_endp(s, pid, ep)->halted;
168 172
}
169 173

  
170
static void clear_halt(USBHostDevice *s, int ep)
174
static void clear_halt(USBHostDevice *s, int pid, int ep)
171 175
{
172 176
    trace_usb_host_ep_clear_halt(s->bus_num, s->addr, ep);
173
    get_endp(s, ep)->halted = 0;
177
    get_endp(s, pid, ep)->halted = 0;
174 178
}
175 179

  
176
static void set_halt(USBHostDevice *s, int ep)
180
static void set_halt(USBHostDevice *s, int pid, int ep)
177 181
{
178
    trace_usb_host_ep_set_halt(s->bus_num, s->addr, ep);
179
    get_endp(s, ep)->halted = 1;
182
    if (ep != 0) {
183
        trace_usb_host_ep_set_halt(s->bus_num, s->addr, ep);
184
        get_endp(s, pid, ep)->halted = 1;
185
    }
180 186
}
181 187

  
182
static int is_iso_started(USBHostDevice *s, int ep)
188
static int is_iso_started(USBHostDevice *s, int pid, int ep)
183 189
{
184
    return get_endp(s, ep)->iso_started;
190
    return get_endp(s, pid, ep)->iso_started;
185 191
}
186 192

  
187
static void clear_iso_started(USBHostDevice *s, int ep)
193
static void clear_iso_started(USBHostDevice *s, int pid, int ep)
188 194
{
189 195
    trace_usb_host_ep_stop_iso(s->bus_num, s->addr, ep);
190
    get_endp(s, ep)->iso_started = 0;
196
    get_endp(s, pid, ep)->iso_started = 0;
191 197
}
192 198

  
193
static void set_iso_started(USBHostDevice *s, int ep)
199
static void set_iso_started(USBHostDevice *s, int pid, int ep)
194 200
{
195
    struct endp_data *e = get_endp(s, ep);
201
    struct endp_data *e = get_endp(s, pid, ep);
196 202

  
197 203
    trace_usb_host_ep_start_iso(s->bus_num, s->addr, ep);
198 204
    if (!e->iso_started) {
......
201 207
    }
202 208
}
203 209

  
204
static int change_iso_inflight(USBHostDevice *s, int ep, int value)
210
static int change_iso_inflight(USBHostDevice *s, int pid, int ep, int value)
205 211
{
206
    struct endp_data *e = get_endp(s, ep);
212
    struct endp_data *e = get_endp(s, pid, ep);
207 213

  
208 214
    e->inflight += value;
209 215
    return e->inflight;
210 216
}
211 217

  
212
static void set_iso_urb(USBHostDevice *s, int ep, AsyncURB *iso_urb)
218
static void set_iso_urb(USBHostDevice *s, int pid, int ep, AsyncURB *iso_urb)
213 219
{
214
    get_endp(s, ep)->iso_urb = iso_urb;
220
    get_endp(s, pid, ep)->iso_urb = iso_urb;
215 221
}
216 222

  
217
static AsyncURB *get_iso_urb(USBHostDevice *s, int ep)
223
static AsyncURB *get_iso_urb(USBHostDevice *s, int pid, int ep)
218 224
{
219
    return get_endp(s, ep)->iso_urb;
225
    return get_endp(s, pid, ep)->iso_urb;
220 226
}
221 227

  
222
static void set_iso_urb_idx(USBHostDevice *s, int ep, int i)
228
static void set_iso_urb_idx(USBHostDevice *s, int pid, int ep, int i)
223 229
{
224
    get_endp(s, ep)->iso_urb_idx = i;
230
    get_endp(s, pid, ep)->iso_urb_idx = i;
225 231
}
226 232

  
227
static int get_iso_urb_idx(USBHostDevice *s, int ep)
233
static int get_iso_urb_idx(USBHostDevice *s, int pid, int ep)
228 234
{
229
    return get_endp(s, ep)->iso_urb_idx;
235
    return get_endp(s, pid, ep)->iso_urb_idx;
230 236
}
231 237

  
232
static void set_iso_buffer_used(USBHostDevice *s, int ep, int i)
238
static void set_iso_buffer_used(USBHostDevice *s, int pid, int ep, int i)
233 239
{
234
    get_endp(s, ep)->iso_buffer_used = i;
240
    get_endp(s, pid, ep)->iso_buffer_used = i;
235 241
}
236 242

  
237
static int get_iso_buffer_used(USBHostDevice *s, int ep)
243
static int get_iso_buffer_used(USBHostDevice *s, int pid, int ep)
238 244
{
239
    return get_endp(s, ep)->iso_buffer_used;
245
    return get_endp(s, pid, ep)->iso_buffer_used;
240 246
}
241 247

  
242
static void set_max_packet_size(USBHostDevice *s, int ep, uint8_t *descriptor)
248
static void set_max_packet_size(USBHostDevice *s, int pid, int ep,
249
                                uint8_t *descriptor)
243 250
{
244 251
    int raw = descriptor[4] + (descriptor[5] << 8);
245 252
    int size, microframes;
......
250 257
    case 2:  microframes = 3; break;
251 258
    default: microframes = 1; break;
252 259
    }
253
    get_endp(s, ep)->max_packet_size = size * microframes;
260
    get_endp(s, pid, ep)->max_packet_size = size * microframes;
254 261
}
255 262

  
256
static int get_max_packet_size(USBHostDevice *s, int ep)
263
static int get_max_packet_size(USBHostDevice *s, int pid, int ep)
257 264
{
258
    return get_endp(s, ep)->max_packet_size;
265
    return get_endp(s, pid, ep)->max_packet_size;
259 266
}
260 267

  
261 268
/*
......
334 341
           anything else (it is handled further in usb_host_handle_iso_data) */
335 342
        if (aurb->iso_frame_idx == -1) {
336 343
            int inflight;
344
            int pid = (aurb->urb.endpoint & USB_DIR_IN) ?
345
                USB_TOKEN_IN : USB_TOKEN_OUT;
346
            int ep = aurb->urb.endpoint & 0xf;
337 347
            if (aurb->urb.status == -EPIPE) {
338
                set_halt(s, aurb->urb.endpoint & 0xf);
348
                set_halt(s, pid, ep);
339 349
            }
340 350
            aurb->iso_frame_idx = 0;
341 351
            urbs++;
342
            inflight = change_iso_inflight(s, aurb->urb.endpoint & 0xf, -1);
343
            if (inflight == 0 && is_iso_started(s, aurb->urb.endpoint & 0xf)) {
352
            inflight = change_iso_inflight(s, pid, ep, -1);
353
            if (inflight == 0 && is_iso_started(s, pid, ep)) {
344 354
                fprintf(stderr, "husb: out of buffers for iso stream\n");
345 355
            }
346 356
            continue;
......
357 367
                break;
358 368

  
359 369
            case -EPIPE:
360
                set_halt(s, p->devep);
370
                set_halt(s, p->pid, p->devep);
361 371
                p->result = USB_RET_STALL;
362 372
                break;
363 373

  
......
536 546
/* iso data is special, we need to keep enough urbs in flight to make sure
537 547
   that the controller never runs out of them, otherwise the device will
538 548
   likely suffer a buffer underrun / overrun. */
539
static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, uint8_t ep, int in)
549
static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, int pid, uint8_t ep)
540 550
{
541 551
    AsyncURB *aurb;
542
    int i, j, len = get_max_packet_size(s, ep);
552
    int i, j, len = get_max_packet_size(s, pid, ep);
543 553

  
544 554
    aurb = g_malloc0(s->iso_urb_count * sizeof(*aurb));
545 555
    for (i = 0; i < s->iso_urb_count; i++) {
......
551 561
        aurb[i].urb.number_of_packets = ISO_FRAME_DESC_PER_URB;
552 562
        for (j = 0 ; j < ISO_FRAME_DESC_PER_URB; j++)
553 563
            aurb[i].urb.iso_frame_desc[j].length = len;
554
        if (in) {
564
        if (pid == USB_TOKEN_IN) {
555 565
            aurb[i].urb.endpoint |= 0x80;
556 566
            /* Mark as fully consumed (idle) */
557 567
            aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB;
558 568
        }
559 569
    }
560
    set_iso_urb(s, ep, aurb);
570
    set_iso_urb(s, pid, ep, aurb);
561 571

  
562 572
    return aurb;
563 573
}
564 574

  
565
static void usb_host_stop_n_free_iso(USBHostDevice *s, uint8_t ep)
575
static void usb_host_stop_n_free_iso(USBHostDevice *s, int pid, uint8_t ep)
566 576
{
567 577
    AsyncURB *aurb;
568 578
    int i, ret, killed = 0, free = 1;
569 579

  
570
    aurb = get_iso_urb(s, ep);
580
    aurb = get_iso_urb(s, pid, ep);
571 581
    if (!aurb) {
572 582
        return;
573 583
    }
......
598 608
        g_free(aurb);
599 609
    else
600 610
        printf("husb: leaking iso urbs because of discard failure\n");
601
    set_iso_urb(s, ep, NULL);
602
    set_iso_urb_idx(s, ep, 0);
603
    clear_iso_started(s, ep);
611
    set_iso_urb(s, pid, ep, NULL);
612
    set_iso_urb_idx(s, pid, ep, 0);
613
    clear_iso_started(s, pid, ep);
604 614
}
605 615

  
606 616
static int urb_status_to_usb_ret(int status)
......
619 629
    int i, j, ret, max_packet_size, offset, len = 0;
620 630
    uint8_t *buf;
621 631

  
622
    max_packet_size = get_max_packet_size(s, p->devep);
632
    max_packet_size = get_max_packet_size(s, p->pid, p->devep);
623 633
    if (max_packet_size == 0)
624 634
        return USB_RET_NAK;
625 635

  
626
    aurb = get_iso_urb(s, p->devep);
636
    aurb = get_iso_urb(s, p->pid, p->devep);
627 637
    if (!aurb) {
628
        aurb = usb_host_alloc_iso(s, p->devep, in);
638
        aurb = usb_host_alloc_iso(s, p->pid, p->devep);
629 639
    }
630 640

  
631
    i = get_iso_urb_idx(s, p->devep);
641
    i = get_iso_urb_idx(s, p->pid, p->devep);
632 642
    j = aurb[i].iso_frame_idx;
633 643
    if (j >= 0 && j < ISO_FRAME_DESC_PER_URB) {
634 644
        if (in) {
......
655 665
            }
656 666
        } else {
657 667
            len = p->iov.size;
658
            offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->devep);
668
            offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->pid, p->devep);
659 669

  
660 670
            /* Check the frame fits */
661 671
            if (len > max_packet_size) {
......
667 677
            usb_packet_copy(p, aurb[i].urb.buffer + offset, len);
668 678
            aurb[i].urb.iso_frame_desc[j].length = len;
669 679
            offset += len;
670
            set_iso_buffer_used(s, p->devep, offset);
680
            set_iso_buffer_used(s, p->pid, p->devep, offset);
671 681

  
672 682
            /* Start the stream once we have buffered enough data */
673
            if (!is_iso_started(s, p->devep) && i == 1 && j == 8) {
674
                set_iso_started(s, p->devep);
683
            if (!is_iso_started(s, p->pid, p->devep) && i == 1 && j == 8) {
684
                set_iso_started(s, p->pid, p->devep);
675 685
            }
676 686
        }
677 687
        aurb[i].iso_frame_idx++;
678 688
        if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
679 689
            i = (i + 1) % s->iso_urb_count;
680
            set_iso_urb_idx(s, p->devep, i);
690
            set_iso_urb_idx(s, p->pid, p->devep, i);
681 691
        }
682 692
    } else {
683 693
        if (in) {
684
            set_iso_started(s, p->devep);
694
            set_iso_started(s, p->pid, p->devep);
685 695
        } else {
686 696
            DPRINTF("hubs: iso out error no free buffer, dropping packet\n");
687 697
        }
688 698
    }
689 699

  
690
    if (is_iso_started(s, p->devep)) {
700
    if (is_iso_started(s, p->pid, p->devep)) {
691 701
        /* (Re)-submit all fully consumed / filled urbs */
692 702
        for (i = 0; i < s->iso_urb_count; i++) {
693 703
            if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
......
707 717
                    break;
708 718
                }
709 719
                aurb[i].iso_frame_idx = -1;
710
                change_iso_inflight(s, p->devep, +1);
720
                change_iso_inflight(s, p->pid, p->devep, 1);
711 721
            }
712 722
        }
713 723
    }
......
728 738
                            p->pid == USB_TOKEN_IN,
729 739
                            p->devep, p->iov.size);
730 740

  
731
    if (!is_valid(s, p->devep)) {
741
    if (!is_valid(s, p->pid, p->devep)) {
732 742
        trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
733 743
        return USB_RET_NAK;
734 744
    }
......
739 749
        ep = p->devep;
740 750
    }
741 751

  
742
    if (is_halted(s, p->devep)) {
752
    if (is_halted(s, p->pid, p->devep)) {
743 753
        unsigned int arg = ep;
744 754
        ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &arg);
745 755
        if (ret < 0) {
......
747 757
            trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
748 758
            return USB_RET_NAK;
749 759
        }
750
        clear_halt(s, p->devep);
760
        clear_halt(s, p->pid, p->devep);
751 761
    }
752 762

  
753
    if (is_isoc(s, p->devep)) {
763
    if (is_isoc(s, p->pid, p->devep)) {
754 764
        return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
755 765
    }
756 766

  
......
854 864
    trace_usb_host_set_interface(s->bus_num, s->addr, iface, alt);
855 865

  
856 866
    for (i = 1; i <= MAX_ENDPOINTS; i++) {
857
        if (is_isoc(s, i)) {
858
            usb_host_stop_n_free_iso(s, i);
867
        if (is_isoc(s, USB_TOKEN_IN, i)) {
868
            usb_host_stop_n_free_iso(s, USB_TOKEN_IN, i);
869
        }
870
        if (is_isoc(s, USB_TOKEN_OUT, i)) {
871
            usb_host_stop_n_free_iso(s, USB_TOKEN_OUT, i);
859 872
        }
860 873
    }
861 874

  
......
995 1008
{
996 1009
    uint8_t *descriptors;
997 1010
    uint8_t devep, type, alt_interface;
998
    int interface, length, i;
1011
    int interface, length, i, ep, pid;
1012
    struct endp_data *epd;
999 1013

  
1000
    for (i = 0; i < MAX_ENDPOINTS; i++)
1001
        s->endp_table[i].type = INVALID_EP_TYPE;
1014
    for (i = 0; i < MAX_ENDPOINTS; i++) {
1015
        s->ep_in[i].type = INVALID_EP_TYPE;
1016
        s->ep_out[i].type = INVALID_EP_TYPE;
1017
    }
1002 1018

  
1003 1019
    if (s->configuration == 0) {
1004 1020
        /* not configured yet -- leave all endpoints disabled */
......
1052 1068
            }
1053 1069

  
1054 1070
            devep = descriptors[i + 2];
1055
            if ((devep & 0x0f) == 0) {
1071
            pid = (devep & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT;
1072
            ep = devep & 0xf;
1073
            if (ep == 0) {
1056 1074
                fprintf(stderr, "usb-linux: invalid ep descriptor, ep == 0\n");
1057 1075
                return 1;
1058 1076
            }
......
1063 1081
                break;
1064 1082
            case 0x01:
1065 1083
                type = USBDEVFS_URB_TYPE_ISO;
1066
                set_max_packet_size(s, (devep & 0xf), descriptors + i);
1084
                set_max_packet_size(s, pid, ep, descriptors + i);
1067 1085
                break;
1068 1086
            case 0x02:
1069 1087
                type = USBDEVFS_URB_TYPE_BULK;
......
1075 1093
                DPRINTF("usb_host: malformed endpoint type\n");
1076 1094
                type = USBDEVFS_URB_TYPE_BULK;
1077 1095
            }
1078
            s->endp_table[(devep & 0xf) - 1].type = type;
1079
            s->endp_table[(devep & 0xf) - 1].halted = 0;
1096
            epd = get_endp(s, pid, ep);
1097
            assert(epd->type == INVALID_EP_TYPE);
1098
            epd->type = type;
1099
            epd->halted = 0;
1080 1100

  
1081 1101
            i += descriptors[i];
1082 1102
        }
......
1242 1262
    qemu_set_fd_handler(dev->fd, NULL, NULL, NULL);
1243 1263
    dev->closing = 1;
1244 1264
    for (i = 1; i <= MAX_ENDPOINTS; i++) {
1245
        if (is_isoc(dev, i)) {
1246
            usb_host_stop_n_free_iso(dev, i);
1265
        if (is_isoc(dev, USB_TOKEN_IN, i)) {
1266
            usb_host_stop_n_free_iso(dev, USB_TOKEN_IN, i);
1267
        }
1268
        if (is_isoc(dev, USB_TOKEN_OUT, i)) {
1269
            usb_host_stop_n_free_iso(dev, USB_TOKEN_OUT, i);
1247 1270
        }
1248 1271
    }
1249 1272
    async_complete(dev);

Also available in: Unified diff