Ticket #4053: usb_midi_fix.diff
File usb_midi_fix.diff, 16.1 KB (added by , 15 years ago) |
---|
-
haiku/src/add-ons/kernel/drivers/midi/
diff -u haiku/src/add-ons/kernel/drivers/midi/usb_midi_ALPHA1/usb_midi.c haiku/src/add-ons/kernel/drivers/midi/usb_midi/usb_midi.c
old new 3 3 * usb_midi.c 4 4 * 5 5 * Copyright 2006-2009 Haiku Inc. All rights reserved. 6 * Distributed under t he terms of the MIT Licence.6 * Distributed under tthe terms of the MIT Licence. 7 7 * 8 8 * Authors: 9 9 * Jérôme Duval … … 17 17 */ 18 18 19 19 20 /* #define DEBUG 1*/ /* Define this to enable DPRINTF_INFO statements */20 /* #define DEBUG 1 */ /* Define this to enable DPRINTF_INFO statements */ 21 21 #include "usb_midi.h" 22 22 23 #include <s upport/Debug.h>23 #include <stdio.h> 24 24 #include <stdlib.h> 25 25 #include <string.h> 26 26 #include <unistd.h> … … 32 32 static int midi_device_number = 0; 33 33 const char* midi_base_name = "midi/usb/"; 34 34 35 36 35 usbmidi_device_info* 37 36 create_device(const usb_device* dev, const usb_interface_info* ii, uint16 ifno) 38 37 { … … 52 51 if (my_dev == NULL) 53 52 return NULL; 54 53 55 my_dev->sem_cb = sem = create_sem(0, DRIVER_NAME "_cb");56 if (sem < 0) {57 DPRINTF_ERR((MY_ID "create_sem() failed %d\n", (int)sem));58 free(my_dev);59 return NULL;60 }61 62 54 my_dev->sem_lock = sem = create_sem(1, DRIVER_NAME "_lock"); 63 55 if (sem < 0) { 64 56 DPRINTF_ERR((MY_ID "create_sem() failed %d\n", (int)sem)); 65 delete_sem(my_dev->sem_cb);66 57 free(my_dev); 67 58 return NULL; 68 59 } … … 73 64 B_PAGE_SIZE, B_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA); 74 65 if (area < 0) { 75 66 DPRINTF_ERR((MY_ID "create_area() failed %d\n", (int)area)); 76 delete_sem(my_dev->sem_cb);77 67 delete_sem(my_dev->sem_lock); 78 68 free(my_dev); 79 69 return NULL; … … 83 73 my_dev->sem_send = sem = create_sem(1, DRIVER_NAME "_send"); 84 74 if (sem < 0) { 85 75 DPRINTF_ERR((MY_ID "create_sem() failed %d\n", (int)sem)); 86 delete_sem(my_dev->sem_cb);87 76 delete_sem(my_dev->sem_lock); 88 77 delete_area(area); 89 78 free(my_dev); … … 92 81 { 93 82 int32 bc; 94 83 get_sem_count(sem, &bc); 95 DPRINTF_INFO((MY_ID "Allocated % d write buffers\n", bc));84 DPRINTF_INFO((MY_ID "Allocated %ld write buffers\n", bc)); 96 85 } 97 86 98 87 … … 100 89 my_dev->dev = dev; 101 90 my_dev->ifno = ifno; 102 91 my_dev->open = 0; 103 my_dev->open_fd s= NULL;92 my_dev->open_fd = NULL; 104 93 my_dev->active = true; 105 94 my_dev->flags = 0; 106 95 my_dev->rbuf = create_ring_buffer(1024); 107 96 my_dev->buffer_size = B_PAGE_SIZE/2; 97 DPRINTF_INFO((MY_ID "Created device %p\n", my_dev);) 108 98 109 99 return my_dev; 110 100 } … … 118 108 delete_ring_buffer(my_dev->rbuf); 119 109 my_dev->rbuf = NULL; 120 110 } 111 DPRINTF_INFO((MY_ID "remove_device %p\n", my_dev);) 121 112 122 113 delete_area(my_dev->buffer_area); 123 delete_sem(my_dev->sem_cb);124 114 delete_sem(my_dev->sem_lock); 125 115 delete_sem(my_dev->sem_send); 126 116 free(my_dev); 127 117 } 128 118 129 119 130 /* driver cookie (per open ) */120 /* driver cookie (per open -- but only one open allowed!) */ 131 121 132 122 typedef struct driver_cookie 133 123 { 134 124 struct driver_cookie *next; 135 125 usbmidi_device_info *my_dev; 126 sem_id sem_cb; 136 127 } driver_cookie; 137 128 138 129 … … 174 165 DPRINTF_INFO((MY_ID "received packet %x:%d %x %x %x\n", packet->cin, packet->cn, 175 166 packet->midi[0], packet->midi[1], packet->midi[2])); 176 167 ring_buffer_write(my_dev->rbuf, packet->midi, pktlen); 177 release_sem_etc(my_dev-> sem_cb, pktlen, B_DO_NOT_RESCHEDULE);168 release_sem_etc(my_dev->open_fd->sem_cb, pktlen, B_DO_NOT_RESCHEDULE); 178 169 packet++; 179 170 bytes_left -= sizeof(usb_midi_event_packet); 180 171 } … … 193 184 usbmidi_device_info* my_dev = cookie; 194 185 195 186 assert(cookie != NULL); 196 DPRINTF_INFO((MY_ID "midi_usb_read_callback() -- packet length % d\n", actual_len));187 DPRINTF_INFO((MY_ID "midi_usb_read_callback() -- packet length %ld\n", actual_len)); 197 188 198 189 acquire_sem(my_dev->sem_lock); 199 190 my_dev->actual_length = actual_len; 200 191 my_dev->bus_status = status; /* B_USB_STATUS_* */ 201 192 if (status != B_OK) { 202 193 /* request failed */ 203 release_sem(my_dev->sem_lock); 204 DPRINTF_ERR((MY_ID "bus status %d\n", (int)status)); 205 if (status == B_CANCELED) { 194 DPRINTF_INFO((MY_ID "bus status %d\n", (int)status)); /* previously DPRINTF_ERR */ 195 if (status == B_CANCELED || !my_dev->active) { 206 196 /* cancelled: device is unplugged */ 197 DPRINTF_INFO((MY_ID "midi_usb_read_callback: cancelled (status=%lx active=%d -- deleting sem_cb\n", 198 status, my_dev->active)); 199 delete_sem(my_dev->open_fd->sem_cb); /* done here to ensure read is freed */ 200 release_sem(my_dev->sem_lock); 207 201 return; 208 202 } 203 release_sem(my_dev->sem_lock); 209 204 } else { 210 205 /* got a report */ 211 206 #if 0 … … 244 239 #endif 245 240 246 241 assert(cookie != NULL); 247 DPRINTF_INFO((MY_ID "midi_usb_write_callback() status %ld length % d pkt %p cin %x\n",242 DPRINTF_INFO((MY_ID "midi_usb_write_callback() status %ld length %ld pkt %p cin %x\n", 248 243 status, actual_len, pkt, pkt->cin)); 249 244 release_sem(my_dev->sem_send); /* done with buffer */ 250 245 } … … 266 261 int alt; 267 262 268 263 assert(dev != NULL && cookie != NULL); 269 DPRINTF_INFO((MY_ID " device_added()\n"));264 DPRINTF_INFO((MY_ID "usb_midi_added(%p, %p)\n", dev, cookie)); 270 265 271 266 dev_desc = usb->get_device_descriptor(dev); 272 267 … … 348 343 add_device_info(my_dev); 349 344 350 345 *cookie = my_dev; 351 DPRINTF_INFO((MY_ID " added %s\n", my_dev->name));346 DPRINTF_INFO((MY_ID "usb_midi_added: added %s\n", my_dev->name)); 352 347 353 348 return B_OK; 354 349 } … … 361 356 362 357 assert(cookie != NULL); 363 358 364 DPRINTF_INFO((MY_ID "device_removed(%s)\n", my_dev->name)); 359 DPRINTF_INFO((MY_ID "usb_midi_removed(%s)\n", my_dev->name)); 360 acquire_sem(usbmidi_device_list_lock); /* convenient mutex for safety */ 361 my_dev->active = false; 362 if (my_dev->open_fd) { 363 my_dev->open_fd->my_dev = NULL; 364 delete_sem(my_dev->open_fd->sem_cb); /* done here to ensure read is freed */ 365 } 366 release_sem(usbmidi_device_list_lock); 365 367 usb->cancel_queued_transfers(my_dev->ept_in->handle); 366 368 usb->cancel_queued_transfers(my_dev->ept_out->handle); 369 DPRINTF_INFO((MY_ID "usb_midi_removed: removing info & device: %s\n", my_dev->name)); 367 370 remove_device_info(my_dev); 368 if (my_dev->open == 0) { 369 remove_device(my_dev); 370 } else { 371 DPRINTF_INFO((MY_ID "%s still open\n", my_dev->name)); 372 my_dev->active = false; 373 } 371 remove_device(my_dev); 374 372 return B_OK; 375 373 } 376 374 … … 400 398 401 399 assert(name != NULL); 402 400 assert(out_cookie != NULL); 403 DPRINTF_INFO((MY_ID " open(%s)\n", name));401 DPRINTF_INFO((MY_ID "usb_midi_open(%s)\n", name)); 404 402 405 403 if ((my_dev = search_device_info(name)) == NULL) 406 404 return B_ENTRY_NOT_FOUND; 405 if (my_dev->open_fd != NULL) 406 return B_BUSY; /* there can only be one open channel to the device */ 407 407 if ((cookie = malloc(sizeof(driver_cookie))) == NULL) 408 408 return B_NO_MEMORY; 409 409 410 acquire_sem(my_dev->sem_lock); 410 cookie->sem_cb = create_sem(0, DRIVER_NAME "_cb"); 411 if (cookie->sem_cb < 0) { 412 DPRINTF_ERR((MY_ID "create_sem() failed %d\n", (int)cookie->sem_cb)); 413 free(cookie); 414 return B_ERROR; 415 } 416 417 acquire_sem(usbmidi_device_list_lock); /* use global mutex now */ 411 418 cookie->my_dev = my_dev; 412 cookie->next = my_dev->open_fds; 413 my_dev->open_fds = cookie; 419 my_dev->open_fd = cookie; 414 420 my_dev->open++; 415 release_sem( my_dev->sem_lock);421 release_sem(usbmidi_device_list_lock); 416 422 417 423 *out_cookie = cookie; 418 DPRINTF_INFO((MY_ID " device %s open (%d)\n", name, my_dev->open));424 DPRINTF_INFO((MY_ID "usb_midi_open: device %s open (%d)\n", name, my_dev->open)); 419 425 return B_OK; 420 426 } 421 427 … … 433 439 434 440 assert(cookie != NULL); 435 441 my_dev = cookie->my_dev; 436 assert(my_dev != NULL);437 442 438 if (!my_dev ->active)439 return B_ERROR; 443 if (!my_dev || !my_dev->active) 444 return B_ERROR; /* already unplugged */ 440 445 441 DPRINTF_INFO((MY_ID " MIDI read (%d byte buffer at %ld cookie %p)\n",446 DPRINTF_INFO((MY_ID "usb_midi_read: (%ld byte buffer at %ld cookie %p)\n", 442 447 *num_bytes, (int32)position, cookie)); 443 err = acquire_sem_etc(my_dev->sem_cb, 1, B_CAN_INTERRUPT, 0LL); 444 if (err != B_OK) 445 return err; 446 acquire_sem(my_dev->sem_lock); 447 ring_buffer_user_read(my_dev->rbuf, buf, 1); 448 release_sem(my_dev->sem_lock); 449 *num_bytes = 1; 450 DPRINTF_INFO((MY_ID "read byte %x -- cookie %p)\n", *(uint8*)buf, cookie)); 451 return err; 448 while (my_dev && my_dev->active) { 449 DPRINTF_INFOZ((MY_ID "waiting on acquire_sem_etc\n");) 450 err = acquire_sem_etc(cookie->sem_cb, 1, 451 B_RELATIVE_TIMEOUT, 1000000); 452 if (err == B_TIMED_OUT) { 453 DPRINTF_INFOZ((MY_ID "acquire_sem_etc timed out\n");) 454 continue; /* see if we're still active */ 455 } 456 if (err != B_OK) { 457 *num_bytes = 0; 458 DPRINTF_INFO((MY_ID "acquire_sem_etc aborted\n");) 459 break; 460 } 461 DPRINTF_INFO((MY_ID "reading from ringbuffer\n");) 462 acquire_sem(my_dev->sem_lock); 463 ring_buffer_user_read(my_dev->rbuf, buf, 1); 464 release_sem(my_dev->sem_lock); 465 *num_bytes = 1; 466 DPRINTF_INFO((MY_ID "read byte %x -- cookie %p)\n", *(uint8*)buf, cookie)); 467 return B_OK; 468 } 469 DPRINTF_INFO((MY_ID "usb_midi_read: loop terminated -- Device no longer active\n");) 470 return B_CANCELED; 452 471 } 453 472 454 473 … … 491 510 492 511 assert(cookie != NULL); 493 512 my_dev = cookie->my_dev; 494 assert(my_dev != NULL);495 513 496 if (!my_dev ->active)514 if (!my_dev || !my_dev->active) 497 515 return B_ERROR; /* already unplugged */ 498 516 499 517 buff_lim = my_dev->buffer_size * 3 / 4; /* max MIDI bytes buffer space */ 500 518 501 DPRINTF_INFO((MY_ID "MIDI write (% d bytes at %ld)\n", *num_bytes, position));519 DPRINTF_INFO((MY_ID "MIDI write (%ld bytes at %Ld)\n", *num_bytes, position)); 502 520 if (*num_bytes > 3 && midicode != 0xF0) { 503 521 DPRINTF_ERR((MY_ID "Non-SysEx packet of %ld bytes -- too big to handle\n", 504 522 *num_bytes)); … … 563 581 { 564 582 usbmidi_device_info* my_dev; 565 583 566 assert(cookie != NULL && cookie->my_dev != NULL); 584 assert(cookie != NULL); 585 delete_sem(cookie->sem_cb); 567 586 my_dev = cookie->my_dev; 568 DPRINTF_INFO((MY_ID " close(%s)\n", my_dev->name));587 DPRINTF_INFO((MY_ID "usb_midi_close(%p device=%p)\n", cookie, my_dev)); 569 588 570 /* detach the cookie from list */571 589 572 acquire_sem(my_dev->sem_lock); 573 if (my_dev->open_fds == cookie) 574 my_dev->open_fds = cookie->next; 575 else { 576 driver_cookie* p; 577 for (p = my_dev->open_fds; p != NULL; p = p->next) { 578 if (p->next == cookie) { 579 p->next = cookie->next; 580 break; 581 } 582 } 590 acquire_sem(usbmidi_device_list_lock); 591 if (my_dev) { 592 /* detach the cookie from device */ 593 my_dev->open_fd = NULL; 594 --my_dev->open; 583 595 } 584 --my_dev->open;585 release_sem(my_dev->sem_lock);596 release_sem(usbmidi_device_list_lock); 597 DPRINTF_INFO((MY_ID "usb_midi_close: complete\n");) 586 598 587 599 return B_OK; 588 600 } … … 598 610 { 599 611 usbmidi_device_info* my_dev; 600 612 601 assert(cookie != NULL && cookie->my_dev != NULL);613 assert(cookie != NULL); 602 614 my_dev = cookie->my_dev; 603 DPRINTF_INFO((MY_ID " free(%s)\n", my_dev->name));615 DPRINTF_INFO((MY_ID "usb_midi_free(%p device=%p)\n", cookie, my_dev)); 604 616 605 617 free(cookie); 606 if (my_dev->open > 0)607 DPRINTF_INFO((MY_ID "%d opens left\n", my_dev->open));608 else if (!my_dev->active) {609 DPRINTF_INFO((MY_ID "removed %s\n", my_dev->name));610 remove_device(my_dev);611 }612 618 613 619 return B_OK; 614 620 } … … 683 689 delete_sem(usbmidi_device_list_lock); 684 690 put_module(B_USB_MODULE_NAME); 685 691 free_device_names(); 692 DPRINTF_INFO((MY_ID "uninit complete\n")); 686 693 } 687 694 688 695 -
haiku/src/add-ons/kernel/drivers/midi/
diff -u haiku/src/add-ons/kernel/drivers/midi/usb_midi_ALPHA1/usb_midi.h haiku/src/add-ons/kernel/drivers/midi/usb_midi/usb_midi.h
old new 62 62 struct usbmidi_device_info* next; 63 63 64 64 /* maintain device */ 65 sem_id sem_cb;66 65 sem_id sem_lock; 67 66 sem_id sem_send; 68 67 area_id buffer_area; … … 77 76 78 77 bool active; 79 78 int open; 80 struct driver_cookie* open_fd s;79 struct driver_cookie* open_fd; 81 80 82 81 /* work area for transfer */ 83 82 int usbd_status, bus_status, cmd_status; -
DeviceWatcher.cpp
diff -u haiku/src/servers/midi_ALPHA1/DeviceWatcher.cpp haiku/src/servers/midi/DeviceWatcher.cpp
old new 8 8 * Philippe Houdoin 9 9 */ 10 10 11 12 11 #include "debug.h" 13 12 #include "DeviceWatcher.h" 14 13 #include "PortDrivers.h" … … 32 31 using BPrivate::HashMap; 33 32 using BPrivate::HashString; 34 33 34 35 35 36 const char *kDevicesRoot = "/dev/midi"; 36 // const char *kDevicesRoot = "/Data/tmp";37 37 38 38 39 39 class DeviceEndpoints { … … 132 132 if (message->FindString("path", &path) != B_OK) 133 133 return; 134 134 135 const char* filename; 136 if (message->FindString("name", &filename) != B_OK) 137 return; 138 135 139 switch (opcode) { 136 140 case B_ENTRY_CREATED: { 137 _AddDevice(path); 141 BPath bpath(path); 142 TRACE(("got path %s leaf %s name %s\n", path, bpath.Leaf(), filename)); 143 if (strcmp(bpath.Leaf(), filename) == 0) _AddDevice(path); 138 144 break; 139 145 } 140 146 case B_ENTRY_REMOVED: { … … 152 158 int32 153 159 DeviceWatcher::_InitialDevicesScanThread(void* data) 154 160 { 155 ((DeviceWatcher*) data)->_ScanDevices(kDevicesRoot);161 ((DeviceWatcher*) data)->_ScanDevices(kDevicesRoot); 156 162 return 0; 157 163 } 158 164 … … 183 189 { 184 190 TRACE(("DeviceWatcher::_AddDevice(\"%s\");\n", path)); 185 191 186 if ( fDeviceEndpointsMap.ContainsKey(path)) {192 if ( fDeviceEndpointsMap.ContainsKey(path) ) { 187 193 // Already known 194 TRACE(("already known...!\n")); 188 195 return; 189 196 } 190 197 191 BEntry entry(path);192 if (entry.IsDirectory())193 // Invalid path !194 return;195 196 if (entry.IsSymLink()) {197 BEntry symlink(path, true);198 if (symlink.IsDirectory()) {199 // Invalid path!200 return;201 }202 }203 204 198 int fd = open(path, O_RDWR | O_EXCL); 205 199 if (fd < 0) 206 return; 200 return; 201 207 202 203 TRACE(("Doing _AddDevice(\"%s\"); fd=%d\n", path, fd)); 204 208 205 MidiPortConsumer* consumer = new MidiPortConsumer(fd, path); 209 206 _SetIcons(consumer); 210 207 TRACE(("Register %s MidiPortConsumer\n", consumer->Name())); … … 215 212 TRACE(("Register %s MidiPortProducer\n", producer->Name())); 216 213 producer->Register(); 217 214 218 DeviceEndpoints * deviceEndpoints = new DeviceEndpoints(fd, consumer, producer);215 DeviceEndpoints * deviceEndpoints = new DeviceEndpoints(fd, consumer, producer); 219 216 fDeviceEndpointsMap.Put(path, deviceEndpoints); 217 TRACE(("Done _AddDevice(\"%s\")\n", path)); 220 218 } 221 219 222 220 … … 225 223 { 226 224 TRACE(("DeviceWatcher::_RemoveDevice(\"%s\");\n", path)); 227 225 228 DeviceEndpoints* deviceEndpoints = fDeviceEndpointsMap.Get(path); 229 if (!deviceEndpoints) 226 DeviceEndpoints * deviceEndpoints = fDeviceEndpointsMap.Get(path); 227 if (!deviceEndpoints) { 228 TRACE(("_RemoveDevice(\"%s\") didn't find endpoint in map!!\n", path)); 230 229 return; 230 } 231 231 232 close(deviceEndpoints->fFD);233 232 233 TRACE((" _RemoveDevice(\"%s\") unregistering\n", path)); 234 234 deviceEndpoints->fConsumer->Unregister(); 235 235 deviceEndpoints->fProducer->Unregister(); 236 236 237 TRACE((" _RemoveDevice(\"%s\") releasing\n", path)); 237 238 deviceEndpoints->fConsumer->Release(); 238 239 deviceEndpoints->fProducer->Release(); 239 240 241 TRACE((" _RemoveDevice(\"%s\") removing from map\n", path)); 240 242 fDeviceEndpointsMap.Remove(path); 243 TRACE(("Done _RemoveDevice(\"%s\")\n", path)); 241 244 } 242 245 243 246 -
haiku/src/servers/
diff -u haiku/src/servers/midi_ALPHA1/PortDrivers.cpp haiku/src/servers/midi/PortDrivers.cpp
old new 15 15 #include <stdio.h> 16 16 #include <stdlib.h> 17 17 #include <unistd.h> 18 #include <errno.h> 18 19 19 20 #include <String.h> 20 21 … … 90 91 91 92 while (fKeepRunning) { 92 93 if (read(fFileDescriptor, &next, 1) != 1) { 93 perror("Error reading data from driver"); 94 if (errno == B_CANCELED) fKeepRunning = false; 95 else perror("Error reading data from driver"); 94 96 break; 95 97 } 96 98 … … 234 236 if (haveSysEx) 235 237 free(sysexBuf); 236 238 237 return fKeepRunning ? B_ERROR: B_OK;239 return fKeepRunning ? errno : B_OK; 238 240 } -
haiku/src/servers/
diff -u haiku/src/servers/midi_ALPHA1/midi_server.rdef haiku/src/servers/midi/midi_server.rdef
old new 10 10 variety = B_APPV_ALPHA, 11 11 internal = 0, 12 12 short_info = "midi_server", 13 long_info = "midi_server ©2002-200 6Haiku"13 long_info = "midi_server ©2002-2009 Haiku" 14 14 }; 15 15 16 16 resource vector_icon array {