1*433d6423SLionel Sambuc #include "common.h" 2*433d6423SLionel Sambuc 3*433d6423SLionel Sambuc #include <ddekit/minix/msg_queue.h> 4*433d6423SLionel Sambuc #include <ddekit/panic.h> 5*433d6423SLionel Sambuc #include <ddekit/printf.h> 6*433d6423SLionel Sambuc #include <ddekit/usb.h> 7*433d6423SLionel Sambuc #include <minix/safecopies.h> 8*433d6423SLionel Sambuc #include <minix/usb.h> 9*433d6423SLionel Sambuc #include <minix/usb_ch9.h> 10*433d6423SLionel Sambuc #include <minix/devman.h> 11*433d6423SLionel Sambuc 12*433d6423SLionel Sambuc #define MAX_URBS 10 13*433d6423SLionel Sambuc 14*433d6423SLionel Sambuc #define DRIVER_UNUSED 0 15*433d6423SLionel Sambuc #define DRIVER_ACTIVE 1 16*433d6423SLionel Sambuc #define DRIVER_BOUND 2 17*433d6423SLionel Sambuc 18*433d6423SLionel Sambuc #if 0 19*433d6423SLionel Sambuc #define DEBUG_MSG(fmt, ...) ddekit_printf("%s : "fmt"\n", __func__, ##__VA_ARGS__ ) 20*433d6423SLionel Sambuc #else 21*433d6423SLionel Sambuc #define DEBUG_MSG(fmt, ...) 22*433d6423SLionel Sambuc #endif 23*433d6423SLionel Sambuc 24*433d6423SLionel Sambuc #undef DDEBUG 25*433d6423SLionel Sambuc #define DDEBUG 0 26*433d6423SLionel Sambuc #include "debug.h" 27*433d6423SLionel Sambuc 28*433d6423SLionel Sambuc #define MAX_DEVS 256 29*433d6423SLionel Sambuc #define MAX_DRIVERS 256 30*433d6423SLionel Sambuc #define OK 0 31*433d6423SLionel Sambuc 32*433d6423SLionel Sambuc #define INVAL_DEV (-1) 33*433d6423SLionel Sambuc 34*433d6423SLionel Sambuc struct my_context { 35*433d6423SLionel Sambuc unsigned urb_id; 36*433d6423SLionel Sambuc struct ddekit_usb_urb *d_urb; 37*433d6423SLionel Sambuc struct usb_urb *mx_urb; 38*433d6423SLionel Sambuc struct minix_usb_driver *drv; 39*433d6423SLionel Sambuc gid_t gid; 40*433d6423SLionel Sambuc }; 41*433d6423SLionel Sambuc 42*433d6423SLionel Sambuc struct minix_usb_driver { 43*433d6423SLionel Sambuc endpoint_t ep; /* address of the client */ 44*433d6423SLionel Sambuc 45*433d6423SLionel Sambuc int status; /* In what state is the client? */ 46*433d6423SLionel Sambuc 47*433d6423SLionel Sambuc int dev; /* which device is this driver handling */ 48*433d6423SLionel Sambuc unsigned interfaces; /* which interfaces of the device the 49*433d6423SLionel Sambuc driver is handling */ 50*433d6423SLionel Sambuc 51*433d6423SLionel Sambuc struct ddekit_usb_urb *urbs[MAX_URBS]; /* pending urbs */ 52*433d6423SLionel Sambuc 53*433d6423SLionel Sambuc unsigned long urb_id; /* generation of driver_local urb_ids */ 54*433d6423SLionel Sambuc }; 55*433d6423SLionel Sambuc 56*433d6423SLionel Sambuc struct minix_usb_device { 57*433d6423SLionel Sambuc struct ddekit_usb_dev *dev; 58*433d6423SLionel Sambuc unsigned int interfaces; 59*433d6423SLionel Sambuc }; 60*433d6423SLionel Sambuc 61*433d6423SLionel Sambuc static struct minix_usb_driver *find_driver(endpoint_t ep); 62*433d6423SLionel Sambuc static struct minix_usb_driver *find_unused_driver(void); 63*433d6423SLionel Sambuc static int add_to_pending_urbs(struct minix_usb_driver *drv, struct 64*433d6423SLionel Sambuc ddekit_usb_urb *urb); 65*433d6423SLionel Sambuc static int remove_from_pending_urbs(struct minix_usb_driver *drv, 66*433d6423SLionel Sambuc struct ddekit_usb_urb *urb); 67*433d6423SLionel Sambuc static struct ddekit_usb_urb * find_pending_urb(struct minix_usb_driver 68*433d6423SLionel Sambuc *drv, unsigned urb_id); 69*433d6423SLionel Sambuc static void register_driver(message *msg); 70*433d6423SLionel Sambuc static struct ddekit_usb_urb *ddekit_usb_urb_from_mx_urb(struct usb_urb 71*433d6423SLionel Sambuc *mx_urb); 72*433d6423SLionel Sambuc static void submit_urb(message *msg); 73*433d6423SLionel Sambuc static void cancle_urb(message *msg); 74*433d6423SLionel Sambuc static void completion_callback(void *priv); 75*433d6423SLionel Sambuc 76*433d6423SLionel Sambuc static void prepare_devman_usbdev(struct ddekit_usb_dev * dev, int 77*433d6423SLionel Sambuc dev_id, unsigned int interfaces, struct devman_usb_dev *dudev); 78*433d6423SLionel Sambuc static void device_disconnect_callback(struct ddekit_usb_dev * dev); 79*433d6423SLionel Sambuc static int add_acl(int dev_id, unsigned interfaces, endpoint_t ep); 80*433d6423SLionel Sambuc static int del_acl(int dev_id, unsigned interaces, endpoint_t ep); 81*433d6423SLionel Sambuc static int handle_msg(message *msg); 82*433d6423SLionel Sambuc static void _ddekit_usb_thread(); 83*433d6423SLionel Sambuc static void device_connect_callback(struct ddekit_usb_dev * dev, 84*433d6423SLionel Sambuc unsigned int interfaces); 85*433d6423SLionel Sambuc 86*433d6423SLionel Sambuc char *_ddekit_usb_get_manufacturer(struct ddekit_usb_dev *ddev); 87*433d6423SLionel Sambuc char *_ddekit_usb_get_product(struct ddekit_usb_dev *ddev); 88*433d6423SLionel Sambuc char *_ddekit_usb_get_serial(struct ddekit_usb_dev *ddev); 89*433d6423SLionel Sambuc usb_device_descriptor_t *_ddekit_usb_get_device_desc(struct 90*433d6423SLionel Sambuc ddekit_usb_dev *ddev); 91*433d6423SLionel Sambuc usb_interface_descriptor_t *_ddekit_usb_get_interface_desc(struct 92*433d6423SLionel Sambuc ddekit_usb_dev *ddev, int inum); 93*433d6423SLionel Sambuc 94*433d6423SLionel Sambuc 95*433d6423SLionel Sambuc static ddekit_usb_malloc_fn my_malloc; 96*433d6423SLionel Sambuc static ddekit_usb_free_fn my_free; 97*433d6423SLionel Sambuc static struct minix_usb_driver gbl_drivers[MAX_DRIVERS]; 98*433d6423SLionel Sambuc static struct minix_usb_device _devices[MAX_DEVS]; 99*433d6423SLionel Sambuc 100*433d6423SLionel Sambuc static struct ddekit_usb_driver my_driver = { 101*433d6423SLionel Sambuc .completion = completion_callback, 102*433d6423SLionel Sambuc .connect = device_connect_callback, 103*433d6423SLionel Sambuc .disconnect = device_disconnect_callback, 104*433d6423SLionel Sambuc }; 105*433d6423SLionel Sambuc 106*433d6423SLionel Sambuc 107*433d6423SLionel Sambuc /***************************************************************************** 108*433d6423SLionel Sambuc * find_driver * 109*433d6423SLionel Sambuc ****************************************************************************/ 110*433d6423SLionel Sambuc static struct minix_usb_driver *find_driver(endpoint_t ep) 111*433d6423SLionel Sambuc { 112*433d6423SLionel Sambuc int i; 113*433d6423SLionel Sambuc for (i = 0; i < MAX_DRIVERS; i++ ){ 114*433d6423SLionel Sambuc if (gbl_drivers[i].ep == ep) { 115*433d6423SLionel Sambuc return &gbl_drivers[i]; 116*433d6423SLionel Sambuc } 117*433d6423SLionel Sambuc } 118*433d6423SLionel Sambuc return NULL; 119*433d6423SLionel Sambuc } 120*433d6423SLionel Sambuc 121*433d6423SLionel Sambuc /***************************************************************************** 122*433d6423SLionel Sambuc * find_unused_driver * 123*433d6423SLionel Sambuc ****************************************************************************/ 124*433d6423SLionel Sambuc static struct minix_usb_driver *find_unused_driver() 125*433d6423SLionel Sambuc { 126*433d6423SLionel Sambuc int i; 127*433d6423SLionel Sambuc for (i = 0; i < MAX_DRIVERS; i++ ){ 128*433d6423SLionel Sambuc if (gbl_drivers[i].status == DRIVER_UNUSED) { 129*433d6423SLionel Sambuc return &gbl_drivers[i]; 130*433d6423SLionel Sambuc } 131*433d6423SLionel Sambuc } 132*433d6423SLionel Sambuc return NULL; 133*433d6423SLionel Sambuc } 134*433d6423SLionel Sambuc 135*433d6423SLionel Sambuc /***************************************************************************** 136*433d6423SLionel Sambuc * add_to_pending_urbs * 137*433d6423SLionel Sambuc ****************************************************************************/ 138*433d6423SLionel Sambuc static int add_to_pending_urbs(struct minix_usb_driver *drv, 139*433d6423SLionel Sambuc struct ddekit_usb_urb *urb) 140*433d6423SLionel Sambuc { 141*433d6423SLionel Sambuc int i; 142*433d6423SLionel Sambuc 143*433d6423SLionel Sambuc for (i = 0; i < MAX_URBS; i++) { 144*433d6423SLionel Sambuc if (drv->urbs[i] == NULL) { 145*433d6423SLionel Sambuc drv->urbs[i] = urb; 146*433d6423SLionel Sambuc return 0; 147*433d6423SLionel Sambuc } 148*433d6423SLionel Sambuc } 149*433d6423SLionel Sambuc 150*433d6423SLionel Sambuc return -1; 151*433d6423SLionel Sambuc } 152*433d6423SLionel Sambuc 153*433d6423SLionel Sambuc /***************************************************************************** 154*433d6423SLionel Sambuc * remove_from_pending_urbs * 155*433d6423SLionel Sambuc ****************************************************************************/ 156*433d6423SLionel Sambuc static int remove_from_pending_urbs(struct minix_usb_driver *drv, 157*433d6423SLionel Sambuc struct ddekit_usb_urb *urb) 158*433d6423SLionel Sambuc { 159*433d6423SLionel Sambuc int i; 160*433d6423SLionel Sambuc 161*433d6423SLionel Sambuc for (i = 0; i < MAX_URBS; i++) { 162*433d6423SLionel Sambuc if (drv->urbs[i] == urb) { 163*433d6423SLionel Sambuc drv->urbs[i] = NULL; 164*433d6423SLionel Sambuc return 0; 165*433d6423SLionel Sambuc } 166*433d6423SLionel Sambuc } 167*433d6423SLionel Sambuc 168*433d6423SLionel Sambuc return -1; 169*433d6423SLionel Sambuc } 170*433d6423SLionel Sambuc 171*433d6423SLionel Sambuc /***************************************************************************** 172*433d6423SLionel Sambuc * find_pending_urb * 173*433d6423SLionel Sambuc ****************************************************************************/ 174*433d6423SLionel Sambuc static struct ddekit_usb_urb * find_pending_urb(struct minix_usb_driver *drv, 175*433d6423SLionel Sambuc unsigned urb_id) 176*433d6423SLionel Sambuc { 177*433d6423SLionel Sambuc int i; 178*433d6423SLionel Sambuc 179*433d6423SLionel Sambuc for (i = 0; i < MAX_URBS; i++) { 180*433d6423SLionel Sambuc if (((struct my_context*)drv->urbs[i]->priv)->urb_id == urb_id) { 181*433d6423SLionel Sambuc return drv->urbs[i]; 182*433d6423SLionel Sambuc } 183*433d6423SLionel Sambuc } 184*433d6423SLionel Sambuc 185*433d6423SLionel Sambuc return NULL; 186*433d6423SLionel Sambuc } 187*433d6423SLionel Sambuc 188*433d6423SLionel Sambuc /***************************************************************************** 189*433d6423SLionel Sambuc * register_driver * 190*433d6423SLionel Sambuc ****************************************************************************/ 191*433d6423SLionel Sambuc static void register_driver(message *msg) 192*433d6423SLionel Sambuc { 193*433d6423SLionel Sambuc endpoint_t ep = msg->m_source; 194*433d6423SLionel Sambuc struct minix_usb_driver *drv; 195*433d6423SLionel Sambuc 196*433d6423SLionel Sambuc msg->m_type=USB_REPLY; 197*433d6423SLionel Sambuc 198*433d6423SLionel Sambuc if ( (drv = find_driver(ep)) != NULL) { 199*433d6423SLionel Sambuc msg->m_type = USB_REPLY; 200*433d6423SLionel Sambuc msg->USB_RESULT = OK; 201*433d6423SLionel Sambuc ipc_send(ep,msg); 202*433d6423SLionel Sambuc } else { 203*433d6423SLionel Sambuc msg->m_type = USB_REPLY; 204*433d6423SLionel Sambuc msg->USB_RESULT = EPERM; 205*433d6423SLionel Sambuc ipc_send(ep,msg); 206*433d6423SLionel Sambuc return; 207*433d6423SLionel Sambuc } 208*433d6423SLionel Sambuc 209*433d6423SLionel Sambuc DEBUG_MSG("DRIVER %d registered \n" 210*433d6423SLionel Sambuc "Announcing device %d, interfaces 0x%x\n", 211*433d6423SLionel Sambuc ep, 212*433d6423SLionel Sambuc drv->dev, 213*433d6423SLionel Sambuc drv->interfaces); 214*433d6423SLionel Sambuc 215*433d6423SLionel Sambuc /* hand out the device */ 216*433d6423SLionel Sambuc msg->m_type = USB_ANNOUCE_DEV; 217*433d6423SLionel Sambuc msg->USB_DEV_ID = drv->dev; 218*433d6423SLionel Sambuc msg->USB_INTERFACES = drv->interfaces; 219*433d6423SLionel Sambuc ipc_send(ep, msg); 220*433d6423SLionel Sambuc } 221*433d6423SLionel Sambuc 222*433d6423SLionel Sambuc /***************************************************************************** 223*433d6423SLionel Sambuc * deregister_driver * 224*433d6423SLionel Sambuc ****************************************************************************/ 225*433d6423SLionel Sambuc static void deregister_driver(message *msg) 226*433d6423SLionel Sambuc { 227*433d6423SLionel Sambuc endpoint_t ep = msg->m_source; 228*433d6423SLionel Sambuc 229*433d6423SLionel Sambuc struct minix_usb_driver *drv; 230*433d6423SLionel Sambuc 231*433d6423SLionel Sambuc msg->m_type=USB_REPLY; 232*433d6423SLionel Sambuc 233*433d6423SLionel Sambuc if ( (drv = find_driver(ep)) == NULL) { 234*433d6423SLionel Sambuc DEBUG_MSG("Non-registered driver tries to unregister."); 235*433d6423SLionel Sambuc return; 236*433d6423SLionel Sambuc } else { 237*433d6423SLionel Sambuc /* do not accept requests for this client anymore! */ 238*433d6423SLionel Sambuc drv->status = DRIVER_UNUSED; 239*433d6423SLionel Sambuc 240*433d6423SLionel Sambuc msg->USB_RESULT = 0; 241*433d6423SLionel Sambuc asynsend3(ep, msg, AMF_NOREPLY); 242*433d6423SLionel Sambuc } 243*433d6423SLionel Sambuc } 244*433d6423SLionel Sambuc 245*433d6423SLionel Sambuc /***************************************************************************** 246*433d6423SLionel Sambuc * ddekit_usb_urb_from_mx_urb * 247*433d6423SLionel Sambuc ****************************************************************************/ 248*433d6423SLionel Sambuc static struct ddekit_usb_urb *ddekit_usb_urb_from_mx_urb(struct usb_urb *mx_urb) 249*433d6423SLionel Sambuc { 250*433d6423SLionel Sambuc /* 251*433d6423SLionel Sambuc * A helper function that generates (allocates and initializes) 252*433d6423SLionel Sambuc * a ddekit_usb_urb. 253*433d6423SLionel Sambuc */ 254*433d6423SLionel Sambuc 255*433d6423SLionel Sambuc struct ddekit_usb_urb *d_urb = (struct ddekit_usb_urb *) 256*433d6423SLionel Sambuc my_malloc(sizeof(struct ddekit_usb_urb)); 257*433d6423SLionel Sambuc 258*433d6423SLionel Sambuc if (d_urb == NULL) { 259*433d6423SLionel Sambuc return NULL; 260*433d6423SLionel Sambuc } 261*433d6423SLionel Sambuc 262*433d6423SLionel Sambuc d_urb->type = mx_urb->type; 263*433d6423SLionel Sambuc d_urb->direction = mx_urb->direction; 264*433d6423SLionel Sambuc d_urb->transfer_flags = mx_urb->transfer_flags; 265*433d6423SLionel Sambuc d_urb->size = mx_urb->size; 266*433d6423SLionel Sambuc d_urb->data = mx_urb->buffer; 267*433d6423SLionel Sambuc d_urb->interval = mx_urb->interval; 268*433d6423SLionel Sambuc d_urb->endpoint = mx_urb->endpoint; 269*433d6423SLionel Sambuc 270*433d6423SLionel Sambuc if (d_urb->type == USB_TRANSFER_CTL) { 271*433d6423SLionel Sambuc d_urb->setup_packet = mx_urb->setup_packet; 272*433d6423SLionel Sambuc } 273*433d6423SLionel Sambuc DEBUG_MSG("setup_package at %p", d_urb->setup_packet); 274*433d6423SLionel Sambuc 275*433d6423SLionel Sambuc if (d_urb->type == USB_TRANSFER_ISO) { 276*433d6423SLionel Sambuc d_urb->iso_desc = (struct ddekit_usb_iso_packet_desc *) 277*433d6423SLionel Sambuc mx_urb->buffer + mx_urb->iso_desc_offset; 278*433d6423SLionel Sambuc d_urb->number_of_packets = mx_urb->number_of_packets; 279*433d6423SLionel Sambuc } 280*433d6423SLionel Sambuc 281*433d6423SLionel Sambuc return d_urb; 282*433d6423SLionel Sambuc } 283*433d6423SLionel Sambuc 284*433d6423SLionel Sambuc /***************************************************************************** 285*433d6423SLionel Sambuc * submit_urb * 286*433d6423SLionel Sambuc ****************************************************************************/ 287*433d6423SLionel Sambuc static void submit_urb(message *msg) 288*433d6423SLionel Sambuc { 289*433d6423SLionel Sambuc /* 290*433d6423SLionel Sambuc * submit_urb 291*433d6423SLionel Sambuc * 292*433d6423SLionel Sambuc * Handles a submit_urb from a minix USB device driver. It copies the 293*433d6423SLionel Sambuc * usb_urb structure containing the buffers and generates and tries to 294*433d6423SLionel Sambuc * submit a ddekit_usb_urb. The reference to the ddekit_usb_urb is stored 295*433d6423SLionel Sambuc * in the driver structure in order to be able to cancle the URB on the 296*433d6423SLionel Sambuc * clients request. 297*433d6423SLionel Sambuc */ 298*433d6423SLionel Sambuc endpoint_t ep = msg->m_source; 299*433d6423SLionel Sambuc struct minix_usb_driver *drv; 300*433d6423SLionel Sambuc 301*433d6423SLionel Sambuc /* find driver */ 302*433d6423SLionel Sambuc if ( (drv = find_driver(ep)) == NULL) { 303*433d6423SLionel Sambuc DEBUG_MSG("Non-registered driver tries to send URB."); 304*433d6423SLionel Sambuc return; 305*433d6423SLionel Sambuc } else { 306*433d6423SLionel Sambuc 307*433d6423SLionel Sambuc int res; 308*433d6423SLionel Sambuc 309*433d6423SLionel Sambuc struct usb_urb *mx_urb = (struct usb_urb*) 310*433d6423SLionel Sambuc my_malloc(msg->USB_GRANT_SIZE+sizeof(void *)); 311*433d6423SLionel Sambuc 312*433d6423SLionel Sambuc if (mx_urb == NULL) { 313*433d6423SLionel Sambuc DEBUG_MSG("Can't allocat mem for mx_urb."); 314*433d6423SLionel Sambuc res = ENOMEM; 315*433d6423SLionel Sambuc goto out; 316*433d6423SLionel Sambuc } 317*433d6423SLionel Sambuc 318*433d6423SLionel Sambuc /* copy in URB */ 319*433d6423SLionel Sambuc res = sys_safecopyfrom(ep, msg->USB_GRANT_ID, 0, 320*433d6423SLionel Sambuc (vir_bytes) &mx_urb->dev_id, msg->USB_GRANT_SIZE); 321*433d6423SLionel Sambuc 322*433d6423SLionel Sambuc if (res != 0) { 323*433d6423SLionel Sambuc DEBUG_MSG("sys_safecopyfrom failed "); 324*433d6423SLionel Sambuc my_free(mx_urb); 325*433d6423SLionel Sambuc res = EINVAL; 326*433d6423SLionel Sambuc goto out; 327*433d6423SLionel Sambuc } 328*433d6423SLionel Sambuc 329*433d6423SLionel Sambuc DEBUG_MSG("URB type: %d", mx_urb->type); 330*433d6423SLionel Sambuc /* check if urb is valid */ 331*433d6423SLionel Sambuc if (mx_urb->dev_id >= MAX_DEVS && mx_urb->dev_id < 0) { 332*433d6423SLionel Sambuc DEBUG_MSG("Bogus device ID."); 333*433d6423SLionel Sambuc res = EINVAL; 334*433d6423SLionel Sambuc goto out; 335*433d6423SLionel Sambuc } 336*433d6423SLionel Sambuc 337*433d6423SLionel Sambuc /* create ddekit_usb_urb */ 338*433d6423SLionel Sambuc struct ddekit_usb_urb *d_urb = ddekit_usb_urb_from_mx_urb(mx_urb); 339*433d6423SLionel Sambuc d_urb->dev = _devices[drv->dev].dev; 340*433d6423SLionel Sambuc /* submit urb */ 341*433d6423SLionel Sambuc 342*433d6423SLionel Sambuc if (!d_urb) { 343*433d6423SLionel Sambuc res = ENOMEM; 344*433d6423SLionel Sambuc goto out; 345*433d6423SLionel Sambuc } 346*433d6423SLionel Sambuc 347*433d6423SLionel Sambuc struct my_context *ctx = (struct my_context *) 348*433d6423SLionel Sambuc my_malloc(sizeof(struct my_context)); 349*433d6423SLionel Sambuc 350*433d6423SLionel Sambuc if(!ctx) { 351*433d6423SLionel Sambuc res = ENOMEM; 352*433d6423SLionel Sambuc goto out; 353*433d6423SLionel Sambuc } 354*433d6423SLionel Sambuc 355*433d6423SLionel Sambuc ctx->drv = drv; 356*433d6423SLionel Sambuc ctx->urb_id = drv->urb_id++; 357*433d6423SLionel Sambuc mx_urb->urb_id = ctx->urb_id; 358*433d6423SLionel Sambuc ctx->mx_urb = mx_urb; 359*433d6423SLionel Sambuc ctx->d_urb = d_urb; 360*433d6423SLionel Sambuc ctx->gid = msg->USB_GRANT_ID; 361*433d6423SLionel Sambuc 362*433d6423SLionel Sambuc DEBUG_MSG("ctx: %p, urb_id: %d, d_urb: %p, mx_urb: %p, drv: %d, gid: %d ", 363*433d6423SLionel Sambuc ctx, ctx->urb_id, ctx->d_urb, ctx->mx_urb, ctx->drv, ctx->gid); 364*433d6423SLionel Sambuc 365*433d6423SLionel Sambuc d_urb->priv = ctx; 366*433d6423SLionel Sambuc 367*433d6423SLionel Sambuc res = add_to_pending_urbs(drv, d_urb); 368*433d6423SLionel Sambuc 369*433d6423SLionel Sambuc if (res == 0) { 370*433d6423SLionel Sambuc DEBUG_MSG("submitting urb..."); 371*433d6423SLionel Sambuc res = ddekit_usb_submit_urb(d_urb); 372*433d6423SLionel Sambuc if(res) { 373*433d6423SLionel Sambuc DEBUG_MSG("submitting urb failed (err: %d)", res); 374*433d6423SLionel Sambuc remove_from_pending_urbs(drv, d_urb); 375*433d6423SLionel Sambuc } 376*433d6423SLionel Sambuc } 377*433d6423SLionel Sambuc 378*433d6423SLionel Sambuc out: 379*433d6423SLionel Sambuc /* reply */ 380*433d6423SLionel Sambuc msg->m_type = USB_REPLY; 381*433d6423SLionel Sambuc msg->USB_URB_ID = mx_urb->urb_id; 382*433d6423SLionel Sambuc msg->USB_RESULT = res; 383*433d6423SLionel Sambuc 384*433d6423SLionel Sambuc if(res != 0) { 385*433d6423SLionel Sambuc 386*433d6423SLionel Sambuc if (mx_urb != NULL) { 387*433d6423SLionel Sambuc my_free(mx_urb); 388*433d6423SLionel Sambuc } 389*433d6423SLionel Sambuc if (ctx != NULL) { 390*433d6423SLionel Sambuc my_free(ctx); 391*433d6423SLionel Sambuc } 392*433d6423SLionel Sambuc 393*433d6423SLionel Sambuc if (d_urb != NULL) { 394*433d6423SLionel Sambuc my_free(d_urb); 395*433d6423SLionel Sambuc } 396*433d6423SLionel Sambuc 397*433d6423SLionel Sambuc } 398*433d6423SLionel Sambuc 399*433d6423SLionel Sambuc /* send reply */ 400*433d6423SLionel Sambuc ipc_send(ep, msg); 401*433d6423SLionel Sambuc } 402*433d6423SLionel Sambuc } 403*433d6423SLionel Sambuc 404*433d6423SLionel Sambuc 405*433d6423SLionel Sambuc /* 406*433d6423SLionel Sambuc * cancle_urb 407*433d6423SLionel Sambuc * 408*433d6423SLionel Sambuc * Cancels the submission of an URB identified by a URB_id 409*433d6423SLionel Sambuc */ 410*433d6423SLionel Sambuc /***************************************************************************** 411*433d6423SLionel Sambuc * cancle_urb * 412*433d6423SLionel Sambuc ****************************************************************************/ 413*433d6423SLionel Sambuc static void cancle_urb(message *msg) 414*433d6423SLionel Sambuc { 415*433d6423SLionel Sambuc endpoint_t ep = msg->m_source; 416*433d6423SLionel Sambuc 417*433d6423SLionel Sambuc struct minix_usb_driver *drv; 418*433d6423SLionel Sambuc 419*433d6423SLionel Sambuc msg->USB_RESULT = -1; 420*433d6423SLionel Sambuc msg->m_type = USB_REPLY; 421*433d6423SLionel Sambuc 422*433d6423SLionel Sambuc /* find driver */ 423*433d6423SLionel Sambuc if ( (drv = find_driver(ep)) == NULL) { 424*433d6423SLionel Sambuc DEBUG_MSG("Non-registered driver tries to cancel URB."); 425*433d6423SLionel Sambuc return; 426*433d6423SLionel Sambuc } else { 427*433d6423SLionel Sambuc struct ddekit_usb_urb *d_urb = NULL; 428*433d6423SLionel Sambuc 429*433d6423SLionel Sambuc d_urb = find_pending_urb(drv, msg->USB_URB_ID); 430*433d6423SLionel Sambuc 431*433d6423SLionel Sambuc if (d_urb != NULL) { 432*433d6423SLionel Sambuc ddekit_usb_cancle_urb(d_urb); 433*433d6423SLionel Sambuc msg->USB_RESULT = 0; 434*433d6423SLionel Sambuc } else { 435*433d6423SLionel Sambuc DEBUG_MSG("No URB to cancle"); 436*433d6423SLionel Sambuc msg->USB_RESULT = ENODEV; 437*433d6423SLionel Sambuc } 438*433d6423SLionel Sambuc } 439*433d6423SLionel Sambuc 440*433d6423SLionel Sambuc ipc_send(ep, msg); 441*433d6423SLionel Sambuc } 442*433d6423SLionel Sambuc 443*433d6423SLionel Sambuc 444*433d6423SLionel Sambuc /***************************************************************************** 445*433d6423SLionel Sambuc * completion_callback * 446*433d6423SLionel Sambuc ****************************************************************************/ 447*433d6423SLionel Sambuc static void completion_callback(void *priv) 448*433d6423SLionel Sambuc { 449*433d6423SLionel Sambuc /* 450*433d6423SLionel Sambuc * completion_callback 451*433d6423SLionel Sambuc * 452*433d6423SLionel Sambuc * This is called by the DDE side. Here the data is copied back to 453*433d6423SLionel Sambuc * the driver and a message is send to inform the driver about the 454*433d6423SLionel Sambuc * completion. 455*433d6423SLionel Sambuc */ 456*433d6423SLionel Sambuc message msg; 457*433d6423SLionel Sambuc int res; 458*433d6423SLionel Sambuc struct my_context *ctx = (struct my_context *)priv; 459*433d6423SLionel Sambuc struct usb_urb *mx_urb = ctx->mx_urb; 460*433d6423SLionel Sambuc struct ddekit_usb_urb *d_urb = ctx->d_urb; 461*433d6423SLionel Sambuc struct minix_usb_driver *drv = ctx->drv; 462*433d6423SLionel Sambuc 463*433d6423SLionel Sambuc DEBUG_MSG("ctx: %p, urb_id: %d, d_urb: %p, mx_urb: %p, drv: %d, gid: %d ", 464*433d6423SLionel Sambuc ctx, ctx->urb_id, ctx->d_urb, ctx->mx_urb, ctx->drv, ctx->gid); 465*433d6423SLionel Sambuc 466*433d6423SLionel Sambuc /* update data in minix URB */ 467*433d6423SLionel Sambuc mx_urb->status = d_urb->status; 468*433d6423SLionel Sambuc mx_urb->actual_length = d_urb->actual_length; 469*433d6423SLionel Sambuc mx_urb->error_count = d_urb->error_count; 470*433d6423SLionel Sambuc mx_urb->transfer_flags = d_urb->transfer_flags; 471*433d6423SLionel Sambuc 472*433d6423SLionel Sambuc remove_from_pending_urbs(drv, d_urb); 473*433d6423SLionel Sambuc 474*433d6423SLionel Sambuc /* copy out URB */ 475*433d6423SLionel Sambuc res = sys_safecopyto(drv->ep, ctx->gid, 0, 476*433d6423SLionel Sambuc (vir_bytes) ((char*)mx_urb) + sizeof(void*), 477*433d6423SLionel Sambuc mx_urb->urb_size - sizeof(void*)); 478*433d6423SLionel Sambuc 479*433d6423SLionel Sambuc if (res != 0) { 480*433d6423SLionel Sambuc DEBUG_MSG("Copy out failed: %d", res); 481*433d6423SLionel Sambuc DEBUG_MSG(" URB ID: %d, Grant-ID: %d, Grant-size: %d", ctx->urb_id, 482*433d6423SLionel Sambuc ctx->gid, mx_urb->urb_size); 483*433d6423SLionel Sambuc } 484*433d6423SLionel Sambuc 485*433d6423SLionel Sambuc /* send message to client */ 486*433d6423SLionel Sambuc msg.m_type = USB_COMPLETE_URB; 487*433d6423SLionel Sambuc msg.USB_URB_ID = ctx->urb_id; 488*433d6423SLionel Sambuc asynsend3(drv->ep, &msg, AMF_NOREPLY); 489*433d6423SLionel Sambuc 490*433d6423SLionel Sambuc /* free stuff */ 491*433d6423SLionel Sambuc my_free(ctx); 492*433d6423SLionel Sambuc my_free(mx_urb); 493*433d6423SLionel Sambuc my_free(d_urb); 494*433d6423SLionel Sambuc } 495*433d6423SLionel Sambuc 496*433d6423SLionel Sambuc 497*433d6423SLionel Sambuc /***************************************************************************** 498*433d6423SLionel Sambuc * prepare_devman_usbdev * 499*433d6423SLionel Sambuc ****************************************************************************/ 500*433d6423SLionel Sambuc static void prepare_devman_usbdev 501*433d6423SLionel Sambuc (struct ddekit_usb_dev * dev, int dev_id, unsigned int interfaces, 502*433d6423SLionel Sambuc struct devman_usb_dev *dudev) 503*433d6423SLionel Sambuc { 504*433d6423SLionel Sambuc int j; 505*433d6423SLionel Sambuc int intf_count; 506*433d6423SLionel Sambuc /* 507*433d6423SLionel Sambuc * currently this is only implemented by stub driver 508*433d6423SLionel Sambuc */ 509*433d6423SLionel Sambuc 510*433d6423SLionel Sambuc usb_device_descriptor_t *desc = _ddekit_usb_get_device_desc(dev); 511*433d6423SLionel Sambuc 512*433d6423SLionel Sambuc dudev->manufacturer = _ddekit_usb_get_manufacturer(dev); 513*433d6423SLionel Sambuc dudev->product = _ddekit_usb_get_product(dev); 514*433d6423SLionel Sambuc dudev->serial = _ddekit_usb_get_serial(dev); 515*433d6423SLionel Sambuc 516*433d6423SLionel Sambuc dudev->desc = desc; 517*433d6423SLionel Sambuc 518*433d6423SLionel Sambuc intf_count = 0; 519*433d6423SLionel Sambuc 520*433d6423SLionel Sambuc for (j=0; j < 32; j++) { 521*433d6423SLionel Sambuc if (interfaces & (1 << j)) { 522*433d6423SLionel Sambuc dudev->interfaces[intf_count++].desc = 523*433d6423SLionel Sambuc _ddekit_usb_get_interface_desc(dev, j); 524*433d6423SLionel Sambuc } 525*433d6423SLionel Sambuc } 526*433d6423SLionel Sambuc 527*433d6423SLionel Sambuc dudev->intf_count = intf_count; 528*433d6423SLionel Sambuc dudev->dev_id = dev_id; 529*433d6423SLionel Sambuc } 530*433d6423SLionel Sambuc 531*433d6423SLionel Sambuc /***************************************************************************** 532*433d6423SLionel Sambuc * device_connect_callback * 533*433d6423SLionel Sambuc ****************************************************************************/ 534*433d6423SLionel Sambuc static void 535*433d6423SLionel Sambuc device_connect_callback 536*433d6423SLionel Sambuc (struct ddekit_usb_dev * dev, unsigned int interfaces) { 537*433d6423SLionel Sambuc 538*433d6423SLionel Sambuc int i, res; 539*433d6423SLionel Sambuc 540*433d6423SLionel Sambuc /* add to device list */ 541*433d6423SLionel Sambuc for (i=0; i < MAX_DEVS; i++) { 542*433d6423SLionel Sambuc if (_devices[i].dev == NULL) 543*433d6423SLionel Sambuc break; 544*433d6423SLionel Sambuc } 545*433d6423SLionel Sambuc 546*433d6423SLionel Sambuc if (i >= MAX_DEVS) { 547*433d6423SLionel Sambuc DEBUG_MSG("Too much devices..."); 548*433d6423SLionel Sambuc } else { 549*433d6423SLionel Sambuc _devices[i].dev = dev; 550*433d6423SLionel Sambuc _devices[i].interfaces = (1 << interfaces); 551*433d6423SLionel Sambuc } 552*433d6423SLionel Sambuc 553*433d6423SLionel Sambuc struct devman_usb_dev *dudev; 554*433d6423SLionel Sambuc 555*433d6423SLionel Sambuc dudev = devman_usb_device_new(i); 556*433d6423SLionel Sambuc 557*433d6423SLionel Sambuc prepare_devman_usbdev(dev, i, interfaces, dudev); 558*433d6423SLionel Sambuc 559*433d6423SLionel Sambuc if (dudev == NULL) { 560*433d6423SLionel Sambuc /* TODO: ERROR */ 561*433d6423SLionel Sambuc printf("ERROR: !"); 562*433d6423SLionel Sambuc } 563*433d6423SLionel Sambuc 564*433d6423SLionel Sambuc ddekit_usb_dev_set_data(dev, dudev); 565*433d6423SLionel Sambuc 566*433d6423SLionel Sambuc res = devman_usb_device_add(dudev); 567*433d6423SLionel Sambuc 568*433d6423SLionel Sambuc if (res != 0) { 569*433d6423SLionel Sambuc /* TODO: Error*/ 570*433d6423SLionel Sambuc printf("ERROR!"); 571*433d6423SLionel Sambuc } 572*433d6423SLionel Sambuc } 573*433d6423SLionel Sambuc 574*433d6423SLionel Sambuc /***************************************************************************** 575*433d6423SLionel Sambuc * device_disconnect_callback * 576*433d6423SLionel Sambuc ****************************************************************************/ 577*433d6423SLionel Sambuc static void device_disconnect_callback(struct ddekit_usb_dev * dev) 578*433d6423SLionel Sambuc { 579*433d6423SLionel Sambuc int i; 580*433d6423SLionel Sambuc 581*433d6423SLionel Sambuc /* remove ACL entry */ 582*433d6423SLionel Sambuc for (i = 0; i< MAX_DRIVERS; i++) { 583*433d6423SLionel Sambuc if (gbl_drivers[i].dev != INVAL_DEV 584*433d6423SLionel Sambuc && _devices[gbl_drivers[i].dev].dev == dev) { 585*433d6423SLionel Sambuc struct minix_usb_driver *drv = &gbl_drivers[i]; 586*433d6423SLionel Sambuc drv->ep = 0; 587*433d6423SLionel Sambuc drv->status = DRIVER_UNUSED; 588*433d6423SLionel Sambuc drv->dev = INVAL_DEV; 589*433d6423SLionel Sambuc } 590*433d6423SLionel Sambuc } 591*433d6423SLionel Sambuc 592*433d6423SLionel Sambuc for (i=0; i < MAX_DEVS; i++) { 593*433d6423SLionel Sambuc if (_devices[i].dev == dev) { 594*433d6423SLionel Sambuc _devices[i].dev = NULL; 595*433d6423SLionel Sambuc _devices[i].interfaces = 0; 596*433d6423SLionel Sambuc } 597*433d6423SLionel Sambuc } 598*433d6423SLionel Sambuc 599*433d6423SLionel Sambuc 600*433d6423SLionel Sambuc /* get the devman device */ 601*433d6423SLionel Sambuc struct devman_usb_dev * dudev = NULL; 602*433d6423SLionel Sambuc 603*433d6423SLionel Sambuc dudev = ddekit_usb_dev_get_data(dev); 604*433d6423SLionel Sambuc 605*433d6423SLionel Sambuc if (dudev == NULL) { 606*433d6423SLionel Sambuc /* TODO: error */ 607*433d6423SLionel Sambuc } 608*433d6423SLionel Sambuc 609*433d6423SLionel Sambuc devman_usb_device_remove(dudev); 610*433d6423SLionel Sambuc 611*433d6423SLionel Sambuc /* free the devman dev */ 612*433d6423SLionel Sambuc devman_usb_device_delete(dudev); 613*433d6423SLionel Sambuc } 614*433d6423SLionel Sambuc 615*433d6423SLionel Sambuc 616*433d6423SLionel Sambuc /***************************************************************************** 617*433d6423SLionel Sambuc * add_acl * 618*433d6423SLionel Sambuc ****************************************************************************/ 619*433d6423SLionel Sambuc static int add_acl(int dev_id, unsigned interfaces, endpoint_t ep) 620*433d6423SLionel Sambuc { 621*433d6423SLionel Sambuc /* 622*433d6423SLionel Sambuc * This functions binds a specific USB interface to a client. 623*433d6423SLionel Sambuc */ 624*433d6423SLionel Sambuc int i; 625*433d6423SLionel Sambuc struct minix_usb_driver *drv; 626*433d6423SLionel Sambuc 627*433d6423SLionel Sambuc if (_devices[dev_id].dev == NULL) { 628*433d6423SLionel Sambuc /* if no device with that ID */ 629*433d6423SLionel Sambuc return ENODEV; 630*433d6423SLionel Sambuc } 631*433d6423SLionel Sambuc 632*433d6423SLionel Sambuc /* is the device allready given to a client*/ 633*433d6423SLionel Sambuc for (i = 0; i< MAX_DRIVERS; i++) { 634*433d6423SLionel Sambuc if (gbl_drivers[i].status != DRIVER_UNUSED && 635*433d6423SLionel Sambuc gbl_drivers[i].dev == dev_id) { 636*433d6423SLionel Sambuc printf("devid: %d\n", dev_id); 637*433d6423SLionel Sambuc return EBUSY; 638*433d6423SLionel Sambuc } 639*433d6423SLionel Sambuc } 640*433d6423SLionel Sambuc 641*433d6423SLionel Sambuc /* bind device to client */ 642*433d6423SLionel Sambuc drv = find_unused_driver(); 643*433d6423SLionel Sambuc 644*433d6423SLionel Sambuc if (drv == NULL) { 645*433d6423SLionel Sambuc return ENOMEM; 646*433d6423SLionel Sambuc } 647*433d6423SLionel Sambuc 648*433d6423SLionel Sambuc drv->status = DRIVER_BOUND; 649*433d6423SLionel Sambuc drv->dev = dev_id; 650*433d6423SLionel Sambuc drv->interfaces = 1 << interfaces; 651*433d6423SLionel Sambuc drv->ep = ep; 652*433d6423SLionel Sambuc drv->urb_id = 0; 653*433d6423SLionel Sambuc 654*433d6423SLionel Sambuc return OK; 655*433d6423SLionel Sambuc } 656*433d6423SLionel Sambuc 657*433d6423SLionel Sambuc /***************************************************************************** 658*433d6423SLionel Sambuc * del_acl * 659*433d6423SLionel Sambuc ****************************************************************************/ 660*433d6423SLionel Sambuc static int del_acl(int dev_id, unsigned interfaces, endpoint_t ep) 661*433d6423SLionel Sambuc { 662*433d6423SLionel Sambuc struct minix_usb_driver *drv; 663*433d6423SLionel Sambuc int dev, withdraw = 0; 664*433d6423SLionel Sambuc message msg; 665*433d6423SLionel Sambuc 666*433d6423SLionel Sambuc /* find driver */ 667*433d6423SLionel Sambuc drv = find_driver(ep); 668*433d6423SLionel Sambuc 669*433d6423SLionel Sambuc if (drv == NULL) { 670*433d6423SLionel Sambuc return ENOENT; 671*433d6423SLionel Sambuc } 672*433d6423SLionel Sambuc 673*433d6423SLionel Sambuc dev = drv->dev; 674*433d6423SLionel Sambuc 675*433d6423SLionel Sambuc if (drv->status == DRIVER_ACTIVE) { 676*433d6423SLionel Sambuc withdraw = 1; 677*433d6423SLionel Sambuc } 678*433d6423SLionel Sambuc 679*433d6423SLionel Sambuc drv->ep = 0; 680*433d6423SLionel Sambuc drv->status = DRIVER_UNUSED; 681*433d6423SLionel Sambuc drv->dev = INVAL_DEV; 682*433d6423SLionel Sambuc 683*433d6423SLionel Sambuc if (withdraw) { 684*433d6423SLionel Sambuc msg.m_type = USB_WITHDRAW_DEV; 685*433d6423SLionel Sambuc msg.USB_DEV_ID = dev; 686*433d6423SLionel Sambuc asynsend3(ep, &msg, AMF_NOREPLY); 687*433d6423SLionel Sambuc } 688*433d6423SLionel Sambuc 689*433d6423SLionel Sambuc return 0; 690*433d6423SLionel Sambuc } 691*433d6423SLionel Sambuc 692*433d6423SLionel Sambuc /***************************************************************************** 693*433d6423SLionel Sambuc * handle_msg * 694*433d6423SLionel Sambuc ****************************************************************************/ 695*433d6423SLionel Sambuc static int handle_msg(message *msg) 696*433d6423SLionel Sambuc { 697*433d6423SLionel Sambuc /* 698*433d6423SLionel Sambuc * handle_msg 699*433d6423SLionel Sambuc * 700*433d6423SLionel Sambuc * The dispatcher for USB related messages. 701*433d6423SLionel Sambuc */ 702*433d6423SLionel Sambuc 703*433d6423SLionel Sambuc switch(msg->m_type) { 704*433d6423SLionel Sambuc case USB_RQ_INIT: 705*433d6423SLionel Sambuc register_driver(msg); 706*433d6423SLionel Sambuc return 1; 707*433d6423SLionel Sambuc case USB_RQ_DEINIT: 708*433d6423SLionel Sambuc deregister_driver(msg); 709*433d6423SLionel Sambuc return 1; 710*433d6423SLionel Sambuc case USB_RQ_SEND_URB: 711*433d6423SLionel Sambuc submit_urb(msg); 712*433d6423SLionel Sambuc return 1; 713*433d6423SLionel Sambuc case USB_RQ_CANCEL_URB: 714*433d6423SLionel Sambuc cancle_urb(msg); 715*433d6423SLionel Sambuc return 1; 716*433d6423SLionel Sambuc default: 717*433d6423SLionel Sambuc return 0; 718*433d6423SLionel Sambuc } 719*433d6423SLionel Sambuc } 720*433d6423SLionel Sambuc 721*433d6423SLionel Sambuc /***************************************************************************** 722*433d6423SLionel Sambuc * devman_tread * 723*433d6423SLionel Sambuc ****************************************************************************/ 724*433d6423SLionel Sambuc static void devman_thread(void *unused) 725*433d6423SLionel Sambuc { 726*433d6423SLionel Sambuc struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(DEVMAN_BASE, 727*433d6423SLionel Sambuc DEVMAN_BASE + 0xff); 728*433d6423SLionel Sambuc int ipc_status; 729*433d6423SLionel Sambuc message m; 730*433d6423SLionel Sambuc while (1) { 731*433d6423SLionel Sambuc ddekit_minix_rcv(mq, &m, &ipc_status); 732*433d6423SLionel Sambuc devman_handle_msg(&m); 733*433d6423SLionel Sambuc } 734*433d6423SLionel Sambuc } 735*433d6423SLionel Sambuc 736*433d6423SLionel Sambuc /***************************************************************************** 737*433d6423SLionel Sambuc * _ddekit_usb_thread * 738*433d6423SLionel Sambuc ****************************************************************************/ 739*433d6423SLionel Sambuc static void _ddekit_usb_thread(void * unused) 740*433d6423SLionel Sambuc { 741*433d6423SLionel Sambuc struct ddekit_minix_msg_q *mq = ddekit_minix_create_msg_q(USB_BASE, 742*433d6423SLionel Sambuc USB_BASE + 0xff); 743*433d6423SLionel Sambuc 744*433d6423SLionel Sambuc message m; 745*433d6423SLionel Sambuc int ipc_status; 746*433d6423SLionel Sambuc 747*433d6423SLionel Sambuc /* create devman thread */ 748*433d6423SLionel Sambuc ddekit_thread_t * dmth; 749*433d6423SLionel Sambuc 750*433d6423SLionel Sambuc dmth = ddekit_thread_create(devman_thread, NULL, "devman_thread"); 751*433d6423SLionel Sambuc 752*433d6423SLionel Sambuc while (1) { 753*433d6423SLionel Sambuc ddekit_minix_rcv(mq, &m, &ipc_status); 754*433d6423SLionel Sambuc handle_msg(&m); 755*433d6423SLionel Sambuc } 756*433d6423SLionel Sambuc } 757*433d6423SLionel Sambuc 758*433d6423SLionel Sambuc 759*433d6423SLionel Sambuc /***************************************************************************** 760*433d6423SLionel Sambuc * bind_cb * 761*433d6423SLionel Sambuc ****************************************************************************/ 762*433d6423SLionel Sambuc static int bind_cb (struct devman_usb_bind_cb_data *data, endpoint_t ep) 763*433d6423SLionel Sambuc { 764*433d6423SLionel Sambuc if(data) { 765*433d6423SLionel Sambuc return add_acl(data->dev_id, data->interface, ep); 766*433d6423SLionel Sambuc } else { 767*433d6423SLionel Sambuc printf("warning: missing cb_data!\n"); 768*433d6423SLionel Sambuc return EINVAL; 769*433d6423SLionel Sambuc } 770*433d6423SLionel Sambuc } 771*433d6423SLionel Sambuc 772*433d6423SLionel Sambuc /***************************************************************************** 773*433d6423SLionel Sambuc * unbind_cb * 774*433d6423SLionel Sambuc ****************************************************************************/ 775*433d6423SLionel Sambuc static int unbind_cb (struct devman_usb_bind_cb_data *data, endpoint_t ep) 776*433d6423SLionel Sambuc { 777*433d6423SLionel Sambuc if(data) { 778*433d6423SLionel Sambuc return del_acl(data->dev_id, data->interface, ep); 779*433d6423SLionel Sambuc } else { 780*433d6423SLionel Sambuc printf("warning: missing cb_data!\n"); 781*433d6423SLionel Sambuc return EINVAL; 782*433d6423SLionel Sambuc } 783*433d6423SLionel Sambuc } 784*433d6423SLionel Sambuc 785*433d6423SLionel Sambuc /***************************************************************************** 786*433d6423SLionel Sambuc * ddekit_usb_server_init * 787*433d6423SLionel Sambuc ****************************************************************************/ 788*433d6423SLionel Sambuc void ddekit_usb_server_init() 789*433d6423SLionel Sambuc { 790*433d6423SLionel Sambuc int i; 791*433d6423SLionel Sambuc /* 792*433d6423SLionel Sambuc * this function has to be called inside the context of an dedicated 793*433d6423SLionel Sambuc * DDELinux thread 794*433d6423SLionel Sambuc */ 795*433d6423SLionel Sambuc devman_usb_init(bind_cb, unbind_cb); 796*433d6423SLionel Sambuc ddekit_usb_init(&my_driver, &my_malloc, &my_free); 797*433d6423SLionel Sambuc for (i = 0; i< MAX_DRIVERS; i++) { 798*433d6423SLionel Sambuc gbl_drivers[i].dev = DRIVER_UNUSED; 799*433d6423SLionel Sambuc gbl_drivers[i].dev = INVAL_DEV; 800*433d6423SLionel Sambuc } 801*433d6423SLionel Sambuc _ddekit_usb_thread(NULL); 802*433d6423SLionel Sambuc 803*433d6423SLionel Sambuc } 804