Applied patch by Pete Goodeve, which adds multi-ports support to usb_midi driver.

Fixed some coding style and a few sanity checks where it make sense.

This driver code is not in a good shape and needs a wide cleanup.
unfortunatly, I still don't have any device to test with, so I can't do that anytime soon.
Intead of letting his patch collecting dust since 3 months (my bad),
I think it's better the multi-port support gets at least more exposure than
just Pete's hardware.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41874 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Philippe Houdoin 2011-06-03 10:30:03 +00:00
parent 5d6dcc0685
commit 1291377a6e
3 changed files with 529 additions and 382 deletions

View File

@ -2,7 +2,7 @@
* midi usb driver
* devlist.c
*
* Copyright 2006-2009 Haiku Inc. All rights reserved.
* Copyright 2006-2011 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT Licence.
*
* Authors:
@ -23,107 +23,127 @@
#include <string.h>
sem_id usbmidi_device_list_lock = -1;
bool usbmidi_device_list_changed = true; /* added or removed */
sem_id usbmidi_port_list_lock = -1;
bool usbmidi_port_list_changed = true; /* added or removed */
static usbmidi_device_info* usbmidi_device_list = NULL;
static int usbmidi_device_count = 0;
static usbmidi_port_info* usbmidi_port_list = NULL;
static int usbmidi_port_count = 0;
void
add_device_info(usbmidi_device_info* my_dev)
add_port_info(usbmidi_port_info* port)
{
assert(my_dev != NULL);
acquire_sem(usbmidi_device_list_lock);
my_dev->next = usbmidi_device_list;
usbmidi_device_list = my_dev;
usbmidi_device_count++;
usbmidi_device_list_changed = true;
release_sem(usbmidi_device_list_lock);
assert(port != NULL);
acquire_sem(usbmidi_port_list_lock);
port->next = usbmidi_port_list;
usbmidi_port_list = port;
usbmidi_port_count++;
usbmidi_port_list_changed = true;
release_sem(usbmidi_port_list_lock);
}
void
remove_device_info(usbmidi_device_info* my_dev)
remove_port_info(usbmidi_port_info* port)
{
assert(my_dev != NULL);
acquire_sem(usbmidi_device_list_lock);
if (usbmidi_device_list == my_dev) {
usbmidi_device_list = my_dev->next;
--usbmidi_device_count;
usbmidi_device_list_changed = true;
assert(port != NULL);
acquire_sem(usbmidi_port_list_lock);
if (usbmidi_port_list == port) {
usbmidi_port_list = port->next;
--usbmidi_port_count;
usbmidi_port_list_changed = true;
} else {
usbmidi_device_info* d;
for (d = usbmidi_device_list; d != NULL; d = d->next) {
if (d->next == my_dev) {
d->next = my_dev->next;
--usbmidi_device_count;
usbmidi_device_list_changed = true;
usbmidi_port_info* d;
for (d = usbmidi_port_list; d != NULL; d = d->next) {
if (d->next == port) {
d->next = port->next;
--usbmidi_port_count;
usbmidi_port_list_changed = true;
break;
}
}
assert(d != NULL);
}
release_sem(usbmidi_device_list_lock);
release_sem(usbmidi_port_list_lock);
}
usbmidi_device_info*
search_device_info(const char* name)
usbmidi_port_info*
search_port_info(const char* name)
{
usbmidi_device_info* my_dev;
usbmidi_port_info* port;
acquire_sem(usbmidi_device_list_lock);
for (my_dev = usbmidi_device_list; my_dev != NULL; my_dev = my_dev->next) {
if (strcmp(my_dev->name, name) == 0)
acquire_sem(usbmidi_port_list_lock);
for (port = usbmidi_port_list; port != NULL; port = port->next) {
if (strcmp(port->name, name) == 0)
break;
}
release_sem(usbmidi_device_list_lock);
return my_dev;
release_sem(usbmidi_port_list_lock);
return port;
}
int
find_free_device_number(void)
{
usbmidi_port_info* port;
int number = 0;
acquire_sem(usbmidi_port_list_lock);
do {
for (port = usbmidi_port_list; port != NULL; port = port->next) {
if (port->device->devnum == number) {
number++;
break; /* try next higher */
}
}
} while (port);
release_sem(usbmidi_port_list_lock);
return number;
}
/*
device names
*/
/* dynamically generated */
char** usbmidi_device_names = NULL;
char** usbmidi_port_names = NULL;
void
alloc_device_names(void)
alloc_port_names(void)
{
assert(usbmidi_device_names == NULL);
usbmidi_device_names = malloc(sizeof(char*) * (usbmidi_device_count + 1));
assert(usbmidi_port_names == NULL);
usbmidi_port_names = malloc(sizeof(char*) * (usbmidi_port_count + 1));
}
void
free_device_names(void)
free_port_names(void)
{
if (usbmidi_device_names != NULL) {
if (usbmidi_port_names != NULL) {
int i;
for (i = 0; usbmidi_device_names[i] != NULL; i++)
free(usbmidi_device_names[i]);
free(usbmidi_device_names);
usbmidi_device_names = NULL;
for (i = 0; usbmidi_port_names[i] != NULL; i++)
free(usbmidi_port_names[i]);
free(usbmidi_port_names);
usbmidi_port_names = NULL;
}
}
void
rebuild_device_names(void)
rebuild_port_names(void)
{
int i;
usbmidi_device_info* my_dev;
usbmidi_port_info* port;
assert(usbmidi_device_names != NULL);
acquire_sem(usbmidi_device_list_lock);
for (i = 0, my_dev = usbmidi_device_list; my_dev != NULL; my_dev = my_dev->next) {
usbmidi_device_names[i++] = strdup(my_dev->name);
DPRINTF_INFO((MY_ID "publishing %s\n", my_dev->name));
assert(usbmidi_port_names != NULL);
acquire_sem(usbmidi_port_list_lock);
for (i = 0, port = usbmidi_port_list; port != NULL; port = port->next) {
usbmidi_port_names[i++] = strdup(port->name);
DPRINTF_INFO((MY_ID "publishing %s\n", port->name));
}
usbmidi_device_names[i] = NULL;
release_sem(usbmidi_device_list_lock);
usbmidi_port_names[i] = NULL;
release_sem(usbmidi_port_list_lock);
}

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
* midi usb driver
* usb_midi.h
*
* Copyright 2006-2009 Haiku Inc. All rights reserved.
* Copyright 2006-2011 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT Licence.
*
* Authors:
@ -23,23 +23,32 @@
#include "ring_buffer.h"
/* Three levels of printout for convenience: */
/* #define DEBUG 1 -- more convenient to define in the code file when needed */
#define DEBUG_INFO 1
#define DEBUG_ERR 1
#if DEBUG
#define DPRINTF_INFO(x) dprintf x
#else
#define DPRINTF_INFO(x)
#endif
/* Normally leave this enabled to leave a record in syslog */
#if DEBUG_ERR
#define DPRINTF_ERR(x) dprintf x
#else
#define DPRINTF_ERR(x)
#endif
/* For local finer debugging control: */
#define DPRINTF_INFOX(x) dprintf x
#define DPRINTF_INFOZ(x)
/* Use this for initialization etc. messages -- nothing repetitive: */
#if DEBUG_INFO
#define DPRINTF_INFO(x) dprintf x
#else
#define DPRINTF_INFO(x)
#endif
/* Enable this to record detailed stuff: */
#if DEBUG
#define DPRINTF_DEBUG(x) dprintf x
#else
#define DPRINTF_DEBUG(x)
#endif
/* driver specific definitions */
@ -49,7 +58,8 @@
#define MY_ERR "\033[31merror:\033[m "
#define MY_WARN "\033[31mwarning:\033[m "
#define assert(x) \
((x) ? 0 : dprintf(MY_ID "assertion failed at " __FILE__ ", line %d\n", __LINE__))
((x) ? 0 : dprintf(MY_ID "assertion failed at " \
__FILE__ ", line %d\n", __LINE__))
#define DEFAULT_CONFIGURATION 0
@ -58,61 +68,91 @@ struct driver_cookie;
typedef struct usbmidi_device_info
{
/* list structure */
/* list structure */ /* should not be needed eventually */
struct usbmidi_device_info* next;
/* maintain device */
/* Set of actual ports ("cables" -- one or more) */
struct usbmidi_port_info* ports[16];
/* maintain device (common for all ports) */
sem_id sem_lock;
sem_id sem_send;
area_id buffer_area;
usb_midi_event_packet* buffer; /* input buffer & base of area */
usb_midi_event_packet* out_buffer; /* above input buff */
usb_midi_event_packet* out_buffer; /* above input buffer */
size_t buffer_size; /* for each of in and out buffers */
const usb_device* dev;
uint16 ifno;
char name[30];
struct ring_buffer* rbuf;
int devnum; /* unique device number */
char name[20];
/* = "/dev/midi/usb/n" --port number will be appended to this */
bool active;
int open;
struct driver_cookie* open_fd;
/* work area for transfer */
int usbd_status, bus_status, cmd_status;
int bus_status;
int actual_length;
const usb_endpoint_info* ept_in;
const usb_endpoint_info* ept_out;
size_t buffer_size;
bigtime_t timestamp;
uint flags;
bigtime_t timestamp; /* Is this needed? Currently set but never read */
uint flags; /* set to 0 but never used */
} usbmidi_device_info;
/* usb_midi.c */
typedef struct usbmidi_port_info
{
/* list structure for manager */
struct usbmidi_port_info* next;
/* Common device that does the work */
usbmidi_device_info* device;
/* Port-specific variables */
char name[40]; /* complete pathname of this port */
struct ring_buffer* rbuf;
int cable; /* index of this port */
bool has_in, has_out;
int open;
struct driver_cookie* open_fd;
} usbmidi_port_info;
/*
usb_midi.c
*/
extern usb_module_info* usb;
extern const char* usb_midi_base_name;
usbmidi_device_info*
create_device(const usb_device* dev, const usb_interface_info* ii, uint16 ifno);
extern usbmidi_port_info* create_usbmidi_port(usbmidi_device_info* devinfo,
int cable, bool has_in, bool has_out);
extern void remove_port(usbmidi_port_info* port);
void
remove_device(usbmidi_device_info* my_dev);
extern usbmidi_device_info* create_device(const usb_device* dev, uint16 ifno);
extern void remove_device(usbmidi_device_info* my_dev);
/* devlist.c */
/*
devlist.c
*/
extern sem_id usbmidi_device_list_lock;
extern bool usbmidi_device_list_changed;
extern sem_id usbmidi_port_list_lock;
extern bool usbmidi_port_list_changed;
void add_device_info(usbmidi_device_info* my_dev);
void remove_device_info(usbmidi_device_info* my_dev);
usbmidi_device_info* search_device_info(const char* name);
extern void add_port_info(usbmidi_port_info* port);
extern void remove_port_info(usbmidi_port_info* port);
extern char** usbmidi_device_names;
extern usbmidi_port_info* search_port_info(const char* name);
void alloc_device_names(void);
void free_device_names(void);
void rebuild_device_names(void);
extern int find_free_device_number(void);
extern char** usbmidi_port_names;
extern void alloc_port_names(void);
extern void free_port_names(void);
extern void rebuild_port_names(void);