📄 flexcop-usb.c
字号:
int l; deb_ts("tmp_buffer_length=%d, buffer_length=%d\n", fc_usb->tmp_buffer_length, buffer_length); if (fc_usb->tmp_buffer_length > 0) { memcpy(fc_usb->tmp_buffer+fc_usb->tmp_buffer_length, buffer, buffer_length); fc_usb->tmp_buffer_length += buffer_length; b = fc_usb->tmp_buffer; l = fc_usb->tmp_buffer_length; } else { b=buffer; l=buffer_length; } while (l >= 190) { if (*b == 0xff) switch (*(b+1) & 0x03) { case 0x01: /* media packet */ if ( *(b+2) == 0x47 ) flexcop_pass_dmx_packets(fc_usb->fc_dev, b+2, 1); else deb_ts("not ts packet %02x %02x %02x %02x \n", *(b+2), *(b+3), *(b+4), *(b+5) ); b += 190; l -= 190; break; default: deb_ts("wrong packet type\n"); l = 0; break; } else { deb_ts("wrong header\n"); l = 0; } } if (l>0) memcpy(fc_usb->tmp_buffer, b, l); fc_usb->tmp_buffer_length = l;}static void flexcop_usb_urb_complete(struct urb *urb){ struct flexcop_usb *fc_usb = urb->context; int i; if (urb->actual_length > 0) deb_ts("urb completed, bufsize: %d actlen; %d\n",urb->transfer_buffer_length, urb->actual_length); for (i = 0; i < urb->number_of_packets; i++) { if (urb->iso_frame_desc[i].status < 0) { err("iso frame descriptor %d has an error: %d\n",i,urb->iso_frame_desc[i].status); } else if (urb->iso_frame_desc[i].actual_length > 0) { deb_ts("passed %d bytes to the demux\n",urb->iso_frame_desc[i].actual_length); flexcop_usb_process_frame(fc_usb, urb->transfer_buffer + urb->iso_frame_desc[i].offset, urb->iso_frame_desc[i].actual_length); } urb->iso_frame_desc[i].status = 0; urb->iso_frame_desc[i].actual_length = 0; } usb_submit_urb(urb,GFP_ATOMIC);}static int flexcop_usb_stream_control(struct flexcop_device *fc, int onoff){ /* submit/kill iso packets */ return 0;}static void flexcop_usb_transfer_exit(struct flexcop_usb *fc_usb){ int i; for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) if (fc_usb->iso_urb[i] != NULL) { deb_ts("unlinking/killing urb no. %d\n",i); usb_kill_urb(fc_usb->iso_urb[i]); usb_free_urb(fc_usb->iso_urb[i]); } if (fc_usb->iso_buffer != NULL) pci_free_consistent(NULL,fc_usb->buffer_size, fc_usb->iso_buffer, fc_usb->dma_addr);}static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb){ u16 frame_size = fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize; int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * frame_size,i,j,ret; int buffer_offset = 0; deb_ts("creating %d iso-urbs with %d frames each of %d bytes size = %d.\n", B2C2_USB_NUM_ISO_URB, B2C2_USB_FRAMES_PER_ISO, frame_size,bufsize); fc_usb->iso_buffer = pci_alloc_consistent(NULL,bufsize,&fc_usb->dma_addr); if (fc_usb->iso_buffer == NULL) return -ENOMEM; memset(fc_usb->iso_buffer, 0, bufsize); fc_usb->buffer_size = bufsize; /* creating iso urbs */ for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) if (!(fc_usb->iso_urb[i] = usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO,GFP_ATOMIC))) { ret = -ENOMEM; goto urb_error; } /* initialising and submitting iso urbs */ for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) { int frame_offset = 0; struct urb *urb = fc_usb->iso_urb[i]; deb_ts("initializing and submitting urb no. %d (buf_offset: %d).\n",i,buffer_offset); urb->dev = fc_usb->udev; urb->context = fc_usb; urb->complete = flexcop_usb_urb_complete; urb->pipe = B2C2_USB_DATA_PIPE; urb->transfer_flags = URB_ISO_ASAP; urb->interval = 1; urb->number_of_packets = B2C2_USB_FRAMES_PER_ISO; urb->transfer_buffer_length = frame_size * B2C2_USB_FRAMES_PER_ISO; urb->transfer_buffer = fc_usb->iso_buffer + buffer_offset; buffer_offset += frame_size * B2C2_USB_FRAMES_PER_ISO; for (j = 0; j < B2C2_USB_FRAMES_PER_ISO; j++) { deb_ts("urb no: %d, frame: %d, frame_offset: %d\n",i,j,frame_offset); urb->iso_frame_desc[j].offset = frame_offset; urb->iso_frame_desc[j].length = frame_size; frame_offset += frame_size; } if ((ret = usb_submit_urb(fc_usb->iso_urb[i],GFP_ATOMIC))) { err("submitting urb %d failed with %d.",i,ret); goto urb_error; } deb_ts("submitted urb no. %d.\n",i); }/* SRAM */ flexcop_sram_set_dest(fc_usb->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET | FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_WAN_USB); flexcop_wan_set_speed(fc_usb->fc_dev,FC_WAN_SPEED_8MBITS); flexcop_sram_ctrl(fc_usb->fc_dev,1,1,1); return 0;urb_error: flexcop_usb_transfer_exit(fc_usb); return ret;}static int flexcop_usb_init(struct flexcop_usb *fc_usb){ /* use the alternate setting with the larges buffer */ usb_set_interface(fc_usb->udev,0,1); switch (fc_usb->udev->speed) { case USB_SPEED_LOW: err("cannot handle USB speed because it is to sLOW."); return -ENODEV; break; case USB_SPEED_FULL: info("running at FULL speed."); break; case USB_SPEED_HIGH: info("running at HIGH speed."); break; case USB_SPEED_UNKNOWN: /* fall through */ default: err("cannot handle USB speed because it is unkown."); return -ENODEV; } usb_set_intfdata(fc_usb->uintf, fc_usb); return 0;}static void flexcop_usb_exit(struct flexcop_usb *fc_usb){ usb_set_intfdata(fc_usb->uintf, NULL);}static int flexcop_usb_probe(struct usb_interface *intf, const struct usb_device_id *id){ struct usb_device *udev = interface_to_usbdev(intf); struct flexcop_usb *fc_usb = NULL; struct flexcop_device *fc = NULL; int ret; if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_usb))) == NULL) { err("out of memory\n"); return -ENOMEM; }/* general flexcop init */ fc_usb = fc->bus_specific; fc_usb->fc_dev = fc; fc->read_ibi_reg = flexcop_usb_read_ibi_reg; fc->write_ibi_reg = flexcop_usb_write_ibi_reg; fc->i2c_request = flexcop_usb_i2c_request; fc->get_mac_addr = flexcop_usb_get_mac_addr; fc->stream_control = flexcop_usb_stream_control; fc->pid_filtering = 1; fc->bus_type = FC_USB; fc->dev = &udev->dev; fc->owner = THIS_MODULE;/* bus specific part */ fc_usb->udev = udev; fc_usb->uintf = intf; if ((ret = flexcop_usb_init(fc_usb)) != 0) goto err_kfree;/* init flexcop */ if ((ret = flexcop_device_initialize(fc)) != 0) goto err_usb_exit;/* xfer init */ if ((ret = flexcop_usb_transfer_init(fc_usb)) != 0) goto err_fc_exit; info("%s successfully initialized and connected.",DRIVER_NAME); return 0;err_fc_exit: flexcop_device_exit(fc);err_usb_exit: flexcop_usb_exit(fc_usb);err_kfree: flexcop_device_kfree(fc); return ret;}static void flexcop_usb_disconnect(struct usb_interface *intf){ struct flexcop_usb *fc_usb = usb_get_intfdata(intf); flexcop_usb_transfer_exit(fc_usb); flexcop_device_exit(fc_usb->fc_dev); flexcop_usb_exit(fc_usb); flexcop_device_kfree(fc_usb->fc_dev); info("%s successfully deinitialized and disconnected.",DRIVER_NAME);}static struct usb_device_id flexcop_usb_table [] = { { USB_DEVICE(0x0af7, 0x0101) }, { }};MODULE_DEVICE_TABLE (usb, flexcop_usb_table);/* usb specific object needed to register this driver with the usb subsystem */static struct usb_driver flexcop_usb_driver = { .name = "b2c2_flexcop_usb", .probe = flexcop_usb_probe, .disconnect = flexcop_usb_disconnect, .id_table = flexcop_usb_table,};/* module stuff */static int __init flexcop_usb_module_init(void){ int result; if ((result = usb_register(&flexcop_usb_driver))) { err("usb_register failed. (%d)",result); return result; } return 0;}static void __exit flexcop_usb_module_exit(void){ /* deregister this driver from the USB subsystem */ usb_deregister(&flexcop_usb_driver);}module_init(flexcop_usb_module_init);module_exit(flexcop_usb_module_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_NAME);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -