📄 garmin_gps.c
字号:
{ struct usb_serial *serial = port->serial; struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); struct urb *urb; unsigned char *buffer; int status; dbg("%s - port %d, state %d", __FUNCTION__, port->number, garmin_data_p->state); garmin_data_p->flags &= ~FLAGS_DROP_DATA; buffer = kmalloc (count, GFP_ATOMIC); if (!buffer) { dev_err(&port->dev, "out of memory\n"); return -ENOMEM; } urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { dev_err(&port->dev, "no more free urbs\n"); kfree (buffer); return -ENOMEM; } memcpy (buffer, buf, count); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer); usb_fill_bulk_urb (urb, serial->dev, usb_sndbulkpipe (serial->dev, port->bulk_out_endpointAddress), buffer, count, garmin_write_bulk_callback, port); urb->transfer_flags |= URB_ZERO_PACKET; if (GARMIN_LAYERID_APPL == getLayerId(buffer)) { garmin_data_p->flags |= FLAGS_APP_REQ_SEEN; if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { pkt_clear(garmin_data_p); garmin_data_p->state = STATE_GSP_WAIT_DATA; } } /* send it down the pipe */ status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { dev_err(&port->dev, "%s - usb_submit_urb(write bulk) " "failed with status = %d\n", __FUNCTION__, status); count = status; } else { if (GARMIN_LAYERID_APPL == getLayerId(buffer) && (garmin_data_p->mode == MODE_GARMIN_SERIAL)) { gsp_send_ack(garmin_data_p, buffer[4]); } } /* we are done with this urb, so let the host driver * really free it when it is finished with it */ usb_free_urb (urb); return count;}static int garmin_write (struct usb_serial_port *port, const unsigned char *buf, int count){ int pktid, pktsiz, len; struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); __le32 *privpkt = (__le32 *)garmin_data_p->privpkt; usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buf); /* check for our private packets */ if (count >= GARMIN_PKTHDR_LENGTH) { len = PRIVPKTSIZ; if (count < len) len = count; memcpy(garmin_data_p->privpkt, buf, len); pktsiz = getDataLength(garmin_data_p->privpkt); pktid = getPacketId(garmin_data_p->privpkt); if (count == (GARMIN_PKTHDR_LENGTH+pktsiz) && GARMIN_LAYERID_PRIVATE == getLayerId(garmin_data_p->privpkt)) { dbg("%s - processing private request %d", __FUNCTION__, pktid); // drop all unfinished transfers garmin_clear(garmin_data_p); switch(pktid) { case PRIV_PKTID_SET_DEBUG: if (pktsiz != 4) return -EINVPKT; debug = __le32_to_cpu(privpkt[3]); dbg("%s - debug level set to 0x%X", __FUNCTION__, debug); break; case PRIV_PKTID_SET_MODE: if (pktsiz != 4) return -EINVPKT; garmin_data_p->mode = __le32_to_cpu(privpkt[3]); dbg("%s - mode set to %d", __FUNCTION__, garmin_data_p->mode); break; case PRIV_PKTID_INFO_REQ: priv_status_resp(port); break; case PRIV_PKTID_RESET_REQ: garmin_data_p->flags |= FLAGS_APP_REQ_SEEN; break; case PRIV_PKTID_SET_DEF_MODE: if (pktsiz != 4) return -EINVPKT; initial_mode = __le32_to_cpu(privpkt[3]); dbg("%s - initial_mode set to %d", __FUNCTION__, garmin_data_p->mode); break; } return count; } } if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { return gsp_receive(garmin_data_p, buf, count); } else { /* MODE_NATIVE */ return nat_receive(garmin_data_p, buf, count); }}static int garmin_write_room (struct usb_serial_port *port){ /* * Report back the bytes currently available in the output buffer. */ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); return GPS_OUT_BUFSIZ-garmin_data_p->outsize;}static int garmin_chars_in_buffer (struct usb_serial_port *port){ /* * Report back the number of bytes currently in our input buffer. * Will this lock up the driver - the buffer contains an incomplete * package which will not be written to the device until it * has been completed ? */ //struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); //return garmin_data_p->insize; return 0;}static void garmin_read_process(struct garmin_data * garmin_data_p, unsigned char *data, unsigned data_length){ if (garmin_data_p->flags & FLAGS_DROP_DATA) { /* abort-transfer cmd is actice */ dbg("%s - pkt dropped", __FUNCTION__); } else if (garmin_data_p->state != STATE_DISCONNECTED && garmin_data_p->state != STATE_RESET ) { /* remember any appl.layer packets, so we know if a reset is required or not when closing the device */ if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY, sizeof(GARMIN_APP_LAYER_REPLY))) garmin_data_p->flags |= FLAGS_APP_RESP_SEEN; /* if throttling is active or postprecessing is required put the received data in th input queue, otherwise send it directly to the tty port */ if (garmin_data_p->flags & FLAGS_QUEUING) { pkt_add(garmin_data_p, data, data_length); } else if (garmin_data_p->mode == MODE_GARMIN_SERIAL) { if (getLayerId(data) == GARMIN_LAYERID_APPL) { pkt_add(garmin_data_p, data, data_length); } } else { send_to_tty(garmin_data_p->port, data, data_length); } }}static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs){ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial = port->serial; struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); unsigned char *data = urb->transfer_buffer; int status; dbg("%s - port %d", __FUNCTION__, port->number); if (!serial) { dbg("%s - bad serial pointer, exiting", __FUNCTION__); return; } if (urb->status) { dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); return; } usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); garmin_read_process(garmin_data_p, data, urb->actual_length); /* Continue trying to read until nothing more is received */ if (urb->actual_length > 0) { usb_fill_bulk_urb (port->read_urb, serial->dev, usb_rcvbulkpipe (serial->dev, port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, garmin_read_bulk_callback, port); status = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (status) dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, status); } return;}static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs){ int status; struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial = port->serial; struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); unsigned char *data = urb->transfer_buffer; switch (urb->status) { case 0: /* success */ break; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); return; default: dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); return; } usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, urb->transfer_buffer); if (urb->actual_length == sizeof(GARMIN_BULK_IN_AVAIL_REPLY) && 0 == memcmp(data, GARMIN_BULK_IN_AVAIL_REPLY, sizeof(GARMIN_BULK_IN_AVAIL_REPLY))) { dbg("%s - bulk data available.", __FUNCTION__); /* bulk data available */ usb_fill_bulk_urb (port->read_urb, serial->dev, usb_rcvbulkpipe (serial->dev, port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, garmin_read_bulk_callback, port); status = usb_submit_urb(port->read_urb, GFP_KERNEL); if (status) { dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, status); } } else if (urb->actual_length == (4+sizeof(GARMIN_START_SESSION_REPLY)) && 0 == memcmp(data, GARMIN_START_SESSION_REPLY, sizeof(GARMIN_START_SESSION_REPLY))) { garmin_data_p->flags |= FLAGS_SESSION_REPLY1_SEEN; /* save the serial number */ garmin_data_p->serial_num = __le32_to_cpup((__le32*)(data+GARMIN_PKTHDR_LENGTH)); dbg("%s - start-of-session reply seen - serial %u.", __FUNCTION__, garmin_data_p->serial_num); } if (garmin_data_p->ignorePkts) { /* this reply belongs to a request generated by the driver, ignore it. */ dbg("%s - pkt ignored (%d)", __FUNCTION__, garmin_data_p->ignorePkts); garmin_data_p->ignorePkts--; } else { garmin_read_process(garmin_data_p, data, urb->actual_length); } port->interrupt_in_urb->dev = port->serial->dev; status = usb_submit_urb (urb, GFP_ATOMIC); if (status) dev_err(&urb->dev->dev, "%s - Error %d submitting interrupt urb\n", __FUNCTION__, status);}/* * Sends the next queued packt to the tty port (garmin native mode only) * and then sets a timer to call itself again until all queued data * is sent. */static int garmin_flush_queue(struct garmin_data * garmin_data_p){ struct garmin_packet *pkt; if ((garmin_data_p->flags & FLAGS_THROTTLED) == 0) { pkt = pkt_pop(garmin_data_p); if (pkt != NULL) { send_to_tty(garmin_data_p->port, pkt->data, pkt->size); kfree(pkt); mod_timer(&garmin_data_p->timer, (1)+jiffies); } else { garmin_data_p->flags &= ~FLAGS_QUEUING; } } return 0;}static void garmin_throttle (struct usb_serial_port *port){ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); dbg("%s - port %d", __FUNCTION__, port->number); /* set flag, data received will be put into a queue for later processing */ garmin_data_p->flags |= FLAGS_QUEUING|FLAGS_THROTTLED;}static void garmin_unthrottle (struct usb_serial_port *port){ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); dbg("%s - port %d", __FUNCTION__, port->number); garmin_data_p->flags &= ~FLAGS_THROTTLED; /* in native mode send queued data to tty, in serial mode nothing needs to be done here */ if (garmin_data_p->mode == MODE_NATIVE) garmin_flush_queue(garmin_data_p);}/* * The timer is currently only used to send queued packets to * the tty in cases where the protocol provides no own handshaking * to initiate the transfer. */static void timeout_handler(unsigned long data){ struct garmin_data *garmin_data_p = (struct garmin_data *) data; /* send the next queued packet to the tty port */ if (garmin_data_p->mode == MODE_NATIVE) if (garmin_data_p->flags & FLAGS_QUEUING) garmin_flush_queue(garmin_data_p);}static int garmin_attach (struct usb_serial *serial){ int status = 0; struct usb_serial_port *port = serial->port[0]; struct garmin_data * garmin_data_p = NULL; dbg("%s", __FUNCTION__); garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL); if (garmin_data_p == NULL) { dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__); return -ENOMEM; } init_timer(&garmin_data_p->timer); spin_lock_init(&garmin_data_p->lock); INIT_LIST_HEAD(&garmin_data_p->pktlist); //garmin_data_p->timer.expires = jiffies + session_timeout; garmin_data_p->timer.data = (unsigned long)garmin_data_p; garmin_data_p->timer.function = timeout_handler; garmin_data_p->port = port; garmin_data_p->state = 0; garmin_data_p->count = 0; usb_set_serial_port_data(port, garmin_data_p); status = garmin_init_session(port); return status;}static void garmin_shutdown (struct usb_serial *serial){ struct usb_serial_port *port = serial->port[0]; struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); dbg("%s", __FUNCTION__); usb_kill_urb (port->interrupt_in_urb); del_timer_sync(&garmin_data_p->timer); kfree (garmin_data_p); usb_set_serial_port_data(port, NULL);}/* All of the device info needed */static struct usb_serial_driver garmin_device = { .driver = { .owner = THIS_MODULE, .name = "garmin_gps", }, .description = "Garmin GPS usb/tty", .id_table = id_table, .num_interrupt_in = 1, .num_bulk_in = 1, .num_bulk_out = 1, .num_ports = 1, .open = garmin_open, .close = garmin_close, .throttle = garmin_throttle, .unthrottle = garmin_unthrottle, .attach = garmin_attach, .shutdown = garmin_shutdown, .write = garmin_write, .write_room = garmin_write_room, .chars_in_buffer = garmin_chars_in_buffer, .write_bulk_callback = garmin_write_bulk_callback, .read_bulk_callback = garmin_read_bulk_callback, .read_int_callback = garmin_read_int_callback,};static int __init garmin_init (void){ int retval; retval = usb_serial_register(&garmin_device); if (retval) goto failed_garmin_register; retval = usb_register(&garmin_driver); if (retval) goto failed_usb_register; info(DRIVER_DESC " " DRIVER_VERSION); return 0;failed_usb_register: usb_serial_deregister(&garmin_device);failed_garmin_register: return retval;}static void __exit garmin_exit (void){ usb_deregister (&garmin_driver); usb_serial_deregister (&garmin_device);}module_init(garmin_init);module_exit(garmin_exit);MODULE_AUTHOR( DRIVER_AUTHOR );MODULE_DESCRIPTION( DRIVER_DESC );MODULE_LICENSE("GPL");module_param(debug, bool, S_IWUSR | S_IRUGO);MODULE_PARM_DESC(debug, "Debug enabled or not");module_param(initial_mode, int, S_IRUGO);MODULE_PARM_DESC(initial_mode, "Initial mode");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -