?? serial.c
字號:
/* Configuration description(s) */struct __devinitdata usb_configuration_description serial_description[] = {#ifdef CONFIG_USBD_SERIAL_CDC {iConfiguration:"CDC 1.1 ACM Configuration", bmAttributes:BMATTRIBUTE, bMaxPower:BMAXPOWER, interfaces:sizeof (cdc_interfaces) / sizeof (struct usb_interface_description), interface_list:cdc_interfaces,},#endif {iConfiguration:"USB Simple Serial Configuration", bmAttributes:BMATTRIBUTE, bMaxPower:BMAXPOWER, interfaces:sizeof (serial_interfaces) / sizeof (struct usb_interface_description), interface_list:serial_interfaces,},};/* Device Description */struct __devinitdata usb_device_description serial_device_description = { bDeviceClass:COMMUNICATIONS_DEVICE_CLASS, bDeviceSubClass:0, // XXX bDeviceProtocol:0, // XXX idVendor:CONFIG_USBD_VENDORID, idProduct:CONFIG_USBD_PRODUCTID, iManufacturer:CONFIG_USBD_MANUFACTURER, iProduct:CONFIG_USBD_PRODUCT_NAME, iSerialNumber:CONFIG_USBD_SERIAL_NUMBER_STR,};/* Transmit Function - called by serproto ****************************************************** */static int serial_xmit_data (int interface, unsigned char *data, int data_length){ int port = 0; // XXX compound device struct usb_serial_private *serial_private; struct usb_device_instance *device; struct urb *urb; int packet_length = data_length; dbg_tx (2, "data: %p data_length: %d", data, data_length); if ((serial_private = get_serial_private (interface)) == NULL) { dbg_tx (0, "cannot recover serial private"); return -EINVAL; } if ((device = serial_private->device) == NULL) { dbg_tx (0, "cannot recover serial private device"); return -EINVAL; } // XXX Check if we are busy if ((urb = usbd_alloc_urb (serial_private->device, (serial_private->device->function_instance_array + port), CONFIG_USBD_SERIAL_IN_ENDPOINT | IN, 0)) == NULL) { dbg_tx (0, "failed to alloc urb"); return -EINVAL; }#ifdef CONFIG_USBD_SERIAL_SAFE if (safe) { __u16 fcs; dbg_tx (1, "safe mode: padded: %d data_length: %d packet_length: %d", padded, data_length, packet_length); // extend length to pad if required if (padded) { //packet_length = MAX(packet_length, CONFIG_USBD_SERIAL_IN_PKTSIZE - 2); //packet_length = MIN(MAX(packet_length, packet_length), CONFIG_USBD_SERIAL_IN_PKTSIZE - 2); packet_length = CONFIG_USBD_SERIAL_IN_PKTSIZE - 2; //packet_length = 2; //packet_length++; } // set length and a null byte data[packet_length] = data_length << 2; data[packet_length + 1] = 0; // compute CRC across data, padding, data_length and null byte fcs = fcs_compute10 (data, packet_length + 2, CRC10_INITFCS); // OR CRC into last two bytes data[packet_length] |= fcs >> 8; data[packet_length + 1] = fcs & 0xff; packet_length += 2; dbg_tx (1, "safe mode: data_length: %d packet_length: %d", data_length, packet_length); }#endif urb->buffer = data; urb->actual_length = packet_length; //dbgPRINTmem(dbgflg_usbdfd_tx,3,urb->buffer,urb->actual_length); dbgPRINTmem (dbgflg_usbdfd_tx, 3, urb->buffer, CONFIG_USBD_SERIAL_IN_PKTSIZE + 4); // push it down into the usb-device layer return usbd_send_urb (urb);}/* serial_urb_sent - called to indicate URB transmit finished * @urb: pointer to struct urb * @rc: result */int serial_urb_sent (struct urb *urb){ int port = 0; // XXX compound device struct usb_device_instance *device = urb->device; struct usb_serial_private *serial_private = (device->function_instance_array + port)->privdata; dbg_tx (2, "%s safe: %d length: %d", urb->device->name, safe, urb->actual_length); serproto_done (serial_private->interface, urb->buffer, safe ? (urb->buffer[urb->actual_length - 2] >> 2) : urb->actual_length, 0); usbd_dealloc_urb (urb); return 0;}/* USB Device Functions ************************************************************************ *//* serial_event - process a device event * */void serial_event (struct usb_device_instance *device, usb_device_event_t event, int data){ int port = 0; // XXX compound device struct usb_function_instance *function; unsigned int flags; if ((function = device->function_instance_array + port) == NULL) { dbg_usbe (1, "no function"); return; } dbg_usbe (3, ""); switch (event) { case DEVICE_UNKNOWN: case DEVICE_INIT: case DEVICE_CREATE: case DEVICE_HUB_CONFIGURED: case DEVICE_RESET: case DEVICE_ADDRESS_ASSIGNED: case DEVICE_CONFIGURED: case DEVICE_DE_CONFIGURED: case DEVICE_SET_INTERFACE: case DEVICE_SET_FEATURE: case DEVICE_CLEAR_FEATURE: case DEVICE_BUS_INACTIVE: case DEVICE_BUS_ACTIVITY: case DEVICE_POWER_INTERRUPTION: case DEVICE_HUB_RESET: case DEVICE_DESTROY: case DEVICE_FUNCTION_PRIVATE: dbg_usbe (1,"%s data: %d", usbd_device_events[event], data); break; default: dbg_usbe (1,"%s", usbd_device_events[DEVICE_UNKNOWN]); break; } switch (event) { case DEVICE_UNKNOWN: case DEVICE_INIT: break; case DEVICE_CREATE: { int i; int interface; struct usb_serial_private *serial_private; // There is no way to indicate error, so make this unconditional // and undo it in the DESTROY event unconditionally as well. // It the responsibility of the USBD core and the bus interface // to see that there is a matching DESTROY for every CREATE. // XXX XXX MOD_INC_USE_COUNT; // Before any sleepable fns such as kmalloc // XXX XXX dbg_init(0,"CREATE sc=%d uc=%d",serial_created,GET_USE_COUNT(THIS_MODULE)); // sanity checks if (serial_created >= MAX_INTERFACES) { dbg_usbe (1, "---> CREATE %s serial_created >= MAX_INTERFACES %d %d", device->name, serial_created, MAX_INTERFACES); dbg_init (0, "CREATE Z1 sc=%d uc=%d", serial_created, GET_USE_COUNT (THIS_MODULE)); return; } write_lock_irqsave (&serial_rwlock, flags); for (i = 0; i < MAX_INTERFACES; i++) { if (serial_private_array[i] == NULL) { break; } } if (i >= MAX_INTERFACES) { write_unlock_irqrestore (&serial_rwlock, flags); dbg_usbe (1, "---> CREATE %s no free interfaces %d %d", device->name, i, MAX_INTERFACES); dbg_init (0, "CREATE Z2 sc=%d uc=%d", serial_created, GET_USE_COUNT (THIS_MODULE)); return; } serial_created++; // allocate private data if ((serial_private = kmalloc (sizeof (struct usb_serial_private), GFP_ATOMIC)) == NULL) { serial_created--; //MOD_DEC_USE_COUNT; //dbg_init(0,"CREATE X1 sc=%d uc=%d",serial_created,GET_USE_COUNT(THIS_MODULE)); write_unlock_irqrestore (&serial_rwlock, flags); dbg_usbe (1, "---> CREATE malloc failed %s", device->name); return; } serial_private->rwlock = RW_LOCK_UNLOCKED; serial_private_array[i] = serial_private; write_unlock_irqrestore (&serial_rwlock, flags); dbg_usbe (1, "---> calling serproto_create(%s,-,%u,%u,%u,%u,%u)", "ttyUSBx", CONFIG_USBD_SERIAL_IN_PKTSIZE, txqueue_urbs, txqueue_bytes, safe, safe ? 2 : 0); if ((interface = serproto_create ("ttyUSBx", serial_xmit_data, (safe ? (CONFIG_USBD_SERIAL_IN_PKTSIZE - 2) : CONFIG_USBD_SERIAL_IN_PKTSIZE), txqueue_urbs, txqueue_bytes, safe, safe ? 2 : 0)) < 0) { // lock and modify device array write_lock_irqsave (&serial_rwlock, flags); kfree (serial_private); serial_created--; //MOD_DEC_USE_COUNT; //dbg_init(0,"CREATE X2 sc=%d uc=%d",serial_created,GET_USE_COUNT(THIS_MODULE)); write_unlock_irqrestore (&serial_rwlock, flags); dbg_usbe (1, "---> serproto_create FAILED"); return; } // lock and modify device array write_lock_irqsave (&serial_rwlock, flags); serial_private->interface = interface; serial_private->device = device; write_unlock_irqrestore (&serial_rwlock, flags); function->privdata = serial_private; dbg_usbe (1, "---> START %s privdata assigned: %p interface: %d", device->name, serial_private, interface); return; } break; case DEVICE_HUB_CONFIGURED: break; case DEVICE_RESET: break; case DEVICE_ADDRESS_ASSIGNED: break; case DEVICE_CONFIGURED: { struct usb_serial_private *serial_private; int interface; if ((serial_private = (device->function_instance_array + port)->privdata) == NULL) { return; } interface = serial_private->interface; if (interface < 0 || interface >= MAX_INTERFACES) { return; } serproto_control (interface, SERPROTO_CONNECT); } break; case DEVICE_SET_INTERFACE:#ifdef CONFIG_USBD_SERIAL_CDC#endif break; case DEVICE_SET_FEATURE: break; case DEVICE_CLEAR_FEATURE: break; case DEVICE_DE_CONFIGURED: { struct usb_serial_private *serial_private; int interface; if ((serial_private = (device->function_instance_array + port)->privdata) == NULL) { return; } interface = serial_private->interface; if (interface < 0 || interface >= MAX_INTERFACES) { return; } serproto_control (interface, SERPROTO_DISCONNECT); } break; case DEVICE_BUS_INACTIVE: break; case DEVICE_BUS_ACTIVITY: break; case DEVICE_POWER_INTERRUPTION: break; case DEVICE_HUB_RESET: break; case DEVICE_DESTROY: { struct usb_serial_private *serial_private; int interface; if ((serial_private = (device->function_instance_array + port)->privdata) == NULL) { dbg_usbe (1, "---> DESTROY %s serial_private null", device->name); // XXX XXX MOD_DEC_USE_COUNT; // XXX XXX dbg_init(0,"DESTROY Z1 sc=%d uc=%d",serial_created,GET_USE_COUNT(THIS_MODULE)); return; } dbg_usbe (1, "---> DESTROY %s serial_private %p", device->name, serial_private); interface = serial_private->interface; if (interface < 0 || interface >= MAX_INTERFACES) { // XXX XXX MOD_DEC_USE_COUNT; // XXX XXX dbg_init(0,"DESTROY Z2 sc=%d uc=%d",serial_created,GET_USE_COUNT(THIS_MODULE)); return; } if (serial_private_array[interface] != serial_private) { // XXX XXX MOD_DEC_USE_COUNT; // XXX XXX dbg_init(0,"DESTROY Z3 sc=%d uc=%d",serial_created,GET_USE_COUNT(THIS_MODULE)); return; } write_lock_irqsave (&serial_rwlock, flags); serial_private_array[interface] = NULL; kfree (serial_private); serial_created--; write_unlock_irqrestore (&serial_rwlock, flags); serproto_destroy (interface); // XXX XXX MOD_DEC_USE_COUNT; // XXX XXX dbg_init(0,"DESTROY sc=%d uc=%d",serial_created,GET_USE_COUNT(THIS_MODULE)); dbg_usbe (1, "---> STOP %s", device->name); return; } break; case DEVICE_FUNCTION_PRIVATE: break; }}/* serial_recv_urb - called to indicate URB has been received * @urb - pointer to struct urb * * Return non-zero if we failed and urb is still valid (not disposed) */int serial_recv_urb (struct urb *urb){ int port = 0; // XXX compound device struct usb_device_instance *device = urb->device; struct usb_serial_private *serial_private = (device->function_instance_array + port)->privdata; int interface = serial_private->interface; dbg_rx (2, "length=%d", urb->actual_length); dbgPRINTmem (dbgflg_usbdfd_rx, 3, urb->buffer, urb->actual_length);#ifdef CONFIG_USBD_SERIAL_SAFE if (safe) { __u16 fcs; if ((fcs = fcs_compute10 (urb->buffer, urb->actual_length, CRC10_INITFCS))) { dbg_rx (0, "CRC check failed"); //return -EINVAL; } else { // recover the length from the trailer urb->actual_length = (urb->buffer[urb->actual_length - 2] >> 2); } } dbg_rx (2, "revised length=%d", urb->actual_length);#endif#if 0 if (0 != dbgflg_usbdfd_loopback) { if (usbd_send_urb (urb)) { //XXX verify not freed in usbd_send_urb() //urb->buffer = NULL; //urb->actual_length = 0; //usbd_dealloc_urb(urb); } return 0; }#endif // push the data up if (serproto_recv (interface, urb->buffer, urb->actual_length)) { return (1); } // free urb usbd_recycle_urb (urb); return (0);}struct usb_function_operations function_ops = { event:serial_event, recv_urb:serial_recv_urb, urb_sent:serial_urb_sent};struct usb_function_driver function_driver = { name:"function prototype", ops:&function_ops, device_description:&serial_device_description, configurations:sizeof (serial_description) / sizeof (struct usb_configuration_description), configuration_description:serial_description, this_module:THIS_MODULE,};/* * serial_modinit - module init * */static int __init serial_modinit (void){ debug_option *op = find_debug_option (dbg_table, "ser"); printk (KERN_INFO "%s (%s)\n", __usbd_module_info, dbg);#ifdef CONFIG_USBD_SERIAL_SAFE printk (KERN_INFO "vendor_id: %04x product_id: %04x safe: %d padded: %d\n", vendor_id, product_id, safe, padded);#else printk (KERN_INFO "vendor_id: %04x product_id: %04x\n", vendor_id, product_id); if (safe || padded) { printk (KERN_ERR "serial_fd: not compiled for safe mode\n"); return -EINVAL; }#endif printk (KERN_INFO "dbg: %s\n", dbg); if (NULL != op) { op->sub_table = serproto_get_dbg_table (); } if (0 != scan_debug_options ("serial_fd", dbg_table, dbg)) { return (-EINVAL); } if (vendor_id) { serial_device_description.idVendor = vendor_id; } if (product_id) { serial_device_description.idProduct = product_id; } // Initialize the function registration code. // //if (usbd_strings_init()) { // return -EINVAL; //} // initialize the serproto library // if (serproto_modinit ("ttyUSBn", MAX_INTERFACES)) { return -EINVAL; } // register us with the usb device support layer // if (usbd_register_function (&function_driver)) { serproto_modexit (); return -EINVAL; } dbg_loop (1, "LOOPBACK mode"); // return return 0;}/* serial_modexit - module cleanup */static void __exit serial_modexit (void){ // de-register us with the usb device support layer // usbd_deregister_function (&function_driver); // tell the serproto library to exit // serproto_modexit ();}module_init (serial_modinit);module_exit (serial_modexit);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -