static int dtf_setup(void) { struct dtf_dev *dev; int ret; _dbgmsg( "IN\n" ); dev = kzalloc( sizeof( *dev ), GFP_KERNEL ); if( !dev ) { printk( KERN_ERR "dtf gadget driver failed to initialize nomem\n" ); return -ENOMEM; } spin_lock_init(&dev->lock); _dtf_dev = dev; ret = dtf_if_init(); if (ret) goto err; _dbgmsg( "OUT\n" ); return 0; err: kfree(dev); printk(KERN_ERR "dtf gadget driver failed to initialize\n"); return ret; }
static void dtf_function_suspend(struct usb_function *f) { _dbgmsg( "IN\n" ); /* MSEMSEMSE */ dtf_if_out_suspend(); _dbgmsg( "OUT\n" ); /* MSEMSEMSE */ }
static int dtf_bind_config(struct usb_configuration *c) { struct dtf_dev *dev = _dtf_dev; int ret; _dbgmsg( "IN\n" ); dev->cdev = c->cdev; dev->function.name = "dtf"; dev->function.descriptors = vFs_dtf_descs; dev->function.hs_descriptors = vHs_dtf_descs; dev->function.bind = dtf_function_bind; dev->function.unbind = dtf_function_unbind; dev->function.setup = dtf_function_setup; dev->function.set_alt = dtf_function_set_alt; dev->function.disable = dtf_function_disable; dev->function.suspend = dtf_function_suspend; dev->function.resume = dtf_function_resume; dev->mCtrl_ep_enbl = 0; dev->mData_ep_enbl = 0; _dbgmsg_gadget( "usb_add_function\n" ); ret = usb_add_function(c, &dev->function); _dbgmsg( "OUT(%d)\n", ret ); return ret; }
static int dtf_function_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct dtf_dev *dev = func_to_dtf(f); int ret; _dbgmsg( "IN\n" ); dev->cdev = cdev; /* allocate Interface IDs */ ret = dtf_allocate_interface_ids( c, f ); if( ret < 0 ) { printk( KERN_ERR "allocate interface IDs error\n" ); return ret; } /* allocate endpoints */ ret = dtf_allocate_endpoints( c, f ); if( ret < 0 ) { printk( KERN_ERR "allocate endpoints error\n" ); return ret; } _dbgmsg( "OUT\n" ); return 0; }
static void dtf_function_disable(struct usb_function *f) { struct dtf_dev *dev = func_to_dtf(f); int speed_check; _dbgmsg( "IN\n" ); if( dev->mCtrl_ep_enbl == 1 ) { dev->mCtrl_ep_enbl = 0; _dbgmsg_gadget( "usb_ep_disable(%s)\n", dev->pg.ep_intr->name ); usb_ep_disable( dev->pg.ep_intr ); } if( dev->mData_ep_enbl == 1 ) { dev->mData_ep_enbl = 0; _dbgmsg_gadget( "usb_ep_dequeue\n" ); usb_ep_dequeue( dev->pg.ep_out, dev->pg.mReq_out ); _dbgmsg_gadget( "usb_ep_disable(%s)\n", dev->pg.ep_intr->name ); usb_ep_disable( dev->pg.ep_in ); _dbgmsg_gadget( "usb_ep_disable(%s)\n", dev->pg.ep_out->name ); usb_ep_disable( dev->pg.ep_out ); } speed_check = (_dtf_dev->cdev->gadget->speed == USB_SPEED_HIGH)?(1):(0); dtf_if_out_disable(speed_check); _dbgmsg( "OUT\n" ); }
static void dtf_cleanup(void) { _dbgmsg( "IN\n" ); kfree(_dtf_dev); _dtf_dev = NULL; _dbgmsg( "OUT\n" ); }
static void dtf_request_free(struct usb_request *req, struct usb_ep *ep) { _dbgmsg( "IN\n" ); if(req) { kfree( req->buf ); _dbgmsg_gadget( "usb_ep_free_request\n" ); usb_ep_free_request( ep, req ); } _dbgmsg( "OUT\n" ); }
static int dtf_function_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct dtf_dev *dev = func_to_dtf(f); struct usb_composite_dev *cdev = f->config->cdev; int ret; int set_alt_end = 0; int speed_check = 0; _dbgmsg("dtf_function_set_alt(intf=%d,alt=%d)\n", intf, alt); /* MSEMSEMSE */ if( dev->pg.mCtrl_id == intf ) { _dbgmsg_gadget( "usb_ep_enable(%s)\n", dev->pg.ep_intr->name ); /* MSEMSEMSE */ ret = usb_ep_enable( dev->pg.ep_intr, ep_choose( cdev->gadget, &vPg1_epintr_desc_hs, &vPg1_epintr_desc ) ); if( ret ) { _dbgmsg( "usb_ep_enable error pg1 ep_intr ret = %d\n", ret );/* MSEMSEMSE */ return ret; } dev->mCtrl_ep_enbl = 1; } else if( dev->pg.mData_id == intf ) { _dbgmsg_gadget( "usb_ep_enable(%s)\n", dev->pg.ep_in->name ); /* MSEMSEMSE */ ret = usb_ep_enable( dev->pg.ep_in, ep_choose( cdev->gadget, &vPg1_epin_desc_hs, &vPg1_epin_desc ) ); if( ret ) { _dbgmsg( "usb_ep_enable error pg1 ep_in ret = %d\n", ret ); /* MSEMSEMSE */ return ret; } _dbgmsg_gadget( "usb_ep_enable(%s)\n", dev->pg.ep_out->name ); /* MSEMSEMSE */ ret = usb_ep_enable( dev->pg.ep_out, ep_choose( cdev->gadget, &vPg1_epout_desc_hs, &vPg1_epout_desc ) ); if( ret ) { _dbgmsg( "usb_ep_enable error pg1 ep_out ret = %d\n", ret );/* MSEMSEMSE */ usb_ep_disable(dev->pg.ep_in); return ret; } dev->pg.mReq_out->length = 512; usb_ep_queue( dev->pg.ep_out, dev->pg.mReq_out, GFP_ATOMIC ); dev->mData_ep_enbl = 1; } else { _dbgmsg( "unknown interface number\n" ); /* MSEMSEMSE */ } set_alt_end = ( (dev->mCtrl_ep_enbl) & (dev->mData_ep_enbl) ); speed_check = (dev->cdev->gadget->speed == USB_SPEED_HIGH)?(1):(0); if (set_alt_end == 1) { dtf_if_out_set_alt( speed_check ); } return 0; }
static void dtf_function_unbind(struct usb_configuration *c, struct usb_function *f) { struct dtf_dev *dev = func_to_dtf(f); _dbgmsg( "IN\n" ); spin_lock_irq(&dev->lock); dtf_request_free( dev->pg.mReq_intr, dev->pg.ep_intr ); dtf_request_free( dev->pg.mReq_in, dev->pg.ep_in ); dtf_request_free( dev->pg.mReq_out, dev->pg.ep_out ); spin_unlock_irq(&dev->lock); _dbgmsg( "OUT\n" ); }
static int get_digits(int a) { int nod; nod = (int)((log10(abs(a))) + 1); _dbgmsg("calculated %i digits for %i", nod, a); return nod; }
static int add_entry(address_t *data) { entry_ptr_t ent; ent = malloc(sizeof(entry_t)); if (ent == NULL) { _dbgerr(MEMORY_ALLOCATION_FAIL); return -1; } else { _dbgmsg("allocated memory for a new entry"); ent->data = data; ent->next = head; head = ent; _dbgmsg("new head at %i", head); } return 0; }
static int dtf_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) { struct dtf_if_ctrlrequest ctrlrequest; _dbgmsg( "IN\n" ); ctrlrequest.bRequestType = ctrl->bRequestType; ctrlrequest.bRequest = ctrl->bRequest; ctrlrequest.wValue = ctrl->wValue; ctrlrequest.wIndex = ctrl->wIndex; ctrlrequest.wLength = ctrl->wLength; dtf_if_out_setup( &ctrlrequest ); _dbgmsg( "OUT\n" ); return 0; }
static void dtf_complete_out(struct usb_ep *ep, struct usb_request *req) { struct dtf_dev *dev = _dtf_dev; _dbgmsg( "IN\n" ); dtf_if_out_complete_out(req->status, (int)req->actual, (char *)req->buf); if ( dev->mData_ep_enbl == 1 ) { dev->pg.mReq_out->length = 512; _dbgmsg_gadget( "usb_ep_queue\n" ); usb_ep_queue( dev->pg.ep_out, dev->pg.mReq_out, GFP_ATOMIC ); } _dbgmsg( "OUT\n" ); }
static unsigned int dtf_if_poll( struct file *pfile, poll_table *pwait ) { unsigned int mask = 0; _dbgmsg_if( "IN\n" ); poll_wait( pfile, &poll_wait_read, pwait ); if (dtf_if_get_read_data_num() > 0) { _dbgmsg( "(POLLIN | POLLRDNORM)\n" ); mask |= (POLLIN | POLLRDNORM); } _dbgmsg_if( "OUT(%d)\n", mask ); return mask; }
static int address_to_data(entry_ptr_t ent) { int length; int offset; int son = get_digits(*(ent->data->number))+1; int soz = get_digits(*(ent->data->zipcode))+1; char nr[son]; char zip[soz]; offset = 5*(strlen(DATA_SEPARATOR)) + strlen(DATA_END); length = get_entry_length(ent) + offset; char line[length]; _dbgmsg("reserved %i characters for the line", length); strcpy(line, ent->data->firstname); strcat(line, DATA_SEPARATOR); strcat(line, ent->data->lastname); strcat(line, DATA_SEPARATOR); strcat(line, ent->data->street); strcat(line, DATA_SEPARATOR); sprintf(nr, "%i", *(ent->data->number)); strcat(line, nr); strcat(line, DATA_SEPARATOR); sprintf(zip, "%i", *(ent->data->zipcode)); strcat(line, zip); strcat(line, DATA_SEPARATOR); strcat(line, ent->data->city); strcat(line, DATA_END); _dbgmsg("created line \"%s\"", line); write_address(line); return 0; }
static int dtf_allocate_interface_ids( struct usb_configuration *c, struct usb_function *f ) { int id; struct dtf_dev *dev = func_to_dtf(f); _dbgmsg( "IN\n" ); /* Allocate Interface ID: PipeGroup1 communication interface */ _dbgmsg_gadget( "usb_interface_id\n" ); id = usb_interface_id(c, f); _dbgmsg( "usb_interface_id() = %d\n", id ); if( id < 0 ) return id; dev->pg.mCtrl_id = id; id = 0; /* fixed interface number */ vPg1_intf_comm_desc.bInterfaceNumber = id; vPg1_union_desc.bMasterInterface0 = id; /* Allocate Interface ID: PipeGroup1 bulk interface */ _dbgmsg_gadget( "usb_interface_id\n" ); id = usb_interface_id(c, f); _dbgmsg( "usb_interface_id() = %d(%d)\n", id, vPg1_intf_comm_desc.bInterfaceNumber ); if( id < 0 ) return id; dev->pg.mData_id = id; id = 1; /* fixed interface number */ vPg1_intf_bulk_desc.bInterfaceNumber = id; vPg1_union_desc.bSlaveInterface0 = id; vPg1_call_mng.bDataInterface = id; _dbgmsg( "usb_interface_id() = %d(%d)\n", id, vPg1_intf_bulk_desc.bInterfaceNumber ); _dbgmsg( "OUT\n" ); return 0; }
void read_all(void) { char *line; int ctr; ctr = 1; while ((line = read_address(ctr)) != NULL) { strtok(line, "\n"); _dbgmsg("Entry %2i: %s\n", ctr, line); data_to_address(ctr); ctr++; } free(line); }
static int get_entry_length(entry_ptr_t ent) { int length; length = 0; length += strlen(ent->data->firstname); length += strlen(ent->data->lastname); length += strlen(ent->data->street); length += get_digits(*(ent->data->number)); length += get_digits(*(ent->data->zipcode)); length += strlen(ent->data->city); _dbgmsg("calculated %i characters for the entry", length); return length; }
static int data_to_address(int n) { _dbgmsg("parsing data from file for entry %i", n); char *line; char c; int i; /* data segment */ int pos; /* position in data segment */ int ctr; /* position in inputline */ int ret; char *firstname; char *lastname; char *street; char *nr; int *number; char *zp; int *zipcode; char *city; i = 0; ctr = 0; pos = 0; line = read_address(n); if (line == NULL) { return -1; } _dbgmsg("read data entry as \"%s\"", line); /* prepare the memory for the data */ firstname = malloc(strlen(line)); lastname = malloc(strlen(line)); street = malloc(strlen(line)); number = malloc(sizeof(int)); nr = malloc(strlen(line)); zipcode = malloc(sizeof(int)); zp = malloc(strlen(line)); city = malloc(strlen(line)); /* initialize the data */ firstname[0] = '\0'; lastname[0] = '\0'; street[0] = '\0'; nr[0] = '\0'; zp[0] = '\0'; city[0] = '\0'; while (((c = line[ctr]) != ';') && (i <= 5)) { if (c == '#') { _dbgwarn("found comment -> skipping rest of line"); return 0; } else if (c == '\n') { _dbgwarn("found newline -> skipping rest of line"); return 0; } else if (c == ',') { i++; ctr++; pos = 0; } else { if (c == ' ') { ctr++; } else { switch (i) { case 0: firstname[pos] = c; firstname[pos+1] = '\0'; break; case 1: lastname[pos] = c; lastname[pos+1] = '\0'; break; case 2: street[pos] = c; street[pos+1] = '\0'; break; case 3: nr[pos] = c; nr[pos+1] = '\0'; break; case 4: zp[pos] = c; zp[pos+1] = '\0'; break; case 5: city[pos] = c; city[pos+1] = '\0'; break; default: _dbgerr("something went wrong at parsing " "\"%c\"", c); break; } pos++; ctr++; } } } /* fitting memory and data */ firstname = realloc(firstname, strlen(firstname)); lastname = realloc(lastname, strlen(lastname)); street = realloc(street, strlen(street)); *number = atoi(nr); free(nr); *zipcode = atoi(zp); free(zp); city = realloc(city, strlen(city)); _dbgmsg("finished parsing -> adding new address entry"); ret = add_address(firstname, lastname, street, number, zipcode, city); free(firstname); free(lastname); free(street); free(number); free(zipcode); free(city); _dbgnice("freed all address data for entry %i", n); return ret; }
static address_t *create_address(char *firstname, char *lastname, char *street, int *number, int *zipcode, char *city) { address_t *n_address; n_address = malloc(sizeof(address_t)); /* preparing address */ if (n_address == NULL) { _dbgerr(MEMORY_ALLOCATION_FAIL); return NULL; } else { _dbgmsg("allocated memory for a new address"); } /* preparing firstname to address */ n_address->firstname = malloc(strlen(firstname)); if (n_address->firstname == NULL) { _dbgerr(MEMORY_ALLOCATION_FAIL); free(n_address); n_address = NULL; return NULL; } else { _dbgmsg("allocated memory for a firstname \"%s\"", firstname); strcpy(n_address->firstname, firstname); } /* THE PROGRAM CRASHES HERE AFTER "delete" AND THEN "add" */ /* preparing lastname to address */ n_address->lastname = malloc(strlen(lastname)); if (n_address->lastname == NULL) { _dbgerr(MEMORY_ALLOCATION_FAIL); free(n_address->firstname); free(n_address); return NULL; } else { _dbgmsg("allocated memory for a lastname \"%s\"", lastname); strcpy(n_address->lastname, lastname); } /* preparing street to address */ n_address->street = malloc(strlen(street)); if (n_address->street == NULL) { _dbgerr(MEMORY_ALLOCATION_FAIL); free(n_address->lastname); free(n_address->firstname); free(n_address); return NULL; } else { _dbgmsg("allocated memory for a street \"%s\"", street); strcpy(n_address->street, street); } /* preparing number to address */ n_address->number = malloc(sizeof(int)); if (n_address->number == NULL) { _dbgerr(MEMORY_ALLOCATION_FAIL); free(n_address->street); free(n_address->lastname); free(n_address->firstname); free(n_address); return NULL; } else { _dbgmsg("allocated memory for a number \"%i\"", *number); *(n_address->number) = *number; } /* preparing zipcode to address */ n_address->zipcode = malloc(sizeof(int)); if (n_address->zipcode == NULL) { _dbgerr(MEMORY_ALLOCATION_FAIL); free(n_address->number); free(n_address->street); free(n_address->lastname); free(n_address->firstname); free(n_address); return NULL; } else { _dbgmsg("allocated memory for a zipcode \"%i\"", *zipcode); *(n_address->zipcode) = *zipcode; } /* preparing city to address */ n_address->city = malloc(strlen(city)); if (n_address->city == NULL) { _dbgerr(MEMORY_ALLOCATION_FAIL); free(n_address->zipcode); free(n_address->number); free(n_address->street); free(n_address->lastname); free(n_address->firstname); free(n_address); return NULL; } else { _dbgmsg("allocated memory for a city \"%s\"", city); strcpy(n_address->city, city); return n_address; } }
static void dtf_ctrl_complete(struct usb_ep *ep, struct usb_request *req) { _dbgmsg( "IN\n" ); dtf_if_out_ctrl_complete(req->length, req->actual, (char *)req->buf); _dbgmsg( "OUT\n" ); }
static int dtf_allocate_endpoints(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct dtf_dev *dev = func_to_dtf(f); struct usb_request *req; struct usb_ep *ep; _dbgmsg( "IN\n" ); /* allocate endpoints: PipeGroup1 intrrupt */ _dbgmsg_gadget( "usb_ep_autoconfig\n" ); ep = usb_ep_autoconfig(cdev->gadget, &vPg1_epintr_desc); if( !ep ) { _dbgmsg( "usb_ep_autoconfig for PG1 ep_intr failed\n" ); return -ENODEV; } _dbgmsg("usb_ep_autoconfig for PG1 ep_intr got %s\n", ep->name); ep->driver_data = dev; dev->pg.ep_intr = ep; /* allocate endpoints: PipeGroup1 bulk(in) */ _dbgmsg_gadget( "usb_ep_autoconfig\n" ); ep = usb_ep_autoconfig(cdev->gadget, &vPg1_epin_desc); if( !ep ) { _dbgmsg( "usb_ep_autoconfig for PG1 ep_in failed\n" ); return -ENODEV; } _dbgmsg("usb_ep_autoconfig for PG1 ep_in got %s\n", ep->name); ep->driver_data = dev; dev->pg.ep_in = ep; /* allocate endpoints: PipeGroup1 bulk(out) */ _dbgmsg_gadget( "usb_ep_autoconfig\n" ); ep = usb_ep_autoconfig(cdev->gadget, &vPg1_epout_desc); if( !ep ) { _dbgmsg( "usb_ep_autoconfig for PG1 ep_out failed\n" ); return -ENODEV; } _dbgmsg("usb_ep_autoconfig for PG1 ep_out got %s\n", ep->name); ep->driver_data = dev; dev->pg.ep_out = ep; /* support high speed hardware */ if (gadget_is_dualspeed(cdev->gadget)) { vPg1_epintr_desc_hs.bEndpointAddress = vPg1_epintr_desc.bEndpointAddress; vPg1_epin_desc_hs.bEndpointAddress = vPg1_epin_desc.bEndpointAddress; vPg1_epout_desc_hs.bEndpointAddress = vPg1_epout_desc.bEndpointAddress; } _dbgmsg("%s speed %s: PG1[INTR/%s, IN/%s, OUT/%s]\n", gadget_is_dualspeed(cdev->gadget) ? "dual" : "full", f->name, dev->pg.ep_intr->name, dev->pg.ep_in->name, dev->pg.ep_out->name); /* allocate request for endpoints */ req = dtf_request_new( dev->pg.ep_intr, 16 ); if(!req) { _dbgmsg( "create request error\n" ); return -ENODEV; } req->complete = dtf_complete_intr; dev->pg.mReq_intr = req; req = dtf_request_new( dev->pg.ep_in, 512 ); if(!req) { _dbgmsg( "create request error\n" ); return -ENODEV; } req->complete = dtf_complete_in; dev->pg.mReq_in = req; req = dtf_request_new( dev->pg.ep_out, 512 ); if(!req) { _dbgmsg( "create request error\n" ); return -ENODEV; } req->complete = dtf_complete_out; dev->pg.mReq_out = req; _dbgmsg( "OUT\n" ); return 0; }
static void dtf_complete_intr(struct usb_ep *ep, struct usb_request *req) { _dbgmsg( "IN\n" ); dtf_if_out_complete_intr(req->status); _dbgmsg( "OUT\n" ); }
static void dtf_function_resume(struct usb_function *f) { _dbgmsg( "IN\n" ); dtf_if_out_resume(); _dbgmsg( "OUT\n" ); }
static void dtf_complete_in(struct usb_ep *ep, struct usb_request *req) { _dbgmsg( "IN\n" ); /* MSEMSEMSE */ dtf_if_out_complete_in(req->status); _dbgmsg( "OUT\n" ); /* MSEMSEMSE */ }